refactor: move tests folder structure and update pytest commands (#2785)

* refactor: move tests folder to src/backend

* chore(Makefile): update pytest commands to run tests from the correct directory paths for unit and integration tests

* refactor: update file path in test_custom_component.py

The file path in the test_custom_component.py file has been updated to use the correct relative path to the component_multiple_outputs.py file. This change ensures that the test code can access the correct file and improves the reliability of the test.
This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-07-18 12:19:43 -03:00 • committed by GitHub
commit 0122a50a35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 5 additions and 5 deletions

View file

@ -74,13 +74,13 @@ coverage: ## run the tests and generate a coverage report
# allow passing arguments to pytest
unit_tests: ## run unit tests
poetry run pytest \
--ignore=tests/integration \
poetry run pytest src/backend/tests \
--ignore=src/backend/tests/integration \
--instafail -ra -n auto -m "not api_key_required" \
$(args)
integration_tests: ## run integration tests
poetry run pytest tests/integration \
poetry run pytest src/backend/tests/integration \
--instafail -ra -n auto \
$(args)

View file

@ -0,0 +1,466 @@
import json
import os.path
import shutil
# 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 dotenv import load_dotenv
from fastapi.testclient import TestClient
from httpx import AsyncClient
from sqlmodel import Session, SQLModel, create_engine, select
from sqlmodel.pool import StaticPool
from typer.testing import CliRunner
from langflow.graph.graph.base import Graph
from langflow.initial_setup.setup import STARTER_FOLDER_NAME
from langflow.services.auth.utils import get_password_hash
from langflow.services.database.models.api_key.model import ApiKey
from langflow.services.database.models.flow.model import Flow, FlowCreate
from langflow.services.database.models.folder.model import Folder
from langflow.services.database.models.user.model import User, UserCreate
from langflow.services.database.utils import session_getter
from langflow.services.deps import get_db_service
if TYPE_CHECKING:
from langflow.services.database.service import DatabaseService
load_dotenv()
def pytest_configure(config):
config.addinivalue_line("markers", "noclient: don't create a client for this test")
config.addinivalue_line("markers", "load_flows: load the flows for this test")
config.addinivalue_line("markers", "api_key_required: run only if the api key is set in the environment variables")
data_path = Path(__file__).parent.absolute() / "data"
pytest.BASIC_EXAMPLE_PATH = data_path / "basic_example.json"
pytest.COMPLEX_EXAMPLE_PATH = data_path / "complex_example.json"
pytest.OPENAPI_EXAMPLE_PATH = data_path / "Openapi.json"
pytest.GROUPED_CHAT_EXAMPLE_PATH = data_path / "grouped_chat.json"
pytest.ONE_GROUPED_CHAT_EXAMPLE_PATH = data_path / "one_group_chat.json"
pytest.VECTOR_STORE_GROUPED_EXAMPLE_PATH = data_path / "vector_store_grouped.json"
pytest.WEBHOOK_TEST = data_path / "WebhookTest.json"
pytest.BASIC_CHAT_WITH_PROMPT_AND_HISTORY = data_path / "BasicChatwithPromptandHistory.json"
pytest.CHAT_INPUT = data_path / "ChatInputTest.json"
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.CODE_WITH_SYNTAX_ERROR = """
def get_text():
retun "Hello World"
"""
# validate that all the paths are correct and the files exist
for path in [
pytest.BASIC_EXAMPLE_PATH,
pytest.COMPLEX_EXAMPLE_PATH,
pytest.OPENAPI_EXAMPLE_PATH,
pytest.GROUPED_CHAT_EXAMPLE_PATH,
pytest.ONE_GROUPED_CHAT_EXAMPLE_PATH,
pytest.VECTOR_STORE_GROUPED_EXAMPLE_PATH,
pytest.BASIC_CHAT_WITH_PROMPT_AND_HISTORY,
pytest.CHAT_INPUT,
pytest.TWO_OUTPUTS,
pytest.VECTOR_STORE_PATH,
]:
assert path.exists(), f"File {path} does not exist. Available files: {list(data_path.iterdir())}"
@pytest.fixture()
async def async_client() -> AsyncGenerator:
from langflow.main import create_app
app = create_app()
async with AsyncClient(app=app, base_url="http://testserver") as client:
yield client
@pytest.fixture(name="session")
def session_fixture():
engine = create_engine("sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool)
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
yield session
class Config:
broker_url = "redis://localhost:6379/0"
result_backend = "redis://localhost:6379/0"
@pytest.fixture(name="load_flows_dir")
def load_flows_dir():
tempdir = tempfile.TemporaryDirectory()
yield tempdir.name
@pytest.fixture(name="distributed_env")
def setup_env(monkeypatch):
monkeypatch.setenv("LANGFLOW_CACHE_TYPE", "redis")
monkeypatch.setenv("LANGFLOW_REDIS_HOST", "result_backend")
monkeypatch.setenv("LANGFLOW_REDIS_PORT", "6379")
monkeypatch.setenv("LANGFLOW_REDIS_DB", "0")
monkeypatch.setenv("LANGFLOW_REDIS_EXPIRE", "3600")
monkeypatch.setenv("LANGFLOW_REDIS_PASSWORD", "")
monkeypatch.setenv("FLOWER_UNAUTHENTICATED_API", "True")
monkeypatch.setenv("BROKER_URL", "redis://result_backend:6379/0")
monkeypatch.setenv("RESULT_BACKEND", "redis://result_backend:6379/0")
monkeypatch.setenv("C_FORCE_ROOT", "true")
@pytest.fixture(name="distributed_client")
def distributed_client_fixture(session: Session, monkeypatch, distributed_env):
# Here we load the .env from ../deploy/.env
from langflow.core import celery_app
db_dir = tempfile.mkdtemp()
db_path = Path(db_dir) / "test.db"
monkeypatch.setenv("LANGFLOW_DATABASE_URL", f"sqlite:///{db_path}")
monkeypatch.setenv("LANGFLOW_AUTO_LOGIN", "false")
# monkeypatch langflow.services.task.manager.USE_CELERY to True
# monkeypatch.setattr(manager, "USE_CELERY", True)
monkeypatch.setattr(celery_app, "celery_app", celery_app.make_celery("langflow", Config))
# def get_session_override():
# return session
from langflow.main import create_app
app = create_app()
# app.dependency_overrides[get_session] = get_session_override
with TestClient(app) as client:
yield client
app.dependency_overrides.clear()
monkeypatch.undo()
def get_graph(_type="basic"):
"""Get a graph from a json file"""
if _type == "basic":
path = pytest.BASIC_EXAMPLE_PATH
elif _type == "complex":
path = pytest.COMPLEX_EXAMPLE_PATH
elif _type == "openapi":
path = pytest.OPENAPI_EXAMPLE_PATH
with open(path, "r") as f:
flow_graph = json.load(f)
data_graph = flow_graph["data"]
nodes = data_graph["nodes"]
edges = data_graph["edges"]
return Graph(nodes, edges)
@pytest.fixture
def basic_graph_data():
with open(pytest.BASIC_EXAMPLE_PATH, "r") as f:
return json.load(f)
@pytest.fixture
def basic_graph():
return get_graph()
@pytest.fixture
def complex_graph():
return get_graph("complex")
@pytest.fixture
def openapi_graph():
return get_graph("openapi")
@pytest.fixture
def json_flow():
with open(pytest.BASIC_EXAMPLE_PATH, "r") as f:
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:
return f.read()
@pytest.fixture
def json_simple_api_test():
with open(pytest.SIMPLE_API_TEST, "r") as f:
return f.read()
@pytest.fixture
def json_vector_store():
with open(pytest.VECTOR_STORE_PATH, "r") as f:
return f.read()
@pytest.fixture
def json_webhook_test():
with open(pytest.WEBHOOK_TEST, "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
if "noclient" in request.keywords:
yield
else:
db_dir = tempfile.mkdtemp()
db_path = Path(db_dir) / "test.db"
monkeypatch.setenv("LANGFLOW_DATABASE_URL", f"sqlite:///{db_path}")
monkeypatch.setenv("LANGFLOW_AUTO_LOGIN", "false")
if "load_flows" in request.keywords:
shutil.copyfile(
pytest.BASIC_EXAMPLE_PATH, os.path.join(load_flows_dir, "c54f9130-f2fa-4a3e-b22a-3856d946351b.json")
)
monkeypatch.setenv("LANGFLOW_LOAD_FLOWS_PATH", load_flows_dir)
monkeypatch.setenv("LANGFLOW_AUTO_LOGIN", "true")
from langflow.main import create_app
app = create_app()
# app.dependency_overrides[get_session] = get_session_override
with TestClient(app) as client:
yield client
# app.dependency_overrides.clear()
monkeypatch.undo()
# clear the temp db
with suppress(FileNotFoundError):
db_path.unlink()
# create a fixture for session_getter above
@pytest.fixture(name="session_getter")
def session_getter_fixture(client):
@contextmanager
def blank_session_getter(db_service: "DatabaseService"):
with Session(db_service.engine) as session:
yield session
yield blank_session_getter
@pytest.fixture
def runner():
return CliRunner()
@pytest.fixture
def test_user(client):
user_data = UserCreate(
username="testuser",
password="testpassword",
)
response = client.post("/api/v1/users", json=user_data.model_dump())
assert response.status_code == 201
return response.json()
@pytest.fixture(scope="function")
def active_user(client):
db_manager = get_db_service()
with session_getter(db_manager) as session:
user = User(
username="activeuser",
password=get_password_hash("testpassword"),
is_active=True,
is_superuser=False,
)
# check if user exists
if active_user := session.exec(select(User).where(User.username == user.username)).first():
return active_user
session.add(user)
session.commit()
session.refresh(user)
return user
@pytest.fixture
def logged_in_headers(client, active_user):
login_data = {"username": active_user.username, "password": "testpassword"}
response = client.post("/api/v1/login", data=login_data)
assert response.status_code == 200
tokens = response.json()
a_token = tokens["access_token"]
return {"Authorization": f"Bearer {a_token}"}
@pytest.fixture
def flow(client, json_flow: str, active_user):
from langflow.services.database.models.flow.model 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 = Flow.model_validate(flow_data)
with session_getter(get_db_service()) as session:
session.add(flow)
session.commit()
session.refresh(flow)
return flow
@pytest.fixture
def json_chat_input():
with open(pytest.CHAT_INPUT, "r") as f:
return f.read()
@pytest.fixture
def json_two_outputs():
with open(pytest.TWO_OUTPUTS, "r") as f:
return f.read()
@pytest.fixture
def added_flow_with_prompt_and_history(client, json_flow_with_prompt_and_history, logged_in_headers):
flow = orjson.loads(json_flow_with_prompt_and_history)
data = flow["data"]
flow = FlowCreate(name="Basic Chat", description="description", data=data)
response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers)
assert response.status_code == 201
assert response.json()["name"] == flow.name
assert response.json()["data"] == flow.data
return response.json()
@pytest.fixture
def added_flow_chat_input(client, json_chat_input, logged_in_headers):
flow = orjson.loads(json_chat_input)
data = flow["data"]
flow = FlowCreate(name="Chat Input", description="description", data=data)
response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers)
assert response.status_code == 201
assert response.json()["name"] == flow.name
assert response.json()["data"] == flow.data
return response.json()
@pytest.fixture
def added_flow_two_outputs(client, json_two_outputs, logged_in_headers):
flow = orjson.loads(json_two_outputs)
data = flow["data"]
flow = FlowCreate(name="Two Outputs", description="description", data=data)
response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers)
assert response.status_code == 201
assert response.json()["name"] == flow.name
assert response.json()["data"] == flow.data
return response.json()
@pytest.fixture
def added_vector_store(client, json_vector_store, logged_in_headers):
vector_store = orjson.loads(json_vector_store)
data = vector_store["data"]
vector_store = FlowCreate(name="Vector Store", description="description", data=data)
response = client.post("api/v1/flows/", json=vector_store.model_dump(), headers=logged_in_headers)
assert response.status_code == 201
assert response.json()["name"] == vector_store.name
assert response.json()["data"] == vector_store.data
return response.json()
@pytest.fixture
def added_webhook_test(client, json_webhook_test, logged_in_headers):
webhook_test = orjson.loads(json_webhook_test)
data = webhook_test["data"]
webhook_test = FlowCreate(
name="Webhook Test", description="description", data=data, endpoint_name=webhook_test["endpoint_name"]
)
response = client.post("api/v1/flows/", json=webhook_test.model_dump(), headers=logged_in_headers)
assert response.status_code == 201
assert response.json()["name"] == webhook_test.name
assert response.json()["data"] == webhook_test.data
return response.json()
@pytest.fixture
def created_api_key(active_user):
hashed = get_password_hash("random_key")
api_key = ApiKey(
name="test_api_key",
user_id=active_user.id,
api_key="random_key",
hashed_api_key=hashed,
)
db_manager = get_db_service()
with session_getter(db_manager) as session:
if existing_api_key := session.exec(select(ApiKey).where(ApiKey.api_key == api_key.api_key)).first():
return existing_api_key
session.add(api_key)
session.commit()
session.refresh(api_key)
return api_key
@pytest.fixture(name="simple_api_test")
def get_simple_api_test(client, logged_in_headers, json_simple_api_test):
# Once the client is created, we can get the starter project
# Just create a new flow with the simple api test
flow = orjson.loads(json_simple_api_test)
data = flow["data"]
flow = FlowCreate(name="Simple API Test", data=data, description="Simple API Test")
response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers)
assert response.status_code == 201
assert response.json()["name"] == flow.name
assert response.json()["data"] == flow.data
return response.json()
@pytest.fixture(name="starter_project")
def get_starter_project(active_user):
# once the client is created, we can get the starter project
with session_getter(get_db_service()) as session:
flow = session.exec(
select(Flow)
.where(Flow.folder.has(Folder.name == STARTER_FOLDER_NAME))
.where(Flow.name == "Basic Prompting (Hello, World)")
).first()
if not flow:
raise ValueError("No starter project found")
new_flow_create = FlowCreate(
name=flow.name,
description=flow.description,
data=flow.data,
user_id=active_user.id,
)
new_flow = Flow.model_validate(new_flow_create, from_attributes=True)
session.add(new_flow)
session.commit()
session.refresh(new_flow)
new_flow_dict = new_flow.model_dump()
return new_flow_dict

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,918 @@
{
"name": "ChatInputTest",
"description": "",
"data": {
"nodes": [
{
"width": 384,
"height": 359,
"id": "PromptTemplate-IKKOx",
"type": "genericNode",
"position": {
"x": 880,
"y": 646.9375
},
"data": {
"type": "PromptTemplate",
"node": {
"template": {
"output_parser": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "output_parser",
"advanced": false,
"dynamic": false,
"info": "",
"type": "BaseOutputParser",
"list": false
},
"input_variables": {
"required": true,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "input_variables",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": true,
"value": [
"input"
]
},
"partial_variables": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "partial_variables",
"advanced": false,
"dynamic": false,
"info": "",
"type": "code",
"list": false
},
"template": {
"required": true,
"placeholder": "",
"show": true,
"multiline": true,
"password": false,
"name": "template",
"advanced": false,
"dynamic": false,
"info": "",
"type": "prompt",
"list": false,
"value": "Input: {input}\nAI:"
},
"template_format": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": "f-string",
"password": false,
"name": "template_format",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": false
},
"validate_template": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": true,
"password": false,
"name": "validate_template",
"advanced": false,
"dynamic": false,
"info": "",
"type": "bool",
"list": false
},
"_type": "PromptTemplate",
"input": {
"required": false,
"placeholder": "",
"show": true,
"multiline": true,
"value": "",
"password": false,
"name": "input",
"display_name": "input",
"advanced": false,
"input_types": [
"Document",
"BaseOutputParser",
"str"
],
"dynamic": false,
"info": "",
"type": "str",
"list": false
}
},
"description": "A prompt template for a language model.",
"base_classes": [
"BasePromptTemplate",
"PromptTemplate",
"StringPromptTemplate"
],
"name": "",
"display_name": "PromptTemplate",
"documentation": "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/",
"custom_fields": {
"": [
"input"
],
"template": [
"input"
]
},
"output_types": [],
"field_formatters": {
"formatters": {
"openai_api_key": {}
},
"base_formatters": {
"kwargs": {},
"optional": {},
"list": {},
"dict": {},
"union": {},
"multiline": {},
"show": {},
"password": {},
"default": {},
"headers": {},
"dict_code_file": {},
"model_fields": {
"MODEL_DICT": {
"OpenAI": [
"text-davinci-003",
"text-davinci-002",
"text-curie-001",
"text-babbage-001",
"text-ada-001"
],
"ChatOpenAI": [
"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"
],
"Anthropic": [
"claude-v1",
"claude-v1-100k",
"claude-instant-v1",
"claude-instant-v1-100k",
"claude-v1.3",
"claude-v1.3-100k",
"claude-v1.2",
"claude-v1.0",
"claude-instant-v1.1",
"claude-instant-v1.1-100k",
"claude-instant-v1.0"
],
"ChatAnthropic": [
"claude-v1",
"claude-v1-100k",
"claude-instant-v1",
"claude-instant-v1-100k",
"claude-v1.3",
"claude-v1.3-100k",
"claude-v1.2",
"claude-v1.0",
"claude-instant-v1.1",
"claude-instant-v1.1-100k",
"claude-instant-v1.0"
]
}
}
}
},
"beta": false,
"error": null
},
"id": "PromptTemplate-IKKOx"
},
"selected": false,
"positionAbsolute": {
"x": 880,
"y": 646.9375
},
"dragging": false
},
{
"width": 384,
"height": 307,
"id": "LLMChain-e2dhN",
"type": "genericNode",
"position": {
"x": 1449.330344958542,
"y": 880.1760221487797
},
"data": {
"type": "LLMChain",
"node": {
"template": {
"callbacks": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "callbacks",
"advanced": false,
"dynamic": false,
"info": "",
"type": "langchain.callbacks.base.BaseCallbackHandler",
"list": true
},
"llm": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "llm",
"advanced": false,
"dynamic": false,
"info": "",
"type": "BaseLanguageModel",
"list": false
},
"memory": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "memory",
"advanced": false,
"dynamic": false,
"info": "",
"type": "BaseMemory",
"list": false
},
"output_parser": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "output_parser",
"advanced": false,
"dynamic": false,
"info": "",
"type": "BaseLLMOutputParser",
"list": false
},
"prompt": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "prompt",
"advanced": false,
"dynamic": false,
"info": "",
"type": "BasePromptTemplate",
"list": false
},
"llm_kwargs": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "llm_kwargs",
"advanced": false,
"dynamic": false,
"info": "",
"type": "code",
"list": false
},
"metadata": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "metadata",
"advanced": false,
"dynamic": false,
"info": "",
"type": "code",
"list": false
},
"output_key": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"value": "text",
"password": false,
"name": "output_key",
"advanced": true,
"dynamic": false,
"info": "",
"type": "str",
"list": false
},
"return_final_only": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": true,
"password": false,
"name": "return_final_only",
"advanced": false,
"dynamic": false,
"info": "",
"type": "bool",
"list": false
},
"tags": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "tags",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": true
},
"verbose": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "verbose",
"advanced": true,
"dynamic": false,
"info": "",
"type": "bool",
"list": false
},
"_type": "LLMChain"
},
"description": "Chain to run queries against LLMs.",
"base_classes": [
"Chain",
"LLMChain",
"function",
"Text"
],
"display_name": "LLMChain",
"custom_fields": {},
"output_types": [],
"documentation": "https://python.langchain.com/docs/modules/chains/foundational/llm_chain",
"beta": false,
"error": null
},
"id": "LLMChain-e2dhN"
},
"positionAbsolute": {
"x": 1449.330344958542,
"y": 880.1760221487797
}
},
{
"width": 384,
"height": 621,
"id": "ChatOpenAI-2I57f",
"type": "genericNode",
"position": {
"x": 393.3551923753797,
"y": 1061.025177453298
},
"data": {
"type": "ChatOpenAI",
"node": {
"template": {
"callbacks": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "callbacks",
"advanced": false,
"dynamic": false,
"info": "",
"type": "langchain.callbacks.base.BaseCallbackHandler",
"list": true
},
"cache": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "cache",
"advanced": false,
"dynamic": false,
"info": "",
"type": "bool",
"list": false
},
"client": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "client",
"advanced": false,
"dynamic": false,
"info": "",
"type": "Any",
"list": false
},
"max_retries": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 6,
"password": false,
"name": "max_retries",
"advanced": false,
"dynamic": false,
"info": "",
"type": "int",
"list": false
},
"max_tokens": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": true,
"name": "max_tokens",
"advanced": false,
"dynamic": false,
"info": "",
"type": "int",
"list": false,
"value": ""
},
"metadata": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "metadata",
"advanced": false,
"dynamic": false,
"info": "",
"type": "code",
"list": false
},
"model_kwargs": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "model_kwargs",
"advanced": true,
"dynamic": false,
"info": "",
"type": "code",
"list": false
},
"model_name": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "gpt-3.5-turbo-0613",
"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",
"gpt-4-32k"
],
"name": "model_name",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": true
},
"n": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 1,
"password": false,
"name": "n",
"advanced": false,
"dynamic": false,
"info": "",
"type": "int",
"list": false
},
"openai_api_base": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "openai_api_base",
"display_name": "OpenAI API Base",
"advanced": false,
"dynamic": false,
"info": "\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n",
"type": "str",
"list": false
},
"openai_api_key": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "",
"password": true,
"name": "openai_api_key",
"display_name": "OpenAI API Key",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": false
},
"openai_organization": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "openai_organization",
"display_name": "OpenAI Organization",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": false
},
"openai_proxy": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "openai_proxy",
"display_name": "OpenAI Proxy",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": false
},
"request_timeout": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "request_timeout",
"advanced": false,
"dynamic": false,
"info": "",
"type": "float",
"list": false
},
"streaming": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "streaming",
"advanced": false,
"dynamic": false,
"info": "",
"type": "bool",
"list": false
},
"tags": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "tags",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": true
},
"temperature": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": 0.7,
"password": false,
"name": "temperature",
"advanced": false,
"dynamic": false,
"info": "",
"type": "float",
"list": false
},
"tiktoken_model_name": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "tiktoken_model_name",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": false
},
"verbose": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "verbose",
"advanced": false,
"dynamic": false,
"info": "",
"type": "bool",
"list": false
},
"_type": "ChatOpenAI"
},
"description": "`OpenAI` Chat large language models API.",
"base_classes": [
"BaseChatModel",
"ChatOpenAI",
"BaseLanguageModel",
"BaseLLM"
],
"display_name": "ChatOpenAI",
"custom_fields": {},
"output_types": [],
"documentation": "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai",
"beta": false,
"error": null
},
"id": "ChatOpenAI-2I57f"
},
"selected": false,
"positionAbsolute": {
"x": 393.3551923753797,
"y": 1061.025177453298
},
"dragging": false
},
{
"width": 384,
"height": 359,
"id": "ChatInput-207IY",
"type": "genericNode",
"position": {
"x": 415.1018926651509,
"y": 506.62736462360317
},
"data": {
"type": "ChatInput",
"node": {
"template": {
"code": {
"dynamic": true,
"required": true,
"placeholder": "",
"show": false,
"multiline": true,
"value": "from typing import Optional\nfrom langflow.custom import CustomComponent\n\n\nclass ChatInput(CustomComponent):\n display_name = \"Chat Input\"\n\n def build(self, message: Optional[str] = \"\") -> str:\n return message\n",
"password": false,
"name": "code",
"advanced": false,
"type": "code",
"list": false
},
"_type": "CustomComponent",
"message": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "",
"password": false,
"name": "message",
"display_name": "message",
"advanced": false,
"dynamic": false,
"info": "",
"type": "str",
"list": false
}
},
"description": "Used to get user input from the chat.",
"base_classes": [
"str"
],
"display_name": "Chat Input",
"custom_fields": {
"message": null
},
"output_types": [
"ChatInput"
],
"documentation": "",
"beta": true,
"error": null
},
"id": "ChatInput-207IY"
},
"positionAbsolute": {
"x": 415.1018926651509,
"y": 506.62736462360317
}
},
{
"width": 384,
"height": 389,
"id": "ChatOutput-1jlJy",
"type": "genericNode",
"position": {
"x": 2002.8008888732943,
"y": 926.1397178702218
},
"data": {
"type": "ChatOutput",
"node": {
"template": {
"code": {
"dynamic": true,
"required": true,
"placeholder": "",
"show": true,
"multiline": true,
"value": "from typing import Optional, Text\nfrom langflow.api.v1.schemas import ChatMessage\nfrom langflow.services.utils import get_chat_manager\nfrom langflow.custom import CustomComponent\nfrom anyio.from_thread import start_blocking_portal\nfrom loguru import logger\n\n\nclass ChatOutput(CustomComponent):\n display_name = \"Chat Output\"\n description = \"Used to send a message to the chat.\"\n\n field_config = {\n \"code\": {\n \"show\": False,\n }\n }\n\n def build_config(self):\n return {\"message\": {\"input_types\": [\"Text\"]}}\n\n def build(self, message: Optional[Text], is_ai: bool = False) -> Text:\n if not message:\n return \"\"\n try:\n chat_manager = get_chat_manager()\n chat_message = ChatMessage(message=message, is_bot=is_ai)\n # send_message is a coroutine\n # run in a thread safe manner\n with start_blocking_portal() as portal:\n portal.call(chat_manager.send_message, chat_message)\n chat_manager.chat_history.add_message(\n chat_manager.cache_manager.current_client_id, chat_message\n )\n except Exception as exc:\n logger.exception(exc)\n logger.debug(f\"Error sending message to chat: {exc}\")\n self.repr_value = message\n return message\n",
"password": false,
"name": "code",
"advanced": false,
"type": "code",
"list": false
},
"_type": "CustomComponent",
"is_ai": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"value": true,
"password": false,
"name": "is_ai",
"display_name": "is_ai",
"advanced": false,
"dynamic": false,
"info": "",
"type": "bool",
"list": false
},
"message": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "message",
"display_name": "message",
"advanced": false,
"input_types": [
"Text"
],
"dynamic": false,
"info": "",
"type": "Text",
"list": false
}
},
"description": "Used to send a message to the chat.",
"base_classes": [
"str"
],
"display_name": "Chat Output",
"custom_fields": {
"is_ai": null,
"message": null
},
"output_types": [
"ChatOutput"
],
"documentation": "",
"beta": true,
"error": null
},
"id": "ChatOutput-1jlJy"
},
"selected": true,
"dragging": false,
"positionAbsolute": {
"x": 2002.8008888732943,
"y": 926.1397178702218
}
}
],
"edges": [
{
"source": "PromptTemplate-IKKOx",
"sourceHandle": "PromptTemplate|PromptTemplate-IKKOx|BasePromptTemplate|PromptTemplate|StringPromptTemplate",
"target": "LLMChain-e2dhN",
"targetHandle": "BasePromptTemplate|prompt|LLMChain-e2dhN",
"style": {
"stroke": "#555"
},
"className": "",
"animated": false,
"id": "reactflow__edge-PromptTemplate-IKKOxPromptTemplate|PromptTemplate-IKKOx|StringPromptTemplate|BasePromptTemplate|PromptTemplate-LLMChain-e2dhNBasePromptTemplate|prompt|LLMChain-e2dhN"
},
{
"source": "ChatOpenAI-2I57f",
"sourceHandle": "ChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM",
"target": "LLMChain-e2dhN",
"targetHandle": "BaseLanguageModel|llm|LLMChain-e2dhN",
"style": {
"stroke": "#555"
},
"className": "",
"animated": false,
"id": "reactflow__edge-ChatOpenAI-2I57fChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM-LLMChain-e2dhNBaseLanguageModel|llm|LLMChain-e2dhN"
},
{
"source": "ChatInput-207IY",
"sourceHandle": "ChatInput|ChatInput-207IY|str",
"target": "PromptTemplate-IKKOx",
"targetHandle": "Document;BaseOutputParser;str|input|PromptTemplate-IKKOx",
"style": {
"stroke": "#555"
},
"className": "",
"animated": false,
"id": "reactflow__edge-ChatInput-207IYChatInput|ChatInput-207IY|str-PromptTemplate-IKKOxDocument;BaseOutputParser;str|input|PromptTemplate-IKKOx"
},
{
"source": "LLMChain-e2dhN",
"sourceHandle": "LLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text",
"target": "ChatOutput-1jlJy",
"targetHandle": "Text|message|ChatOutput-1jlJy",
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"animated": true,
"id": "reactflow__edge-LLMChain-e2dhNLLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text-ChatOutput-1jlJyText|message|ChatOutput-1jlJy"
}
],
"viewport": {
"x": -141.98308184453367,
"y": -104.98637616656356,
"zoom": 0.4788209787464315
}
},
"id": "b3388ab9-b5dc-4447-b560-79caef40faa5",
"user_id": "c65bfea3-3eea-4e71-8fc4-106238eb0583"
}

