Revert "Release 0.5.6"
This commit is contained in:
parent
8b40217f9d
commit
79b12b8135
134 changed files with 2228 additions and 11169 deletions
|
|
@ -35,16 +35,6 @@ def pytest_configure():
|
|||
pytest.OPENAPI_EXAMPLE_PATH = (
|
||||
Path(__file__).parent.absolute() / "data" / "Openapi.json"
|
||||
)
|
||||
pytest.GROUPED_CHAT_EXAMPLE_PATH = (
|
||||
Path(__file__).parent.absolute() / "data" / "grouped_chat.json"
|
||||
)
|
||||
pytest.ONE_GROUPED_CHAT_EXAMPLE_PATH = (
|
||||
Path(__file__).parent.absolute() / "data" / "one_group_chat.json"
|
||||
)
|
||||
pytest.VECTOR_STORE_GROUPED_EXAMPLE_PATH = (
|
||||
Path(__file__).parent.absolute() / "data" / "vector_store_grouped.json"
|
||||
)
|
||||
|
||||
pytest.BASIC_CHAT_WITH_PROMPT_AND_HISTORY = (
|
||||
Path(__file__).parent.absolute() / "data" / "BasicChatwithPromptandHistory.json"
|
||||
)
|
||||
|
|
@ -169,24 +159,6 @@ def json_flow():
|
|||
return f.read()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def grouped_chat_json_flow():
|
||||
with open(pytest.GROUPED_CHAT_EXAMPLE_PATH, "r") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def one_grouped_chat_json_flow():
|
||||
with open(pytest.ONE_GROUPED_CHAT_EXAMPLE_PATH, "r") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vector_store_grouped_json_flow():
|
||||
with open(pytest.VECTOR_STORE_GROUPED_EXAMPLE_PATH, "r") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def json_flow_with_prompt_and_history():
|
||||
with open(pytest.BASIC_CHAT_WITH_PROMPT_AND_HISTORY, "r") as f:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,3 @@
|
|||
import copy
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
|
@ -18,15 +17,6 @@ from langflow.graph.vertex.types import (
|
|||
)
|
||||
from langflow.processing.process import get_result_and_thought
|
||||
from langflow.utils.payload import get_root_node
|
||||
from langflow.graph.graph.utils import (
|
||||
find_last_node,
|
||||
set_new_target_handle,
|
||||
ungroup_node,
|
||||
process_flow,
|
||||
update_source_handle,
|
||||
update_target_handle,
|
||||
update_template,
|
||||
)
|
||||
|
||||
# Test cases for the graph module
|
||||
|
||||
|
|
@ -34,52 +24,6 @@ from langflow.graph.graph.utils import (
|
|||
# BASIC_EXAMPLE_PATH, COMPLEX_EXAMPLE_PATH, OPENAPI_EXAMPLE_PATH
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_template():
|
||||
return {
|
||||
"field1": {"proxy": {"field": "some_field", "id": "node1"}},
|
||||
"field2": {"proxy": {"field": "other_field", "id": "node2"}},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_nodes():
|
||||
return [
|
||||
{
|
||||
"id": "node1",
|
||||
"data": {
|
||||
"node": {
|
||||
"template": {
|
||||
"some_field": {"show": True, "advanced": False, "name": "Name1"}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "node2",
|
||||
"data": {
|
||||
"node": {
|
||||
"template": {
|
||||
"other_field": {
|
||||
"show": False,
|
||||
"advanced": True,
|
||||
"display_name": "DisplayName2",
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "node3",
|
||||
"data": {
|
||||
"node": {
|
||||
"template": {"unrelated_field": {"show": True, "advanced": True}}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def get_node_by_type(graph, node_type: Type[Vertex]) -> Union[Vertex, None]:
|
||||
"""Get a node by type"""
|
||||
return next((node for node in graph.nodes if isinstance(node, node_type)), None)
|
||||
|
|
@ -169,6 +113,55 @@ def test_get_node_neighbors_basic(basic_graph):
|
|||
)
|
||||
|
||||
|
||||
# def test_get_node_neighbors_complex(complex_graph):
|
||||
# """Test getting node neighbors"""
|
||||
# assert isinstance(complex_graph, Graph)
|
||||
# # Get root node
|
||||
# root = get_root_node(complex_graph)
|
||||
# assert root is not None
|
||||
# neighbors = complex_graph.get_nodes_with_target(root)
|
||||
# assert neighbors is not None
|
||||
# # Neighbors should be a list of nodes
|
||||
# assert isinstance(neighbors, list)
|
||||
# # Root Node is an Agent, it requires an LLMChain and tools
|
||||
# # We need to check if there is a Chain in the one of the neighbors'
|
||||
# assert any("Chain" in neighbor.data["type"] for neighbor in neighbors)
|
||||
# # assert Tool is in the neighbors
|
||||
# assert any("Tool" in neighbor.data["type"] for neighbor in neighbors)
|
||||
# # Now on to the Chain's neighbors
|
||||
# chain = next(neighbor for neighbor in neighbors if "Chain" in neighbor.data["type"])
|
||||
# chain_neighbors = complex_graph.get_nodes_with_target(chain)
|
||||
# assert chain_neighbors is not None
|
||||
# # Check if there is a LLM in the chain's neighbors
|
||||
# assert any("OpenAI" in neighbor.data["type"] for neighbor in chain_neighbors)
|
||||
# # Chain should have a Prompt as a neighbor
|
||||
# assert any("Prompt" in neighbor.data["type"] for neighbor in chain_neighbors)
|
||||
# # Now on to the Tool's neighbors
|
||||
# tool = next(neighbor for neighbor in neighbors if "Tool" in neighbor.data["type"])
|
||||
# tool_neighbors = complex_graph.get_nodes_with_target(tool)
|
||||
# assert tool_neighbors is not None
|
||||
# # Check if there is an Agent in the tool's neighbors
|
||||
# assert any("Agent" in neighbor.data["type"] for neighbor in tool_neighbors)
|
||||
# # This Agent has a Tool that has a PythonFunction as func
|
||||
# agent = next(
|
||||
# neighbor for neighbor in tool_neighbors if "Agent" in neighbor.data["type"]
|
||||
# )
|
||||
# agent_neighbors = complex_graph.get_nodes_with_target(agent)
|
||||
# assert agent_neighbors is not None
|
||||
# # Check if there is a Tool in the agent's neighbors
|
||||
# assert any("Tool" in neighbor.data["type"] for neighbor in agent_neighbors)
|
||||
# # This Tool has a PythonFunction as func
|
||||
# tool = next(
|
||||
# neighbor for neighbor in agent_neighbors if "Tool" in neighbor.data["type"]
|
||||
# )
|
||||
# tool_neighbors = complex_graph.get_nodes_with_target(tool)
|
||||
# assert tool_neighbors is not None
|
||||
# # Check if there is a PythonFunction in the tool's neighbors
|
||||
# assert any(
|
||||
# "PythonFunctionTool" in neighbor.data["type"] for neighbor in tool_neighbors
|
||||
# )
|
||||
|
||||
|
||||
def test_get_node(basic_graph):
|
||||
"""Test getting a single node"""
|
||||
node_id = basic_graph.nodes[0].id
|
||||
|
|
@ -329,196 +322,6 @@ def test_get_result_and_thought(basic_graph):
|
|||
assert isinstance(result, dict)
|
||||
|
||||
|
||||
def test_find_last_node(grouped_chat_json_flow):
|
||||
grouped_chat_data = json.loads(grouped_chat_json_flow).get("data")
|
||||
nodes, edges = grouped_chat_data["nodes"], grouped_chat_data["edges"]
|
||||
last_node = find_last_node(nodes, edges)
|
||||
assert last_node is not None # Replace with the actual expected value
|
||||
assert last_node["id"] == "LLMChain-pimAb" # Replace with the actual expected value
|
||||
|
||||
|
||||
def test_ungroup_node(grouped_chat_json_flow):
|
||||
grouped_chat_data = json.loads(grouped_chat_json_flow).get("data")
|
||||
group_node = grouped_chat_data["nodes"][
|
||||
2
|
||||
] # Assuming the first node is a group node
|
||||
base_flow = copy.deepcopy(grouped_chat_data)
|
||||
ungroup_node(group_node["data"], base_flow)
|
||||
# after ungroup_node is called, the base_flow and grouped_chat_data should be different
|
||||
assert base_flow != grouped_chat_data
|
||||
# assert node 2 is not a group node anymore
|
||||
assert base_flow["nodes"][2]["data"]["node"].get("flow") is None
|
||||
# assert the edges are updated
|
||||
assert len(base_flow["edges"]) > len(grouped_chat_data["edges"])
|
||||
assert base_flow["edges"][0]["source"] == "ConversationBufferMemory-kUMif"
|
||||
assert base_flow["edges"][0]["target"] == "LLMChain-2P369"
|
||||
assert base_flow["edges"][1]["source"] == "PromptTemplate-Wjk4g"
|
||||
assert base_flow["edges"][1]["target"] == "LLMChain-2P369"
|
||||
assert base_flow["edges"][2]["source"] == "ChatOpenAI-rUJ1b"
|
||||
assert base_flow["edges"][2]["target"] == "LLMChain-2P369"
|
||||
|
||||
|
||||
def test_process_flow(grouped_chat_json_flow):
|
||||
grouped_chat_data = json.loads(grouped_chat_json_flow).get("data")
|
||||
|
||||
processed_flow = process_flow(grouped_chat_data)
|
||||
assert processed_flow is not None
|
||||
assert isinstance(processed_flow, dict)
|
||||
assert "nodes" in processed_flow
|
||||
assert "edges" in processed_flow
|
||||
|
||||
|
||||
def test_process_flow_one_group(one_grouped_chat_json_flow):
|
||||
grouped_chat_data = json.loads(one_grouped_chat_json_flow).get("data")
|
||||
# There should be only one node
|
||||
assert len(grouped_chat_data["nodes"]) == 1
|
||||
# Get the node, it should be a group node
|
||||
group_node = grouped_chat_data["nodes"][0]
|
||||
node_data = group_node["data"]["node"]
|
||||
assert node_data.get("flow") is not None
|
||||
template_data = node_data["template"]
|
||||
assert any("openai_api_key" in key for key in template_data.keys())
|
||||
# Get the openai_api_key dict
|
||||
openai_api_key = next(
|
||||
(template_data[key] for key in template_data.keys() if "openai_api_key" in key),
|
||||
None,
|
||||
)
|
||||
assert openai_api_key is not None
|
||||
assert openai_api_key["value"] == "test"
|
||||
|
||||
processed_flow = process_flow(grouped_chat_data)
|
||||
assert processed_flow is not None
|
||||
assert isinstance(processed_flow, dict)
|
||||
assert "nodes" in processed_flow
|
||||
assert "edges" in processed_flow
|
||||
|
||||
# Now get the node that has ChatOpenAI in its id
|
||||
chat_openai_node = next(
|
||||
(node for node in processed_flow["nodes"] if "ChatOpenAI" in node["id"]), None
|
||||
)
|
||||
assert chat_openai_node is not None
|
||||
assert (
|
||||
chat_openai_node["data"]["node"]["template"]["openai_api_key"]["value"]
|
||||
== "test"
|
||||
)
|
||||
|
||||
|
||||
def test_process_flow_vector_store_grouped(vector_store_grouped_json_flow):
|
||||
grouped_chat_data = json.loads(vector_store_grouped_json_flow).get("data")
|
||||
nodes = grouped_chat_data["nodes"]
|
||||
assert len(nodes) == 4
|
||||
# There are two group nodes in this flow
|
||||
# One of them is inside the other totalling 7 nodes
|
||||
# 4 nodes grouped, one of these turns into 1 normal node and 1 group node
|
||||
# This group node has 2 nodes inside it
|
||||
|
||||
processed_flow = process_flow(grouped_chat_data)
|
||||
assert processed_flow is not None
|
||||
processed_nodes = processed_flow["nodes"]
|
||||
assert len(processed_nodes) == 7
|
||||
assert isinstance(processed_flow, dict)
|
||||
assert "nodes" in processed_flow
|
||||
assert "edges" in processed_flow
|
||||
edges = processed_flow["edges"]
|
||||
# Expected keywords in source and target fields
|
||||
expected_keywords = [
|
||||
{"source": "VectorStoreInfo", "target": "VectorStoreAgent"},
|
||||
{"source": "ChatOpenAI", "target": "VectorStoreAgent"},
|
||||
{"source": "OpenAIEmbeddings", "target": "Chroma"},
|
||||
{"source": "Chroma", "target": "VectorStoreInfo"},
|
||||
{"source": "WebBaseLoader", "target": "RecursiveCharacterTextSplitter"},
|
||||
{"source": "RecursiveCharacterTextSplitter", "target": "Chroma"},
|
||||
]
|
||||
|
||||
for idx, expected_keyword in enumerate(expected_keywords):
|
||||
for key, value in expected_keyword.items():
|
||||
assert (
|
||||
value in edges[idx][key].split("-")[0]
|
||||
), f"Edge {idx}, key {key} expected to contain {value} but got {edges[idx][key]}"
|
||||
|
||||
|
||||
def test_update_template(sample_template, sample_nodes):
|
||||
# Making a deep copy to keep original sample_nodes unchanged
|
||||
nodes_copy = copy.deepcopy(sample_nodes)
|
||||
update_template(sample_template, nodes_copy)
|
||||
|
||||
# Now, validate the updates.
|
||||
node1_updated = next((n for n in nodes_copy if n["id"] == "node1"), None)
|
||||
node2_updated = next((n for n in nodes_copy if n["id"] == "node2"), None)
|
||||
node3_updated = next((n for n in nodes_copy if n["id"] == "node3"), None)
|
||||
|
||||
assert node1_updated["data"]["node"]["template"]["some_field"]["show"] is True
|
||||
assert node1_updated["data"]["node"]["template"]["some_field"]["advanced"] is False
|
||||
assert (
|
||||
node1_updated["data"]["node"]["template"]["some_field"]["display_name"]
|
||||
== "Name1"
|
||||
)
|
||||
|
||||
assert node2_updated["data"]["node"]["template"]["other_field"]["show"] is False
|
||||
assert node2_updated["data"]["node"]["template"]["other_field"]["advanced"] is True
|
||||
assert (
|
||||
node2_updated["data"]["node"]["template"]["other_field"]["display_name"]
|
||||
== "DisplayName2"
|
||||
)
|
||||
|
||||
# Ensure node3 remains unchanged
|
||||
assert node3_updated == sample_nodes[2]
|
||||
|
||||
|
||||
# Test `update_target_handle`
|
||||
def test_update_target_handle_proxy():
|
||||
new_edge = {
|
||||
"data": {
|
||||
"targetHandle": {
|
||||
"type": "some_type",
|
||||
"proxy": {"id": "some_id", "field": ""},
|
||||
}
|
||||
}
|
||||
}
|
||||
g_nodes = [{"id": "some_id", "data": {"node": {"flow": None}}}]
|
||||
group_node_id = "group_id"
|
||||
updated_edge = update_target_handle(new_edge, g_nodes, group_node_id)
|
||||
assert updated_edge["data"]["targetHandle"] == new_edge["data"]["targetHandle"]
|
||||
|
||||
|
||||
# Test `set_new_target_handle`
|
||||
def test_set_new_target_handle():
|
||||
proxy_id = "proxy_id"
|
||||
new_edge = {"target": None, "data": {"targetHandle": {}}}
|
||||
target_handle = {"type": "type_1", "proxy": {"field": "field_1"}}
|
||||
node = {
|
||||
"data": {
|
||||
"node": {
|
||||
"flow": True,
|
||||
"template": {
|
||||
"field_1": {"proxy": {"field": "new_field", "id": "new_id"}}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
set_new_target_handle(proxy_id, new_edge, target_handle, node)
|
||||
assert new_edge["target"] == "proxy_id"
|
||||
assert new_edge["data"]["targetHandle"]["fieldName"] == "field_1"
|
||||
assert new_edge["data"]["targetHandle"]["proxy"] == {
|
||||
"field": "new_field",
|
||||
"id": "new_id",
|
||||
}
|
||||
|
||||
|
||||
# Test `update_source_handle`
|
||||
def test_update_source_handle():
|
||||
new_edge = {"source": None, "data": {"sourceHandle": {"id": None}}}
|
||||
flow_data = {
|
||||
"nodes": [{"id": "some_node"}, {"id": "last_node"}],
|
||||
"edges": [{"source": "some_node"}],
|
||||
}
|
||||
updated_edge = update_source_handle(
|
||||
new_edge, flow_data["nodes"], flow_data["edges"]
|
||||
)
|
||||
assert updated_edge["source"] == "last_node"
|
||||
assert updated_edge["data"]["sourceHandle"]["id"] == "last_node"
|
||||
|
||||
|
||||
def test_pickle_graph(json_vector_store):
|
||||
loaded_json = json.loads(json_vector_store)
|
||||
graph = Graph.from_payload(loaded_json)
|
||||
|
|
|
|||
|
|
@ -309,14 +309,17 @@ def test_chat_open_ai(client: TestClient, logged_in_headers):
|
|||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": False,
|
||||
"value": "gpt-4-1106-preview",
|
||||
"value": "gpt-3.5-turbo-0613",
|
||||
"password": False,
|
||||
"options": [
|
||||
"gpt-4-1106-preview",
|
||||
"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",
|
||||
"gpt-4-32k",
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-16k",
|
||||
],
|
||||
"name": "model_name",
|
||||
"type": "str",
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ def test_prompt_template(client: TestClient, logged_in_headers):
|
|||
template = prompt["template"]
|
||||
assert template["input_variables"] == {
|
||||
"required": True,
|
||||
"dynamic": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
|
|
@ -35,7 +35,7 @@ def test_prompt_template(client: TestClient, logged_in_headers):
|
|||
|
||||
assert template["output_parser"] == {
|
||||
"required": False,
|
||||
"dynamic": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
|
|
@ -49,7 +49,7 @@ def test_prompt_template(client: TestClient, logged_in_headers):
|
|||
|
||||
assert template["partial_variables"] == {
|
||||
"required": False,
|
||||
"dynamic": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
|
|
@ -63,7 +63,7 @@ def test_prompt_template(client: TestClient, logged_in_headers):
|
|||
|
||||
assert template["template"] == {
|
||||
"required": True,
|
||||
"dynamic": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": True,
|
||||
"multiline": True,
|
||||
|
|
@ -75,24 +75,9 @@ def test_prompt_template(client: TestClient, logged_in_headers):
|
|||
"info": "",
|
||||
}
|
||||
|
||||
assert template["template_format"] == {
|
||||
"required": False,
|
||||
"dynamic": True,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
"value": "f-string",
|
||||
"password": False,
|
||||
"name": "template_format",
|
||||
"type": "str",
|
||||
"list": False,
|
||||
"advanced": False,
|
||||
"info": "",
|
||||
}
|
||||
|
||||
assert template["validate_template"] == {
|
||||
"required": False,
|
||||
"dynamic": True,
|
||||
"dynamic": False,
|
||||
"placeholder": "",
|
||||
"show": False,
|
||||
"multiline": False,
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ def test_format_dict():
|
|||
"password": False,
|
||||
"multiline": False,
|
||||
"options": CHAT_OPENAI_MODELS,
|
||||
"value": "gpt-4-1106-preview",
|
||||
"value": "gpt-3.5-turbo-0613",
|
||||
},
|
||||
}
|
||||
assert format_dict(input_dict, "OpenAI") == expected_output_openai
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue