Merge branch 'db' of personal:logspace-ai/langflow into db

This commit is contained in:
anovazzi1 2023-06-16 15:54:30 -03:00
commit 8fd94f0298
11 changed files with 76 additions and 101 deletions

2
poetry.lock generated
View file

@ -6416,4 +6416,4 @@ deploy = ["langchain-serve"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.9,<3.12"
content-hash = "e3a7355edeae80f8330e6e71fd5acbc446fd287397cf7d8d027ab6b450569f28"
content-hash = "4ed469589797b717f4b878f219dfe7c83d21d45d6947617693b6d2feb55cee3a"

View file

@ -61,6 +61,7 @@ faiss-cpu = "^1.7.4"
anthropic = "^0.2.9"
orjson = "^3.9.0"
multiprocess = "^0.70.14"
cachetools = "^5.3.1"
[tool.poetry.group.dev.dependencies]

View file

@ -12,10 +12,11 @@ from langflow.api.v1.schemas import BuiltResponse, InitResponse
from langflow.chat.manager import ChatManager
from langflow.graph.graph.base import Graph
from langflow.utils.logger import logger
from cachetools import LRUCache
router = APIRouter(tags=["Chat"])
chat_manager = ChatManager()
flow_data_store = {}
flow_data_store = LRUCache(maxsize=10)
@router.websocket("/chat/{client_id}")
@ -38,7 +39,8 @@ async def init_build(graph_data: dict):
try:
flow_id = graph_data.get("id")
if flow_id is None:
raise ValueError("No ID provided")
flow_data_store[flow_id] = graph_data
return InitResponse(flowId=flow_id)

View file

@ -3,7 +3,6 @@ from langflow.processing.process import process_graph_cached, process_tweaks
from langflow.utils.logger import logger
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security import HTTPBearer
from langflow.api.v1.schemas import (
PredictRequest,
@ -17,20 +16,6 @@ from sqlmodel import Session
# build router
router = APIRouter(tags=["Base"])
security = HTTPBearer()
def get_flow_from_token(
bearer: HTTPBearer = Depends(security), session: Session = Depends(get_session)
) -> str:
# Extract the token, which is the flow_id in this case
flow_id = bearer.credentials
# Check if the flow_id exists in the database
flow = session.get(Flow, flow_id)
if flow is None:
raise HTTPException(status_code=401, detail="Invalid token")
return flow
@router.get("/all")
def get_all():
@ -51,6 +36,9 @@ async def predict_flow(
flow = session.get(Flow, flow_id)
if flow is None:
raise ValueError(f"Flow {flow_id} not found")
if flow.data is None:
raise ValueError(f"Flow {flow_id} has no data")
graph_data = flow.data
if predict_request.tweaks:
graph_data = process_tweaks(graph_data, predict_request.tweaks)

View file

@ -252,7 +252,11 @@ class VectorStoreRouterAgent(CustomAgentExecutor):
):
"""Construct a vector store router agent from an LLM and tools."""
tools = vectorstoreroutertoolkit.get_tools()
tools = (
vectorstoreroutertoolkit
if isinstance(vectorstoreroutertoolkit, list)
else vectorstoreroutertoolkit.get_tools()
)
prompt = ZeroShotAgent.create_prompt(tools, prefix=VECTORSTORE_ROUTER_PREFIX)
llm_chain = LLMChain(
llm=llm,

View file

@ -1,3 +1,5 @@
import os
from fastapi import FastAPI
from fastapi.responses import FileResponse
from fastapi.middleware.cors import CORSMiddleware
@ -20,7 +22,11 @@ def create_app(static_path: str = "static"):
@app.exception_handler(404)
async def custom_404_handler(request, __):
return FileResponse(f"{static_path}/index.html")
path = f"{static_path}/index.html"
if not os.path.isfile(path):
raise RuntimeError(f"File at path {path} does not exist.")
return FileResponse(path)
app.add_middleware(
CORSMiddleware,

View file

@ -172,7 +172,7 @@ def load_flow_from_json(path: str, build=True):
return graph
def process_tweaks(graph_data: dict, tweaks: dict):
def process_tweaks(graph_data: Dict, tweaks: Dict):
"""This function is used to tweak the graph data using the node id and the tweaks dict"""
# the tweaks dict is a dict of dicts
# the key is the node id and the value is a dict of the tweaks

View file

@ -120,7 +120,7 @@ def test_initialize_agent(client: TestClient):
json_response = response.json()
agents = json_response["agents"]
initialize_agent = agents["initialize_agent"]
initialize_agent = agents["AgentInitializer"]
assert initialize_agent["base_classes"] == ["AgentExecutor", "function"]
template = initialize_agent["template"]
@ -136,6 +136,7 @@ def test_initialize_agent(client: TestClient):
"react-docstore",
"self-ask-with-search",
"conversational-react-description",
"openai-functions",
],
"name": "agent",
"type": "str",

View file

@ -18,14 +18,15 @@ def test_conversation_chain(client: TestClient):
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"]) == {
"function",
"LLMChain",
"ConversationChain",
"LLMChain",
"Chain",
"Serializable",
"function",
}
template = chain["template"]
assert template["memory"] == {
"required": False,
@ -101,7 +102,13 @@ def test_llm_chain(client: TestClient):
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"}
assert set(chain["base_classes"]) == {
"Serializable",
"function",
"LLMChain",
"Chain"
}
template = chain["template"]
assert template["memory"] == {
"required": False,
@ -159,31 +166,14 @@ def test_llm_checker_chain(client: TestClient):
chain = chains["LLMCheckerChain"]
# Test the base classes, template, memory, verbose, llm, input_key, output_key, and _type objects
assert set(chain["base_classes"]) == {"function", "LLMCheckerChain", "Chain"}
assert set(chain["base_classes"]) == {
"Serializable",
"function",
"LLMCheckerChain",
"Chain"
}
template = chain["template"]
assert template["memory"] == {
"required": False,
"placeholder": "",
"show": True,
"multiline": False,
"password": False,
"name": "memory",
"type": "BaseMemory",
"list": False,
"advanced": False,
}
assert template["verbose"] == {
"required": False,
"placeholder": "",
"show": True,
"multiline": False,
"value": False,
"password": False,
"name": "verbose",
"type": "bool",
"list": False,
"advanced": True,
}
assert template["llm"] == {
"required": True,
"placeholder": "",
@ -195,35 +185,11 @@ def test_llm_checker_chain(client: TestClient):
"list": False,
"advanced": False,
}
assert template["input_key"] == {
"required": True,
"placeholder": "",
"show": True,
"multiline": False,
"value": "query",
"password": False,
"name": "input_key",
"type": "str",
"list": False,
"advanced": True,
}
assert template["output_key"] == {
"required": True,
"placeholder": "",
"show": True,
"multiline": False,
"value": "result",
"password": False,
"name": "output_key",
"type": "str",
"list": False,
"advanced": True,
}
assert template["_type"] == "LLMCheckerChain"
# Test the description object
assert (
chain["description"] == "Chain for question-answering with self-verification."
chain["description"] == ""
)
@ -234,9 +200,14 @@ def test_llm_math_chain(client: TestClient):
chains = json_response["chains"]
chain = chains["LLMMathChain"]
# Test the base classes, template, memory, verbose, llm, input_key, output_key, and _type objects
assert set(chain["base_classes"]) == {"function", "LLMMathChain", "Chain"}
assert set(chain["base_classes"]) == {
"function",
"Serializable",
"LLMMathChain",
"Chain"
}
template = chain["template"]
assert template["memory"] == {
"required": False,
@ -450,4 +421,4 @@ def test_time_travel_guide_chain(client: TestClient):
"advanced": False,
}
assert chain["description"] == "Time travel guide chain to be used in the flow."
assert chain["description"] == "Time travel guide chain."

View file

@ -1,21 +1,21 @@
from uuid import UUID, uuid4
from langflow.api.v1.schemas import FlowListCreate
from langflow.database.models.flow import FlowCreate, FlowUpdate
import json
import pytest
import threading
from uuid import UUID, uuid4
from sqlalchemy.orm import Session
from langflow.database.models.flow import Flow
from fastapi.testclient import TestClient
from fastapi.encoders import jsonable_encoder
from langflow.api.v1.schemas import FlowListCreate
from langflow.database.models.flow import Flow, FlowCreate, FlowUpdate
from langflow.database.models.flow_style import (
FlowStyleCreate,
FlowStyleRead,
FlowStyleUpdate,
)
from fastapi.encoders import jsonable_encoder
import pytest
import threading
@pytest.fixture(scope="module")
@ -37,13 +37,13 @@ def test_create_flow(client: TestClient, json_flow: str):
data = flow["data"]
flow = FlowCreate(name="Test Flow", description="description", data=data)
response = client.post("api/v1/flows/", json=flow.dict())
assert response.status_code == 200
assert response.status_code == 201
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")
response = client.post("api/v1/flows/", json=flow.dict(exclude_unset=True))
assert response.status_code == 200
assert response.status_code == 201
assert response.json()["name"] == flow.name
assert response.json()["data"] == flow.data
@ -53,7 +53,7 @@ def test_read_flows(client: TestClient, json_flow: str):
data = flow_data["data"]
flow = FlowCreate(name="Test Flow", description="description", data=data)
response = client.post("api/v1/flows/", json=flow.dict())
assert response.status_code == 200
assert response.status_code == 201
assert response.json()["name"] == flow.name
assert response.json()["data"] == flow.data
@ -68,7 +68,7 @@ def test_read_flows(client: TestClient, json_flow: str):
flow = FlowCreate(name="Test Flow", description="description", data=data)
response = client.post("api/v1/flows/", json=flow.dict())
assert response.status_code == 200
assert response.status_code == 201
assert response.json()["name"] == flow.name
assert response.json()["data"] == flow.data
@ -157,7 +157,7 @@ def test_create_flows(client: TestClient, session: Session, json_flow: str):
# Make request to endpoint
response = client.post("api/v1/flows/batch/", json=flow_list.dict())
# Check response status code
assert response.status_code == 200
assert response.status_code == 201
# Check response data
response_data = response.json()
assert len(response_data) == 2
@ -185,7 +185,7 @@ def test_upload_file(client: TestClient, session: Session, json_flow: str):
files={"file": ("examples.json", file_contents, "application/json")},
)
# Check response status code
assert response.status_code == 200
assert response.status_code == 201
# Check response data
response_data = response.json()
assert len(response_data) == 2
@ -233,10 +233,10 @@ def test_create_flow_with_invalid_data(client: TestClient):
def test_get_nonexistent_flow(client: TestClient):
# uuid4 generates a random UUID
uuid = uuid4()
response = client.get(f"api/v1/flows/{uuid}")
assert response.status_code == 404
with pytest.raises(RuntimeError) as excinfo:
client.get(f"api/v1/flows/{uuid}")
assert str(excinfo.value) == "File at path static/index.html does not exist."
def test_update_flow_idempotency(client: TestClient, json_flow: str):
@ -260,14 +260,16 @@ def test_update_nonexistent_flow(client: TestClient, json_flow: str):
description="description",
data=data,
)
response = client.patch(f"api/v1/flows/{uuid}", json=updated_flow.dict())
assert response.status_code == 404
with pytest.raises(RuntimeError) as excinfo:
client.patch(f"api/v1/flows/{uuid}", json=updated_flow.dict())
assert str(excinfo.value) == "File at path static/index.html does not exist."
def test_delete_nonexistent_flow(client: TestClient):
uuid = uuid4()
response = client.delete(f"api/v1/flows/{uuid}")
assert response.status_code == 404
with pytest.raises(RuntimeError) as excinfo:
client.delete(f"api/v1/flows/{uuid}")
assert str(excinfo.value) == "File at path static/index.html does not exist."
def test_read_empty_flows(client: TestClient):

View file

@ -9,7 +9,7 @@ def test_init_build(client):
response = client.post(
"api/v1/build/init", json={"id": "test", "data": {"key": "value"}}
)
assert response.status_code == 200
assert response.status_code == 201
assert response.json() == {"flowId": "test"}