View file

@ -0,0 +1,445 @@
{
"description": "",
"name": "openapi",
"id": "1",
"data": {
"nodes": [
{
"width": 384,
"height": 311,
"id": "dndnode_19",
"type": "genericNode",
"position": {
"x": -207.85635949789724,
"y": -105.73915116823618
},
"data": {
"type": "JsonToolkit",
"node": {
"template": {
"spec": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "spec",
"type": "JsonSpec",
"list": false
},
"_type": "JsonToolkit"
},
"description": "Toolkit for interacting with a JSON spec.",
"base_classes": [
"BaseToolkit"
]
},
"id": "dndnode_19",
"value": null
},
"selected": false,
"positionAbsolute": {
"x": -207.85635949789724,
"y": -105.73915116823618
},
"dragging": false
},
{
"width": 384,
"height": 351,
"id": "dndnode_32",
"type": "genericNode",
"position": {
"x": 745.308873444751,
"y": -37.007911201107675
},
"data": {
"type": "OpenAPIToolkit",
"node": {
"template": {
"json_agent": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "json_agent",
"type": "AgentExecutor",
"list": false
},
"requests_wrapper": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "requests_wrapper",
"type": "TextRequestsWrapper",
"list": false
},
"_type": "OpenAPIToolkit"
},
"description": "Toolkit for interacting with a OpenAPI api.",
"base_classes": [
"BaseToolkit"
]
},
"id": "dndnode_32",
"value": null
},
"selected": false,
"positionAbsolute": {
"x": 745.308873444751,
"y": -37.007911201107675
},
"dragging": false
},
{
"width": 384,
"height": 351,
"id": "dndnode_33",
"type": "genericNode",
"position": {
"x": 281.30887344475104,
"y": 2.9920887988923255
},
"data": {
"type": "JsonAgent",
"node": {
"template": {
"toolkit": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "toolkit",
"type": "BaseToolkit",
"list": false
},
"llm": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "llm",
"type": "BaseLanguageModel",
"list": false
},
"_type": "JsonAgent"
},
"description": "Construct a json agent from an LLM and tools.",
"base_classes": [
"AgentExecutor"
]
},
"id": "dndnode_33",
"value": null
},
"selected": false,
"dragging": false,
"positionAbsolute": {
"x": 281.30887344475104,
"y": 2.9920887988923255
}
},
{
"width": 384,
"height": 349,
"id": "dndnode_34",
"type": "genericNode",
"position": {
"x": 301.30887344475104,
"y": 532.9920887988924
},
"data": {
"type": "TextRequestsWrapper",
"node": {
"template": {
"headers": {
"required": false,
"placeholder": "",
"show": true,
"multiline": true,
"value": "{'Authorization':\n 'Bearer <token>'}",
"password": false,
"name": "headers",
"type": "code",
"list": false
},
"aiosession": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "aiosession",
"type": "ClientSession",
"list": false
},
"_type": "TextRequestsWrapper"
},
"description": "Lightweight wrapper around requests library.",
"base_classes": [
"TextRequestsWrapper"
]
},
"id": "dndnode_34",
"value": null
},
"positionAbsolute": {
"x": 301.30887344475104,
"y": 532.9920887988924
}
},
{
"width": 384,
"height": 407,
"id": "dndnode_35",
"type": "genericNode",
"position": {
"x": -754.691126555249,
"y": -37.00791120110762
},
"data": {
"type": "JsonSpec",
"node": {
"template": {
"path": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"value": "api-with-examples.yaml",
"suffixes": [
".json",
".yaml",
".yml"
],
"password": false,
"name": "path",
"type": "file",
"list": false,
"fileTypes": [
"json",
"yaml",
"yml"
],
"file_path": "api-with-examples.yaml"
},
"max_value_length": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "4000",
"password": false,
"name": "max_value_length",
"type": "int",
"list": false
},
"_type": "JsonSpec"
},
"description": "",
"base_classes": [
"Tool",
"JsonSpec"
]
},
"id": "dndnode_35",
"value": null
},
"selected": false,
"dragging": false,
"positionAbsolute": {
"x": -754.691126555249,
"y": -37.00791120110762
}
},
{
"width": 384,
"height": 563,
"id": "dndnode_36",
"type": "genericNode",
"position": {
"x": -310.69112655524896,
"y": 514.9920887988924
},
"data": {
"type": "ChatOpenAI",
"node": {
"template": {
"cache": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "cache",
"type": "bool",
"list": false
},
"verbose": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "verbose",
"type": "bool",
"list": false
},
"client": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "client",
"type": "Any",
"list": false
},
"model_name": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "gpt-3.5-turbo",
"password": false,
"name": "model_name",
"type": "str",
"list": false
},
"model_kwargs": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "model_kwargs",
"type": "code",
"list": false
},
"openai_api_key": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "openai_api_key",
"type": "str",
"list": false,
"value": "sk-"
},
"max_retries": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 6,
"password": false,
"name": "max_retries",
"type": "int",
"list": false
},
"prefix_messages": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "prefix_messages",
"type": "Any",
"list": true
},
"streaming": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "streaming",
"type": "bool",
"list": false
},
"_type": "ChatOpenAI"
},
"description": "Wrapper around OpenAI Chat large language models.To use, you should have the ``openai`` python package installed, and theenvironment variable ``OPENAI_API_KEY`` set with your API key.Any parameters that are valid to be passed to the openai.create call can be passedin, even if not explicitly saved on this class.",
"base_classes": [
"BaseLanguageModel",
"BaseLLM"
]
},
"id": "dndnode_36",
"value": null
},
"selected": false,
"dragging": false,
"positionAbsolute": {
"x": -310.69112655524896,
"y": 514.9920887988924
}
}
],
"edges": [
{
"source": "dndnode_19",
"sourceHandle": "JsonToolkit|dndnode_19|BaseToolkit",
"target": "dndnode_33",
"targetHandle": "BaseToolkit|toolkit|dndnode_33",
"className": "animate-pulse",
"id": "reactflow__edge-dndnode_19JsonToolkit|dndnode_19|BaseToolkit-dndnode_33BaseToolkit|toolkit|dndnode_33",
"selected": false
},
{
"source": "dndnode_33",
"sourceHandle": "JsonAgent|dndnode_33|AgentExecutor",
"target": "dndnode_32",
"targetHandle": "AgentExecutor|json_agent|dndnode_32",
"className": "animate-pulse",
"id": "reactflow__edge-dndnode_33JsonAgent|dndnode_33|AgentExecutor-dndnode_32AgentExecutor|json_agent|dndnode_32",
"selected": false
},
{
"source": "dndnode_34",
"sourceHandle": "TextRequestsWrapper|dndnode_34|TextRequestsWrapper",
"target": "dndnode_32",
"targetHandle": "TextRequestsWrapper|requests_wrapper|dndnode_32",
"className": "animate-pulse",
"id": "reactflow__edge-dndnode_34RequestsWrapper|dndnode_34|TextRequestsWrapper-dndnode_32RequestsWrapper|requests_wrapper|dndnode_32",
"selected": false
},
{
"source": "dndnode_35",
"sourceHandle": "JsonSpec|dndnode_35|Tool|JsonSpec",
"target": "dndnode_19",
"targetHandle": "JsonSpec|spec|dndnode_19",
"className": "animate-pulse",
"id": "reactflow__edge-dndnode_35JsonSpec|dndnode_35|Tool|JsonSpec-dndnode_19JsonSpec|spec|dndnode_19",
"selected": false
},
{
"source": "dndnode_36",
"sourceHandle": "ChatOpenAI|dndnode_36|BaseLanguageModel|BaseLLM",
"target": "dndnode_33",
"targetHandle": "BaseLanguageModel|llm|dndnode_33",
"className": "animate-pulse",
"id": "reactflow__edge-dndnode_36OpenAIChat|dndnode_36|BaseLanguageModel|BaseLLM-dndnode_33BaseLanguageModel|llm|dndnode_33"
}
],
"viewport": {
"x": 0,
"y": 0,
"zoom": 1
}
},
"chat": [
{
"message": "test",
"isSend": true
}
]
}

