Merge remote-tracking branch 'origin/dev' into feature/store

This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-11-14 21:41:58 -03:00
commit 60f6d08fc3
123 changed files with 2288 additions and 1124 deletions

View file

@ -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)

View file

@ -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"] == {

View file

@ -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",

View file

@ -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)

View file

@ -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

View file

@ -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",

View file

@ -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",

View file

@ -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

View file

@ -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",
}
]
}