Add support for Python 3.12 (#1873)

* Add support for Python 3.12

* chore: Update Python version to 3.11 and DuckDB dependency to 0.10.2

* chore: fix mistral components lint

* Update SQLAgent and SQLExecutor imports to use langchain_community utilities

* Update langchain import to langchain_community

* Update langchain import to langchain_community

* 📝 (langflow/__main__.py): Import warnings module to suppress warnings during app execution
📝 (langflow/api/v1/schemas.py): Update timestamp field default value to use datetime.now with timezone.utc
📝 (auth/utils.py): Ignore warnings related to datetime.utcnow when decoding JWT tokens and creating refresh tokens
📝 (models/flow/model.py): Update updated_at field default value to use lambda function with timezone.utc
📝 (models/user/model.py): Update create_at and updated_at field default values to use lambda function with timezone.utc
This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-05-10 12:25:34 -03:00 • committed by GitHub
commit 5ca1c22893
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 470 additions and 876 deletions

View file

@ -22,8 +22,9 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.12"
- "3.11"
- "3.10"
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}

View file

@ -23,8 +23,9 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.12"
- "3.11"
- "3.10"
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
steps:

View file

@ -8,7 +8,7 @@ on:
env:
POETRY_VERSION: "1.8.2"
NODE_VERSION: "21"
PYTHON_VERSION: "3.10"
PYTHON_VERSION: "3.12"
# Define the directory where Playwright browsers will be installed.
# Adjust if your project uses a different path.
PLAYWRIGHT_BROWSERS_PATH: "ms-playwright"

869
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ langflow = "langflow.__main__:main"
[tool.poetry.dependencies]
python = ">=3.10,<3.12"
python = ">=3.10,<3.13"
langflow-base = { path = "./src/backend/base", develop = true }
beautifulsoup4 = "^4.12.2"
google-search-results = "^2.4.1"
@ -72,7 +72,7 @@ langchain-cohere = "^0.1.0rc1"
elasticsearch = "^8.12.0"
pytube = "^15.0.0"
llama-index = "^0.10.13"
unstructured = { extras = ["md"], version = "^0.12.4" }
# unstructured = { extras = ["md"], version = "^0.12.4" }
dspy-ai = "^2.4.0"
html2text = "^2024.2.26"
assemblyai = "^0.23.1"
@ -85,7 +85,7 @@ zep-python = { version = "^2.0.0rc5", allow-prereleases = true }
langchain-google-vertexai = "^1.0.3"
langchain-groq = "^0.1.3"
langchain-pinecone = "^0.1.0"
langchain-mistralai ="^0.1.6"
langchain-mistralai = "^0.1.6"
[tool.poetry.group.dev.dependencies]

View file