View file

@ -0,0 +1,567 @@
{
"id": "e9380216-9300-41a1-bc35-7ee92fe4b30d",
"data": {
"nodes": [
{
"id": "ChatInput-irFJf",
"type": "genericNode",
"position": {
"x": 180,
"y": 200.296875
},
"data": {
"type": "ChatInput",
"node": {
"template": {
"_type": "Component",
"files": {
"trace_as_metadata": true,
"file_path": "",
"fileTypes": [
"txt",
"md",
"mdx",
"csv",
"json",
"yaml",
"yml",
"xml",
"html",
"htm",
"pdf",
"docx",
"py",
"sh",
"sql",
"js",
"ts",
"tsx",
"jpg",
"jpeg",
"png",
"bmp",
"image"
],
"list": true,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "files",
"display_name": "Files",
"advanced": true,
"dynamic": false,
"info": "Files to be sent with the message.",
"title_case": false,
"type": "file"
},
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from langflow.base.data.utils import IMG_FILE_TYPES, TEXT_FILE_TYPES\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput\nfrom langflow.io import DropdownInput, FileInput, MessageTextInput, MultilineInput, Output\nfrom langflow.memory import store_message\nfrom langflow.schema.message import Message\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n name = \"ChatInput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n value=\"\",\n info=\"Message to be passed as input.\",\n ),\n BoolInput(\n name=\"store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"User\",\n info=\"Type of sender.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=\"User\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n FileInput(\n name=\"files\",\n display_name=\"Files\",\n file_types=TEXT_FILE_TYPES + IMG_FILE_TYPES,\n info=\"Files to be sent with the message.\",\n advanced=True,\n is_list=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n files=self.files,\n )\n\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n store_message(\n message,\n flow_id=self.graph.flow_id,\n )\n self.message.value = message\n\n self.status = message\n return message\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"input_value": {
"trace_as_input": true,
"multiline": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "input_value",
"display_name": "Text",
"advanced": false,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Message to be passed as input.",
"title_case": false,
"type": "str"
},
"sender": {
"trace_as_metadata": true,
"options": [
"Machine",
"User"
],
"required": false,
"placeholder": "",
"show": true,
"value": "User",
"name": "sender",
"display_name": "Sender Type",
"advanced": true,
"dynamic": false,
"info": "Type of sender.",
"title_case": false,
"type": "str"
},
"sender_name": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "User",
"name": "sender_name",
"display_name": "Sender Name",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Name of the sender.",
"title_case": false,
"type": "str"
},
"session_id": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "session_id",
"display_name": "Session ID",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Session ID for the message.",
"title_case": false,
"type": "str"
},
"store_message": {
"trace_as_metadata": true,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": true,
"name": "store_message",
"display_name": "Store Messages",
"advanced": true,
"dynamic": false,
"info": "Store the message in the history.",
"title_case": false,
"type": "bool"
}
},
"description": "Get chat inputs from the Playground.",
"icon": "ChatInput",
"base_classes": [
"Message"
],
"display_name": "Chat Input",
"documentation": "",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [
"Message"
],
"selected": "Message",
"name": "message",
"display_name": "Message",
"method": "message_response",
"value": "__UNDEFINED__",
"cache": true
}
],
"field_order": [
"input_value",
"store_message",
"sender",
"sender_name",
"session_id",
"files"
],
"beta": false,
"edited": false
},
"id": "ChatInput-irFJf",
"description": "Get chat inputs from the Playground.",
"display_name": "Chat Input"
},
"selected": false,
"width": 384,
"height": 309
},
{
"id": "TextInput-tcoZg",
"type": "genericNode",
"position": {
"x": 186,
"y": 549.296875
},
"data": {
"type": "TextInput",
"node": {
"template": {
"_type": "Component",
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from langflow.base.io.text import TextComponent\nfrom langflow.io import MessageTextInput, Output\nfrom langflow.schema.message import Message\n\n\nclass TextInputComponent(TextComponent):\n display_name = \"Text Input\"\n description = \"Get text inputs from the Playground.\"\n icon = \"type\"\n name = \"TextInput\"\n\n inputs = [\n MessageTextInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Text to be passed as input.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n ]\n\n def text_response(self) -> Message:\n message = Message(\n text=self.input_value,\n )\n return message\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"input_value": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "AI",
"name": "input_value",
"display_name": "Text",
"advanced": false,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Text to be passed as input.",
"title_case": false,
"type": "str"
}
},
"description": "Get text inputs from the Playground.",
"icon": "type",
"base_classes": [
"Message"
],
"display_name": "Text Input",
"documentation": "",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [
"Message"
],
"selected": "Message",
"name": "text",
"display_name": "Text",
"method": "text_response",
"value": "__UNDEFINED__",
"cache": true
}
],
"field_order": [
"input_value"
],
"beta": false,
"edited": false
},
"id": "TextInput-tcoZg"
},
"selected": true,
"width": 384,
"height": 309,
"positionAbsolute": {
"x": 186,
"y": 549.296875
},
"dragging": false
},
{
"id": "ChatOutput-dJRst",
"type": "genericNode",
"position": {
"x": 820,
"y": 224.296875
},
"data": {
"type": "ChatOutput",
"node": {
"template": {
"_type": "Component",
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput\nfrom langflow.io import DropdownInput, MessageTextInput, Output\nfrom langflow.memory import store_message\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n name = \"ChatOutput\"\n\n inputs = [\n MessageTextInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n ),\n BoolInput(\n name=\"store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True\n ),\n MessageTextInput(\n name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n store_message(\n message,\n flow_id=self.graph.flow_id,\n )\n self.message.value = message\n\n self.status = message\n return message\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"data_template": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "{text}",
"name": "data_template",
"display_name": "Data Template",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"title_case": false,
"type": "str"
},
"input_value": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "input_value",
"display_name": "Text",
"advanced": false,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Message to be passed as output.",
"title_case": false,
"type": "str"
},
"sender": {
"trace_as_metadata": true,
"options": [
"Machine",
"User"
],
"required": false,
"placeholder": "",
"show": true,
"value": "Machine",
"name": "sender",
"display_name": "Sender Type",
"advanced": true,
"dynamic": false,
"info": "Type of sender.",
"title_case": false,
"type": "str"
},
"sender_name": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "sender_name",
"display_name": "Sender Name",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Name of the sender.",
"title_case": false,
"type": "str"
},
"session_id": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "session_id",
"display_name": "Session ID",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Session ID for the message.",
"title_case": false,
"type": "str"
},
"store_message": {
"trace_as_metadata": true,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": true,
"name": "store_message",
"display_name": "Store Messages",
"advanced": true,
"dynamic": false,
"info": "Store the message in the history.",
"title_case": false,
"type": "bool"
}
},
"description": "Display a chat message in the Playground.",
"icon": "ChatOutput",
"base_classes": [
"Message"
],
"display_name": "Chat Output",
"documentation": "",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [
"Message"
],
"selected": "Message",
"name": "message",
"display_name": "Message",
"method": "message_response",
"value": "__UNDEFINED__",
"cache": true
}
],
"field_order": [
"input_value",
"store_message",
"sender",
"sender_name",
"session_id",
"data_template"
],
"beta": false,
"edited": false
},
"id": "ChatOutput-dJRst",
"description": "Display a chat message in the Playground.",
"display_name": "Chat Output"
},
"selected": false,
"width": 384,
"height": 403,
"positionAbsolute": {
"x": 820,
"y": 224.296875
},
"dragging": false
}
],
"edges": [
{
"source": "ChatInput-irFJf",
"sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-irFJfœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}",
"target": "ChatOutput-dJRst",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-dJRstœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "ChatOutput-dJRst",
"inputTypes": [
"Message"
],
"type": "str"
},
"sourceHandle": {
"dataType": "ChatInput",
"id": "ChatInput-irFJf",
"name": "message",
"output_types": [
"Message"
]
}
},
"id": "reactflow__edge-ChatInput-irFJf{œdataTypeœ:œChatInputœ,œidœ:œChatInput-irFJfœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-dJRst{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-dJRstœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"className": ""
},
{
"source": "TextInput-tcoZg",
"sourceHandle": "{œdataTypeœ:œTextInputœ,œidœ:œTextInput-tcoZgœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}",
"target": "ChatOutput-dJRst",
"targetHandle": "{œfieldNameœ:œsender_nameœ,œidœ:œChatOutput-dJRstœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "sender_name",
"id": "ChatOutput-dJRst",
"inputTypes": [
"Message"
],
"type": "str"
},
"sourceHandle": {
"dataType": "TextInput",
"id": "TextInput-tcoZg",
"name": "text",
"output_types": [
"Message"
]
}
},
"id": "reactflow__edge-TextInput-tcoZg{œdataTypeœ:œTextInputœ,œidœ:œTextInput-tcoZgœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-dJRst{œfieldNameœ:œsender_nameœ,œidœ:œChatOutput-dJRstœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"className": ""
}
],
"viewport": {
"x": -117,
"y": -69,
"zoom": 1
}
},
"description": "Nurture NLP Nodes Here.",
"name": "Simple API Test",
"last_tested_version": "1.0.9",
"endpoint_name": null,
"is_component": false
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,749 @@
{
"id": "b00c375e-c858-42b5-a352-561d3f40bd15",
"data": {
"nodes": [
{
"id": "CustomComponent-aF0h1",
"type": "genericNode",
"position": {
"x": 888.0012384532345,
"y": 272.41352212880344
},
"data": {
"type": "CustomComponent",
"node": {
"template": {
"_type": "Component",
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "# from langflow.field_typing import Data\nfrom langflow.custom import Component\nfrom langflow.io import StrInput\nfrom langflow.schema import Data\nfrom langflow.io import Output\nfrom pathlib import Path\nimport aiofiles\n\nclass CustomComponent(Component):\n display_name = \"Async Component\"\n description = \"Use as a template to create your own component.\"\n documentation: str = \"http://docs.langflow.org/components/custom\"\n icon = \"custom_components\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input Value\", value=\"Hello, World!\", input_types=[\"Data\"]),\n ]\n\n outputs = [\n Output(display_name=\"Output\", name=\"output\", method=\"build_output\"),\n ]\n\n async def build_output(self) -> Data:\n if isinstance(self.input_value, Data):\n data = self.input_value\n else:\n data = Data(value=self.input_value)\n \n if \"path\" in data:\n path = self.resolve_path(data.path)\n path_obj = Path(path)\n async with aiofiles.open(path, \"w\") as f:\n await f.write(data.model_dump())\n \n self.status = data\n return data",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"input_value": {
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "Hello, World!",
"name": "input_value",
"display_name": "Input Value",
"advanced": false,
"input_types": [
"Data"
],
"dynamic": false,
"info": "",
"title_case": false,
"type": "str"
}
},
"description": "Use as a template to create your own component.",
"icon": "custom_components",
"base_classes": [
"Data"
],
"display_name": "Custom Component",
"documentation": "http://docs.langflow.org/components/custom",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [
"Data"
],
"selected": "Data",
"name": "output",
"display_name": "Output",
"method": "build_output",
"value": "__UNDEFINED__",
"cache": true,
"hidden": false
}
],
"field_order": [
"input_value"
],
"beta": false,
"edited": false
},
"id": "CustomComponent-aF0h1",
"description": "Use as a template to create your own component.",
"display_name": "Custom Component"
},
"selected": false,
"width": 384,
"height": 337,
"positionAbsolute": {
"x": 888.0012384532345,
"y": 272.41352212880344
},
"dragging": false
},
{
"id": "Webhook-BeRcd",
"type": "genericNode",
"position": {
"x": 418,
"y": 270.2890625
},
"data": {
"type": "Webhook",
"node": {
"template": {
"_type": "Component",
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "import json\n\nfrom langflow.custom import Component\nfrom langflow.io import MultilineInput, Output\nfrom langflow.schema import Data\n\n\nclass WebhookComponent(Component):\n display_name = \"Webhook Input\"\n description = \"Defines a webhook input for the flow.\"\n name = \"Webhook\"\n\n inputs = [\n MultilineInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"Use this field to quickly test the webhook component by providing a JSON payload.\",\n )\n ]\n outputs = [\n Output(display_name=\"Data\", name=\"output_data\", method=\"build_data\"),\n ]\n\n def build_data(self) -> Data:\n message: str | Data = \"\"\n if not self.data:\n self.status = \"No data provided.\"\n return Data(data={})\n try:\n body = json.loads(self.data or \"{}\")\n except json.JSONDecodeError:\n body = {\"payload\": self.data}\n message = f\"Invalid JSON payload. Please check the format.\\n\\n{self.data}\"\n data = Data(data=body)\n if not message:\n message = data\n self.status = message\n return data\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"data": {
"trace_as_input": true,
"multiline": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "{\"test\":1}",
"name": "data",
"display_name": "Data",
"advanced": false,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Use this field to quickly test the webhook component by providing a JSON payload.",
"title_case": false,
"type": "str"
}
},
"description": "Defines a webhook input for the flow.",
"base_classes": [
"Data"
],
"display_name": "Webhook Input",
"documentation": "",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [
"Data"
],
"selected": "Data",
"name": "output_data",
"display_name": "Data",
"method": "build_data",
"value": "__UNDEFINED__",
"cache": true,
"hidden": false
}
],
"field_order": [
"data"
],
"beta": false,
"edited": false
},
"id": "Webhook-BeRcd",
"description": "Defines a webhook input for the flow.",
"display_name": "Webhook Input"
},
"selected": false,
"width": 384,
"height": 309,
"dragging": true,
"positionAbsolute": {
"x": 418,
"y": 270.2890625
}
},
{
"id": "ChatInput-QivBB",
"type": "genericNode",
"position": {
"x": 419.7235078147726,
"y": 646.9863203129902
},
"data": {
"type": "ChatInput",
"node": {
"template": {
"_type": "Component",
"files": {
"trace_as_metadata": true,
"file_path": "",
"fileTypes": [
"txt",
"md",
"mdx",
"csv",
"json",
"yaml",
"yml",
"xml",
"html",
"htm",
"pdf",
"docx",
"py",
"sh",
"sql",
"js",
"ts",
"tsx",
"jpg",
"jpeg",
"png",
"bmp",
"image"
],
"list": true,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "files",
"display_name": "Files",
"advanced": true,
"dynamic": false,
"info": "Files to be sent with the message.",
"title_case": false,
"type": "file"
},
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from langflow.base.data.utils import IMG_FILE_TYPES, TEXT_FILE_TYPES\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.io import DropdownInput, FileInput, MessageTextInput, MultilineInput, Output\nfrom langflow.schema.message import Message\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n name = \"ChatInput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n value=\"\",\n info=\"Message to be passed as input.\",\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"User\",\n info=\"Type of sender.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=\"User\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n FileInput(\n name=\"files\",\n display_name=\"Files\",\n file_types=TEXT_FILE_TYPES + IMG_FILE_TYPES,\n info=\"Files to be sent with the message.\",\n advanced=True,\n is_list=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n files=self.files,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"input_value": {
"trace_as_input": true,
"multiline": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "Should not run",
"name": "input_value",
"display_name": "Text",
"advanced": false,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Message to be passed as input.",
"title_case": false,
"type": "str"
},
"sender": {
"trace_as_metadata": true,
"options": [
"Machine",
"User"
],
"required": false,
"placeholder": "",
"show": true,
"value": "User",
"name": "sender",
"display_name": "Sender Type",
"advanced": true,
"dynamic": false,
"info": "Type of sender.",
"title_case": false,
"type": "str"
},
"sender_name": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "User",
"name": "sender_name",
"display_name": "Sender Name",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Name of the sender.",
"title_case": false,
"type": "str"
},
"session_id": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "session_id",
"display_name": "Session ID",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Session ID for the message.",
"title_case": false,
"type": "str"
}
},
"description": "Get chat inputs from the Playground.",
"icon": "ChatInput",
"base_classes": [
"Message"
],
"display_name": "Chat Input",
"documentation": "",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [
"Message"
],
"selected": "Message",
"name": "message",
"display_name": "Message",
"method": "message_response",
"value": "__UNDEFINED__",
"cache": true,
"hidden": false
}
],
"field_order": [
"input_value",
"sender",
"sender_name",
"session_id",
"files"
],
"beta": false,
"edited": false
},
"id": "ChatInput-QivBB"
},
"selected": false,
"width": 384,
"height": 309,
"positionAbsolute": {
"x": 419.7235078147726,
"y": 646.9863203129902
},
"dragging": false
},
{
"id": "ChatOutput-mN2VY",
"type": "genericNode",
"position": {
"x": 884.7327265656637,
"y": 662.4287265670896
},
"data": {
"type": "ChatOutput",
"node": {
"template": {
"_type": "Component",
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.io import DropdownInput, MessageTextInput, Output\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n name = \"ChatOutput\"\n\n inputs = [\n MessageTextInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True\n ),\n MessageTextInput(\n name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"data_template": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "{text}",
"name": "data_template",
"display_name": "Data Template",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"title_case": false,
"type": "str"
},
"input_value": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "input_value",
"display_name": "Text",
"advanced": false,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Message to be passed as output.",
"title_case": false,
"type": "str"
},
"sender": {
"trace_as_metadata": true,
"options": [
"Machine",
"User"
],
"required": false,
"placeholder": "",
"show": true,
"value": "Machine",
"name": "sender",
"display_name": "Sender Type",
"advanced": true,
"dynamic": false,
"info": "Type of sender.",
"title_case": false,
"type": "str"
},
"sender_name": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "AI",
"name": "sender_name",
"display_name": "Sender Name",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Name of the sender.",
"title_case": false,
"type": "str"
},
"session_id": {
"trace_as_input": true,
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "",
"name": "session_id",
"display_name": "Session ID",
"advanced": true,
"input_types": [
"Message"
],
"dynamic": false,
"info": "Session ID for the message.",
"title_case": false,
"type": "str"
}
},
"description": "Display a chat message in the Playground.",
"icon": "ChatOutput",
"base_classes": [
"Message"
],
"display_name": "Chat Output",
"documentation": "",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [
"Message"
],
"selected": "Message",
"name": "message",
"display_name": "Message",
"method": "message_response",
"value": "__UNDEFINED__",
"cache": true
}
],
"field_order": [
"input_value",
"sender",
"sender_name",
"session_id",
"data_template"
],
"beta": false,
"edited": false
},
"id": "ChatOutput-mN2VY"
},
"selected": false,
"width": 384,
"height": 309,
"positionAbsolute": {
"x": 884.7327265656637,
"y": 662.4287265670896
},
"dragging": false
},
{
"id": "CustomComponent-Ntw7h",
"type": "genericNode",
"position": {
"x": 1396.7134608749789,
"y": 284.91367968123217
},
"data": {
"type": "CustomComponent",
"node": {
"template": {
"_type": "Component",
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "# from langflow.field_typing import Data\nfrom langflow.custom import Component\nfrom langflow.io import StrInput\nfrom langflow.schema import Data\nfrom langflow.io import Output\nfrom pathlib import Path\nimport httpx\nclass CustomComponent(Component):\n display_name = \"Async Component\"\n description = \"Use as a template to create your own component.\"\n documentation: str = \"http://docs.langflow.org/components/custom\"\n icon = \"custom_components\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input Value\", value=\"Hello, World!\", input_types=[\"Data\"]),\n ]\n\n outputs = [\n Output(display_name=\"Output\", name=\"output\", method=\"build_output\"),\n ]\n\n async def build_output(self) -> Data:\n async with httpx.AsyncClient() as client:\n response = await client.get(\"https://www.google.com\")\n response.raise_for_status()\n return Data(response=response.text)",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"input_value": {
"trace_as_metadata": true,
"load_from_db": false,
"list": false,
"required": false,
"placeholder": "",
"show": true,
"value": "Hello, World!",
"name": "input_value",
"display_name": "Input Value",
"advanced": false,
"input_types": [
"Data"
],
"dynamic": false,
"info": "",
"title_case": false,
"type": "str"
}
},
"description": "Use as a template to create your own component.",
"icon": "custom_components",
"base_classes": [],
"display_name": "Custom Component",
"documentation": "http://docs.langflow.org/components/custom",
"custom_fields": {},
"output_types": [],
"pinned": false,
"conditional_paths": [],
"frozen": false,
"outputs": [
{
"types": [],
"name": "output",
"display_name": "Output",
"method": "build_output",
"value": "__UNDEFINED__",
"cache": true
}
],
"field_order": [
"input_value"
],
"beta": false,
"edited": true
},
"id": "CustomComponent-Ntw7h",
"description": "Use as a template to create your own component.",
"display_name": "Custom Component"
},
"selected": true,
"width": 384,
"height": 337,
"positionAbsolute": {
"x": 1396.7134608749789,
"y": 284.91367968123217
},
"dragging": false
}
],
"edges": [
{
"source": "Webhook-BeRcd",
"sourceHandle": "{œdataTypeœ:œWebhookœ,œidœ:œWebhook-BeRcdœ,œnameœ:œoutput_dataœ,œoutput_typesœ:[œDataœ]}",
"target": "CustomComponent-aF0h1",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œCustomComponent-aF0h1œ,œinputTypesœ:[œDataœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "CustomComponent-aF0h1",
"inputTypes": [
"Data"
],
"type": "str"
},
"sourceHandle": {
"dataType": "Webhook",
"id": "Webhook-BeRcd",
"name": "output_data",
"output_types": [
"Data"
]
}
},
"id": "reactflow__edge-Webhook-BeRcd{œdataTypeœ:œWebhookœ,œidœ:œWebhook-BeRcdœ,œnameœ:œoutput_dataœ,œoutput_typesœ:[œDataœ]}-CustomComponent-aF0h1{œfieldNameœ:œinput_valueœ,œidœ:œCustomComponent-aF0h1œ,œinputTypesœ:[œDataœ],œtypeœ:œstrœ}",
"className": ""
},
{
"source": "ChatInput-QivBB",
"sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-QivBBœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}",
"target": "ChatOutput-mN2VY",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-mN2VYœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "ChatOutput-mN2VY",
"inputTypes": [
"Message"
],
"type": "str"
},
"sourceHandle": {
"dataType": "ChatInput",
"id": "ChatInput-QivBB",
"name": "message",
"output_types": [
"Message"
]
}
},
"id": "reactflow__edge-ChatInput-QivBB{œdataTypeœ:œChatInputœ,œidœ:œChatInput-QivBBœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-mN2VY{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-mN2VYœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"className": ""
},
{
"source": "CustomComponent-aF0h1",
"sourceHandle": "{œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-aF0h1œ,œnameœ:œoutputœ,œoutput_typesœ:[œDataœ]}",
"target": "CustomComponent-Ntw7h",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œCustomComponent-Ntw7hœ,œinputTypesœ:[œDataœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "CustomComponent-Ntw7h",
"inputTypes": [
"Data"
],
"type": "str"
},
"sourceHandle": {
"dataType": "CustomComponent",
"id": "CustomComponent-aF0h1",
"name": "output",
"output_types": [
"Data"
]
}
},
"id": "reactflow__edge-CustomComponent-aF0h1{œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-aF0h1œ,œnameœ:œoutputœ,œoutput_typesœ:[œDataœ]}-CustomComponent-Ntw7h{œfieldNameœ:œinput_valueœ,œidœ:œCustomComponent-Ntw7hœ,œinputTypesœ:[œDataœ],œtypeœ:œstrœ}"
}
],
"viewport": {
"x": -7.6743264594028915,
"y": 186.6544574916296,
"zoom": 0.520510798842055
}
},
"description": "The Power of Language at Your Fingertips.",
"name": "Webhook Test",
"last_tested_version": "1.0.7",
"endpoint_name": "webhook-test",
"is_component": false
}

View file

@ -0,0 +1,510 @@
{
"description": "",
"name": "BasicExample",
"id": "a53f9130-f2fa-4a3e-b22a-3856d946351a",
"data": {
"nodes": [
{
"width": 384,
"height": 267,
"id": "dndnode_81",
"type": "genericNode",
"position": {
"x": 1030,
"y": 694
},
"data": {
"type": "TimeTravelGuideChain",
"node": {
"template": {
"llm": {
"required": true,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "llm",
"advanced": false,
"type": "BaseLanguageModel",
"list": false
},
"memory": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "memory",
"advanced": false,
"type": "BaseChatMemory",
"list": false
},
"_type": "TimeTravelGuideChain"
},
"description": "Time travel guide chain to be used in the flow.",
"base_classes": [
"LLMChain",
"BaseCustomChain",
"TimeTravelGuideChain",
"Chain",
"ConversationChain"
]
},
"id": "dndnode_81",
"value": null
},
"selected": false,
"positionAbsolute": {
"x": 1030,
"y": 694
},
"dragging": false
},
{
"width": 384,
"height": 597,
"id": "dndnode_82",
"type": "genericNode",
"position": {
"x": 520,
"y": 732
},
"data": {
"type": "OpenAI",
"node": {
"template": {
"cache": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "cache",
"advanced": false,
"type": "bool",
"list": false
},
"verbose": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "verbose",
"advanced": false,
"type": "bool",
"list": false
},
"callbacks": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "callbacks",
"advanced": false,
"type": "langchain.callbacks.base.BaseCallbackHandler",
"list": true
},
"client": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "client",
"advanced": false,
"type": "Any",
"list": false
},
"model_name": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "text-davinci-003",
"password": false,
"options": [
"text-davinci-003",
"text-davinci-002",
"text-curie-001",
"text-babbage-001",
"text-ada-001"
],
"name": "model_name",
"advanced": false,
"type": "str",
"list": true
},
"temperature": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": 0.7,
"password": false,
"name": "temperature",
"advanced": false,
"type": "float",
"list": false
},
"max_tokens": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": 256,
"password": true,
"name": "max_tokens",
"advanced": false,
"type": "int",
"list": false
},
"top_p": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 1,
"password": false,
"name": "top_p",
"advanced": false,
"type": "float",
"list": false
},
"frequency_penalty": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 0,
"password": false,
"name": "frequency_penalty",
"advanced": false,
"type": "float",
"list": false
},
"presence_penalty": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 0,
"password": false,
"name": "presence_penalty",
"advanced": false,
"type": "float",
"list": false
},
"n": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 1,
"password": false,
"name": "n",
"advanced": false,
"type": "int",
"list": false
},
"best_of": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 1,
"password": false,
"name": "best_of",
"advanced": false,
"type": "int",
"list": false
},
"model_kwargs": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": false,
"name": "model_kwargs",
"advanced": true,
"type": "code",
"list": false
},
"openai_api_key": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": null,
"password": true,
"name": "openai_api_key",
"display_name": "OpenAI API Key",
"advanced": false,
"type": "str",
"list": false
},
"openai_api_base": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"password": true,
"name": "openai_api_base",
"advanced": false,
"type": "str",
"list": false
},
"openai_organization": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "openai_organization",
"advanced": false,
"type": "str",
"list": false
},
"batch_size": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 20,
"password": false,
"name": "batch_size",
"advanced": false,
"type": "int",
"list": false
},
"request_timeout": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "request_timeout",
"advanced": false,
"type": "float",
"list": false
},
"logit_bias": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "logit_bias",
"advanced": false,
"type": "code",
"list": false
},
"max_retries": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": 6,
"password": false,
"name": "max_retries",
"advanced": false,
"type": "int",
"list": false
},
"streaming": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": false,
"password": false,
"name": "streaming",
"advanced": false,
"type": "bool",
"list": false
},
"allowed_special": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": [],
"password": false,
"name": "allowed_special",
"advanced": false,
"type": "Literal'all'",
"list": true
},
"disallowed_special": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": "all",
"password": false,
"name": "disallowed_special",
"advanced": false,
"type": "Literal'all'",
"list": false
},
"_type": "OpenAI"
},
"description": "Wrapper around OpenAI large language models.",
"base_classes": [
"BaseLLM",
"OpenAI",
"BaseOpenAI",
"BaseLanguageModel"
]
},
"id": "dndnode_82",
"value": null
},
"selected": false,
"positionAbsolute": {
"x": 520,
"y": 732
},
"dragging": false
},
{
"width": 384,
"height": 273,
"id": "dndnode_83",
"type": "genericNode",
"position": {
"x": 512,
"y": 402
},
"data": {
"type": "ConversationBufferMemory",
"node": {
"template": {
"chat_memory": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "chat_memory",
"advanced": false,
"type": "BaseChatMessageHistory",
"list": false
},
"output_key": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "output_key",
"advanced": false,
"type": "str",
"list": false
},
"input_key": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "input_key",
"advanced": false,
"type": "str",
"list": false
},
"return_messages": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"password": false,
"name": "return_messages",
"advanced": false,
"type": "bool",
"list": false
},
"human_prefix": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": "Human",
"password": false,
"name": "human_prefix",
"advanced": false,
"type": "str",
"list": false
},
"ai_prefix": {
"required": false,
"placeholder": "",
"show": false,
"multiline": false,
"value": "AI",
"password": false,
"name": "ai_prefix",
"advanced": false,
"type": "str",
"list": false
},
"memory_key": {
"required": false,
"placeholder": "",
"show": true,
"multiline": false,
"value": "history",
"password": false,
"name": "memory_key",
"advanced": false,
"type": "str",
"list": false
},
"_type": "ConversationBufferMemory"
},
"description": "Buffer for storing conversation memory.",
"base_classes": [
"ConversationBufferMemory",
"BaseChatMemory",
"BaseMemory"
]
},
"id": "dndnode_83",
"value": null
},
"selected": false,
"positionAbsolute": {
"x": 512,
"y": 402
},
"dragging": false
}
],
"edges": [
{
"source": "dndnode_82",
"sourceHandle": "OpenAI|dndnode_82|BaseLLM|OpenAI|BaseOpenAI|BaseLanguageModel",
"target": "dndnode_81",
"targetHandle": "BaseLanguageModel|llm|dndnode_81",
"className": "animate-pulse",
"id": "reactflow__edge-dndnode_82OpenAI|dndnode_82|BaseLLM|OpenAI|BaseOpenAI|BaseLanguageModel-dndnode_81BaseLanguageModel|llm|dndnode_81",
"selected": false
},
{
"source": "dndnode_83",
"sourceHandle": "ConversationBufferMemory|dndnode_83|ConversationBufferMemory|BaseChatMemory|BaseMemory",
"target": "dndnode_81",
"targetHandle": "BaseChatMemory|memory|dndnode_81",
"className": "animate-pulse",
"id": "reactflow__edge-dndnode_83ConversationBufferMemory|dndnode_83|ConversationBufferMemory|BaseChatMemory|BaseMemory-dndnode_81BaseChatMemory|memory|dndnode_81"
}
],
"viewport": {
"x": 1,
"y": 0,
"zoom": 0.5
}
},
"last_tested_version": "0.6.2"
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,16 @@
import random
from langflow.custom import CustomComponent
class TestComponent(CustomComponent):
def refresh_values(self):
# This is a function that will be called every time the component is updated
# and should return a list of random strings
return [f"Random {random.randint(1, 100)}" for _ in range(5)]
def build_config(self):
return {"param": {"display_name": "Param", "options": self.refresh_values}}
def build(self, param: int):
return param

