Merge remote-tracking branch 'origin/dev' into zustand/io/migration

This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-02-06 14:21:50 -03:00
commit 6854c25dae
39 changed files with 2125 additions and 685 deletions

View file

@ -1,6 +1,6 @@
import time
from fastapi import APIRouter, Body, Depends, HTTPException, Query, WebSocket, WebSocketException, status
from fastapi import APIRouter, Body, Depends, HTTPException, WebSocket, WebSocketException, status
from fastapi.responses import StreamingResponse
from langflow.api.utils import build_input_keys_response, format_elapsed_time
from langflow.api.v1.schemas import (
@ -15,7 +15,7 @@ from langflow.api.v1.schemas import (
from langflow.graph.graph.base import Graph
from langflow.graph.vertex.base import StatelessVertex
from langflow.processing.process import process_tweaks_on_graph
from langflow.services.auth.utils import get_current_active_user, get_current_user_by_jwt
from langflow.services.auth.utils import get_current_active_user, get_current_user_for_websocket
from langflow.services.cache.service import BaseCacheService
from langflow.services.cache.utils import update_build_status
from langflow.services.chat.service import ChatService
@ -32,17 +32,16 @@ router = APIRouter(tags=["Chat"])
async def chat(
client_id: str,
websocket: WebSocket,
token: str = Query(...),
db: Session = Depends(get_session),
chat_service: "ChatService" = Depends(get_chat_service),
):
"""Websocket endpoint for chat."""
try:
user = await get_current_user_by_jwt(token, db)
user = await get_current_user_for_websocket(websocket, db)
await websocket.accept()
if not user:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized")
if not user.is_active:
elif not user.is_active:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized")
if client_id in chat_service.cache_service:

View file

@ -41,12 +41,11 @@ class AgentInitializerComponent(CustomComponent):
handle_parsing_errors=True,
max_iterations=max_iterations,
)
else:
return initialize_agent(
tools=tools,
llm=llm,
agent=agent,
return_intermediate_steps=True,
handle_parsing_errors=True,
max_iterations=max_iterations,
)
return initialize_agent(
tools=tools,
llm=llm,
agent=agent,
return_intermediate_steps=True,
handle_parsing_errors=True,
max_iterations=max_iterations,
)

View file

@ -3,13 +3,12 @@ from typing import List, Optional
from langchain.agents.agent import AgentExecutor
from langchain.agents.agent_toolkits.conversational_retrieval.openai_functions import _get_default_system_message
from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent
from langchain_community.chat_models import ChatOpenAI
from langchain.memory.token_buffer import ConversationTokenBufferMemory
from langchain.prompts import SystemMessagePromptTemplate
from langchain.prompts.chat import MessagesPlaceholder
from langchain.schema.memory import BaseMemory
from langchain.tools import Tool
from langchain_community.chat_models import ChatOpenAI
from langflow import CustomComponent
from langflow.field_typing.range_spec import RangeSpec
@ -20,11 +19,12 @@ class ConversationalAgent(CustomComponent):
def build_config(self):
openai_function_models = [
"gpt-4-turbo-preview",
"gpt-4-0125-preview",
"gpt-4-1106-preview",
"gpt-3.5-turbo",
"gpt-3.5-turbo-16k",
"gpt-4",
"gpt-4-32k",
"gpt-4-vision-preview",
"gpt-3.5-turbo-0125",
"gpt-3.5-turbo-1106",
]
return {
"tools": {"display_name": "Tools"},

View file

@ -1,7 +1,6 @@
from langchain.llms.base import BaseLLM
from langchain.prompts import PromptTemplate
from langchain_core.messages import BaseMessage
from langflow import CustomComponent
from langflow.field_typing import Text

View file

@ -1,5 +1,4 @@
from langchain.schema import Document
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.utils.constants import LOADERS_INFO

View file

@ -1,7 +1,8 @@
from typing import List
from langchain import document_loaders
from langchain.schema import Document
from langchain_core.documents import Document
from langflow import CustomComponent

View file

@ -42,7 +42,11 @@ class OpenAIEmbeddingsComponent(CustomComponent):
"advanced": True,
},
"max_retries": {"display_name": "Max Retries", "advanced": True},
"model": {"display_name": "Model", "advanced": True},
"model": {
"display_name": "Model",
"advanced": False,
"options": ["text-embedding-3-small", "text-embedding-3-large", "text-embedding-ada-002"],
},
"model_kwargs": {"display_name": "Model Kwargs", "advanced": True},
"openai_api_base": {"display_name": "OpenAI API Base", "password": True, "advanced": True},
"openai_api_key": {"display_name": "OpenAI API Key", "password": True},
@ -74,10 +78,10 @@ class OpenAIEmbeddingsComponent(CustomComponent):
disallowed_special: List[str] = ["all"],
chunk_size: int = 1000,
client: Optional[Any] = None,
deployment: str = "text-embedding-ada-002",
deployment: str = "text-embedding-3-small",
embedding_ctx_length: int = 8191,
max_retries: int = 6,
model: str = "text-embedding-ada-002",
model: str = "text-embedding-3-small",
model_kwargs: NestedDict = {},
openai_api_base: Optional[str] = None,
openai_api_key: Optional[str] = "",

View file

@ -2,6 +2,7 @@ from typing import Optional, Union
from langchain.llms import BaseLLM
from langchain_community.chat_models.openai import ChatOpenAI
from langflow import CustomComponent
from langflow.field_typing import BaseLanguageModel, NestedDict
@ -30,11 +31,12 @@ class ChatOpenAIComponent(CustomComponent):
"advanced": False,
"required": False,
"options": [
"gpt-4-turbo-preview",
"gpt-4-0125-preview",
"gpt-4-1106-preview",
"gpt-4",
"gpt-4-32k",
"gpt-3.5-turbo",
"gpt-3.5-turbo-16k",
"gpt-4-vision-preview",
"gpt-3.5-turbo-0125",
"gpt-3.5-turbo-1106",
],
},
"openai_api_base": {

View file

@ -1,7 +1,7 @@
from typing import Optional
from langchain.schema import Document
from langchain.text_splitter import Language
from langchain_core.documents import Document
from langflow import CustomComponent

View file

@ -1,7 +1,10 @@
from typing import Optional
from langchain_core.documents import Document
from langflow import CustomComponent
from langchain.schema import Document
from langflow.utils.util import build_loader_repr_from_documents
from langchain.text_splitter import RecursiveCharacterTextSplitter
class RecursiveCharacterTextSplitterComponent(CustomComponent):
@ -54,7 +57,6 @@ class RecursiveCharacterTextSplitterComponent(CustomComponent):
Returns:
list[str]: The chunks of text.
"""
from langchain.text_splitter import RecursiveCharacterTextSplitter
if separators == "":
separators = None

View file

@ -1,9 +1,10 @@
from langflow import CustomComponent
from langchain.schema import Document
from langflow.services.database.models.base import orjson_dumps
import requests
from typing import Optional
import requests
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.services.database.models.base import orjson_dumps
class GetRequest(CustomComponent):
display_name: str = "GET Request"

View file

@ -11,7 +11,7 @@
# - **Document:** The Document containing the JSON object.
from langchain.schema import Document
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.services.database.models.base import orjson_dumps

View file

@ -1,9 +1,10 @@
from langflow import CustomComponent
from langchain.schema import Document
from langflow.services.database.models.base import orjson_dumps
import requests
from typing import Optional
import requests
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.services.database.models.base import orjson_dumps
class PostRequest(CustomComponent):
display_name: str = "POST Request"

View file

@ -1,7 +1,8 @@
from typing import List, Optional
import requests
from langchain_core.documents import Document
from langflow import CustomComponent
from langchain.schema import Document
from langflow.services.database.models.base import orjson_dumps

View file

@ -1,9 +1,11 @@
from typing import Optional
from typing import Optional, Union
from langchain.embeddings.base import Embeddings
from langchain.schema import Document
from langchain_community.vectorstores import VectorStore
from langchain_community.vectorstores.redis import Redis
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever
from langflow import CustomComponent
@ -42,7 +44,7 @@ class RedisComponent(CustomComponent):
redis_server_url: str,
redis_index_name: str,
documents: Optional[Document] = None,
) -> VectorStore:
) -> Union[VectorStore, BaseRetriever]:
"""
Builds the Vector Store or BaseRetriever object.
@ -55,10 +57,19 @@ class RedisComponent(CustomComponent):
Returns:
- VectorStore: The Vector Store object.
"""
return Redis.from_documents(
documents=documents, # type: ignore
embedding=embedding,
redis_url=redis_server_url,
index_name=redis_index_name,
)
if documents is None:
redis_vs = Redis.from_existing_index(
embedding=embedding,
index_name=redis_index_name,
schema=None,
key_prefix=None,
redis_url=redis_server_url,
)
else:
redis_vs = Redis.from_documents(
documents=documents, # type: ignore
embedding=embedding,
redis_url=redis_server_url,
index_name=redis_index_name,
)
return redis_vs

View file

@ -3,11 +3,12 @@ import urllib
import urllib.request
from typing import List, Optional, Union
from langchain.embeddings import FakeEmbeddings
from langchain.schema import BaseRetriever, Document
from langchain_community.vectorstores import Vectara, VectorStore
from langchain_community.embeddings import FakeEmbeddings
from langchain_community.vectorstores.vectara import Vectara
from langchain_core.vectorstores import VectorStore
from langflow import CustomComponent
from langflow.field_typing import BaseRetriever, Document
class VectaraComponent(CustomComponent):
@ -18,25 +19,18 @@ class VectaraComponent(CustomComponent):
field_config = {
"vectara_customer_id": {
"display_name": "Vectara Customer ID",
"required": True,
},
"vectara_corpus_id": {
"display_name": "Vectara Corpus ID",
"required": True,
},
"vectara_api_key": {
"display_name": "Vectara API Key",
"password": True,
"required": True,
},
"code": {"show": False},
"documents": {
"display_name": "Documents",
"info": "Pass in either for Self Query Retriever or for making a Vectara Object",
},
"documents": {"display_name": "Documents", "info": "If provided, will be upserted to corpus (optional)"},
"files_url": {
"display_name": "Files Url",
"info": "Make vectara object using url of files(documents not needed)",
"info": "Make vectara object using url of files (optional)",
},
}
@ -48,6 +42,8 @@ class VectaraComponent(CustomComponent):
files_url: Optional[List[str]] = None,
documents: Optional[Document] = None,
) -> Union[VectorStore, BaseRetriever]:
source = "Langflow"
if documents is not None:
return Vectara.from_documents(
documents=documents,
@ -55,6 +51,7 @@ class VectaraComponent(CustomComponent):
vectara_customer_id=vectara_customer_id,
vectara_corpus_id=vectara_corpus_id,
vectara_api_key=vectara_api_key,
source=source,
)
if files_url is not None:
@ -70,10 +67,12 @@ class VectaraComponent(CustomComponent):
vectara_customer_id=vectara_customer_id,
vectara_corpus_id=vectara_corpus_id,
vectara_api_key=vectara_api_key,
source=source,
)
return Vectara(
vectara_customer_id=vectara_customer_id,
vectara_corpus_id=vectara_corpus_id,
vectara_api_key=vectara_api_key,
source=source,
)

View file

@ -1,13 +1,15 @@
from typing import List, Optional
from typing import Optional, Union
from langchain.embeddings.base import Embeddings
from langchain.schema import Document
from langchain_community.vectorstores import VectorStore
from langchain_community.vectorstores.pgvector import PGVector
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever
from langflow import CustomComponent
class PostgresqlVectorComponent(CustomComponent):
class PGVectorComponent(CustomComponent):
"""
A custom component for implementing a Vector Store using PostgreSQL.
"""
@ -15,7 +17,6 @@ class PostgresqlVectorComponent(CustomComponent):
display_name: str = "PGVector"
description: str = "Implementation of Vector Store using PostgreSQL"
documentation = "https://python.langchain.com/docs/integrations/vectorstores/pgvector"
beta = True
def build_config(self):
"""
@ -25,8 +26,7 @@ class PostgresqlVectorComponent(CustomComponent):
- dict: A dictionary containing the configuration options for the component.
"""
return {
"index_name": {"display_name": "Index Name", "value": "your_index"},
"code": {"show": True, "display_name": "Code"},
"code": {"show": False},
"documents": {"display_name": "Documents", "is_list": True},
"embedding": {"display_name": "Embedding"},
"pg_server_url": {
@ -41,8 +41,8 @@ class PostgresqlVectorComponent(CustomComponent):
embedding: Embeddings,
pg_server_url: str,
collection_name: str,
documents: Optional[List[Document]] = None,
) -> VectorStore:
documents: Optional[Document] = None,
) -> Union[VectorStore, BaseRetriever]:
"""
Builds the Vector Store or BaseRetriever object.
@ -58,13 +58,13 @@ class PostgresqlVectorComponent(CustomComponent):
try:
if documents is None:
return PGVector.from_existing_index(
vector_store = PGVector.from_existing_index(
embedding=embedding,
collection_name=collection_name,
connection_string=pg_server_url,
)
return PGVector.from_documents(
vector_store = PGVector.from_documents(
embedding=embedding,
documents=documents,
collection_name=collection_name,
@ -72,3 +72,4 @@ class PostgresqlVectorComponent(CustomComponent):
)
except Exception as e:
raise RuntimeError(f"Failed to build PGVector: {e}")
return vector_store

View file

@ -174,6 +174,8 @@ prompts:
textsplitters:
CharacterTextSplitter:
documentation: "https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter"
RecursiveCharacterTextSplitter:
documentation: "https://python.langchain.com/docs/modules/data_connection/document_transformers/recursive_text_splitter"
toolkits:
OpenAPIToolkit:
documentation: ""

View file

@ -2,6 +2,7 @@ import ast
import os
import zlib
from langflow.interface.custom.custom_component import CustomComponent
from loguru import logger
@ -245,9 +246,18 @@ class DirectoryReader:
else:
component_name_camelcase = component_name
if validation_result:
try:
output_types = self.get_output_types_from_code(result_content)
except Exception as exc:
logger.exception(f"Error while getting output types from code: {str(exc)}")
output_types = [component_name_camelcase]
else:
output_types = [component_name_camelcase]
component_info = {
"name": "CustomComponent",
"output_types": [component_name_camelcase],
"output_types": output_types,
"file": filename,
"code": result_content if validation_result else "",
"error": "" if validation_result else result_content,
@ -259,3 +269,13 @@ class DirectoryReader:
response["menu"].append(menu_result)
logger.debug("-------------------- Component menu list built --------------------")
return response
@staticmethod
def get_output_types_from_code(code: str) -> list:
"""
Get the output types from the code.
"""
custom_component = CustomComponent(code=code)
types_list = custom_component.get_function_entrypoint_return_type
# Get the name of types classes
return [type_.__name__ for type_ in types_list if hasattr(type_, "__name__")]

View file

@ -7,8 +7,6 @@ from typing import Any, Dict, List, Optional, Union
from uuid import UUID
from fastapi import HTTPException
from loguru import logger
from langflow.field_typing.range_spec import RangeSpec
from langflow.interface.custom.code_parser.utils import extract_inner_type
from langflow.interface.custom.custom_component import CustomComponent
@ -21,6 +19,7 @@ from langflow.interface.importing.utils import eval_custom_component_code
from langflow.template.field.base import TemplateField
from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
from langflow.utils.util import get_base_classes
from loguru import logger
def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: List[str]):

View file

@ -9,8 +9,8 @@ from langchain.agents.agent_toolkits.base import BaseToolkit
from langchain.agents.tools import BaseTool
from langchain.chains.base import Chain
from langchain.document_loaders.base import BaseLoader
from langchain.schema import Document
from langchain_community.vectorstores import VectorStore
from langchain_core.documents import Document
from loguru import logger
from pydantic import ValidationError

View file

@ -2,7 +2,6 @@ import os
from typing import Any, Callable, Dict, Type
import orjson
from langchain.schema import Document
from langchain_community.vectorstores import (
FAISS,
Chroma,
@ -13,6 +12,7 @@ from langchain_community.vectorstores import (
SupabaseVectorStore,
Weaviate,
)
from langchain_core.documents import Document
def docs_in_params(params: dict) -> bool:

View file

@ -7,6 +7,7 @@ from fastapi import Depends, HTTPException, Security, status
from fastapi.security import APIKeyHeader, APIKeyQuery, OAuth2PasswordBearer
from jose import JWTError, jwt
from sqlmodel import Session
from starlette.websockets import WebSocket
from langflow.services.database.models.api_key.model import ApiKey
from langflow.services.database.models.api_key.crud import check_key
@ -130,6 +131,21 @@ async def get_current_user_by_jwt(
return user
async def get_current_user_for_websocket(
websocket: WebSocket,
db: Session = Depends(get_session),
query_param: str = Security(api_key_query),
) -> Optional[User]:
token = websocket.query_params.get("token")
api_key = websocket.query_params.get("x-api-key")
if token:
return await get_current_user_by_jwt(token, db)
elif api_key:
return await api_key_security(api_key, query_param, db)
else:
return None
def get_current_active_user(current_user: Annotated[User, Depends(get_current_user)]):
if not current_user.is_active:
raise HTTPException(status_code=400, detail="Inactive user")

View file

@ -8,12 +8,12 @@ OPENAI_MODELS = [
"text-ada-001",
]
CHAT_OPENAI_MODELS = [
"gpt-4-turbo-preview",
"gpt-4-0125-preview",
"gpt-4-1106-preview",
"gpt-4-vision-preview",
"gpt-4",
"gpt-4-32k",
"gpt-3.5-turbo",
"gpt-3.5-turbo-16k",
"gpt-3.5-turbo-0125",
"gpt-3.5-turbo-1106",
]

View file

@ -1,14 +1,14 @@
import re
import inspect
import importlib
import inspect
import re
from functools import wraps
from typing import List, Optional, Dict, Any, Union
from typing import Any, Dict, List, Optional, Union
from docstring_parser import parse
from langchain_core.documents import Document
from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS
from langflow.utils import constants
from langchain.schema import Document
def remove_ansi_escape_codes(text):