feat: ui build in one single http request (#3020)

* feat: ui build in one single http request

* fix use session_id

* fix frozen

* [autofix.ci] apply automated fixes

* prettier

* add tests

* add tests

* fix mypy

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Nicolò Boschi 2024-08-02 15:53:34 +02:00 • committed by GitHub
commit f311a6db54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 707 additions and 46 deletions

View file

@ -53,6 +53,7 @@ def pytest_configure(config):
pytest.TWO_OUTPUTS = data_path / "TwoOutputsTest.json"
pytest.VECTOR_STORE_PATH = data_path / "Vector_store.json"
pytest.SIMPLE_API_TEST = data_path / "SimpleAPITest.json"
pytest.MEMORY_CHATBOT_NO_LLM = data_path / "MemoryChatbotNoLLM.json"
pytest.CODE_WITH_SYNTAX_ERROR = """
def get_text():
retun "Hello World"
@ -70,6 +71,7 @@ def get_text():
pytest.CHAT_INPUT,
pytest.TWO_OUTPUTS,
pytest.VECTOR_STORE_PATH,
pytest.MEMORY_CHATBOT_NO_LLM,
]:
assert path.exists(), f"File {path} does not exist. Available files: {list(data_path.iterdir())}"
@ -232,6 +234,12 @@ def json_webhook_test():
return f.read()
@pytest.fixture
def json_memory_chatbot_no_llm():
with open(pytest.MEMORY_CHATBOT_NO_LLM, "r") as f:
return f.read()
@pytest.fixture(name="client", autouse=True)
def client_fixture(session: Session, monkeypatch, request, load_flows_dir):
# Set the database url to a test database

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,93 @@
import json
from uuid import UUID
from orjson import orjson
from langflow.memory import get_messages
from langflow.services.database.models.flow import FlowCreate, FlowUpdate
def test_build_flow(client, json_memory_chatbot_no_llm, logged_in_headers):
flow_id = _create_flow(client, json_memory_chatbot_no_llm, logged_in_headers)
with client.stream("POST", f"api/v1/build/{flow_id}/flow", json={}, headers=logged_in_headers) as r:
consume_and_assert_stream(r)
check_messages(flow_id)
def test_build_flow_from_request_data(client, json_memory_chatbot_no_llm, logged_in_headers):
flow_id = _create_flow(client, json_memory_chatbot_no_llm, logged_in_headers)
flow_data = client.get("api/v1/flows/" + str(flow_id), headers=logged_in_headers).json()
with client.stream(
"POST", f"api/v1/build/{flow_id}/flow", json={"data": flow_data["data"]}, headers=logged_in_headers
) as r:
consume_and_assert_stream(r)
check_messages(flow_id)
def test_build_flow_with_frozen_path(client, json_memory_chatbot_no_llm, logged_in_headers):
flow_id = _create_flow(client, json_memory_chatbot_no_llm, logged_in_headers)
flow_data = client.get("api/v1/flows/" + str(flow_id), headers=logged_in_headers).json()
flow_data["data"]["nodes"][0]["data"]["node"]["frozen"] = True
response = client.patch(
"api/v1/flows/" + str(flow_id),
json=FlowUpdate(name="Flow", description="description", data=flow_data["data"]).model_dump(),
headers=logged_in_headers,
)
response.raise_for_status()
with client.stream("POST", f"api/v1/build/{flow_id}/flow", json={}, headers=logged_in_headers) as r:
consume_and_assert_stream(r)
check_messages(flow_id)
def check_messages(flow_id):
messages = get_messages(flow_id=UUID(flow_id), order="ASC")
assert len(messages) == 2
assert messages[0].session_id == flow_id
assert messages[0].sender == "User"
assert messages[0].sender_name == "User"
assert messages[0].text == ""
assert messages[1].session_id == flow_id
assert messages[1].sender == "Machine"
assert messages[1].sender_name == "AI"
def consume_and_assert_stream(r):
count = 0
for line in r.iter_lines():
# httpx split by \n, but ndjson sends two \n for each line
if not line:
continue
parsed = json.loads(line)
if count == 0:
assert parsed["event"] == "vertices_sorted"
ids = parsed["data"]["ids"]
ids.sort()
assert ids == ["ChatInput-CIGht", "Memory-amN4Z"]
to_run = parsed["data"]["to_run"]
to_run.sort()
assert to_run == ["ChatInput-CIGht", "ChatOutput-QA7ej", "Memory-amN4Z", "Prompt-iWbCC"]
elif count > 0 and count < 5:
assert parsed["event"] == "end_vertex"
assert parsed["data"]["build_data"] is not None
elif count == 5:
assert parsed["event"] == "end"
else:
raise ValueError(f"Unexpected line: {line}")
count += 1
def _create_flow(client, json_memory_chatbot_no_llm, logged_in_headers):
vector_store = orjson.loads(json_memory_chatbot_no_llm)
data = vector_store["data"]
vector_store = FlowCreate(name="Flow", description="description", data=data, endpoint_name="f")
response = client.post("api/v1/flows/", json=vector_store.model_dump(), headers=logged_in_headers)
response.raise_for_status()
flow_id = response.json()["id"]
return flow_id