View file

@ -0,0 +1,20 @@
from langflow.custom import Component
from langflow.inputs.inputs import IntInput, MessageTextInput
from langflow.template.field.base import Output
class MultipleOutputsComponent(Component):
inputs = [
MessageTextInput(display_name="Input", name="input"),
IntInput(display_name="Number", name="number"),
]
outputs = [
Output(display_name="Certain Output", name="certain_output", method="certain_output"),
Output(display_name="Other Output", name="other_output", method="other_output"),
]
def certain_output(self) -> str:
return f"This is my string input: {self.input}"
def other_output(self) -> int:
return f"This is my int input multiplied by 2: {self.number * 2}"

View file

@ -0,0 +1,22 @@
from random import randint
from langflow.custom import Component
from langflow.inputs.inputs import IntInput, MessageTextInput
from langflow.template.field.base import Output
class MultipleOutputsComponent(Component):
inputs = [
MessageTextInput(display_name="Input", name="input"),
IntInput(display_name="Number", name="number"),
]
outputs = [
Output(display_name="Certain Output", name="certain_output", method="certain_output"),
Output(display_name="Other Output", name="other_output", method="other_output"),
]
def certain_output(self) -> int:
return randint(0, self.number)
def other_output(self) -> int:
return self.certain_output()

View file

@ -0,0 +1,17 @@
import random
from langflow.custom import CustomComponent
from langflow.field_typing import Input
class TestComponent(CustomComponent):
def refresh_values(self):
# This is a function that will be called every time the component is updated
# and should return a list of random strings
return [f"Random {random.randint(1, 100)}" for _ in range(5)]
def build_config(self):
return {"param": Input(display_name="Param", options=self.refresh_values)}
def build(self, param: int):
return param

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

Some files were not shown because too many files have changed in this diff Show more