Merge remote-tracking branch 'origin/dev' into feature/store
This commit is contained in:
commit
60f6d08fc3
123 changed files with 2288 additions and 1124 deletions
|
|
@ -1,26 +1,25 @@
|
|||
from contextlib import contextmanager
|
||||
import json
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
from typing import AsyncGenerator, TYPE_CHECKING
|
||||
|
||||
# we need to import tmpdir
|
||||
import tempfile
|
||||
from contextlib import contextmanager, suppress
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, AsyncGenerator
|
||||
|
||||
import orjson
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from httpx import AsyncClient
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.services.auth.utils import get_password_hash
|
||||
from langflow.services.database.models.flow.flow import Flow, FlowCreate
|
||||
from langflow.services.database.models.user.user import User, UserCreate
|
||||
import orjson
|
||||
from langflow.services.database.utils import session_getter
|
||||
from langflow.services.deps import get_db_service
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from httpx import AsyncClient
|
||||
from sqlmodel import SQLModel, Session, create_engine
|
||||
from sqlmodel import Session, SQLModel, create_engine
|
||||
from sqlmodel.pool import StaticPool
|
||||
from typer.testing import CliRunner
|
||||
|
||||
# we need to import tmpdir
|
||||
import tempfile
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.services.database.service import DatabaseService
|
||||
|
||||
|
|
@ -264,7 +263,12 @@ def flow(client, json_flow: str, active_user):
|
|||
from langflow.services.database.models.flow.flow import FlowCreate
|
||||
|
||||
loaded_json = json.loads(json_flow)
|
||||
flow_data = FlowCreate(name="test_flow", data=loaded_json.get("data"), user_id=active_user.id)
|
||||
flow_data = FlowCreate(
|
||||
name="test_flow",
|
||||
data=loaded_json.get("data"),
|
||||
user_id=active_user.id,
|
||||
description="description",
|
||||
)
|
||||
flow = Flow(**flow_data.dict())
|
||||
with session_getter(get_db_service()) as session:
|
||||
session.add(flow)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ def test_zero_shot_agent(client: TestClient, logged_in_headers):
|
|||
"ZeroShotAgent",
|
||||
"BaseSingleActionAgent",
|
||||
"Agent",
|
||||
"function",
|
||||
"Callable",
|
||||
}
|
||||
template = zero_shot_agent["template"]
|
||||
|
||||
|
|
@ -202,7 +202,7 @@ def test_initialize_agent(client: TestClient, logged_in_headers):
|
|||
agents = json_response["agents"]
|
||||
|
||||
initialize_agent = agents["AgentInitializer"]
|
||||
assert initialize_agent["base_classes"] == ["AgentExecutor", "function"]
|
||||
assert initialize_agent["base_classes"] == ["AgentExecutor", "Callable"]
|
||||
template = initialize_agent["template"]
|
||||
|
||||
assert template["agent"] == {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
# def test_chains_settings(client: TestClient, logged_in_headers):
|
||||
# response = client.get("api/v1/all", headers=logged_in_headers)
|
||||
# assert response.status_code == 200
|
||||
|
|
@ -9,167 +8,6 @@ from fastapi.testclient import TestClient
|
|||
# assert set(chains.keys()) == set(settings.chains)
|
||||
|
||||
|
||||
# Test the ConversationChain object
|
||||
def test_conversation_chain(client: TestClient, logged_in_headers):
|
||||
response = client.get("api/v1/all", headers=logged_in_headers)
|
||||
assert response.status_code == 200
|
||||
json_response = response.json()
|
||||
chains = json_response["chains"]
|
||||
|
||||
chain = chains["ConversationChain"]
|
||||
# Test the base classes, template, memory, verbose, llm, input_key, output_key, and _type objects
|
||||
assert set(chain["base_classes"]) == {
|
||||
"ConversationChain",
|
||||
"LLMChain",
|
||||
"Chain",
|
||||
"function",
|
||||
}
|
||||
|
||||
template = chain["template"]
|
||||
assert template["memory"] == {
|
||||
"required": False,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
"info": "",
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
"info": "",
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
"info": "",
|
||||
}
|
||||
assert template["input_key"] == {
|
||||
"required": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "input",
|
||||
"password": False,
|
||||
"name": "input_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
"info": "",
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "response",
|
||||
"password": False,
|
||||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
"info": "",
|
||||
}
|
||||
assert template["_type"] == "ConversationChain"
|
||||
|
||||
# Test the description object
|
||||
assert chain["description"] == "Chain to have a conversation and load context from memory."
|
||||
|
||||
|
||||
def test_llm_chain(client: TestClient, logged_in_headers):
|
||||
response = client.get("api/v1/all", headers=logged_in_headers)
|
||||
assert response.status_code == 200
|
||||
json_response = response.json()
|
||||
chains = json_response["chains"]
|
||||
chain = chains["LLMChain"]
|
||||
|
||||
# Test the base classes, template, memory, verbose, llm, input_key, output_key, and _type objects
|
||||
assert set(chain["base_classes"]) == {
|
||||
"function",
|
||||
"LLMChain",
|
||||
"Chain",
|
||||
}
|
||||
|
||||
template = chain["template"]
|
||||
assert template["memory"] == {
|
||||
"required": False,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "memory",
|
||||
"type": "BaseMemory",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
"info": "",
|
||||
}
|
||||
assert template["verbose"] == {
|
||||
"required": False,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"value": False,
|
||||
"password": False,
|
||||
"name": "verbose",
|
||||
"type": "bool",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
"info": "",
|
||||
}
|
||||
assert template["llm"] == {
|
||||
"required": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"password": False,
|
||||
"name": "llm",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
"info": "",
|
||||
}
|
||||
assert template["output_key"] == {
|
||||
"required": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "text",
|
||||
"password": False,
|
||||
"name": "output_key",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": True,
|
||||
"info": "",
|
||||
}
|
||||
|
||||
|
||||
def test_llm_checker_chain(client: TestClient, logged_in_headers):
|
||||
response = client.get("api/v1/all", headers=logged_in_headers)
|
||||
assert response.status_code == 200
|
||||
|
|
@ -179,7 +17,7 @@ def test_llm_checker_chain(client: TestClient, logged_in_headers):
|
|||
|
||||
# Test the base classes, template, memory, verbose, llm, input_key, output_key, and _type objects
|
||||
assert set(chain["base_classes"]) == {
|
||||
"function",
|
||||
"Callable",
|
||||
"LLMCheckerChain",
|
||||
"Chain",
|
||||
}
|
||||
|
|
@ -213,7 +51,7 @@ def test_llm_math_chain(client: TestClient, logged_in_headers):
|
|||
chain = chains["LLMMathChain"]
|
||||
# Test the base classes, template, memory, verbose, llm, input_key, output_key, and _type objects
|
||||
assert set(chain["base_classes"]) == {
|
||||
"function",
|
||||
"Callable",
|
||||
"LLMMathChain",
|
||||
"Chain",
|
||||
}
|
||||
|
|
@ -303,7 +141,7 @@ def test_series_character_chain(client: TestClient, logged_in_headers):
|
|||
|
||||
# Test the base classes, template, memory, verbose, llm, input_key, output_key, and _type objects
|
||||
assert set(chain["base_classes"]) == {
|
||||
"function",
|
||||
"Callable",
|
||||
"LLMChain",
|
||||
"BaseCustomChain",
|
||||
"Chain",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from langflow.interface.custom.base import CustomComponent
|
|||
from langflow.interface.custom.component import (
|
||||
Component,
|
||||
ComponentCodeNullError,
|
||||
ComponentFunctionEntrypointNameNullError,
|
||||
)
|
||||
from langflow.interface.custom.code_parser import CodeParser, CodeSyntaxError
|
||||
|
||||
|
|
@ -73,16 +72,16 @@ def test_component_init():
|
|||
"""
|
||||
Test the initialization of the Component class.
|
||||
"""
|
||||
component = Component(code=code_default, function_entrypoint_name="build")
|
||||
component = Component(code=code_default, _function_entrypoint_name="build")
|
||||
assert component.code == code_default
|
||||
assert component.function_entrypoint_name == "build"
|
||||
assert component._function_entrypoint_name == "build"
|
||||
|
||||
|
||||
def test_component_get_code_tree():
|
||||
"""
|
||||
Test the get_code_tree method of the Component class.
|
||||
"""
|
||||
component = Component(code=code_default, function_entrypoint_name="build")
|
||||
component = Component(code=code_default, _function_entrypoint_name="build")
|
||||
tree = component.get_code_tree(component.code)
|
||||
assert "imports" in tree
|
||||
|
||||
|
|
@ -92,19 +91,20 @@ def test_component_code_null_error():
|
|||
Test the get_function method raises the
|
||||
ComponentCodeNullError when the code is empty.
|
||||
"""
|
||||
component = Component(code="", function_entrypoint_name="")
|
||||
component = Component(code="", _function_entrypoint_name="")
|
||||
with pytest.raises(ComponentCodeNullError):
|
||||
component.get_function()
|
||||
|
||||
|
||||
def test_component_function_entrypoint_name_null_error():
|
||||
"""
|
||||
Test the get_function method raises the ComponentFunctionEntrypointNameNullError
|
||||
when the function_entrypoint_name is empty.
|
||||
"""
|
||||
component = Component(code=code_default, function_entrypoint_name="")
|
||||
with pytest.raises(ComponentFunctionEntrypointNameNullError):
|
||||
component.get_function()
|
||||
# TODO: Validate if we should remove this
|
||||
# def test_component_function_entrypoint_name_null_error():
|
||||
# """
|
||||
# Test the get_function method raises the ComponentFunctionEntrypointNameNullError
|
||||
# when the function_entrypoint_name is empty.
|
||||
# """
|
||||
# component = Component(code=code_default, _function_entrypoint_name="")
|
||||
# with pytest.raises(ComponentFunctionEntrypointNameNullError):
|
||||
# component.get_function()
|
||||
|
||||
|
||||
def test_custom_component_init():
|
||||
|
|
@ -206,7 +206,7 @@ def test_component_get_function_valid():
|
|||
Test the get_function method of the Component
|
||||
class with valid code and function_entrypoint_name.
|
||||
"""
|
||||
component = Component(code="def build(): pass", function_entrypoint_name="build")
|
||||
component = Component(code="def build(): pass", _function_entrypoint_name="build")
|
||||
my_function = component.get_function()
|
||||
assert callable(my_function)
|
||||
|
||||
|
|
@ -362,7 +362,7 @@ def test_component_get_code_tree_syntax_error():
|
|||
Test the get_code_tree method of the Component class
|
||||
raises the CodeSyntaxError when given incorrect syntax.
|
||||
"""
|
||||
component = Component(code="import os as", function_entrypoint_name="build")
|
||||
component = Component(code="import os as", _function_entrypoint_name="build")
|
||||
with pytest.raises(CodeSyntaxError):
|
||||
component.get_code_tree(component.code)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
from langflow.services.database.models.base import orjson_dumps
|
||||
from langflow.services.database.utils import session_getter
|
||||
from langflow.services.deps import get_db_service
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import orjson
|
||||
import pytest
|
||||
|
||||
from uuid import UUID, uuid4
|
||||
from sqlmodel import Session
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from langflow.api.v1.schemas import FlowListCreate
|
||||
from langflow.services.database.models.base import orjson_dumps
|
||||
from langflow.services.database.models.flow import Flow, FlowCreate, FlowUpdate
|
||||
from langflow.services.database.utils import session_getter
|
||||
from langflow.services.deps import get_db_service
|
||||
from sqlmodel import Session
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
|
@ -36,7 +34,7 @@ def test_create_flow(client: TestClient, json_flow: str, active_user, logged_in_
|
|||
assert response.json()["name"] == flow.name
|
||||
assert response.json()["data"] == flow.data
|
||||
# flow is optional so we can create a flow without a flow
|
||||
flow = FlowCreate(name="Test Flow")
|
||||
flow = FlowCreate(name="Test Flow", description="description")
|
||||
response = client.post("api/v1/flows/", json=flow.dict(exclude_unset=True), headers=logged_in_headers)
|
||||
assert response.status_code == 201
|
||||
assert response.json()["name"] == flow.name
|
||||
|
|
|
|||
|
|
@ -309,17 +309,14 @@ def test_chat_open_ai(client: TestClient, logged_in_headers):
|
|||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "gpt-3.5-turbo-0613",
|
||||
"value": "gpt-4-1106-preview",
|
||||
"password": False,
|
||||
"options": [
|
||||
"gpt-3.5-turbo-0613",
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-16k-0613",
|
||||
"gpt-3.5-turbo-16k",
|
||||
"gpt-4-0613",
|
||||
"gpt-4-32k-0613",
|
||||
"gpt-4-1106-preview",
|
||||
"gpt-4",
|
||||
"gpt-4-32k",
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-16k",
|
||||
],
|
||||
"name": "model_name",
|
||||
"type": "str",
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ def test_prompt_template(client: TestClient, logged_in_headers):
|
|||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"value": True,
|
||||
"value": False,
|
||||
"password": False,
|
||||
"name": "validate_template",
|
||||
"type": "bool",
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ def test_build_template_from_function():
|
|||
# Test with add_function=True
|
||||
result_with_function = build_template_from_function("ExampleClass1", type_to_loader_dict, add_function=True)
|
||||
assert result_with_function is not None
|
||||
assert "function" in result_with_function["base_classes"]
|
||||
assert "Callable" in result_with_function["base_classes"]
|
||||
|
||||
# Test with invalid name
|
||||
with pytest.raises(ValueError, match=r".* not found"):
|
||||
|
|
@ -235,7 +235,7 @@ def test_format_dict():
|
|||
"password": False,
|
||||
"multiline": False,
|
||||
"options": CHAT_OPENAI_MODELS,
|
||||
"value": "gpt-3.5-turbo-0613",
|
||||
"value": "gpt-4-1106-preview",
|
||||
},
|
||||
}
|
||||
assert format_dict(input_dict, "OpenAI") == expected_output_openai
|
||||
|
|
|
|||
|
|
@ -202,9 +202,14 @@ def test_patch_user_wrong_id(client, active_user, logged_in_headers):
|
|||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "uuid_parsing",
|
||||
"loc": ["path", "user_id"],
|
||||
"msg": "value is not a valid uuid",
|
||||
"type": "type_error.uuid",
|
||||
"msg": "Input should be a valid UUID, invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `w` at 1", # noqa
|
||||
"input": "wrong_id",
|
||||
"ctx": {
|
||||
"error": "invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `w` at 1" # noqa
|
||||
},
|
||||
"url": "https://errors.pydantic.dev/2.4/v/uuid_parsing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -224,9 +229,14 @@ def test_delete_user_wrong_id(client, test_user, super_user_headers):
|
|||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "uuid_parsing",
|
||||
"loc": ["path", "user_id"],
|
||||
"msg": "value is not a valid uuid",
|
||||
"type": "type_error.uuid",
|
||||
"msg": "Input should be a valid UUID, invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `w` at 1", # noqa
|
||||
"input": "wrong_id",
|
||||
"ctx": {
|
||||
"error": "invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `w` at 1" # noqa
|
||||
},
|
||||
"url": "https://errors.pydantic.dev/2.4/v/uuid_parsing",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue