Merge branch 'logspace-ai:dev' into Add-Ollama-LLM

This commit is contained in:
yamonkjd 2023-12-23 03:58:56 +09:00 • committed by GitHub
commit 6c0b4fb416
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 833 additions and 650 deletions

View file

@ -8,6 +8,7 @@ on:
- dev - dev
paths: paths:
- "pyproject.toml" - "pyproject.toml"
workflow_dispatch:
env: env:
POETRY_VERSION: "1.5.1" POETRY_VERSION: "1.5.1"
@ -40,7 +41,7 @@ jobs:
generateReleaseNotes: true generateReleaseNotes: true
prerelease: true prerelease: true
tag: v${{ steps.check-version.outputs.version }} tag: v${{ steps.check-version.outputs.version }}
commit: main commit: dev
- name: Publish to PyPI - name: Publish to PyPI
env: env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}

1005
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "langflow" name = "langflow"
version = "0.6.3a5" version = "0.6.3"
description = "A Python package with a built-in web application" description = "A Python package with a built-in web application"
authors = ["Logspace <contact@logspace.ai>"] authors = ["Logspace <contact@logspace.ai>"]
maintainers = [ maintainers = [

View file

@ -1,19 +1,15 @@
import time import time
from fastapi import (APIRouter, Depends, HTTPException, Query, WebSocket, from fastapi import APIRouter, Depends, HTTPException, Query, WebSocket, WebSocketException, status
WebSocketException, status)
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from langflow.api.utils import build_input_keys_response, format_elapsed_time from langflow.api.utils import build_input_keys_response, format_elapsed_time
from langflow.api.v1.schemas import (BuildStatus, BuiltResponse, InitResponse, from langflow.api.v1.schemas import BuildStatus, BuiltResponse, InitResponse, StreamData
StreamData)
from langflow.graph.graph.base import Graph from langflow.graph.graph.base import Graph
from langflow.services.auth.utils import (get_current_active_user, from langflow.services.auth.utils import get_current_active_user, get_current_user_by_jwt
get_current_user_by_jwt)
from langflow.services.cache.service import BaseCacheService from langflow.services.cache.service import BaseCacheService
from langflow.services.cache.utils import update_build_status from langflow.services.cache.utils import update_build_status
from langflow.services.chat.service import ChatService from langflow.services.chat.service import ChatService
from langflow.services.deps import (get_cache_service, get_chat_service, from langflow.services.deps import get_cache_service, get_chat_service, get_session
get_session)
from loguru import logger from loguru import logger
from sqlmodel import Session from sqlmodel import Session

View file

@ -1,5 +1,5 @@
from http import HTTPStatus from http import HTTPStatus
from typing import Annotated, List, Optional, Union from typing import Annotated, Any, List, Optional, Union
import sqlalchemy as sa import sqlalchemy as sa
from fastapi import APIRouter, Body, Depends, HTTPException, UploadFile, status from fastapi import APIRouter, Body, Depends, HTTPException, UploadFile, status
@ -16,7 +16,7 @@ from langflow.api.v1.schemas import (
) )
from langflow.interface.custom.custom_component import CustomComponent from langflow.interface.custom.custom_component import CustomComponent
from langflow.interface.custom.directory_reader import DirectoryReader from langflow.interface.custom.directory_reader import DirectoryReader
from langflow.interface.custom.utils import build_custom_component_template, create_and_validate_component from langflow.interface.custom.utils import build_custom_component_template
from langflow.processing.process import process_graph_cached, process_tweaks from langflow.processing.process import process_graph_cached, process_tweaks
from langflow.services.auth.utils import api_key_security, get_current_active_user from langflow.services.auth.utils import api_key_security, get_current_active_user
from langflow.services.cache.utils import save_uploaded_file from langflow.services.cache.utils import save_uploaded_file
@ -49,7 +49,7 @@ async def process_graph_data(
task_service: "TaskService" = Depends(get_task_service), task_service: "TaskService" = Depends(get_task_service),
sync: bool = True, sync: bool = True,
): ):
task_result = None task_result: Any = None
task_status = None task_status = None
if tweaks: if tweaks:
try: try:
@ -270,7 +270,7 @@ async def custom_component(
raw_code: CustomComponentCode, raw_code: CustomComponentCode,
user: User = Depends(get_current_active_user), user: User = Depends(get_current_active_user),
): ):
component = create_and_validate_component(raw_code.code) component = CustomComponent(code=raw_code.code)
built_frontend_node = build_custom_component_template(component, user_id=user.id) built_frontend_node = build_custom_component_template(component, user_id=user.id)
@ -289,7 +289,6 @@ async def reload_custom_component(path: str, user: User = Depends(get_current_ac
raise ValueError(content) raise ValueError(content)
extractor = CustomComponent(code=content) extractor = CustomComponent(code=content)
extractor.validate()
return build_custom_component_template(extractor, user_id=user.id) return build_custom_component_template(extractor, user_id=user.id)
except Exception as exc: except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc)) raise HTTPException(status_code=400, detail=str(exc))
@ -300,7 +299,7 @@ async def custom_component_update(
raw_code: CustomComponentCode, raw_code: CustomComponentCode,
user: User = Depends(get_current_active_user), user: User = Depends(get_current_active_user),
): ):
component = create_and_validate_component(raw_code.code) component = CustomComponent(code=raw_code.code)
component_node = build_custom_component_template(component, user_id=user.id, update_field=raw_code.field) component_node = build_custom_component_template(component, user_id=user.id, update_field=raw_code.field)
# Update the field # Update the field

View file

@ -1,7 +1,6 @@
from typing import Callable, List, Union from typing import Callable, List, Optional, Union
from langchain.agents import AgentExecutor, AgentType, initialize_agent, types from langchain.agents import AgentExecutor, AgentType, initialize_agent, types
from langflow import CustomComponent from langflow import CustomComponent
from langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool from langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool
@ -20,12 +19,19 @@ class AgentInitializerComponent(CustomComponent):
"memory": {"display_name": "Memory"}, "memory": {"display_name": "Memory"},
"tools": {"display_name": "Tools"}, "tools": {"display_name": "Tools"},
"llm": {"display_name": "Language Model"}, "llm": {"display_name": "Language Model"},
"code": {"advanced": True},
} }
def build( def build(
self, agent: str, llm: BaseLanguageModel, memory: BaseChatMemory, tools: List[Tool], max_iterations: int self,
agent: str,
llm: BaseLanguageModel,
tools: List[Tool],
max_iterations: int,
memory: Optional[BaseChatMemory] = None,
) -> Union[AgentExecutor, Callable]: ) -> Union[AgentExecutor, Callable]:
agent = AgentType(agent) agent = AgentType(agent)
if memory:
return initialize_agent( return initialize_agent(
tools=tools, tools=tools,
llm=llm, llm=llm,
@ -35,3 +41,12 @@ class AgentInitializerComponent(CustomComponent):
handle_parsing_errors=True, handle_parsing_errors=True,
max_iterations=max_iterations, 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,
)

View file

@ -3,6 +3,7 @@ from langflow import CustomComponent
from langchain.llms.base import BaseLanguageModel from langchain.llms.base import BaseLanguageModel
from langchain.chat_models.azure_openai import AzureChatOpenAI from langchain.chat_models.azure_openai import AzureChatOpenAI
class AzureChatOpenAIComponent(CustomComponent): class AzureChatOpenAIComponent(CustomComponent):
display_name: str = "AzureChatOpenAI" display_name: str = "AzureChatOpenAI"
description: str = "LLM model from Azure OpenAI." description: str = "LLM model from Azure OpenAI."
@ -28,7 +29,7 @@ class AzureChatOpenAIComponent(CustomComponent):
"azure_endpoint": { "azure_endpoint": {
"display_name": "Azure Endpoint", "display_name": "Azure Endpoint",
"required": True, "required": True,
"info": "Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`" "info": "Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`",
}, },
"azure_deployment": { "azure_deployment": {
"display_name": "Deployment Name", "display_name": "Deployment Name",
@ -40,11 +41,7 @@ class AzureChatOpenAIComponent(CustomComponent):
"required": True, "required": True,
"advanced": True, "advanced": True,
}, },
"api_key": { "api_key": {"display_name": "API Key", "required": True, "password": True},
"display_name": "API Key",
"required": True,
"password": True
},
"temperature": { "temperature": {
"display_name": "Temperature", "display_name": "Temperature",
"value": 0.7, "value": 0.7,
@ -71,8 +68,6 @@ class AzureChatOpenAIComponent(CustomComponent):
temperature: float = 0.7, temperature: float = 0.7,
max_tokens: Optional[int] = 1000, max_tokens: Optional[int] = 1000,
) -> BaseLanguageModel: ) -> BaseLanguageModel:
return AzureChatOpenAI( return AzureChatOpenAI(
model=model, model=model,
azure_endpoint=azure_endpoint, azure_endpoint=azure_endpoint,
@ -80,5 +75,5 @@ class AzureChatOpenAIComponent(CustomComponent):
api_version=api_version, api_version=api_version,
api_key=api_key, api_key=api_key,
temperature=temperature, temperature=temperature,
max_tokens=max_tokens max_tokens=max_tokens,
) )

View file

@ -12,18 +12,29 @@ from langchain.embeddings.base import Embeddings
class WeaviateVectorStore(CustomComponent): class WeaviateVectorStore(CustomComponent):
display_name: str = "Weaviate" display_name: str = "Weaviate"
description: str = "Implementation of Vector Store using Weaviate" description: str = "Implementation of Vector Store using Weaviate"
documentation = ( documentation = "https://python.langchain.com/docs/integrations/vectorstores/weaviate"
"https://python.langchain.com/docs/integrations/vectorstores/weaviate"
)
beta = True beta = True
field_config = { field_config = {
"url": {"display_name": "Weaviate URL", "value": "http://localhost:8080"}, "url": {"display_name": "Weaviate URL", "value": "http://localhost:8080"},
"api_key": { "display_name": "API Key", "password": True,"required": False, }, "api_key": {
"index_name": {"display_name": "Index name","required": False,}, "display_name": "API Key",
"text_key": {"display_name": "Text Key","required": False, "advanced": True, "value": "text"}, "password": True,
"required": False,
},
"index_name": {
"display_name": "Index name",
"required": False,
},
"text_key": {"display_name": "Text Key", "required": False, "advanced": True, "value": "text"},
"documents": {"display_name": "Documents", "is_list": True}, "documents": {"display_name": "Documents", "is_list": True},
"embedding": {"display_name": "Embedding"}, "embedding": {"display_name": "Embedding"},
"attributes": {"display_name": "Attributes", "required": False, "is_list": True, "field_type": "str", "advanced": True}, "attributes": {
"display_name": "Attributes",
"required": False,
"is_list": True,
"field_type": "str",
"advanced": True,
},
"search_by_text": {"display_name": "Search By Text", "field_type": "bool", "advanced": True}, "search_by_text": {"display_name": "Search By Text", "field_type": "bool", "advanced": True},
"code": {"show": False}, "code": {"show": False},
} }

View file

@ -1,6 +1,6 @@
from typing import Any, List, Optional from typing import Any, Optional
from langchain.agents import AgentExecutor, AgentType, Tool, ZeroShotAgent, initialize_agent from langchain.agents import AgentExecutor, ZeroShotAgent
from langchain.agents.agent_toolkits import ( from langchain.agents.agent_toolkits import (
SQLDatabaseToolkit, SQLDatabaseToolkit,
VectorStoreInfo, VectorStoreInfo,
@ -15,7 +15,6 @@ from langchain.agents.agent_toolkits.vectorstore.prompt import ROUTER_PREFIX as
from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS
from langchain.base_language import BaseLanguageModel from langchain.base_language import BaseLanguageModel
from langchain.chains.llm import LLMChain from langchain.chains.llm import LLMChain
from langchain.memory.chat_memory import BaseChatMemory
from langchain.sql_database import SQLDatabase from langchain.sql_database import SQLDatabase
from langchain.tools.sql_database.prompt import QUERY_CHECKER from langchain.tools.sql_database.prompt import QUERY_CHECKER
from langchain_experimental.agents.agent_toolkits.pandas.prompt import PREFIX as PANDAS_PREFIX from langchain_experimental.agents.agent_toolkits.pandas.prompt import PREFIX as PANDAS_PREFIX

View file

@ -6,8 +6,7 @@ from typing import Any, Dict, List, Type, Union
from cachetools import TTLCache, cachedmethod, keys from cachetools import TTLCache, cachedmethod, keys
from fastapi import HTTPException from fastapi import HTTPException
from langflow.interface.custom.schema import (CallableCodeDetails, from langflow.interface.custom.schema import CallableCodeDetails, ClassCodeDetails
ClassCodeDetails)
class CodeSyntaxError(HTTPException): class CodeSyntaxError(HTTPException):

View file

@ -5,10 +5,11 @@ from uuid import UUID
import yaml import yaml
from cachetools import TTLCache, cachedmethod from cachetools import TTLCache, cachedmethod
from fastapi import HTTPException from fastapi import HTTPException
from langflow.interface.custom.code_parser.utils import ( from langflow.interface.custom.code_parser.utils import (
extract_inner_type_from_generic_alias, extract_inner_type_from_generic_alias,
extract_union_types_from_generic_alias) extract_union_types_from_generic_alias,
from langflow.interface.custom.directory_reader import DirectoryReader )
from langflow.services.database.models.flow import Flow from langflow.services.database.models.flow import Flow
from langflow.services.database.utils import session_getter from langflow.services.database.utils import session_getter
from langflow.services.deps import get_credential_service, get_db_service from langflow.services.deps import get_credential_service, get_db_service
@ -46,34 +47,6 @@ class CustomComponent(Component):
def build_config(self): def build_config(self):
return self.field_config return self.field_config
def _class_template_validation(self, code: str):
TYPE_HINT_LIST = ["Optional", "Prompt", "PromptTemplate", "LLMChain"]
if not code:
raise HTTPException(
status_code=400,
detail={
"error": self.ERROR_CODE_NULL,
"traceback": "",
},
)
reader = DirectoryReader("", False)
for type_hint in TYPE_HINT_LIST:
if reader._is_type_hint_used_in_args(type_hint, code) and not reader._is_type_hint_imported(
type_hint, code
):
error_detail = {
"error": "Type hint Error",
"traceback": f"Type hint '{type_hint}' is used but not imported in the code.",
}
raise HTTPException(status_code=400, detail=error_detail)
return True
def validate(self) -> bool:
return self._class_template_validation(self.code) if self.code else False
@property @property
def tree(self): def tree(self):
return self.get_code_tree(self.code or "") return self.get_code_tree(self.code or "")
@ -206,8 +179,7 @@ class CustomComponent(Component):
return validate.create_function(self.code, self.function_entrypoint_name) return validate.create_function(self.code, self.function_entrypoint_name)
async def load_flow(self, flow_id: str, tweaks: Optional[dict] = None) -> Any: async def load_flow(self, flow_id: str, tweaks: Optional[dict] = None) -> Any:
from langflow.processing.process import (build_sorted_vertices, from langflow.processing.process import build_sorted_vertices, process_tweaks
process_tweaks)
db_service = get_db_service() db_service = get_db_service()
with session_getter(db_service) as session: with session_getter(db_service) as session:

View file

@ -65,12 +65,13 @@ class DirectoryReader:
def filter_loaded_components(self, data: dict, with_errors: bool) -> dict: def filter_loaded_components(self, data: dict, with_errors: bool) -> dict:
from langflow.interface.custom.utils import build_component from langflow.interface.custom.utils import build_component
items = [ items = [
{ {
"name": menu["name"], "name": menu["name"],
"path": menu["path"], "path": menu["path"],
"components": [ "components": [
(*build_component(component),component) (*build_component(component), component)
for component in menu["components"] for component in menu["components"]
if (component["error"] if with_errors else not component["error"]) if (component["error"] if with_errors else not component["error"])
], ],

View file

@ -1,6 +1,5 @@
from langflow.interface.custom.directory_reader import DirectoryReader from langflow.interface.custom.directory_reader import DirectoryReader
from langflow.template.frontend_node.custom_components import \ from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
CustomComponentFrontendNode
from loguru import logger from loguru import logger
@ -79,7 +78,6 @@ def create_invalid_component_template(component, component_name):
display_name=f"ERROR - {component_name}", display_name=f"ERROR - {component_name}",
) )
component_frontend_node.error = component.get("error", None) component_frontend_node.error = component.get("error", None)
field = component_frontend_node.template.get_field("code") field = component_frontend_node.template.get_field("code")
field.value = component_code field.value = component_code

View file

@ -7,18 +7,20 @@ from typing import Any, Dict, List, Optional, Union
from uuid import UUID from uuid import UUID
from fastapi import HTTPException from fastapi import HTTPException
from loguru import logger
from langflow.field_typing.range_spec import RangeSpec from langflow.field_typing.range_spec import RangeSpec
from langflow.interface.custom.code_parser.utils import extract_inner_type from langflow.interface.custom.code_parser.utils import extract_inner_type
from langflow.interface.custom.custom_component import CustomComponent from langflow.interface.custom.custom_component import CustomComponent
from langflow.interface.custom.directory_reader.utils import ( from langflow.interface.custom.directory_reader.utils import (
build_custom_component_list_from_path, determine_component_name, build_custom_component_list_from_path,
merge_nested_dicts_with_renaming) determine_component_name,
merge_nested_dicts_with_renaming,
)
from langflow.interface.importing.utils import eval_custom_component_code from langflow.interface.importing.utils import eval_custom_component_code
from langflow.template.field.base import TemplateField from langflow.template.field.base import TemplateField
from langflow.template.frontend_node.custom_components import \ from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
CustomComponentFrontendNode
from langflow.utils.util import get_base_classes from langflow.utils.util import get_base_classes
from loguru import logger
def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: List[str]): def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: List[str]):
@ -174,9 +176,7 @@ def get_field_dict(field: Union[TemplateField, dict]):
return field return field
def run_build_config( def run_build_config(custom_component: CustomComponent, user_id: Optional[Union[str, UUID]] = None, update_field=None):
custom_component: CustomComponent, user_id: Optional[Union[str, UUID]] = None, update_field=None
):
"""Build the field configuration for a custom component""" """Build the field configuration for a custom component"""
try: try:
@ -311,7 +311,6 @@ def create_component_template(component):
component_output_types = component["output_types"] component_output_types = component["output_types"]
component_extractor = CustomComponent(code=component_code) component_extractor = CustomComponent(code=component_code)
component_extractor.validate()
component_template = build_custom_component_template(component_extractor) component_template = build_custom_component_template(component_extractor)
component_template["output_types"] = component_output_types component_template["output_types"] = component_output_types
@ -343,12 +342,6 @@ def build_custom_components(settings_service):
return custom_components_from_file return custom_components_from_file
def create_and_validate_component(code: str) -> CustomComponent:
component = CustomComponent(code=code)
component.validate()
return component
def update_field_dict(field_dict): def update_field_dict(field_dict):
"""Update the field dictionary by calling options() or value() if they are callable""" """Update the field dictionary by calling options() or value() if they are callable"""
if "options" in field_dict and callable(field_dict["options"]): if "options" in field_dict and callable(field_dict["options"]):
@ -378,6 +371,3 @@ def build_component(component):
component_name = determine_component_name(component) component_name = determine_component_name(component)
component_template = create_component_template(component) component_template = create_component_template(component)
return component_name, component_template return component_name, component_template

View file

@ -1,9 +1,7 @@
from cachetools import LRUCache, cached from cachetools import LRUCache, cached
from langflow.interface.agents.base import agent_creator from langflow.interface.agents.base import agent_creator
from langflow.interface.chains.base import chain_creator from langflow.interface.chains.base import chain_creator
from langflow.interface.custom.directory_reader.utils import \ from langflow.interface.custom.directory_reader.utils import merge_nested_dicts_with_renaming
merge_nested_dicts_with_renaming
from langflow.interface.custom.utils import build_custom_components from langflow.interface.custom.utils import build_custom_components
from langflow.interface.document_loaders.base import documentloader_creator from langflow.interface.document_loaders.base import documentloader_creator
from langflow.interface.embeddings.base import embedding_creator from langflow.interface.embeddings.base import embedding_creator
@ -70,5 +68,3 @@ def get_all_types_dict(settings_service):
native_components = build_langchain_types_dict() native_components = build_langchain_types_dict()
custom_components_from_file = build_custom_components(settings_service) custom_components_from_file = build_custom_components(settings_service)
return merge_nested_dicts_with_renaming(native_components, custom_components_from_file) return merge_nested_dicts_with_renaming(native_components, custom_components_from_file)

View file

@ -5,6 +5,7 @@ from langchain.agents import AgentExecutor
from langchain.chains.base import Chain from langchain.chains.base import Chain
from langchain.schema import AgentAction, Document from langchain.schema import AgentAction, Document
from langchain.vectorstores.base import VectorStore from langchain.vectorstores.base import VectorStore
from langchain_core.messages import AIMessage
from langchain_core.runnables.base import Runnable from langchain_core.runnables.base import Runnable
from langflow.interface.custom.custom_component import CustomComponent from langflow.interface.custom.custom_component import CustomComponent
from langflow.interface.run import build_sorted_vertices, get_memory_key, update_memory_keys from langflow.interface.run import build_sorted_vertices, get_memory_key, update_memory_keys
@ -105,10 +106,23 @@ def get_build_result(data_graph, session_id):
return build_sorted_vertices(data_graph) return build_sorted_vertices(data_graph)
def process_inputs(inputs: Optional[dict], artifacts: Dict[str, Any]) -> dict: def process_inputs(
inputs: Optional[Union[dict, List[dict]]] = None, artifacts: Optional[Dict[str, Any]] = None
) -> Union[dict, List[dict]]:
if inputs is None: if inputs is None:
inputs = {} inputs = {}
if artifacts is None:
artifacts = {}
if isinstance(inputs, dict):
inputs = update_inputs_dict(inputs, artifacts)
elif isinstance(inputs, List):
inputs = [update_inputs_dict(inp, artifacts) for inp in inputs]
return inputs
def update_inputs_dict(inputs: dict, artifacts: Dict[str, Any]) -> dict:
for key, value in artifacts.items(): for key, value in artifacts.items():
if key == "repr": if key == "repr":
continue continue
@ -125,6 +139,11 @@ async def process_runnable(runnable: Runnable, inputs: Union[dict, List[dict]]):
result = await runnable.ainvoke(inputs) result = await runnable.ainvoke(inputs)
else: else:
raise ValueError(f"Runnable {runnable} does not support inputs of type {type(inputs)}") raise ValueError(f"Runnable {runnable} does not support inputs of type {type(inputs)}")
# Check if the result is a list of AIMessages
if isinstance(result, list) and all(isinstance(r, AIMessage) for r in result):
result = [r.content for r in result]
elif isinstance(result, AIMessage):
result = result.content
return result return result

View file

@ -2,7 +2,7 @@ import ast
import contextlib import contextlib
import importlib import importlib
from types import FunctionType from types import FunctionType
from typing import Dict from typing import Dict, List, Optional, Union
from langflow.field_typing.constants import CUSTOM_COMPONENT_SUPPORTED_TYPES from langflow.field_typing.constants import CUSTOM_COMPONENT_SUPPORTED_TYPES
@ -260,14 +260,13 @@ def get_default_imports(code_string):
""" """
Returns a dictionary of default imports for the dynamic class constructor. Returns a dictionary of default imports for the dynamic class constructor.
""" """
typing_module = importlib.import_module("typing")
default_imports = {
"Optional": typing_module.Optional,
"List": typing_module.List,
"Dict": typing_module.Dict,
"Union": typing_module.Union,
}
default_imports = {
"Optional": Optional,
"List": List,
"Dict": Dict,
"Union": Union,
}
langflow_imports = list(CUSTOM_COMPONENT_SUPPORTED_TYPES.keys()) langflow_imports = list(CUSTOM_COMPONENT_SUPPORTED_TYPES.keys())
necessary_imports = find_names_in_code(code_string, langflow_imports) necessary_imports = find_names_in_code(code_string, langflow_imports)
langflow_module = importlib.import_module("langflow.field_typing") langflow_module = importlib.import_module("langflow.field_typing")

View file

@ -1,14 +1,13 @@
from typing import TYPE_CHECKING, Any, Dict, Optional from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
from celery.exceptions import SoftTimeLimitExceeded # type: ignore from celery.exceptions import SoftTimeLimitExceeded # type: ignore
from loguru import logger
from rich import print
from langflow.core.celery_app import celery_app from langflow.core.celery_app import celery_app
from langflow.processing.process import Result, generate_result, process_inputs from langflow.processing.process import Result, generate_result, process_inputs
from langflow.services.deps import get_session_service from langflow.services.deps import get_session_service
from langflow.services.manager import initialize_session_service from langflow.services.manager import initialize_session_service
from loguru import logger
from rich import print
if TYPE_CHECKING: if TYPE_CHECKING:
from langflow.graph.vertex.base import Vertex from langflow.graph.vertex.base import Vertex
@ -35,7 +34,7 @@ def build_vertex(self, vertex: "Vertex") -> "Vertex":
@celery_app.task(acks_late=True) @celery_app.task(acks_late=True)
def process_graph_cached_task( def process_graph_cached_task(
data_graph: Dict[str, Any], data_graph: Dict[str, Any],
inputs: Optional[dict] = None, inputs: Optional[Union[dict, List[dict]]] = None,
clear_cache=False, clear_cache=False,
session_id=None, session_id=None,
) -> Dict[str, Any]: ) -> Dict[str, Any]:

View file

@ -231,7 +231,7 @@ export default function ExtraSidebar(): JSX.Element {
return ( return (
<div className="side-bar-arrangement"> <div className="side-bar-arrangement">
<div className="side-bar-buttons-arrangement"> <div className="side-bar-buttons-arrangement">
{hasStore && ( {hasStore && validApiKey && (
<ShadTooltip <ShadTooltip
content={ content={
!hasApiKey || !validApiKey !hasApiKey || !validApiKey
@ -263,7 +263,7 @@ export default function ExtraSidebar(): JSX.Element {
</button> </button>
</ShadTooltip> </ShadTooltip>
</div> </div>
{!hasStore && ExportMemo} {(!hasApiKey || !validApiKey) && ExportMemo}
<ShadTooltip content={"Code"} side="top"> <ShadTooltip content={"Code"} side="top">
<div className="side-bar-button"> <div className="side-bar-button">
{flow && flow.data && ( {flow && flow.data && (

View file

@ -129,12 +129,12 @@ import { NotionIcon } from "../icons/Notion";
import { OpenAiIcon } from "../icons/OpenAi"; import { OpenAiIcon } from "../icons/OpenAi";
import { PineconeIcon } from "../icons/Pinecone"; import { PineconeIcon } from "../icons/Pinecone";
import { QDrantIcon } from "../icons/QDrant"; import { QDrantIcon } from "../icons/QDrant";
import { WeaviateIcon } from "../icons/Weaviate";
import { SearxIcon } from "../icons/Searx"; import { SearxIcon } from "../icons/Searx";
import { ShareIcon } from "../icons/Share"; import { ShareIcon } from "../icons/Share";
import { Share2Icon } from "../icons/Share2"; import { Share2Icon } from "../icons/Share2";
import SvgSlackIcon from "../icons/Slack/SlackIcon"; import SvgSlackIcon from "../icons/Slack/SlackIcon";
import { VertexAIIcon } from "../icons/VertexAI"; import { VertexAIIcon } from "../icons/VertexAI";
import { WeaviateIcon } from "../icons/Weaviate";
import SvgWikipedia from "../icons/Wikipedia/Wikipedia"; import SvgWikipedia from "../icons/Wikipedia/Wikipedia";
import SvgWolfram from "../icons/Wolfram/Wolfram"; import SvgWolfram from "../icons/Wolfram/Wolfram";
import { HackerNewsIcon } from "../icons/hackerNews"; import { HackerNewsIcon } from "../icons/hackerNews";

File diff suppressed because one or more lines are too long

View file

@ -3,14 +3,10 @@ import types
from uuid import uuid4 from uuid import uuid4
import pytest import pytest
from fastapi import HTTPException
from langflow.interface.custom.base import CustomComponent from langflow.interface.custom.base import CustomComponent
from langflow.interface.custom.code_parser.code_parser import (CodeParser, from langflow.interface.custom.code_parser.code_parser import CodeParser, CodeSyntaxError
CodeSyntaxError) from langflow.interface.custom.custom_component.component import Component, ComponentCodeNullError
from langflow.interface.custom.custom_component.component import ( from langflow.interface.custom.utils import build_custom_component_template
Component, ComponentCodeNullError)
from langflow.interface.custom.utils import (build_custom_component_template,
create_and_validate_component)
from langflow.services.database.models.flow import Flow, FlowCreate from langflow.services.database.models.flow import Flow, FlowCreate
code_default = """ code_default = """
@ -368,16 +364,6 @@ def test_component_get_code_tree_syntax_error():
component.get_code_tree(component.code) component.get_code_tree(component.code)
def test_custom_component_class_template_validation_no_code():
"""
Test the _class_template_validation method of the CustomComponent class
raises the HTTPException when the code is None.
"""
custom_component = CustomComponent(code=None, function_entrypoint_name="build")
with pytest.raises(HTTPException):
custom_component._class_template_validation(custom_component.code)
def test_custom_component_get_code_tree_syntax_error(): def test_custom_component_get_code_tree_syntax_error():
""" """
Test the get_code_tree method of the CustomComponent class Test the get_code_tree method of the CustomComponent class
@ -535,12 +521,12 @@ def test_build_config_field_value_keys(component):
def test_create_and_validate_component_valid_code(test_component_code): def test_create_and_validate_component_valid_code(test_component_code):
component = create_and_validate_component(test_component_code) component = CustomComponent(code=test_component_code)
assert isinstance(component, CustomComponent) assert isinstance(component, CustomComponent)
def test_build_langchain_template_custom_component_valid_code(test_component_code): def test_build_langchain_template_custom_component_valid_code(test_component_code):
component = create_and_validate_component(test_component_code) component = CustomComponent(code=test_component_code)
frontend_node = build_custom_component_template(component) frontend_node = build_custom_component_template(component)
assert isinstance(frontend_node, dict) assert isinstance(frontend_node, dict)
template = frontend_node["template"] template = frontend_node["template"]
@ -554,7 +540,7 @@ def test_build_langchain_template_custom_component_valid_code(test_component_cod
def test_build_langchain_template_custom_component_templatefield(test_component_with_templatefield_code): def test_build_langchain_template_custom_component_templatefield(test_component_with_templatefield_code):
component = create_and_validate_component(test_component_with_templatefield_code) component = CustomComponent(code=test_component_with_templatefield_code)
frontend_node = build_custom_component_template(component) frontend_node = build_custom_component_template(component)
assert isinstance(frontend_node, dict) assert isinstance(frontend_node, dict)
template = frontend_node["template"] template = frontend_node["template"]