@ -4,6 +4,7 @@ import sys
import time
from pathlib import Path
from typing import Optional
import warnings
import click
import httpx
@ -468,7 +469,9 @@ def migration(
def main():
app()
with warnings.catch_warnings():
warnings.simplefilter("ignore")
app()
if __name__ == "__main__":

View file

@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timezone
from typing import List
from uuid import UUID
@ -33,7 +33,7 @@ def create_flow(
flow.user_id = current_user.id
db_flow = Flow.model_validate(flow, from_attributes=True)
db_flow.updated_at = datetime.utcnow()
db_flow.updated_at = datetime.now(timezone.utc)
session.add(db_flow)
session.commit()
@ -128,7 +128,7 @@ def update_flow(
for key, value in flow_data.items():
if value is not None:
setattr(db_flow, key, value)
db_flow.updated_at = datetime.utcnow()
db_flow.updated_at = datetime.now(timezone.utc)
session.add(db_flow)
session.commit()
session.refresh(db_flow)

View file

@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timezone
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List, Optional, Union
@ -250,7 +250,7 @@ class VertexBuildResponse(BaseModel):
"""JSON string of the params."""
data: ResultDataResponse
"""Mapping of vertex ids to result dict containing the param name and result value."""
timestamp: Optional[datetime] = Field(default_factory=datetime.utcnow)
timestamp: Optional[datetime] = Field(default_factory=lambda: datetime.now(timezone.utc))
"""Timestamp of the build."""

View file

@ -67,23 +67,25 @@ def retrieve_file_paths(
return file_paths
def partition_file_to_record(file_path: str, silent_errors: bool) -> Optional[Record]:
# Use the partition function to load the file
from unstructured.partition.auto import partition # type: ignore
# ! Removing unstructured dependency until
# ! 3.12 is supported
# def partition_file_to_record(file_path: str, silent_errors: bool) -> Optional[Record]:
# # Use the partition function to load the file
# from unstructured.partition.auto import partition # type: ignore
try:
elements = partition(file_path)
except Exception as e:
if not silent_errors:
raise ValueError(f"Error loading file {file_path}: {e}") from e
return None
# try:
# elements = partition(file_path)
# except Exception as e:
# if not silent_errors:
# raise ValueError(f"Error loading file {file_path}: {e}") from e
# return None
# Create a Record
text = "\n\n".join([Text(el) for el in elements])
metadata = elements.metadata if hasattr(elements, "metadata") else {}
metadata["file_path"] = file_path
record = Record(text=text, data=metadata)
return record
# # Create a Record
# text = "\n\n".join([Text(el) for el in elements])
# metadata = elements.metadata if hasattr(elements, "metadata") else {}
# metadata["file_path"] = file_path
# record = Record(text=text, data=metadata)
# return record
def read_text_file(file_path: str) -> str:
@ -131,18 +133,20 @@ def parse_text_file_to_record(file_path: str, silent_errors: bool) -> Optional[R
return record
def get_elements(
file_paths: List[str],
silent_errors: bool,
max_concurrency: int,
use_multithreading: bool,
) -> List[Optional[Record]]:
if use_multithreading:
records = parallel_load_records(file_paths, silent_errors, max_concurrency)
else:
records = [partition_file_to_record(file_path, silent_errors) for file_path in file_paths]
records = list(filter(None, records))
return records
# ! Removing unstructured dependency until
# ! 3.12 is supported
# def get_elements(
# file_paths: List[str],
# silent_errors: bool,
# max_concurrency: int,
# use_multithreading: bool,
# ) -> List[Optional[Record]]:
# if use_multithreading:
# records = parallel_load_records(file_paths, silent_errors, max_concurrency)
# else:
# records = [partition_file_to_record(file_path, silent_errors) for file_path in file_paths]
# records = list(filter(None, records))
# return records
def parallel_load_records(

View file

@ -1,7 +1,7 @@
from typing import Callable, Union
from langchain.agents import AgentExecutor
from langchain.sql_database import SQLDatabase
from langchain_community.utilities import SQLDatabase
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_community.agent_toolkits.sql.base import create_sql_agent

View file

@ -1,5 +1,5 @@
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
from langchain_experimental.sql.base import SQLDatabase
from langchain_community.utilities import SQLDatabase
from langflow.field_typing import Text
from langflow.interface.custom.custom_component import CustomComponent

View file

@ -1,6 +1,6 @@
from typing import Optional
from langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint
from langchain_community.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint
from langflow.interface.custom.custom_component import CustomComponent
from langflow.field_typing import BaseLanguageModel

View file

@ -30,7 +30,7 @@ class MistralAIModelComponent(CustomComponent):
"open-mixtral-8x22b",
"mistral-small-latest",
"mistral-medium-latest",
"mistral-large-latest"
"mistral-large-latest",
],
"info": "Name of the model to use.",
"required": True,
@ -64,9 +64,9 @@ class MistralAIModelComponent(CustomComponent):
def build(
self,
model: str,
temperature: float = 0.1,
mistral_api_key: Optional[str] = None,
max_tokens: Optional[int] = None,
temperature: Optional[float] = None,
mistral_api_base: Optional[str] = None,
) -> BaseLanguageModel:
# Set default API endpoint if not provided
@ -75,11 +75,11 @@ class MistralAIModelComponent(CustomComponent):
try:
output = ChatMistralAI(
model=model,
model_name=model,
api_key=(SecretStr(mistral_api_key) if mistral_api_key else None),
max_tokens=max_tokens,
temperature=temperature,
base_url=mistral_api_base,
endpoint=mistral_api_base,
)
except Exception as e:
raise ValueError("Could not connect to Mistral API.") from e

View file

@ -1,7 +1,7 @@
from typing import Optional
from langflow.field_typing import BaseLanguageModel
from langchain.llms.huggingface_endpoint import HuggingFaceEndpoint
from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint
from langflow.interface.custom.custom_component import CustomComponent

View file

@ -5,7 +5,7 @@ from pydantic.v1 import SecretStr
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import NestedDict, Text
from langflow.field_typing import Text
class MistralAIModelComponent(LCModelComponent):
@ -32,10 +32,6 @@ class MistralAIModelComponent(LCModelComponent):
"display_name": "Max Tokens",
"advanced": True,
},
"model_kwargs": {
"display_name": "Model Kwargs",
"advanced": True,
},
"model_name": {
"display_name": "Model Name",
"advanced": False,
@ -45,7 +41,7 @@ class MistralAIModelComponent(LCModelComponent):
"open-mixtral-8x22b",
"mistral-small-latest",
"mistral-medium-latest",
"mistral-large-latest"
"mistral-large-latest",
],
"value": "open-mistral-7b",
},
@ -78,19 +74,48 @@ class MistralAIModelComponent(LCModelComponent):
"info": "System message to pass to the model.",
"advanced": True,
},
"max_retries": {
"display_name": "Max Retries",
"advanced": True,
},
"timeout": {
"display_name": "Timeout",
"advanced": True,
},
"max_concurrent_requests": {
"display_name": "Max Concurrent Requests",
"advanced": True,
},
"top_p": {
"display_name": "Top P",
"advanced": True,
},
"random_seed": {
"display_name": "Random Seed",
"advanced": True,
},
"safe_mode": {
"display_name": "Safe Mode",
"advanced": True,
},
}
def build(
self,
input_value: Text,
mistral_api_key: str,
temperature: float,
model_name: str,
temperature: float = 0.1,
max_tokens: Optional[int] = 256,
model_kwargs: NestedDict = {},
mistral_api_base: Optional[str] = None,
stream: bool = False,
system_message: Optional[str] = None,
max_retries: int = 5,
timeout: int = 120,
max_concurrent_requests: int = 64,
top_p: float = 1,
random_seed: Optional[int] = None,
safe_mode: bool = False,
) -> Text:
if not mistral_api_base:
mistral_api_base = "https://api.mistral.ai"
@ -101,11 +126,16 @@ class MistralAIModelComponent(LCModelComponent):
chat_model = ChatMistralAI(
max_tokens=max_tokens,
model_kwargs=model_kwargs,
model=model_name,
base_url=mistral_api_base,
model_name=model_name,
endpoint=mistral_api_base,
api_key=api_key,
temperature=temperature,
max_retries=max_retries,
timeout=timeout,
max_concurrent_requests=max_concurrent_requests,
top_p=top_p,
random_seed=random_seed,
safe_mode=safe_mode,
)
return self.get_chat_result(chat_model, stream, input_value, system_message)

View file

@ -224,11 +224,6 @@ wrappers:
documentation: ""
SQLDatabase:
documentation: ""
output_parsers:
StructuredOutputParser:
documentation: "https://python.langchain.com/docs/modules/model_io/output_parsers/structured"
ResponseSchema:
documentation: "https://python.langchain.com/docs/modules/model_io/output_parsers/structured"
custom_components:
CustomComponent:
documentation: "https://docs.langflow.org/guidelines/custom-component"

View file

@ -5,7 +5,6 @@ from langflow.interface.document_loaders.base import documentloader_creator
from langflow.interface.embeddings.base import embedding_creator
from langflow.interface.llms.base import llm_creator
from langflow.interface.memories.base import memory_creator
from langflow.interface.output_parsers.base import output_parser_creator
from langflow.interface.prompts.base import prompt_creator
from langflow.interface.retrievers.base import retriever_creator
from langflow.interface.text_splitters.base import textsplitter_creator
@ -46,7 +45,6 @@ class VertexTypesDict(LazyLoadDictBase):
# **{t: types.VectorStoreVertex for t in vectorstore_creator.to_list()},
**{t: types.DocumentLoaderVertex for t in documentloader_creator.to_list()},
**{t: types.TextSplitterVertex for t in textsplitter_creator.to_list()},
**{t: types.OutputParserVertex for t in output_parser_creator.to_list()},
**{t: types.CustomComponentVertex for t in custom_component_creator.to_list()},
**{t: types.RetrieverVertex for t in retriever_creator.to_list()},
**{t: types.ChatVertex for t in CHAT_COMPONENTS},

View file

@ -300,11 +300,6 @@ class PromptVertex(Vertex):
return str(self._built_object)
class OutputParserVertex(Vertex):
def __init__(self, data: Dict, graph):
super().__init__(data, graph=graph, base_type="output_parsers")
class CustomComponentVertex(Vertex):
def __init__(self, data: Dict, graph):
super().__init__(data, graph=graph, base_type="custom_components")

View file

@ -7,7 +7,7 @@ from langchain.agents.agent_toolkits.vectorstore.prompt import ROUTER_PREFIX as
from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS
from langchain.base_language import BaseLanguageModel
from langchain.chains.llm import LLMChain
from langchain.sql_database import SQLDatabase
from langchain_community.utilities import SQLDatabase
from langchain.tools.sql_database.prompt import QUERY_CHECKER
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_community.agent_toolkits.json.prompt import JSON_PREFIX, JSON_SUFFIX

View file

@ -1,7 +1,7 @@
import inspect
from typing import Any
from langchain import llms, memory, requests, text_splitter
from langchain import llms, memory, text_splitter
from langchain_community import agent_toolkits, document_loaders, embeddings
from langchain_community.chat_models import AzureChatOpenAI, ChatAnthropic, ChatOpenAI, ChatVertexAI
@ -43,8 +43,6 @@ memory_type_to_cls_dict: dict[str, Any] = {
memory_name: import_class(f"langchain.memory.{memory_name}") for memory_name in memory.__all__
}
# Wrappers
wrapper_type_to_cls_dict: dict[str, Any] = {wrapper.__name__: wrapper for wrapper in [requests.RequestsWrapper]}
# Embeddings
embedding_type_to_cls_dict: dict[str, Any] = {

Some files were not shown because too many files have changed in this diff Show more