Merge remote-tracking branch 'origin/two_edges_dev' into two_edges
This commit is contained in:
commit
6f40941925
83 changed files with 1427 additions and 2465 deletions
83
.github/workflows/docker-build.yml
vendored
83
.github/workflows/docker-build.yml
vendored
|
|
@ -23,14 +23,23 @@ env:
|
|||
POETRY_VERSION: "1.8.2"
|
||||
|
||||
jobs:
|
||||
docker_build:
|
||||
name: Build Docker Image
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
base_tags: ${{ steps.set-vars.outputs.base_tags }}
|
||||
main_tags: ${{ steps.set-vars.outputs.main_tags }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set Dockerfile and Tags
|
||||
id: set-vars
|
||||
run: |
|
||||
echo "base_tags=langflowai/langflow:base-${{ inputs.version }}" >> $GITHUB_OUTPUT
|
||||
echo "main_tags=langflowai/langflow:${{ inputs.version }},langflowai/langflow:1.0-alpha" >> $GITHUB_OUTPUT
|
||||
build_base:
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
id: qemu
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
|
|
@ -38,56 +47,54 @@ jobs:
|
|||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Set Dockerfile and Tags
|
||||
id: set-vars
|
||||
run: |
|
||||
if [ "${{ inputs.release_type }}" == "base" ]; then
|
||||
echo "DOCKERFILE=./docker/build_and_push_base.Dockerfile" >> $GITHUB_ENV
|
||||
echo "TAGS=langflowai/langflow:base-${{ inputs.version }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "DOCKERFILE=./docker/build_and_push.Dockerfile" >> $GITHUB_ENV
|
||||
echo "TAGS=langflowai/langflow:${{ inputs.version }},langflowai/langflow:1.0-alpha" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Build and push
|
||||
- name: Build and push Base Image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: "linux/amd64,linux/arm64/v8"
|
||||
file: ${{ env.DOCKERFILE }}
|
||||
tags: ${{ env.TAGS }}
|
||||
- name: Wait for Docker Hub to propagate
|
||||
run: sleep 120
|
||||
- name: Build and push (backend)
|
||||
if: ${{ inputs.release_type == 'main' }}
|
||||
file: ./docker/build_and_push_base.Dockerfile
|
||||
tags: ${{ needs.setup.outputs.base_tags }}
|
||||
|
||||
build_components:
|
||||
if: ${{ inputs.release_type == 'main' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build_base
|
||||
strategy:
|
||||
matrix:
|
||||
component: [backend, frontend]
|
||||
include:
|
||||
- component: backend
|
||||
dockerfile: ./docker/build_and_push_backend.Dockerfile
|
||||
tags: langflowai/langflow-backend:${{ inputs.version }},langflowai/langflow-backend:1.0-alpha
|
||||
- component: frontend
|
||||
dockerfile: ./docker/frontend/build_and_push_frontend.Dockerfile
|
||||
tags: langflowai/langflow-frontend:${{ inputs.version }},langflowai/langflow-frontend:1.0-alpha
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push ${{ matrix.component }}
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: "linux/amd64,linux/arm64/v8"
|
||||
file: ./docker/build_and_push_backend.Dockerfile
|
||||
build-args: |
|
||||
LANGFLOW_IMAGE=langflowai/langflow:${{ inputs.version }}
|
||||
tags: |
|
||||
langflowai/langflow-backend:${{ inputs.version }}
|
||||
langflowai/langflow-backend:1.0-alpha
|
||||
- name: Build and push (frontend)
|
||||
if: ${{ inputs.release_type == 'main' }}
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
file: ./docker/frontend/build_and_push_frontend.Dockerfile
|
||||
platforms: "linux/amd64,linux/arm64/v8"
|
||||
tags: |
|
||||
langflowai/langflow-frontend:${{ inputs.version }}
|
||||
langflowai/langflow-frontend:1.0-alpha
|
||||
file: ${{ matrix.dockerfile }}
|
||||
tags: ${{ matrix.tags }}
|
||||
|
||||
restart-space:
|
||||
name: Restart HuggingFace Spaces
|
||||
if: ${{ inputs.release_type == 'main' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: docker_build
|
||||
needs: build_base
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
|
|
|
|||
18
.github/workflows/docker_test.yml
vendored
18
.github/workflows/docker_test.yml
vendored
|
|
@ -24,6 +24,7 @@ env:
|
|||
jobs:
|
||||
test-docker:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test docker images
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build image
|
||||
|
|
@ -61,20 +62,3 @@ jobs:
|
|||
docker build -t langflowai/langflow-frontend:latest-dev \
|
||||
-f docker/frontend/build_and_push_frontend.Dockerfile \
|
||||
.
|
||||
test-multi-arch-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
id: qemu
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
file: ./docker/build_and_push.Dockerfile
|
||||
platforms: "linux/amd64,linux/arm64/v8"
|
||||
tags: langflowai/langflow:latest-dev
|
||||
|
|
|
|||
51
.github/workflows/lint-js.yml
vendored
Normal file
51
.github/workflows/lint-js.yml
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
name: Lint Frontend
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "src/frontend/**"
|
||||
|
||||
env:
|
||||
NODE_VERSION: "21"
|
||||
|
||||
jobs:
|
||||
run-linters:
|
||||
name: Run linters
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
id: setup-node
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
- name: Cache Node.js dependencies
|
||||
uses: actions/cache@v4
|
||||
id: npm-cache
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('src/frontend/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: |
|
||||
cd src/frontend
|
||||
npm ci
|
||||
if: ${{ steps.setup-node.outputs.cache-hit != 'true' }}
|
||||
|
||||
- name: Run linters
|
||||
uses: wearerequired/lint-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
auto_fix: true
|
||||
git_email: "gabriel@langflow.org"
|
||||
# Enable linters
|
||||
eslint: true
|
||||
prettier: true
|
||||
prettier_args: '--write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore'
|
||||
|
||||
|
|
@ -1,17 +1,12 @@
|
|||
name: lint
|
||||
name: Lint Python
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "poetry.lock"
|
||||
- "pyproject.toml"
|
||||
- "src/backend/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "poetry.lock"
|
||||
- "pyproject.toml"
|
||||
- "src/backend/**"
|
||||
- "tests/**"
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.8.2"
|
||||
|
|
@ -45,6 +40,13 @@ jobs:
|
|||
path: |
|
||||
./.mypy_cache
|
||||
key: ${{ runner.os }}-mypy-${{ hashFiles('**/pyproject.toml') }}
|
||||
- name: Lint check
|
||||
run: |
|
||||
make lint
|
||||
- name: Run linters
|
||||
uses: wearerequired/lint-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
# Enable linters
|
||||
git_email: "gabriel@langflow.org"
|
||||
mypy: true
|
||||
mypy_args: '--namespace-packages -p "langflow"'
|
||||
mypy_command_prefix: "poetry run"
|
||||
|
||||
14
.github/workflows/matchers/ruff.json
vendored
Normal file
14
.github/workflows/matchers/ruff.json
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "ruff",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(Would reformat): (.+)$",
|
||||
"message": 1,
|
||||
"file": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
39
.github/workflows/style-check-py.yml
vendored
Normal file
39
.github/workflows/style-check-py.yml
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
name: Ruff Style Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "poetry.lock"
|
||||
- "pyproject.toml"
|
||||
- "src/backend/**"
|
||||
- "tests/**"
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.8.2"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.12"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
|
||||
uses: "./.github/actions/poetry_caching"
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
cache-key: ${{ runner.os }}-poetry-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }}
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
poetry env use ${{ matrix.python-version }}
|
||||
poetry install
|
||||
- name: Register problem matcher
|
||||
run: echo "::add-matcher::.github/workflows/matchers/ruff.json"
|
||||
- name: Run Ruff
|
||||
run: poetry run ruff check --output-format=github .
|
||||
- name: Run Ruff format
|
||||
run: poetry run ruff format --check .
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -180,6 +180,8 @@ coverage.xml
|
|||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
|
|
|
|||
|
|
@ -1,18 +1,5 @@
|
|||
fail_fast: true
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/mirrors-eslint
|
||||
rev: "v9.1.1"
|
||||
hooks:
|
||||
- id: eslint
|
||||
files: \.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx
|
||||
types: [file]
|
||||
args: ["--fix", "--no-warn-ignored"]
|
||||
additional_dependencies:
|
||||
- eslint@9.1.1
|
||||
- eslint-plugin-prettier
|
||||
- eslint-config-prettier
|
||||
- prettier
|
||||
- eslint-plugin-react@latest
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.1.0
|
||||
hooks:
|
||||
|
|
@ -25,16 +12,3 @@ repos:
|
|||
args:
|
||||
- --fix=lf
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.4.2
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
# Python
|
||||
files: \.py$
|
||||
types: [file]
|
||||
# Run the formatter.
|
||||
- id: ruff-format
|
||||
files: \.py$
|
||||
types: [file]
|
||||
|
|
|
|||
75
Makefile
75
Makefile
|
|
@ -9,17 +9,21 @@ open_browser ?= true
|
|||
path = src/backend/base/langflow/frontend
|
||||
workers ?= 1
|
||||
|
||||
|
||||
codespell:
|
||||
@poetry install --with spelling
|
||||
poetry run codespell --toml pyproject.toml
|
||||
|
||||
|
||||
fix_codespell:
|
||||
@poetry install --with spelling
|
||||
poetry run codespell --toml pyproject.toml --write
|
||||
|
||||
|
||||
setup_poetry:
|
||||
pipx install poetry
|
||||
|
||||
|
||||
add:
|
||||
@echo 'Adding dependencies'
|
||||
ifdef devel
|
||||
|
|
@ -34,45 +38,54 @@ ifdef base
|
|||
cd src/backend/base && poetry add $(base)
|
||||
endif
|
||||
|
||||
|
||||
init:
|
||||
@echo 'Installing backend dependencies'
|
||||
make install_backend
|
||||
@echo 'Installing frontend dependencies'
|
||||
make install_frontend
|
||||
|
||||
coverage:
|
||||
|
||||
coverage: ## run the tests and generate a coverage report
|
||||
poetry run pytest --cov \
|
||||
--cov-config=.coveragerc \
|
||||
--cov-report xml \
|
||||
--cov-report term-missing:skip-covered \
|
||||
--cov-report lcov:coverage/lcov-pytest.info
|
||||
|
||||
|
||||
# allow passing arguments to pytest
|
||||
tests:
|
||||
tests: ## run the tests
|
||||
poetry run pytest tests --instafail -ra -n auto -m "not api_key_required" $(args)
|
||||
|
||||
|
||||
format:
|
||||
format: ## run code formatters
|
||||
poetry run ruff check . --fix
|
||||
poetry run ruff format .
|
||||
cd src/frontend && npm run format
|
||||
|
||||
lint:
|
||||
|
||||
lint: ## run linters
|
||||
poetry run mypy --namespace-packages -p "langflow"
|
||||
|
||||
install_frontend:
|
||||
|
||||
install_frontend: ## install the frontend dependencies
|
||||
cd src/frontend && npm install
|
||||
|
||||
|
||||
install_frontendci:
|
||||
cd src/frontend && npm ci
|
||||
|
||||
|
||||
install_frontendc:
|
||||
cd src/frontend && rm -rf node_modules package-lock.json && npm install
|
||||
|
||||
|
||||
run_frontend:
|
||||
@-kill -9 `lsof -t -i:3000`
|
||||
cd src/frontend && npm start
|
||||
|
||||
|
||||
tests_frontend:
|
||||
ifeq ($(UI), true)
|
||||
cd src/frontend && npx playwright test --ui --project=chromium
|
||||
|
|
@ -80,6 +93,7 @@ else
|
|||
cd src/frontend && npx playwright test --project=chromium
|
||||
endif
|
||||
|
||||
|
||||
run_cli:
|
||||
@echo 'Running the CLI'
|
||||
@make install_frontend > /dev/null
|
||||
|
|
@ -93,6 +107,7 @@ else
|
|||
@make start host=$(host) port=$(port) log_level=$(log_level)
|
||||
endif
|
||||
|
||||
|
||||
run_cli_debug:
|
||||
@echo 'Running the CLI in debug mode'
|
||||
@make install_frontend > /dev/null
|
||||
|
|
@ -106,6 +121,7 @@ else
|
|||
@make start host=$(host) port=$(port) log_level=debug
|
||||
endif
|
||||
|
||||
|
||||
start:
|
||||
@echo 'Running the CLI'
|
||||
|
||||
|
|
@ -116,30 +132,34 @@ else
|
|||
endif
|
||||
|
||||
|
||||
|
||||
setup_devcontainer:
|
||||
make init
|
||||
make build_frontend
|
||||
poetry run langflow --path src/frontend/build
|
||||
|
||||
|
||||
setup_env:
|
||||
@sh ./scripts/setup/update_poetry.sh 1.8.2
|
||||
@sh ./scripts/setup/setup_env.sh
|
||||
|
||||
frontend:
|
||||
|
||||
frontend: ## run the frontend in development mode
|
||||
make install_frontend
|
||||
make run_frontend
|
||||
|
||||
|
||||
frontendc:
|
||||
make install_frontendc
|
||||
make run_frontend
|
||||
|
||||
|
||||
install_backend:
|
||||
@echo 'Installing backend dependencies'
|
||||
@poetry install
|
||||
@poetry run pre-commit install
|
||||
|
||||
backend:
|
||||
|
||||
backend: ## run the backend in development mode
|
||||
@echo 'Setting up the environment'
|
||||
@make setup_env
|
||||
make install_backend
|
||||
|
|
@ -152,6 +172,7 @@ else
|
|||
poetry run uvicorn --factory langflow.main:create_app --host 0.0.0.0 --port 7860 --reload --env-file .env --loop asyncio --workers $(workers)
|
||||
endif
|
||||
|
||||
|
||||
build_and_run:
|
||||
@echo 'Removing dist folder'
|
||||
@make setup_env
|
||||
|
|
@ -161,18 +182,21 @@ build_and_run:
|
|||
poetry run pip install dist/*.tar.gz
|
||||
poetry run langflow run
|
||||
|
||||
|
||||
build_and_install:
|
||||
@echo 'Removing dist folder'
|
||||
rm -rf dist
|
||||
rm -rf src/backend/base/dist
|
||||
make build && poetry run pip install dist/*.whl && pip install src/backend/base/dist/*.whl --force-reinstall
|
||||
|
||||
build_frontend:
|
||||
|
||||
build_frontend: ## build the frontend static files
|
||||
cd src/frontend && CI='' npm run build
|
||||
rm -rf src/backend/base/langflow/frontend
|
||||
cp -r src/frontend/build src/backend/base/langflow/frontend
|
||||
|
||||
build:
|
||||
|
||||
build: ## build the frontend static files and package the project
|
||||
@echo 'Building the project'
|
||||
@make setup_env
|
||||
ifdef base
|
||||
|
|
@ -185,13 +209,16 @@ ifdef main
|
|||
make build_langflow
|
||||
endif
|
||||
|
||||
|
||||
build_langflow_base:
|
||||
cd src/backend/base && poetry build
|
||||
rm -rf src/backend/base/langflow/frontend
|
||||
|
||||
|
||||
build_langflow_backup:
|
||||
poetry lock && poetry build
|
||||
|
||||
|
||||
build_langflow:
|
||||
cd ./scripts && poetry run python update_dependencies.py
|
||||
poetry lock
|
||||
|
|
@ -201,7 +228,8 @@ ifdef restore
|
|||
mv poetry.lock.bak poetry.lock
|
||||
endif
|
||||
|
||||
dev:
|
||||
|
||||
dev: ## run the project in development mode with docker compose
|
||||
make install_frontend
|
||||
ifeq ($(build),1)
|
||||
@echo 'Running docker compose up with build'
|
||||
|
|
@ -211,25 +239,30 @@ else
|
|||
docker compose $(if $(debug),-f docker-compose.debug.yml) up
|
||||
endif
|
||||
|
||||
|
||||
lock_base:
|
||||
cd src/backend/base && poetry lock
|
||||
|
||||
lock_langflow:
|
||||
poetry lock
|
||||
|
||||
|
||||
lock:
|
||||
# Run both in parallel
|
||||
@echo 'Locking dependencies'
|
||||
cd src/backend/base && poetry lock
|
||||
poetry lock
|
||||
|
||||
|
||||
publish_base:
|
||||
cd src/backend/base && poetry publish
|
||||
|
||||
|
||||
publish_langflow:
|
||||
poetry publish
|
||||
|
||||
publish:
|
||||
|
||||
publish: ## build the frontend static files and package the project and publish it to PyPI
|
||||
@echo 'Publishing the project'
|
||||
ifdef base
|
||||
make publish_base
|
||||
|
|
@ -239,17 +272,11 @@ ifdef main
|
|||
make publish_langflow
|
||||
endif
|
||||
|
||||
help:
|
||||
|
||||
help: ## show this help message
|
||||
@echo '----'
|
||||
@echo 'format - run code formatters'
|
||||
@echo 'lint - run linters'
|
||||
@echo 'install_frontend - install the frontend dependencies'
|
||||
@echo 'build_frontend - build the frontend static files'
|
||||
@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'
|
||||
@echo 'tests - run the tests'
|
||||
@echo 'coverage - run the tests and generate a coverage report'
|
||||
@echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | \
|
||||
sed -e 's/:.*##\s*/:/' \
|
||||
-e 's/^\(.\+\):\(.*\)/\\x1b[36mmake \1\\x1b[m:\2/' | \
|
||||
column -c2 -t -s :']]')"
|
||||
@echo '----'
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@
|
|||
# Used to build deps + create our virtual environment
|
||||
################################
|
||||
|
||||
# force platform to the current architecture to increase build speed time on multi-platform builds
|
||||
FROM --platform=$BUILDPLATFORM python:3.12-slim as builder-base
|
||||
# 1. use python:3.12.3-slim as the base image until https://github.com/pydantic/pydantic-core/issues/1292 gets resolved
|
||||
# 2. do not add --platform=$BUILDPLATFORM because the pydantic binaries must be resolved for the final architecture
|
||||
FROM python:3.12.3-slim as builder-base
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
\
|
||||
|
|
@ -51,15 +52,27 @@ COPY pyproject.toml poetry.lock README.md ./
|
|||
COPY src/ ./src
|
||||
COPY scripts/ ./scripts
|
||||
RUN python -m pip install requests --user && cd ./scripts && python update_dependencies.py
|
||||
|
||||
# 1. Install the dependencies using the current poetry.lock file to create reproducible builds
|
||||
# 2. Do not install dev dependencies
|
||||
# 3. Install all the extras to ensure all optionals are installed as well
|
||||
# 4. --sync to ensure nothing else is in the environment
|
||||
# 5. Build the wheel and install "langflow" package (mainly for version)
|
||||
|
||||
# Note: moving to build and installing the wheel will make the docker images not reproducible.
|
||||
RUN $POETRY_HOME/bin/poetry lock --no-update \
|
||||
# install current lock file with fixed dependencies versions \
|
||||
# do not install dev dependencies \
|
||||
&& $POETRY_HOME/bin/poetry install --without dev --sync -E deploy -E couchbase -E cassio \
|
||||
&& $POETRY_HOME/bin/poetry build -f wheel \
|
||||
&& $POETRY_HOME/bin/poetry run pip install dist/*.whl --force-reinstall
|
||||
&& $POETRY_HOME/bin/poetry run pip install dist/*.whl
|
||||
|
||||
################################
|
||||
# RUNTIME
|
||||
# Setup user, utilities and copy the virtual environment only
|
||||
################################
|
||||
FROM python:3.12-slim as runtime
|
||||
# 1. use python:3.12.3-slim as the base image until https://github.com/pydantic/pydantic-core/issues/1292 gets resolved
|
||||
FROM python:3.12.3-slim as runtime
|
||||
|
||||
RUN apt-get -y update \
|
||||
&& apt-get install --no-install-recommends -y \
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
# PYTHON-BASE
|
||||
# Sets up all our shared environment variables
|
||||
################################
|
||||
FROM python:3.12-slim as python-base
|
||||
|
||||
# use python:3.12.3-slim as the base image until https://github.com/pydantic/pydantic-core/issues/1292 gets resolved
|
||||
FROM python:3.12.3-slim as python-base
|
||||
|
||||
# python
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# BUILDER-BASE
|
||||
################################
|
||||
|
||||
# force platform to the current architecture to increase build speed time on multi-platform builds
|
||||
# 1. force platform to the current architecture to increase build speed time on multi-platform builds
|
||||
FROM --platform=$BUILDPLATFORM node:lts-bookworm-slim as builder-base
|
||||
COPY src/frontend /frontend
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ server {
|
|||
gzip_vary on;
|
||||
gzip_disable "MSIE [4-6] \.";
|
||||
|
||||
listen 80;
|
||||
listen __FRONTEND_PORT__;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
|
|
|
|||
|
|
@ -4,11 +4,20 @@ trap 'kill -TERM $PID' TERM INT
|
|||
if [ -z "$BACKEND_URL" ]; then
|
||||
BACKEND_URL="$1"
|
||||
fi
|
||||
if [ -z "$FRONTEND_PORT" ]; then
|
||||
FRONTEND_PORT="$2"
|
||||
fi
|
||||
if [ -z "$FRONTEND_PORT" ]; then
|
||||
FRONTEND_PORT="80"
|
||||
fi
|
||||
if [ -z "$BACKEND_URL" ]; then
|
||||
echo "BACKEND_URL must be set as an environment variable or as first parameter. (e.g. http://localhost:7860)"
|
||||
exit 1
|
||||
fi
|
||||
echo "BACKEND_URL: $BACKEND_URL"
|
||||
echo "FRONTEND_PORT: $FRONTEND_PORT"
|
||||
sed -i "s|__BACKEND_URL__|$BACKEND_URL|g" /etc/nginx/conf.d/default.conf
|
||||
sed -i "s|__FRONTEND_PORT__|$FRONTEND_PORT|g" /etc/nginx/conf.d/default.conf
|
||||
cat /etc/nginx/conf.d/default.conf
|
||||
|
||||
|
||||
|
|
|
|||
51
poetry.lock
generated
51
poetry.lock
generated
|
|
@ -471,17 +471,17 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "boto3"
|
||||
version = "1.34.125"
|
||||
version = "1.34.126"
|
||||
description = "The AWS SDK for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "boto3-1.34.125-py3-none-any.whl", hash = "sha256:116d9eb3c26cf313a2e1e44ef704d1f98f9eb18e7628695d07b01b44a8683544"},
|
||||
{file = "boto3-1.34.125.tar.gz", hash = "sha256:31c4a5e4d6f9e6116be61ff654b424ddbd1afcdefe0e8b870c4796f9108eb1c6"},
|
||||
{file = "boto3-1.34.126-py3-none-any.whl", hash = "sha256:7f676daef674fe74f34ce4063228eccc6e60c811f574720e31f230296c4bf29a"},
|
||||
{file = "boto3-1.34.126.tar.gz", hash = "sha256:7e8418b47dd43954a9088d504541bed8a42b6d06e712d02befba134c1c4d7c6d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
botocore = ">=1.34.125,<1.35.0"
|
||||
botocore = ">=1.34.126,<1.35.0"
|
||||
jmespath = ">=0.7.1,<2.0.0"
|
||||
s3transfer = ">=0.10.0,<0.11.0"
|
||||
|
||||
|
|
@ -490,13 +490,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
|
|||
|
||||
[[package]]
|
||||
name = "botocore"
|
||||
version = "1.34.125"
|
||||
version = "1.34.126"
|
||||
description = "Low-level, data-driven core of boto 3."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "botocore-1.34.125-py3-none-any.whl", hash = "sha256:71e97e7d2c088f1188ba6976441b5857a5425acd4aaa31b45d13119c9cb86424"},
|
||||
{file = "botocore-1.34.125.tar.gz", hash = "sha256:d2882be011ad5b16e7ab4a96360b5b66a0a7e175c1ea06dbf2de473c0a0a33d8"},
|
||||
{file = "botocore-1.34.126-py3-none-any.whl", hash = "sha256:7eff883c638fe30e0b036789df32d851e093d12544615a3b90062b42ac85bdbc"},
|
||||
{file = "botocore-1.34.126.tar.gz", hash = "sha256:7a8ccb6a7c02456757a984a3a44331b6f51c94cb8b9b287cd045122fd177a4b0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
@ -4113,22 +4113,25 @@ adal = ["adal (>=1.0.2)"]
|
|||
|
||||
[[package]]
|
||||
name = "langchain"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langchain-0.2.3-py3-none-any.whl", hash = "sha256:5dc33cd9c8008693d328b7cb698df69073acecc89ad9c2a95f243b3314f8d834"},
|
||||
{file = "langchain-0.2.3.tar.gz", hash = "sha256:81962cc72cce6515f7bd71e01542727870789bf8b666c6913d85559080c1a201"},
|
||||
{file = "langchain-0.2.4-py3-none-any.whl", hash = "sha256:a04813215c30f944df006031e2febde872af8fab628dcee825d969e07b6cd621"},
|
||||
{file = "langchain-0.2.4.tar.gz", hash = "sha256:e704b5b06222d5eba2d02c76f891321d1bac8952ed54e093831b2bdabf99dcd5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
aiohttp = ">=3.8.3,<4.0.0"
|
||||
async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""}
|
||||
langchain-core = ">=0.2.0,<0.3.0"
|
||||
langchain-core = ">=0.2.6,<0.3.0"
|
||||
langchain-text-splitters = ">=0.2.0,<0.3.0"
|
||||
langsmith = ">=0.1.17,<0.2.0"
|
||||
numpy = ">=1,<2"
|
||||
numpy = [
|
||||
{version = ">=1,<2", markers = "python_version < \"3.12\""},
|
||||
{version = ">=1.26.0,<2.0.0", markers = "python_version >= \"3.12\""},
|
||||
]
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
requests = ">=2,<3"
|
||||
|
|
@ -4224,19 +4227,19 @@ tenacity = ">=8.1.0,<9.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "langchain-core"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langchain_core-0.2.5-py3-none-any.whl", hash = "sha256:abe5138f22acff23a079ec538be5268bbf97cf023d51987a0dd474d2a16cae3e"},
|
||||
{file = "langchain_core-0.2.5.tar.gz", hash = "sha256:4a5c2f56b22396a63ef4790043660e393adbfa6832b978f023ca996a04b8e752"},
|
||||
{file = "langchain_core-0.2.6-py3-none-any.whl", hash = "sha256:90521c9fc95d8f925e0d2e2d952382676aea6d3f8de611eda1b1810874c31e5d"},
|
||||
{file = "langchain_core-0.2.6.tar.gz", hash = "sha256:9f0e38da722a558a6e95b6d86de01bd92e84558c47ac8ba599f02eab70a1c873"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
jsonpatch = ">=1.33,<2.0"
|
||||
langsmith = ">=0.1.66,<0.2.0"
|
||||
packaging = ">=23.2,<24.0"
|
||||
langsmith = ">=0.1.75,<0.2.0"
|
||||
packaging = ">=23.2,<25"
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
tenacity = ">=8.1.0,<9.0.0"
|
||||
|
|
@ -4409,7 +4412,7 @@ six = "*"
|
|||
|
||||
[[package]]
|
||||
name = "langflow-base"
|
||||
version = "0.0.63"
|
||||
version = "0.0.68"
|
||||
description = "A Python package with a built-in web application"
|
||||
optional = false
|
||||
python-versions = ">=3.10,<3.13"
|
||||
|
|
@ -4506,13 +4509,13 @@ requests = ">=2,<3"
|
|||
|
||||
[[package]]
|
||||
name = "litellm"
|
||||
version = "1.40.9"
|
||||
version = "1.40.12"
|
||||
description = "Library to easily interface with LLM API providers"
|
||||
optional = false
|
||||
python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8"
|
||||
files = [
|
||||
{file = "litellm-1.40.9-py3-none-any.whl", hash = "sha256:8a4107b9cce114d822de52cbc9bce56f8edc6620f19d0f2257e71834715fb366"},
|
||||
{file = "litellm-1.40.9.tar.gz", hash = "sha256:e0ea07d0b55001a6f60bba2b2ecd72d1f0dca07e656f63937adfdf45f31e5ad7"},
|
||||
{file = "litellm-1.40.12-py3-none-any.whl", hash = "sha256:42f1648507f29c60543ba5fdf35d38fc161694da043b201508225bae50d3328c"},
|
||||
{file = "litellm-1.40.12.tar.gz", hash = "sha256:366bb9c3694b9ef59b3d073bb37ff9ca175ab4090dc187b0a11d2b21db3a6a5d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
@ -7850,13 +7853,13 @@ websockets = ">=11,<13"
|
|||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "5.0.5"
|
||||
version = "5.0.6"
|
||||
description = "Python client for Redis database and key-value store"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "redis-5.0.5-py3-none-any.whl", hash = "sha256:30b47d4ebb6b7a0b9b40c1275a19b87bb6f46b3bed82a89012cf56dea4024ada"},
|
||||
{file = "redis-5.0.5.tar.gz", hash = "sha256:3417688621acf6ee368dec4a04dd95881be24efd34c79f00d31f62bb528800ae"},
|
||||
{file = "redis-5.0.6-py3-none-any.whl", hash = "sha256:c0d6d990850c627bbf7be01c5c4cbaadf67b48593e913bb71c9819c30df37eee"},
|
||||
{file = "redis-5.0.6.tar.gz", hash = "sha256:38473cd7c6389ad3e44a91f4c3eaf6bcb8a9f746007f29bf4fb20824ff0b2197"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "langflow"
|
||||
version = "1.0.0a52"
|
||||
version = "1.0.0a57"
|
||||
description = "A Python package with a built-in web application"
|
||||
authors = ["Langflow <contact@langflow.org>"]
|
||||
maintainers = [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from typing import Optional
|
||||
from langchain_core.embeddings import Embeddings
|
||||
from langchain_openai import AzureOpenAIEmbeddings
|
||||
from pydantic.v1 import SecretStr
|
||||
|
|
@ -44,6 +45,11 @@ class AzureOpenAIEmbeddingsComponent(CustomComponent):
|
|||
"password": True,
|
||||
},
|
||||
"code": {"show": False},
|
||||
"dimensions": {
|
||||
"display_name": "Dimensions",
|
||||
"info": "The number of dimensions the resulting output embeddings should have. Only supported by certain models.",
|
||||
"advanced": True,
|
||||
},
|
||||
}
|
||||
|
||||
def build(
|
||||
|
|
@ -52,6 +58,7 @@ class AzureOpenAIEmbeddingsComponent(CustomComponent):
|
|||
azure_deployment: str,
|
||||
api_version: str,
|
||||
api_key: str,
|
||||
dimensions: Optional[int] = None,
|
||||
) -> Embeddings:
|
||||
if api_key:
|
||||
azure_api_key = SecretStr(api_key)
|
||||
|
|
@ -63,6 +70,7 @@ class AzureOpenAIEmbeddingsComponent(CustomComponent):
|
|||
azure_deployment=azure_deployment,
|
||||
api_version=api_version,
|
||||
api_key=azure_api_key,
|
||||
dimensions=dimensions,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -84,6 +84,11 @@ class OpenAIEmbeddingsComponent(CustomComponent):
|
|||
"advanced": True,
|
||||
},
|
||||
"tiktoken_enable": {"display_name": "TikToken Enable", "advanced": True},
|
||||
"dimensions": {
|
||||
"display_name": "Dimensions",
|
||||
"info": "The number of dimensions the resulting output embeddings should have. Only supported by certain models.",
|
||||
"advanced": True,
|
||||
},
|
||||
}
|
||||
|
||||
def build(
|
||||
|
|
@ -109,6 +114,7 @@ class OpenAIEmbeddingsComponent(CustomComponent):
|
|||
skip_empty: bool = False,
|
||||
tiktoken_enable: bool = True,
|
||||
tiktoken_model_name: Optional[str] = None,
|
||||
dimensions: Optional[int] = None,
|
||||
) -> Embeddings:
|
||||
# This is to avoid errors with Vector Stores (e.g Chroma)
|
||||
if disallowed_special == ["all"]:
|
||||
|
|
@ -140,4 +146,5 @@ class OpenAIEmbeddingsComponent(CustomComponent):
|
|||
show_progress_bar=show_progress_bar,
|
||||
skip_empty=skip_empty,
|
||||
tiktoken_model_name=tiktoken_model_name,
|
||||
dimensions=dimensions,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class ChatOpenAIComponent(CustomComponent):
|
|||
self,
|
||||
max_tokens: Optional[int] = 0,
|
||||
model_kwargs: NestedDict = {},
|
||||
model_name: str = "gpt-4o",
|
||||
model_name: str = "gpt-3.5-turbo",
|
||||
openai_api_base: Optional[str] = None,
|
||||
openai_api_key: Optional[str] = None,
|
||||
temperature: float = 0.7,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class AstraDBSearchComponent(LCVectorStoreComponent):
|
|||
"info": "The name of the collection within Astra DB where the vectors will be stored.",
|
||||
},
|
||||
"token": {
|
||||
"display_name": "Token",
|
||||
"display_name": "Astra DB Application Token",
|
||||
"info": "Authentication token for accessing Astra DB.",
|
||||
"password": True,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from typing import List, Optional
|
|||
import chromadb
|
||||
from chromadb.config import Settings
|
||||
from langchain_chroma import Chroma
|
||||
|
||||
from langflow.components.vectorstores.base.model import LCVectorStoreComponent
|
||||
from langflow.field_typing import Embeddings, Text
|
||||
from langflow.schema import Data
|
||||
|
|
@ -104,10 +103,11 @@ class ChromaSearchComponent(LCVectorStoreComponent):
|
|||
client = chromadb.HttpClient(settings=chroma_settings)
|
||||
if index_directory:
|
||||
index_directory = self.resolve_path(index_directory)
|
||||
|
||||
vector_store = Chroma(
|
||||
embedding_function=embedding,
|
||||
collection_name=collection_name,
|
||||
persist_directory=index_directory,
|
||||
persist_directory=index_directory or None,
|
||||
client=client,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class AstraDBVectorStoreComponent(CustomComponent):
|
|||
"info": "The name of the collection within Astra DB where the vectors will be stored.",
|
||||
},
|
||||
"token": {
|
||||
"display_name": "Token",
|
||||
"display_name": "Astra DB Application Token",
|
||||
"info": "Authentication token for accessing Astra DB.",
|
||||
"password": True,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
from typing import Any, Union
|
||||
from enum import Enum
|
||||
from typing import Any, Generator, Union
|
||||
|
||||
from langchain_core.documents import Document
|
||||
from pydantic import BaseModel
|
||||
|
||||
from langflow.interface.utils import extract_input_variables_from_prompt
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
||||
class UnbuiltObject:
|
||||
|
|
@ -14,6 +16,16 @@ class UnbuiltResult:
|
|||
pass
|
||||
|
||||
|
||||
class ArtifactType(str, Enum):
|
||||
TEXT = "text"
|
||||
RECORD = "record"
|
||||
OBJECT = "object"
|
||||
ARRAY = "array"
|
||||
STREAM = "stream"
|
||||
UNKNOWN = "unknown"
|
||||
MESSAGE = "message"
|
||||
|
||||
|
||||
def validate_prompt(prompt: str):
|
||||
"""Validate prompt."""
|
||||
if extract_input_variables_from_prompt(prompt):
|
||||
|
|
@ -50,3 +62,37 @@ def serialize_field(value):
|
|||
elif isinstance(value, str):
|
||||
return {"result": value}
|
||||
return value
|
||||
|
||||
|
||||
def get_artifact_type(value, build_result) -> str:
|
||||
result = ArtifactType.UNKNOWN
|
||||
match value:
|
||||
case Record():
|
||||
result = ArtifactType.RECORD
|
||||
|
||||
case str():
|
||||
result = ArtifactType.TEXT
|
||||
|
||||
case dict():
|
||||
result = ArtifactType.OBJECT
|
||||
|
||||
case list():
|
||||
result = ArtifactType.ARRAY
|
||||
|
||||
case Message():
|
||||
result = ArtifactType.MESSAGE
|
||||
|
||||
if result == ArtifactType.UNKNOWN:
|
||||
if isinstance(build_result, Generator):
|
||||
result = ArtifactType.STREAM
|
||||
elif isinstance(value, Message) and isinstance(value.text, Generator):
|
||||
result = ArtifactType.STREAM
|
||||
|
||||
return result.value
|
||||
|
||||
|
||||
def post_process_raw(raw, artifact_type: str):
|
||||
if artifact_type == ArtifactType.STREAM.value:
|
||||
raw = ""
|
||||
|
||||
return raw
|
||||
|
|
|
|||
|
|
@ -181,6 +181,9 @@ def update_new_output(data):
|
|||
}
|
||||
)
|
||||
deduplicated_outputs = []
|
||||
if source_node is None:
|
||||
source_node = {"data": {"node": {"outputs": []}}}
|
||||
|
||||
for output in source_node["data"]["node"]["outputs"]:
|
||||
if output["name"] not in [d["name"] for d in deduplicated_outputs]:
|
||||
deduplicated_outputs.append(output)
|
||||
|
|
|
|||
|
|
@ -8,17 +8,12 @@
|
|||
"dataType": "OpenAIModel",
|
||||
"id": "OpenAIModel-k39HS",
|
||||
"name": "text_output",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "ChatOutput-njtka",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"inputTypes": ["Text", "Message"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -38,18 +33,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-uxBqP",
|
||||
"name": "prompt",
|
||||
"output_types": [
|
||||
"Prompt"
|
||||
]
|
||||
"output_types": ["Prompt"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "OpenAIModel-k39HS",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"inputTypes": ["Text", "Data", "Prompt"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -69,19 +58,12 @@
|
|||
"dataType": "ChatInput",
|
||||
"id": "ChatInput-P3fgL",
|
||||
"name": "message",
|
||||
"output_types": [
|
||||
"Message"
|
||||
]
|
||||
"output_types": ["Message"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "user_input",
|
||||
"id": "Prompt-uxBqP",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "Message", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -102,16 +84,10 @@
|
|||
"display_name": "Prompt",
|
||||
"id": "Prompt-uxBqP",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"str",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["object", "str", "Text"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"template": [
|
||||
"user_input"
|
||||
]
|
||||
"template": ["user_input"]
|
||||
},
|
||||
"description": "Create a prompt template with dynamic variables.",
|
||||
"display_name": "Prompt",
|
||||
|
|
@ -134,9 +110,7 @@
|
|||
"method": "build_prompt",
|
||||
"name": "prompt",
|
||||
"selected": "Prompt",
|
||||
"types": [
|
||||
"Prompt"
|
||||
],
|
||||
"types": ["Prompt"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -145,9 +119,7 @@
|
|||
"method": "format_prompt",
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -178,9 +150,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -201,12 +171,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Document", "Message", "Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -244,11 +209,7 @@
|
|||
"display_name": "OpenAI",
|
||||
"id": "OpenAIModel-k39HS",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"Text",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["object", "Text", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -286,9 +247,7 @@
|
|||
"method": "text_response",
|
||||
"name": "text_output",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -297,9 +256,7 @@
|
|||
"method": "build_model",
|
||||
"name": "model_output",
|
||||
"selected": "BaseLanguageModel",
|
||||
"types": [
|
||||
"BaseLanguageModel"
|
||||
],
|
||||
"types": ["BaseLanguageModel"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -330,11 +287,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"input_types": ["Text", "Data", "Prompt"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -354,9 +307,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -376,9 +327,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -398,9 +347,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -418,7 +365,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "str",
|
||||
"value": "gpt-4o"
|
||||
"value": "gpt-3.5-turbo"
|
||||
},
|
||||
"openai_api_base": {
|
||||
"advanced": true,
|
||||
|
|
@ -427,9 +374,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -449,9 +394,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The OpenAI API Key to use for the OpenAI model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": true,
|
||||
"multiline": false,
|
||||
|
|
@ -471,9 +414,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Stream the response from the model. Streaming works only in Chat.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -493,9 +434,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "System message to pass to the model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -515,9 +454,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -553,12 +490,7 @@
|
|||
"data": {
|
||||
"id": "ChatOutput-njtka",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Record",
|
||||
"Text",
|
||||
"str",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["Record", "Text", "str", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -583,9 +515,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -616,10 +546,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Message to be passed as output.",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"input_types": ["Text", "Message"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -639,17 +566,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -665,9 +587,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -687,9 +607,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -725,12 +643,7 @@
|
|||
"data": {
|
||||
"id": "ChatInput-P3fgL",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"Record",
|
||||
"str",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["object", "Record", "str", "Text"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -754,9 +667,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -807,17 +718,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -833,9 +739,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -855,9 +759,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -901,4 +803,4 @@
|
|||
"is_component": false,
|
||||
"last_tested_version": "1.0.0a4",
|
||||
"name": "Basic Prompting (Hello, World)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,7 @@
|
|||
"targetHandle": {
|
||||
"fieldName": "reference_2",
|
||||
"id": "Prompt-Rse03",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"BaseOutputParser",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "BaseOutputParser", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -39,17 +34,12 @@
|
|||
"dataType": "OpenAIModel",
|
||||
"id": "OpenAIModel-gi29P",
|
||||
"name": "text_output",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "ChatOutput-JPlxl",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"inputTypes": ["Text", "Message"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -74,12 +64,7 @@
|
|||
"targetHandle": {
|
||||
"fieldName": "reference_1",
|
||||
"id": "Prompt-Rse03",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"BaseOutputParser",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "BaseOutputParser", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -99,19 +84,12 @@
|
|||
"dataType": "TextInput",
|
||||
"id": "TextInput-og8Or",
|
||||
"name": "Text",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "instructions",
|
||||
"id": "Prompt-Rse03",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"BaseOutputParser",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "BaseOutputParser", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -131,18 +109,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-Rse03",
|
||||
"name": "prompt",
|
||||
"output_types": [
|
||||
"Prompt"
|
||||
]
|
||||
"output_types": ["Prompt"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "OpenAIModel-gi29P",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"inputTypes": ["Text", "Data", "Prompt"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -164,18 +136,10 @@
|
|||
"display_name": "Prompt",
|
||||
"id": "Prompt-Rse03",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"Text",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["object", "Text", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"template": [
|
||||
"reference_1",
|
||||
"reference_2",
|
||||
"instructions"
|
||||
]
|
||||
"template": ["reference_1", "reference_2", "instructions"]
|
||||
},
|
||||
"description": "Create a prompt template with dynamic variables.",
|
||||
"display_name": "Prompt",
|
||||
|
|
@ -198,9 +162,7 @@
|
|||
"method": "build_prompt",
|
||||
"name": "prompt",
|
||||
"selected": "Prompt",
|
||||
"types": [
|
||||
"Prompt"
|
||||
],
|
||||
"types": ["Prompt"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -209,9 +171,7 @@
|
|||
"method": "format_prompt",
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -320,9 +280,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -358,9 +316,7 @@
|
|||
"data": {
|
||||
"id": "URL-HYPkR",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Record"
|
||||
],
|
||||
"base_classes": ["Record"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"urls": null
|
||||
|
|
@ -380,9 +336,7 @@
|
|||
"method": "fetch_content",
|
||||
"name": "data",
|
||||
"selected": "Data",
|
||||
"types": [
|
||||
"Data"
|
||||
],
|
||||
"types": ["Data"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -404,7 +358,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "code",
|
||||
"value": "from langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.inputs import StrInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n inputs = [\n StrInput(\n name=\"urls\",\n display_name=\"URLs\",\n info=\"Enter one or more URLs, separated by commas.\",\n value=\"\",\n is_list=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n ]\n\n def fetch_content(self) -> Data:\n urls = [url.strip() for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n data = [Data(content=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n"
|
||||
"value": "from langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.inputs import StrInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\nimport re\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n inputs = [\n StrInput(\n name=\"urls\",\n display_name=\"URLs\",\n info=\"Enter one or more URLs, separated by commas.\",\n value=\"\",\n is_list=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n ]\n\n def ensure_url(self, string: str) -> str:\n \"\"\"\n Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(http://|https://)?\" # http:// or https://\n r\"(([a-zA-Z0-9\\.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,}))\" # top-level domain\n r\"(:[0-9]{1,5})?\" # optional port\n r\"(\\/.*)?$\" # optional path\n )\n\n if not re.match(url_regex, string):\n raise ValueError(f\"Invalid URL: {string}\")\n\n return string\n\n def fetch_content(self) -> Data:\n urls = [self.ensure_url(url.strip()) for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n data = [Data(content=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n"
|
||||
},
|
||||
"urls": {
|
||||
"advanced": false,
|
||||
|
|
@ -444,12 +398,7 @@
|
|||
"data": {
|
||||
"id": "ChatOutput-JPlxl",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Text",
|
||||
"Record",
|
||||
"object",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["Text", "Record", "object", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -474,9 +423,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -507,10 +454,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Message to be passed as output.",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"input_types": ["Text", "Message"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -530,17 +474,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -556,9 +495,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -578,9 +515,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -611,11 +546,7 @@
|
|||
"data": {
|
||||
"id": "OpenAIModel-gi29P",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -653,9 +584,7 @@
|
|||
"method": "text_response",
|
||||
"name": "text_output",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -664,9 +593,7 @@
|
|||
"method": "build_model",
|
||||
"name": "model_output",
|
||||
"selected": "BaseLanguageModel",
|
||||
"types": [
|
||||
"BaseLanguageModel"
|
||||
],
|
||||
"types": ["BaseLanguageModel"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -697,11 +624,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"input_types": ["Text", "Data", "Prompt"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -721,9 +644,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -743,9 +664,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -765,9 +684,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -785,7 +702,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "str",
|
||||
"value": "gpt-4o"
|
||||
"value": "gpt-3.5-turbo"
|
||||
},
|
||||
"openai_api_base": {
|
||||
"advanced": true,
|
||||
|
|
@ -794,9 +711,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -816,9 +731,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The OpenAI API Key to use for the OpenAI model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": true,
|
||||
"multiline": false,
|
||||
|
|
@ -838,9 +751,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Stream the response from the model. Streaming works only in Chat.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -860,9 +771,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "System message to pass to the model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -882,9 +791,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -920,9 +827,7 @@
|
|||
"data": {
|
||||
"id": "URL-2cX90",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Record"
|
||||
],
|
||||
"base_classes": ["Record"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"urls": null
|
||||
|
|
@ -942,9 +847,7 @@
|
|||
"method": "fetch_content",
|
||||
"name": "data",
|
||||
"selected": "Data",
|
||||
"types": [
|
||||
"Data"
|
||||
],
|
||||
"types": ["Data"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -966,7 +869,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "code",
|
||||
"value": "from langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.inputs import StrInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n inputs = [\n StrInput(\n name=\"urls\",\n display_name=\"URLs\",\n info=\"Enter one or more URLs, separated by commas.\",\n value=\"\",\n is_list=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n ]\n\n def fetch_content(self) -> Data:\n urls = [url.strip() for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n data = [Data(content=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n"
|
||||
"value": "from langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.inputs import StrInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\nimport re\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n inputs = [\n StrInput(\n name=\"urls\",\n display_name=\"URLs\",\n info=\"Enter one or more URLs, separated by commas.\",\n value=\"\",\n is_list=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n ]\n\n def ensure_url(self, string: str) -> str:\n \"\"\"\n Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(http://|https://)?\" # http:// or https://\n r\"(([a-zA-Z0-9\\.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,}))\" # top-level domain\n r\"(:[0-9]{1,5})?\" # optional port\n r\"(\\/.*)?$\" # optional path\n )\n\n if not re.match(url_regex, string):\n raise ValueError(f\"Invalid URL: {string}\")\n\n return string\n\n def fetch_content(self) -> Data:\n urls = [self.ensure_url(url.strip()) for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n data = [Data(content=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n"
|
||||
},
|
||||
"urls": {
|
||||
"advanced": false,
|
||||
|
|
@ -1006,11 +909,7 @@
|
|||
"data": {
|
||||
"id": "TextInput-og8Or",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"Text",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["object", "Text", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -1023,16 +922,12 @@
|
|||
"field_order": [],
|
||||
"frozen": false,
|
||||
"icon": "type",
|
||||
"output_types": [
|
||||
"Text"
|
||||
],
|
||||
"output_types": ["Text"],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "Text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
]
|
||||
"types": ["Text"]
|
||||
}
|
||||
],
|
||||
"template": {
|
||||
|
|
@ -1062,10 +957,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Text or Record to be passed as input.",
|
||||
"input_types": [
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1085,9 +977,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -1131,4 +1021,4 @@
|
|||
"is_component": false,
|
||||
"last_tested_version": "1.0.0a0",
|
||||
"name": "Blog Writer"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,19 +7,12 @@
|
|||
"dataType": "File",
|
||||
"id": "File-BzIs2",
|
||||
"name": "data",
|
||||
"output_types": [
|
||||
"Data"
|
||||
]
|
||||
"output_types": ["Data"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "Document",
|
||||
"id": "Prompt-9DNZG",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Data",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "Message", "Data", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -35,19 +28,12 @@
|
|||
"dataType": "ChatInput",
|
||||
"id": "ChatInput-27Usy",
|
||||
"name": "message",
|
||||
"output_types": [
|
||||
"Message"
|
||||
]
|
||||
"output_types": ["Message"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "Question",
|
||||
"id": "Prompt-9DNZG",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Data",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "Message", "Data", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -63,18 +49,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-9DNZG",
|
||||
"name": "prompt",
|
||||
"output_types": [
|
||||
"Prompt"
|
||||
]
|
||||
"output_types": ["Prompt"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "OpenAIModel-8b6nG",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"inputTypes": ["Text", "Data", "Prompt"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -90,17 +70,12 @@
|
|||
"dataType": "OpenAIModel",
|
||||
"id": "OpenAIModel-8b6nG",
|
||||
"name": "text_output",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "ChatOutput-y4SCS",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"inputTypes": ["Text", "Message"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -118,18 +93,11 @@
|
|||
"display_name": "Prompt",
|
||||
"id": "Prompt-9DNZG",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"str",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["object", "str", "Text"],
|
||||
"beta": false,
|
||||
"conditional_paths": [],
|
||||
"custom_fields": {
|
||||
"template": [
|
||||
"Document",
|
||||
"Question"
|
||||
]
|
||||
"template": ["Document", "Question"]
|
||||
},
|
||||
"description": "Create a prompt template with dynamic variables.",
|
||||
"display_name": "Prompt",
|
||||
|
|
@ -151,9 +119,7 @@
|
|||
"method": "build_prompt",
|
||||
"name": "prompt",
|
||||
"selected": "Prompt",
|
||||
"types": [
|
||||
"Prompt"
|
||||
],
|
||||
"types": ["Prompt"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -162,9 +128,7 @@
|
|||
"method": "format_prompt",
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -178,12 +142,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Data",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Document", "Message", "Data", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -204,12 +163,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Data",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Document", "Message", "Data", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -248,9 +202,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -286,12 +238,7 @@
|
|||
"data": {
|
||||
"id": "ChatInput-27Usy",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Record",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Record", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -315,9 +262,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -368,17 +313,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -394,9 +334,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -416,9 +354,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -454,12 +390,7 @@
|
|||
"data": {
|
||||
"id": "ChatOutput-y4SCS",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Record",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Record", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -483,9 +414,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -516,10 +445,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Message to be passed as output.",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"input_types": ["Text", "Message"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -539,17 +465,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -565,9 +486,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -587,9 +506,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -627,9 +544,7 @@
|
|||
"display_name": "File",
|
||||
"id": "File-BzIs2",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Data"
|
||||
],
|
||||
"base_classes": ["Data"],
|
||||
"beta": false,
|
||||
"conditional_paths": [],
|
||||
"custom_fields": {},
|
||||
|
|
@ -637,10 +552,7 @@
|
|||
"display_name": "File",
|
||||
"documentation": "",
|
||||
"edited": true,
|
||||
"field_order": [
|
||||
"path",
|
||||
"silent_errors"
|
||||
],
|
||||
"field_order": ["path", "silent_errors"],
|
||||
"frozen": false,
|
||||
"icon": "file-text",
|
||||
"output_types": [],
|
||||
|
|
@ -651,9 +563,7 @@
|
|||
"method": "load_file",
|
||||
"name": "data",
|
||||
"selected": "Data",
|
||||
"types": [
|
||||
"Data"
|
||||
],
|
||||
"types": ["Data"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -750,10 +660,7 @@
|
|||
"data": {
|
||||
"id": "OpenAIModel-8b6nG",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"BaseLanguageModel",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["BaseLanguageModel", "Text"],
|
||||
"beta": false,
|
||||
"conditional_paths": [],
|
||||
"custom_fields": {},
|
||||
|
|
@ -781,9 +688,7 @@
|
|||
"method": "text_response",
|
||||
"name": "text_output",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -792,9 +697,7 @@
|
|||
"method": "build_model",
|
||||
"name": "model_output",
|
||||
"selected": "BaseLanguageModel",
|
||||
"types": [
|
||||
"BaseLanguageModel"
|
||||
],
|
||||
"types": ["BaseLanguageModel"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -824,11 +727,7 @@
|
|||
"display_name": "Input",
|
||||
"dynamic": false,
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"input_types": ["Text", "Data", "Prompt"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"name": "input_value",
|
||||
|
|
@ -883,7 +782,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "str",
|
||||
"value": "gpt-4o"
|
||||
"value": "gpt-3.5-turbo"
|
||||
},
|
||||
"openai_api_base": {
|
||||
"advanced": true,
|
||||
|
|
@ -905,9 +804,7 @@
|
|||
"display_name": "OpenAI API Key",
|
||||
"dynamic": false,
|
||||
"info": "The OpenAI API Key to use for the OpenAI model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"load_from_db": true,
|
||||
"name": "openai_api_key",
|
||||
"password": true,
|
||||
|
|
@ -992,4 +889,4 @@
|
|||
"is_component": false,
|
||||
"last_tested_version": "1.0.0a52",
|
||||
"name": "Document QA"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,19 +8,12 @@
|
|||
"dataType": "MemoryComponent",
|
||||
"id": "MemoryComponent-cdA1J",
|
||||
"name": "text",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "context",
|
||||
"id": "Prompt-ODkUx",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "Message", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -41,19 +34,12 @@
|
|||
"dataType": "ChatInput",
|
||||
"id": "ChatInput-t7F8v",
|
||||
"name": "message",
|
||||
"output_types": [
|
||||
"Message"
|
||||
]
|
||||
"output_types": ["Message"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "user_message",
|
||||
"id": "Prompt-ODkUx",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "Message", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -74,18 +60,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-ODkUx",
|
||||
"name": "prompt",
|
||||
"output_types": [
|
||||
"Prompt"
|
||||
]
|
||||
"output_types": ["Prompt"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "OpenAIModel-9RykF",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"inputTypes": ["Text", "Data", "Prompt"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -105,17 +85,12 @@
|
|||
"dataType": "OpenAIModel",
|
||||
"id": "OpenAIModel-9RykF",
|
||||
"name": "text_output",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "ChatOutput-P1jEe",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"inputTypes": ["Text", "Message"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -135,17 +110,12 @@
|
|||
"dataType": "MemoryComponent",
|
||||
"id": "MemoryComponent-cdA1J",
|
||||
"name": "text",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "TextOutput-vrs6T",
|
||||
"inputTypes": [
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -164,12 +134,7 @@
|
|||
"data": {
|
||||
"id": "ChatInput-t7F8v",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Text",
|
||||
"object",
|
||||
"Record",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["Text", "object", "Record", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -193,9 +158,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -246,17 +209,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -272,9 +230,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -294,9 +250,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -332,12 +286,7 @@
|
|||
"data": {
|
||||
"id": "ChatOutput-P1jEe",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Text",
|
||||
"object",
|
||||
"Record",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["Text", "object", "Record", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -361,9 +310,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -394,10 +341,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Message to be passed as output.",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"input_types": ["Text", "Message"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -417,17 +361,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -443,9 +382,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -465,9 +402,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -505,11 +440,7 @@
|
|||
"display_name": "Chat Memory",
|
||||
"id": "MemoryComponent-cdA1J",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Text", "object"],
|
||||
"beta": true,
|
||||
"custom_fields": {
|
||||
"n_messages": null,
|
||||
|
|
@ -526,9 +457,7 @@
|
|||
"field_order": [],
|
||||
"frozen": false,
|
||||
"icon": "history",
|
||||
"output_types": [
|
||||
"Text"
|
||||
],
|
||||
"output_types": ["Text"],
|
||||
"outputs": [
|
||||
{
|
||||
"cache": true,
|
||||
|
|
@ -537,9 +466,7 @@
|
|||
"method": null,
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -589,17 +516,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Order of the messages.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "order",
|
||||
"options": [
|
||||
"Ascending",
|
||||
"Descending"
|
||||
],
|
||||
"options": ["Ascending", "Descending"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -615,18 +537,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User",
|
||||
"Machine and User"
|
||||
],
|
||||
"options": ["Machine", "User", "Machine and User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -642,9 +558,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -663,9 +577,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID of the chat history.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -703,17 +615,10 @@
|
|||
"display_name": "Prompt",
|
||||
"id": "Prompt-ODkUx",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"Text",
|
||||
"str",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["Text", "str", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"template": [
|
||||
"context",
|
||||
"user_message"
|
||||
]
|
||||
"template": ["context", "user_message"]
|
||||
},
|
||||
"description": "Create a prompt template with dynamic variables.",
|
||||
"display_name": "Prompt",
|
||||
|
|
@ -736,9 +641,7 @@
|
|||
"method": "build_prompt",
|
||||
"name": "prompt",
|
||||
"selected": "Prompt",
|
||||
"types": [
|
||||
"Prompt"
|
||||
],
|
||||
"types": ["Prompt"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -747,9 +650,7 @@
|
|||
"method": "format_prompt",
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -781,12 +682,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Document", "Message", "Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -806,9 +702,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -829,12 +723,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Document", "Message", "Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -870,11 +759,7 @@
|
|||
"data": {
|
||||
"id": "OpenAIModel-9RykF",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"object",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["str", "object", "Text"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -912,9 +797,7 @@
|
|||
"method": "text_response",
|
||||
"name": "text_output",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -923,9 +806,7 @@
|
|||
"method": "build_model",
|
||||
"name": "model_output",
|
||||
"selected": "BaseLanguageModel",
|
||||
"types": [
|
||||
"BaseLanguageModel"
|
||||
],
|
||||
"types": ["BaseLanguageModel"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -956,11 +837,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"input_types": ["Text", "Data", "Prompt"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -980,9 +857,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1002,9 +877,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1024,9 +897,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1044,7 +915,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "str",
|
||||
"value": "gpt-4o"
|
||||
"value": "gpt-3.5-turbo"
|
||||
},
|
||||
"openai_api_base": {
|
||||
"advanced": true,
|
||||
|
|
@ -1053,9 +924,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1075,9 +944,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The OpenAI API Key to use for the OpenAI model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": true,
|
||||
"multiline": false,
|
||||
|
|
@ -1097,9 +964,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Stream the response from the model. Streaming works only in Chat.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1119,9 +984,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "System message to pass to the model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1141,9 +1004,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1179,11 +1040,7 @@
|
|||
"data": {
|
||||
"id": "TextOutput-vrs6T",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"object",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["str", "object", "Text"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -1196,9 +1053,7 @@
|
|||
"field_order": [],
|
||||
"frozen": false,
|
||||
"icon": "type",
|
||||
"output_types": [
|
||||
"Text"
|
||||
],
|
||||
"output_types": ["Text"],
|
||||
"template": {
|
||||
"_type": "CustomComponent",
|
||||
"code": {
|
||||
|
|
@ -1226,10 +1081,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Text or Record to be passed as output.",
|
||||
"input_types": [
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1249,9 +1101,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -1297,4 +1147,4 @@
|
|||
"is_component": false,
|
||||
"last_tested_version": "1.0.0a0",
|
||||
"name": "Memory Chatbot"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,19 +8,12 @@
|
|||
"dataType": "TextInput",
|
||||
"id": "TextInput-sptaH",
|
||||
"name": "text",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "document",
|
||||
"id": "Prompt-amqBu",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "Message", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -40,17 +33,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-amqBu",
|
||||
"name": "text",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "TextOutput-2MS4a",
|
||||
"inputTypes": [
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -70,18 +58,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-amqBu",
|
||||
"name": "prompt",
|
||||
"output_types": [
|
||||
"Prompt"
|
||||
]
|
||||
"output_types": ["Prompt"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "OpenAIModel-uYXZJ",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"inputTypes": ["Text", "Data", "Prompt"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -101,19 +83,12 @@
|
|||
"dataType": "OpenAIModel",
|
||||
"id": "OpenAIModel-uYXZJ",
|
||||
"name": "text_output",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "summary",
|
||||
"id": "Prompt-gTNiz",
|
||||
"inputTypes": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Document", "Message", "Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -133,17 +108,12 @@
|
|||
"dataType": "OpenAIModel",
|
||||
"id": "OpenAIModel-uYXZJ",
|
||||
"name": "text_output",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "ChatOutput-EJkG3",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"inputTypes": ["Text", "Message"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -163,17 +133,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-gTNiz",
|
||||
"name": "text",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "TextOutput-MUDOR",
|
||||
"inputTypes": [
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"inputTypes": ["Record", "Text"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -193,18 +158,12 @@
|
|||
"dataType": "Prompt",
|
||||
"id": "Prompt-gTNiz",
|
||||
"name": "prompt",
|
||||
"output_types": [
|
||||
"Prompt"
|
||||
]
|
||||
"output_types": ["Prompt"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "OpenAIModel-XawYB",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"inputTypes": ["Text", "Data", "Prompt"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -224,17 +183,12 @@
|
|||
"dataType": "OpenAIModel",
|
||||
"id": "OpenAIModel-XawYB",
|
||||
"name": "text_output",
|
||||
"output_types": [
|
||||
"Text"
|
||||
]
|
||||
"output_types": ["Text"]
|
||||
},
|
||||
"targetHandle": {
|
||||
"fieldName": "input_value",
|
||||
"id": "ChatOutput-DNmvg",
|
||||
"inputTypes": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"inputTypes": ["Text", "Message"],
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
|
|
@ -255,16 +209,10 @@
|
|||
"display_name": "Prompt",
|
||||
"id": "Prompt-amqBu",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"str",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["object", "str", "Text"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"template": [
|
||||
"document"
|
||||
]
|
||||
"template": ["document"]
|
||||
},
|
||||
"description": "Create a prompt template with dynamic variables.",
|
||||
"display_name": "Prompt",
|
||||
|
|
@ -287,9 +235,7 @@
|
|||
"method": "build_prompt",
|
||||
"name": "prompt",
|
||||
"selected": "Prompt",
|
||||
"types": [
|
||||
"Prompt"
|
||||
],
|
||||
"types": ["Prompt"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -298,9 +244,7 @@
|
|||
"method": "format_prompt",
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -332,12 +276,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Document", "Message", "Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -357,9 +296,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -397,16 +334,10 @@
|
|||
"display_name": "Prompt",
|
||||
"id": "Prompt-gTNiz",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"str",
|
||||
"Text"
|
||||
],
|
||||
"base_classes": ["object", "str", "Text"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"template": [
|
||||
"summary"
|
||||
]
|
||||
"template": ["summary"]
|
||||
},
|
||||
"description": "Create a prompt template with dynamic variables.",
|
||||
"display_name": "Prompt",
|
||||
|
|
@ -429,9 +360,7 @@
|
|||
"method": "build_prompt",
|
||||
"name": "prompt",
|
||||
"selected": "Prompt",
|
||||
"types": [
|
||||
"Prompt"
|
||||
],
|
||||
"types": ["Prompt"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -440,9 +369,7 @@
|
|||
"method": "format_prompt",
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -474,12 +401,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Document",
|
||||
"Message",
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Document", "Message", "Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -499,9 +421,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -533,12 +453,7 @@
|
|||
"data": {
|
||||
"id": "ChatOutput-EJkG3",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"Record",
|
||||
"Text",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["object", "Record", "Text", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -563,9 +478,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -596,10 +509,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Message to be passed as output.",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"input_types": ["Text", "Message"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -619,17 +529,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -645,9 +550,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -667,9 +570,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -701,12 +602,7 @@
|
|||
"data": {
|
||||
"id": "ChatOutput-DNmvg",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"object",
|
||||
"Record",
|
||||
"Text",
|
||||
"str"
|
||||
],
|
||||
"base_classes": ["object", "Record", "Text", "str"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -731,9 +627,7 @@
|
|||
"method": "message_response",
|
||||
"name": "message",
|
||||
"selected": "Message",
|
||||
"types": [
|
||||
"Message"
|
||||
],
|
||||
"types": ["Message"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -764,10 +658,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Message to be passed as output.",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Message"
|
||||
],
|
||||
"input_types": ["Text", "Message"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -787,17 +678,12 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Type of sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
"name": "sender",
|
||||
"options": [
|
||||
"Machine",
|
||||
"User"
|
||||
],
|
||||
"options": ["Machine", "User"],
|
||||
"password": false,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
|
|
@ -813,9 +699,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Name of the sender.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -835,9 +719,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Session ID for the message.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -868,11 +750,7 @@
|
|||
"data": {
|
||||
"id": "TextInput-sptaH",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -893,9 +771,7 @@
|
|||
"method": "text_response",
|
||||
"name": "text",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -926,10 +802,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Text to be passed as input.",
|
||||
"input_types": [
|
||||
"Data",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -965,11 +838,7 @@
|
|||
"data": {
|
||||
"id": "TextOutput-2MS4a",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -982,9 +851,7 @@
|
|||
"field_order": [],
|
||||
"frozen": false,
|
||||
"icon": "type",
|
||||
"output_types": [
|
||||
"Text"
|
||||
],
|
||||
"output_types": ["Text"],
|
||||
"template": {
|
||||
"_type": "CustomComponent",
|
||||
"code": {
|
||||
|
|
@ -1012,10 +879,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Text or Record to be passed as output.",
|
||||
"input_types": [
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1035,9 +899,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -1073,11 +935,7 @@
|
|||
"data": {
|
||||
"id": "OpenAIModel-uYXZJ",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -1115,9 +973,7 @@
|
|||
"method": "text_response",
|
||||
"name": "text_output",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -1126,9 +982,7 @@
|
|||
"method": "build_model",
|
||||
"name": "model_output",
|
||||
"selected": "BaseLanguageModel",
|
||||
"types": [
|
||||
"BaseLanguageModel"
|
||||
],
|
||||
"types": ["BaseLanguageModel"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -1159,11 +1013,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"input_types": ["Text", "Data", "Prompt"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1183,9 +1033,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1205,9 +1053,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1227,9 +1073,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1247,7 +1091,7 @@
|
|||
"show": true,
|
||||
"title_case": false,
|
||||
"type": "str",
|
||||
"value": "gpt-4o"
|
||||
"value": "gpt-3.5-turbo"
|
||||
},
|
||||
"openai_api_base": {
|
||||
"advanced": true,
|
||||
|
|
@ -1256,9 +1100,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1278,9 +1120,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The OpenAI API Key to use for the OpenAI model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": true,
|
||||
"multiline": false,
|
||||
|
|
@ -1300,9 +1140,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Stream the response from the model. Streaming works only in Chat.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1322,9 +1160,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "System message to pass to the model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1344,9 +1180,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1382,11 +1216,7 @@
|
|||
"data": {
|
||||
"id": "TextOutput-MUDOR",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -1399,9 +1229,7 @@
|
|||
"field_order": [],
|
||||
"frozen": false,
|
||||
"icon": "type",
|
||||
"output_types": [
|
||||
"Text"
|
||||
],
|
||||
"output_types": ["Text"],
|
||||
"template": {
|
||||
"_type": "CustomComponent",
|
||||
"code": {
|
||||
|
|
@ -1429,10 +1257,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Text or Record to be passed as output.",
|
||||
"input_types": [
|
||||
"Record",
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Record", "Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1452,9 +1277,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": true,
|
||||
|
|
@ -1490,11 +1313,7 @@
|
|||
"data": {
|
||||
"id": "OpenAIModel-XawYB",
|
||||
"node": {
|
||||
"base_classes": [
|
||||
"str",
|
||||
"Text",
|
||||
"object"
|
||||
],
|
||||
"base_classes": ["str", "Text", "object"],
|
||||
"beta": false,
|
||||
"custom_fields": {
|
||||
"input_value": null,
|
||||
|
|
@ -1532,9 +1351,7 @@
|
|||
"method": "text_response",
|
||||
"name": "text_output",
|
||||
"selected": "Text",
|
||||
"types": [
|
||||
"Text"
|
||||
],
|
||||
"types": ["Text"],
|
||||
"value": "__UNDEFINED__"
|
||||
},
|
||||
{
|
||||
|
|
@ -1543,9 +1360,7 @@
|
|||
"method": "build_model",
|
||||
"name": "model_output",
|
||||
"selected": "BaseLanguageModel",
|
||||
"types": [
|
||||
"BaseLanguageModel"
|
||||
],
|
||||
"types": ["BaseLanguageModel"],
|
||||
"value": "__UNDEFINED__"
|
||||
}
|
||||
],
|
||||
|
|
@ -1576,11 +1391,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text",
|
||||
"Data",
|
||||
"Prompt"
|
||||
],
|
||||
"input_types": ["Text", "Data", "Prompt"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1600,9 +1411,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1622,9 +1431,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1644,9 +1451,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": true,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1673,9 +1478,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1695,9 +1498,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "The OpenAI API Key to use for the OpenAI model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": true,
|
||||
"multiline": false,
|
||||
|
|
@ -1717,9 +1518,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "Stream the response from the model. Streaming works only in Chat.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1739,9 +1538,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "System message to pass to the model.",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1761,9 +1558,7 @@
|
|||
"fileTypes": [],
|
||||
"file_path": "",
|
||||
"info": "",
|
||||
"input_types": [
|
||||
"Text"
|
||||
],
|
||||
"input_types": ["Text"],
|
||||
"list": false,
|
||||
"load_from_db": false,
|
||||
"multiline": false,
|
||||
|
|
@ -1807,4 +1602,4 @@
|
|||
"is_component": false,
|
||||
"last_tested_version": "1.0.0a0",
|
||||
"name": "Prompt Chaining"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -160,7 +160,7 @@ async def build_custom_component(params: dict, custom_component: "CustomComponen
|
|||
if raw is None and isinstance(build_result, (dict, Data, str)):
|
||||
raw = build_result.data if isinstance(build_result, Data) else build_result
|
||||
|
||||
artifact_type = get_artifact_type(custom_component.repr_value or raw, build_result)
|
||||
artifact_type = get_artifact_type(custom_component or raw, build_result)
|
||||
raw = post_process_raw(raw, artifact_type)
|
||||
artifact = {"repr": custom_repr, "raw": raw, "type": artifact_type}
|
||||
return custom_component, build_result, artifact
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import warnings
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Annotated, Coroutine, Optional, Union
|
||||
from uuid import UUID
|
||||
import warnings
|
||||
|
||||
from cryptography.fernet import Fernet
|
||||
from fastapi import Depends, HTTPException, Security, status
|
||||
from fastapi.security import APIKeyHeader, APIKeyQuery, OAuth2PasswordBearer
|
||||
|
||||
|
||||
from jose import JWTError, jwt
|
||||
from loguru import logger
|
||||
from sqlmodel import Session
|
||||
from starlette.websockets import WebSocket
|
||||
|
||||
|
|
@ -92,44 +91,58 @@ async def get_current_user_by_jwt(
|
|||
) -> User:
|
||||
settings_service = get_settings_service()
|
||||
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
if isinstance(token, Coroutine):
|
||||
token = await token
|
||||
|
||||
if settings_service.auth_settings.SECRET_KEY.get_secret_value() is None:
|
||||
raise credentials_exception
|
||||
secret_key = settings_service.auth_settings.SECRET_KEY.get_secret_value()
|
||||
if secret_key is None:
|
||||
logger.error("Secret key is not set in settings.")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
# Careful not to leak sensitive information
|
||||
detail="Authentication failure: Verify authentication settings.",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
try:
|
||||
# Ignore warning about datetime.utcnow
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
|
||||
payload = jwt.decode(
|
||||
token,
|
||||
settings_service.auth_settings.SECRET_KEY.get_secret_value(),
|
||||
algorithms=[settings_service.auth_settings.ALGORITHM],
|
||||
)
|
||||
user_id: UUID = payload.get("sub") # type: ignore
|
||||
token_type: str = payload.get("type") # type: ignore
|
||||
payload = jwt.decode(token, secret_key, algorithms=[settings_service.auth_settings.ALGORITHM])
|
||||
user_id: UUID = payload.get("sub")
|
||||
token_type: str = payload.get("type")
|
||||
if expires := payload.get("exp", None):
|
||||
expires_datetime = datetime.fromtimestamp(expires, timezone.utc)
|
||||
# TypeError: can't compare offset-naive and offset-aware datetimes
|
||||
if datetime.now(timezone.utc) > expires_datetime:
|
||||
raise credentials_exception
|
||||
logger.info("Token expired for user")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Token has expired.",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
if user_id is None or token_type:
|
||||
raise credentials_exception
|
||||
logger.info(f"Invalid token payload. Token type: {token_type}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid token details.",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
except JWTError as e:
|
||||
raise credentials_exception from e
|
||||
logger.error(f"JWT decoding error: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
) from e
|
||||
|
||||
user = get_user_by_id(db, user_id) # type: ignore
|
||||
user = get_user_by_id(db, user_id)
|
||||
if user is None or not user.is_active:
|
||||
raise credentials_exception
|
||||
logger.info("User not found or inactive.")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="User not found or is inactive.",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
return user
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,24 +6,21 @@ from typing import TYPE_CHECKING
|
|||
import sqlalchemy as sa
|
||||
from alembic import command, util
|
||||
from alembic.config import Config
|
||||
from loguru import logger
|
||||
from sqlalchemy import inspect
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy import event
|
||||
from sqlmodel import Session, SQLModel, create_engine, select, text
|
||||
|
||||
from langflow.services.base import Service
|
||||
from langflow.services.database import models # noqa
|
||||
from langflow.services.database.models.user.crud import get_user_by_username
|
||||
from langflow.services.database.utils import Result, TableResults
|
||||
from langflow.services.deps import get_settings_service
|
||||
from langflow.services.utils import teardown_superuser
|
||||
from loguru import logger
|
||||
from sqlalchemy import event, inspect
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from sqlmodel import Session, SQLModel, create_engine, select, text
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sqlalchemy.engine import Engine
|
||||
|
||||
from langflow.services.settings.service import SettingsService
|
||||
from sqlalchemy.engine import Engine
|
||||
|
||||
|
||||
class DatabaseService(Service):
|
||||
|
|
@ -48,12 +45,23 @@ class DatabaseService(Service):
|
|||
connect_args = {"check_same_thread": False}
|
||||
else:
|
||||
connect_args = {}
|
||||
return create_engine(
|
||||
self.database_url,
|
||||
connect_args=connect_args,
|
||||
pool_size=self.settings_service.settings.pool_size,
|
||||
max_overflow=self.settings_service.settings.max_overflow,
|
||||
)
|
||||
try:
|
||||
return create_engine(
|
||||
self.database_url,
|
||||
connect_args=connect_args,
|
||||
pool_size=self.settings_service.settings.pool_size,
|
||||
max_overflow=self.settings_service.settings.max_overflow,
|
||||
)
|
||||
except sa.exc.NoSuchModuleError as exc:
|
||||
# sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres
|
||||
if "postgres" in str(exc) and not self.database_url.startswith("postgresql"):
|
||||
# https://stackoverflow.com/questions/62688256/sqlalchemy-exc-nosuchmoduleerror-cant-load-plugin-sqlalchemy-dialectspostgre
|
||||
self.database_url = self.database_url.replace("postgres://", "postgresql://")
|
||||
logger.warning(
|
||||
"Fixed postgres dialect in database URL. Replacing postgres:// with postgresql://. To avoid this warning, update the database URL."
|
||||
)
|
||||
return self._create_engine()
|
||||
raise RuntimeError("Error creating database engine") from exc
|
||||
|
||||
@event.listens_for(Engine, "connect")
|
||||
def on_connection(dbapi_connection, connection_record):
|
||||
|
|
|
|||
|
|
@ -91,9 +91,17 @@ class MessageModel(DefaultModel):
|
|||
files: list[str] = []
|
||||
|
||||
@field_validator("files", mode="before")
|
||||
@classmethod
|
||||
def validate_files(cls, v):
|
||||
if isinstance(v, str):
|
||||
return json.loads(v)
|
||||
v = json.loads(v)
|
||||
return v
|
||||
|
||||
@field_serializer("files")
|
||||
@classmethod
|
||||
def serialize_files(cls, v):
|
||||
if isinstance(v, list):
|
||||
return json.dumps(v)
|
||||
return v
|
||||
|
||||
@classmethod
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@ from pathlib import Path
|
|||
from typing import TYPE_CHECKING, List, Optional, Union
|
||||
|
||||
import duckdb
|
||||
from loguru import logger
|
||||
from platformdirs import user_cache_dir
|
||||
|
||||
from langflow.services.base import Service
|
||||
from langflow.services.monitor.schema import MessageModel, TransactionModel, VertexBuildModel
|
||||
from langflow.services.monitor.utils import add_row_to_table, drop_and_create_table_if_schema_mismatch
|
||||
from loguru import logger
|
||||
from platformdirs import user_cache_dir
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.services.settings.manager import SettingsService
|
||||
|
|
@ -141,7 +140,7 @@ class MonitorService(Service):
|
|||
order: Optional[str] = "DESC",
|
||||
limit: Optional[int] = None,
|
||||
):
|
||||
query = "SELECT index, flow_id, sender_name, sender, session_id, text, timestamp FROM messages"
|
||||
query = "SELECT index, flow_id, sender_name, sender, session_id, text, files, timestamp FROM messages"
|
||||
conditions = []
|
||||
if sender:
|
||||
conditions.append(f"sender = '{sender}'")
|
||||
|
|
|
|||
31
src/backend/base/poetry.lock
generated
31
src/backend/base/poetry.lock
generated
|
|
@ -1158,22 +1158,25 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "langchain"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langchain-0.2.3-py3-none-any.whl", hash = "sha256:5dc33cd9c8008693d328b7cb698df69073acecc89ad9c2a95f243b3314f8d834"},
|
||||
{file = "langchain-0.2.3.tar.gz", hash = "sha256:81962cc72cce6515f7bd71e01542727870789bf8b666c6913d85559080c1a201"},
|
||||
{file = "langchain-0.2.4-py3-none-any.whl", hash = "sha256:a04813215c30f944df006031e2febde872af8fab628dcee825d969e07b6cd621"},
|
||||
{file = "langchain-0.2.4.tar.gz", hash = "sha256:e704b5b06222d5eba2d02c76f891321d1bac8952ed54e093831b2bdabf99dcd5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
aiohttp = ">=3.8.3,<4.0.0"
|
||||
async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""}
|
||||
langchain-core = ">=0.2.0,<0.3.0"
|
||||
langchain-core = ">=0.2.6,<0.3.0"
|
||||
langchain-text-splitters = ">=0.2.0,<0.3.0"
|
||||
langsmith = ">=0.1.17,<0.2.0"
|
||||
numpy = ">=1,<2"
|
||||
numpy = [
|
||||
{version = ">=1,<2", markers = "python_version < \"3.12\""},
|
||||
{version = ">=1.26.0,<2.0.0", markers = "python_version >= \"3.12\""},
|
||||
]
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
requests = ">=2,<3"
|
||||
|
|
@ -1205,19 +1208,19 @@ tenacity = ">=8.1.0,<9.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "langchain-core"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langchain_core-0.2.5-py3-none-any.whl", hash = "sha256:abe5138f22acff23a079ec538be5268bbf97cf023d51987a0dd474d2a16cae3e"},
|
||||
{file = "langchain_core-0.2.5.tar.gz", hash = "sha256:4a5c2f56b22396a63ef4790043660e393adbfa6832b978f023ca996a04b8e752"},
|
||||
{file = "langchain_core-0.2.6-py3-none-any.whl", hash = "sha256:90521c9fc95d8f925e0d2e2d952382676aea6d3f8de611eda1b1810874c31e5d"},
|
||||
{file = "langchain_core-0.2.6.tar.gz", hash = "sha256:9f0e38da722a558a6e95b6d86de01bd92e84558c47ac8ba599f02eab70a1c873"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
jsonpatch = ">=1.33,<2.0"
|
||||
langsmith = ">=0.1.66,<0.2.0"
|
||||
packaging = ">=23.2,<24.0"
|
||||
langsmith = ">=0.1.75,<0.2.0"
|
||||
packaging = ">=23.2,<25"
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
tenacity = ">=8.1.0,<9.0.0"
|
||||
|
|
@ -1859,13 +1862,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "23.2"
|
||||
version = "24.1"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
|
||||
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
|
||||
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "langflow-base"
|
||||
version = "0.0.63"
|
||||
version = "0.0.68"
|
||||
description = "A Python package with a built-in web application"
|
||||
authors = ["Langflow <contact@langflow.org>"]
|
||||
maintainers = [
|
||||
|
|
|
|||
963
src/frontend/package-lock.json
generated
963
src/frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -85,9 +85,6 @@
|
|||
"format": "npx prettier --write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
|
||||
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "npx pretty-quick --staged"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
|
|
@ -130,7 +127,6 @@
|
|||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-organize-imports": "^3.2.3",
|
||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"tailwindcss-dotted-background": "^1.1.0",
|
||||
|
|
@ -138,4 +134,4 @@
|
|||
"ua-parser-js": "^1.0.37",
|
||||
"vite": "^4.5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,13 +18,13 @@ import { autoLogin, getGlobalVariables, getHealth } from "./controllers/API";
|
|||
import { setupAxiosDefaults } from "./controllers/API/utils";
|
||||
import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path";
|
||||
import Router from "./routes";
|
||||
import { Case } from "./shared/components/caseComponent";
|
||||
import useAlertStore from "./stores/alertStore";
|
||||
import { useDarkStore } from "./stores/darkStore";
|
||||
import useFlowsManagerStore from "./stores/flowsManagerStore";
|
||||
import { useFolderStore } from "./stores/foldersStore";
|
||||
import { useGlobalVariablesStore } from "./stores/globalVariablesStore/globalVariables";
|
||||
import { useStoreStore } from "./stores/storeStore";
|
||||
import { useTypesStore } from "./stores/typesStore";
|
||||
export default function App() {
|
||||
useTrackLastVisitedPath();
|
||||
|
||||
|
|
@ -43,10 +43,8 @@ export default function App() {
|
|||
|
||||
const { isAuthenticated, login, setUserData, setAutoLogin, getUser } =
|
||||
useContext(AuthContext);
|
||||
const refreshFlows = useFlowsManagerStore((state) => state.refreshFlows);
|
||||
const setLoading = useAlertStore((state) => state.setLoading);
|
||||
const fetchApiData = useStoreStore((state) => state.fetchApiData);
|
||||
const getTypes = useTypesStore((state) => state.getTypes);
|
||||
const refreshVersion = useDarkStore((state) => state.refreshVersion);
|
||||
const refreshStars = useDarkStore((state) => state.refreshStars);
|
||||
const setGlobalVariables = useGlobalVariablesStore(
|
||||
|
|
@ -56,8 +54,7 @@ export default function App() {
|
|||
const navigate = useNavigate();
|
||||
const dark = useDarkStore((state) => state.dark);
|
||||
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
const loadingFolders = useFolderStore((state) => state.loading);
|
||||
const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
|
||||
|
||||
const [isLoadingHealth, setIsLoadingHealth] = useState(false);
|
||||
|
||||
|
|
@ -80,7 +77,6 @@ export default function App() {
|
|||
login(user["access_token"]);
|
||||
setUserData(user);
|
||||
setAutoLogin(true);
|
||||
setLoading(false);
|
||||
fetchAllData();
|
||||
}
|
||||
})
|
||||
|
|
@ -116,13 +112,13 @@ export default function App() {
|
|||
if (isAuthenticated) {
|
||||
try {
|
||||
await setupAxiosDefaults();
|
||||
await getFoldersApi();
|
||||
await getTypes();
|
||||
await refreshFlows();
|
||||
|
||||
const res = await getGlobalVariables();
|
||||
setGlobalVariables(res);
|
||||
|
||||
checkHasStore();
|
||||
fetchApiData();
|
||||
|
||||
resolve();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch data:", error);
|
||||
|
|
@ -175,6 +171,8 @@ export default function App() {
|
|||
}
|
||||
};
|
||||
|
||||
const isLoadingApplication = isLoading || isLoadingFolders;
|
||||
|
||||
return (
|
||||
//need parent component with width and height
|
||||
<div className="flex h-full flex-col">
|
||||
|
|
@ -197,15 +195,15 @@ export default function App() {
|
|||
></FetchErrorComponent>
|
||||
}
|
||||
|
||||
{isLoading || loadingFolders ? (
|
||||
<Case condition={isLoadingApplication}>
|
||||
<div className="loading-page-panel">
|
||||
<LoadingComponent remSize={50} />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Router />
|
||||
</>
|
||||
)}
|
||||
</Case>
|
||||
|
||||
<Case condition={!isLoadingApplication}>
|
||||
<Router />
|
||||
</Case>
|
||||
</>
|
||||
</ErrorBoundary>
|
||||
<div></div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { ReactNode, useEffect, useRef, useState } from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||
import DictComponent from "../../../../components/dictComponent";
|
||||
|
|
@ -18,7 +17,10 @@ import TextAreaComponent from "../../../../components/textAreaComponent";
|
|||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import { RefreshButton } from "../../../../components/ui/refreshButton";
|
||||
import { LANGFLOW_SUPPORTED_TYPES } from "../../../../constants/constants";
|
||||
import {
|
||||
LANGFLOW_SUPPORTED_TYPES,
|
||||
TOOLTIP_EMPTY,
|
||||
} from "../../../../constants/constants";
|
||||
import { Case } from "../../../../shared/components/caseComponent";
|
||||
import useFlowStore from "../../../../stores/flowStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
|
|
@ -49,8 +51,10 @@ import useHandleNodeClass from "../../../hooks/use-handle-node-class";
|
|||
import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons";
|
||||
import HandleTooltips from "../HandleTooltipComponent";
|
||||
import OutputComponent from "../OutputComponent";
|
||||
import OutputModal from "../outputModal";
|
||||
import TooltipRenderComponent from "../tooltipRenderComponent";
|
||||
import { TEXT_FIELD_TYPES } from "./constants";
|
||||
import OutputModal from "../outputModal";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
|
||||
export default function ParameterComponent({
|
||||
left,
|
||||
|
|
@ -71,6 +75,8 @@ export default function ParameterComponent({
|
|||
selected,
|
||||
outputProxy,
|
||||
}: ParameterComponentType): JSX.Element {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const refHtml = useRef<HTMLDivElement & ReactNode>(null);
|
||||
const infoHtml = useRef<HTMLDivElement & ReactNode>(null);
|
||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
|
|
@ -81,13 +87,16 @@ export default function ParameterComponent({
|
|||
const [isLoading, setIsLoading] = useState(false);
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
const flow = currentFlow?.data?.nodes ?? null;
|
||||
const groupedEdge = useRef(null);
|
||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||
const [openOutputModal, setOpenOutputModal] = useState(false);
|
||||
const flowPool = useFlowStore((state) => state.flowPool);
|
||||
|
||||
const isValid =
|
||||
const displayOutputPreview =
|
||||
!!flowPool[data.id] &&
|
||||
flowPool[data.id][flowPool[data.id].length - 1]?.valid;
|
||||
flowPool[data.id][flowPool[data.id].length - 1]?.valid &&
|
||||
flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.message;
|
||||
|
||||
const flowPoolNode = (flowPool[data.id] ?? [])[
|
||||
(flowPool[data.id]?.length ?? 1) - 1
|
||||
|
|
@ -96,7 +105,6 @@ export default function ParameterComponent({
|
|||
if (flowPoolNode?.data?.logs && outputName) {
|
||||
hasOutputs = flowPoolNode?.data?.logs[outputName] ?? null;
|
||||
}
|
||||
const displayOutputPreview = isValid && hasOutputs;
|
||||
const unknownOutput = !!(
|
||||
flowPool[data.id] &&
|
||||
flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.type ===
|
||||
|
|
@ -157,7 +165,7 @@ export default function ParameterComponent({
|
|||
|
||||
const handleOnNewValue = async (
|
||||
newValue: string | string[] | boolean | Object[],
|
||||
skipSnapshot: boolean | undefined = false
|
||||
skipSnapshot: boolean | undefined = false,
|
||||
): Promise<void> => {
|
||||
handleOnNewValueHook(newValue, skipSnapshot);
|
||||
};
|
||||
|
|
@ -270,7 +278,7 @@ export default function ParameterComponent({
|
|||
className={classNames(
|
||||
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
|
||||
"h-3 w-3 rounded-full border-2 bg-background",
|
||||
!showNode ? "mt-0" : ""
|
||||
!showNode ? "mt-0" : "",
|
||||
)}
|
||||
style={{
|
||||
borderColor: color ?? nodeColors.unknown,
|
||||
|
|
@ -287,6 +295,7 @@ export default function ParameterComponent({
|
|||
)
|
||||
) : (
|
||||
<div
|
||||
ref={ref}
|
||||
className={
|
||||
"relative mt-1 flex w-full flex-wrap items-center justify-between bg-muted px-5 py-2" +
|
||||
((name === "code" && type === "code") ||
|
||||
|
|
|
|||
|
|
@ -464,10 +464,11 @@ export default function GenericNode({
|
|||
.filter((templateField) => templateField.charAt(0) !== "_")
|
||||
.map(
|
||||
(templateField: string, idx) =>
|
||||
data.node!.template[templateField].show &&
|
||||
!data.node!.template[templateField].advanced && (
|
||||
data.node!.template[templateField]?.show &&
|
||||
!data.node!.template[templateField]?.advanced && (
|
||||
<ParameterComponent
|
||||
index={idx}
|
||||
selected={selected}
|
||||
index={idx.toString()}
|
||||
key={scapedJSONStringfy({
|
||||
inputTypes:
|
||||
data.node!.template[templateField].input_types,
|
||||
|
|
@ -551,7 +552,7 @@ export default function GenericNode({
|
|||
title={
|
||||
data.node?.output_types &&
|
||||
data.node.output_types.length > 0
|
||||
? data.node.output_types.join("|")
|
||||
? data.node.output_types.join(" | ")
|
||||
: data.type
|
||||
}
|
||||
tooltipTitle={data.node?.base_classes.join("\n")}
|
||||
|
|
@ -724,10 +725,11 @@ export default function GenericNode({
|
|||
.sort((a, b) => sortFields(a, b, data.node?.field_order ?? []))
|
||||
.map((templateField: string, idx) => (
|
||||
<div key={idx}>
|
||||
{data.node!.template[templateField].show &&
|
||||
!data.node!.template[templateField].advanced ? (
|
||||
{data.node!.template[templateField]?.show &&
|
||||
!data.node!.template[templateField]?.advanced ? (
|
||||
<ParameterComponent
|
||||
index={idx}
|
||||
selected={selected}
|
||||
index={idx.toString()}
|
||||
key={scapedJSONStringfy({
|
||||
inputTypes:
|
||||
data.node!.template[templateField].input_types,
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ export function countHandlesFn(data: NodeDataType): number {
|
|||
.filter((templateField) => templateField.charAt(0) !== "_")
|
||||
.map((templateCamp) => {
|
||||
const { template } = data.node!;
|
||||
if (template[templateCamp].input_types) return true;
|
||||
if (!template[templateCamp].show) return false;
|
||||
switch (template[templateCamp].type) {
|
||||
if (template[templateCamp]?.input_types) return true;
|
||||
if (!template[templateCamp]?.show) return false;
|
||||
switch (template[templateCamp]?.type) {
|
||||
case "str":
|
||||
case "bool":
|
||||
case "float":
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
ERROR_UPDATING_COMPONENT,
|
||||
TITLE_ERROR_UPDATING_COMPONENT,
|
||||
} from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { ResponseErrorDetailAPI } from "../../types/api";
|
||||
|
||||
|
|
@ -38,8 +42,10 @@ const useFetchDataOnMount = (
|
|||
let responseError = error as ResponseErrorDetailAPI;
|
||||
|
||||
setErrorData({
|
||||
title: "Error while updating the Component",
|
||||
list: [responseError?.response?.data?.detail ?? "Unknown error"],
|
||||
title: TITLE_ERROR_UPDATING_COMPONENT,
|
||||
list: [
|
||||
responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT,
|
||||
],
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import {
|
||||
ERROR_UPDATING_COMPONENT,
|
||||
TITLE_ERROR_UPDATING_COMPONENT,
|
||||
} from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { ResponseErrorTypeAPI } from "../../types/api";
|
||||
|
||||
|
|
@ -42,9 +46,10 @@ const useHandleOnNewValue = (
|
|||
} catch (error) {
|
||||
let responseError = error as ResponseErrorTypeAPI;
|
||||
setErrorData({
|
||||
title: "Error while updating the Component",
|
||||
title: TITLE_ERROR_UPDATING_COMPONENT,
|
||||
list: [
|
||||
responseError?.response?.data?.detail.error ?? "Unknown error",
|
||||
responseError?.response?.data?.detail.error ??
|
||||
ERROR_UPDATING_COMPONENT,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import {
|
||||
ERROR_UPDATING_COMPONENT,
|
||||
TITLE_ERROR_UPDATING_COMPONENT,
|
||||
} from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { ResponseErrorDetailAPI } from "../../types/api";
|
||||
import { handleUpdateValues } from "../../utils/parameterUtils";
|
||||
|
|
@ -25,8 +29,10 @@ const useHandleRefreshButtonPress = (setIsLoading, setNode) => {
|
|||
let responseError = error as ResponseErrorDetailAPI;
|
||||
|
||||
setErrorData({
|
||||
title: "Error while updating the Component",
|
||||
list: [responseError?.response?.data?.detail ?? "Unknown error"],
|
||||
title: TITLE_ERROR_UPDATING_COMPONENT,
|
||||
list: [
|
||||
responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT,
|
||||
],
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
|
|
|
|||
|
|
@ -70,7 +70,10 @@ export default function AddNewVariableButton({
|
|||
let responseError = error as ResponseErrorDetailAPI;
|
||||
setErrorData({
|
||||
title: "Error creating variable",
|
||||
list: [responseError?.response?.data?.detail ?? "Unknown error"],
|
||||
list: [
|
||||
responseError?.response?.data?.detail ??
|
||||
"An unexpected error occurred while adding a new variable. Please try again.",
|
||||
],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export default function Header(): JSX.Element {
|
|||
const location = useLocation();
|
||||
|
||||
const { logout, autoLogin, isAdmin, userData } = useContext(AuthContext);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const removeFlow = useFlowsManagerStore((store) => store.removeFlow);
|
||||
const hasStore = useStoreStore((state) => state.hasStore);
|
||||
|
|
@ -208,7 +209,7 @@ export default function Header(): JSX.Element {
|
|||
0,
|
||||
BACKEND_URL.length - 1
|
||||
)}${BASE_URL_API}files/profile_pictures/${
|
||||
userData?.profile_image ?? "Space/046-rocket.png"
|
||||
userData?.profile_image ?? "Space/046-rocket.svg"
|
||||
}` ?? profileCircle
|
||||
}
|
||||
className="h-7 w-7 shrink-0 focus-visible:outline-0"
|
||||
|
|
@ -226,7 +227,7 @@ export default function Header(): JSX.Element {
|
|||
0,
|
||||
BACKEND_URL.length - 1
|
||||
)}${BASE_URL_API}files/profile_pictures/${
|
||||
userData?.profile_image
|
||||
userData?.profile_image ?? "Space/046-rocket.svg"
|
||||
}` ?? profileCircle
|
||||
}
|
||||
className="h-5 w-5 focus-visible:outline-0 "
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default function InputListComponent({
|
|||
<div
|
||||
className={classNames(
|
||||
value.length > 1 && editNode ? "my-1" : "",
|
||||
"flex flex-col gap-3",
|
||||
"flex flex-col gap-3"
|
||||
)}
|
||||
>
|
||||
{value.map((singleValue, idx) => {
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ const SideBarFoldersButtonsComponent = ({
|
|||
const currentFolder = pathname.split("/");
|
||||
const urlWithoutPath = pathname.split("/").length < 4;
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
|
||||
const refreshFolders = useFolderStore((state) => state.refreshFolders);
|
||||
|
||||
const checkPathName = (itemId: string) => {
|
||||
if (urlWithoutPath && itemId === myCollectionId) {
|
||||
|
|
@ -85,7 +85,7 @@ const SideBarFoldersButtonsComponent = ({
|
|||
function addNewFolder() {
|
||||
addFolder({ name: "New Folder", parent_id: null, description: "" }).then(
|
||||
(res) => {
|
||||
getFoldersApi(true);
|
||||
refreshFolders();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
);
|
||||
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
const refreshFolders = useFolderStore((state) => state.refreshFolders);
|
||||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
|
||||
const triggerFolderChange = (folderId) => {
|
||||
|
|
@ -118,7 +118,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
setFolderIdDragging("");
|
||||
|
||||
updateFlowInDatabase(updatedFlow).then(() => {
|
||||
getFoldersApi(true);
|
||||
refreshFolders();
|
||||
triggerFolderChange(folderId);
|
||||
});
|
||||
};
|
||||
|
|
@ -129,7 +129,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
setFolderDragging(false);
|
||||
setFolderIdDragging("");
|
||||
uploadFlowsFromFolders(formData).then(() => {
|
||||
getFoldersApi(true);
|
||||
refreshFolders();
|
||||
triggerFolderChange(folderId);
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export default function SidebarNav({
|
|||
}: SidebarNavProps) {
|
||||
const location = useLocation();
|
||||
const pathname = location.pathname;
|
||||
const loadingFolders = useFolderStore((state) => state.loading);
|
||||
const loadingFolders = useFolderStore((state) => state.isLoadingFolders);
|
||||
const folders = useFolderStore((state) => state.folders);
|
||||
|
||||
const pathValues = ["folder", "components", "flows", "all"];
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ const TableComponent = forwardRef<
|
|||
}
|
||||
}, 50);
|
||||
setTimeout(() => {
|
||||
realRef.current.api.hideOverlay();
|
||||
realRef?.current?.api?.hideOverlay();
|
||||
}, 1000);
|
||||
if (props.onGridReady) props.onGridReady(params);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -853,3 +853,8 @@ export const ALLOWED_IMAGE_INPUT_EXTENSIONS = ["png", "jpg", "jpeg"];
|
|||
export const FS_ERROR_TEXT =
|
||||
"Please ensure your file has one of the following extensions:";
|
||||
export const SN_ERROR_TEXT = ALLOWED_IMAGE_INPUT_EXTENSIONS.join(", ");
|
||||
|
||||
export const ERROR_UPDATING_COMPONENT =
|
||||
"An unexpected error occurred while updating the Component. Please try again.";
|
||||
export const TITLE_ERROR_UPDATING_COMPONENT =
|
||||
"Error while updating the Component";
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { useNavigate } from "react-router-dom";
|
|||
import Cookies from "universal-cookie";
|
||||
import { getLoggedUser, requestLogout } from "../controllers/API";
|
||||
import useAlertStore from "../stores/alertStore";
|
||||
import { useFolderStore } from "../stores/foldersStore";
|
||||
import { Users } from "../types/api";
|
||||
import { AuthContextType } from "../types/contexts/auth";
|
||||
|
||||
|
|
@ -43,6 +44,8 @@ export function AuthProvider({ children }): React.ReactElement {
|
|||
cookies.get("apikey_tkn_lflw")
|
||||
);
|
||||
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
|
||||
useEffect(() => {
|
||||
const storedAccessToken = cookies.get("access_token_lf");
|
||||
if (storedAccessToken) {
|
||||
|
|
@ -59,11 +62,12 @@ export function AuthProvider({ children }): React.ReactElement {
|
|||
|
||||
function getUser() {
|
||||
getLoggedUser()
|
||||
.then((user) => {
|
||||
.then(async (user) => {
|
||||
setUserData(user);
|
||||
setLoading(false);
|
||||
const isSuperUser = user!.is_superuser;
|
||||
setIsAdmin(isSuperUser);
|
||||
|
||||
getFoldersApi(true, true);
|
||||
})
|
||||
.catch((error) => {
|
||||
setLoading(false);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ function ApiInterceptor() {
|
|||
|
||||
if (!checkRequest) {
|
||||
controller.abort("Duplicate Request");
|
||||
console.error("Duplicate Request");
|
||||
}
|
||||
|
||||
const accessToken = cookies.get("access_token_lf");
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ export function checkDuplicateRequestAndStoreRequest(config) {
|
|||
const lastUrl = localStorage.getItem("lastUrlCalled");
|
||||
const lastMethodCalled = localStorage.getItem("lastMethodCalled");
|
||||
const lastRequestTime = localStorage.getItem("lastRequestTime");
|
||||
const lastCurrentUrl = localStorage.getItem("lastCurrentUrl");
|
||||
|
||||
const currentUrl = window.location.pathname;
|
||||
const currentTime = Date.now();
|
||||
|
||||
const isContained = AUTHORIZED_DUPLICATE_REQUESTS.some((request) =>
|
||||
config?.url!.includes(request)
|
||||
);
|
||||
|
|
@ -17,7 +18,8 @@ export function checkDuplicateRequestAndStoreRequest(config) {
|
|||
lastMethodCalled === config.method &&
|
||||
lastMethodCalled === "get" && // Assuming you want to check only for GET requests
|
||||
lastRequestTime &&
|
||||
currentTime - parseInt(lastRequestTime, 10) < 800
|
||||
currentTime - parseInt(lastRequestTime, 10) < 300 &&
|
||||
lastCurrentUrl === currentUrl
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -25,6 +27,7 @@ export function checkDuplicateRequestAndStoreRequest(config) {
|
|||
localStorage.setItem("lastUrlCalled", config.url ?? "");
|
||||
localStorage.setItem("lastMethodCalled", config.method ?? "");
|
||||
localStorage.setItem("lastRequestTime", currentTime.toString());
|
||||
localStorage.setItem("lastCurrentUrl", currentUrl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1094,8 +1094,6 @@ export async function getMessagesTable(
|
|||
|
||||
const rowsOrganized = rows.data;
|
||||
|
||||
console.log(rowsOrganized);
|
||||
|
||||
const columns = extractColumnsFromRows(rowsOrganized, mode, excludedFields);
|
||||
const sessions = new Set<string>();
|
||||
rowsOrganized.forEach((row) => {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import CsvOutputComponent from "../../../../components/csvOutputComponent";
|
|||
import DataOutputComponent from "../../../../components/dataOutputComponent";
|
||||
import InputListComponent from "../../../../components/inputListComponent";
|
||||
import PdfViewer from "../../../../components/pdfViewer";
|
||||
import RecordsOutputComponent from "../../../../components/recordsOutputComponent";
|
||||
import { Textarea } from "../../../../components/ui/textarea";
|
||||
import { PDFViewConstant } from "../../../../constants/constants";
|
||||
import { InputOutput } from "../../../../constants/enums";
|
||||
|
|
@ -253,7 +254,7 @@ export default function IOFieldView({
|
|||
rows={
|
||||
Array.isArray(flowPoolNode?.data?.artifacts)
|
||||
? flowPoolNode?.data?.artifacts?.map(
|
||||
(artifact) => artifact.data
|
||||
(artifact) => artifact.data,
|
||||
) ?? []
|
||||
: [flowPoolNode?.data?.artifacts]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default function SessionView({ rows }: { rows: Array<any> }) {
|
|||
setSelectedRows,
|
||||
setSuccessData,
|
||||
setErrorData,
|
||||
selectedRows,
|
||||
selectedRows
|
||||
);
|
||||
|
||||
const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData);
|
||||
|
|
|
|||
|
|
@ -36,12 +36,6 @@ export default function ChatView({
|
|||
const outputTypes = outputs.map((obj) => obj.type);
|
||||
const updateFlowPool = useFlowStore((state) => state.updateFlowPool);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!outputTypes.includes("ChatOutput")) {
|
||||
// setNoticeData({ title: NOCHATOUTPUT_NOTICE_ALERT });
|
||||
// }
|
||||
// }, []);
|
||||
|
||||
//build chat history
|
||||
useEffect(() => {
|
||||
const chatOutputResponses: VertexBuildTypeAPI[] = [];
|
||||
|
|
@ -62,14 +56,24 @@ export default function ChatView({
|
|||
const chatMessages: ChatMessageType[] = chatOutputResponses
|
||||
.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp))
|
||||
//
|
||||
.filter((output) => output.data.message)
|
||||
.filter(
|
||||
(output) =>
|
||||
output.data.message || (!output.data.message && output.artifacts)
|
||||
)
|
||||
.map((output, index) => {
|
||||
try {
|
||||
console.log("output:", output);
|
||||
|
||||
const messageOutput = output.data.message;
|
||||
const hasMessageValue =
|
||||
messageOutput?.message ||
|
||||
messageOutput?.message === "" ||
|
||||
(messageOutput?.files ?? []).length > 0 ||
|
||||
messageOutput?.stream_url;
|
||||
|
||||
const { sender, message, sender_name, stream_url, files } =
|
||||
output.data.message;
|
||||
console.log("output.data.message:", output.data.message);
|
||||
console.log("output.data.message.files:", output.data.message.files);
|
||||
hasMessageValue ? output.data.message : output.artifacts;
|
||||
|
||||
const is_ai =
|
||||
sender === "Machine" || sender === null || sender === undefined;
|
||||
return {
|
||||
|
|
@ -136,26 +140,12 @@ export default function ChatView({
|
|||
message: string,
|
||||
stream_url?: string
|
||||
) {
|
||||
// if (message === "") return;
|
||||
chat.message = message;
|
||||
// chat is one of the chatHistory
|
||||
updateFlowPool(chat.componentId, {
|
||||
message,
|
||||
sender_name: chat.sender_name ?? "Bot",
|
||||
sender: chat.isSend ? "User" : "Machine",
|
||||
});
|
||||
// setChatHistory((oldChatHistory) => {
|
||||
// const index = oldChatHistory.findIndex((ch) => ch.id === chat.id);
|
||||
// if (index === -1) return oldChatHistory;
|
||||
// let newChatHistory = _.cloneDeep(oldChatHistory);
|
||||
// newChatHistory = [
|
||||
// ...newChatHistory.slice(0, index),
|
||||
// chat,
|
||||
// ...newChatHistory.slice(index + 1),
|
||||
// ];
|
||||
// console.log("newChatHistory:", newChatHistory);
|
||||
// return newChatHistory;
|
||||
// });
|
||||
}
|
||||
const [files, setFiles] = useState<FilePreviewType[]>([]);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
|
|
@ -190,44 +180,6 @@ export default function ChatView({
|
|||
aria-hidden="true"
|
||||
/>
|
||||
</Button>
|
||||
{/* <Select
|
||||
onValueChange={handleSelectChange}
|
||||
value=""
|
||||
disabled={lockChat}
|
||||
>
|
||||
<SelectTrigger className="">
|
||||
<button className="flex gap-1">
|
||||
<IconComponent
|
||||
name="Eraser"
|
||||
className={classNames(
|
||||
"h-5 w-5 transition-all duration-100",
|
||||
lockChat ? "animate-pulse text-primary" : "text-primary",
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</SelectTrigger>
|
||||
<SelectContent className="right-[9.5em]">
|
||||
<SelectItem value="builds" className="cursor-pointer">
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name={"Trash2"}
|
||||
className={`relative top-0.5 mr-2 h-4 w-4`}
|
||||
/>
|
||||
<span className="">Clear Builds</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="buildsNSession" className="cursor-pointer">
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name={"Trash2"}
|
||||
className={`relative top-0.5 mr-2 h-4 w-4`}
|
||||
/>
|
||||
<span className="">Clear Builds & Session</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select> */}
|
||||
</div>
|
||||
<div ref={messagesRef} className="chat-message-div">
|
||||
{chatHistory?.length > 0 ? (
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import IconComponent from "../../components/genericIconComponent";
|
|||
import { EXPORT_CODE_DIALOG } from "../../constants/constants";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { useTweaksStore } from "../../stores/tweaksStore";
|
||||
import { InputFieldType } from "../../types/api";
|
||||
import { TemplateVariableType } from "../../types/api";
|
||||
import { uniqueTweakType } from "../../types/components";
|
||||
import { FlowType } from "../../types/flow/index";
|
||||
import BaseModal from "../baseModal";
|
||||
|
|
@ -39,7 +39,7 @@ const ApiModal = forwardRef(
|
|||
open?: boolean;
|
||||
setOpen?: (a: boolean | ((o?: boolean) => boolean)) => void;
|
||||
},
|
||||
ref
|
||||
ref,
|
||||
) => {
|
||||
const tweak = useTweaksStore((state) => state.tweak);
|
||||
const addTweaks = useTweaksStore((state) => state.setTweak);
|
||||
|
|
@ -57,18 +57,18 @@ const ApiModal = forwardRef(
|
|||
flow?.id,
|
||||
autoLogin,
|
||||
tweak,
|
||||
flow?.endpoint_name
|
||||
flow?.endpoint_name,
|
||||
);
|
||||
const curl_run_code = getCurlRunCode(
|
||||
flow?.id,
|
||||
autoLogin,
|
||||
tweak,
|
||||
flow?.endpoint_name
|
||||
flow?.endpoint_name,
|
||||
);
|
||||
const curl_webhook_code = getCurlWebhookCode(
|
||||
flow?.id,
|
||||
autoLogin,
|
||||
flow?.endpoint_name
|
||||
flow?.endpoint_name,
|
||||
);
|
||||
const pythonCode = getPythonCode(flow?.name, tweak);
|
||||
const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin);
|
||||
|
|
@ -83,7 +83,7 @@ const ApiModal = forwardRef(
|
|||
pythonCode,
|
||||
];
|
||||
const [tabs, setTabs] = useState(
|
||||
createTabsArray(codesArray, includeWebhook)
|
||||
createTabsArray(codesArray, includeWebhook),
|
||||
);
|
||||
|
||||
const canShowTweaks =
|
||||
|
|
@ -132,7 +132,7 @@ const ApiModal = forwardRef(
|
|||
buildTweakObject(
|
||||
nodeId,
|
||||
element.data.node.template[templateField].value,
|
||||
element.data.node.template[templateField]
|
||||
element.data.node.template[templateField],
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -149,7 +149,7 @@ const ApiModal = forwardRef(
|
|||
async function buildTweakObject(
|
||||
tw: string,
|
||||
changes: string | string[] | boolean | number | Object[] | Object,
|
||||
template: InputFieldType
|
||||
template: TemplateVariableType,
|
||||
) {
|
||||
changes = getChangesType(changes, template);
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ const ApiModal = forwardRef(
|
|||
flow?.id,
|
||||
autoLogin,
|
||||
cloneTweak,
|
||||
flow?.endpoint_name
|
||||
flow?.endpoint_name,
|
||||
);
|
||||
const pythonCode = getPythonCode(flow?.name, cloneTweak);
|
||||
const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin);
|
||||
|
|
@ -235,7 +235,7 @@ const ApiModal = forwardRef(
|
|||
</BaseModal.Content>
|
||||
</BaseModal>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export default ApiModal;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { InputFieldType } from "../../../types/api";
|
||||
import { TemplateVariableType } from "../../../types/api";
|
||||
import { convertArrayToObj } from "../../../utils/reactflowUtils";
|
||||
|
||||
export const getChangesType = (
|
||||
changes: string | string[] | boolean | number | Object[] | Object,
|
||||
template: InputFieldType
|
||||
template: TemplateVariableType,
|
||||
) => {
|
||||
if (typeof changes === "string" && template.type === "float") {
|
||||
changes = parseFloat(changes);
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ export const getNodesWithDefaultValue = (flow) => {
|
|||
.filter(
|
||||
(templateField) =>
|
||||
templateField.charAt(0) !== "_" &&
|
||||
node.data.node.template[templateField].show &&
|
||||
node.data.node.template[templateField]?.show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
node.data.node.template[templateField].type
|
||||
)
|
||||
node.data.node.template[templateField].type,
|
||||
),
|
||||
)
|
||||
.map((n, i) => {
|
||||
arrNodesWithValues.push(node["id"]);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { InputFieldType } from "../../../types/api";
|
||||
import { TemplateVariableType } from "../../../types/api";
|
||||
import { NodeType } from "../../../types/flow";
|
||||
|
||||
export const getValue = (
|
||||
value: string,
|
||||
node: NodeType,
|
||||
template: InputFieldType,
|
||||
tweak: Object[]
|
||||
template: TemplateVariableType,
|
||||
tweak: Object[],
|
||||
) => {
|
||||
let returnValue = value ?? "";
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default function FlowSettingsModal({
|
|||
useEffect(() => {
|
||||
setName(currentFlow!.name);
|
||||
setDescription(currentFlow!.description);
|
||||
}, [currentFlow!.name, currentFlow!.description, open]);
|
||||
}, [currentFlow?.name, currentFlow?.description, open]);
|
||||
|
||||
const [name, setName] = useState(currentFlow!.name);
|
||||
const [description, setDescription] = useState(currentFlow!.description);
|
||||
|
|
@ -40,6 +40,7 @@ export default function FlowSettingsModal({
|
|||
list: [err?.response?.data.detail ?? ""],
|
||||
});
|
||||
console.error(err);
|
||||
setIsSaving(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export default function LoginAdminPage() {
|
|||
const [inputState, setInputState] =
|
||||
useState<loginInputStateType>(CONTROL_LOGIN_STATE);
|
||||
const { login, isAuthenticated, setUserData } = useContext(AuthContext);
|
||||
const setLoading = useAlertStore((state) => state.setLoading);
|
||||
|
||||
const { password, username } = inputState;
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
|
|
@ -35,6 +36,10 @@ export default function LoginAdminPage() {
|
|||
};
|
||||
onLogin(user)
|
||||
.then((user) => {
|
||||
console.log("admin page");
|
||||
|
||||
setLoading(true);
|
||||
|
||||
login(user.access_token);
|
||||
navigate("/admin/");
|
||||
})
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import {
|
|||
generateNodeFromFlow,
|
||||
getNodeId,
|
||||
isValidConnection,
|
||||
reconnectEdges,
|
||||
scapeJSONParse,
|
||||
updateIds,
|
||||
validateSelection,
|
||||
|
|
@ -61,19 +62,19 @@ export default function Page({
|
|||
const preventDefault = true;
|
||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||
const autoSaveCurrentFlow = useFlowsManagerStore(
|
||||
(state) => state.autoSaveCurrentFlow
|
||||
(state) => state.autoSaveCurrentFlow,
|
||||
);
|
||||
const types = useTypesStore((state) => state.types);
|
||||
const templates = useTypesStore((state) => state.templates);
|
||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||
const reactFlowWrapper = useRef<HTMLDivElement>(null);
|
||||
const [showCanvas, setSHowCanvas] = useState(
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
|
||||
);
|
||||
|
||||
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
|
||||
const setReactFlowInstance = useFlowStore(
|
||||
(state) => state.setReactFlowInstance
|
||||
(state) => state.setReactFlowInstance,
|
||||
);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
|
|
@ -90,10 +91,10 @@ export default function Page({
|
|||
const paste = useFlowStore((state) => state.paste);
|
||||
const resetFlow = useFlowStore((state) => state.resetFlow);
|
||||
const lastCopiedSelection = useFlowStore(
|
||||
(state) => state.lastCopiedSelection
|
||||
(state) => state.lastCopiedSelection,
|
||||
);
|
||||
const setLastCopiedSelection = useFlowStore(
|
||||
(state) => state.setLastCopiedSelection
|
||||
(state) => state.setLastCopiedSelection,
|
||||
);
|
||||
const onConnect = useFlowStore((state) => state.onConnect);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
|
|
@ -116,7 +117,7 @@ export default function Page({
|
|||
clonedSelection!,
|
||||
clonedNodes,
|
||||
clonedEdges,
|
||||
getRandomName()
|
||||
getRandomName(),
|
||||
);
|
||||
const newGroupNode = generateNodeFromFlow(newFlow, getNodeId);
|
||||
// const newEdges = reconnectEdges(newGroupNode, removedEdges);
|
||||
|
|
@ -124,8 +125,8 @@ export default function Page({
|
|||
...clonedNodes.filter(
|
||||
(oldNodes) =>
|
||||
!clonedSelection?.nodes.some(
|
||||
(selectionNode) => selectionNode.id === oldNodes.id
|
||||
)
|
||||
(selectionNode) => selectionNode.id === oldNodes.id,
|
||||
),
|
||||
),
|
||||
newGroupNode,
|
||||
]);
|
||||
|
|
@ -212,7 +213,7 @@ export default function Page({
|
|||
{
|
||||
x: position.current.x,
|
||||
y: position.current.y,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -296,7 +297,7 @@ export default function Page({
|
|||
|
||||
useEffect(() => {
|
||||
setSHowCanvas(
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
|
||||
);
|
||||
}, [templates, types]);
|
||||
|
||||
|
|
@ -305,7 +306,7 @@ export default function Page({
|
|||
takeSnapshot();
|
||||
onConnect(params);
|
||||
},
|
||||
[takeSnapshot, onConnect]
|
||||
[takeSnapshot, onConnect],
|
||||
);
|
||||
|
||||
const onNodeDragStart: NodeDragHandler = useCallback(() => {
|
||||
|
|
@ -346,7 +347,7 @@ export default function Page({
|
|||
|
||||
// Extract the data from the drag event and parse it as a JSON object
|
||||
const data: { type: string; node?: APIClassType } = JSON.parse(
|
||||
event.dataTransfer.getData("nodedata")
|
||||
event.dataTransfer.getData("nodedata"),
|
||||
);
|
||||
|
||||
const newId = getNodeId(data.type);
|
||||
|
|
@ -362,7 +363,7 @@ export default function Page({
|
|||
};
|
||||
paste(
|
||||
{ nodes: [newNode], edges: [] },
|
||||
{ x: event.clientX, y: event.clientY }
|
||||
{ x: event.clientX, y: event.clientY },
|
||||
);
|
||||
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
||||
takeSnapshot();
|
||||
|
|
@ -391,7 +392,7 @@ export default function Page({
|
|||
}
|
||||
},
|
||||
// Specify dependencies for useCallback
|
||||
[getNodeId, setNodes, takeSnapshot, paste]
|
||||
[getNodeId, setNodes, takeSnapshot, paste],
|
||||
);
|
||||
|
||||
const onEdgeUpdateStart = useCallback(() => {
|
||||
|
|
@ -407,7 +408,7 @@ export default function Page({
|
|||
setEdges((els) => updateEdge(oldEdge, newConnection, els));
|
||||
}
|
||||
},
|
||||
[setEdges]
|
||||
[setEdges],
|
||||
);
|
||||
|
||||
const onEdgeUpdateEnd = useCallback((_, edge: Edge): void => {
|
||||
|
|
@ -440,7 +441,7 @@ export default function Page({
|
|||
(flow: OnSelectionChangeParams): void => {
|
||||
setLastSelection(flow);
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
const onPaneClick = useCallback((flow) => {
|
||||
|
|
|
|||
|
|
@ -57,17 +57,17 @@ export default function NodeToolbarComponent({
|
|||
const nodeLength = Object.keys(data.node!.template).filter(
|
||||
(templateField) =>
|
||||
templateField.charAt(0) !== "_" &&
|
||||
data.node?.template[templateField].show &&
|
||||
(data.node.template[templateField].type === "str" ||
|
||||
data.node.template[templateField].type === "bool" ||
|
||||
data.node.template[templateField].type === "float" ||
|
||||
data.node.template[templateField].type === "code" ||
|
||||
data.node.template[templateField].type === "prompt" ||
|
||||
data.node.template[templateField].type === "file" ||
|
||||
data.node.template[templateField].type === "Any" ||
|
||||
data.node.template[templateField].type === "int" ||
|
||||
data.node.template[templateField].type === "dict" ||
|
||||
data.node.template[templateField].type === "NestedDict")
|
||||
data.node?.template[templateField]?.show &&
|
||||
(data.node.template[templateField]?.type === "str" ||
|
||||
data.node.template[templateField]?.type === "bool" ||
|
||||
data.node.template[templateField]?.type === "float" ||
|
||||
data.node.template[templateField]?.type === "code" ||
|
||||
data.node.template[templateField]?.type === "prompt" ||
|
||||
data.node.template[templateField]?.type === "file" ||
|
||||
data.node.template[templateField]?.type === "Any" ||
|
||||
data.node.template[templateField]?.type === "int" ||
|
||||
data.node.template[templateField]?.type === "dict" ||
|
||||
data.node.template[templateField]?.type === "NestedDict")
|
||||
).length;
|
||||
|
||||
const hasStore = useStoreStore((state) => state.hasStore);
|
||||
|
|
@ -626,7 +626,7 @@ export default function NodeToolbarComponent({
|
|||
/>
|
||||
</SelectItem>
|
||||
)}
|
||||
{(!hasStore || !hasApiKey || !validApiKey) && (
|
||||
{/* {(!hasStore || !hasApiKey || !validApiKey) && (
|
||||
<SelectItem value={"Download"}>
|
||||
<ToolbarSelectItem
|
||||
shortcut={
|
||||
|
|
@ -638,7 +638,7 @@ export default function NodeToolbarComponent({
|
|||
dataTestId="Download-button-modal"
|
||||
/>
|
||||
</SelectItem>
|
||||
)}
|
||||
)} */}
|
||||
<SelectItem
|
||||
value={"documentation"}
|
||||
disabled={data.node?.documentation === ""}
|
||||
|
|
@ -688,16 +688,19 @@ export default function NodeToolbarComponent({
|
|||
style={`${frozen ? " text-ice" : ""} transition-all`}
|
||||
/>
|
||||
</SelectItem>
|
||||
<SelectItem value="Download">
|
||||
<ToolbarSelectItem
|
||||
shortcut={
|
||||
shortcuts.find((obj) => obj.name === "Download")?.shortcut!
|
||||
}
|
||||
value={"Download"}
|
||||
icon={"Download"}
|
||||
dataTestId="download-button-modal"
|
||||
/>
|
||||
</SelectItem>
|
||||
{(!hasStore || !hasApiKey || !validApiKey) && (
|
||||
<SelectItem value="Download">
|
||||
<ToolbarSelectItem
|
||||
shortcut={
|
||||
shortcuts.find((obj) => obj.name === "Download")
|
||||
?.shortcut!
|
||||
}
|
||||
value={"Download"}
|
||||
icon={"Download"}
|
||||
dataTestId="download-button-modal"
|
||||
/>
|
||||
</SelectItem>
|
||||
)}
|
||||
<SelectItem
|
||||
value={"delete"}
|
||||
className="focus:bg-red-400/[.20]"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { CONTROL_LOGIN_STATE } from "../../constants/constants";
|
|||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { onLogin } from "../../controllers/API";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { LoginType } from "../../types/api";
|
||||
import {
|
||||
inputHandlerEventType,
|
||||
|
|
@ -20,10 +21,10 @@ export default function LoginPage(): JSX.Element {
|
|||
useState<loginInputStateType>(CONTROL_LOGIN_STATE);
|
||||
|
||||
const { password, username } = inputState;
|
||||
const { login, isAuthenticated, setUserData, setIsAdmin } =
|
||||
useContext(AuthContext);
|
||||
const { login } = useContext(AuthContext);
|
||||
const navigate = useNavigate();
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const setLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
|
||||
function handleInput({
|
||||
target: { name, value },
|
||||
|
|
@ -38,6 +39,9 @@ export default function LoginPage(): JSX.Element {
|
|||
};
|
||||
onLogin(user)
|
||||
.then((user) => {
|
||||
console.log("login page");
|
||||
|
||||
setLoading(true);
|
||||
login(user.access_token);
|
||||
navigate("/");
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,39 +1,19 @@
|
|||
import { useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import useAlertStore from "../../../../../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../../../../../stores/flowsManagerStore";
|
||||
import { useFolderStore } from "../../../../../../stores/foldersStore";
|
||||
import { handleDownloadFolderFn } from "../../../../utils/handle-download-folder";
|
||||
import InputSearchComponent from "../inputSearchComponent";
|
||||
import TabsSearchComponent from "../tabsComponent";
|
||||
|
||||
type HeaderTabsSearchComponentProps = {};
|
||||
|
||||
const HeaderTabsSearchComponent = ({}: HeaderTabsSearchComponentProps) => {
|
||||
const location = useLocation();
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const folderId = location?.state?.folderId || myCollectionId;
|
||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||
const [tabActive, setTabActive] = useState("Flows");
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const allFlows = useFlowsManagerStore((state) => state.allFlows);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
|
||||
const setSearchFlowsComponents = useFlowsManagerStore(
|
||||
(state) => state.setSearchFlowsComponents
|
||||
);
|
||||
|
||||
const handleDownloadFolder = () => {
|
||||
if (allFlows.length === 0) {
|
||||
setErrorData({
|
||||
title: "Folder is empty",
|
||||
list: [],
|
||||
});
|
||||
return;
|
||||
}
|
||||
handleDownloadFolderFn(folderId);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative flex items-end gap-4">
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@ import useAlertStore from "../../../stores/alertStore";
|
|||
import { useFolderStore } from "../../../stores/foldersStore";
|
||||
import { deleteFolder, getFolderById } from "../services";
|
||||
|
||||
const useDeleteFolder = ({ navigate, getFoldersApi }) => {
|
||||
const useDeleteFolder = ({ navigate }) => {
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const folderToEdit = useFolderStore((state) => state.folderToEdit);
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
|
||||
const handleDeleteFolder = () => {
|
||||
deleteFolder(folderToEdit?.id!)
|
||||
|
|
|
|||
|
|
@ -25,16 +25,9 @@ export default function HomePage(): JSX.Element {
|
|||
const [openFolderModal, setOpenFolderModal] = useState(false);
|
||||
const [openDeleteFolderModal, setOpenDeleteFolderModal] = useState(false);
|
||||
const is_component = pathname === "/components";
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
const setFolderToEdit = useFolderStore((state) => state.setFolderToEdit);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
getFoldersApi();
|
||||
}, 300);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentFlowId("");
|
||||
}, [pathname]);
|
||||
|
|
@ -45,7 +38,7 @@ export default function HomePage(): JSX.Element {
|
|||
is_component,
|
||||
});
|
||||
|
||||
const { handleDeleteFolder } = useDeleteFolder({ navigate, getFoldersApi });
|
||||
const { handleDeleteFolder } = useDeleteFolder({ navigate });
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ const ProfilePictureFormComponent = ({
|
|||
} else {
|
||||
prev[folder] = [path];
|
||||
}
|
||||
setLoading(false);
|
||||
return prev;
|
||||
});
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export default function MessagesPage() {
|
|||
setSelectedRows,
|
||||
setSuccessData,
|
||||
setErrorData,
|
||||
selectedRows,
|
||||
selectedRows
|
||||
);
|
||||
|
||||
const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData);
|
||||
|
|
@ -61,7 +61,7 @@ export default function MessagesPage() {
|
|||
overlayNoRowsTemplate="No data available"
|
||||
onSelectionChanged={(event: SelectionChangedEvent) => {
|
||||
setSelectedRows(
|
||||
event.api.getSelectedRows().map((row) => row.index),
|
||||
event.api.getSelectedRows().map((row) => row.index)
|
||||
);
|
||||
}}
|
||||
rowSelection="multiple"
|
||||
|
|
|
|||
|
|
@ -7,20 +7,21 @@ import {
|
|||
} from "../pages/MainPage/services";
|
||||
import { FoldersStoreType } from "../types/zustand/folders";
|
||||
import useFlowsManagerStore from "./flowsManagerStore";
|
||||
import { useTypesStore } from "./typesStore";
|
||||
|
||||
export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
||||
folders: [],
|
||||
getFoldersApi: (refetch = false) => {
|
||||
getFoldersApi: (refetch = false, startupApplication: boolean = false) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (get()?.folders.length === 0 || refetch === true) {
|
||||
get().setLoading(true);
|
||||
get().setIsLoadingFolders(true);
|
||||
getFolders().then(
|
||||
(res) => {
|
||||
const foldersWithoutStarterProjects = res.filter(
|
||||
async (res) => {
|
||||
const foldersWithoutStarterProjects = res?.filter(
|
||||
(folder) => folder.name !== STARTER_FOLDER_NAME
|
||||
);
|
||||
|
||||
const starterProjects = res.find(
|
||||
const starterProjects = res?.find(
|
||||
(folder) => folder.name === STARTER_FOLDER_NAME
|
||||
);
|
||||
|
||||
|
|
@ -33,45 +34,77 @@ export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
|||
|
||||
set({ myCollectionId });
|
||||
|
||||
if (refetch === true) {
|
||||
useFlowsManagerStore.getState().refreshFlows();
|
||||
useFlowsManagerStore.getState().setAllFlows;
|
||||
}
|
||||
const { refreshFlows } = useFlowsManagerStore.getState();
|
||||
const { getTypes } = useTypesStore.getState();
|
||||
const { setIsLoadingFolders } = get();
|
||||
|
||||
if (refetch) {
|
||||
if (startupApplication) {
|
||||
await refreshFlows();
|
||||
await getTypes();
|
||||
} else {
|
||||
refreshFlows();
|
||||
getTypes();
|
||||
}
|
||||
}
|
||||
setIsLoadingFolders(false);
|
||||
|
||||
get().setLoading(false);
|
||||
resolve();
|
||||
},
|
||||
(error) => {
|
||||
set({ folders: [] });
|
||||
get().setLoading(false);
|
||||
get().setIsLoadingFolders(false);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
setFolders: (folders) => set(() => ({ folders: folders })),
|
||||
loading: false,
|
||||
setLoading: (loading) => set(() => ({ loading: loading })),
|
||||
getFolderById: (id) => {
|
||||
get().setLoadingById(true);
|
||||
if (id) {
|
||||
getFolderById(id).then(
|
||||
(res) => {
|
||||
const setAllFlows = useFlowsManagerStore.getState().setAllFlows;
|
||||
setAllFlows(res.flows);
|
||||
set({ selectedFolder: res });
|
||||
get().setLoadingById(false);
|
||||
refreshFolders: () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
getFolders().then(
|
||||
async (res) => {
|
||||
const foldersWithoutStarterProjects = res?.filter(
|
||||
(folder) => folder.name !== STARTER_FOLDER_NAME
|
||||
);
|
||||
|
||||
const starterProjects = res?.find(
|
||||
(folder) => folder.name === STARTER_FOLDER_NAME
|
||||
);
|
||||
|
||||
set({ starterProjectId: starterProjects!.id ?? "" });
|
||||
set({ folders: foldersWithoutStarterProjects });
|
||||
|
||||
const myCollectionId = res?.find(
|
||||
(f) => f.name === DEFAULT_FOLDER
|
||||
)?.id;
|
||||
|
||||
set({ myCollectionId });
|
||||
|
||||
resolve();
|
||||
},
|
||||
() => {
|
||||
get().setLoadingById(false);
|
||||
(error) => {
|
||||
set({ folders: [] });
|
||||
get().setIsLoadingFolders(false);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
setFolders: (folders) => set(() => ({ folders: folders })),
|
||||
isLoadingFolders: false,
|
||||
setIsLoadingFolders: (isLoadingFolders) => set(() => ({ isLoadingFolders })),
|
||||
getFolderById: (id) => {
|
||||
if (id) {
|
||||
getFolderById(id).then((res) => {
|
||||
const setAllFlows = useFlowsManagerStore.getState().setAllFlows;
|
||||
setAllFlows(res.flows);
|
||||
set({ selectedFolder: res });
|
||||
});
|
||||
}
|
||||
},
|
||||
selectedFolder: null,
|
||||
loadingById: false,
|
||||
setLoadingById: (loading) => set(() => ({ loadingById: loading })),
|
||||
getMyCollectionFolder: () => {
|
||||
const folders = get().folders;
|
||||
const myCollectionId = folders?.find((f) => f.name === DEFAULT_FOLDER)?.id;
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ export type VertexBuildTypeAPI = {
|
|||
timestamp: string;
|
||||
params: any;
|
||||
messages: ChatOutputType[] | ChatInputType[];
|
||||
artifacts: any | ChatOutputType | ChatInputType;
|
||||
};
|
||||
|
||||
export type LogType = {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export type ParameterComponentType = {
|
|||
info?: string;
|
||||
proxy?: { field: string; id: string };
|
||||
showNode?: boolean;
|
||||
index: number;
|
||||
index?: string;
|
||||
onCloseModal?: (close: boolean) => void;
|
||||
outputName?: string;
|
||||
outputProxy?: OutputFieldProxyType;
|
||||
|
|
@ -511,7 +511,7 @@ export type ChatInputType = {
|
|||
isDragging: boolean;
|
||||
files: FilePreviewType[];
|
||||
setFiles: (
|
||||
files: FilePreviewType[] | ((prev: FilePreviewType[]) => FilePreviewType[])
|
||||
files: FilePreviewType[] | ((prev: FilePreviewType[]) => FilePreviewType[]),
|
||||
) => void;
|
||||
chatValue: string;
|
||||
inputRef: {
|
||||
|
|
@ -614,7 +614,7 @@ export type chatMessagePropsType = {
|
|||
updateChat: (
|
||||
chat: ChatMessageType,
|
||||
message: string,
|
||||
stream_url?: string
|
||||
stream_url?: string,
|
||||
) => void;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ import { FolderType } from "../../../pages/MainPage/entities";
|
|||
|
||||
export type FoldersStoreType = {
|
||||
folders: FolderType[];
|
||||
getFoldersApi: (refetch?: boolean) => Promise<void>;
|
||||
getFoldersApi: (
|
||||
refetch?: boolean,
|
||||
startupApplication?: boolean
|
||||
) => Promise<void>;
|
||||
setFolders: (folders: FolderType[]) => void;
|
||||
loading: boolean;
|
||||
setLoading: (loading: boolean) => void;
|
||||
isLoadingFolders: boolean;
|
||||
setIsLoadingFolders: (isLoadingFolders: boolean) => void;
|
||||
selectedFolder: FolderType | null;
|
||||
getFolderById: (id: string) => void;
|
||||
loadingById: boolean;
|
||||
setLoadingById: (loading: boolean) => void;
|
||||
getMyCollectionFolder: () => void;
|
||||
myCollectionFlows: FolderType | null;
|
||||
myCollectionId: string | null;
|
||||
|
|
@ -25,4 +26,5 @@ export type FoldersStoreType = {
|
|||
setFolderIdDragging: (id: string) => void;
|
||||
starterProjectId: string;
|
||||
setStarterProjectId: (id: string) => void;
|
||||
refreshFolders: () => void;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ type BuildVerticesParams = {
|
|||
onBuildUpdate?: (
|
||||
data: VertexBuildTypeAPI,
|
||||
status: BuildStatus,
|
||||
buildId: string
|
||||
buildId: string,
|
||||
) => void; // Replace any with the actual type if it's not any
|
||||
onBuildComplete?: (allNodesValid: boolean) => void;
|
||||
onBuildError?: (title, list, idList: VertexLayerElementType[]) => void;
|
||||
|
|
@ -55,7 +55,7 @@ export async function updateVerticesOrder(
|
|||
startNodeId?: string | null,
|
||||
stopNodeId?: string | null,
|
||||
nodes?: Node[],
|
||||
edges?: Edge[]
|
||||
edges?: Edge[],
|
||||
): Promise<{
|
||||
verticesLayers: VertexLayerElementType[][];
|
||||
verticesIds: string[];
|
||||
|
|
@ -71,7 +71,7 @@ export async function updateVerticesOrder(
|
|||
startNodeId,
|
||||
stopNodeId,
|
||||
nodes,
|
||||
edges
|
||||
edges,
|
||||
);
|
||||
} catch (error: any) {
|
||||
setErrorData({
|
||||
|
|
@ -128,7 +128,7 @@ export async function buildVertices({
|
|||
startNodeId,
|
||||
stopNodeId,
|
||||
nodes,
|
||||
edges
|
||||
edges,
|
||||
);
|
||||
if (onValidateNodes) {
|
||||
try {
|
||||
|
|
@ -162,7 +162,6 @@ export async function buildVertices({
|
|||
const currentLayer =
|
||||
useFlowStore.getState().verticesBuild?.verticesLayers![currentLayerIndex];
|
||||
// If there are no more layers, we are done
|
||||
console.log("currentLayer", currentLayer);
|
||||
if (!currentLayer) {
|
||||
if (onBuildComplete) {
|
||||
const allNodesValid = buildResults.every((result) => result);
|
||||
|
|
@ -191,14 +190,14 @@ export async function buildVertices({
|
|||
onBuildUpdate(
|
||||
getInactiveVertexData(element.id),
|
||||
BuildStatus.INACTIVE,
|
||||
runId
|
||||
runId,
|
||||
);
|
||||
}
|
||||
if (element.reference) {
|
||||
onBuildUpdate(
|
||||
getInactiveVertexData(element.reference),
|
||||
BuildStatus.INACTIVE,
|
||||
runId
|
||||
runId,
|
||||
);
|
||||
}
|
||||
buildResults.push(false);
|
||||
|
|
@ -224,7 +223,7 @@ export async function buildVertices({
|
|||
if (stop) {
|
||||
return;
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
// Once the current layer is built, move to the next layer
|
||||
currentLayerIndex += 1;
|
||||
|
|
@ -289,7 +288,10 @@ async function buildVertex({
|
|||
console.error(error);
|
||||
onBuildError!(
|
||||
"Error Building Component",
|
||||
[(error as AxiosError<any>).response?.data?.detail ?? "Unknown Error"],
|
||||
[
|
||||
(error as AxiosError<any>).response?.data?.detail ??
|
||||
"An unexpected error occurred while building the Component. Please try again.",
|
||||
],
|
||||
verticesIds.map((id) => ({ id }))
|
||||
);
|
||||
stopBuild();
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export function normalCaseToSnakeCase(str: string): string {
|
|||
|
||||
export function toTitleCase(
|
||||
str: string | undefined,
|
||||
isNodeField?: boolean,
|
||||
isNodeField?: boolean
|
||||
): string {
|
||||
if (!str) return "";
|
||||
let result = str
|
||||
|
|
@ -65,7 +65,7 @@ export function toTitleCase(
|
|||
if (isNodeField) return word;
|
||||
if (index === 0) {
|
||||
return checkUpperWords(
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
||||
);
|
||||
}
|
||||
return checkUpperWords(word.toLowerCase());
|
||||
|
|
@ -78,7 +78,7 @@ export function toTitleCase(
|
|||
if (isNodeField) return word;
|
||||
if (index === 0) {
|
||||
return checkUpperWords(
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
||||
);
|
||||
}
|
||||
return checkUpperWords(word.toLowerCase());
|
||||
|
|
@ -182,7 +182,7 @@ export function checkLocalStorageKey(key: string): boolean {
|
|||
|
||||
export function IncrementObjectKey(
|
||||
object: object,
|
||||
key: string,
|
||||
key: string
|
||||
): { newKey: string; increment: number } {
|
||||
let count = 1;
|
||||
const type = removeCountFromString(key);
|
||||
|
|
@ -217,7 +217,7 @@ export function groupByFamily(
|
|||
data: APIDataType,
|
||||
baseClasses: string,
|
||||
left: boolean,
|
||||
flow?: NodeType[],
|
||||
flow?: NodeType[]
|
||||
): groupedObjType[] {
|
||||
const baseClassesSet = new Set(baseClasses.split("\n"));
|
||||
let arrOfPossibleInputs: Array<{
|
||||
|
|
@ -237,13 +237,13 @@ export function groupByFamily(
|
|||
|
||||
const checkBaseClass = (template: InputFieldType) => {
|
||||
return (
|
||||
template.type &&
|
||||
template.show &&
|
||||
template?.type &&
|
||||
template?.show &&
|
||||
((!excludeTypes.has(template.type) &&
|
||||
baseClassesSet.has(template.type)) ||
|
||||
(template.input_types &&
|
||||
template.input_types.some((inputType) =>
|
||||
baseClassesSet.has(inputType),
|
||||
(template?.input_types &&
|
||||
template?.input_types.some((inputType) =>
|
||||
baseClassesSet.has(inputType)
|
||||
)))
|
||||
);
|
||||
};
|
||||
|
|
@ -263,7 +263,7 @@ export function groupByFamily(
|
|||
hasBaseClassInBaseClasses:
|
||||
foundNode?.hasBaseClassInBaseClasses ||
|
||||
nodeData.node!.base_classes?.some((baseClass) =>
|
||||
baseClassesSet.has(baseClass),
|
||||
baseClassesSet.has(baseClass)
|
||||
), //seta como anterior ou verifica se o node tem base class
|
||||
displayName: nodeData.node?.display_name,
|
||||
});
|
||||
|
|
@ -280,10 +280,10 @@ export function groupByFamily(
|
|||
if (!foundNode) {
|
||||
foundNode = {
|
||||
hasBaseClassInTemplate: Object.values(node!.template).some(
|
||||
checkBaseClass,
|
||||
checkBaseClass
|
||||
),
|
||||
hasBaseClassInBaseClasses: node!.base_classes?.some((baseClass) =>
|
||||
baseClassesSet.has(baseClass),
|
||||
baseClassesSet.has(baseClass)
|
||||
),
|
||||
displayName: node?.display_name,
|
||||
};
|
||||
|
|
@ -355,7 +355,7 @@ export function isTimeStampString(str: string): boolean {
|
|||
export function extractColumnsFromRows(
|
||||
rows: object[],
|
||||
mode: "intersection" | "union",
|
||||
excludeColumns?: Array<string>,
|
||||
excludeColumns?: Array<string>
|
||||
): (ColDef<any> | ColGroupDef<any>)[] {
|
||||
let columnsKeys: { [key: string]: ColDef<any> | ColGroupDef<any> } = {};
|
||||
if (rows.length === 0) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ test("CodeAreaModalComponent", async ({ page }) => {
|
|||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
||||
await page.getByTestId("code-button-modal").click();
|
||||
|
||||
const wCode =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from langflow.services.auth.utils import create_super_user, get_password_hash
|
||||
from langflow.services.database.models.user import UserUpdate
|
||||
from langflow.services.database.models.user.model import User
|
||||
|
|
@ -95,7 +96,7 @@ def test_data_consistency_after_update(client, active_user, logged_in_headers, s
|
|||
# Fetch the updated user from the database
|
||||
response = client.get("/api/v1/users/whoami", headers=logged_in_headers)
|
||||
assert response.status_code == 401, response.json()
|
||||
assert response.json()["detail"] == "Could not validate credentials"
|
||||
assert response.json()["detail"] == "User not found or is inactive."
|
||||
|
||||
|
||||
def test_data_consistency_after_delete(client, test_user, super_user_headers):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue