Merge branch 'dev' of https://github.com/logspace-ai/langflow into 45-implement-agents-as-tools
This commit is contained in:
commit
1fc05f6f46
28 changed files with 162 additions and 109 deletions
|
|
@ -43,9 +43,11 @@ the system we use to tag our issues and pull requests.
|
|||
You can develop LangFlow using docker compose, or locally.
|
||||
|
||||
#### **Docker compose**
|
||||
This will run the backend and frontend in separate containers. The frontend will be available at `localhost:3000` and the backend at `localhost:5003`.
|
||||
This will run the backend and frontend in separate containers. The frontend will be available at `localhost:3000` and the backend at `localhost:7860`.
|
||||
```bash
|
||||
docker compose up --build
|
||||
# or
|
||||
make dev build=1
|
||||
```
|
||||
|
||||
#### **Locally**
|
||||
|
|
@ -58,7 +60,6 @@ Before you start, make sure you have the following installed:
|
|||
For the backend, you will need to install the dependencies and start the development server.
|
||||
```bash
|
||||
poetry install
|
||||
# Port 5003 is required for the backend to work with the frontend
|
||||
make run_backend
|
||||
```
|
||||
For the frontend, you will need to install the dependencies and start the development server.
|
||||
|
|
|
|||
17
Makefile
17
Makefile
|
|
@ -39,6 +39,17 @@ build:
|
|||
poetry build --format sdist
|
||||
rm -rf src/backend/langflow/frontend
|
||||
|
||||
dev:
|
||||
make install_frontend
|
||||
ifeq ($(build),1)
|
||||
@echo 'Running docker compose up with build'
|
||||
docker compose up --build
|
||||
else
|
||||
@echo 'Running docker compose up without build'
|
||||
docker compose up
|
||||
endif
|
||||
|
||||
|
||||
publish:
|
||||
make build
|
||||
poetry publish
|
||||
|
|
@ -49,4 +60,8 @@ help:
|
|||
@echo 'lint - run linters'
|
||||
@echo 'install_frontend - install the frontend dependencies'
|
||||
@echo 'build_frontend - build the frontend static files'
|
||||
@echo 'build - build the frontend static files and package the project'
|
||||
@echo 'run_frontend - run the frontend in development mode'
|
||||
@echo 'run_backend - run the backend in development mode'
|
||||
@echo 'build - build the frontend static files and package the project'
|
||||
@echo 'publish - build the frontend static files and package the project and publish it to PyPI'
|
||||
@echo 'dev - run the project in development mode with docker compose'
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -34,6 +34,18 @@ Creating flows with LangFlow is easy. Simply drag sidebar components onto the ca
|
|||
|
||||
Explore by editing prompt parameters, link chains and agents, track an agent's thought process, and export your flow.
|
||||
|
||||
Once you're done, you can export your flow as a JSON file to use with LangChain.
|
||||
To do so, click the "Export" button in the top right corner of the canvas, then
|
||||
in Python, you can load the flow with:
|
||||
|
||||
```python
|
||||
from langflow import load_flow_from_json
|
||||
|
||||
flow = load_flow_from_json("path/to/flow.json")
|
||||
# Now you can use it like any chain
|
||||
flow("Hey, have you heard of LangFlow?")
|
||||
```
|
||||
|
||||
|
||||
## 👋 Contributing
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ FROM python:3.10-slim
|
|||
WORKDIR /app
|
||||
|
||||
# Install Poetry
|
||||
RUN apt-get update && apt-get install -y curl
|
||||
RUN apt-get update && apt-get install gcc curl -y
|
||||
RUN curl -sSL https://install.python-poetry.org | python3 -
|
||||
# # Add Poetry to PATH
|
||||
ENV PATH="${PATH}:/root/.local/bin"
|
||||
|
|
|
|||
|
|
@ -15,12 +15,12 @@ services:
|
|||
build:
|
||||
context: ./src/frontend
|
||||
dockerfile: ./dev.Dockerfile
|
||||
args:
|
||||
- BACKEND_URL=http://backend:7860
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./src/frontend:/app
|
||||
# Set process.env.BACKEND to the backend service
|
||||
environment:
|
||||
- BACKEND_HOST="http://backend"
|
||||
- BACKEND_PORT="7860"
|
||||
restart: on-failure
|
||||
- ./src/frontend/public:/home/node/app/public
|
||||
- ./src/frontend/src:/home/node/app/src
|
||||
- ./src/frontend/package.json:/home/node/app/package.json
|
||||
restart: on-failure
|
||||
9
poetry.lock
generated
9
poetry.lock
generated
|
|
@ -1378,13 +1378,14 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "openai"
|
||||
version = "0.26.5"
|
||||
version = "0.27.2"
|
||||
description = "Python client library for the OpenAI API"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7.1"
|
||||
files = [
|
||||
{file = "openai-0.26.5.tar.gz", hash = "sha256:2882a59c67ae33c2716a04389a6e6680d061f073424953732f917fde219addfd"},
|
||||
{file = "openai-0.27.2-py3-none-any.whl", hash = "sha256:6df674cf257e9e0504f1fd191c333d3f6a2442b13218d0eccf06230eb24d320e"},
|
||||
{file = "openai-0.27.2.tar.gz", hash = "sha256:5869fdfa34b0ec66c39afa22f4a0fb83a135dff81f6505f52834c6ab3113f762"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
@ -1395,7 +1396,7 @@ tqdm = "*"
|
|||
[package.extras]
|
||||
datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
|
||||
dev = ["black (>=21.6b0,<22.0)", "pytest (>=6.0.0,<7.0.0)", "pytest-asyncio", "pytest-mock"]
|
||||
embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "sklearn", "tenacity (>=8.0.1)"]
|
||||
embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"]
|
||||
wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2406,4 +2407,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "9287450d71ec7c3bd7b1ef2766e22b86fb92bf0e2f51260adf039b1175c74f7c"
|
||||
content-hash = "ebc0a8ca9ea284d8e986306a10f13ff91e7e8aae18341c83329f5b1e1bcc66bd"
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
[tool.poetry]
|
||||
name = "langflow"
|
||||
version = "0.0.40"
|
||||
version = "0.0.45"
|
||||
description = "A Python package with a built-in web application"
|
||||
authors = ["Logspace <contact@logspace.ai>"]
|
||||
packages = [
|
||||
{ include = "langflow", from = "src/backend" },
|
||||
maintainers = [
|
||||
"Gabriel Almeida <gabriel@logspace.ai>",
|
||||
"Ibis Prevedello <ibiscp@gmail.com>",
|
||||
"Lucas Eduoli <lucaseduoli@gmail.com>",
|
||||
"Otávio Anovazzi <otavio2204@gmail.com>",
|
||||
]
|
||||
include = ["src/backend/langflow/*", "src/backend/langflow/**/*"]
|
||||
repository = "https://github.com/logspace-ai/langflow"
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
keywords = ["nlp", "langchain", "openai", "gpt", "gui"]
|
||||
packages = [{ include = "langflow", from = "src/backend" }]
|
||||
include = ["src/backend/langflow/*", "src/backend/langflow/**/*"]
|
||||
|
||||
|
||||
[tool.poetry.scripts]
|
||||
langflow = "langflow.__main__:main"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
openai = "^0.26.5"
|
||||
fastapi = "^0.92.0"
|
||||
uvicorn = "^0.20.0"
|
||||
beautifulsoup4 = "^4.11.2"
|
||||
|
|
@ -24,6 +30,7 @@ google-api-python-client = "^2.79.0"
|
|||
typer = "^0.7.0"
|
||||
gunicorn = "^20.1.0"
|
||||
langchain = "^0.0.113"
|
||||
openai = "^0.27.2"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "^23.1.0"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import multiprocessing
|
||||
import platform
|
||||
import re
|
||||
|
||||
from langflow.main import create_app
|
||||
|
||||
import typer
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from pathlib import Path
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_number_of_workers(workers=None):
|
||||
|
|
@ -15,35 +17,6 @@ def get_number_of_workers(workers=None):
|
|||
return workers
|
||||
|
||||
|
||||
def replace_port(static_files_dir, host, port):
|
||||
# Load index.html from frontend directory
|
||||
# In it there is a script tag that sets the base url
|
||||
# like so setItem("port", "http://localhost:7860")
|
||||
# localhost could be anything so we need to verify for string
|
||||
# we need to set the base url to the port that the server is running on
|
||||
# so that the frontend can make requests to the backend
|
||||
# This is a hacky way to do it, but it works
|
||||
new_string = f'setItem("port","http://{host}:{port}")'
|
||||
with open(static_files_dir / "index.html", "r") as f:
|
||||
index_html = f.read()
|
||||
# using regex to replace the port
|
||||
index_html = re.sub(
|
||||
r"setItem\(\"port\",.*\)",
|
||||
new_string,
|
||||
index_html,
|
||||
)
|
||||
with open(static_files_dir / "index.html", "w") as f:
|
||||
f.write(index_html)
|
||||
# Verify that the port was replaced
|
||||
with open(static_files_dir / "index.html", "r") as f:
|
||||
index_html = f.read()
|
||||
if new_string not in index_html:
|
||||
raise ValueError(
|
||||
"The port was not replaced in index.html. "
|
||||
"Please check the regex in main.py"
|
||||
)
|
||||
|
||||
|
||||
def serve(
|
||||
host: str = "127.0.0.1", workers: int = 1, timeout: int = 60, port: int = 7860
|
||||
):
|
||||
|
|
@ -63,9 +36,6 @@ def serve(
|
|||
"timeout": timeout,
|
||||
}
|
||||
|
||||
# Replace the port in index.html
|
||||
replace_port(static_files_dir, host, port)
|
||||
|
||||
if platform.system() in ["Darwin", "Windows"]:
|
||||
# Run using uvicorn on MacOS and Windows
|
||||
# Windows doesn't support gunicorn
|
||||
|
|
|
|||
6
src/backend/langflow/interface/custom_lists.py
Normal file
6
src/backend/langflow/interface/custom_lists.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from langchain import llms
|
||||
from langchain.llms.openai import OpenAIChat
|
||||
|
||||
|
||||
llm_type_to_cls_dict = llms.type_to_cls_dict
|
||||
llm_type_to_cls_dict["openai-chat"] = OpenAIChat
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
from langchain import chains, agents, prompts, llms
|
||||
from langchain import chains, agents, prompts
|
||||
from langflow.interface.custom_lists import llm_type_to_cls_dict
|
||||
from langflow.custom import customs
|
||||
from langflow.utils import util, allowed_components
|
||||
from langchain.agents.load_tools import get_all_tool_names
|
||||
|
|
@ -55,7 +56,7 @@ def list_llms():
|
|||
"""List all llm types"""
|
||||
return [
|
||||
llm.__name__
|
||||
for llm in llms.type_to_cls_dict.values()
|
||||
for llm in llm_type_to_cls_dict.values()
|
||||
if llm.__name__ in allowed_components.LLMS
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from typing import Dict, Any # noqa: F401
|
||||
from langchain import agents, chains, llms, prompts
|
||||
from langchain import agents, chains, prompts
|
||||
from langflow.interface.custom_lists import llm_type_to_cls_dict
|
||||
from langchain.agents.load_tools import (
|
||||
_BASE_TOOLS,
|
||||
_EXTRA_LLM_TOOLS,
|
||||
|
|
@ -56,7 +57,7 @@ def get_prompt_signature(name: str):
|
|||
def get_llm_signature(name: str):
|
||||
"""Get the signature of an llm."""
|
||||
try:
|
||||
return util.build_template_from_class(name, llms.type_to_cls_dict)
|
||||
return util.build_template_from_class(name, llm_type_to_cls_dict)
|
||||
except ValueError as exc:
|
||||
raise ValueError("LLM not found") from exc
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ AGENTS = ["ZeroShotAgent"]
|
|||
|
||||
PROMPTS = ["PromptTemplate", "FewShotPromptTemplate"]
|
||||
|
||||
LLMS = ["OpenAI"]
|
||||
LLMS = ["OpenAI", "OpenAIChat"]
|
||||
|
||||
TOOLS = ["Search", "PAL-MATH", "Calculator", "Serper Search"]
|
||||
|
|
|
|||
8
src/backend/langflow/utils/constants.py
Normal file
8
src/backend/langflow/utils/constants.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENAI_MODELS = [
|
||||
"text-davinci-003",
|
||||
"text-davinci-002",
|
||||
"text-curie-001",
|
||||
"text-babbage-001",
|
||||
"text-ada-001",
|
||||
]
|
||||
CHAT_OPENAI_MODELS = ["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]
|
||||
|
|
@ -11,6 +11,8 @@ from langchain.agents.load_tools import (
|
|||
)
|
||||
from typing import Optional, Dict
|
||||
|
||||
from langflow.utils import constants
|
||||
|
||||
|
||||
def build_template_from_function(name: str, type_to_loader_dict: Dict):
|
||||
classes = [
|
||||
|
|
@ -296,7 +298,9 @@ def format_dict(d, name: Optional[str] = None):
|
|||
|
||||
# Add options to openai
|
||||
if name == "OpenAI" and key == "model_name":
|
||||
value["options"] = ["text-davinci-003", "text-davinci-002"]
|
||||
value["options"] = constants.OPENAI_MODELS
|
||||
elif name == "OpenAIChat" and key == "model_name":
|
||||
value["options"] = constants.CHAT_OPENAI_MODELS
|
||||
|
||||
return d
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,23 @@
|
|||
FROM node:19-alpine as frontend_build
|
||||
ARG BACKEND
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
RUN npm install
|
||||
#baseline
|
||||
FROM node:19-bullseye-slim AS base
|
||||
RUN mkdir -p /home/node/app
|
||||
RUN chown -R node:node /home/node && chmod -R 770 /home/node
|
||||
RUN apt-get update && apt-get install -y jq
|
||||
WORKDIR /home/node/app
|
||||
|
||||
# client build
|
||||
FROM base AS builder-client
|
||||
ARG BACKEND_URL
|
||||
ENV BACKEND_URL $BACKEND_URL
|
||||
RUN echo "BACKEND_URL: $BACKEND_URL"
|
||||
|
||||
WORKDIR /home/node/app
|
||||
COPY --chown=node:node . ./
|
||||
|
||||
COPY ./set_proxy.sh .
|
||||
RUN chmod +x set_proxy.sh && ./set_proxy.sh
|
||||
|
||||
USER node
|
||||
|
||||
RUN npm install --loglevel warn
|
||||
CMD ["npm", "start"]
|
||||
10
src/frontend/package-lock.json
generated
10
src/frontend/package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "langflow",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "langflow",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
|
|
@ -17080,9 +17080,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.75.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz",
|
||||
"integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==",
|
||||
"version": "5.76.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.2.tgz",
|
||||
"integrity": "sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w==",
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^0.0.51",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "langflow",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.10.5",
|
||||
|
|
@ -53,5 +53,6 @@
|
|||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
},
|
||||
"proxy": "http://backend:7860"
|
||||
}
|
||||
|
|
@ -5,13 +5,10 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LangFLow</title>
|
||||
<script>
|
||||
window.sessionStorage.setItem("port","http://localhost:7860")
|
||||
</script>
|
||||
</head>
|
||||
<body id='body' style="width: 100%; height:100%">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div style="width: 100vw; height:100vh" id='root'>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
10
src/frontend/set_proxy.sh
Executable file
10
src/frontend/set_proxy.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#! /bin/bash
|
||||
# Edit package.json to set proxy
|
||||
backend_url=$BACKEND_URL
|
||||
echo "Setting proxy to $backend_url"
|
||||
# Load package.json file and edit proxy
|
||||
packagejson=$(cat package.json)
|
||||
|
||||
packagejson=$(echo "$packagejson" | jq ".proxy = \"$backend_url\"")
|
||||
|
||||
echo "$packagejson" > package.json
|
||||
|
|
@ -39,7 +39,6 @@ export default function ParameterComponent({
|
|||
const [enabled, setEnabled] = useState(
|
||||
data.node.template[name]?.value ?? false
|
||||
);
|
||||
console.log(data.node.template[name]);
|
||||
const { reactFlowInstance } = useContext(typesContext);
|
||||
let disabled =
|
||||
reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false;
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ export default function GenericNode({ data, selected}:{data:NodeDataType,selecte
|
|||
data={data}
|
||||
color={nodeColors[types[data.type]]}
|
||||
title={data.type}
|
||||
tooltipTitle={"Type: str"}
|
||||
id={data.type + "|" + data.id + data.node.base_classes.map((b) => ("|" + b))}
|
||||
tooltipTitle={`Type: ${data.node.base_classes.join(' | ')}`}
|
||||
id={[data.type, data.id, ...data.node.base_classes].join('|')}
|
||||
type={'str'}
|
||||
left={false}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { SingleAlertComponentType } from "../../../../types/alerts";
|
|||
export default function SingleAlert({ dropItem, removeAlert}:SingleAlertComponentType) {
|
||||
const [show, setShow] = useState(true);
|
||||
const type = dropItem.type;
|
||||
console.log(dropItem.id)
|
||||
|
||||
return (
|
||||
<Transition
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ export default function AlertDropdown({}: AlertDropdownType) {
|
|||
componentRef.current &&
|
||||
!componentRef.current.contains(event.target as Node)
|
||||
) {
|
||||
console.log(event)
|
||||
closePopUp();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
|
|||
setChatHistory((old) => {
|
||||
let newChat = _.cloneDeep(old);
|
||||
if(JSON.stringify(flow.chat) !==JSON.stringify(old)){
|
||||
console.log(old,flow.chat)
|
||||
tabsChange = true
|
||||
return old
|
||||
}
|
||||
|
|
@ -43,7 +42,6 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
|
|||
return newChat;
|
||||
});
|
||||
if(tabsChange){
|
||||
console.log(flow.chat)
|
||||
if(thought){
|
||||
updateFlow({..._.cloneDeep(flow),chat:[...flow.chat,{isSend,message,thought}]})
|
||||
}
|
||||
|
|
@ -98,11 +96,9 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
|
|||
let message = chatValue;
|
||||
setChatValue("");
|
||||
addChatHistory(message, true);
|
||||
console.log({ ...reactFlowInstance.toObject(), message, chatHistory });
|
||||
|
||||
sendAll({ ...reactFlowInstance.toObject(), message, chatHistory})
|
||||
.then((r) => {
|
||||
console.log(r.data);
|
||||
addChatHistory(r.data.result, false, r.data.thought);
|
||||
setLockChat(false);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
// Create a new flow with a default name if no flow is provided.
|
||||
let newFlow: FlowType = {
|
||||
name: flow ? flow.name : "New Flow " + (flows.length===0?"":flows.length),
|
||||
name: "New Flow",
|
||||
id: id.toString(),
|
||||
data,
|
||||
chat: flow ? flow.chat : [],
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
import { APIObjectType, sendAllProps } from '../../types/api/index';
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
|
||||
const backendUrl = window.sessionStorage.getItem('port') || "http://localhost:7860";
|
||||
|
||||
export async function getAll():Promise<AxiosResponse<APIObjectType>> {
|
||||
return await axios.get(`${backendUrl}/all`);
|
||||
return await axios.get(`/all`);
|
||||
}
|
||||
|
||||
export async function sendAll(data:sendAllProps) {
|
||||
console.log(data);
|
||||
return await axios.post(`${backendUrl}/predict`, data);
|
||||
return await axios.post(`/predict`, data);
|
||||
}
|
||||
|
|
@ -4,17 +4,24 @@ import TabComponent from "../tabComponent";
|
|||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import FlowPage from "../..";
|
||||
import { darkContext } from "../../../../contexts/darkContext";
|
||||
import { BellIcon, MoonIcon, SunIcon } from "@heroicons/react/24/outline";
|
||||
import {
|
||||
ArrowDownTrayIcon,
|
||||
ArrowUpTrayIcon,
|
||||
BellIcon,
|
||||
MoonIcon,
|
||||
SunIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||
import AlertDropdown from "../../../../alerts/alertDropDown";
|
||||
import { alertContext } from "../../../../contexts/alertContext";
|
||||
|
||||
export default function TabsManagerComponent() {
|
||||
const { flows, addFlow, tabIndex, setTabIndex } = useContext(TabsContext);
|
||||
const { flows, addFlow, tabIndex, setTabIndex, uploadFlow, downloadFlow } = useContext(TabsContext);
|
||||
const { openPopUp } = useContext(PopUpContext);
|
||||
const AlertWidth = 256
|
||||
const AlertWidth = 256;
|
||||
const { dark, setDark } = useContext(darkContext);
|
||||
const {notificationCenter, setNotificationCenter} = useContext(alertContext)
|
||||
const { notificationCenter, setNotificationCenter } =
|
||||
useContext(alertContext);
|
||||
useEffect(() => {
|
||||
//create the first flow
|
||||
if (flows.length === 0) {
|
||||
|
|
@ -43,6 +50,12 @@ export default function TabsManagerComponent() {
|
|||
flow={null}
|
||||
/>
|
||||
<div className="ml-auto mr-2 flex gap-3">
|
||||
<button onClick={() => uploadFlow()} className="flex items-center gap-1 pr-2 border-gray-400 border-r text-sm text-gray-400 hover:text-gray-500">
|
||||
Import <ArrowUpTrayIcon className="w-5 h-5" />
|
||||
</button>
|
||||
<button onClick={() => downloadFlow()} className="flex items-center gap-1 mr-2 text-sm text-gray-400 hover:text-gray-500">
|
||||
Export <ArrowDownTrayIcon className="h-5 w-5" />
|
||||
</button>
|
||||
<button
|
||||
className="text-gray-400 hover:text-gray-500 "
|
||||
onClick={() => {
|
||||
|
|
@ -58,13 +71,23 @@ export default function TabsManagerComponent() {
|
|||
<button
|
||||
className="text-gray-400 hover:text-gray-500 relative"
|
||||
onClick={(event: React.MouseEvent<HTMLElement>) => {
|
||||
setNotificationCenter(false)
|
||||
const top = (event.target as Element).getBoundingClientRect().top
|
||||
const left = (event.target as Element).getBoundingClientRect().left
|
||||
openPopUp(<div className="z-10 absolute" style={{top:top+20, left:left-AlertWidth}}><AlertDropdown/></div>)
|
||||
setNotificationCenter(false);
|
||||
const top = (event.target as Element).getBoundingClientRect().top;
|
||||
const left = (event.target as Element).getBoundingClientRect()
|
||||
.left;
|
||||
openPopUp(
|
||||
<div
|
||||
className="z-10 absolute"
|
||||
style={{ top: top + 20, left: left - AlertWidth }}
|
||||
>
|
||||
<AlertDropdown />
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{notificationCenter&&<div className='absolute w-1.5 h-1.5 rounded-full bg-red-600 right-[3px]'></div>}
|
||||
{notificationCenter && (
|
||||
<div className="absolute w-1.5 h-1.5 rounded-full bg-red-600 right-[3px]"></div>
|
||||
)}
|
||||
<BellIcon className="h-5 w-5" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -182,17 +182,6 @@ export default function FlowPage({ flow }:{flow:FlowType}) {
|
|||
>
|
||||
<Background className="dark:bg-gray-900"/>
|
||||
<Controls className="[&>button]:text-black [&>button]:dark:bg-gray-800 hover:[&>button]:dark:bg-gray-700 [&>button]:dark:text-gray-400 [&>button]:dark:fill-gray-400 [&>button]:dark:border-gray-600">
|
||||
<ControlButton
|
||||
onClick={() => uploadFlow()}
|
||||
>
|
||||
<ArrowUpTrayIcon />
|
||||
</ControlButton>
|
||||
|
||||
<ControlButton
|
||||
onClick={() => downloadFlow()}
|
||||
>
|
||||
<ArrowDownTrayIcon />
|
||||
</ControlButton>
|
||||
</Controls>
|
||||
</ReactFlow>
|
||||
<Chat flow={flow} reactFlowInstance={reactFlowInstance} />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue