merging branch release into dev
This commit is contained in:
parent
683c69340b
commit
168a1b9e0f
75 changed files with 2956 additions and 848 deletions
827
poetry.lock
generated
827
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "langflow"
|
name = "langflow"
|
||||||
version = "0.2.2"
|
version = "0.2.7"
|
||||||
description = "A Python package with a built-in web application"
|
description = "A Python package with a built-in web application"
|
||||||
authors = ["Logspace <contact@logspace.ai>"]
|
authors = ["Logspace <contact@logspace.ai>"]
|
||||||
maintainers = [
|
maintainers = [
|
||||||
|
|
@ -25,22 +25,21 @@ langflow = "langflow.__main__:main"
|
||||||
python = ">=3.9,<3.12"
|
python = ">=3.9,<3.12"
|
||||||
fastapi = "^0.98.0"
|
fastapi = "^0.98.0"
|
||||||
uvicorn = "^0.22.0"
|
uvicorn = "^0.22.0"
|
||||||
beautifulsoup4 = "^4.11.2"
|
beautifulsoup4 = "^4.12.2"
|
||||||
google-search-results = "^2.4.1"
|
google-search-results = "^2.4.1"
|
||||||
google-api-python-client = "^2.79.0"
|
google-api-python-client = "^2.79.0"
|
||||||
typer = "^0.9.0"
|
typer = "^0.9.0"
|
||||||
gunicorn = "^20.1.0"
|
gunicorn = "^20.1.0"
|
||||||
langchain = "^0.0.215"
|
langchain = "^0.0.219"
|
||||||
openai = "^0.27.8"
|
openai = "^0.27.8"
|
||||||
types-pyyaml = "^6.0.12.8"
|
pandas = "^2.0.0"
|
||||||
pandas = "^1.5.3"
|
|
||||||
chromadb = "^0.3.21"
|
chromadb = "^0.3.21"
|
||||||
huggingface-hub = "^0.13.3"
|
huggingface-hub = "^0.15.0"
|
||||||
rich = "^13.4.2"
|
rich = "^13.4.2"
|
||||||
llama-cpp-python = "~0.1.0"
|
llama-cpp-python = "~0.1.0"
|
||||||
networkx = "^3.1"
|
networkx = "^3.1"
|
||||||
unstructured = "^0.5.11"
|
unstructured = "^0.7.0"
|
||||||
pypdf = "^3.7.1"
|
pypdf = "^3.11.0"
|
||||||
lxml = "^4.9.2"
|
lxml = "^4.9.2"
|
||||||
pysrt = "^1.1.2"
|
pysrt = "^1.1.2"
|
||||||
fake-useragent = "^1.1.3"
|
fake-useragent = "^1.1.3"
|
||||||
|
|
@ -49,18 +48,18 @@ psycopg2-binary = "^2.9.6"
|
||||||
pyarrow = "^12.0.0"
|
pyarrow = "^12.0.0"
|
||||||
tiktoken = "~0.4.0"
|
tiktoken = "~0.4.0"
|
||||||
wikipedia = "^1.4.0"
|
wikipedia = "^1.4.0"
|
||||||
langchain-serve = { version = ">0.0.39", optional = true }
|
langchain-serve = { version = ">0.0.47", optional = true }
|
||||||
qdrant-client = "^1.2.0"
|
qdrant-client = "^1.3.0"
|
||||||
websockets = "^10.3"
|
websockets = "^10.3"
|
||||||
weaviate-client = "^3.21.0"
|
weaviate-client = "^3.21.0"
|
||||||
jina = "3.15.2"
|
jina = "3.15.2"
|
||||||
sentence-transformers = "^2.2.2"
|
sentence-transformers = "^2.2.2"
|
||||||
ctransformers = "^0.2.2"
|
ctransformers = "^0.2.10"
|
||||||
cohere = "^4.6.0"
|
cohere = "^4.11.0"
|
||||||
python-multipart = "^0.0.6"
|
python-multipart = "^0.0.6"
|
||||||
sqlmodel = "^0.0.8"
|
sqlmodel = "^0.0.8"
|
||||||
faiss-cpu = "^1.7.4"
|
faiss-cpu = "^1.7.4"
|
||||||
anthropic = "^0.2.10"
|
anthropic = "^0.3.0"
|
||||||
orjson = "^3.9.1"
|
orjson = "^3.9.1"
|
||||||
multiprocess = "^0.70.14"
|
multiprocess = "^0.70.14"
|
||||||
cachetools = "^5.3.1"
|
cachetools = "^5.3.1"
|
||||||
|
|
@ -70,7 +69,8 @@ pinecone-client = "^2.2.2"
|
||||||
supabase = "^1.0.3"
|
supabase = "^1.0.3"
|
||||||
pymongo = "^4.4.0"
|
pymongo = "^4.4.0"
|
||||||
certifi = "^2023.5.7"
|
certifi = "^2023.5.7"
|
||||||
|
psycopg = "^3.1.9"
|
||||||
|
psycopg-binary = "^3.1.9"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
black = "^23.1.0"
|
black = "^23.1.0"
|
||||||
|
|
@ -85,6 +85,7 @@ pytest-cov = "^4.0.0"
|
||||||
pandas-stubs = "^2.0.0.230412"
|
pandas-stubs = "^2.0.0.230412"
|
||||||
types-pillow = "^9.5.0.2"
|
types-pillow = "^9.5.0.2"
|
||||||
types-appdirs = "^1.4.3.5"
|
types-appdirs = "^1.4.3.5"
|
||||||
|
types-pyyaml = "^6.0.12.8"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.extras]
|
[tool.poetry.extras]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from fastapi import FastAPI
|
|
||||||
import httpx
|
import httpx
|
||||||
from multiprocess import Process, cpu_count # type: ignore
|
from multiprocess import Process, cpu_count # type: ignore
|
||||||
import platform
|
import platform
|
||||||
|
|
@ -11,9 +10,7 @@ from rich.panel import Panel
|
||||||
from rich import box
|
from rich import box
|
||||||
from rich import print as rprint
|
from rich import print as rprint
|
||||||
import typer
|
import typer
|
||||||
from fastapi.staticfiles import StaticFiles
|
from langflow.main import setup_app
|
||||||
from fastapi.responses import FileResponse
|
|
||||||
from langflow.main import create_app
|
|
||||||
from langflow.settings import settings
|
from langflow.settings import settings
|
||||||
from langflow.utils.logger import configure, logger
|
from langflow.utils.logger import configure, logger
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
@ -144,15 +141,9 @@ def serve(
|
||||||
remove_api_keys=remove_api_keys,
|
remove_api_keys=remove_api_keys,
|
||||||
cache=cache,
|
cache=cache,
|
||||||
)
|
)
|
||||||
# get the directory of the current file
|
# create path object if path is provided
|
||||||
if not path:
|
static_files_dir: Optional[Path] = Path(path) if path else None
|
||||||
frontend_path = Path(__file__).parent
|
app = setup_app(static_files_dir=static_files_dir)
|
||||||
static_files_dir = frontend_path / "frontend"
|
|
||||||
else:
|
|
||||||
static_files_dir = Path(path)
|
|
||||||
|
|
||||||
app = create_app()
|
|
||||||
setup_static_files(app, static_files_dir)
|
|
||||||
# check if port is being used
|
# check if port is being used
|
||||||
if is_port_in_use(port, host):
|
if is_port_in_use(port, host):
|
||||||
port = get_free_port(port)
|
port = get_free_port(port)
|
||||||
|
|
@ -200,29 +191,6 @@ def run_on_windows(host, port, log_level, options, app):
|
||||||
run_langflow(host, port, log_level, options, app)
|
run_langflow(host, port, log_level, options, app)
|
||||||
|
|
||||||
|
|
||||||
def setup_static_files(app: FastAPI, static_files_dir: Path):
|
|
||||||
"""
|
|
||||||
Setup the static files directory.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
app (FastAPI): FastAPI app.
|
|
||||||
path (str): Path to the static files directory.
|
|
||||||
"""
|
|
||||||
app.mount(
|
|
||||||
"/",
|
|
||||||
StaticFiles(directory=static_files_dir, html=True),
|
|
||||||
name="static",
|
|
||||||
)
|
|
||||||
|
|
||||||
@app.exception_handler(404)
|
|
||||||
async def custom_404_handler(request, __):
|
|
||||||
path = static_files_dir / "index.html"
|
|
||||||
|
|
||||||
if not path.exists():
|
|
||||||
raise RuntimeError(f"File at path {path} does not exist.")
|
|
||||||
return FileResponse(path)
|
|
||||||
|
|
||||||
|
|
||||||
def is_port_in_use(port, host="localhost"):
|
def is_port_in_use(port, host="localhost"):
|
||||||
"""
|
"""
|
||||||
Check if a port is in use.
|
Check if a port is in use.
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,6 @@
|
||||||
from fastapi import (
|
from fastapi import APIRouter, HTTPException, WebSocket, WebSocketException, status
|
||||||
APIRouter,
|
|
||||||
HTTPException,
|
|
||||||
WebSocket,
|
|
||||||
WebSocketException,
|
|
||||||
status,
|
|
||||||
)
|
|
||||||
from fastapi.responses import StreamingResponse
|
from fastapi.responses import StreamingResponse
|
||||||
from langflow.api.v1.schemas import BuiltResponse, InitResponse, StreamData
|
from langflow.api.v1.schemas import BuildStatus, BuiltResponse, InitResponse, StreamData
|
||||||
|
|
||||||
from langflow.chat.manager import ChatManager
|
from langflow.chat.manager import ChatManager
|
||||||
from langflow.graph.graph.base import Graph
|
from langflow.graph.graph.base import Graph
|
||||||
|
|
@ -32,15 +26,29 @@ async def chat(client_id: str, websocket: WebSocket):
|
||||||
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=str(exc))
|
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=str(exc))
|
||||||
|
|
||||||
|
|
||||||
@router.post("/build/init", response_model=InitResponse, status_code=201)
|
@router.post("/build/init/{flow_id}", response_model=InitResponse, status_code=201)
|
||||||
async def init_build(graph_data: dict):
|
async def init_build(graph_data: dict, flow_id: str):
|
||||||
"""Initialize the build by storing graph data and returning a unique session ID."""
|
"""Initialize the build by storing graph data and returning a unique session ID."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
flow_id = graph_data.get("id")
|
|
||||||
if flow_id is None:
|
if flow_id is None:
|
||||||
raise ValueError("No ID provided")
|
raise ValueError("No ID provided")
|
||||||
flow_data_store[flow_id] = graph_data
|
# Check if already building
|
||||||
|
if (
|
||||||
|
flow_id in flow_data_store
|
||||||
|
and flow_data_store[flow_id]["status"] == BuildStatus.IN_PROGRESS
|
||||||
|
):
|
||||||
|
return InitResponse(flowId=flow_id)
|
||||||
|
|
||||||
|
# Delete from cache if already exists
|
||||||
|
if flow_id in chat_manager.in_memory_cache:
|
||||||
|
with chat_manager.in_memory_cache._lock:
|
||||||
|
chat_manager.in_memory_cache.delete(flow_id)
|
||||||
|
logger.debug(f"Deleted flow {flow_id} from cache")
|
||||||
|
flow_data_store[flow_id] = {
|
||||||
|
"graph_data": graph_data,
|
||||||
|
"status": BuildStatus.STARTED,
|
||||||
|
}
|
||||||
|
|
||||||
return InitResponse(flowId=flow_id)
|
return InitResponse(flowId=flow_id)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|
@ -52,8 +60,9 @@ async def init_build(graph_data: dict):
|
||||||
async def build_status(flow_id: str):
|
async def build_status(flow_id: str):
|
||||||
"""Check the flow_id is in the flow_data_store."""
|
"""Check the flow_id is in the flow_data_store."""
|
||||||
try:
|
try:
|
||||||
built = flow_id in flow_data_store and not isinstance(
|
built = (
|
||||||
flow_data_store[flow_id], dict
|
flow_id in flow_data_store
|
||||||
|
and flow_data_store[flow_id]["status"] == BuildStatus.SUCCESS
|
||||||
)
|
)
|
||||||
|
|
||||||
return BuiltResponse(
|
return BuiltResponse(
|
||||||
|
|
@ -77,7 +86,12 @@ async def stream_build(flow_id: str):
|
||||||
yield str(StreamData(event="error", data={"error": error_message}))
|
yield str(StreamData(event="error", data={"error": error_message}))
|
||||||
return
|
return
|
||||||
|
|
||||||
graph_data = flow_data_store[flow_id].get("data")
|
if flow_data_store[flow_id].get("status") == BuildStatus.IN_PROGRESS:
|
||||||
|
error_message = "Already building"
|
||||||
|
yield str(StreamData(event="error", data={"error": error_message}))
|
||||||
|
return
|
||||||
|
|
||||||
|
graph_data = flow_data_store[flow_id].get("graph_data")
|
||||||
|
|
||||||
if not graph_data:
|
if not graph_data:
|
||||||
error_message = "No data provided"
|
error_message = "No data provided"
|
||||||
|
|
@ -95,6 +109,7 @@ async def stream_build(flow_id: str):
|
||||||
return
|
return
|
||||||
|
|
||||||
number_of_nodes = len(graph.nodes)
|
number_of_nodes = len(graph.nodes)
|
||||||
|
flow_data_store[flow_id]["status"] = BuildStatus.IN_PROGRESS
|
||||||
for i, vertex in enumerate(graph.generator_build(), 1):
|
for i, vertex in enumerate(graph.generator_build(), 1):
|
||||||
try:
|
try:
|
||||||
log_dict = {
|
log_dict = {
|
||||||
|
|
@ -110,6 +125,7 @@ async def stream_build(flow_id: str):
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
params = str(exc)
|
params = str(exc)
|
||||||
valid = False
|
valid = False
|
||||||
|
flow_data_store[flow_id]["status"] = BuildStatus.FAILURE
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
"valid": valid,
|
"valid": valid,
|
||||||
|
|
@ -121,8 +137,10 @@ async def stream_build(flow_id: str):
|
||||||
yield str(StreamData(event="message", data=response))
|
yield str(StreamData(event="message", data=response))
|
||||||
|
|
||||||
chat_manager.set_cache(flow_id, graph.build())
|
chat_manager.set_cache(flow_id, graph.build())
|
||||||
|
flow_data_store[flow_id]["status"] = BuildStatus.SUCCESS
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error("Error while building the flow: %s", exc)
|
logger.error("Error while building the flow: %s", exc)
|
||||||
|
flow_data_store[flow_id]["status"] = BuildStatus.FAILURE
|
||||||
yield str(StreamData(event="error", data={"error": str(exc)}))
|
yield str(StreamData(event="error", data={"error": str(exc)}))
|
||||||
finally:
|
finally:
|
||||||
yield str(StreamData(event="message", data=final_response))
|
yield str(StreamData(event="message", data=final_response))
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ from langflow.api.v1.schemas import (
|
||||||
UploadFileResponse,
|
UploadFileResponse,
|
||||||
)
|
)
|
||||||
|
|
||||||
from langflow.interface.types import build_langchain_types_dict
|
from langflow.interface.types import langchain_types_dict
|
||||||
from langflow.database.base import get_session
|
from langflow.database.base import get_session
|
||||||
from sqlmodel import Session
|
from sqlmodel import Session
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ router = APIRouter(tags=["Base"])
|
||||||
|
|
||||||
@router.get("/all")
|
@router.get("/all")
|
||||||
def get_all():
|
def get_all():
|
||||||
return build_langchain_types_dict()
|
return langchain_types_dict
|
||||||
|
|
||||||
|
|
||||||
# For backwards compatibility we will keep the old endpoint
|
# For backwards compatibility we will keep the old endpoint
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
from langflow.database.models.flow import FlowCreate, FlowRead
|
from langflow.database.models.flow import FlowCreate, FlowRead
|
||||||
|
|
@ -5,6 +6,15 @@ from pydantic import BaseModel, Field, validator
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class BuildStatus(Enum):
|
||||||
|
"""Status of the build."""
|
||||||
|
|
||||||
|
SUCCESS = "success"
|
||||||
|
FAILURE = "failure"
|
||||||
|
STARTED = "started"
|
||||||
|
IN_PROGRESS = "in_progress"
|
||||||
|
|
||||||
|
|
||||||
class GraphData(BaseModel):
|
class GraphData(BaseModel):
|
||||||
"""Data inside the exported flow."""
|
"""Data inside the exported flow."""
|
||||||
|
|
||||||
|
|
|
||||||
2
src/backend/langflow/chat/config.py
Normal file
2
src/backend/langflow/chat/config.py
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
class ChatConfig:
|
||||||
|
streaming: bool = True
|
||||||
|
|
@ -1,141 +1,264 @@
|
||||||
---
|
|
||||||
agents:
|
agents:
|
||||||
- ZeroShotAgent
|
ZeroShotAgent:
|
||||||
- JsonAgent
|
documentation: "https://python.langchain.com/docs/modules/agents/how_to/custom_mrkl_agent"
|
||||||
- CSVAgent
|
JsonAgent:
|
||||||
- AgentInitializer
|
documentation: "https://python.langchain.com/docs/modules/agents/toolkits/openapi"
|
||||||
- VectorStoreAgent
|
CSVAgent:
|
||||||
- VectorStoreRouterAgent
|
documentation: "https://python.langchain.com/docs/modules/agents/toolkits/csv"
|
||||||
- SQLAgent
|
AgentInitializer:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/agents/agent_types/"
|
||||||
|
VectorStoreAgent:
|
||||||
|
documentation: ""
|
||||||
|
VectorStoreRouterAgent:
|
||||||
|
documentation: ""
|
||||||
|
SQLAgent:
|
||||||
|
documentation: ""
|
||||||
chains:
|
chains:
|
||||||
- LLMChain
|
LLMChain:
|
||||||
- LLMMathChain
|
documentation: "https://python.langchain.com/docs/modules/chains/foundational/llm_chain"
|
||||||
- LLMCheckerChain
|
LLMMathChain:
|
||||||
- ConversationChain
|
documentation: "https://python.langchain.com/docs/modules/chains/additional/llm_math"
|
||||||
- SeriesCharacterChain
|
LLMCheckerChain:
|
||||||
- MidJourneyPromptChain
|
documentation: "https://python.langchain.com/docs/modules/chains/additional/llm_checker"
|
||||||
- TimeTravelGuideChain
|
ConversationChain:
|
||||||
- SQLDatabaseChain
|
documentation: ""
|
||||||
- RetrievalQA
|
SeriesCharacterChain:
|
||||||
- RetrievalQAWithSourcesChain
|
documentation: ""
|
||||||
- ConversationalRetrievalChain
|
MidJourneyPromptChain:
|
||||||
- CombineDocsChain
|
documentation: ""
|
||||||
|
TimeTravelGuideChain:
|
||||||
|
documentation: ""
|
||||||
|
SQLDatabaseChain:
|
||||||
|
documentation: ""
|
||||||
|
RetrievalQA:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/chains/popular/vector_db_qa"
|
||||||
|
RetrievalQAWithSourcesChain:
|
||||||
|
documentation: ""
|
||||||
|
ConversationalRetrievalChain:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/chains/popular/chat_vector_db"
|
||||||
|
CombineDocsChain:
|
||||||
|
documentation: ""
|
||||||
documentloaders:
|
documentloaders:
|
||||||
- AirbyteJSONLoader
|
AirbyteJSONLoader:
|
||||||
- CoNLLULoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json"
|
||||||
- CSVLoader
|
CoNLLULoader:
|
||||||
- UnstructuredEmailLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/conll-u"
|
||||||
- EverNoteLoader
|
CSVLoader:
|
||||||
- FacebookChatLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv"
|
||||||
- GutenbergLoader
|
UnstructuredEmailLoader:
|
||||||
- BSHTMLLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/email"
|
||||||
- UnstructuredHTMLLoader
|
EverNoteLoader:
|
||||||
# - UnstructuredImageLoader # Issue with Python 3.11 (https://github.com/Unstructured-IO/unstructured-inference/issues/83)
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/evernote"
|
||||||
- UnstructuredMarkdownLoader
|
FacebookChatLoader:
|
||||||
- PyPDFLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/facebook_chat"
|
||||||
- UnstructuredPowerPointLoader
|
GutenbergLoader:
|
||||||
- SRTLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gutenberg"
|
||||||
- TelegramChatLoader
|
BSHTMLLoader:
|
||||||
- TextLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html"
|
||||||
- UnstructuredWordDocumentLoader
|
UnstructuredHTMLLoader:
|
||||||
- WebBaseLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html"
|
||||||
- AZLyricsLoader
|
UnstructuredMarkdownLoader:
|
||||||
- CollegeConfidentialLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/markdown"
|
||||||
- HNLoader
|
PyPDFLoader:
|
||||||
- IFixitLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/pdf"
|
||||||
- IMSDbLoader
|
UnstructuredPowerPointLoader:
|
||||||
- GitbookLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_powerpoint"
|
||||||
- ReadTheDocsLoader
|
SRTLoader:
|
||||||
- SlackDirectoryLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/subtitle"
|
||||||
- NotionDirectoryLoader
|
TelegramChatLoader:
|
||||||
- DirectoryLoader
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/telegram"
|
||||||
- GitLoader
|
TextLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/"
|
||||||
|
UnstructuredWordDocumentLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_word"
|
||||||
|
WebBaseLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/web_base"
|
||||||
|
AZLyricsLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/azlyrics"
|
||||||
|
CollegeConfidentialLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/college_confidential"
|
||||||
|
HNLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/hacker_news"
|
||||||
|
IFixitLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/ifixit"
|
||||||
|
IMSDbLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/imsdb"
|
||||||
|
GitbookLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gitbook"
|
||||||
|
ReadTheDocsLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/readthedocs_documentation"
|
||||||
|
SlackDirectoryLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/slack"
|
||||||
|
NotionDirectoryLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/notion"
|
||||||
|
DirectoryLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/file_directory"
|
||||||
|
GitLoader:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/git"
|
||||||
embeddings:
|
embeddings:
|
||||||
- OpenAIEmbeddings
|
OpenAIEmbeddings:
|
||||||
- HuggingFaceEmbeddings
|
documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai"
|
||||||
- CohereEmbeddings
|
HuggingFaceEmbeddings:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/sentence_transformers"
|
||||||
|
CohereEmbeddings:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/cohere"
|
||||||
llms:
|
llms:
|
||||||
- OpenAI
|
OpenAI:
|
||||||
# - AzureOpenAI
|
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai"
|
||||||
# - AzureChatOpenAI
|
ChatOpenAI:
|
||||||
- ChatOpenAI
|
documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai"
|
||||||
- LlamaCpp
|
LlamaCpp:
|
||||||
- CTransformers
|
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp"
|
||||||
- Cohere
|
CTransformers:
|
||||||
- Anthropic
|
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers"
|
||||||
- ChatAnthropic
|
Cohere:
|
||||||
- HuggingFaceHub
|
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere"
|
||||||
|
Anthropic:
|
||||||
|
documentation: ""
|
||||||
|
ChatAnthropic:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic"
|
||||||
|
HuggingFaceHub:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/huggingface_hub"
|
||||||
memories:
|
memories:
|
||||||
- ConversationBufferMemory
|
# https://github.com/supabase-community/supabase-py/issues/482
|
||||||
- ConversationSummaryMemory
|
# ZepChatMessageHistory:
|
||||||
- ConversationKGMemory
|
# documentation: "https://python.langchain.com/docs/modules/memory/integrations/zep_memory"
|
||||||
|
ConversationEntityMemory:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/memory/integrations/entity_memory_with_sqlite"
|
||||||
|
# https://github.com/hwchase17/langchain/issues/6091
|
||||||
|
# SQLiteEntityStore:
|
||||||
|
# documentation: "https://python.langchain.com/docs/modules/memory/integrations/entity_memory_with_sqlite"
|
||||||
|
PostgresChatMessageHistory:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/memory/integrations/postgres_chat_message_history"
|
||||||
|
ConversationBufferMemory:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/memory/how_to/buffer"
|
||||||
|
ConversationSummaryMemory:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/memory/how_to/summary"
|
||||||
|
ConversationKGMemory:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/memory/how_to/kg"
|
||||||
|
ConversationBufferWindowMemory:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/memory/how_to/buffer_window"
|
||||||
|
VectorStoreRetrieverMemory:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/memory/how_to/vectorstore_retriever_memory"
|
||||||
|
|
||||||
prompts:
|
prompts:
|
||||||
- PromptTemplate
|
PromptTemplate:
|
||||||
- FewShotPromptTemplate
|
documentation: "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/"
|
||||||
- ZeroShotPrompt
|
ZeroShotPrompt:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/agents/how_to/custom_mrkl_agent"
|
||||||
textsplitters:
|
textsplitters:
|
||||||
- CharacterTextSplitter
|
CharacterTextSplitter:
|
||||||
- RecursiveCharacterTextSplitter
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter"
|
||||||
# - LatexTextSplitter
|
RecursiveCharacterTextSplitter:
|
||||||
# - PythonCodeTextSplitter
|
documentation: "https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/recursive_text_splitter"
|
||||||
toolkits:
|
toolkits:
|
||||||
- OpenAPIToolkit
|
OpenAPIToolkit:
|
||||||
- JsonToolkit
|
documentation: ""
|
||||||
- VectorStoreInfo
|
JsonToolkit:
|
||||||
- VectorStoreRouterToolkit
|
documentation: ""
|
||||||
- VectorStoreToolkit
|
VectorStoreInfo:
|
||||||
|
documentation: ""
|
||||||
|
VectorStoreRouterToolkit:
|
||||||
|
documentation: ""
|
||||||
|
VectorStoreToolkit:
|
||||||
|
documentation: ""
|
||||||
tools:
|
tools:
|
||||||
- Search
|
Search:
|
||||||
- PAL-MATH
|
documentation: ""
|
||||||
- Calculator
|
PAL-MATH:
|
||||||
- Serper Search
|
documentation: ""
|
||||||
- Tool
|
Calculator:
|
||||||
- PythonFunctionTool
|
documentation: ""
|
||||||
- PythonFunction
|
Serper Search:
|
||||||
- JsonSpec
|
documentation: ""
|
||||||
- News API
|
Tool:
|
||||||
- TMDB API
|
documentation: ""
|
||||||
- Podcast API
|
PythonFunctionTool:
|
||||||
- QuerySQLDataBaseTool
|
documentation: ""
|
||||||
- InfoSQLDatabaseTool
|
PythonFunction:
|
||||||
- ListSQLDatabaseTool
|
documentation: ""
|
||||||
# - QueryCheckerTool
|
JsonSpec:
|
||||||
- BingSearchRun
|
documentation: ""
|
||||||
- GoogleSearchRun
|
News API:
|
||||||
- GoogleSearchResults
|
documentation: ""
|
||||||
- GoogleSerperRun
|
TMDB API:
|
||||||
- JsonListKeysTool
|
documentation: ""
|
||||||
- JsonGetValueTool
|
Podcast API:
|
||||||
- PythonREPLTool
|
documentation: ""
|
||||||
- PythonAstREPLTool
|
QuerySQLDataBaseTool:
|
||||||
- RequestsGetTool
|
documentation: ""
|
||||||
- RequestsPostTool
|
InfoSQLDatabaseTool:
|
||||||
- RequestsPatchTool
|
documentation: ""
|
||||||
- RequestsPutTool
|
ListSQLDatabaseTool:
|
||||||
- RequestsDeleteTool
|
documentation: ""
|
||||||
- WikipediaQueryRun
|
BingSearchRun:
|
||||||
- WolframAlphaQueryRun
|
documentation: ""
|
||||||
|
GoogleSearchRun:
|
||||||
|
documentation: ""
|
||||||
|
GoogleSearchResults:
|
||||||
|
documentation: ""
|
||||||
|
GoogleSerperRun:
|
||||||
|
documentation: ""
|
||||||
|
JsonListKeysTool:
|
||||||
|
documentation: ""
|
||||||
|
JsonGetValueTool:
|
||||||
|
documentation: ""
|
||||||
|
PythonREPLTool:
|
||||||
|
documentation: ""
|
||||||
|
PythonAstREPLTool:
|
||||||
|
documentation: ""
|
||||||
|
RequestsGetTool:
|
||||||
|
documentation: ""
|
||||||
|
RequestsPostTool:
|
||||||
|
documentation: ""
|
||||||
|
RequestsPatchTool:
|
||||||
|
documentation: ""
|
||||||
|
RequestsPutTool:
|
||||||
|
documentation: ""
|
||||||
|
RequestsDeleteTool:
|
||||||
|
documentation: ""
|
||||||
|
WikipediaQueryRun:
|
||||||
|
documentation: ""
|
||||||
|
WolframAlphaQueryRun:
|
||||||
|
documentation: ""
|
||||||
utilities:
|
utilities:
|
||||||
- BingSearchAPIWrapper
|
BingSearchAPIWrapper:
|
||||||
- GoogleSearchAPIWrapper
|
documentation: ""
|
||||||
- GoogleSerperAPIWrapper
|
GoogleSearchAPIWrapper:
|
||||||
- SearxResults
|
documentation: ""
|
||||||
- SearxSearchWrapper
|
GoogleSerperAPIWrapper:
|
||||||
- SerpAPIWrapper
|
documentation: ""
|
||||||
- WikipediaAPIWrapper
|
SearxResults:
|
||||||
- WolframAlphaAPIWrapper
|
documentation: ""
|
||||||
# - ZapierNLAWrapper
|
SearxSearchWrapper:
|
||||||
- SQLDatabase
|
documentation: ""
|
||||||
|
SerpAPIWrapper:
|
||||||
|
documentation: ""
|
||||||
|
WikipediaAPIWrapper:
|
||||||
|
documentation: ""
|
||||||
|
WolframAlphaAPIWrapper:
|
||||||
|
documentation: ""
|
||||||
|
retrievers:
|
||||||
|
MultiQueryRetriever:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/retrievers/how_to/MultiQueryRetriever"
|
||||||
|
# https://github.com/supabase-community/supabase-py/issues/482
|
||||||
|
# ZepRetriever:
|
||||||
|
# documentation: "https://python.langchain.com/docs/modules/data_connection/retrievers/integrations/zep_memorystore"
|
||||||
vectorstores:
|
vectorstores:
|
||||||
- Chroma
|
Chroma:
|
||||||
- Qdrant
|
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma"
|
||||||
- Weaviate
|
Qdrant:
|
||||||
- FAISS
|
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/qdrant"
|
||||||
- Pinecone
|
Weaviate:
|
||||||
- SupabaseVectorStore
|
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/weaviate"
|
||||||
- MongoDBAtlasVectorSearch
|
FAISS:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss"
|
||||||
|
Pinecone:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/pinecone"
|
||||||
|
SupabaseVectorStore:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/supabase"
|
||||||
|
MongoDBAtlasVectorSearch:
|
||||||
|
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/mongodb_atlas_vector_search"
|
||||||
wrappers:
|
wrappers:
|
||||||
- RequestsWrapper
|
RequestsWrapper:
|
||||||
# - ChatPromptTemplate
|
documentation: ""
|
||||||
# - SystemMessagePromptTemplate
|
|
||||||
# - HumanMessagePromptTemplate
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ CUSTOM_NODES = {
|
||||||
"utilities": {
|
"utilities": {
|
||||||
"SQLDatabase": frontend_node.agents.SQLDatabaseNode(),
|
"SQLDatabase": frontend_node.agents.SQLDatabaseNode(),
|
||||||
},
|
},
|
||||||
|
"memories": {
|
||||||
|
"PostgresChatMessageHistory": frontend_node.memories.PostgresChatMessageHistoryFrontendNode(),
|
||||||
|
},
|
||||||
"chains": {
|
"chains": {
|
||||||
"SeriesCharacterChain": frontend_node.chains.SeriesCharacterChainNode(),
|
"SeriesCharacterChain": frontend_node.chains.SeriesCharacterChainNode(),
|
||||||
"TimeTravelGuideChain": frontend_node.chains.TimeTravelGuideChainNode(),
|
"TimeTravelGuideChain": frontend_node.chains.TimeTravelGuideChainNode(),
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from langflow.graph.vertex.types import (
|
||||||
ToolkitVertex,
|
ToolkitVertex,
|
||||||
VectorStoreVertex,
|
VectorStoreVertex,
|
||||||
WrapperVertex,
|
WrapperVertex,
|
||||||
|
RetrieverVertex,
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|
@ -32,4 +33,5 @@ __all__ = [
|
||||||
"ToolkitVertex",
|
"ToolkitVertex",
|
||||||
"VectorStoreVertex",
|
"VectorStoreVertex",
|
||||||
"WrapperVertex",
|
"WrapperVertex",
|
||||||
|
"RetrieverVertex",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,5 @@
|
||||||
from langflow.graph.vertex.base import Vertex
|
from langflow.graph.vertex.base import Vertex
|
||||||
from langflow.graph.vertex.types import (
|
from langflow.graph.vertex import types
|
||||||
AgentVertex,
|
|
||||||
ChainVertex,
|
|
||||||
DocumentLoaderVertex,
|
|
||||||
EmbeddingVertex,
|
|
||||||
LLMVertex,
|
|
||||||
MemoryVertex,
|
|
||||||
PromptVertex,
|
|
||||||
TextSplitterVertex,
|
|
||||||
ToolVertex,
|
|
||||||
ToolkitVertex,
|
|
||||||
VectorStoreVertex,
|
|
||||||
WrapperVertex,
|
|
||||||
)
|
|
||||||
from langflow.interface.agents.base import agent_creator
|
from langflow.interface.agents.base import agent_creator
|
||||||
from langflow.interface.chains.base import chain_creator
|
from langflow.interface.chains.base import chain_creator
|
||||||
from langflow.interface.document_loaders.base import documentloader_creator
|
from langflow.interface.document_loaders.base import documentloader_creator
|
||||||
|
|
@ -25,22 +12,23 @@ from langflow.interface.toolkits.base import toolkits_creator
|
||||||
from langflow.interface.tools.base import tool_creator
|
from langflow.interface.tools.base import tool_creator
|
||||||
from langflow.interface.vector_store.base import vectorstore_creator
|
from langflow.interface.vector_store.base import vectorstore_creator
|
||||||
from langflow.interface.wrappers.base import wrapper_creator
|
from langflow.interface.wrappers.base import wrapper_creator
|
||||||
|
from langflow.interface.retrievers.base import retriever_creator
|
||||||
|
|
||||||
from typing import Dict, Type
|
from typing import Dict, Type
|
||||||
|
|
||||||
|
|
||||||
VERTEX_TYPE_MAP: Dict[str, Type[Vertex]] = {
|
VERTEX_TYPE_MAP: Dict[str, Type[Vertex]] = {
|
||||||
**{t: PromptVertex for t in prompt_creator.to_list()},
|
**{t: types.PromptVertex for t in prompt_creator.to_list()},
|
||||||
**{t: AgentVertex for t in agent_creator.to_list()},
|
**{t: types.AgentVertex for t in agent_creator.to_list()},
|
||||||
**{t: ChainVertex for t in chain_creator.to_list()},
|
**{t: types.ChainVertex for t in chain_creator.to_list()},
|
||||||
**{t: ToolVertex for t in tool_creator.to_list()},
|
**{t: types.ToolVertex for t in tool_creator.to_list()},
|
||||||
**{t: ToolkitVertex for t in toolkits_creator.to_list()},
|
**{t: types.ToolkitVertex for t in toolkits_creator.to_list()},
|
||||||
**{t: WrapperVertex for t in wrapper_creator.to_list()},
|
**{t: types.WrapperVertex for t in wrapper_creator.to_list()},
|
||||||
**{t: LLMVertex for t in llm_creator.to_list()},
|
**{t: types.LLMVertex for t in llm_creator.to_list()},
|
||||||
**{t: MemoryVertex for t in memory_creator.to_list()},
|
**{t: types.MemoryVertex for t in memory_creator.to_list()},
|
||||||
**{t: EmbeddingVertex for t in embedding_creator.to_list()},
|
**{t: types.EmbeddingVertex for t in embedding_creator.to_list()},
|
||||||
**{t: VectorStoreVertex for t in vectorstore_creator.to_list()},
|
**{t: types.VectorStoreVertex for t in vectorstore_creator.to_list()},
|
||||||
**{t: DocumentLoaderVertex for t in documentloader_creator.to_list()},
|
**{t: types.DocumentLoaderVertex for t in documentloader_creator.to_list()},
|
||||||
**{t: TextSplitterVertex for t in textsplitter_creator.to_list()},
|
**{t: types.TextSplitterVertex for t in textsplitter_creator.to_list()},
|
||||||
|
**{t: types.RetrieverVertex for t in retriever_creator.to_list()},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,11 @@ class MemoryVertex(Vertex):
|
||||||
super().__init__(data, base_type="memory")
|
super().__init__(data, base_type="memory")
|
||||||
|
|
||||||
|
|
||||||
|
class RetrieverVertex(Vertex):
|
||||||
|
def __init__(self, data: Dict):
|
||||||
|
super().__init__(data, base_type="retrievers")
|
||||||
|
|
||||||
|
|
||||||
class TextSplitterVertex(Vertex):
|
class TextSplitterVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="textsplitters")
|
super().__init__(data, base_type="textsplitters")
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.base import FrontendNode
|
from langflow.template.frontend_node.base import FrontendNode
|
||||||
from langflow.template.template.base import Template
|
from langflow.template.template.base import Template
|
||||||
from langflow.utils.logger import logger
|
from langflow.utils.logger import logger
|
||||||
|
from langflow.settings import settings
|
||||||
|
|
||||||
# Assuming necessary imports for Field, Template, and FrontendNode classes
|
# Assuming necessary imports for Field, Template, and FrontendNode classes
|
||||||
|
|
||||||
|
|
@ -15,12 +16,29 @@ from langflow.utils.logger import logger
|
||||||
class LangChainTypeCreator(BaseModel, ABC):
|
class LangChainTypeCreator(BaseModel, ABC):
|
||||||
type_name: str
|
type_name: str
|
||||||
type_dict: Optional[Dict] = None
|
type_dict: Optional[Dict] = None
|
||||||
|
name_docs_dict: Optional[Dict[str, str]] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def frontend_node_class(self) -> Type[FrontendNode]:
|
def frontend_node_class(self) -> Type[FrontendNode]:
|
||||||
"""The class type of the FrontendNode created in frontend_node."""
|
"""The class type of the FrontendNode created in frontend_node."""
|
||||||
return FrontendNode
|
return FrontendNode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def docs_map(self) -> Dict[str, str]:
|
||||||
|
"""A dict with the name of the component as key and the documentation link as value."""
|
||||||
|
if self.name_docs_dict is None:
|
||||||
|
try:
|
||||||
|
type_settings = getattr(settings, self.type_name)
|
||||||
|
self.name_docs_dict = {
|
||||||
|
name: value_dict["documentation"]
|
||||||
|
for name, value_dict in type_settings.items()
|
||||||
|
}
|
||||||
|
except AttributeError as exc:
|
||||||
|
logger.error(exc)
|
||||||
|
|
||||||
|
self.name_docs_dict = {}
|
||||||
|
return self.name_docs_dict
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def type_to_loader_dict(self) -> Dict:
|
def type_to_loader_dict(self) -> Dict:
|
||||||
|
|
@ -83,7 +101,7 @@ class LangChainTypeCreator(BaseModel, ABC):
|
||||||
|
|
||||||
signature.add_extra_fields()
|
signature.add_extra_fields()
|
||||||
signature.add_extra_base_classes()
|
signature.add_extra_base_classes()
|
||||||
|
signature.set_documentation(self.docs_map.get(name, ""))
|
||||||
return signature
|
return signature
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ def import_by_type(_type: str, name: str) -> Any:
|
||||||
"documentloaders": import_documentloader,
|
"documentloaders": import_documentloader,
|
||||||
"textsplitters": import_textsplitter,
|
"textsplitters": import_textsplitter,
|
||||||
"utilities": import_utility,
|
"utilities": import_utility,
|
||||||
|
"retrievers": import_retriever,
|
||||||
}
|
}
|
||||||
if _type == "llms":
|
if _type == "llms":
|
||||||
key = "chat" if "chat" in name.lower() else "llm"
|
key = "chat" if "chat" in name.lower() else "llm"
|
||||||
|
|
@ -59,6 +60,11 @@ def import_chat_llm(llm: str) -> BaseChatModel:
|
||||||
return import_class(f"langchain.chat_models.{llm}")
|
return import_class(f"langchain.chat_models.{llm}")
|
||||||
|
|
||||||
|
|
||||||
|
def import_retriever(retriever: str) -> Any:
|
||||||
|
"""Import retriever from retriever name"""
|
||||||
|
return import_module(f"from langchain.retrievers import {retriever}")
|
||||||
|
|
||||||
|
|
||||||
def import_memory(memory: str) -> Any:
|
def import_memory(memory: str) -> Any:
|
||||||
"""Import memory from memory name"""
|
"""Import memory from memory name"""
|
||||||
return import_module(f"from langchain.memory import {memory}")
|
return import_module(f"from langchain.memory import {memory}")
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import json
|
import json
|
||||||
from typing import Any, Callable, Dict, Sequence
|
from typing import Any, Callable, Dict, Sequence, Type
|
||||||
|
|
||||||
from langchain.agents import ZeroShotAgent
|
from langchain.agents import ZeroShotAgent
|
||||||
from langchain.agents import agent as agent_module
|
from langchain.agents import agent as agent_module
|
||||||
from langchain.agents.agent import AgentExecutor
|
from langchain.agents.agent import AgentExecutor
|
||||||
from langchain.agents.agent_toolkits.base import BaseToolkit
|
from langchain.agents.agent_toolkits.base import BaseToolkit
|
||||||
from langchain.agents.tools import BaseTool
|
from langchain.agents.tools import BaseTool
|
||||||
|
|
||||||
from langflow.interface.initialize.vector_store import vecstore_initializer
|
from langflow.interface.initialize.vector_store import vecstore_initializer
|
||||||
|
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
|
|
@ -14,8 +15,13 @@ from langflow.interface.custom_lists import CUSTOM_NODES
|
||||||
from langflow.interface.importing.utils import get_function, import_by_type
|
from langflow.interface.importing.utils import get_function, import_by_type
|
||||||
from langflow.interface.toolkits.base import toolkits_creator
|
from langflow.interface.toolkits.base import toolkits_creator
|
||||||
from langflow.interface.chains.base import chain_creator
|
from langflow.interface.chains.base import chain_creator
|
||||||
|
from langflow.interface.retrievers.base import retriever_creator
|
||||||
from langflow.interface.utils import load_file_into_dict
|
from langflow.interface.utils import load_file_into_dict
|
||||||
from langflow.utils import validate
|
from langflow.utils import validate
|
||||||
|
from langchain.chains.base import Chain
|
||||||
|
from langchain.vectorstores.base import VectorStore
|
||||||
|
from langchain.document_loaders.base import BaseLoader
|
||||||
|
from langchain.prompts.base import BasePromptTemplate
|
||||||
|
|
||||||
|
|
||||||
def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any:
|
def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any:
|
||||||
|
|
@ -43,8 +49,8 @@ def convert_params_to_sets(params):
|
||||||
|
|
||||||
def convert_kwargs(params):
|
def convert_kwargs(params):
|
||||||
# if *kwargs are passed as a string, convert to dict
|
# if *kwargs are passed as a string, convert to dict
|
||||||
# first find any key that has kwargs in it
|
# first find any key that has kwargs or config in it
|
||||||
kwargs_keys = [key for key in params.keys() if "kwargs" in key]
|
kwargs_keys = [key for key in params.keys() if "kwargs" in key or "config" in key]
|
||||||
for key in kwargs_keys:
|
for key in kwargs_keys:
|
||||||
if isinstance(params[key], str):
|
if isinstance(params[key], str):
|
||||||
params[key] = json.loads(params[key])
|
params[key] = json.loads(params[key])
|
||||||
|
|
@ -72,11 +78,50 @@ def instantiate_based_on_type(class_object, base_type, node_type, params):
|
||||||
return instantiate_utility(node_type, class_object, params)
|
return instantiate_utility(node_type, class_object, params)
|
||||||
elif base_type == "chains":
|
elif base_type == "chains":
|
||||||
return instantiate_chains(node_type, class_object, params)
|
return instantiate_chains(node_type, class_object, params)
|
||||||
|
elif base_type == "llms":
|
||||||
|
return instantiate_llm(node_type, class_object, params)
|
||||||
|
elif base_type == "retrievers":
|
||||||
|
return instantiate_retriever(node_type, class_object, params)
|
||||||
|
elif base_type == "memory":
|
||||||
|
return instantiate_memory(node_type, class_object, params)
|
||||||
else:
|
else:
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
||||||
|
|
||||||
def instantiate_chains(node_type, class_object, params):
|
def instantiate_memory(node_type, class_object, params):
|
||||||
|
try:
|
||||||
|
return class_object(**params)
|
||||||
|
# I want to catch a specific attribute error that happens
|
||||||
|
# when the object does not have a cursor attribute
|
||||||
|
except Exception as exc:
|
||||||
|
if "object has no attribute 'cursor'" in str(
|
||||||
|
exc
|
||||||
|
) or 'object has no field "conn"' in str(exc):
|
||||||
|
raise AttributeError(
|
||||||
|
(
|
||||||
|
"Failed to build connection to database."
|
||||||
|
f" Please check your connection string and try again. Error: {exc}"
|
||||||
|
)
|
||||||
|
) from exc
|
||||||
|
raise exc
|
||||||
|
|
||||||
|
|
||||||
|
def instantiate_retriever(node_type, class_object, params):
|
||||||
|
if "retriever" in params and hasattr(params["retriever"], "as_retriever"):
|
||||||
|
params["retriever"] = params["retriever"].as_retriever()
|
||||||
|
if node_type in retriever_creator.from_method_nodes:
|
||||||
|
method = retriever_creator.from_method_nodes[node_type]
|
||||||
|
if class_method := getattr(class_object, method, None):
|
||||||
|
return class_method(**params)
|
||||||
|
raise ValueError(f"Method {method} not found in {class_object}")
|
||||||
|
return class_object(**params)
|
||||||
|
|
||||||
|
|
||||||
|
def instantiate_llm(node_type, class_object, params: Dict):
|
||||||
|
return class_object(**params)
|
||||||
|
|
||||||
|
|
||||||
|
def instantiate_chains(node_type, class_object: Type[Chain], params: Dict):
|
||||||
if "retriever" in params and hasattr(params["retriever"], "as_retriever"):
|
if "retriever" in params and hasattr(params["retriever"], "as_retriever"):
|
||||||
params["retriever"] = params["retriever"].as_retriever()
|
params["retriever"] = params["retriever"].as_retriever()
|
||||||
if node_type in chain_creator.from_method_nodes:
|
if node_type in chain_creator.from_method_nodes:
|
||||||
|
|
@ -88,11 +133,11 @@ def instantiate_chains(node_type, class_object, params):
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
||||||
|
|
||||||
def instantiate_agent(class_object, params):
|
def instantiate_agent(class_object: Type[agent_module.Agent], params: Dict):
|
||||||
return load_agent_executor(class_object, params)
|
return load_agent_executor(class_object, params)
|
||||||
|
|
||||||
|
|
||||||
def instantiate_prompt(node_type, class_object, params):
|
def instantiate_prompt(node_type, class_object: Type[BasePromptTemplate], params: Dict):
|
||||||
if node_type == "ZeroShotPrompt":
|
if node_type == "ZeroShotPrompt":
|
||||||
if "tools" not in params:
|
if "tools" not in params:
|
||||||
params["tools"] = []
|
params["tools"] = []
|
||||||
|
|
@ -100,7 +145,7 @@ def instantiate_prompt(node_type, class_object, params):
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
||||||
|
|
||||||
def instantiate_tool(node_type, class_object, params):
|
def instantiate_tool(node_type, class_object: Type[BaseTool], params: Dict):
|
||||||
if node_type == "JsonSpec":
|
if node_type == "JsonSpec":
|
||||||
params["dict_"] = load_file_into_dict(params.pop("path"))
|
params["dict_"] = load_file_into_dict(params.pop("path"))
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
@ -118,7 +163,7 @@ def instantiate_tool(node_type, class_object, params):
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
||||||
|
|
||||||
def instantiate_toolkit(node_type, class_object, params):
|
def instantiate_toolkit(node_type, class_object: Type[BaseToolkit], params: Dict):
|
||||||
loaded_toolkit = class_object(**params)
|
loaded_toolkit = class_object(**params)
|
||||||
# Commenting this out for now to use toolkits as normal tools
|
# Commenting this out for now to use toolkits as normal tools
|
||||||
# if toolkits_creator.has_create_function(node_type):
|
# if toolkits_creator.has_create_function(node_type):
|
||||||
|
|
@ -128,7 +173,7 @@ def instantiate_toolkit(node_type, class_object, params):
|
||||||
return loaded_toolkit
|
return loaded_toolkit
|
||||||
|
|
||||||
|
|
||||||
def instantiate_embedding(class_object, params):
|
def instantiate_embedding(class_object, params: Dict):
|
||||||
params.pop("model", None)
|
params.pop("model", None)
|
||||||
params.pop("headers", None)
|
params.pop("headers", None)
|
||||||
try:
|
try:
|
||||||
|
|
@ -142,7 +187,7 @@ def instantiate_embedding(class_object, params):
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
||||||
|
|
||||||
def instantiate_vectorstore(class_object, params):
|
def instantiate_vectorstore(class_object: Type[VectorStore], params: Dict):
|
||||||
search_kwargs = params.pop("search_kwargs", {})
|
search_kwargs = params.pop("search_kwargs", {})
|
||||||
if initializer := vecstore_initializer.get(class_object.__name__):
|
if initializer := vecstore_initializer.get(class_object.__name__):
|
||||||
vecstore = initializer(class_object, params)
|
vecstore = initializer(class_object, params)
|
||||||
|
|
@ -158,7 +203,7 @@ def instantiate_vectorstore(class_object, params):
|
||||||
return vecstore
|
return vecstore
|
||||||
|
|
||||||
|
|
||||||
def instantiate_documentloader(class_object, params):
|
def instantiate_documentloader(class_object: Type[BaseLoader], params: Dict):
|
||||||
if "file_filter" in params:
|
if "file_filter" in params:
|
||||||
# file_filter will be a string but we need a function
|
# file_filter will be a string but we need a function
|
||||||
# that will be used to filter the files using file_filter
|
# that will be used to filter the files using file_filter
|
||||||
|
|
@ -171,35 +216,55 @@ def instantiate_documentloader(class_object, params):
|
||||||
extension.strip() in x for extension in extensions
|
extension.strip() in x for extension in extensions
|
||||||
)
|
)
|
||||||
metadata = params.pop("metadata", None)
|
metadata = params.pop("metadata", None)
|
||||||
|
if metadata and isinstance(metadata, str):
|
||||||
|
try:
|
||||||
|
metadata = json.loads(metadata)
|
||||||
|
except json.JSONDecodeError as exc:
|
||||||
|
raise ValueError(
|
||||||
|
"The metadata you provided is not a valid JSON string."
|
||||||
|
) from exc
|
||||||
docs = class_object(**params).load()
|
docs = class_object(**params).load()
|
||||||
|
# Now if metadata is an empty dict, we will not add it to the documents
|
||||||
if metadata:
|
if metadata:
|
||||||
if isinstance(metadata, str):
|
|
||||||
try:
|
|
||||||
metadata = json.loads(metadata)
|
|
||||||
except json.JSONDecodeError as exc:
|
|
||||||
raise ValueError(
|
|
||||||
"The metadata you provided is not a valid JSON string."
|
|
||||||
) from exc
|
|
||||||
|
|
||||||
for doc in docs:
|
for doc in docs:
|
||||||
doc.metadata = metadata
|
# If the document already has metadata, we will not overwrite it
|
||||||
|
if not doc.metadata:
|
||||||
|
doc.metadata = metadata
|
||||||
|
else:
|
||||||
|
doc.metadata.update(metadata)
|
||||||
|
|
||||||
return docs
|
return docs
|
||||||
|
|
||||||
|
|
||||||
def instantiate_textsplitter(class_object, params):
|
def instantiate_textsplitter(
|
||||||
|
class_object,
|
||||||
|
params: Dict,
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
documents = params.pop("documents")
|
documents = params.pop("documents")
|
||||||
except KeyError as e:
|
except KeyError as exc:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"The source you provided did not load correctly or was empty."
|
"The source you provided did not load correctly or was empty."
|
||||||
"Try changing the chunk_size of the Text Splitter."
|
"Try changing the chunk_size of the Text Splitter."
|
||||||
) from e
|
) from exc
|
||||||
text_splitter = class_object(**params)
|
|
||||||
|
if (
|
||||||
|
"separator_type" in params and params["separator_type"] == "Text"
|
||||||
|
) or "separator_type" not in params:
|
||||||
|
params.pop("separator_type", None)
|
||||||
|
text_splitter = class_object(**params)
|
||||||
|
else:
|
||||||
|
from langchain.text_splitter import Language
|
||||||
|
|
||||||
|
language = params.pop("separator_type", None)
|
||||||
|
params["language"] = Language(language)
|
||||||
|
params.pop("separators", None)
|
||||||
|
|
||||||
|
text_splitter = class_object.from_language(**params)
|
||||||
return text_splitter.split_documents(documents)
|
return text_splitter.split_documents(documents)
|
||||||
|
|
||||||
|
|
||||||
def instantiate_utility(node_type, class_object, params):
|
def instantiate_utility(node_type, class_object, params: Dict):
|
||||||
if node_type == "SQLDatabase":
|
if node_type == "SQLDatabase":
|
||||||
return class_object.from_uri(params.pop("uri"))
|
return class_object.from_uri(params.pop("uri"))
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
@ -225,6 +290,8 @@ def load_agent_executor(agent_class: type[agent_module.Agent], params, **kwargs)
|
||||||
"""Load agent executor from agent class, tools and chain"""
|
"""Load agent executor from agent class, tools and chain"""
|
||||||
allowed_tools: Sequence[BaseTool] = params.get("allowed_tools", [])
|
allowed_tools: Sequence[BaseTool] = params.get("allowed_tools", [])
|
||||||
llm_chain = params["llm_chain"]
|
llm_chain = params["llm_chain"]
|
||||||
|
# agent has hidden args for memory. might need to be support
|
||||||
|
# memory = params["memory"]
|
||||||
# if allowed_tools is not a list or set, make it a list
|
# if allowed_tools is not a list or set, make it a list
|
||||||
if not isinstance(allowed_tools, (list, set)) and isinstance(
|
if not isinstance(allowed_tools, (list, set)) and isinstance(
|
||||||
allowed_tools, BaseTool
|
allowed_tools, BaseTool
|
||||||
|
|
@ -237,6 +304,7 @@ def load_agent_executor(agent_class: type[agent_module.Agent], params, **kwargs)
|
||||||
return AgentExecutor.from_agent_and_tools(
|
return AgentExecutor.from_agent_and_tools(
|
||||||
agent=agent,
|
agent=agent,
|
||||||
tools=allowed_tools,
|
tools=allowed_tools,
|
||||||
|
# memory=memory,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from langflow.interface.tools.base import tool_creator
|
||||||
from langflow.interface.utilities.base import utility_creator
|
from langflow.interface.utilities.base import utility_creator
|
||||||
from langflow.interface.vector_store.base import vectorstore_creator
|
from langflow.interface.vector_store.base import vectorstore_creator
|
||||||
from langflow.interface.wrappers.base import wrapper_creator
|
from langflow.interface.wrappers.base import wrapper_creator
|
||||||
|
from langflow.interface.retrievers.base import retriever_creator
|
||||||
|
|
||||||
|
|
||||||
def get_type_dict():
|
def get_type_dict():
|
||||||
|
|
@ -28,6 +29,7 @@ def get_type_dict():
|
||||||
"embeddings": embedding_creator.to_list(),
|
"embeddings": embedding_creator.to_list(),
|
||||||
"textSplitters": textsplitter_creator.to_list(),
|
"textSplitters": textsplitter_creator.to_list(),
|
||||||
"utilities": utility_creator.to_list(),
|
"utilities": utility_creator.to_list(),
|
||||||
|
"retrievers": retriever_creator.to_list(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,18 @@ from langflow.settings import settings
|
||||||
from langflow.template.frontend_node.base import FrontendNode
|
from langflow.template.frontend_node.base import FrontendNode
|
||||||
from langflow.template.frontend_node.memories import MemoryFrontendNode
|
from langflow.template.frontend_node.memories import MemoryFrontendNode
|
||||||
from langflow.utils.logger import logger
|
from langflow.utils.logger import logger
|
||||||
from langflow.utils.util import build_template_from_class
|
from langflow.utils.util import build_template_from_class, build_template_from_method
|
||||||
|
from langflow.custom.customs import get_custom_nodes
|
||||||
|
|
||||||
|
|
||||||
class MemoryCreator(LangChainTypeCreator):
|
class MemoryCreator(LangChainTypeCreator):
|
||||||
type_name: str = "memories"
|
type_name: str = "memories"
|
||||||
|
|
||||||
|
from_method_nodes = {
|
||||||
|
"ZepChatMessageHistory": "__init__",
|
||||||
|
"SQLiteEntityStore": "__init__",
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def frontend_node_class(self) -> Type[FrontendNode]:
|
def frontend_node_class(self) -> Type[FrontendNode]:
|
||||||
"""The class type of the FrontendNode created in frontend_node."""
|
"""The class type of the FrontendNode created in frontend_node."""
|
||||||
|
|
@ -26,6 +32,14 @@ class MemoryCreator(LangChainTypeCreator):
|
||||||
def get_signature(self, name: str) -> Optional[Dict]:
|
def get_signature(self, name: str) -> Optional[Dict]:
|
||||||
"""Get the signature of a memory."""
|
"""Get the signature of a memory."""
|
||||||
try:
|
try:
|
||||||
|
if name in get_custom_nodes(self.type_name).keys():
|
||||||
|
return get_custom_nodes(self.type_name)[name]
|
||||||
|
elif name in self.from_method_nodes:
|
||||||
|
return build_template_from_method(
|
||||||
|
name,
|
||||||
|
type_to_cls_dict=memory_type_to_cls_dict,
|
||||||
|
method_name=self.from_method_nodes[name],
|
||||||
|
)
|
||||||
return build_template_from_class(name, memory_type_to_cls_dict)
|
return build_template_from_class(name, memory_type_to_cls_dict)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
raise ValueError("Memory not found") from exc
|
raise ValueError("Memory not found") from exc
|
||||||
|
|
|
||||||
0
src/backend/langflow/interface/retrievers/__init__.py
Normal file
0
src/backend/langflow/interface/retrievers/__init__.py
Normal file
58
src/backend/langflow/interface/retrievers/base.py
Normal file
58
src/backend/langflow/interface/retrievers/base.py
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
from typing import Any, Dict, List, Optional, Type
|
||||||
|
|
||||||
|
from langchain import retrievers
|
||||||
|
|
||||||
|
from langflow.interface.base import LangChainTypeCreator
|
||||||
|
from langflow.interface.importing.utils import import_class
|
||||||
|
from langflow.settings import settings
|
||||||
|
from langflow.template.frontend_node.retrievers import RetrieverFrontendNode
|
||||||
|
from langflow.utils.logger import logger
|
||||||
|
from langflow.utils.util import build_template_from_method, build_template_from_class
|
||||||
|
|
||||||
|
|
||||||
|
class RetrieverCreator(LangChainTypeCreator):
|
||||||
|
type_name: str = "retrievers"
|
||||||
|
|
||||||
|
from_method_nodes = {"MultiQueryRetriever": "from_llm", "ZepRetriever": "__init__"}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def frontend_node_class(self) -> Type[RetrieverFrontendNode]:
|
||||||
|
return RetrieverFrontendNode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type_to_loader_dict(self) -> Dict:
|
||||||
|
if self.type_dict is None:
|
||||||
|
self.type_dict: dict[str, Any] = {
|
||||||
|
retriever_name: import_class(f"langchain.retrievers.{retriever_name}")
|
||||||
|
for retriever_name in retrievers.__all__
|
||||||
|
}
|
||||||
|
return self.type_dict
|
||||||
|
|
||||||
|
def get_signature(self, name: str) -> Optional[Dict]:
|
||||||
|
"""Get the signature of an embedding."""
|
||||||
|
try:
|
||||||
|
if name in self.from_method_nodes:
|
||||||
|
return build_template_from_method(
|
||||||
|
name,
|
||||||
|
type_to_cls_dict=self.type_to_loader_dict,
|
||||||
|
method_name=self.from_method_nodes[name],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return build_template_from_class(
|
||||||
|
name, type_to_cls_dict=self.type_to_loader_dict
|
||||||
|
)
|
||||||
|
except ValueError as exc:
|
||||||
|
raise ValueError(f"Retriever {name} not found") from exc
|
||||||
|
except AttributeError as exc:
|
||||||
|
logger.error(f"Retriever {name} not loaded: {exc}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def to_list(self) -> List[str]:
|
||||||
|
return [
|
||||||
|
retriever
|
||||||
|
for retriever in self.type_to_loader_dict.keys()
|
||||||
|
if retriever in settings.retrievers or settings.dev
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
retriever_creator = RetrieverCreator()
|
||||||
|
|
@ -11,6 +11,7 @@ from langflow.interface.tools.base import tool_creator
|
||||||
from langflow.interface.utilities.base import utility_creator
|
from langflow.interface.utilities.base import utility_creator
|
||||||
from langflow.interface.vector_store.base import vectorstore_creator
|
from langflow.interface.vector_store.base import vectorstore_creator
|
||||||
from langflow.interface.wrappers.base import wrapper_creator
|
from langflow.interface.wrappers.base import wrapper_creator
|
||||||
|
from langflow.interface.retrievers.base import retriever_creator
|
||||||
|
|
||||||
|
|
||||||
def get_type_list():
|
def get_type_list():
|
||||||
|
|
@ -44,6 +45,7 @@ def build_langchain_types_dict(): # sourcery skip: dict-assign-update-to-union
|
||||||
documentloader_creator,
|
documentloader_creator,
|
||||||
textsplitter_creator,
|
textsplitter_creator,
|
||||||
utility_creator,
|
utility_creator,
|
||||||
|
retriever_creator,
|
||||||
]
|
]
|
||||||
|
|
||||||
all_types = {}
|
all_types = {}
|
||||||
|
|
@ -52,3 +54,6 @@ def build_langchain_types_dict(): # sourcery skip: dict-assign-update-to-union
|
||||||
if created_types[creator.type_name].values():
|
if created_types[creator.type_name].values():
|
||||||
all_types.update(created_types)
|
all_types.update(created_types)
|
||||||
return all_types
|
return all_types
|
||||||
|
|
||||||
|
|
||||||
|
langchain_types_dict = build_langchain_types_dict()
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,12 @@ import os
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from langchain.base_language import BaseLanguageModel
|
from langchain.base_language import BaseLanguageModel
|
||||||
from PIL.Image import Image
|
from PIL.Image import Image
|
||||||
from langflow.utils.logger import logger
|
from langflow.utils.logger import logger
|
||||||
|
from langflow.chat.config import ChatConfig
|
||||||
|
|
||||||
|
|
||||||
def load_file_into_dict(file_path: str) -> dict:
|
def load_file_into_dict(file_path: str) -> dict:
|
||||||
|
|
@ -49,9 +51,9 @@ def try_setting_streaming_options(langchain_object, websocket):
|
||||||
|
|
||||||
if isinstance(llm, BaseLanguageModel):
|
if isinstance(llm, BaseLanguageModel):
|
||||||
if hasattr(llm, "streaming") and isinstance(llm.streaming, bool):
|
if hasattr(llm, "streaming") and isinstance(llm.streaming, bool):
|
||||||
llm.streaming = True
|
llm.streaming = ChatConfig.streaming
|
||||||
elif hasattr(llm, "stream") and isinstance(llm.stream, bool):
|
elif hasattr(llm, "stream") and isinstance(llm.stream, bool):
|
||||||
llm.stream = True
|
llm.stream = ChatConfig.streaming
|
||||||
|
|
||||||
return langchain_object
|
return langchain_object
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
from langflow.api import router
|
from langflow.api import router
|
||||||
from langflow.database.base import create_db_and_tables
|
from langflow.database.base import create_db_and_tables
|
||||||
|
|
@ -33,6 +37,42 @@ def create_app():
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
def setup_static_files(app: FastAPI, static_files_dir: Path):
|
||||||
|
"""
|
||||||
|
Setup the static files directory.
|
||||||
|
Args:
|
||||||
|
app (FastAPI): FastAPI app.
|
||||||
|
path (str): Path to the static files directory.
|
||||||
|
"""
|
||||||
|
app.mount(
|
||||||
|
"/",
|
||||||
|
StaticFiles(directory=static_files_dir, html=True),
|
||||||
|
name="static",
|
||||||
|
)
|
||||||
|
|
||||||
|
@app.exception_handler(404)
|
||||||
|
async def custom_404_handler(request, __):
|
||||||
|
path = static_files_dir / "index.html"
|
||||||
|
|
||||||
|
if not path.exists():
|
||||||
|
raise RuntimeError(f"File at path {path} does not exist.")
|
||||||
|
return FileResponse(path)
|
||||||
|
|
||||||
|
|
||||||
|
# app = create_app()
|
||||||
|
# setup_static_files(app, static_files_dir)
|
||||||
|
def setup_app(static_files_dir: Optional[Path]) -> FastAPI:
|
||||||
|
"""Setup the FastAPI app."""
|
||||||
|
# get the directory of the current file
|
||||||
|
if not static_files_dir:
|
||||||
|
frontend_path = Path(__file__).parent
|
||||||
|
static_files_dir = frontend_path / "frontend"
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
setup_static_files(app, static_files_dir)
|
||||||
|
return app
|
||||||
|
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,10 @@ def process_graph_cached(data_graph: Dict[str, Any], inputs: Optional[dict] = No
|
||||||
elif isinstance(langchain_object, VectorStore):
|
elif isinstance(langchain_object, VectorStore):
|
||||||
class_name = langchain_object.__class__.__name__
|
class_name = langchain_object.__class__.__name__
|
||||||
result = {"message": f"Processed {class_name} successfully"}
|
result = {"message": f"Processed {class_name} successfully"}
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Unknown langchain_object type: {type(langchain_object).__name__}"
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,24 @@
|
||||||
import os
|
import os
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from pydantic import BaseSettings, root_validator
|
from pydantic import BaseSettings, root_validator
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
chains: List[str] = []
|
chains: dict = {}
|
||||||
agents: List[str] = []
|
agents: dict = {}
|
||||||
prompts: List[str] = []
|
prompts: dict = {}
|
||||||
llms: List[str] = []
|
llms: dict = {}
|
||||||
tools: List[str] = []
|
tools: dict = {}
|
||||||
memories: List[str] = []
|
memories: dict = {}
|
||||||
embeddings: List[str] = []
|
embeddings: dict = {}
|
||||||
vectorstores: List[str] = []
|
vectorstores: dict = {}
|
||||||
documentloaders: List[str] = []
|
documentloaders: dict = {}
|
||||||
wrappers: List[str] = []
|
wrappers: dict = {}
|
||||||
toolkits: List[str] = []
|
retrievers: dict = {}
|
||||||
textsplitters: List[str] = []
|
toolkits: dict = {}
|
||||||
utilities: List[str] = []
|
textsplitters: dict = {}
|
||||||
|
utilities: dict = {}
|
||||||
dev: bool = False
|
dev: bool = False
|
||||||
database_url: str = "sqlite:///./langflow.db"
|
database_url: str = "sqlite:///./langflow.db"
|
||||||
cache: str = "InMemoryCache"
|
cache: str = "InMemoryCache"
|
||||||
|
|
@ -38,16 +38,21 @@ class Settings(BaseSettings):
|
||||||
|
|
||||||
def update_from_yaml(self, file_path: str, dev: bool = False):
|
def update_from_yaml(self, file_path: str, dev: bool = False):
|
||||||
new_settings = load_settings_from_yaml(file_path)
|
new_settings = load_settings_from_yaml(file_path)
|
||||||
self.chains = new_settings.chains or []
|
self.chains = new_settings.chains or {}
|
||||||
self.agents = new_settings.agents or []
|
self.agents = new_settings.agents or {}
|
||||||
self.prompts = new_settings.prompts or []
|
self.prompts = new_settings.prompts or {}
|
||||||
self.llms = new_settings.llms or []
|
self.llms = new_settings.llms or {}
|
||||||
self.tools = new_settings.tools or []
|
self.tools = new_settings.tools or {}
|
||||||
self.memories = new_settings.memories or []
|
self.memories = new_settings.memories or {}
|
||||||
self.wrappers = new_settings.wrappers or []
|
self.wrappers = new_settings.wrappers or {}
|
||||||
self.toolkits = new_settings.toolkits or []
|
self.toolkits = new_settings.toolkits or {}
|
||||||
self.textsplitters = new_settings.textsplitters or []
|
self.textsplitters = new_settings.textsplitters or {}
|
||||||
self.utilities = new_settings.utilities or []
|
self.utilities = new_settings.utilities or {}
|
||||||
|
self.embeddings = new_settings.embeddings or {}
|
||||||
|
self.vectorstores = new_settings.vectorstores or {}
|
||||||
|
self.documentloaders = new_settings.documentloaders or {}
|
||||||
|
self.retrievers = new_settings.retrievers or {}
|
||||||
|
|
||||||
self.dev = dev
|
self.dev = dev
|
||||||
|
|
||||||
def update_settings(self, **kwargs):
|
def update_settings(self, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ class TemplateFieldCreator(BaseModel, ABC):
|
||||||
name: str = ""
|
name: str = ""
|
||||||
display_name: Optional[str] = None
|
display_name: Optional[str] = None
|
||||||
advanced: bool = False
|
advanced: bool = False
|
||||||
|
info: Optional[str] = ""
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
result = self.dict()
|
result = self.dict()
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,43 @@
|
||||||
import re
|
import re
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS
|
from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.template.base import Template
|
from langflow.template.template.base import Template
|
||||||
from langflow.utils import constants
|
from langflow.utils import constants
|
||||||
|
from langflow.template.frontend_node.formatter import field_formatters
|
||||||
|
|
||||||
|
CLASSES_TO_REMOVE = ["Serializable", "BaseModel"]
|
||||||
|
|
||||||
|
|
||||||
|
class FieldFormatters(BaseModel):
|
||||||
|
formatters = {
|
||||||
|
"openai_api_key": field_formatters.OpenAIAPIKeyFormatter(),
|
||||||
|
}
|
||||||
|
base_formatters = {
|
||||||
|
"kwargs": field_formatters.KwargsFormatter(),
|
||||||
|
"optional": field_formatters.RemoveOptionalFormatter(),
|
||||||
|
"list": field_formatters.ListTypeFormatter(),
|
||||||
|
"dict": field_formatters.DictTypeFormatter(),
|
||||||
|
"union": field_formatters.UnionTypeFormatter(),
|
||||||
|
"multiline": field_formatters.MultilineFieldFormatter(),
|
||||||
|
"show": field_formatters.ShowFieldFormatter(),
|
||||||
|
"password": field_formatters.PasswordFieldFormatter(),
|
||||||
|
"default": field_formatters.DefaultValueFormatter(),
|
||||||
|
"headers": field_formatters.HeadersDefaultValueFormatter(),
|
||||||
|
"dict_code_file": field_formatters.DictCodeFileFormatter(),
|
||||||
|
"model_fields": field_formatters.ModelSpecificFieldFormatter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
for key, formatter in self.base_formatters.items():
|
||||||
|
formatter.format(field, name)
|
||||||
|
|
||||||
|
for key, formatter in self.formatters.items():
|
||||||
|
if key == field.name:
|
||||||
|
formatter.format(field, name)
|
||||||
|
|
||||||
|
|
||||||
class FrontendNode(BaseModel):
|
class FrontendNode(BaseModel):
|
||||||
|
|
@ -15,14 +46,37 @@ class FrontendNode(BaseModel):
|
||||||
base_classes: List[str]
|
base_classes: List[str]
|
||||||
name: str = ""
|
name: str = ""
|
||||||
display_name: str = ""
|
display_name: str = ""
|
||||||
|
documentation: str = ""
|
||||||
|
field_formatters: FieldFormatters = Field(default_factory=FieldFormatters)
|
||||||
|
|
||||||
|
def process_base_classes(self) -> None:
|
||||||
|
"""Removes unwanted base classes from the list of base classes."""
|
||||||
|
self.base_classes = [
|
||||||
|
base_class
|
||||||
|
for base_class in self.base_classes
|
||||||
|
if base_class not in CLASSES_TO_REMOVE
|
||||||
|
]
|
||||||
|
|
||||||
|
# field formatters is an instance attribute but it is not used in the class
|
||||||
|
# so we need to create a method to get it
|
||||||
|
@staticmethod
|
||||||
|
def get_field_formatters() -> FieldFormatters:
|
||||||
|
return FieldFormatters()
|
||||||
|
|
||||||
|
def set_documentation(self, documentation: str) -> None:
|
||||||
|
"""Sets the documentation of the frontend node."""
|
||||||
|
self.documentation = documentation
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
|
"""Returns a dict representation of the frontend node."""
|
||||||
|
self.process_base_classes()
|
||||||
return {
|
return {
|
||||||
self.name: {
|
self.name: {
|
||||||
"template": self.template.to_dict(self.format_field),
|
"template": self.template.to_dict(self.format_field),
|
||||||
"description": self.description,
|
"description": self.description,
|
||||||
"base_classes": self.base_classes,
|
"base_classes": self.base_classes,
|
||||||
"display_name": self.display_name or self.name,
|
"display_name": self.display_name or self.name,
|
||||||
|
"documentation": self.documentation,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,33 +89,8 @@ class FrontendNode(BaseModel):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
"""Formats a given field based on its attributes and value."""
|
"""Formats a given field based on its attributes and value."""
|
||||||
SPECIAL_FIELD_HANDLERS = {
|
|
||||||
"allowed_tools": lambda field: "Tool",
|
|
||||||
"max_value_length": lambda field: "int",
|
|
||||||
}
|
|
||||||
|
|
||||||
key = field.name
|
FrontendNode.get_field_formatters().format(field, name)
|
||||||
value = field.to_dict()
|
|
||||||
_type = value["type"]
|
|
||||||
|
|
||||||
_type = FrontendNode.remove_optional(_type)
|
|
||||||
_type, is_list = FrontendNode.check_for_list_type(_type)
|
|
||||||
field.is_list = is_list or field.is_list
|
|
||||||
_type = FrontendNode.replace_mapping_with_dict(_type)
|
|
||||||
_type = FrontendNode.handle_union_type(_type)
|
|
||||||
|
|
||||||
field.field_type = FrontendNode.handle_special_field(
|
|
||||||
field, key, _type, SPECIAL_FIELD_HANDLERS
|
|
||||||
)
|
|
||||||
field.field_type = FrontendNode.handle_dict_type(field, _type)
|
|
||||||
field.show = FrontendNode.should_show_field(key, field.required)
|
|
||||||
field.password = FrontendNode.should_be_password(key, field.show)
|
|
||||||
field.multiline = FrontendNode.should_be_multiline(key)
|
|
||||||
|
|
||||||
FrontendNode.replace_default_value(field, value)
|
|
||||||
FrontendNode.handle_specific_field_values(field, key, name)
|
|
||||||
FrontendNode.handle_kwargs_field(field)
|
|
||||||
FrontendNode.handle_api_key_field(field, key)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_optional(_type: str) -> str:
|
def remove_optional(_type: str) -> str:
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,10 @@ class ChainFrontendNode(FrontendNode):
|
||||||
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
FrontendNode.format_field(field, name)
|
FrontendNode.format_field(field, name)
|
||||||
|
|
||||||
|
if "name" == "RetrievalQA" and field.name == "memory":
|
||||||
|
field.show = False
|
||||||
|
field.required = False
|
||||||
|
|
||||||
field.advanced = False
|
field.advanced = False
|
||||||
if "key" in field.name:
|
if "key" in field.name:
|
||||||
field.password = False
|
field.password = False
|
||||||
|
|
|
||||||
|
|
@ -32,3 +32,29 @@ You are a good listener and you can talk about anything.
|
||||||
HUMAN_PROMPT = "{input}"
|
HUMAN_PROMPT = "{input}"
|
||||||
|
|
||||||
QA_CHAIN_TYPES = ["stuff", "map_reduce", "map_rerank", "refine"]
|
QA_CHAIN_TYPES = ["stuff", "map_reduce", "map_rerank", "refine"]
|
||||||
|
|
||||||
|
CTRANSFORMERS_DEFAULT_CONFIG = {
|
||||||
|
"top_k": 40,
|
||||||
|
"top_p": 0.95,
|
||||||
|
"temperature": 0.8,
|
||||||
|
"repetition_penalty": 1.1,
|
||||||
|
"last_n_tokens": 64,
|
||||||
|
"seed": -1,
|
||||||
|
"max_new_tokens": 256,
|
||||||
|
"stop": None,
|
||||||
|
"stream": False,
|
||||||
|
"reset": True,
|
||||||
|
"batch_size": 8,
|
||||||
|
"threads": -1,
|
||||||
|
"context_length": -1,
|
||||||
|
"gpu_layers": 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
# This variable is used to tell the user
|
||||||
|
# that it can be changed to use other APIs
|
||||||
|
# like Prem and LocalAI
|
||||||
|
OPENAI_API_BASE_INFO = """
|
||||||
|
The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.
|
||||||
|
|
||||||
|
You can change this to use other APIs like JinaChat, LocalAI and Prem.
|
||||||
|
"""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from langflow.template.field.base import TemplateField
|
||||||
|
|
||||||
|
|
||||||
|
class FieldFormatter(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def format(self, field: TemplateField, name: Optional[str]) -> None:
|
||||||
|
pass
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
from typing import Optional
|
||||||
|
from langflow.template.field.base import TemplateField
|
||||||
|
from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS
|
||||||
|
from langflow.template.frontend_node.formatter.base import FieldFormatter
|
||||||
|
import re
|
||||||
|
|
||||||
|
from langflow.utils.constants import (
|
||||||
|
ANTHROPIC_MODELS,
|
||||||
|
CHAT_OPENAI_MODELS,
|
||||||
|
OPENAI_MODELS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class OpenAIAPIKeyFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
if "api_key" in field.name and "OpenAI" in str(name):
|
||||||
|
field.display_name = "OpenAI API Key"
|
||||||
|
field.required = False
|
||||||
|
if field.value is None:
|
||||||
|
field.value = ""
|
||||||
|
|
||||||
|
|
||||||
|
class ModelSpecificFieldFormatter(FieldFormatter):
|
||||||
|
MODEL_DICT = {
|
||||||
|
"OpenAI": OPENAI_MODELS,
|
||||||
|
"ChatOpenAI": CHAT_OPENAI_MODELS,
|
||||||
|
"Anthropic": ANTHROPIC_MODELS,
|
||||||
|
"ChatAnthropic": ANTHROPIC_MODELS,
|
||||||
|
}
|
||||||
|
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
if name in self.MODEL_DICT and field.name == "model_name":
|
||||||
|
field.options = self.MODEL_DICT[name]
|
||||||
|
field.is_list = True
|
||||||
|
|
||||||
|
|
||||||
|
class KwargsFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
if "kwargs" in field.name.lower():
|
||||||
|
field.advanced = True
|
||||||
|
field.required = False
|
||||||
|
field.show = False
|
||||||
|
|
||||||
|
|
||||||
|
class APIKeyFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
if "api" in field.name.lower() and "key" in field.name.lower():
|
||||||
|
field.required = False
|
||||||
|
field.advanced = False
|
||||||
|
|
||||||
|
field.display_name = field.name.replace("_", " ").title()
|
||||||
|
field.display_name = field.display_name.replace("Api", "API")
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveOptionalFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
_type = field.field_type
|
||||||
|
field.field_type = re.sub(r"Optional\[(.*)\]", r"\1", _type)
|
||||||
|
|
||||||
|
|
||||||
|
class ListTypeFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
_type = field.field_type
|
||||||
|
is_list = "List" in _type or "Sequence" in _type
|
||||||
|
if is_list:
|
||||||
|
_type = re.sub(r"(List|Sequence)\[(.*)\]", r"\2", _type)
|
||||||
|
field.is_list = True
|
||||||
|
field.field_type = _type
|
||||||
|
|
||||||
|
|
||||||
|
class DictTypeFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
_type = field.field_type
|
||||||
|
_type = _type.replace("Mapping", "dict")
|
||||||
|
field.field_type = _type
|
||||||
|
|
||||||
|
|
||||||
|
class UnionTypeFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
_type = field.field_type
|
||||||
|
if "Union" in _type:
|
||||||
|
_type = _type.replace("Union[", "")[:-1]
|
||||||
|
_type = _type.split(",")[0]
|
||||||
|
_type = _type.replace("]", "").replace("[", "")
|
||||||
|
field.field_type = _type
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialFieldFormatter(FieldFormatter):
|
||||||
|
SPECIAL_FIELD_HANDLERS = {
|
||||||
|
"allowed_tools": lambda field: "Tool",
|
||||||
|
"max_value_length": lambda field: "int",
|
||||||
|
}
|
||||||
|
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
handler = self.SPECIAL_FIELD_HANDLERS.get(field.name)
|
||||||
|
field.field_type = handler(field) if handler else field.field_type
|
||||||
|
|
||||||
|
|
||||||
|
class ShowFieldFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
key = field.name
|
||||||
|
required = field.required
|
||||||
|
field.show = (
|
||||||
|
(required and key not in ["input_variables"])
|
||||||
|
or key in FORCE_SHOW_FIELDS
|
||||||
|
or "api" in key
|
||||||
|
or ("key" in key and "input" not in key and "output" not in key)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordFieldFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
key = field.name
|
||||||
|
show = field.show
|
||||||
|
if (
|
||||||
|
any(text in key.lower() for text in {"password", "token", "api", "key"})
|
||||||
|
and show
|
||||||
|
):
|
||||||
|
field.password = True
|
||||||
|
|
||||||
|
|
||||||
|
class MultilineFieldFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
key = field.name
|
||||||
|
if key in {
|
||||||
|
"suffix",
|
||||||
|
"prefix",
|
||||||
|
"template",
|
||||||
|
"examples",
|
||||||
|
"code",
|
||||||
|
"headers",
|
||||||
|
"description",
|
||||||
|
}:
|
||||||
|
field.multiline = True
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultValueFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
value = field.to_dict()
|
||||||
|
if "default" in value:
|
||||||
|
field.value = value["default"]
|
||||||
|
|
||||||
|
|
||||||
|
class HeadersDefaultValueFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
key = field.name
|
||||||
|
if key == "headers":
|
||||||
|
field.value = """{'Authorization': 'Bearer <token>'}"""
|
||||||
|
|
||||||
|
|
||||||
|
class DictCodeFileFormatter(FieldFormatter):
|
||||||
|
def format(self, field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
key = field.name
|
||||||
|
value = field.to_dict()
|
||||||
|
_type = value["type"]
|
||||||
|
if "dict" in _type.lower():
|
||||||
|
if key == "dict_":
|
||||||
|
field.field_type = "file"
|
||||||
|
field.suffixes = [".json", ".yaml", ".yml"]
|
||||||
|
field.file_types = ["json", "yaml", "yml"]
|
||||||
|
else:
|
||||||
|
field.field_type = "code"
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
import json
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.base import FrontendNode
|
from langflow.template.frontend_node.base import FrontendNode
|
||||||
|
from langflow.template.frontend_node.constants import CTRANSFORMERS_DEFAULT_CONFIG
|
||||||
|
from langflow.template.frontend_node.constants import OPENAI_API_BASE_INFO
|
||||||
|
|
||||||
|
|
||||||
class LLMFrontendNode(FrontendNode):
|
class LLMFrontendNode(FrontendNode):
|
||||||
|
|
@ -15,6 +18,13 @@ class LLMFrontendNode(FrontendNode):
|
||||||
if "key" not in field.name.lower() and "token" not in field.name.lower():
|
if "key" not in field.name.lower() and "token" not in field.name.lower():
|
||||||
field.password = False
|
field.password = False
|
||||||
|
|
||||||
|
if field.name == "openai_api_base":
|
||||||
|
field.info = OPENAI_API_BASE_INFO
|
||||||
|
|
||||||
|
def add_extra_base_classes(self) -> None:
|
||||||
|
if "BaseLLM" not in self.base_classes:
|
||||||
|
self.base_classes.append("BaseLLM")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_azure_field(field: TemplateField):
|
def format_azure_field(field: TemplateField):
|
||||||
if field.name == "model_name":
|
if field.name == "model_name":
|
||||||
|
|
@ -31,6 +41,13 @@ class LLMFrontendNode(FrontendNode):
|
||||||
field.show = True
|
field.show = True
|
||||||
field.advanced = not field.required
|
field.advanced = not field.required
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format_ctransformers_field(field: TemplateField):
|
||||||
|
if field.name == "config":
|
||||||
|
field.show = True
|
||||||
|
field.advanced = True
|
||||||
|
field.value = json.dumps(CTRANSFORMERS_DEFAULT_CONFIG, indent=2)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
display_names_dict = {
|
display_names_dict = {
|
||||||
|
|
@ -38,6 +55,7 @@ class LLMFrontendNode(FrontendNode):
|
||||||
}
|
}
|
||||||
FrontendNode.format_field(field, name)
|
FrontendNode.format_field(field, name)
|
||||||
LLMFrontendNode.format_openai_field(field)
|
LLMFrontendNode.format_openai_field(field)
|
||||||
|
LLMFrontendNode.format_ctransformers_field(field)
|
||||||
if name and "azure" in name.lower():
|
if name and "azure" in name.lower():
|
||||||
LLMFrontendNode.format_azure_field(field)
|
LLMFrontendNode.format_azure_field(field)
|
||||||
if name and "llama" in name.lower():
|
if name and "llama" in name.lower():
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,19 @@ from typing import Optional
|
||||||
|
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.base import FrontendNode
|
from langflow.template.frontend_node.base import FrontendNode
|
||||||
|
from langflow.template.template.base import Template
|
||||||
|
from langchain.memory.chat_message_histories.postgres import DEFAULT_CONNECTION_STRING
|
||||||
|
|
||||||
|
|
||||||
class MemoryFrontendNode(FrontendNode):
|
class MemoryFrontendNode(FrontendNode):
|
||||||
#! Needs testing
|
#! Needs testing
|
||||||
def add_extra_fields(self) -> None:
|
def add_extra_fields(self) -> None:
|
||||||
|
# chat history should have another way to add common field?
|
||||||
|
# prevent adding incorect field in ChatMessageHistory
|
||||||
|
base_message_classes = ["BaseEntityStore", "BaseChatMessageHistory"]
|
||||||
|
if any(base_class in self.base_classes for base_class in base_message_classes):
|
||||||
|
return
|
||||||
|
|
||||||
# add return_messages field
|
# add return_messages field
|
||||||
self.template.add_field(
|
self.template.add_field(
|
||||||
TemplateField(
|
TemplateField(
|
||||||
|
|
@ -64,3 +72,50 @@ class MemoryFrontendNode(FrontendNode):
|
||||||
field.value = ""
|
field.value = ""
|
||||||
if field.name == "memory_key":
|
if field.name == "memory_key":
|
||||||
field.value = "chat_history"
|
field.value = "chat_history"
|
||||||
|
if field.name == "chat_memory":
|
||||||
|
field.show = True
|
||||||
|
field.advanced = False
|
||||||
|
field.required = False
|
||||||
|
if field.name == "url":
|
||||||
|
field.show = True
|
||||||
|
if field.name == "entity_store":
|
||||||
|
field.show = True
|
||||||
|
if name == "SQLiteEntityStore":
|
||||||
|
field.show = True
|
||||||
|
|
||||||
|
|
||||||
|
class PostgresChatMessageHistoryFrontendNode(MemoryFrontendNode):
|
||||||
|
name: str = "PostgresChatMessageHistory"
|
||||||
|
template: Template = Template(
|
||||||
|
type_name="PostgresChatMessageHistory",
|
||||||
|
fields=[
|
||||||
|
TemplateField(
|
||||||
|
field_type="str",
|
||||||
|
required=True,
|
||||||
|
placeholder="",
|
||||||
|
is_list=False,
|
||||||
|
show=True,
|
||||||
|
multiline=False,
|
||||||
|
name="session_id",
|
||||||
|
),
|
||||||
|
TemplateField(
|
||||||
|
field_type="str",
|
||||||
|
required=True,
|
||||||
|
show=True,
|
||||||
|
name="connection_string",
|
||||||
|
value=DEFAULT_CONNECTION_STRING,
|
||||||
|
),
|
||||||
|
TemplateField(
|
||||||
|
field_type="str",
|
||||||
|
required=True,
|
||||||
|
placeholder="",
|
||||||
|
is_list=False,
|
||||||
|
show=True,
|
||||||
|
multiline=False,
|
||||||
|
value="message_store",
|
||||||
|
name="table_name",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
description: str = "Memory store with Postgres"
|
||||||
|
base_classes: list[str] = ["PostgresChatMessageHistory", "BaseChatMessageHistory"]
|
||||||
|
|
|
||||||
15
src/backend/langflow/template/frontend_node/retrievers.py
Normal file
15
src/backend/langflow/template/frontend_node/retrievers.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from langflow.template.field.base import TemplateField
|
||||||
|
from langflow.template.frontend_node.base import FrontendNode
|
||||||
|
|
||||||
|
|
||||||
|
class RetrieverFrontendNode(FrontendNode):
|
||||||
|
@staticmethod
|
||||||
|
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
FrontendNode.format_field(field, name)
|
||||||
|
# Define common field attributes
|
||||||
|
field.show = True
|
||||||
|
if field.name == "parser_key":
|
||||||
|
field.display_name = "Parser Key"
|
||||||
|
field.password = False
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.base import FrontendNode
|
from langflow.template.frontend_node.base import FrontendNode
|
||||||
|
from langchain.text_splitter import Language
|
||||||
|
|
||||||
|
|
||||||
class TextSplittersFrontendNode(FrontendNode):
|
class TextSplittersFrontendNode(FrontendNode):
|
||||||
|
|
@ -17,6 +18,24 @@ class TextSplittersFrontendNode(FrontendNode):
|
||||||
name = "separator"
|
name = "separator"
|
||||||
elif self.template.type_name == "RecursiveCharacterTextSplitter":
|
elif self.template.type_name == "RecursiveCharacterTextSplitter":
|
||||||
name = "separators"
|
name = "separators"
|
||||||
|
# Add a field for type of separator
|
||||||
|
# which will have Text or any value from the
|
||||||
|
# Language enum
|
||||||
|
options = [x.value for x in Language] + ["Text"]
|
||||||
|
options.sort()
|
||||||
|
self.template.add_field(
|
||||||
|
TemplateField(
|
||||||
|
field_type="str",
|
||||||
|
required=True,
|
||||||
|
show=True,
|
||||||
|
name="separator_type",
|
||||||
|
advanced=False,
|
||||||
|
is_list=True,
|
||||||
|
options=options,
|
||||||
|
value="Text",
|
||||||
|
display_name="Separator Type",
|
||||||
|
)
|
||||||
|
)
|
||||||
self.template.add_field(
|
self.template.add_field(
|
||||||
TemplateField(
|
TemplateField(
|
||||||
field_type="str",
|
field_type="str",
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ class VectorStoreFrontendNode(FrontendNode):
|
||||||
self.template.add_field(field)
|
self.template.add_field(field)
|
||||||
|
|
||||||
def add_extra_base_classes(self) -> None:
|
def add_extra_base_classes(self) -> None:
|
||||||
self.base_classes.append("BaseRetriever")
|
self.base_classes.extend(("BaseRetriever", "VectorStoreRetriever"))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ def build_template_from_method(
|
||||||
"required": param.default == param.empty,
|
"required": param.default == param.empty,
|
||||||
}
|
}
|
||||||
for name, param in params.items()
|
for name, param in params.items()
|
||||||
|
if name not in ["self", "kwargs", "args"]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,6 +234,9 @@ def format_dict(d, name: Optional[str] = None):
|
||||||
|
|
||||||
_type = value["type"]
|
_type = value["type"]
|
||||||
|
|
||||||
|
if not isinstance(_type, str):
|
||||||
|
_type = _type.__name__
|
||||||
|
|
||||||
# Remove 'Optional' wrapper
|
# Remove 'Optional' wrapper
|
||||||
if "Optional" in _type:
|
if "Optional" in _type:
|
||||||
_type = _type.replace("Optional[", "")[:-1]
|
_type = _type.replace("Optional[", "")[:-1]
|
||||||
|
|
|
||||||
294
src/frontend/package-lock.json
generated
294
src/frontend/package-lock.json
generated
|
|
@ -13,9 +13,11 @@
|
||||||
"@headlessui/react": "^1.7.10",
|
"@headlessui/react": "^1.7.10",
|
||||||
"@heroicons/react": "^2.0.15",
|
"@heroicons/react": "^2.0.15",
|
||||||
"@mui/material": "^5.11.9",
|
"@mui/material": "^5.11.9",
|
||||||
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-dialog": "^1.0.4",
|
"@radix-ui/react-dialog": "^1.0.4",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
"@radix-ui/react-menubar": "^1.0.3",
|
"@radix-ui/react-menubar": "^1.0.3",
|
||||||
"@radix-ui/react-progress": "^1.0.3",
|
"@radix-ui/react-progress": "^1.0.3",
|
||||||
|
|
@ -27,6 +29,7 @@
|
||||||
"@tabler/icons-react": "^2.18.0",
|
"@tabler/icons-react": "^2.18.0",
|
||||||
"@tailwindcss/forms": "^0.5.3",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
"@tailwindcss/line-clamp": "^0.4.4",
|
"@tailwindcss/line-clamp": "^0.4.4",
|
||||||
|
"accordion": "^3.0.2",
|
||||||
"ace-builds": "^1.16.0",
|
"ace-builds": "^1.16.0",
|
||||||
"add": "^2.0.6",
|
"add": "^2.0.6",
|
||||||
"ansi-to-html": "^0.7.2",
|
"ansi-to-html": "^0.7.2",
|
||||||
|
|
@ -34,6 +37,7 @@
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"class-variance-authority": "^0.6.0",
|
"class-variance-authority": "^0.6.0",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
|
"dompurify": "^3.0.3",
|
||||||
"esbuild": "^0.17.18",
|
"esbuild": "^0.17.18",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.233.0",
|
"lucide-react": "^0.233.0",
|
||||||
|
|
@ -53,7 +57,7 @@
|
||||||
"rehype-mathjax": "^4.0.2",
|
"rehype-mathjax": "^4.0.2",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-math": "^5.1.1",
|
"remark-math": "^5.1.1",
|
||||||
"shadcn-ui": "^0.1.3",
|
"shadcn-ui": "^0.2.2",
|
||||||
"short-unique-id": "^4.4.4",
|
"short-unique-id": "^4.4.4",
|
||||||
"switch": "^0.0.0",
|
"switch": "^0.0.0",
|
||||||
"table": "^6.8.1",
|
"table": "^6.8.1",
|
||||||
|
|
@ -114,6 +118,20 @@
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@antfu/ni": {
|
||||||
|
"version": "0.21.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@antfu/ni/-/ni-0.21.4.tgz",
|
||||||
|
"integrity": "sha512-O0Uv9LbLDSoEg26fnMDdDRiPwFJnQSoD4WnrflDwKCJm8Cx/0mV4cGxwBLXan5mGIrpK4Dd7vizf4rQm0QCEAA==",
|
||||||
|
"bin": {
|
||||||
|
"na": "bin/na.mjs",
|
||||||
|
"nci": "bin/nci.mjs",
|
||||||
|
"ni": "bin/ni.mjs",
|
||||||
|
"nlx": "bin/nlx.mjs",
|
||||||
|
"nr": "bin/nr.mjs",
|
||||||
|
"nu": "bin/nu.mjs",
|
||||||
|
"nun": "bin/nun.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
"version": "7.21.4",
|
"version": "7.21.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
|
||||||
|
|
@ -1212,15 +1230,15 @@
|
||||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@mui/system": {
|
"node_modules/@mui/system": {
|
||||||
"version": "5.13.5",
|
"version": "5.13.6",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.5.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.6.tgz",
|
||||||
"integrity": "sha512-n0gzUxoZ2ZHZgnExkh2Htvo9uW2oakofgPRQrDoa/GQOWyRD0NH9MDszBwOb6AAoXZb+OV5TE7I4LeZ/dzgHYA==",
|
"integrity": "sha512-G3Xr28uLqU3DyF6r2LQkHGw/ku4P0AHzlKVe7FGXOPl7X1u+hoe2xxj8Vdiq/69II/mh9OP21i38yBWgWb7WgQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.21.0",
|
"@babel/runtime": "^7.22.5",
|
||||||
"@mui/private-theming": "^5.13.1",
|
"@mui/private-theming": "^5.13.1",
|
||||||
"@mui/styled-engine": "^5.13.2",
|
"@mui/styled-engine": "^5.13.2",
|
||||||
"@mui/types": "^7.2.4",
|
"@mui/types": "^7.2.4",
|
||||||
"@mui/utils": "^5.13.1",
|
"@mui/utils": "^5.13.6",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"csstype": "^3.1.2",
|
"csstype": "^3.1.2",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
|
|
@ -1280,11 +1298,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/utils": {
|
"node_modules/@mui/utils": {
|
||||||
"version": "5.13.1",
|
"version": "5.13.6",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.6.tgz",
|
||||||
"integrity": "sha512-6lXdWwmlUbEU2jUI8blw38Kt+3ly7xkmV9ljzY4Q20WhsJMWiNry9CX8M+TaP/HbtuyR8XKsdMgQW7h7MM3n3A==",
|
"integrity": "sha512-ggNlxl5NPSbp+kNcQLmSig6WVB0Id+4gOxhx644987v4fsji+CSXc+MFYLocFB/x4oHtzCUlSzbVHlJfP/fXoQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.21.0",
|
"@babel/runtime": "^7.22.5",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"@types/react-is": "^18.2.0",
|
"@types/react-is": "^18.2.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
|
|
@ -1366,6 +1384,37 @@
|
||||||
"@babel/runtime": "^7.13.10"
|
"@babel/runtime": "^7.13.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-accordion": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-collapsible": "1.0.3",
|
||||||
|
"@radix-ui/react-collection": "1.0.3",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.1",
|
||||||
|
"@radix-ui/react-context": "1.0.1",
|
||||||
|
"@radix-ui/react-direction": "1.0.1",
|
||||||
|
"@radix-ui/react-id": "1.0.1",
|
||||||
|
"@radix-ui/react-primitive": "1.0.3",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-arrow": {
|
"node_modules/@radix-ui/react-arrow": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz",
|
||||||
|
|
@ -1419,6 +1468,36 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-collapsible": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.13.10",
|
||||||
|
"@radix-ui/primitive": "1.0.1",
|
||||||
|
"@radix-ui/react-compose-refs": "1.0.1",
|
||||||
|
"@radix-ui/react-context": "1.0.1",
|
||||||
|
"@radix-ui/react-id": "1.0.1",
|
||||||
|
"@radix-ui/react-presence": "1.0.1",
|
||||||
|
"@radix-ui/react-primitive": "1.0.3",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.0.1",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-collection": {
|
"node_modules/@radix-ui/react-collection": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz",
|
||||||
|
|
@ -1630,6 +1709,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-icons": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.x || ^17.x || ^18.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-id": {
|
"node_modules/@radix-ui/react-id": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
|
||||||
|
|
@ -3106,6 +3193,39 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@ts-morph/common": {
|
||||||
|
"version": "0.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.19.0.tgz",
|
||||||
|
"integrity": "sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-glob": "^3.2.12",
|
||||||
|
"minimatch": "^7.4.3",
|
||||||
|
"mkdirp": "^2.1.6",
|
||||||
|
"path-browserify": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@ts-morph/common/node_modules/brace-expansion": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@ts-morph/common/node_modules/minimatch": {
|
||||||
|
"version": "7.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
|
||||||
|
"integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/aria-query": {
|
"node_modules/@types/aria-query": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz",
|
||||||
|
|
@ -3547,6 +3667,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
||||||
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="
|
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/accordion": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/accordion/-/accordion-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-jbQfFaw+57OBwPt7qSNHuW+RA8smmRwkWRS1Ozh6K/QxUspBgBV/LpdSzlY7vee8TomS6j3D33B9rIeH1qMwsA=="
|
||||||
|
},
|
||||||
"node_modules/ace-builds": {
|
"node_modules/ace-builds": {
|
||||||
"version": "1.16.0",
|
"version": "1.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.16.0.tgz",
|
||||||
|
|
@ -3714,9 +3839,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/aria-query": {
|
"node_modules/aria-query": {
|
||||||
"version": "5.2.1",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
|
||||||
"integrity": "sha512-7uFg4b+lETFgdaJyETnILsXgnnzVnkHcgRbwbPwevm5x/LmUlt3MjczMRe1zg824iBgXZNRPTBftNYyRSKLp2g==",
|
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dequal": "^2.0.3"
|
"dequal": "^2.0.3"
|
||||||
|
|
@ -4491,6 +4616,11 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/code-block-writer": {
|
||||||
|
"version": "12.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz",
|
||||||
|
"integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w=="
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
|
@ -5009,10 +5139,15 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dompurify": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
|
||||||
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.438",
|
"version": "1.4.440",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.438.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz",
|
||||||
"integrity": "sha512-x94U0FhphEsHsOloCvlsujHCvoir0ZQ73ZAs/QN4PLx98uNvyEU79F75rq1db75Bx/atvuh7KPeuxelh+xfYJw=="
|
"integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw=="
|
||||||
},
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
|
|
@ -6745,9 +6880,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/katex": {
|
"node_modules/katex": {
|
||||||
"version": "0.16.7",
|
"version": "0.16.8",
|
||||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.7.tgz",
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
|
||||||
"integrity": "sha512-Xk9C6oGKRwJTfqfIbtr0Kes9OSv6IFsuhFGc7tW4urlpMJtuh+7YhzU6YEG9n8gmWKcMAFzkp7nr+r69kV0zrA==",
|
"integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
"https://opencollective.com/katex",
|
"https://opencollective.com/katex",
|
||||||
"https://github.com/sponsors/katex"
|
"https://github.com/sponsors/katex"
|
||||||
|
|
@ -6863,9 +6998,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/log-symbols/node_modules/chalk": {
|
"node_modules/log-symbols/node_modules/chalk": {
|
||||||
"version": "5.2.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||||
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
|
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||||
},
|
},
|
||||||
|
|
@ -7838,11 +7973,33 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mj-context-menu": {
|
"node_modules/mj-context-menu": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
|
||||||
"integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
|
"integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/mkdirp": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==",
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "dist/cjs/src/bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mri": {
|
"node_modules/mri": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||||
|
|
@ -8111,9 +8268,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ora/node_modules/chalk": {
|
"node_modules/ora/node_modules/chalk": {
|
||||||
"version": "5.2.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||||
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
|
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||||
},
|
},
|
||||||
|
|
@ -8210,6 +8367,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
||||||
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
|
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/path-browserify": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
|
||||||
|
},
|
||||||
"node_modules/path-is-absolute": {
|
"node_modules/path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
|
@ -9286,23 +9448,40 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/shadcn-ui": {
|
"node_modules/shadcn-ui": {
|
||||||
"version": "0.1.3",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/shadcn-ui/-/shadcn-ui-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/shadcn-ui/-/shadcn-ui-0.2.2.tgz",
|
||||||
"integrity": "sha512-f6Wa4ZIxsigfOonC3yyJkPb2JXJnuGFyUn1fJJrDUHvIJOydUukcdQsZg7Lp6F6llkmfRjra1dZOo0KpSfdjuQ==",
|
"integrity": "sha512-T76EeZymSB45Yz63gkYOv9P0Ke+UA9IZenysx+975nyNzXxU7HRBgfwuHiMcrcubtOLrzRVedTLX3lcOMqDeRQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@antfu/ni": "^0.21.4",
|
||||||
"chalk": "5.2.0",
|
"chalk": "5.2.0",
|
||||||
"commander": "^10.0.0",
|
"commander": "^10.0.0",
|
||||||
|
"cosmiconfig": "^8.1.3",
|
||||||
|
"diff": "^5.1.0",
|
||||||
"execa": "^7.0.0",
|
"execa": "^7.0.0",
|
||||||
"fs-extra": "^11.1.0",
|
"fs-extra": "^11.1.0",
|
||||||
|
"https-proxy-agent": "^6.2.0",
|
||||||
"node-fetch": "^3.3.0",
|
"node-fetch": "^3.3.0",
|
||||||
"ora": "^6.1.2",
|
"ora": "^6.1.2",
|
||||||
"prompts": "^2.4.2",
|
"prompts": "^2.4.2",
|
||||||
|
"ts-morph": "^18.0.0",
|
||||||
|
"tsconfig-paths": "^4.2.0",
|
||||||
"zod": "^3.20.2"
|
"zod": "^3.20.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"shadcn-ui": "dist/index.js"
|
"shadcn-ui": "dist/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/shadcn-ui/node_modules/agent-base": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/shadcn-ui/node_modules/chalk": {
|
"node_modules/shadcn-ui/node_modules/chalk": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
|
||||||
|
|
@ -9322,6 +9501,35 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/shadcn-ui/node_modules/cosmiconfig": {
|
||||||
|
"version": "8.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz",
|
||||||
|
"integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"import-fresh": "^3.2.1",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"parse-json": "^5.0.0",
|
||||||
|
"path-type": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/d-fischer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/shadcn-ui/node_modules/https-proxy-agent": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-ONsE3+yfZF2caH5+bJlcddtWqNI3Gvs5A38+ngvljxaBiRXRswym2c7yf8UAeFpRFKjFNHIFEHqR/OLAWJzyiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.0.2",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
|
|
@ -9575,6 +9783,14 @@
|
||||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/strip-bom": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/strip-eof": {
|
"node_modules/strip-eof": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||||
|
|
@ -9950,6 +10166,28 @@
|
||||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
|
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-morph": {
|
||||||
|
"version": "18.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-18.0.0.tgz",
|
||||||
|
"integrity": "sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@ts-morph/common": "~0.19.0",
|
||||||
|
"code-block-writer": "^12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tsconfig-paths": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
|
||||||
|
"dependencies": {
|
||||||
|
"json5": "^2.2.2",
|
||||||
|
"minimist": "^1.2.6",
|
||||||
|
"strip-bom": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.5.3",
|
"version": "2.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@
|
||||||
"@headlessui/react": "^1.7.10",
|
"@headlessui/react": "^1.7.10",
|
||||||
"@heroicons/react": "^2.0.15",
|
"@heroicons/react": "^2.0.15",
|
||||||
"@mui/material": "^5.11.9",
|
"@mui/material": "^5.11.9",
|
||||||
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-dialog": "^1.0.4",
|
"@radix-ui/react-dialog": "^1.0.4",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
"@radix-ui/react-menubar": "^1.0.3",
|
"@radix-ui/react-menubar": "^1.0.3",
|
||||||
"@radix-ui/react-progress": "^1.0.3",
|
"@radix-ui/react-progress": "^1.0.3",
|
||||||
|
|
@ -22,6 +24,7 @@
|
||||||
"@tabler/icons-react": "^2.18.0",
|
"@tabler/icons-react": "^2.18.0",
|
||||||
"@tailwindcss/forms": "^0.5.3",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
"@tailwindcss/line-clamp": "^0.4.4",
|
"@tailwindcss/line-clamp": "^0.4.4",
|
||||||
|
"accordion": "^3.0.2",
|
||||||
"ace-builds": "^1.16.0",
|
"ace-builds": "^1.16.0",
|
||||||
"add": "^2.0.6",
|
"add": "^2.0.6",
|
||||||
"ansi-to-html": "^0.7.2",
|
"ansi-to-html": "^0.7.2",
|
||||||
|
|
@ -29,6 +32,7 @@
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"class-variance-authority": "^0.6.0",
|
"class-variance-authority": "^0.6.0",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
|
"dompurify": "^3.0.3",
|
||||||
"esbuild": "^0.17.18",
|
"esbuild": "^0.17.18",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.233.0",
|
"lucide-react": "^0.233.0",
|
||||||
|
|
@ -48,7 +52,7 @@
|
||||||
"rehype-mathjax": "^4.0.2",
|
"rehype-mathjax": "^4.0.2",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-math": "^5.1.1",
|
"remark-math": "^5.1.1",
|
||||||
"shadcn-ui": "^0.1.3",
|
"shadcn-ui": "^0.2.2",
|
||||||
"short-unique-id": "^4.4.4",
|
"short-unique-id": "^4.4.4",
|
||||||
"switch": "^0.0.0",
|
"switch": "^0.0.0",
|
||||||
"table": "^6.8.1",
|
"table": "^6.8.1",
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import { nodeColors } from "../../../../utils";
|
||||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||||
|
import { Info } from "lucide-react";
|
||||||
|
|
||||||
export default function ParameterComponent({
|
export default function ParameterComponent({
|
||||||
left,
|
left,
|
||||||
|
|
@ -36,9 +37,11 @@ export default function ParameterComponent({
|
||||||
type,
|
type,
|
||||||
name = "",
|
name = "",
|
||||||
required = false,
|
required = false,
|
||||||
|
info = "",
|
||||||
}: ParameterComponentType) {
|
}: ParameterComponentType) {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
const refHtml = useRef(null);
|
const refHtml = useRef(null);
|
||||||
|
const infoHtml = useRef(null);
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
const [position, setPosition] = useState(0);
|
const [position, setPosition] = useState(0);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
|
|
@ -79,6 +82,18 @@ export default function ParameterComponent({
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
infoHtml.current = (
|
||||||
|
<div className="h-full w-full break-words">
|
||||||
|
{info.split("\n").map((line, i) => (
|
||||||
|
<p key={i} className="block">
|
||||||
|
{line}
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [info]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const groupedObj = groupByFamily(myData, tooltipTitle);
|
const groupedObj = groupByFamily(myData, tooltipTitle);
|
||||||
|
|
||||||
|
|
@ -126,9 +141,22 @@ export default function ParameterComponent({
|
||||||
className="w-full flex flex-wrap justify-between items-center bg-muted mt-1 px-5 py-2"
|
className="w-full flex flex-wrap justify-between items-center bg-muted mt-1 px-5 py-2"
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<div className={"text-sm truncate w-full " + (left ? "" : "text-end")}>
|
<div
|
||||||
|
className={
|
||||||
|
"text-sm truncate w-full" +
|
||||||
|
(left ? "" : " text-end") +
|
||||||
|
(info !== "" ? " flex items-center" : "")
|
||||||
|
}
|
||||||
|
>
|
||||||
{title}
|
{title}
|
||||||
<span className="text-destructive">{required ? " *" : ""}</span>
|
<span className="text-destructive">{required ? " *" : ""}</span>
|
||||||
|
<div className="">
|
||||||
|
{info !== "" && (
|
||||||
|
<ShadTooltip content={infoHtml.current}>
|
||||||
|
<Info className="ml-2 relative bottom-0.5 w-3 h-3" />
|
||||||
|
</ShadTooltip>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{left &&
|
{left &&
|
||||||
(type === "str" ||
|
(type === "str" ||
|
||||||
|
|
@ -144,7 +172,6 @@ export default function ParameterComponent({
|
||||||
delayDuration={0}
|
delayDuration={0}
|
||||||
content={refHtml.current}
|
content={refHtml.current}
|
||||||
side={left ? "left" : "right"}
|
side={left ? "left" : "right"}
|
||||||
open={refHtml?.current?.length > 0}
|
|
||||||
>
|
>
|
||||||
<Handle
|
<Handle
|
||||||
type={left ? "target" : "source"}
|
type={left ? "target" : "source"}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,7 @@ import {
|
||||||
} from "../../utils";
|
} from "../../utils";
|
||||||
import ParameterComponent from "./components/parameterComponent";
|
import ParameterComponent from "./components/parameterComponent";
|
||||||
import { typesContext } from "../../contexts/typesContext";
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
import {
|
import { useContext, useState, useEffect, useRef } from "react";
|
||||||
useContext,
|
|
||||||
useState,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
ForwardRefExoticComponent,
|
|
||||||
ComponentType,
|
|
||||||
SVGProps,
|
|
||||||
ReactNode,
|
|
||||||
} from "react";
|
|
||||||
import { NodeDataType } from "../../types/flow";
|
import { NodeDataType } from "../../types/flow";
|
||||||
import { alertContext } from "../../contexts/alertContext";
|
import { alertContext } from "../../contexts/alertContext";
|
||||||
import { PopUpContext } from "../../contexts/popUpContext";
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
|
@ -23,10 +14,8 @@ import NodeModal from "../../modals/NodeModal";
|
||||||
import Tooltip from "../../components/TooltipComponent";
|
import Tooltip from "../../components/TooltipComponent";
|
||||||
import { NodeToolbar } from "reactflow";
|
import { NodeToolbar } from "reactflow";
|
||||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||||
|
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||||
import { useSSE } from "../../contexts/SSEContext";
|
import { useSSE } from "../../contexts/SSEContext";
|
||||||
import { ReactElement } from "react-markdown/lib/react-markdown";
|
|
||||||
|
|
||||||
export default function GenericNode({
|
export default function GenericNode({
|
||||||
data,
|
data,
|
||||||
|
|
@ -46,6 +35,7 @@ export default function GenericNode({
|
||||||
const [validationStatus, setValidationStatus] = useState(null);
|
const [validationStatus, setValidationStatus] = useState(null);
|
||||||
// State for outline color
|
// State for outline color
|
||||||
const { sseData, isBuilding } = useSSE();
|
const { sseData, isBuilding } = useSSE();
|
||||||
|
const refHtml = useRef(null);
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// if (reactFlowInstance) {
|
// if (reactFlowInstance) {
|
||||||
|
|
@ -215,6 +205,7 @@ export default function GenericNode({
|
||||||
? toTitleCase(data.node.template[t].name)
|
? toTitleCase(data.node.template[t].name)
|
||||||
: toTitleCase(t)
|
: toTitleCase(t)
|
||||||
}
|
}
|
||||||
|
info={data.node.template[t].info}
|
||||||
name={t}
|
name={t}
|
||||||
tooltipTitle={data.node.template[t].type}
|
tooltipTitle={data.node.template[t].type}
|
||||||
required={data.node.template[t].required}
|
required={data.node.template[t].required}
|
||||||
|
|
|
||||||
56
src/frontend/src/components/AccordionComponent/index.tsx
Normal file
56
src/frontend/src/components/AccordionComponent/index.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { ReactElement, useContext, useEffect, useRef, useState } from "react";
|
||||||
|
import {
|
||||||
|
AccordionComponentType,
|
||||||
|
ProgressBarType,
|
||||||
|
} from "../../types/components";
|
||||||
|
import { Progress } from "../../components/ui/progress";
|
||||||
|
import { setInterval } from "timers/promises";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "../../components/ui/accordion";
|
||||||
|
|
||||||
|
export default function AccordionComponent({
|
||||||
|
trigger,
|
||||||
|
children,
|
||||||
|
open = [],
|
||||||
|
}: AccordionComponentType) {
|
||||||
|
const [value, setValue] = useState(
|
||||||
|
open.length == 0 ? "" : getOpenAccordion()
|
||||||
|
);
|
||||||
|
|
||||||
|
function getOpenAccordion() {
|
||||||
|
let value = "";
|
||||||
|
open.forEach((el) => {
|
||||||
|
if (el == trigger) {
|
||||||
|
value = trigger;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
value == "" ? setValue(trigger) : setValue("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Accordion type="single" value={value} onValueChange={setValue}>
|
||||||
|
<AccordionItem value={trigger} className="border-none">
|
||||||
|
<AccordionTrigger
|
||||||
|
onClick={() => {
|
||||||
|
handleClick();
|
||||||
|
}}
|
||||||
|
className="ml-3"
|
||||||
|
>
|
||||||
|
{trigger}
|
||||||
|
</AccordionTrigger>
|
||||||
|
<AccordionContent>{children}</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { ShadTooltipProps } from "../../types/components";
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
|
|
@ -5,18 +6,19 @@ import {
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "../ui/tooltip";
|
} from "../ui/tooltip";
|
||||||
|
|
||||||
const ShadTooltip = (props) => {
|
const ShadTooltip = ({
|
||||||
|
delayDuration = 500,
|
||||||
|
side,
|
||||||
|
content,
|
||||||
|
children,
|
||||||
|
}: ShadTooltipProps) => {
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip delayDuration={props.delayDuration}>
|
<Tooltip delayDuration={delayDuration}>
|
||||||
<TooltipTrigger asChild>{props.children}</TooltipTrigger>
|
<TooltipTrigger asChild>{children}</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent
|
<TooltipContent side={side} avoidCollisions={false} sticky="always">
|
||||||
side={props.side}
|
{content}
|
||||||
avoidCollisions={false}
|
|
||||||
sticky="always"
|
|
||||||
>
|
|
||||||
{props.content}
|
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ import { useState } from "react";
|
||||||
import { ChatMessageType } from "../../../types/chat";
|
import { ChatMessageType } from "../../../types/chat";
|
||||||
import { nodeColors } from "../../../utils";
|
import { nodeColors } from "../../../utils";
|
||||||
import Convert from "ansi-to-html";
|
import Convert from "ansi-to-html";
|
||||||
const convert = new Convert({ newline: true });
|
|
||||||
import { MessageCircle } from "lucide-react";
|
import { MessageCircle } from "lucide-react";
|
||||||
|
import DOMPurify from "dompurify";
|
||||||
|
const convert = new Convert({ newline: true });
|
||||||
export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
||||||
const [hidden, setHidden] = useState(true);
|
const [hidden, setHidden] = useState(true);
|
||||||
return (
|
return (
|
||||||
|
|
@ -23,13 +23,14 @@ export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
||||||
<MessageCircle className="w-5 h-5 animate-bounce" />
|
<MessageCircle className="w-5 h-5 animate-bounce" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{chat.thought && chat.thought !== "" && !hidden && (
|
{chat.thought && chat.thought !== "" && !hidden && (
|
||||||
<div
|
<div
|
||||||
onClick={() => setHidden((prev) => !prev)}
|
onClick={() => setHidden((prev) => !prev)}
|
||||||
style={{ backgroundColor: nodeColors["thought"] }}
|
style={{ backgroundColor: nodeColors["thought"] }}
|
||||||
className=" text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer"
|
className="text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: convert.toHtml(chat.thought),
|
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ export default function CodeAreaComponent({
|
||||||
disabled,
|
disabled,
|
||||||
editNode = false,
|
editNode = false,
|
||||||
}: TextAreaComponentType) {
|
}: TextAreaComponentType) {
|
||||||
const [myValue, setMyValue] = useState(value);
|
const [myValue, setMyValue] = useState(
|
||||||
|
typeof value == "string" ? value : JSON.stringify(value)
|
||||||
|
);
|
||||||
const { openPopUp } = useContext(PopUpContext);
|
const { openPopUp } = useContext(PopUpContext);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
@ -22,7 +24,7 @@ export default function CodeAreaComponent({
|
||||||
}, [disabled, onChange]);
|
}, [disabled, onChange]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMyValue(value);
|
setMyValue(typeof value == "string" ? value : JSON.stringify(value));
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import { Listbox, Transition } from "@headlessui/react";
|
import { Listbox, Transition } from "@headlessui/react";
|
||||||
import { Fragment, useEffect, useState } from "react";
|
import { Fragment, useContext, useEffect, useState } from "react";
|
||||||
import { DropDownComponentType } from "../../types/components";
|
import { DropDownComponentType } from "../../types/components";
|
||||||
import { classNames } from "../../utils";
|
import { classNames } from "../../utils";
|
||||||
import { INPUT_STYLE } from "../../constants";
|
import { INPUT_STYLE } from "../../constants";
|
||||||
import { ChevronsUpDown, Check } from "lucide-react";
|
import { ChevronsUpDown, Check } from "lucide-react";
|
||||||
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
import { TabsContext } from "../../contexts/tabsContext";
|
||||||
|
|
||||||
export default function Dropdown({
|
export default function Dropdown({
|
||||||
value,
|
value,
|
||||||
|
|
@ -11,13 +13,17 @@ export default function Dropdown({
|
||||||
onSelect,
|
onSelect,
|
||||||
editNode = false,
|
editNode = false,
|
||||||
numberOfOptions = 0,
|
numberOfOptions = 0,
|
||||||
|
apiModal = false,
|
||||||
}: DropDownComponentType) {
|
}: DropDownComponentType) {
|
||||||
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
|
|
||||||
let [internalValue, setInternalValue] = useState(
|
let [internalValue, setInternalValue] = useState(
|
||||||
value === "" || !value ? "Choose an option" : value
|
value === "" || !value ? "Choose an option" : value
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setInternalValue(value === "" || !value ? "Choose an option" : value);
|
setInternalValue(value === "" || !value ? "Choose an option" : value);
|
||||||
}, [value]);
|
}, [closePopUp]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -63,11 +69,12 @@ export default function Dropdown({
|
||||||
leaveTo="opacity-0"
|
leaveTo="opacity-0"
|
||||||
>
|
>
|
||||||
<Listbox.Options
|
<Listbox.Options
|
||||||
className={
|
className={classNames(
|
||||||
editNode
|
editNode
|
||||||
? "absolute z-10 mt-1 max-h-60 overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm w-[215px]"
|
? "z-10 mt-1 max-h-60 overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm w-[215px]"
|
||||||
: "nowheel absolute z-10 mt-1 max-h-60 w-full overflow-auto overflow-y rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm "
|
: "nowheel z-10 mt-1 max-h-60 w-full overflow-auto overflow-y rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm ",
|
||||||
}
|
apiModal ? "w-[250px] mb-2" : "absolute"
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{options.map((option, id) => (
|
{options.map((option, id) => (
|
||||||
<Listbox.Option
|
<Listbox.Option
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { useContext, useEffect, useState } from "react";
|
||||||
import { FloatComponentType } from "../../types/components";
|
import { FloatComponentType } from "../../types/components";
|
||||||
import { TabsContext } from "../../contexts/tabsContext";
|
import { TabsContext } from "../../contexts/tabsContext";
|
||||||
import { INPUT_STYLE } from "../../constants";
|
import { INPUT_STYLE } from "../../constants";
|
||||||
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
|
||||||
export default function FloatComponent({
|
export default function FloatComponent({
|
||||||
value,
|
value,
|
||||||
|
|
@ -12,6 +13,7 @@ export default function FloatComponent({
|
||||||
}: FloatComponentType) {
|
}: FloatComponentType) {
|
||||||
const [myValue, setMyValue] = useState(value ?? "");
|
const [myValue, setMyValue] = useState(value ?? "");
|
||||||
const { setDisableCopyPaste } = useContext(TabsContext);
|
const { setDisableCopyPaste } = useContext(TabsContext);
|
||||||
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
|
|
||||||
const step = 0.1;
|
const step = 0.1;
|
||||||
const min = 0;
|
const min = 0;
|
||||||
|
|
@ -26,7 +28,7 @@ export default function FloatComponent({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMyValue(value);
|
setMyValue(value);
|
||||||
}, [value]);
|
}, [closePopUp]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ export default function InputFileComponent({
|
||||||
disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"
|
disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="w-full flex items-center gap-2">
|
<div className="w-full flex items-center">
|
||||||
<span
|
<span
|
||||||
onClick={handleButtonClick}
|
onClick={handleButtonClick}
|
||||||
className={
|
className={
|
||||||
|
|
@ -114,7 +114,7 @@ export default function InputFileComponent({
|
||||||
</span>
|
</span>
|
||||||
<button onClick={handleButtonClick}>
|
<button onClick={handleButtonClick}>
|
||||||
{!editNode && !loading && (
|
{!editNode && !loading && (
|
||||||
<FileSearch2 className="w-6 h-6 hover:text-ring" />
|
<FileSearch2 className="w-6 h-6 hover:text-ring ml-3" />
|
||||||
)}
|
)}
|
||||||
{!editNode && loading && (
|
{!editNode && loading && (
|
||||||
<span className="loading loading-spinner loading-sm pl-3 h-8 pointer-events-none"></span>
|
<span className="loading loading-spinner loading-sm pl-3 h-8 pointer-events-none"></span>
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,29 @@ import { TabsContext } from "../../contexts/tabsContext";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { INPUT_STYLE } from "../../constants";
|
import { INPUT_STYLE } from "../../constants";
|
||||||
import { X, Plus } from "lucide-react";
|
import { X, Plus } from "lucide-react";
|
||||||
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
|
||||||
export default function InputListComponent({
|
export default function InputListComponent({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
disabled,
|
disabled,
|
||||||
editNode = false,
|
editNode = false,
|
||||||
|
onAddInput,
|
||||||
}: InputListComponentType) {
|
}: InputListComponentType) {
|
||||||
const [inputList, setInputList] = useState(value ?? [""]);
|
const [inputList, setInputList] = useState(value ?? [""]);
|
||||||
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
setInputList([""]);
|
setInputList([""]);
|
||||||
onChange([""]);
|
onChange([""]);
|
||||||
}
|
}
|
||||||
}, [disabled, onChange]);
|
}, [disabled, onChange]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInputList(value);
|
||||||
|
}, [closePopUp]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
|
|
@ -44,9 +53,9 @@ export default function InputListComponent({
|
||||||
setInputList((old) => {
|
setInputList((old) => {
|
||||||
let newInputList = _.cloneDeep(old);
|
let newInputList = _.cloneDeep(old);
|
||||||
newInputList[idx] = e.target.value;
|
newInputList[idx] = e.target.value;
|
||||||
|
onChange(newInputList);
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
onChange(inputList);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{idx === inputList.length - 1 ? (
|
{idx === inputList.length - 1 ? (
|
||||||
|
|
@ -55,6 +64,7 @@ export default function InputListComponent({
|
||||||
setInputList((old) => {
|
setInputList((old) => {
|
||||||
let newInputList = _.cloneDeep(old);
|
let newInputList = _.cloneDeep(old);
|
||||||
newInputList.push("");
|
newInputList.push("");
|
||||||
|
onAddInput(newInputList);
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
onChange(inputList);
|
onChange(inputList);
|
||||||
|
|
@ -68,6 +78,7 @@ export default function InputListComponent({
|
||||||
setInputList((old) => {
|
setInputList((old) => {
|
||||||
let newInputList = _.cloneDeep(old);
|
let newInputList = _.cloneDeep(old);
|
||||||
newInputList.splice(idx, 1);
|
newInputList.splice(idx, 1);
|
||||||
|
onAddInput(newInputList);
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
onChange(inputList);
|
onChange(inputList);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { FloatComponentType } from "../../types/components";
|
||||||
import { TabsContext } from "../../contexts/tabsContext";
|
import { TabsContext } from "../../contexts/tabsContext";
|
||||||
import { classNames } from "../../utils";
|
import { classNames } from "../../utils";
|
||||||
import { INPUT_STYLE } from "../../constants";
|
import { INPUT_STYLE } from "../../constants";
|
||||||
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
|
||||||
export default function IntComponent({
|
export default function IntComponent({
|
||||||
value,
|
value,
|
||||||
|
|
@ -14,6 +15,7 @@ export default function IntComponent({
|
||||||
const [myValue, setMyValue] = useState(value ?? "");
|
const [myValue, setMyValue] = useState(value ?? "");
|
||||||
const { setDisableCopyPaste } = useContext(TabsContext);
|
const { setDisableCopyPaste } = useContext(TabsContext);
|
||||||
const min = 0;
|
const min = 0;
|
||||||
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
@ -24,7 +26,7 @@ export default function IntComponent({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMyValue(value);
|
setMyValue(value);
|
||||||
}, [value]);
|
}, [closePopUp]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export default function PromptAreaComponent({
|
||||||
disabled ? "pointer-events-none cursor-not-allowed w-full" : " w-full"
|
disabled ? "pointer-events-none cursor-not-allowed w-full" : " w-full"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="w-full flex items-center gap-3">
|
<div className="w-full flex items-center">
|
||||||
<span
|
<span
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
openPopUp(
|
openPopUp(
|
||||||
|
|
|
||||||
59
src/frontend/src/components/ui/accordion.tsx
Normal file
59
src/frontend/src/components/ui/accordion.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
||||||
|
import { ChevronDownIcon } from "@radix-ui/react-icons";
|
||||||
|
import { cn } from "../../utils";
|
||||||
|
|
||||||
|
const Accordion = AccordionPrimitive.Root;
|
||||||
|
|
||||||
|
const AccordionItem = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Item>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Item
|
||||||
|
ref={ref}
|
||||||
|
className={cn("border-b", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
AccordionItem.displayName = "AccordionItem";
|
||||||
|
|
||||||
|
const AccordionTrigger = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Header className="flex">
|
||||||
|
<AccordionPrimitive.Trigger
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<ChevronDownIcon className="h-4 w-4 text-muted-foreground transition-transform duration-200" />
|
||||||
|
</AccordionPrimitive.Trigger>
|
||||||
|
</AccordionPrimitive.Header>
|
||||||
|
));
|
||||||
|
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
|
||||||
|
|
||||||
|
const AccordionContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div className="pb-4 pt-0">{children}</div>
|
||||||
|
</AccordionPrimitive.Content>
|
||||||
|
));
|
||||||
|
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
||||||
|
|
@ -54,7 +54,7 @@ export const TEXT_DIALOG_SUBTITLE = "Edit your text.";
|
||||||
* @param {string} flowId - The id of the flow
|
* @param {string} flowId - The id of the flow
|
||||||
* @returns {string} - The python code
|
* @returns {string} - The python code
|
||||||
*/
|
*/
|
||||||
export const getPythonApiCode = (flow: FlowType): string => {
|
export const getPythonApiCode = (flow: FlowType, tweak?): string => {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
|
|
||||||
// create a dictionary of node ids and the values is an empty dictionary
|
// create a dictionary of node ids and the values is an empty dictionary
|
||||||
|
|
@ -70,7 +70,11 @@ BASE_API_URL = "${window.location.protocol}//${
|
||||||
FLOW_ID = "${flowId}"
|
FLOW_ID = "${flowId}"
|
||||||
# You can tweak the flow by adding a tweaks dictionary
|
# You can tweak the flow by adding a tweaks dictionary
|
||||||
# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}}
|
# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}}
|
||||||
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
|
TWEAKS = ${
|
||||||
|
tweak && tweak.length > 0
|
||||||
|
? buildTweakObject(tweak)
|
||||||
|
: JSON.stringify(tweaks, null, 2)
|
||||||
|
}
|
||||||
|
|
||||||
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
||||||
"""
|
"""
|
||||||
|
|
@ -100,7 +104,7 @@ print(run_flow("Your message", flow_id=FLOW_ID, tweaks=TWEAKS))`;
|
||||||
* @param {string} flowId - The id of the flow
|
* @param {string} flowId - The id of the flow
|
||||||
* @returns {string} - The curl code
|
* @returns {string} - The curl code
|
||||||
*/
|
*/
|
||||||
export const getCurlCode = (flow: FlowType): string => {
|
export const getCurlCode = (flow: FlowType, tweak?): string => {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
const tweaks = buildTweaks(flow);
|
const tweaks = buildTweaks(flow);
|
||||||
return `curl -X POST \\
|
return `curl -X POST \\
|
||||||
|
|
@ -108,27 +112,46 @@ export const getCurlCode = (flow: FlowType): string => {
|
||||||
window.location.host
|
window.location.host
|
||||||
}/api/v1/process/${flowId} \\
|
}/api/v1/process/${flowId} \\
|
||||||
-H 'Content-Type: application/json' \\
|
-H 'Content-Type: application/json' \\
|
||||||
-d '{"inputs": {"input": message}, "tweaks": ${JSON.stringify(
|
-d '{"inputs": {"input": message}, "tweaks": ${
|
||||||
tweaks,
|
tweak && tweak.length > 0
|
||||||
null,
|
? buildTweakObject(tweak)
|
||||||
2
|
: JSON.stringify(tweaks, null, 2)
|
||||||
)}}'`;
|
}}'`;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Function to get the python code for the API
|
* Function to get the python code for the API
|
||||||
* @param {string} flowName - The name of the flow
|
* @param {string} flowName - The name of the flow
|
||||||
* @returns {string} - The python code
|
* @returns {string} - The python code
|
||||||
*/
|
*/
|
||||||
export const getPythonCode = (flow: FlowType): string => {
|
export const getPythonCode = (flow: FlowType, tweak?): string => {
|
||||||
const flowName = flow.name;
|
const flowName = flow.name;
|
||||||
const tweaks = buildTweaks(flow);
|
const tweaks = buildTweaks(flow);
|
||||||
return `from langflow import load_flow_from_json
|
return `from langflow import load_flow_from_json
|
||||||
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
|
TWEAKS = ${
|
||||||
|
tweak && tweak.length > 0
|
||||||
|
? buildTweakObject(tweak)
|
||||||
|
: JSON.stringify(tweaks, null, 2)
|
||||||
|
}
|
||||||
flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS)
|
flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS)
|
||||||
# Now you can use it like any chain
|
# Now you can use it like any chain
|
||||||
flow("Hey, have you heard of LangFlow?")`;
|
flow("Hey, have you heard of LangFlow?")`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function buildTweakObject(tweak) {
|
||||||
|
tweak.forEach((el) => {
|
||||||
|
Object.keys(el).forEach((key) => {
|
||||||
|
for (let kp in el[key]) {
|
||||||
|
try {
|
||||||
|
el[key][kp] = JSON.parse(el[key][kp]);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const tweakString = JSON.stringify(tweak, null, 2);
|
||||||
|
return tweakString;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base text for subtitle of Import Dialog
|
* The base text for subtitle of Import Dialog
|
||||||
* @constant
|
* @constant
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import React, { useState } from "react";
|
||||||
export const PopUpContext = createContext({
|
export const PopUpContext = createContext({
|
||||||
openPopUp: (popUpElement: JSX.Element) => {},
|
openPopUp: (popUpElement: JSX.Element) => {},
|
||||||
closePopUp: () => {},
|
closePopUp: () => {},
|
||||||
|
setCloseEdit: (value: string) => {},
|
||||||
|
closeEdit: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
interface PopUpProviderProps {
|
interface PopUpProviderProps {
|
||||||
|
|
@ -22,8 +24,12 @@ const PopUpProvider = ({ children }: PopUpProviderProps) => {
|
||||||
setPopUpElements((prevPopUps) => prevPopUps.slice(1));
|
setPopUpElements((prevPopUps) => prevPopUps.slice(1));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [closeEdit, setCloseEdit] = useState("");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PopUpContext.Provider value={{ openPopUp, closePopUp }}>
|
<PopUpContext.Provider
|
||||||
|
value={{ openPopUp, closePopUp, closeEdit, setCloseEdit }}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
{popUpElements[0]}
|
{popUpElements[0]}
|
||||||
</PopUpContext.Provider>
|
</PopUpContext.Provider>
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ const TabsContextInitialValue: TabsContextType = {
|
||||||
tabsState: {},
|
tabsState: {},
|
||||||
setTabsState: (state: TabsState) => {},
|
setTabsState: (state: TabsState) => {},
|
||||||
getNodeId: (nodeType: string) => "",
|
getNodeId: (nodeType: string) => "",
|
||||||
|
setTweak: (tweak: any) => {},
|
||||||
|
getTweak: {},
|
||||||
paste: (
|
paste: (
|
||||||
selection: { nodes: any; edges: any },
|
selection: { nodes: any; edges: any },
|
||||||
position: { x: number; y: number; paneX?: number; paneY?: number }
|
position: { x: number; y: number; paneX?: number; paneY?: number }
|
||||||
|
|
@ -73,6 +75,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
const { templates, reactFlowInstance } = useContext(typesContext);
|
const { templates, reactFlowInstance } = useContext(typesContext);
|
||||||
const [lastCopiedSelection, setLastCopiedSelection] = useState(null);
|
const [lastCopiedSelection, setLastCopiedSelection] = useState(null);
|
||||||
const [tabsState, setTabsState] = useState<TabsState>({});
|
const [tabsState, setTabsState] = useState<TabsState>({});
|
||||||
|
const [getTweak, setTweak] = useState({});
|
||||||
|
|
||||||
const newNodeId = useRef(uid());
|
const newNodeId = useRef(uid());
|
||||||
function incrementNodeId() {
|
function incrementNodeId() {
|
||||||
|
|
@ -198,10 +201,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
edge.style = { stroke: "#555555" };
|
edge.style = { stroke: "#555555" };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDisplay_name(node: NodeType, template: APIClassType) {
|
function updateDisplay_name(node: NodeType, template: APIClassType) {
|
||||||
node.data.node.display_name = template["display_name"]
|
node.data.node.display_name = template["display_name"] || node.data.type;
|
||||||
? template["display_name"]
|
}
|
||||||
: node.data.type;
|
|
||||||
|
function updateNodeDocumentation(node: NodeType, template: APIClassType) {
|
||||||
|
node.data.node.documentation = template["documentation"];
|
||||||
}
|
}
|
||||||
|
|
||||||
function processFlowNodes(flow) {
|
function processFlowNodes(flow) {
|
||||||
|
|
@ -218,6 +224,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
updateNodeEdges(flow, node, template);
|
updateNodeEdges(flow, node, template);
|
||||||
updateNodeDescription(node, template);
|
updateNodeDescription(node, template);
|
||||||
updateNodeTemplate(node, template);
|
updateNodeTemplate(node, template);
|
||||||
|
updateNodeDocumentation(node, template);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -410,7 +417,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
y: insidePosition.y + n.position.y - minimumY,
|
y: insidePosition.y + n.position.y - minimumY,
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
...n.data,
|
..._.cloneDeep(n.data),
|
||||||
id: newId,
|
id: newId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -640,6 +647,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
tabsState,
|
tabsState,
|
||||||
setTabsState,
|
setTabsState,
|
||||||
paste,
|
paste,
|
||||||
|
getTweak,
|
||||||
|
setTweak,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ export async function getBuildStatus(
|
||||||
export async function postBuildInit(
|
export async function postBuildInit(
|
||||||
flow: FlowType
|
flow: FlowType
|
||||||
): Promise<AxiosResponse<InitTypeAPI>> {
|
): Promise<AxiosResponse<InitTypeAPI>> {
|
||||||
return await axios.post(`/api/v1/build/init`, flow);
|
return await axios.post(`/api/v1/build/init/${flow.id}`, flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch(`/upload/${id}`, {
|
// fetch(`/upload/${id}`, {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useEffect, useRef, useState } from "react";
|
||||||
import { PopUpContext } from "../../contexts/popUpContext";
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
import "ace-builds/src-noconflict/mode-python";
|
import "ace-builds/src-noconflict/mode-python";
|
||||||
import "ace-builds/src-noconflict/theme-github";
|
import "ace-builds/src-noconflict/theme-github";
|
||||||
|
|
@ -26,14 +26,42 @@ import {
|
||||||
TabsTrigger,
|
TabsTrigger,
|
||||||
} from "../../components/ui/tabs";
|
} from "../../components/ui/tabs";
|
||||||
import { Check, Clipboard, Code2 } from "lucide-react";
|
import { Check, Clipboard, Code2 } from "lucide-react";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCaption,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "../../components/ui/table";
|
||||||
|
import { buildTweaks, classNames, limitScrollFieldsModal } from "../../utils";
|
||||||
|
import AccordionComponent from "../../components/AccordionComponent";
|
||||||
|
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||||
|
import Dropdown from "../../components/dropdownComponent";
|
||||||
|
import FloatComponent from "../../components/floatComponent";
|
||||||
|
import InputComponent from "../../components/inputComponent";
|
||||||
|
import InputFileComponent from "../../components/inputFileComponent";
|
||||||
|
import InputListComponent from "../../components/inputListComponent";
|
||||||
|
import IntComponent from "../../components/intComponent";
|
||||||
|
import PromptAreaComponent from "../../components/promptComponent";
|
||||||
|
import TextAreaComponent from "../../components/textAreaComponent";
|
||||||
|
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||||
|
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||||
|
import { cloneDeep, filter } from "lodash";
|
||||||
|
import { TabsContext } from "../../contexts/tabsContext";
|
||||||
|
|
||||||
export default function ApiModal({ flow }: { flow: FlowType }) {
|
export default function ApiModal({ flow }: { flow: FlowType }) {
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
const { dark } = useContext(darkContext);
|
const { dark } = useContext(darkContext);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp, closeEdit, setCloseEdit } = useContext(PopUpContext);
|
||||||
const [activeTab, setActiveTab] = useState("0");
|
const [activeTab, setActiveTab] = useState("0");
|
||||||
const [isCopied, setIsCopied] = useState<Boolean>(false);
|
const [isCopied, setIsCopied] = useState<Boolean>(false);
|
||||||
|
const [enabled, setEnabled] = useState(null);
|
||||||
|
const [openAccordion, setOpenAccordion] = useState([]);
|
||||||
|
const tweak = useRef([]);
|
||||||
|
const tweaksList = useRef([]);
|
||||||
|
const { setTweak, getTweak } = useContext(TabsContext);
|
||||||
const copyToClipboard = () => {
|
const copyToClipboard = () => {
|
||||||
if (!navigator.clipboard || !navigator.clipboard.writeText) {
|
if (!navigator.clipboard || !navigator.clipboard.writeText) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -47,18 +75,10 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
function setModalOpen(x: boolean) {
|
const pythonApiCode = getPythonApiCode(flow, tweak.current);
|
||||||
setOpen(x);
|
const curl_code = getCurlCode(flow, tweak.current);
|
||||||
if (x === false) {
|
const pythonCode = getPythonCode(flow, tweak.current);
|
||||||
closePopUp();
|
const tweaksCode = buildTweaks(flow);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pythonApiCode = getPythonApiCode(flow);
|
|
||||||
|
|
||||||
const curl_code = getCurlCode(flow);
|
|
||||||
const pythonCode = getPythonCode(flow);
|
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
name: "cURL",
|
name: "cURL",
|
||||||
|
|
@ -80,10 +100,169 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
||||||
code: pythonCode,
|
code: pythonCode,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (closeEdit !== "") {
|
||||||
|
tweak.current = getTweak;
|
||||||
|
if (tweak.current.length > 0) {
|
||||||
|
setActiveTab("3");
|
||||||
|
openAccordions();
|
||||||
|
} else {
|
||||||
|
startTweaks();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startTweaks();
|
||||||
|
}
|
||||||
|
}, [closeEdit]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
filterNodes();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (Object.keys(tweaksCode).length > 0) {
|
||||||
|
tabs.push({
|
||||||
|
name: "Tweaks",
|
||||||
|
mode: "python",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
code: pythonCode,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setModalOpen(x: boolean) {
|
||||||
|
setOpen(x);
|
||||||
|
if (x === false) {
|
||||||
|
setCloseEdit("");
|
||||||
|
setTweak([]);
|
||||||
|
closePopUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTweaks() {
|
||||||
|
tweak.current.push(buildTweaks(flow));
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterNodes() {
|
||||||
|
let arrNodesWithValues = [];
|
||||||
|
|
||||||
|
flow["data"]["nodes"].forEach((t) => {
|
||||||
|
Object.keys(t["data"]["node"]["template"])
|
||||||
|
.filter(
|
||||||
|
(n) =>
|
||||||
|
n.charAt(0) !== "_" &&
|
||||||
|
t.data.node.template[n].show &&
|
||||||
|
(t.data.node.template[n].type === "str" ||
|
||||||
|
t.data.node.template[n].type === "bool" ||
|
||||||
|
t.data.node.template[n].type === "float" ||
|
||||||
|
t.data.node.template[n].type === "code" ||
|
||||||
|
t.data.node.template[n].type === "prompt" ||
|
||||||
|
t.data.node.template[n].type === "file" ||
|
||||||
|
t.data.node.template[n].type === "int")
|
||||||
|
)
|
||||||
|
.map((n, i) => {
|
||||||
|
arrNodesWithValues.push(t["id"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tweaksList.current = arrNodesWithValues.filter((value, index, self) => {
|
||||||
|
return self.indexOf(value) === index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTweakObject(tw, changes, template) {
|
||||||
|
if (template.type === "float") {
|
||||||
|
changes = parseFloat(changes);
|
||||||
|
}
|
||||||
|
if (template.type === "int") {
|
||||||
|
changes = parseInt(changes);
|
||||||
|
}
|
||||||
|
if (template.list === true && Array.isArray(changes)) {
|
||||||
|
changes = changes?.filter((x) => x !== "");
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingTweak = tweak.current.find((element) =>
|
||||||
|
element.hasOwnProperty(tw)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingTweak) {
|
||||||
|
existingTweak[tw][template["name"]] = changes;
|
||||||
|
|
||||||
|
if (existingTweak[tw][template["name"]] == template.value) {
|
||||||
|
tweak.current.forEach((element) => {
|
||||||
|
if (element[tw] && Object.keys(element[tw])?.length === 0) {
|
||||||
|
tweak.current = tweak.current.filter((obj) => {
|
||||||
|
const prop = obj[Object.keys(obj)[0]].prop;
|
||||||
|
return prop !== undefined && prop !== null && prop !== "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const newTweak = {
|
||||||
|
[tw]: {
|
||||||
|
[template["name"]]: changes,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
tweak.current.push(newTweak);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pythonApiCode = getPythonApiCode(flow, tweak.current);
|
||||||
|
const curl_code = getCurlCode(flow, tweak.current);
|
||||||
|
const pythonCode = getPythonCode(flow, tweak.current);
|
||||||
|
|
||||||
|
tabs[0].code = curl_code;
|
||||||
|
tabs[1].code = pythonApiCode;
|
||||||
|
tabs[2].code = pythonCode;
|
||||||
|
|
||||||
|
setTweak(tweak.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildContent(value) {
|
||||||
|
const htmlContent = (
|
||||||
|
<div className="w-[200px]">
|
||||||
|
<span>{value != null && value != "" ? value : "None"}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
return htmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getValue(value, node, template) {
|
||||||
|
let returnValue = value ?? "";
|
||||||
|
|
||||||
|
if (getTweak.length > 0) {
|
||||||
|
for (const obj of getTweak) {
|
||||||
|
Object.keys(obj).forEach((key) => {
|
||||||
|
const value = obj[key];
|
||||||
|
if (key == node["id"]) {
|
||||||
|
Object.keys(value).forEach((key) => {
|
||||||
|
if (key == template["name"]) {
|
||||||
|
returnValue = value[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return value ?? "";
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAccordions() {
|
||||||
|
let accordionsToOpen = [];
|
||||||
|
tweak.current.forEach((el) => {
|
||||||
|
Object.keys(el).forEach((key) => {
|
||||||
|
if (Object.keys(el[key]).length > 0) {
|
||||||
|
accordionsToOpen.push(key);
|
||||||
|
setOpenAccordion(accordionsToOpen);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={true} onOpenChange={setModalOpen}>
|
<Dialog open={true} onOpenChange={setModalOpen}>
|
||||||
<DialogTrigger></DialogTrigger>
|
<DialogTrigger></DialogTrigger>
|
||||||
<DialogContent className="lg:max-w-[800px] sm:max-w-[600px] h-[580px]">
|
<DialogContent className="lg:max-w-[850px] sm:max-w-[700px] h-[580px]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="flex items-center">
|
<DialogTitle className="flex items-center">
|
||||||
<span className="pr-2">Code</span>
|
<span className="pr-2">Code</span>
|
||||||
|
|
@ -93,9 +272,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue={"0"}
|
value={activeTab}
|
||||||
className="w-full h-full overflow-hidden text-center bg-muted rounded-md border"
|
className="w-full h-full overflow-hidden text-center bg-muted rounded-md border"
|
||||||
onValueChange={(value) => setActiveTab(value)}
|
onValueChange={(value) => {
|
||||||
|
setActiveTab(value);
|
||||||
|
if (value === "3") {
|
||||||
|
openAccordions();
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between px-2">
|
<div className="flex items-center justify-between px-2">
|
||||||
<TabsList>
|
<TabsList>
|
||||||
|
|
@ -120,14 +304,448 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
||||||
<TabsContent
|
<TabsContent
|
||||||
value={index.toString()}
|
value={index.toString()}
|
||||||
className="overflow-hidden w-full h-full px-4 pb-4 -mt-1"
|
className="overflow-hidden w-full h-full px-4 pb-4 -mt-1"
|
||||||
|
key={index} // Remember to add a unique key prop
|
||||||
>
|
>
|
||||||
<SyntaxHighlighter
|
{index < 3 ? (
|
||||||
className="h-[400px] w-full overflow-auto"
|
<SyntaxHighlighter
|
||||||
language={tab.mode}
|
className="h-[400px] w-full overflow-auto"
|
||||||
style={oneDark}
|
language={tab.mode}
|
||||||
>
|
style={oneDark}
|
||||||
{tab.code}
|
>
|
||||||
</SyntaxHighlighter>
|
{tab.code}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
) : index === 3 ? (
|
||||||
|
<>
|
||||||
|
<div className="flex w-full h-[400px] mt-2">
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
"w-full rounded-lg bg-muted border-[1px] border-gray-200",
|
||||||
|
1 == 1
|
||||||
|
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||||
|
: "overflow-hidden"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{flow["data"]["nodes"].map((t: any, index) => (
|
||||||
|
<div className="px-3" key={index}>
|
||||||
|
{tweaksList.current.includes(t["data"]["id"]) && (
|
||||||
|
<AccordionComponent
|
||||||
|
trigger={t["data"]["id"]}
|
||||||
|
open={openAccordion}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-5 h-fit">
|
||||||
|
<Table className="table-fixed bg-muted outline-1">
|
||||||
|
<TableHeader className="border-gray-200 text-gray-500 text-xs font-medium h-10">
|
||||||
|
<TableRow className="dark:border-b-muted">
|
||||||
|
<TableHead className="h-7 text-center">
|
||||||
|
PARAM
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="p-0 h-7 text-center">
|
||||||
|
VALUE
|
||||||
|
</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody className="p-0">
|
||||||
|
{Object.keys(t["data"]["node"]["template"])
|
||||||
|
.filter(
|
||||||
|
(n) =>
|
||||||
|
n.charAt(0) !== "_" &&
|
||||||
|
t.data.node.template[n].show &&
|
||||||
|
(t.data.node.template[n].type ===
|
||||||
|
"str" ||
|
||||||
|
t.data.node.template[n].type ===
|
||||||
|
"bool" ||
|
||||||
|
t.data.node.template[n].type ===
|
||||||
|
"float" ||
|
||||||
|
t.data.node.template[n].type ===
|
||||||
|
"code" ||
|
||||||
|
t.data.node.template[n].type ===
|
||||||
|
"prompt" ||
|
||||||
|
t.data.node.template[n].type ===
|
||||||
|
"file" ||
|
||||||
|
t.data.node.template[n].type ===
|
||||||
|
"int")
|
||||||
|
)
|
||||||
|
.map((n, i) => {
|
||||||
|
//console.log(t.data.node.template[n]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow
|
||||||
|
key={i}
|
||||||
|
className="h-10 dark:border-b-muted"
|
||||||
|
>
|
||||||
|
<TableCell className="p-0 text-center text-gray-900 text-sm">
|
||||||
|
{n}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="p-0 text-center text-gray-900 text-xs dark:text-gray-300">
|
||||||
|
<div className="w-[250px] m-auto">
|
||||||
|
{t.data.node.template[n]
|
||||||
|
.type === "str" &&
|
||||||
|
!t.data.node.template[n]
|
||||||
|
.options ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
{t.data.node.template[n]
|
||||||
|
.list ? (
|
||||||
|
<InputListComponent
|
||||||
|
editNode={true}
|
||||||
|
disabled={false}
|
||||||
|
value={
|
||||||
|
!t.data.node.template[
|
||||||
|
n
|
||||||
|
].value ||
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].value === ""
|
||||||
|
? [""]
|
||||||
|
: t.data.node
|
||||||
|
.template[n]
|
||||||
|
.value
|
||||||
|
}
|
||||||
|
onChange={(k) => {}}
|
||||||
|
onAddInput={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node
|
||||||
|
.template[n]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.multiline ? (
|
||||||
|
<ShadTooltip
|
||||||
|
delayDuration={1000}
|
||||||
|
content={buildContent(
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].value
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<TextAreaComponent
|
||||||
|
disabled={false}
|
||||||
|
editNode={true}
|
||||||
|
value={getValue(
|
||||||
|
t.data.node
|
||||||
|
.template[n]
|
||||||
|
.value,
|
||||||
|
t.data,
|
||||||
|
t.data.node
|
||||||
|
.template[n]
|
||||||
|
)}
|
||||||
|
onChange={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node
|
||||||
|
.template[n]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ShadTooltip>
|
||||||
|
) : (
|
||||||
|
<InputComponent
|
||||||
|
editNode={true}
|
||||||
|
disabled={false}
|
||||||
|
password={
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].password ?? false
|
||||||
|
}
|
||||||
|
value={getValue(
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
]
|
||||||
|
)}
|
||||||
|
onChange={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node
|
||||||
|
.template[n]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "bool" ? (
|
||||||
|
<div className="ml-auto">
|
||||||
|
{" "}
|
||||||
|
<ToggleShadComponent
|
||||||
|
enabled={
|
||||||
|
t.data.node.template[n]
|
||||||
|
.value
|
||||||
|
}
|
||||||
|
setEnabled={(e) => {
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].value = e;
|
||||||
|
setEnabled(e);
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
e,
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
disabled={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "file" ? (
|
||||||
|
<ShadTooltip
|
||||||
|
delayDuration={1000}
|
||||||
|
content={buildContent(
|
||||||
|
getValue(
|
||||||
|
t.data.node.template[n]
|
||||||
|
.value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[n]
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="mx-auto">
|
||||||
|
<InputFileComponent
|
||||||
|
editNode={true}
|
||||||
|
disabled={false}
|
||||||
|
value={
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(
|
||||||
|
k: any
|
||||||
|
) => {}}
|
||||||
|
fileTypes={
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].fileTypes
|
||||||
|
}
|
||||||
|
suffixes={
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].suffixes
|
||||||
|
}
|
||||||
|
onFileChange={(
|
||||||
|
k: any
|
||||||
|
) => {}}
|
||||||
|
></InputFileComponent>
|
||||||
|
</div>
|
||||||
|
</ShadTooltip>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "float" ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<FloatComponent
|
||||||
|
disabled={false}
|
||||||
|
editNode={true}
|
||||||
|
value={getValue(
|
||||||
|
t.data.node.template[n]
|
||||||
|
.value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[n]
|
||||||
|
)}
|
||||||
|
onChange={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "str" &&
|
||||||
|
t.data.node.template[n]
|
||||||
|
.options ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<Dropdown
|
||||||
|
editNode={true}
|
||||||
|
apiModal={true}
|
||||||
|
options={
|
||||||
|
t.data.node.template[n]
|
||||||
|
.options
|
||||||
|
}
|
||||||
|
onSelect={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
value={getValue(
|
||||||
|
t.data.node.template[n]
|
||||||
|
.value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[n]
|
||||||
|
)}
|
||||||
|
></Dropdown>
|
||||||
|
</div>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "int" ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<IntComponent
|
||||||
|
disabled={false}
|
||||||
|
editNode={true}
|
||||||
|
value={getValue(
|
||||||
|
t.data.node.template[n]
|
||||||
|
.value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[n]
|
||||||
|
)}
|
||||||
|
onChange={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "prompt" ? (
|
||||||
|
<ShadTooltip
|
||||||
|
delayDuration={1000}
|
||||||
|
content={buildContent(
|
||||||
|
getValue(
|
||||||
|
t.data.node.template[n]
|
||||||
|
.value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[n]
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="mx-auto">
|
||||||
|
<PromptAreaComponent
|
||||||
|
editNode={true}
|
||||||
|
disabled={false}
|
||||||
|
value={getValue(
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
]
|
||||||
|
)}
|
||||||
|
onChange={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node
|
||||||
|
.template[n]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ShadTooltip>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "code" ? (
|
||||||
|
<ShadTooltip
|
||||||
|
delayDuration={1000}
|
||||||
|
content={buildContent(
|
||||||
|
getValue(
|
||||||
|
t.data.node.template[n]
|
||||||
|
.value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[n]
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="mx-auto">
|
||||||
|
<CodeAreaComponent
|
||||||
|
disabled={false}
|
||||||
|
editNode={true}
|
||||||
|
value={getValue(
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
].value,
|
||||||
|
t.data,
|
||||||
|
t.data.node.template[
|
||||||
|
n
|
||||||
|
]
|
||||||
|
)}
|
||||||
|
onChange={(k) => {
|
||||||
|
buildTweakObject(
|
||||||
|
t["data"]["id"],
|
||||||
|
k,
|
||||||
|
t.data.node
|
||||||
|
.template[n]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ShadTooltip>
|
||||||
|
) : t.data.node.template[n]
|
||||||
|
.type === "Any" ? (
|
||||||
|
"-"
|
||||||
|
) : (
|
||||||
|
<div className="hidden"></div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</AccordionComponent>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{tweaksList.current.length === 0 && (
|
||||||
|
<>
|
||||||
|
<div className="pt-3">
|
||||||
|
No tweaks are available for this flow.
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<div className="flex flex-col gap-5 bg-muted">
|
||||||
|
<Table className="table-fixed bg-muted outline-1">
|
||||||
|
<TableHeader className="border-gray-200 text-gray-500 text-xs font-medium h-10">
|
||||||
|
<TableRow className="dark:border-b-muted">
|
||||||
|
<TableHead className="h-5 text-center">
|
||||||
|
TWEAK
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="p-0 h-5 text-center">
|
||||||
|
VALUE
|
||||||
|
</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{invoices.map((invoice) => (
|
||||||
|
<TableRow className="p-0 text-center text-gray-900 text-sm">
|
||||||
|
<TableCell className="p-2 text-center text-gray-900 text-sm truncate">
|
||||||
|
{invoice.paymentStatus}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="p-2 text-center text-gray-900 text-sm truncate">
|
||||||
|
{invoice.paymentMethod}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
))}
|
))}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@ import {
|
||||||
classNames,
|
classNames,
|
||||||
limitScrollFieldsModal,
|
limitScrollFieldsModal,
|
||||||
nodeColors,
|
nodeColors,
|
||||||
nodeIcons,
|
nodeIconsLucide,
|
||||||
toNormalCase,
|
|
||||||
toTitleCase,
|
toTitleCase,
|
||||||
} from "../../utils";
|
} from "../../utils";
|
||||||
import { typesContext } from "../../contexts/typesContext";
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
|
|
@ -28,7 +27,7 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// any to avoid type conflict
|
// any to avoid type conflict
|
||||||
const Icon: any = nodeIcons[types[data.type]];
|
const Icon: any = nodeIconsLucide[types[data.type]];
|
||||||
return (
|
return (
|
||||||
<Transition.Root show={open} appear={true} as={Fragment}>
|
<Transition.Root show={open} appear={true} as={Fragment}>
|
||||||
<Dialog
|
<Dialog
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import remarkMath from "remark-math";
|
||||||
import { CodeBlock } from "./codeBlock";
|
import { CodeBlock } from "./codeBlock";
|
||||||
import Convert from "ansi-to-html";
|
import Convert from "ansi-to-html";
|
||||||
import { User2, MessageCircle } from "lucide-react";
|
import { User2, MessageCircle } from "lucide-react";
|
||||||
|
import DOMPurify from "dompurify";
|
||||||
export default function ChatMessage({
|
export default function ChatMessage({
|
||||||
chat,
|
chat,
|
||||||
lockChat,
|
lockChat,
|
||||||
|
|
@ -77,7 +77,7 @@ export default function ChatMessage({
|
||||||
className=" text-start inline-block rounded-md text-muted-foreground h-full border border-ring
|
className=" text-start inline-block rounded-md text-muted-foreground h-full border border-ring
|
||||||
bg-muted w-[95%] pb-3 pt-3 px-2 ml-3 cursor-pointer scrollbar-hide overflow-scroll"
|
bg-muted w-[95%] pb-3 pt-3 px-2 ml-3 cursor-pointer scrollbar-hide overflow-scroll"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: convert.toHtml(chat.thought),
|
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -148,12 +148,12 @@ export default function ChatMessage({
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full flex items-center">
|
<div className="w-full flex items-center">
|
||||||
<div className="text-start inline-block px-3 text-muted-foreground ">
|
<div className="text-start inline-block px-3 text-muted-foreground ">
|
||||||
<span
|
{message.split("\n").map((line, index) => (
|
||||||
className="text-muted-foreground "
|
<span key={index} className="text-muted-foreground ">
|
||||||
dangerouslySetInnerHTML={{
|
{line}
|
||||||
__html: message.replace(/\n/g, "<br>"),
|
<br />
|
||||||
}}
|
</span>
|
||||||
></span>
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,13 @@ export default function CodeAreaModal({
|
||||||
const [code, setCode] = useState(value);
|
const [code, setCode] = useState(value);
|
||||||
const { dark } = useContext(darkContext);
|
const { dark } = useContext(darkContext);
|
||||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
|
||||||
const ref = useRef();
|
const ref = useRef();
|
||||||
function setModalOpen(x: boolean) {
|
function setModalOpen(x: boolean) {
|
||||||
setOpen(x);
|
setOpen(x);
|
||||||
if (x === false) {
|
if (x === false) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
setCloseEdit("editcode");
|
||||||
closePopUp();
|
closePopUp();
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,12 @@ export default function GenericModal({
|
||||||
const [myValue, setMyValue] = useState(value);
|
const [myValue, setMyValue] = useState(value);
|
||||||
const { dark } = useContext(darkContext);
|
const { dark } = useContext(darkContext);
|
||||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
|
||||||
const ref = useRef();
|
const ref = useRef();
|
||||||
function setModalOpen(x: boolean) {
|
function setModalOpen(x: boolean) {
|
||||||
setOpen(x);
|
setOpen(x);
|
||||||
if (x === false) {
|
if (x === false) {
|
||||||
|
setCloseEdit("generic");
|
||||||
closePopUp();
|
closePopUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,13 @@ export default function PromptAreaModal({
|
||||||
const [myValue, setMyValue] = useState(value);
|
const [myValue, setMyValue] = useState(value);
|
||||||
const { dark } = useContext(darkContext);
|
const { dark } = useContext(darkContext);
|
||||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
|
||||||
const ref = useRef();
|
const ref = useRef();
|
||||||
function setModalOpen(x: boolean) {
|
function setModalOpen(x: boolean) {
|
||||||
setOpen(x);
|
setOpen(x);
|
||||||
if (x === false) {
|
if (x === false) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
setCloseEdit("prompt");
|
||||||
closePopUp();
|
closePopUp();
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,13 @@ export default function TextAreaModal({
|
||||||
}) {
|
}) {
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
const [myValue, setMyValue] = useState(value);
|
const [myValue, setMyValue] = useState(value);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
|
||||||
const ref = useRef();
|
const ref = useRef();
|
||||||
function setModalOpen(x: boolean) {
|
function setModalOpen(x: boolean) {
|
||||||
setOpen(x);
|
setOpen(x);
|
||||||
if (x === false) {
|
if (x === false) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
setCloseEdit("textarea");
|
||||||
closePopUp();
|
closePopUp();
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ export default function ExtraSidebar() {
|
||||||
return (
|
return (
|
||||||
<div className="w-52 flex flex-col overflow-hidden scrollbar-hide h-full border-r">
|
<div className="w-52 flex flex-col overflow-hidden scrollbar-hide h-full border-r">
|
||||||
<div className="mt-2 mb-2 w-full flex gap-2 justify-between px-2 items-center">
|
<div className="mt-2 mb-2 w-full flex gap-2 justify-between px-2 items-center">
|
||||||
<ShadTooltip delayDuration={1000} content="Import" side="top">
|
<ShadTooltip content="Import" side="top">
|
||||||
<button
|
<button
|
||||||
className="text-foreground w-full justify-center shadow-sm transition-all duration-500 ease-in-out relative inline-flex items-center rounded-md bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted"
|
className="text-foreground w-full justify-center shadow-sm transition-all duration-500 ease-in-out relative inline-flex items-center rounded-md bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -74,7 +74,7 @@ export default function ExtraSidebar() {
|
||||||
</button>
|
</button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
|
|
||||||
<ShadTooltip delayDuration={1000} content="Export" side="top">
|
<ShadTooltip content="Export" side="top">
|
||||||
<button
|
<button
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"text-foreground w-full justify-center shadow-sm transition-all duration-500 ease-in-out relative inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted rounded-md"
|
"text-foreground w-full justify-center shadow-sm transition-all duration-500 ease-in-out relative inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted rounded-md"
|
||||||
|
|
@ -86,7 +86,7 @@ export default function ExtraSidebar() {
|
||||||
<FileDown strokeWidth={1.5} className="w-5 h-5 "></FileDown>
|
<FileDown strokeWidth={1.5} className="w-5 h-5 "></FileDown>
|
||||||
</button>
|
</button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
<ShadTooltip delayDuration={1000} content="Code" side="top">
|
<ShadTooltip content="Code" side="top">
|
||||||
<button
|
<button
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"text-foreground w-full justify-center shadow-sm transition-all duration-500 ease-in-out relative inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted rounded-md"
|
"text-foreground w-full justify-center shadow-sm transition-all duration-500 ease-in-out relative inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted rounded-md"
|
||||||
|
|
@ -99,7 +99,7 @@ export default function ExtraSidebar() {
|
||||||
</button>
|
</button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
|
|
||||||
<ShadTooltip delayDuration={1000} content="Save" side="top">
|
<ShadTooltip content="Save" side="top">
|
||||||
<button
|
<button
|
||||||
className="text-foreground w-full justify-center transition-all shadow-sm duration-500 ease-in-out relative inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted rounded-md"
|
className="text-foreground w-full justify-center transition-all shadow-sm duration-500 ease-in-out relative inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-input hover:bg-muted rounded-md"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
|
|
@ -158,7 +158,6 @@ export default function ExtraSidebar() {
|
||||||
.map((t: string, k) => (
|
.map((t: string, k) => (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={data[d][t].display_name}
|
content={data[d][t].display_name}
|
||||||
delayDuration={1500}
|
|
||||||
side="right"
|
side="right"
|
||||||
key={data[d][t].display_name}
|
key={data[d][t].display_name}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { Settings2, Copy, Trash2, Menu } from "lucide-react";
|
import { Settings2, Copy, Trash2, FileText } from "lucide-react";
|
||||||
import { classNames } from "../../../../utils";
|
import { classNames } from "../../../../utils";
|
||||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||||
import { useReactFlow } from "reactflow";
|
import { useReactFlow } from "reactflow";
|
||||||
|
|
@ -30,23 +30,21 @@ const NodeToolbarComponent = (props) => {
|
||||||
<>
|
<>
|
||||||
<div className="h-10 w-26">
|
<div className="h-10 w-26">
|
||||||
<span className="isolate inline-flex rounded-md shadow-sm">
|
<span className="isolate inline-flex rounded-md shadow-sm">
|
||||||
<ShadTooltip delayDuration={1000} content="Delete" side="top">
|
<ShadTooltip content="Delete" side="top">
|
||||||
<button
|
<button
|
||||||
className="text-foreground transition-all duration-500 ease-in-out shadow-md relative inline-flex items-center rounded-l-md bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10"
|
className="text-foreground transition-all duration-500 ease-in-out shadow-md relative inline-flex items-center rounded-l-md bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.deleteNode(props.data.id);
|
props.deleteNode(props.data.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4 "></Trash2>
|
<Trash2 className="w-4 h-4" ></Trash2>
|
||||||
</button>
|
</button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
|
|
||||||
<ShadTooltip delayDuration={1000} content="Duplicate" side="top">
|
<ShadTooltip content="Duplicate" side="top">
|
||||||
<button
|
<button
|
||||||
className={classNames(
|
className={classNames(
|
||||||
nodeLength > 0
|
"text-foreground transition-all duration-500 ease-in-out shadow-md relative -ml-px inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10"
|
||||||
? "text-foreground transition-all duration-500 ease-in-out shadow-md relative -ml-px inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10"
|
|
||||||
: "text-foreground transition-all duration-500 ease-in-out shadow-md relative -ml-px inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10 rounded-r-md"
|
|
||||||
)}
|
)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -65,26 +63,62 @@ const NodeToolbarComponent = (props) => {
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Copy className="w-4 h-4 "></Copy>
|
<Copy className="w-4 h-4"></Copy>
|
||||||
</button>
|
</button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
|
|
||||||
{nodeLength > 0 && (
|
<ShadTooltip
|
||||||
<ShadTooltip delayDuration={1000} content="Edit" side="top">
|
content={
|
||||||
<button
|
props.data.node.documentation === ""
|
||||||
className="text-foreground transition-all duration-500 ease-in-out shadow-md relative -ml-px inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10 rounded-r-md"
|
? "Coming Soon"
|
||||||
onClick={(event) => {
|
: "Documentation"
|
||||||
|
}
|
||||||
|
side="top"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
className={classNames(
|
||||||
|
"text-foreground transition-all duration-500 ease-in-out shadow-md relative -ml-px inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10" +
|
||||||
|
(props.data.node.documentation === ""
|
||||||
|
? " text-muted-foreground"
|
||||||
|
: " text-foreground")
|
||||||
|
)}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={props.data.node.documentation}
|
||||||
|
// deactivate link if no documentation is provided
|
||||||
|
onClick={(event) => {
|
||||||
|
if (props.data.node.documentation === "") {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
props.openPopUp(<EditNodeModal data={props.data} />);
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Settings2 className="w-4 h-4 "></Settings2>
|
<FileText className="w-4 h-4 "></FileText>
|
||||||
</button>
|
</a>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* <Menu as="div" className="relative inline-block text-left z-100">
|
<ShadTooltip content="Edit" side="top">
|
||||||
<button className="text-gray-700 transition-all duration-500 ease-in-out shadow-md relative -ml-px inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md">
|
<button
|
||||||
|
className={classNames(
|
||||||
|
"text-foreground transition-all duration-500 ease-in-out shadow-md relative -ml-px inline-flex items-center bg-background px-2 py-2 ring-1 ring-inset ring-ring hover:bg-muted focus:z-10 rounded-r-md" +
|
||||||
|
(nodeLength == 0
|
||||||
|
? " text-muted-foreground"
|
||||||
|
: " text-foreground")
|
||||||
|
)}
|
||||||
|
onClick={(event) => {
|
||||||
|
if (nodeLength == 0) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
props.openPopUp(<EditNodeModal data={props.data} />);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Settings2 className="w-4 h-4 "></Settings2>
|
||||||
|
</button>
|
||||||
|
</ShadTooltip>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<Menu as="div" className="relative inline-block text-left z-100">
|
||||||
|
<button className="hover:dark:hover:bg-[#242f47] text-foreground transition-all duration-500 ease-in-out dark:bg-gray-800 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md">
|
||||||
<div>
|
<div>
|
||||||
<Menu.Button className="flex items-center">
|
<Menu.Button className="flex items-center">
|
||||||
<EllipsisVerticalIcon
|
<EllipsisVerticalIcon
|
||||||
|
|
@ -117,7 +151,7 @@ const NodeToolbarComponent = (props) => {
|
||||||
className={classNames(
|
className={classNames(
|
||||||
active
|
active
|
||||||
? "bg-muted text-gray-900"
|
? "bg-muted text-gray-900"
|
||||||
: "text-gray-700",
|
: "text-foreground",
|
||||||
"w-full group flex items-center px-4 py-2 text-sm"
|
"w-full group flex items-center px-4 py-2 text-sm"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -157,7 +191,7 @@ const NodeToolbarComponent = (props) => {
|
||||||
className={classNames(
|
className={classNames(
|
||||||
active
|
active
|
||||||
? "bg-muted text-gray-900"
|
? "bg-muted text-gray-900"
|
||||||
: "text-gray-700",
|
: "text-foreground",
|
||||||
"w-full group flex items-center px-4 py-2 text-sm"
|
"w-full group flex items-center px-4 py-2 text-sm"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export type APIClassType = {
|
||||||
description: string;
|
description: string;
|
||||||
template: APITemplateType;
|
template: APITemplateType;
|
||||||
display_name: string;
|
display_name: string;
|
||||||
|
documentation: string;
|
||||||
[key: string]: Array<string> | string | APITemplateType;
|
[key: string]: Array<string> | string | APITemplateType;
|
||||||
};
|
};
|
||||||
export type TemplateVariableType = {
|
export type TemplateVariableType = {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,4 @@
|
||||||
import {
|
import { ReactElement, ReactNode } from "react";
|
||||||
ComponentType,
|
|
||||||
ForwardRefExoticComponent,
|
|
||||||
ReactElement,
|
|
||||||
ReactNode,
|
|
||||||
SVGProps,
|
|
||||||
} from "react";
|
|
||||||
import { NodeDataType } from "../flow/index";
|
import { NodeDataType } from "../flow/index";
|
||||||
import { typesContextType } from "../typesContext";
|
import { typesContextType } from "../typesContext";
|
||||||
export type InputComponentType = {
|
export type InputComponentType = {
|
||||||
|
|
@ -28,6 +22,7 @@ export type DropDownComponentType = {
|
||||||
options: string[];
|
options: string[];
|
||||||
onSelect: (value: string) => void;
|
onSelect: (value: string) => void;
|
||||||
editNode?: boolean;
|
editNode?: boolean;
|
||||||
|
apiModal?: boolean;
|
||||||
numberOfOptions?: number;
|
numberOfOptions?: number;
|
||||||
};
|
};
|
||||||
export type ParameterComponentType = {
|
export type ParameterComponentType = {
|
||||||
|
|
@ -41,12 +36,14 @@ export type ParameterComponentType = {
|
||||||
name?: string;
|
name?: string;
|
||||||
tooltipTitle: string;
|
tooltipTitle: string;
|
||||||
dataContext?: typesContextType;
|
dataContext?: typesContextType;
|
||||||
|
info?: string;
|
||||||
};
|
};
|
||||||
export type InputListComponentType = {
|
export type InputListComponentType = {
|
||||||
value: string[];
|
value: string[];
|
||||||
onChange: (value: string[]) => void;
|
onChange: (value: string[]) => void;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
editNode?: boolean;
|
editNode?: boolean;
|
||||||
|
onAddInput?: (value?: string[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TextAreaComponentType = {
|
export type TextAreaComponentType = {
|
||||||
|
|
@ -115,3 +112,17 @@ export type RadialProgressType = {
|
||||||
value?: number;
|
value?: number;
|
||||||
color?: string;
|
color?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AccordionComponentType = {
|
||||||
|
children?: ReactElement;
|
||||||
|
open?: string[];
|
||||||
|
trigger?: string;
|
||||||
|
};
|
||||||
|
export type Side = "top" | "right" | "bottom" | "left";
|
||||||
|
|
||||||
|
export type ShadTooltipProps = {
|
||||||
|
delayDuration?: number;
|
||||||
|
side?: Side;
|
||||||
|
content: ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ export type TabsContextType = {
|
||||||
) => void;
|
) => void;
|
||||||
lastCopiedSelection: { nodes: any; edges: any };
|
lastCopiedSelection: { nodes: any; edges: any };
|
||||||
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
|
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
|
||||||
|
setTweak: (tweak: any) => void;
|
||||||
|
getTweak: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TabsState = {
|
export type TabsState = {
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
import {
|
|
||||||
RocketLaunchIcon,
|
|
||||||
LinkIcon,
|
|
||||||
CpuChipIcon,
|
|
||||||
LightBulbIcon,
|
|
||||||
CommandLineIcon,
|
|
||||||
WrenchScrewdriverIcon,
|
|
||||||
WrenchIcon,
|
|
||||||
ComputerDesktopIcon,
|
|
||||||
GiftIcon,
|
|
||||||
PaperClipIcon,
|
|
||||||
QuestionMarkCircleIcon,
|
|
||||||
FingerPrintIcon,
|
|
||||||
ScissorsIcon,
|
|
||||||
CircleStackIcon,
|
|
||||||
Squares2X2Icon,
|
|
||||||
Bars3CenterLeftIcon,
|
|
||||||
} from "@heroicons/react/24/outline";
|
|
||||||
import { Connection, Edge, Node, ReactFlowInstance } from "reactflow";
|
import { Connection, Edge, Node, ReactFlowInstance } from "reactflow";
|
||||||
import { FlowType, NodeType } from "./types/flow";
|
import { FlowType, NodeType } from "./types/flow";
|
||||||
import { APITemplateType } from "./types/api";
|
import { APITemplateType } from "./types/api";
|
||||||
|
|
@ -58,6 +40,7 @@ import {
|
||||||
Paperclip,
|
Paperclip,
|
||||||
Rocket,
|
Rocket,
|
||||||
Scissors,
|
Scissors,
|
||||||
|
FileSearch,
|
||||||
TerminalSquare,
|
TerminalSquare,
|
||||||
Wand2,
|
Wand2,
|
||||||
Wrench,
|
Wrench,
|
||||||
|
|
@ -139,6 +122,7 @@ export const nodeColors: { [char: string]: string } = {
|
||||||
toolkits: "#DB2C2C",
|
toolkits: "#DB2C2C",
|
||||||
wrappers: "#E6277A",
|
wrappers: "#E6277A",
|
||||||
utilities: "#31A3CC",
|
utilities: "#31A3CC",
|
||||||
|
retrievers: "#e6b25a",
|
||||||
unknown: "#9CA3AF",
|
unknown: "#9CA3AF",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -157,72 +141,11 @@ export const nodeNames: { [char: string]: string } = {
|
||||||
toolkits: "Toolkits",
|
toolkits: "Toolkits",
|
||||||
wrappers: "Wrappers",
|
wrappers: "Wrappers",
|
||||||
textsplitters: "Text Splitters",
|
textsplitters: "Text Splitters",
|
||||||
|
retrievers: "Retrievers",
|
||||||
utilities: "Utilities",
|
utilities: "Utilities",
|
||||||
unknown: "Unknown",
|
unknown: "Unknown",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const nodeIcons: {
|
|
||||||
[char: string]: React.ForwardRefExoticComponent<
|
|
||||||
React.SVGProps<SVGSVGElement>
|
|
||||||
>;
|
|
||||||
} = {
|
|
||||||
Chroma: ChromaIcon,
|
|
||||||
AirbyteJSONLoader: AirbyteIcon,
|
|
||||||
// SerpAPIWrapper: SerperIcon,
|
|
||||||
// AZLyricsLoader: AzIcon,
|
|
||||||
Anthropic: AnthropicIcon,
|
|
||||||
ChatAnthropic: AnthropicIcon,
|
|
||||||
BingSearchAPIWrapper: BingIcon,
|
|
||||||
BingSearchRun: BingIcon,
|
|
||||||
Cohere: CohereIcon,
|
|
||||||
CohereEmbeddings: CohereIcon,
|
|
||||||
EverNoteLoader: EvernoteIcon,
|
|
||||||
FacebookChatLoader: FBIcon,
|
|
||||||
GitbookLoader: GitBookIcon,
|
|
||||||
GoogleSearchAPIWrapper: GoogleIcon,
|
|
||||||
GoogleSearchResults: GoogleIcon,
|
|
||||||
GoogleSearchRun: GoogleIcon,
|
|
||||||
HNLoader: HackerNewsIcon,
|
|
||||||
HuggingFaceHub: HugginFaceIcon,
|
|
||||||
HuggingFaceEmbeddings: HugginFaceIcon,
|
|
||||||
IFixitLoader: IFixIcon,
|
|
||||||
Meta: MetaIcon,
|
|
||||||
Midjourney: MidjourneyIcon,
|
|
||||||
NotionDirectoryLoader: NotionIcon,
|
|
||||||
ChatOpenAI: OpenAiIcon,
|
|
||||||
OpenAI: OpenAiIcon,
|
|
||||||
OpenAIEmbeddings: OpenAiIcon,
|
|
||||||
Pinecone: PineconeIcon,
|
|
||||||
SupabaseVectorStore: SupabaseIcon,
|
|
||||||
MongoDBAtlasVectorSearch: MongoDBIcon,
|
|
||||||
// UnstructuredPowerPointLoader: PowerPointIcon, // word and powerpoint have differente styles
|
|
||||||
Qdrant: QDrantIcon,
|
|
||||||
// ReadTheDocsLoader: ReadTheDocsIcon, // does not work
|
|
||||||
Searx: SearxIcon,
|
|
||||||
SlackDirectoryLoader: SlackIcon,
|
|
||||||
// Weaviate: WeaviateIcon, // does not work
|
|
||||||
// WikipediaAPIWrapper: WikipediaIcon,
|
|
||||||
// WolframAlphaQueryRun: WolframIcon,
|
|
||||||
// WolframAlphaAPIWrapper: WolframIcon,
|
|
||||||
// UnstructuredWordDocumentLoader: WordIcon, // word and powerpoint have differente styles
|
|
||||||
agents: RocketLaunchIcon,
|
|
||||||
chains: LinkIcon,
|
|
||||||
memories: CpuChipIcon,
|
|
||||||
llms: LightBulbIcon,
|
|
||||||
prompts: CommandLineIcon,
|
|
||||||
tools: WrenchIcon,
|
|
||||||
advanced: ComputerDesktopIcon,
|
|
||||||
chat: Bars3CenterLeftIcon,
|
|
||||||
embeddings: FingerPrintIcon,
|
|
||||||
documentloaders: PaperClipIcon,
|
|
||||||
vectorstores: CircleStackIcon,
|
|
||||||
toolkits: WrenchScrewdriverIcon,
|
|
||||||
textsplitters: ScissorsIcon,
|
|
||||||
wrappers: GiftIcon,
|
|
||||||
utilities: Squares2X2Icon,
|
|
||||||
unknown: QuestionMarkCircleIcon,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const nodeIconsLucide: {
|
export const nodeIconsLucide: {
|
||||||
[char: string]: React.ForwardRefExoticComponent<
|
[char: string]: React.ForwardRefExoticComponent<
|
||||||
ComponentType<SVGProps<SVGSVGElement>>
|
ComponentType<SVGProps<SVGSVGElement>>
|
||||||
|
|
@ -363,6 +286,9 @@ export const nodeIconsLucide: {
|
||||||
utilities: Wand2 as React.ForwardRefExoticComponent<
|
utilities: Wand2 as React.ForwardRefExoticComponent<
|
||||||
ComponentType<SVGProps<SVGSVGElement>>
|
ComponentType<SVGProps<SVGSVGElement>>
|
||||||
>,
|
>,
|
||||||
|
retrievers: FileSearch as React.ForwardRefExoticComponent<
|
||||||
|
ComponentType<SVGProps<SVGSVGElement>>
|
||||||
|
>,
|
||||||
unknown: HelpCircle as React.ForwardRefExoticComponent<
|
unknown: HelpCircle as React.ForwardRefExoticComponent<
|
||||||
ComponentType<SVGProps<SVGSVGElement>>
|
ComponentType<SVGProps<SVGSVGElement>>
|
||||||
>,
|
>,
|
||||||
|
|
@ -995,5 +921,5 @@ export function getRandomKeyByssmm(): string {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const seconds = String(now.getSeconds()).padStart(2, "0");
|
const seconds = String(now.getSeconds()).padStart(2, "0");
|
||||||
const milliseconds = String(now.getMilliseconds()).padStart(3, "0");
|
const milliseconds = String(now.getMilliseconds()).padStart(3, "0");
|
||||||
return seconds + milliseconds;
|
return seconds + milliseconds + Math.abs(Math.floor(Math.random() * 10001));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,20 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
keyframes: {
|
||||||
|
"accordion-down": {
|
||||||
|
from: { height: 0 },
|
||||||
|
to: { height: "var(--radix-accordion-content-height)" },
|
||||||
|
},
|
||||||
|
"accordion-up": {
|
||||||
|
from: { height: "var(--radix-accordion-content-height)" },
|
||||||
|
to: { height: 0 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
"almost-dark-gray": "var(--almost-dark-gray)",
|
"almost-dark-gray": "var(--almost-dark-gray)",
|
||||||
"almost-light-blue": "var(--almost-light-blue)",
|
"almost-light-blue": "var(--almost-light-blue)",
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ def test_zero_shot_agent(client: TestClient):
|
||||||
"type": "LLMChain",
|
"type": "LLMChain",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["allowed_tools"] == {
|
assert template["allowed_tools"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -37,6 +38,7 @@ def test_zero_shot_agent(client: TestClient):
|
||||||
"type": "Tool",
|
"type": "Tool",
|
||||||
"list": True,
|
"list": True,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -60,6 +62,7 @@ def test_json_agent(client: TestClient):
|
||||||
"type": "BaseToolkit",
|
"type": "BaseToolkit",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["llm"] == {
|
assert template["llm"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -72,6 +75,7 @@ def test_json_agent(client: TestClient):
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
"display_name": "LLM",
|
"display_name": "LLM",
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -99,6 +103,7 @@ def test_csv_agent(client: TestClient):
|
||||||
"list": False,
|
"list": False,
|
||||||
"file_path": None,
|
"file_path": None,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["llm"] == {
|
assert template["llm"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -111,6 +116,7 @@ def test_csv_agent(client: TestClient):
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
"display_name": "LLM",
|
"display_name": "LLM",
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -143,6 +149,7 @@ def test_initialize_agent(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": True,
|
"list": True,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["memory"] == {
|
assert template["memory"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -154,6 +161,7 @@ def test_initialize_agent(client: TestClient):
|
||||||
"type": "BaseChatMemory",
|
"type": "BaseChatMemory",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["tools"] == {
|
assert template["tools"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -165,6 +173,7 @@ def test_initialize_agent(client: TestClient):
|
||||||
"type": "Tool",
|
"type": "Tool",
|
||||||
"list": True,
|
"list": True,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["llm"] == {
|
assert template["llm"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -177,4 +186,5 @@ def test_initialize_agent(client: TestClient):
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
"display_name": "LLM",
|
"display_name": "LLM",
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ def test_conversation_chain(client: TestClient):
|
||||||
"type": "BaseMemory",
|
"type": "BaseMemory",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["verbose"] == {
|
assert template["verbose"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -49,6 +50,7 @@ def test_conversation_chain(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["llm"] == {
|
assert template["llm"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -60,6 +62,7 @@ def test_conversation_chain(client: TestClient):
|
||||||
"type": "BaseLanguageModel",
|
"type": "BaseLanguageModel",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["input_key"] == {
|
assert template["input_key"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -72,6 +75,7 @@ def test_conversation_chain(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["output_key"] == {
|
assert template["output_key"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -84,6 +88,7 @@ def test_conversation_chain(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["_type"] == "ConversationChain"
|
assert template["_type"] == "ConversationChain"
|
||||||
|
|
||||||
|
|
@ -120,6 +125,7 @@ def test_llm_chain(client: TestClient):
|
||||||
"type": "BaseMemory",
|
"type": "BaseMemory",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["verbose"] == {
|
assert template["verbose"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -132,6 +138,7 @@ def test_llm_chain(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["llm"] == {
|
assert template["llm"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -143,6 +150,7 @@ def test_llm_chain(client: TestClient):
|
||||||
"type": "BaseLanguageModel",
|
"type": "BaseLanguageModel",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["output_key"] == {
|
assert template["output_key"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -155,6 +163,7 @@ def test_llm_chain(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -184,6 +193,7 @@ def test_llm_checker_chain(client: TestClient):
|
||||||
"type": "BaseLanguageModel",
|
"type": "BaseLanguageModel",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["_type"] == "LLMCheckerChain"
|
assert template["_type"] == "LLMCheckerChain"
|
||||||
|
|
||||||
|
|
@ -217,6 +227,7 @@ def test_llm_math_chain(client: TestClient):
|
||||||
"type": "BaseMemory",
|
"type": "BaseMemory",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["verbose"] == {
|
assert template["verbose"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -229,6 +240,7 @@ def test_llm_math_chain(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["llm"] == {
|
assert template["llm"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -240,6 +252,7 @@ def test_llm_math_chain(client: TestClient):
|
||||||
"type": "BaseLanguageModel",
|
"type": "BaseLanguageModel",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["input_key"] == {
|
assert template["input_key"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -252,6 +265,7 @@ def test_llm_math_chain(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["output_key"] == {
|
assert template["output_key"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -264,6 +278,7 @@ def test_llm_math_chain(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["_type"] == "LLMMathChain"
|
assert template["_type"] == "LLMMathChain"
|
||||||
|
|
||||||
|
|
@ -304,6 +319,7 @@ def test_series_character_chain(client: TestClient):
|
||||||
"type": "BaseLanguageModel",
|
"type": "BaseLanguageModel",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["character"] == {
|
assert template["character"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -315,6 +331,7 @@ def test_series_character_chain(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["series"] == {
|
assert template["series"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -326,6 +343,7 @@ def test_series_character_chain(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["_type"] == "SeriesCharacterChain"
|
assert template["_type"] == "SeriesCharacterChain"
|
||||||
|
|
||||||
|
|
@ -367,6 +385,7 @@ def test_mid_journey_prompt_chain(client: TestClient):
|
||||||
"type": "BaseLanguageModel",
|
"type": "BaseLanguageModel",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
# Test the description object
|
# Test the description object
|
||||||
assert (
|
assert (
|
||||||
|
|
@ -406,6 +425,7 @@ def test_time_travel_guide_chain(client: TestClient):
|
||||||
"type": "BaseLanguageModel",
|
"type": "BaseLanguageModel",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["memory"] == {
|
assert template["memory"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -417,6 +437,7 @@ def test_time_travel_guide_chain(client: TestClient):
|
||||||
"type": "BaseChatMemory",
|
"type": "BaseChatMemory",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
assert chain["description"] == "Time travel guide chain."
|
assert chain["description"] == "Time travel guide chain."
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["verbose"] == {
|
assert template["verbose"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -132,6 +133,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["client"] == {
|
assert template["client"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -143,6 +145,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "Any",
|
"type": "Any",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["model_name"] == {
|
assert template["model_name"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -162,6 +165,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": True,
|
"list": True,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
# Add more assertions for other properties here
|
# Add more assertions for other properties here
|
||||||
assert template["temperature"] == {
|
assert template["temperature"] == {
|
||||||
|
|
@ -175,6 +179,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["max_tokens"] == {
|
assert template["max_tokens"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -187,6 +192,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["top_p"] == {
|
assert template["top_p"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -199,6 +205,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["frequency_penalty"] == {
|
assert template["frequency_penalty"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -211,6 +218,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["presence_penalty"] == {
|
assert template["presence_penalty"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -223,6 +231,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["n"] == {
|
assert template["n"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -235,6 +244,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["best_of"] == {
|
assert template["best_of"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -247,6 +257,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["model_kwargs"] == {
|
assert template["model_kwargs"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -258,6 +269,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "code",
|
"type": "code",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["openai_api_key"] == {
|
assert template["openai_api_key"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -271,6 +283,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["batch_size"] == {
|
assert template["batch_size"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -283,6 +296,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["request_timeout"] == {
|
assert template["request_timeout"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -294,6 +308,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["logit_bias"] == {
|
assert template["logit_bias"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -305,6 +320,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "code",
|
"type": "code",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["max_retries"] == {
|
assert template["max_retries"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -317,6 +333,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["streaming"] == {
|
assert template["streaming"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -329,6 +346,7 @@ def test_openai(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -352,6 +370,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["client"] == {
|
assert template["client"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -363,6 +382,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "Any",
|
"type": "Any",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["model_name"] == {
|
assert template["model_name"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -385,6 +405,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": True,
|
"list": True,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["temperature"] == {
|
assert template["temperature"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -397,6 +418,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["model_kwargs"] == {
|
assert template["model_kwargs"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -408,6 +430,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "code",
|
"type": "code",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["openai_api_key"] == {
|
assert template["openai_api_key"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -421,6 +444,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["request_timeout"] == {
|
assert template["request_timeout"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -432,6 +456,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["max_retries"] == {
|
assert template["max_retries"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -444,6 +469,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["streaming"] == {
|
assert template["streaming"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -456,6 +482,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["n"] == {
|
assert template["n"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -468,6 +495,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
assert template["max_tokens"] == {
|
assert template["max_tokens"] == {
|
||||||
|
|
@ -480,6 +508,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["_type"] == "ChatOpenAI"
|
assert template["_type"] == "ChatOpenAI"
|
||||||
assert (
|
assert (
|
||||||
|
|
@ -487,7 +516,7 @@ def test_chat_open_ai(client: TestClient):
|
||||||
== "Wrapper around OpenAI Chat large language models." # noqa E501
|
== "Wrapper around OpenAI Chat large language models." # noqa E501
|
||||||
)
|
)
|
||||||
assert set(model["base_classes"]) == {
|
assert set(model["base_classes"]) == {
|
||||||
"Serializable",
|
"BaseLLM",
|
||||||
"BaseChatModel",
|
"BaseChatModel",
|
||||||
"ChatOpenAI",
|
"ChatOpenAI",
|
||||||
"BaseLanguageModel",
|
"BaseLanguageModel",
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ def test_prompt_template(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": True,
|
"list": True,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["output_parser"] == {
|
assert template["output_parser"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -39,6 +40,7 @@ def test_prompt_template(client: TestClient):
|
||||||
"type": "BaseOutputParser",
|
"type": "BaseOutputParser",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["partial_variables"] == {
|
assert template["partial_variables"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -50,6 +52,7 @@ def test_prompt_template(client: TestClient):
|
||||||
"type": "code",
|
"type": "code",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["template"] == {
|
assert template["template"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -61,6 +64,7 @@ def test_prompt_template(client: TestClient):
|
||||||
"type": "prompt",
|
"type": "prompt",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["template_format"] == {
|
assert template["template_format"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -73,6 +77,7 @@ def test_prompt_template(client: TestClient):
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["validate_template"] == {
|
assert template["validate_template"] == {
|
||||||
"required": False,
|
"required": False,
|
||||||
|
|
@ -85,85 +90,7 @@ def test_prompt_template(client: TestClient):
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
}
|
"info": "",
|
||||||
|
|
||||||
|
|
||||||
def test_few_shot_prompt_template(client: TestClient):
|
|
||||||
response = client.get("api/v1/all")
|
|
||||||
assert response.status_code == 200
|
|
||||||
json_response = response.json()
|
|
||||||
prompts = json_response["prompts"]
|
|
||||||
|
|
||||||
prompt = prompts["FewShotPromptTemplate"]
|
|
||||||
template = prompt["template"]
|
|
||||||
# Test other fields in the template similar to PromptTemplate
|
|
||||||
assert template["examples"] == {
|
|
||||||
"required": False,
|
|
||||||
"placeholder": "",
|
|
||||||
"show": True,
|
|
||||||
"multiline": True,
|
|
||||||
"password": False,
|
|
||||||
"name": "examples",
|
|
||||||
"type": "prompt",
|
|
||||||
"list": True,
|
|
||||||
"advanced": False,
|
|
||||||
}
|
|
||||||
assert template["example_selector"] == {
|
|
||||||
"required": False,
|
|
||||||
"placeholder": "",
|
|
||||||
"show": False,
|
|
||||||
"multiline": False,
|
|
||||||
"password": False,
|
|
||||||
"name": "example_selector",
|
|
||||||
"type": "BaseExampleSelector",
|
|
||||||
"list": False,
|
|
||||||
"advanced": False,
|
|
||||||
}
|
|
||||||
assert template["example_prompt"] == {
|
|
||||||
"required": True,
|
|
||||||
"placeholder": "",
|
|
||||||
"show": True,
|
|
||||||
"multiline": False,
|
|
||||||
"password": False,
|
|
||||||
"name": "example_prompt",
|
|
||||||
"type": "PromptTemplate",
|
|
||||||
"list": False,
|
|
||||||
"advanced": False,
|
|
||||||
}
|
|
||||||
assert template["suffix"] == {
|
|
||||||
"required": True,
|
|
||||||
"placeholder": "",
|
|
||||||
"show": True,
|
|
||||||
"multiline": True,
|
|
||||||
"password": False,
|
|
||||||
"name": "suffix",
|
|
||||||
"type": "prompt",
|
|
||||||
"list": False,
|
|
||||||
"advanced": False,
|
|
||||||
}
|
|
||||||
assert template["example_separator"] == {
|
|
||||||
"required": False,
|
|
||||||
"placeholder": "",
|
|
||||||
"show": False,
|
|
||||||
"multiline": False,
|
|
||||||
"value": "\n\n",
|
|
||||||
"password": False,
|
|
||||||
"name": "example_separator",
|
|
||||||
"type": "str",
|
|
||||||
"list": False,
|
|
||||||
"advanced": False,
|
|
||||||
}
|
|
||||||
assert template["prefix"] == {
|
|
||||||
"required": False,
|
|
||||||
"placeholder": "",
|
|
||||||
"show": True,
|
|
||||||
"multiline": True,
|
|
||||||
"value": "",
|
|
||||||
"password": False,
|
|
||||||
"name": "prefix",
|
|
||||||
"type": "prompt",
|
|
||||||
"list": False,
|
|
||||||
"advanced": False,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -185,6 +112,7 @@ def test_zero_shot_prompt(client: TestClient):
|
||||||
"type": "prompt",
|
"type": "prompt",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["suffix"] == {
|
assert template["suffix"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -197,6 +125,7 @@ def test_zero_shot_prompt(client: TestClient):
|
||||||
"type": "prompt",
|
"type": "prompt",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
assert template["format_instructions"] == {
|
assert template["format_instructions"] == {
|
||||||
"required": True,
|
"required": True,
|
||||||
|
|
@ -209,4 +138,5 @@ def test_zero_shot_prompt(client: TestClient):
|
||||||
"type": "prompt",
|
"type": "prompt",
|
||||||
"list": False,
|
"list": False,
|
||||||
"advanced": False,
|
"advanced": False,
|
||||||
|
"info": "",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import pytest
|
||||||
|
|
||||||
def test_init_build(client):
|
def test_init_build(client):
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"api/v1/build/init", json={"id": "test", "data": {"key": "value"}}
|
"api/v1/build/init/test", json={"id": "test", "data": {"key": "value"}}
|
||||||
)
|
)
|
||||||
assert response.status_code == 201
|
assert response.status_code == 201
|
||||||
assert response.json() == {"flowId": "test"}
|
assert response.json() == {"flowId": "test"}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue