Merge branch 'dev' into mainPage
This commit is contained in:
commit
56d0898861
33 changed files with 436 additions and 250 deletions
164
poetry.lock
generated
164
poetry.lock
generated
|
|
@ -1,4 +1,4 @@
|
||||||
# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aiofiles"
|
name = "aiofiles"
|
||||||
|
|
@ -148,6 +148,27 @@ files = [
|
||||||
{file = "aiostream-0.4.5.tar.gz", hash = "sha256:3ecbf87085230fbcd9605c32ca20c4fb41af02c71d076eab246ea22e35947d88"},
|
{file = "aiostream-0.4.5.tar.gz", hash = "sha256:3ecbf87085230fbcd9605c32ca20c4fb41af02c71d076eab246ea22e35947d88"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anthropic"
|
||||||
|
version = "0.2.10"
|
||||||
|
description = "Library for accessing the anthropic API"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "anthropic-0.2.10-py3-none-any.whl", hash = "sha256:a007496207fd186b0bcb9592b00ca130069d2a427f3d6f602a61dbbd1ac6316e"},
|
||||||
|
{file = "anthropic-0.2.10.tar.gz", hash = "sha256:e4da061a86d8ffb86072c0b0feaf219a3a4f7dfddd4224df9ba769e469498c19"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
aiohttp = "*"
|
||||||
|
httpx = "*"
|
||||||
|
requests = "*"
|
||||||
|
tokenizers = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["black (>=22.3.0)", "pytest"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyio"
|
name = "anyio"
|
||||||
version = "3.7.0"
|
version = "3.7.0"
|
||||||
|
|
@ -719,14 +740,14 @@ superset = ["apache-superset (>=1.4.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cohere"
|
name = "cohere"
|
||||||
version = "4.6.0"
|
version = "4.7.0"
|
||||||
description = ""
|
description = ""
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7,<4.0"
|
python-versions = ">=3.7,<4.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "cohere-4.6.0-py3-none-any.whl", hash = "sha256:fc60fa73a2d96bdb9f70da4a290d3ede320b74ac01a24c229011049d7cb3511f"},
|
{file = "cohere-4.7.0-py3-none-any.whl", hash = "sha256:ed15621bd271b941110a572cbf6187a4db78cc8d7d9d35a881bffcaeeea21d7c"},
|
||||||
{file = "cohere-4.6.0.tar.gz", hash = "sha256:43218a0a40f6fc023e068732994fb631ce5d160a0bc9f9a3a22524b5932f34ea"},
|
{file = "cohere-4.7.0.tar.gz", hash = "sha256:46c674545ad36133a555c6db7f25bdc299e05ec4f77dee707b661a57eb06aea6"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -862,31 +883,31 @@ toml = ["tomli"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "40.0.2"
|
version = "41.0.1"
|
||||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:8f79b5ff5ad9d3218afb1e7e20ea74da5f76943ee5edb7f76e56ec5161ec782b"},
|
{file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:05dc219433b14046c476f6f09d7636b92a1c3e5808b9a6536adf4932b3b2c440"},
|
{file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4df2af28d7bedc84fe45bd49bc35d710aede676e2a4cb7fc6d103a2adc8afe4d"},
|
{file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dcca15d3a19a66e63662dc8d30f8036b07be851a8680eda92d079868f106288"},
|
{file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a04386fb7bc85fab9cd51b6308633a3c271e3d0d3eae917eebab2fac6219b6d2"},
|
{file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:adc0d980fd2760c9e5de537c28935cc32b9353baaf28e0814df417619c6c8c3b"},
|
{file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d5a1bd0e9e2031465761dfa920c16b0065ad77321d8a8c1f5ee331021fda65e9"},
|
{file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a95f4802d49faa6a674242e25bfeea6fc2acd915b5e5e29ac90a32b1139cae1c"},
|
{file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-win32.whl", hash = "sha256:aecbb1592b0188e030cb01f82d12556cf72e218280f621deed7d806afd2113f9"},
|
{file = "cryptography-41.0.1-cp37-abi3-win32.whl", hash = "sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5"},
|
||||||
{file = "cryptography-40.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:b12794f01d4cacfbd3177b9042198f3af1c856eedd0a98f10f141385c809a14b"},
|
{file = "cryptography-41.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c"},
|
||||||
{file = "cryptography-40.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:142bae539ef28a1c76794cca7f49729e7c54423f615cfd9b0b1fa90ebe53244b"},
|
{file = "cryptography-41.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb"},
|
||||||
{file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:956ba8701b4ffe91ba59665ed170a2ebbdc6fc0e40de5f6059195d9f2b33ca0e"},
|
{file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3"},
|
||||||
{file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f01c9863da784558165f5d4d916093737a75203a5c5286fde60e503e4276c7a"},
|
{file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039"},
|
||||||
{file = "cryptography-40.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3daf9b114213f8ba460b829a02896789751626a2a4e7a43a28ee77c04b5e4958"},
|
{file = "cryptography-41.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc"},
|
||||||
{file = "cryptography-40.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48f388d0d153350f378c7f7b41497a54ff1513c816bcbbcafe5b829e59b9ce5b"},
|
{file = "cryptography-41.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485"},
|
||||||
{file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c0764e72b36a3dc065c155e5b22f93df465da9c39af65516fe04ed3c68c92636"},
|
{file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c"},
|
||||||
{file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:cbaba590180cba88cb99a5f76f90808a624f18b169b90a4abb40c1fd8c19420e"},
|
{file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a"},
|
||||||
{file = "cryptography-40.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7a38250f433cd41df7fcb763caa3ee9362777fdb4dc642b9a349721d2bf47404"},
|
{file = "cryptography-41.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5"},
|
||||||
{file = "cryptography-40.0.2.tar.gz", hash = "sha256:c33c0d32b8594fa647d2e01dbccc303478e16fdd7cf98652d5b3ed11aa5e5c99"},
|
{file = "cryptography-41.0.1.tar.gz", hash = "sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -895,23 +916,23 @@ cffi = ">=1.12"
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
|
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
|
||||||
docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
|
docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
|
||||||
pep8test = ["black", "check-manifest", "mypy", "ruff"]
|
nox = ["nox"]
|
||||||
sdist = ["setuptools-rust (>=0.11.4)"]
|
pep8test = ["black", "check-sdist", "mypy", "ruff"]
|
||||||
|
sdist = ["build"]
|
||||||
ssh = ["bcrypt (>=3.1.5)"]
|
ssh = ["bcrypt (>=3.1.5)"]
|
||||||
test = ["iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist"]
|
test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
|
||||||
test-randomorder = ["pytest-randomly"]
|
test-randomorder = ["pytest-randomly"]
|
||||||
tox = ["tox"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctransformers"
|
name = "ctransformers"
|
||||||
version = "0.2.2"
|
version = "0.2.5"
|
||||||
description = "Python bindings for the Transformer models implemented in C/C++ using GGML library."
|
description = "Python bindings for the Transformer models implemented in C/C++ using GGML library."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
{file = "ctransformers-0.2.2-py3-none-any.whl", hash = "sha256:bf682dd0293dd87911c9a9a1169a4873ff55baebc16d465c6029c77f11b18cf6"},
|
{file = "ctransformers-0.2.5-py3-none-any.whl", hash = "sha256:5e0ee7d2be2cb1d627a702acdbf1f4f3c9c97d706e9d7f59a13079c1836a1432"},
|
||||||
{file = "ctransformers-0.2.2.tar.gz", hash = "sha256:1fc36b3fde36d9fd3cb69e48993315bb1f5f54ae552720eb909dc4b3a131c743"},
|
{file = "ctransformers-0.2.5.tar.gz", hash = "sha256:b813f19d5c2249b75422ae3188b1c834aeb8a095800df32328559a740acdb404"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -1044,14 +1065,14 @@ weaviate = ["weaviate-client (>=3.9.0,<3.10.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "docker"
|
name = "docker"
|
||||||
version = "6.1.2"
|
version = "6.1.3"
|
||||||
description = "A Python library for the Docker Engine API."
|
description = "A Python library for the Docker Engine API."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "docker-6.1.2-py3-none-any.whl", hash = "sha256:134cd828f84543cbf8e594ff81ca90c38288df3c0a559794c12f2e4b634ea19e"},
|
{file = "docker-6.1.3-py3-none-any.whl", hash = "sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9"},
|
||||||
{file = "docker-6.1.2.tar.gz", hash = "sha256:dcc088adc2ec4e7cfc594e275d8bd2c9738c56c808de97476939ef67db5af8c2"},
|
{file = "docker-6.1.3.tar.gz", hash = "sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -1096,9 +1117,7 @@ files = [
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b2707096d6df4321044fcde2c9f04da632d11a8be60957fd09d49a42fae71a29"},
|
{file = "duckdb-0.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b2707096d6df4321044fcde2c9f04da632d11a8be60957fd09d49a42fae71a29"},
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b27df1b70ae74d2c88efb5ffca8490954fdc678099509a9c4404ca30acc53426"},
|
{file = "duckdb-0.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b27df1b70ae74d2c88efb5ffca8490954fdc678099509a9c4404ca30acc53426"},
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75a97c800271b52dd0f37696d074c50576dcb4b2750b6115932a98696a268070"},
|
{file = "duckdb-0.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75a97c800271b52dd0f37696d074c50576dcb4b2750b6115932a98696a268070"},
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:804cac261a5e016506a6d67838a65d19b06a237f7949f1704f0e800eb708286a"},
|
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6b9abca7fa6713e1d031c18485343b4de99742c7e1b85c10718aa2f31a4e2c6"},
|
{file = "duckdb-0.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6b9abca7fa6713e1d031c18485343b4de99742c7e1b85c10718aa2f31a4e2c6"},
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:51aa6d606d49072abcfeb3be209eb559ac94c1b5e70f58ac3adbb94aca9cd69f"},
|
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7c8dc769aaf2be0a1c57995ca657e5b92c1c56fc8437edb720ca6cab571adf14"},
|
{file = "duckdb-0.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7c8dc769aaf2be0a1c57995ca657e5b92c1c56fc8437edb720ca6cab571adf14"},
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-win32.whl", hash = "sha256:c4207d18b42387c4a035846d8878eb967070198be8ac26fd77797ce320d1a400"},
|
{file = "duckdb-0.8.0-cp311-cp311-win32.whl", hash = "sha256:c4207d18b42387c4a035846d8878eb967070198be8ac26fd77797ce320d1a400"},
|
||||||
{file = "duckdb-0.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:0c392257547c20794c3072fcbca99a49ef0a49974005d755e93893e2b4875267"},
|
{file = "duckdb-0.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:0c392257547c20794c3072fcbca99a49ef0a49974005d755e93893e2b4875267"},
|
||||||
|
|
@ -1194,6 +1213,41 @@ files = [
|
||||||
[package.extras]
|
[package.extras]
|
||||||
tests = ["asttokens", "littleutils", "pytest", "rich"]
|
tests = ["asttokens", "littleutils", "pytest", "rich"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "faiss-cpu"
|
||||||
|
version = "1.7.4"
|
||||||
|
description = "A library for efficient similarity search and clustering of dense vectors."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "faiss-cpu-1.7.4.tar.gz", hash = "sha256:265dc31b0c079bf4433303bf6010f73922490adff9188b915e2d3f5e9c82dd0a"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50d4ebe7f1869483751c558558504f818980292a9b55be36f9a1ee1009d9a686"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b1db7fae7bd8312aeedd0c41536bcd19a6e297229e1dce526bde3a73ab8c0b5"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17b7fa7194a228a84929d9e6619d0e7dbf00cc0f717e3462253766f5e3d07de8"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dca531952a2e3eac56f479ff22951af4715ee44788a3fe991d208d766d3f95f3"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp310-cp310-win_amd64.whl", hash = "sha256:7173081d605e74766f950f2e3d6568a6f00c53f32fd9318063e96728c6c62821"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d0bbd6f55d7940cc0692f79e32a58c66106c3c950cee2341b05722de9da23ea3"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e13c14280376100f143767d0efe47dcb32618f69e62bbd3ea5cd38c2e1755926"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c521cb8462f3b00c0c7dfb11caff492bb67816528b947be28a3b76373952c41d"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afdd9fe1141117fed85961fd36ee627c83fc3b9fd47bafb52d3c849cc2f088b7"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp311-cp311-win_amd64.whl", hash = "sha256:2ff7f57889ea31d945e3b87275be3cad5d55b6261a4e3f51c7aba304d76b81fb"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:eeaf92f27d76249fb53c1adafe617b0f217ab65837acf7b4ec818511caf6e3d8"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:102b1bd763e9b0c281ac312590af3eaf1c8b663ccbc1145821fe6a9f92b8eaaf"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5512da6707c967310c46ff712b00418b7ae28e93cb609726136e826e9f2f14fa"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0c2e5b9d8c28c99f990e87379d5bbcc6c914da91ebb4250166864fd12db5755b"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:43f67f325393145d360171cd98786fcea6120ce50397319afd3bb78be409fb8a"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6a4e4af194b8fce74c4b770cad67ad1dd1b4673677fc169723e4c50ba5bd97a8"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31bfb7b9cffc36897ae02a983e04c09fe3b8c053110a287134751a115334a1df"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52d7de96abef2340c0d373c1f5cbc78026a3cebb0f8f3a5920920a00210ead1f"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:699feef85b23c2c729d794e26ca69bebc0bee920d676028c06fd0e0becc15c7e"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:559a0133f5ed44422acb09ee1ac0acffd90c6666d1bc0d671c18f6e93ad603e2"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1d71539fe3dc0f1bed41ef954ca701678776f231046bf0ca22ccea5cf5bef6"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12d45e0157024eb3249842163162983a1ac8b458f1a8b17bbf86f01be4585a99"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f0eab359e066d32c874f51a7d4bf6440edeec068b7fe47e6d803c73605a8b4c"},
|
||||||
|
{file = "faiss_cpu-1.7.4-cp39-cp39-win_amd64.whl", hash = "sha256:98459ceeeb735b9df1a5b94572106ffe0a6ce740eb7e4626715dd218657bb4dc"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fake-useragent"
|
name = "fake-useragent"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
|
@ -1211,14 +1265,14 @@ importlib-resources = {version = ">=5.0", markers = "python_version < \"3.10\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi"
|
name = "fastapi"
|
||||||
version = "0.95.2"
|
version = "0.96.0"
|
||||||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "fastapi-0.95.2-py3-none-any.whl", hash = "sha256:d374dbc4ef2ad9b803899bd3360d34c534adc574546e25314ab72c0c4411749f"},
|
{file = "fastapi-0.96.0-py3-none-any.whl", hash = "sha256:b8e11fe81e81eab4e1504209917338e0b80f783878a42c2b99467e5e1019a1e9"},
|
||||||
{file = "fastapi-0.95.2.tar.gz", hash = "sha256:4d9d3e8c71c73f11874bcf5e33626258d143252e329a01002f767306c64fb982"},
|
{file = "fastapi-0.96.0.tar.gz", hash = "sha256:71232d47c2787446991c81c41c249f8a16238d52d779c0e6b43927d3773dbe3c"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -1387,14 +1441,14 @@ uritemplate = ">=3.0.1,<5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "google-auth"
|
name = "google-auth"
|
||||||
version = "2.19.0"
|
version = "2.19.1"
|
||||||
description = "Google Authentication Library"
|
description = "Google Authentication Library"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
{file = "google-auth-2.19.0.tar.gz", hash = "sha256:f39d528077ac540793dd3c22a8706178f157642a67d874db25c640b7fead277e"},
|
{file = "google-auth-2.19.1.tar.gz", hash = "sha256:a9cfa88b3e16196845e64a3658eb953992129d13ac7337b064c6546f77c17183"},
|
||||||
{file = "google_auth-2.19.0-py2.py3-none-any.whl", hash = "sha256:be617bfaf77774008e9d177573f782e109188c8a64ae6e744285df5cea3e7df6"},
|
{file = "google_auth-2.19.1-py2.py3-none-any.whl", hash = "sha256:ea165e014c7cbd496558796b627c271aa8c18b4cba79dc1cc962b24c5efdfb85"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -2037,14 +2091,14 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipython"
|
name = "ipython"
|
||||||
version = "8.13.2"
|
version = "8.14.0"
|
||||||
description = "IPython: Productive Interactive Computing"
|
description = "IPython: Productive Interactive Computing"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "ipython-8.13.2-py3-none-any.whl", hash = "sha256:ffca270240fbd21b06b2974e14a86494d6d29290184e788275f55e0b55914926"},
|
{file = "ipython-8.14.0-py3-none-any.whl", hash = "sha256:248aca623f5c99a6635bc3857677b7320b9b8039f99f070ee0d20a5ca5a8e6bf"},
|
||||||
{file = "ipython-8.13.2.tar.gz", hash = "sha256:7dff3fad32b97f6488e02f87b970f309d082f758d7b7fc252e3b19ee0e432dbb"},
|
{file = "ipython-8.14.0.tar.gz", hash = "sha256:1d197b907b6ba441b692c48cf2a3a2de280dc0ac91a3405b39349a50272ca0a1"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -2376,13 +2430,13 @@ text-helpers = ["chardet (>=5.1.0,<6.0.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "langchain-serve"
|
name = "langchain-serve"
|
||||||
version = "0.0.40"
|
version = "0.0.41"
|
||||||
description = "Langchain Serve - serve your langchain apps on Jina AI Cloud."
|
description = "Langchain Serve - serve your langchain apps on Jina AI Cloud."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
{file = "langchain-serve-0.0.40.tar.gz", hash = "sha256:c60b173fcf0b682fbb70d34e8f485ce168e2229f55cb5c4ffbc26a5206af1c06"},
|
{file = "langchain-serve-0.0.41.tar.gz", hash = "sha256:fcf0d3ac9e48b5b24825ae2e1d8a383795c5744b18ef61cb74a99020a9e5d46a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -4679,14 +4733,14 @@ idna2008 = ["idna"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rich"
|
name = "rich"
|
||||||
version = "13.3.5"
|
version = "13.4.1"
|
||||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7.0"
|
python-versions = ">=3.7.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "rich-13.3.5-py3-none-any.whl", hash = "sha256:69cdf53799e63f38b95b9bf9c875f8c90e78dd62b2f00c13a911c7a3b9fa4704"},
|
{file = "rich-13.4.1-py3-none-any.whl", hash = "sha256:d204aadb50b936bf6b1a695385429d192bc1fdaf3e8b907e8e26f4c4e4b5bf75"},
|
||||||
{file = "rich-13.3.5.tar.gz", hash = "sha256:2d11b9b8dd03868f09b4fffadc84a6a8cda574e40dc90821bd845720ebb8e89c"},
|
{file = "rich-13.4.1.tar.gz", hash = "sha256:76f6b65ea7e5c5d924ba80e322231d7cb5b5981aa60bfc1e694f1bc097fe6fe1"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -5100,14 +5154,14 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textual"
|
name = "textual"
|
||||||
version = "0.26.0"
|
version = "0.27.0"
|
||||||
description = "Modern Text User Interface framework"
|
description = "Modern Text User Interface framework"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7,<4.0"
|
python-versions = ">=3.7,<4.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "textual-0.26.0-py3-none-any.whl", hash = "sha256:1efd04e9f61b3e95fd1c65436d3262f99e3f86cdeb524d13045bb551eb615c02"},
|
{file = "textual-0.27.0-py3-none-any.whl", hash = "sha256:dc45eaf7da330686c56d6f76f59d05fd216ce6aad90fa44ee269881efc622151"},
|
||||||
{file = "textual-0.26.0.tar.gz", hash = "sha256:78094c83017d2836b726513abdf434cc034a0e68cc45e63b3b056c9b8b7fa673"},
|
{file = "textual-0.27.0.tar.gz", hash = "sha256:8bdcb09dc35a706ef939b1276ccfdec10eaaee6147b41cb7587cf33298a8dd33"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
@ -6180,4 +6234,4 @@ deploy = ["langchain-serve"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = ">=3.9,<3.12"
|
python-versions = ">=3.9,<3.12"
|
||||||
content-hash = "2bf357ad30f79c68751b34c991b4a73767ceb628657f4133228d4eb487d8a6fb"
|
content-hash = "4cac7dea0c1222711ba7eed82d5716d5e361d454edb6e0299b387fbb115d2c3d"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "langflow"
|
name = "langflow"
|
||||||
version = "0.0.79"
|
version = "0.0.80"
|
||||||
description = "A Python package with a built-in web application"
|
description = "A Python package with a built-in web application"
|
||||||
authors = ["Logspace <contact@logspace.ai>"]
|
authors = ["Logspace <contact@logspace.ai>"]
|
||||||
maintainers = [
|
maintainers = [
|
||||||
|
|
@ -22,7 +22,7 @@ langflow = "langflow.__main__:main"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = ">=3.9,<3.12"
|
python = ">=3.9,<3.12"
|
||||||
fastapi = "^0.95.0"
|
fastapi = "^0.96.0"
|
||||||
uvicorn = "^0.20.0"
|
uvicorn = "^0.20.0"
|
||||||
beautifulsoup4 = "^4.11.2"
|
beautifulsoup4 = "^4.11.2"
|
||||||
google-search-results = "^2.4.1"
|
google-search-results = "^2.4.1"
|
||||||
|
|
@ -57,6 +57,8 @@ jina = "3.15.2"
|
||||||
sentence-transformers = "^2.2.2"
|
sentence-transformers = "^2.2.2"
|
||||||
ctransformers = "^0.2.2"
|
ctransformers = "^0.2.2"
|
||||||
cohere = "^4.6.0"
|
cohere = "^4.6.0"
|
||||||
|
faiss-cpu = "^1.7.4"
|
||||||
|
anthropic = "^0.2.9"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from langflow.api.base import (
|
||||||
PromptValidationResponse,
|
PromptValidationResponse,
|
||||||
validate_prompt,
|
validate_prompt,
|
||||||
)
|
)
|
||||||
from langflow.graph.node.types import VectorStoreNode
|
from langflow.graph.vertex.types import VectorStoreVertex
|
||||||
from langflow.interface.run import build_graph
|
from langflow.interface.run import build_graph
|
||||||
from langflow.utils.logger import logger
|
from langflow.utils.logger import logger
|
||||||
from langflow.utils.validate import validate_code
|
from langflow.utils.validate import validate_code
|
||||||
|
|
@ -49,7 +49,7 @@ def post_validate_node(node_id: str, data: dict):
|
||||||
node = graph.get_node(node_id)
|
node = graph.get_node(node_id)
|
||||||
if node is None:
|
if node is None:
|
||||||
raise ValueError(f"Node {node_id} not found")
|
raise ValueError(f"Node {node_id} not found")
|
||||||
if not isinstance(node, VectorStoreNode):
|
if not isinstance(node, VectorStoreVertex):
|
||||||
node.build()
|
node.build()
|
||||||
return json.dumps({"valid": True, "params": str(node._built_object_repr())})
|
return json.dumps({"valid": True, "params": str(node._built_object_repr())})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ llms:
|
||||||
- LlamaCpp
|
- LlamaCpp
|
||||||
- CTransformers
|
- CTransformers
|
||||||
- Cohere
|
- Cohere
|
||||||
|
- Anthropic
|
||||||
|
- ChatAnthropic
|
||||||
memories:
|
memories:
|
||||||
- ConversationBufferMemory
|
- ConversationBufferMemory
|
||||||
- ConversationSummaryMemory
|
- ConversationSummaryMemory
|
||||||
|
|
@ -79,7 +81,7 @@ tools:
|
||||||
- Calculator
|
- Calculator
|
||||||
- Serper Search
|
- Serper Search
|
||||||
- Tool
|
- Tool
|
||||||
- PythonFunction
|
- PythonFunctionTool
|
||||||
- JsonSpec
|
- JsonSpec
|
||||||
- News API
|
- News API
|
||||||
- TMDB API
|
- TMDB API
|
||||||
|
|
@ -118,6 +120,7 @@ vectorstores:
|
||||||
- Chroma
|
- Chroma
|
||||||
- Qdrant
|
- Qdrant
|
||||||
- Weaviate
|
- Weaviate
|
||||||
|
- FAISS
|
||||||
wrappers:
|
wrappers:
|
||||||
- RequestsWrapper
|
- RequestsWrapper
|
||||||
# - ChatPromptTemplate
|
# - ChatPromptTemplate
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from langflow.template import frontend_node
|
||||||
CUSTOM_NODES = {
|
CUSTOM_NODES = {
|
||||||
"prompts": {"ZeroShotPrompt": frontend_node.prompts.ZeroShotPromptNode()},
|
"prompts": {"ZeroShotPrompt": frontend_node.prompts.ZeroShotPromptNode()},
|
||||||
"tools": {
|
"tools": {
|
||||||
"PythonFunction": frontend_node.tools.PythonFunctionNode(),
|
"PythonFunctionTool": frontend_node.tools.PythonFunctionToolNode(),
|
||||||
"Tool": frontend_node.tools.ToolNode(),
|
"Tool": frontend_node.tools.ToolNode(),
|
||||||
},
|
},
|
||||||
"agents": {
|
"agents": {
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,35 @@
|
||||||
from langflow.graph.edge.base import Edge
|
from langflow.graph.edge.base import Edge
|
||||||
from langflow.graph.graph.base import Graph
|
from langflow.graph.graph.base import Graph
|
||||||
from langflow.graph.node.base import Node
|
from langflow.graph.vertex.base import Vertex
|
||||||
from langflow.graph.node.types import (
|
from langflow.graph.vertex.types import (
|
||||||
AgentNode,
|
AgentVertex,
|
||||||
ChainNode,
|
ChainVertex,
|
||||||
DocumentLoaderNode,
|
DocumentLoaderVertex,
|
||||||
EmbeddingNode,
|
EmbeddingVertex,
|
||||||
LLMNode,
|
LLMVertex,
|
||||||
MemoryNode,
|
MemoryVertex,
|
||||||
PromptNode,
|
PromptVertex,
|
||||||
TextSplitterNode,
|
TextSplitterVertex,
|
||||||
ToolNode,
|
ToolVertex,
|
||||||
ToolkitNode,
|
ToolkitVertex,
|
||||||
VectorStoreNode,
|
VectorStoreVertex,
|
||||||
WrapperNode,
|
WrapperVertex,
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Graph",
|
"Graph",
|
||||||
"Node",
|
"Vertex",
|
||||||
"Edge",
|
"Edge",
|
||||||
"AgentNode",
|
"AgentVertex",
|
||||||
"ChainNode",
|
"ChainVertex",
|
||||||
"DocumentLoaderNode",
|
"DocumentLoaderVertex",
|
||||||
"EmbeddingNode",
|
"EmbeddingVertex",
|
||||||
"LLMNode",
|
"LLMVertex",
|
||||||
"MemoryNode",
|
"MemoryVertex",
|
||||||
"PromptNode",
|
"PromptVertex",
|
||||||
"TextSplitterNode",
|
"TextSplitterVertex",
|
||||||
"ToolNode",
|
"ToolVertex",
|
||||||
"ToolkitNode",
|
"ToolkitVertex",
|
||||||
"VectorStoreNode",
|
"VectorStoreVertex",
|
||||||
"WrapperNode",
|
"WrapperVertex",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ from langflow.utils.logger import logger
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from langflow.graph.node.base import Node
|
from langflow.graph.vertex.base import Vertex
|
||||||
|
|
||||||
|
|
||||||
class Edge:
|
class Edge:
|
||||||
def __init__(self, source: "Node", target: "Node"):
|
def __init__(self, source: "Vertex", target: "Vertex"):
|
||||||
self.source: "Node" = source
|
self.source: "Vertex" = source
|
||||||
self.target: "Node" = target
|
self.target: "Vertex" = target
|
||||||
self.validate_edge()
|
self.validate_edge()
|
||||||
|
|
||||||
def validate_edge(self) -> None:
|
def validate_edge(self) -> None:
|
||||||
|
|
@ -41,7 +41,7 @@ class Edge:
|
||||||
logger.debug(self.target_reqs)
|
logger.debug(self.target_reqs)
|
||||||
if no_matched_type:
|
if no_matched_type:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Edge between {self.source.node_type} and {self.target.node_type} "
|
f"Edge between {self.source.vertex_type} and {self.target.vertex_type} "
|
||||||
f"has no matched type"
|
f"has no matched type"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
from typing import Dict, List, Type, Union
|
from typing import Dict, List, Type, Union
|
||||||
|
|
||||||
from langflow.graph.edge.base import Edge
|
from langflow.graph.edge.base import Edge
|
||||||
from langflow.graph.graph.constants import NODE_TYPE_MAP
|
from langflow.graph.graph.constants import VERTEX_TYPE_MAP
|
||||||
from langflow.graph.node.base import Node
|
from langflow.graph.vertex.base import Vertex
|
||||||
from langflow.graph.node.types import (
|
from langflow.graph.vertex.types import (
|
||||||
FileToolNode,
|
FileToolVertex,
|
||||||
LLMNode,
|
LLMVertex,
|
||||||
ToolkitNode,
|
ToolkitVertex,
|
||||||
)
|
)
|
||||||
from langflow.interface.tools.constants import FILE_TOOLS
|
from langflow.interface.tools.constants import FILE_TOOLS
|
||||||
from langflow.utils import payload
|
from langflow.utils import payload
|
||||||
|
|
@ -26,7 +26,7 @@ class Graph:
|
||||||
|
|
||||||
def _build_graph(self) -> None:
|
def _build_graph(self) -> None:
|
||||||
"""Builds the graph from the nodes and edges."""
|
"""Builds the graph from the nodes and edges."""
|
||||||
self.nodes = self._build_nodes()
|
self.nodes = self._build_vertices()
|
||||||
self.edges = self._build_edges()
|
self.edges = self._build_edges()
|
||||||
for edge in self.edges:
|
for edge in self.edges:
|
||||||
edge.source.add_edge(edge)
|
edge.source.add_edge(edge)
|
||||||
|
|
@ -43,12 +43,12 @@ class Graph:
|
||||||
llm_node = None
|
llm_node = None
|
||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
node._build_params()
|
node._build_params()
|
||||||
if isinstance(node, LLMNode):
|
if isinstance(node, LLMVertex):
|
||||||
llm_node = node
|
llm_node = node
|
||||||
|
|
||||||
if llm_node:
|
if llm_node:
|
||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
if isinstance(node, ToolkitNode):
|
if isinstance(node, ToolkitVertex):
|
||||||
node.params["llm"] = llm_node
|
node.params["llm"] = llm_node
|
||||||
|
|
||||||
def _remove_invalid_nodes(self) -> None:
|
def _remove_invalid_nodes(self) -> None:
|
||||||
|
|
@ -60,23 +60,23 @@ class Graph:
|
||||||
or (len(self.nodes) == 1 and len(self.edges) == 0)
|
or (len(self.nodes) == 1 and len(self.edges) == 0)
|
||||||
]
|
]
|
||||||
|
|
||||||
def _validate_node(self, node: Node) -> bool:
|
def _validate_node(self, node: Vertex) -> bool:
|
||||||
"""Validates a node."""
|
"""Validates a node."""
|
||||||
# All nodes that do not have edges are invalid
|
# All nodes that do not have edges are invalid
|
||||||
return len(node.edges) > 0
|
return len(node.edges) > 0
|
||||||
|
|
||||||
def get_node(self, node_id: str) -> Union[None, Node]:
|
def get_node(self, node_id: str) -> Union[None, Vertex]:
|
||||||
"""Returns a node by id."""
|
"""Returns a node by id."""
|
||||||
return next((node for node in self.nodes if node.id == node_id), None)
|
return next((node for node in self.nodes if node.id == node_id), None)
|
||||||
|
|
||||||
def get_nodes_with_target(self, node: Node) -> List[Node]:
|
def get_nodes_with_target(self, node: Vertex) -> List[Vertex]:
|
||||||
"""Returns the nodes connected to a node."""
|
"""Returns the nodes connected to a node."""
|
||||||
connected_nodes: List[Node] = [
|
connected_nodes: List[Vertex] = [
|
||||||
edge.source for edge in self.edges if edge.target == node
|
edge.source for edge in self.edges if edge.target == node
|
||||||
]
|
]
|
||||||
return connected_nodes
|
return connected_nodes
|
||||||
|
|
||||||
def build(self) -> List[Node]:
|
def build(self) -> List[Vertex]:
|
||||||
"""Builds the graph."""
|
"""Builds the graph."""
|
||||||
# Get root node
|
# Get root node
|
||||||
root_node = payload.get_root_node(self)
|
root_node = payload.get_root_node(self)
|
||||||
|
|
@ -84,9 +84,9 @@ class Graph:
|
||||||
raise ValueError("No root node found")
|
raise ValueError("No root node found")
|
||||||
return root_node.build()
|
return root_node.build()
|
||||||
|
|
||||||
def get_node_neighbors(self, node: Node) -> Dict[Node, int]:
|
def get_node_neighbors(self, node: Vertex) -> Dict[Vertex, int]:
|
||||||
"""Returns the neighbors of a node."""
|
"""Returns the neighbors of a node."""
|
||||||
neighbors: Dict[Node, int] = {}
|
neighbors: Dict[Vertex, int] = {}
|
||||||
for edge in self.edges:
|
for edge in self.edges:
|
||||||
if edge.source == node:
|
if edge.source == node:
|
||||||
neighbor = edge.target
|
neighbor = edge.target
|
||||||
|
|
@ -117,28 +117,30 @@ class Graph:
|
||||||
edges.append(Edge(source, target))
|
edges.append(Edge(source, target))
|
||||||
return edges
|
return edges
|
||||||
|
|
||||||
def _get_node_class(self, node_type: str, node_lc_type: str) -> Type[Node]:
|
def _get_vertex_class(self, node_type: str, node_lc_type: str) -> Type[Vertex]:
|
||||||
"""Returns the node class based on the node type."""
|
"""Returns the node class based on the node type."""
|
||||||
if node_type in FILE_TOOLS:
|
if node_type in FILE_TOOLS:
|
||||||
return FileToolNode
|
return FileToolVertex
|
||||||
if node_type in NODE_TYPE_MAP:
|
if node_type in VERTEX_TYPE_MAP:
|
||||||
return NODE_TYPE_MAP[node_type]
|
return VERTEX_TYPE_MAP[node_type]
|
||||||
return NODE_TYPE_MAP[node_lc_type] if node_lc_type in NODE_TYPE_MAP else Node
|
return (
|
||||||
|
VERTEX_TYPE_MAP[node_lc_type] if node_lc_type in VERTEX_TYPE_MAP else Vertex
|
||||||
|
)
|
||||||
|
|
||||||
def _build_nodes(self) -> List[Node]:
|
def _build_vertices(self) -> List[Vertex]:
|
||||||
"""Builds the nodes of the graph."""
|
"""Builds the vertices of the graph."""
|
||||||
nodes: List[Node] = []
|
nodes: List[Vertex] = []
|
||||||
for node in self._nodes:
|
for node in self._nodes:
|
||||||
node_data = node["data"]
|
node_data = node["data"]
|
||||||
node_type: str = node_data["type"] # type: ignore
|
node_type: str = node_data["type"] # type: ignore
|
||||||
node_lc_type: str = node_data["node"]["template"]["_type"] # type: ignore
|
node_lc_type: str = node_data["node"]["template"]["_type"] # type: ignore
|
||||||
|
|
||||||
NodeClass = self._get_node_class(node_type, node_lc_type)
|
VertexClass = self._get_vertex_class(node_type, node_lc_type)
|
||||||
nodes.append(NodeClass(node))
|
nodes.append(VertexClass(node))
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def get_children_by_node_type(self, node: Node, node_type: str) -> List[Node]:
|
def get_children_by_node_type(self, node: Vertex, node_type: str) -> List[Vertex]:
|
||||||
"""Returns the children of a node based on the node type."""
|
"""Returns the children of a node based on the node type."""
|
||||||
children = []
|
children = []
|
||||||
node_types = [node.data["type"]]
|
node_types = [node.data["type"]]
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
from langflow.graph.node.base import Node
|
from langflow.graph.vertex.base import Vertex
|
||||||
from langflow.graph.node.types import (
|
from langflow.graph.vertex.types import (
|
||||||
AgentNode,
|
AgentVertex,
|
||||||
ChainNode,
|
ChainVertex,
|
||||||
DocumentLoaderNode,
|
DocumentLoaderVertex,
|
||||||
EmbeddingNode,
|
EmbeddingVertex,
|
||||||
LLMNode,
|
LLMVertex,
|
||||||
MemoryNode,
|
MemoryVertex,
|
||||||
PromptNode,
|
PromptVertex,
|
||||||
TextSplitterNode,
|
TextSplitterVertex,
|
||||||
ToolNode,
|
ToolVertex,
|
||||||
ToolkitNode,
|
ToolkitVertex,
|
||||||
VectorStoreNode,
|
VectorStoreVertex,
|
||||||
WrapperNode,
|
WrapperVertex,
|
||||||
)
|
)
|
||||||
from langflow.interface.agents.base import agent_creator
|
from langflow.interface.agents.base import agent_creator
|
||||||
from langflow.interface.chains.base import chain_creator
|
from langflow.interface.chains.base import chain_creator
|
||||||
|
|
@ -33,17 +33,17 @@ from typing import Dict, Type
|
||||||
DIRECT_TYPES = ["str", "bool", "code", "int", "float", "Any", "prompt"]
|
DIRECT_TYPES = ["str", "bool", "code", "int", "float", "Any", "prompt"]
|
||||||
|
|
||||||
|
|
||||||
NODE_TYPE_MAP: Dict[str, Type[Node]] = {
|
VERTEX_TYPE_MAP: Dict[str, Type[Vertex]] = {
|
||||||
**{t: PromptNode for t in prompt_creator.to_list()},
|
**{t: PromptVertex for t in prompt_creator.to_list()},
|
||||||
**{t: AgentNode for t in agent_creator.to_list()},
|
**{t: AgentVertex for t in agent_creator.to_list()},
|
||||||
**{t: ChainNode for t in chain_creator.to_list()},
|
**{t: ChainVertex for t in chain_creator.to_list()},
|
||||||
**{t: ToolNode for t in tool_creator.to_list()},
|
**{t: ToolVertex for t in tool_creator.to_list()},
|
||||||
**{t: ToolkitNode for t in toolkits_creator.to_list()},
|
**{t: ToolkitVertex for t in toolkits_creator.to_list()},
|
||||||
**{t: WrapperNode for t in wrapper_creator.to_list()},
|
**{t: WrapperVertex for t in wrapper_creator.to_list()},
|
||||||
**{t: LLMNode for t in llm_creator.to_list()},
|
**{t: LLMVertex for t in llm_creator.to_list()},
|
||||||
**{t: MemoryNode for t in memory_creator.to_list()},
|
**{t: MemoryVertex for t in memory_creator.to_list()},
|
||||||
**{t: EmbeddingNode for t in embedding_creator.to_list()},
|
**{t: EmbeddingVertex for t in embedding_creator.to_list()},
|
||||||
**{t: VectorStoreNode for t in vectorstore_creator.to_list()},
|
**{t: VectorStoreVertex for t in vectorstore_creator.to_list()},
|
||||||
**{t: DocumentLoaderNode for t in documentloader_creator.to_list()},
|
**{t: DocumentLoaderVertex for t in documentloader_creator.to_list()},
|
||||||
**{t: TextSplitterNode for t in textsplitter_creator.to_list()},
|
**{t: TextSplitterVertex for t in textsplitter_creator.to_list()},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from langflow.cache import base as cache_utils
|
from langflow.cache import base as cache_utils
|
||||||
from langflow.graph.node.constants import DIRECT_TYPES
|
from langflow.graph.vertex.constants import DIRECT_TYPES
|
||||||
from langflow.interface import loading
|
from langflow.interface import loading
|
||||||
from langflow.interface.listing import ALL_TYPES_DICT
|
from langflow.interface.listing import ALL_TYPES_DICT
|
||||||
from langflow.utils.logger import logger
|
from langflow.utils.logger import logger
|
||||||
|
|
@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
||||||
from langflow.graph.edge.base import Edge
|
from langflow.graph.edge.base import Edge
|
||||||
|
|
||||||
|
|
||||||
class Node:
|
class Vertex:
|
||||||
def __init__(self, data: Dict, base_type: Optional[str] = None) -> None:
|
def __init__(self, data: Dict, base_type: Optional[str] = None) -> None:
|
||||||
self.id: str = data["id"]
|
self.id: str = data["id"]
|
||||||
self._data = data
|
self._data = data
|
||||||
|
|
@ -48,12 +48,12 @@ class Node:
|
||||||
]
|
]
|
||||||
|
|
||||||
template_dict = self.data["node"]["template"]
|
template_dict = self.data["node"]["template"]
|
||||||
self.node_type = (
|
self.vertex_type = (
|
||||||
self.data["type"] if "Tool" not in self.output else template_dict["_type"]
|
self.data["type"] if "Tool" not in self.output else template_dict["_type"]
|
||||||
)
|
)
|
||||||
if self.base_type is None:
|
if self.base_type is None:
|
||||||
for base_type, value in ALL_TYPES_DICT.items():
|
for base_type, value in ALL_TYPES_DICT.items():
|
||||||
if self.node_type in value:
|
if self.vertex_type in value:
|
||||||
self.base_type = base_type
|
self.base_type = base_type
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
@ -113,7 +113,7 @@ class Node:
|
||||||
if value["required"] and not edges:
|
if value["required"] and not edges:
|
||||||
# If a required parameter is not found, raise an error
|
# If a required parameter is not found, raise an error
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Required input {key} for module {self.node_type} not found"
|
f"Required input {key} for module {self.vertex_type} not found"
|
||||||
)
|
)
|
||||||
elif value["list"]:
|
elif value["list"]:
|
||||||
# If this is a list parameter, append all sources to a list
|
# If this is a list parameter, append all sources to a list
|
||||||
|
|
@ -128,7 +128,7 @@ class Node:
|
||||||
# so we need to check if value has value
|
# so we need to check if value has value
|
||||||
new_value = value.get("value")
|
new_value = value.get("value")
|
||||||
if new_value is None:
|
if new_value is None:
|
||||||
warnings.warn(f"Value for {key} in {self.node_type} is None. ")
|
warnings.warn(f"Value for {key} in {self.vertex_type} is None. ")
|
||||||
if value.get("type") == "int":
|
if value.get("type") == "int":
|
||||||
with contextlib.suppress(TypeError, ValueError):
|
with contextlib.suppress(TypeError, ValueError):
|
||||||
new_value = int(new_value) # type: ignore
|
new_value = int(new_value) # type: ignore
|
||||||
|
|
@ -148,12 +148,12 @@ class Node:
|
||||||
# and continue
|
# and continue
|
||||||
# Another aspect is that the node_type is the class that we need to import
|
# Another aspect is that the node_type is the class that we need to import
|
||||||
# and instantiate with these built params
|
# and instantiate with these built params
|
||||||
logger.debug(f"Building {self.node_type}")
|
logger.debug(f"Building {self.vertex_type}")
|
||||||
# Build each node in the params dict
|
# Build each node in the params dict
|
||||||
for key, value in self.params.copy().items():
|
for key, value in self.params.copy().items():
|
||||||
# Check if Node or list of Nodes and not self
|
# Check if Node or list of Nodes and not self
|
||||||
# to avoid recursion
|
# to avoid recursion
|
||||||
if isinstance(value, Node):
|
if isinstance(value, Vertex):
|
||||||
if value == self:
|
if value == self:
|
||||||
del self.params[key]
|
del self.params[key]
|
||||||
continue
|
continue
|
||||||
|
|
@ -177,7 +177,7 @@ class Node:
|
||||||
|
|
||||||
self.params[key] = result
|
self.params[key] = result
|
||||||
elif isinstance(value, list) and all(
|
elif isinstance(value, list) and all(
|
||||||
isinstance(node, Node) for node in value
|
isinstance(node, Vertex) for node in value
|
||||||
):
|
):
|
||||||
self.params[key] = []
|
self.params[key] = []
|
||||||
for node in value:
|
for node in value:
|
||||||
|
|
@ -193,17 +193,17 @@ class Node:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._built_object = loading.instantiate_class(
|
self._built_object = loading.instantiate_class(
|
||||||
node_type=self.node_type,
|
node_type=self.vertex_type,
|
||||||
base_type=self.base_type,
|
base_type=self.base_type,
|
||||||
params=self.params,
|
params=self.params,
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Error building node {self.node_type}: {str(exc)}"
|
f"Error building node {self.vertex_type}: {str(exc)}"
|
||||||
) from exc
|
) from exc
|
||||||
|
|
||||||
if self._built_object is None:
|
if self._built_object is None:
|
||||||
raise ValueError(f"Node type {self.node_type} not found")
|
raise ValueError(f"Node type {self.vertex_type} not found")
|
||||||
|
|
||||||
self._built = True
|
self._built = True
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ class Node:
|
||||||
return f"Node(id={self.id}, data={self.data})"
|
return f"Node(id={self.id}, data={self.data})"
|
||||||
|
|
||||||
def __eq__(self, __o: object) -> bool:
|
def __eq__(self, __o: object) -> bool:
|
||||||
return self.id == __o.id if isinstance(__o, Node) else False
|
return self.id == __o.id if isinstance(__o, Vertex) else False
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return id(self)
|
return id(self)
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from langflow.graph.node.base import Node
|
from langflow.graph.vertex.base import Vertex
|
||||||
from langflow.graph.utils import extract_input_variables_from_prompt
|
from langflow.graph.utils import extract_input_variables_from_prompt
|
||||||
|
|
||||||
|
|
||||||
class AgentNode(Node):
|
class AgentVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="agents")
|
super().__init__(data, base_type="agents")
|
||||||
|
|
||||||
self.tools: List[ToolNode] = []
|
self.tools: List[ToolVertex] = []
|
||||||
self.chains: List[ChainNode] = []
|
self.chains: List[ChainVertex] = []
|
||||||
|
|
||||||
def _set_tools_and_chains(self) -> None:
|
def _set_tools_and_chains(self) -> None:
|
||||||
for edge in self.edges:
|
for edge in self.edges:
|
||||||
source_node = edge.source
|
source_node = edge.source
|
||||||
if isinstance(source_node, ToolNode):
|
if isinstance(source_node, ToolVertex):
|
||||||
self.tools.append(source_node)
|
self.tools.append(source_node)
|
||||||
elif isinstance(source_node, ChainNode):
|
elif isinstance(source_node, ChainVertex):
|
||||||
self.chains.append(source_node)
|
self.chains.append(source_node)
|
||||||
|
|
||||||
def build(self, force: bool = False) -> Any:
|
def build(self, force: bool = False) -> Any:
|
||||||
|
|
@ -33,24 +33,28 @@ class AgentNode(Node):
|
||||||
self._build()
|
self._build()
|
||||||
|
|
||||||
#! Cannot deepcopy VectorStore, VectorStoreRouter, or SQL agents
|
#! Cannot deepcopy VectorStore, VectorStoreRouter, or SQL agents
|
||||||
if self.node_type in ["VectorStoreAgent", "VectorStoreRouterAgent", "SQLAgent"]:
|
if self.vertex_type in [
|
||||||
|
"VectorStoreAgent",
|
||||||
|
"VectorStoreRouterAgent",
|
||||||
|
"SQLAgent",
|
||||||
|
]:
|
||||||
return self._built_object
|
return self._built_object
|
||||||
return self._built_object
|
return self._built_object
|
||||||
|
|
||||||
|
|
||||||
class ToolNode(Node):
|
class ToolVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="tools")
|
super().__init__(data, base_type="tools")
|
||||||
|
|
||||||
|
|
||||||
class PromptNode(Node):
|
class PromptVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="prompts")
|
super().__init__(data, base_type="prompts")
|
||||||
|
|
||||||
def build(
|
def build(
|
||||||
self,
|
self,
|
||||||
force: bool = False,
|
force: bool = False,
|
||||||
tools: Optional[Union[List[Node], List[ToolNode]]] = None,
|
tools: Optional[Union[List[Vertex], List[ToolVertex]]] = None,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
if not self._built or force:
|
if not self._built or force:
|
||||||
if (
|
if (
|
||||||
|
|
@ -59,7 +63,7 @@ class PromptNode(Node):
|
||||||
):
|
):
|
||||||
self.params["input_variables"] = []
|
self.params["input_variables"] = []
|
||||||
# Check if it is a ZeroShotPrompt and needs a tool
|
# Check if it is a ZeroShotPrompt and needs a tool
|
||||||
if "ShotPrompt" in self.node_type:
|
if "ShotPrompt" in self.vertex_type:
|
||||||
tools = (
|
tools = (
|
||||||
[tool_node.build() for tool_node in tools]
|
[tool_node.build() for tool_node in tools]
|
||||||
if tools is not None
|
if tools is not None
|
||||||
|
|
@ -83,31 +87,31 @@ class PromptNode(Node):
|
||||||
return self._built_object
|
return self._built_object
|
||||||
|
|
||||||
|
|
||||||
class ChainNode(Node):
|
class ChainVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="chains")
|
super().__init__(data, base_type="chains")
|
||||||
|
|
||||||
def build(
|
def build(
|
||||||
self,
|
self,
|
||||||
force: bool = False,
|
force: bool = False,
|
||||||
tools: Optional[Union[List[Node], List[ToolNode]]] = None,
|
tools: Optional[Union[List[Vertex], List[ToolVertex]]] = None,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
if not self._built or force:
|
if not self._built or force:
|
||||||
# Check if the chain requires a PromptNode
|
# Check if the chain requires a PromptNode
|
||||||
for key, value in self.params.items():
|
for key, value in self.params.items():
|
||||||
if isinstance(value, PromptNode):
|
if isinstance(value, PromptVertex):
|
||||||
# Build the PromptNode, passing the tools if available
|
# Build the PromptNode, passing the tools if available
|
||||||
self.params[key] = value.build(tools=tools, force=force)
|
self.params[key] = value.build(tools=tools, force=force)
|
||||||
|
|
||||||
self._build()
|
self._build()
|
||||||
|
|
||||||
#! Cannot deepcopy SQLDatabaseChain
|
#! Cannot deepcopy SQLDatabaseChain
|
||||||
if self.node_type in ["SQLDatabaseChain"]:
|
if self.vertex_type in ["SQLDatabaseChain"]:
|
||||||
return self._built_object
|
return self._built_object
|
||||||
return self._built_object
|
return self._built_object
|
||||||
|
|
||||||
|
|
||||||
class LLMNode(Node):
|
class LLMVertex(Vertex):
|
||||||
built_node_type = None
|
built_node_type = None
|
||||||
class_built_object = None
|
class_built_object = None
|
||||||
|
|
||||||
|
|
@ -117,28 +121,28 @@ class LLMNode(Node):
|
||||||
def build(self, force: bool = False) -> Any:
|
def build(self, force: bool = False) -> Any:
|
||||||
# LLM is different because some models might take up too much memory
|
# LLM is different because some models might take up too much memory
|
||||||
# or time to load. So we only load them when we need them.ß
|
# or time to load. So we only load them when we need them.ß
|
||||||
if self.node_type == self.built_node_type:
|
if self.vertex_type == self.built_node_type:
|
||||||
return self.class_built_object
|
return self.class_built_object
|
||||||
if not self._built or force:
|
if not self._built or force:
|
||||||
self._build()
|
self._build()
|
||||||
self.built_node_type = self.node_type
|
self.built_node_type = self.vertex_type
|
||||||
self.class_built_object = self._built_object
|
self.class_built_object = self._built_object
|
||||||
# Avoid deepcopying the LLM
|
# Avoid deepcopying the LLM
|
||||||
# that are loaded from a file
|
# that are loaded from a file
|
||||||
return self._built_object
|
return self._built_object
|
||||||
|
|
||||||
|
|
||||||
class ToolkitNode(Node):
|
class ToolkitVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="toolkits")
|
super().__init__(data, base_type="toolkits")
|
||||||
|
|
||||||
|
|
||||||
class FileToolNode(ToolNode):
|
class FileToolVertex(ToolVertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data)
|
super().__init__(data)
|
||||||
|
|
||||||
|
|
||||||
class WrapperNode(Node):
|
class WrapperVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="wrappers")
|
super().__init__(data, base_type="wrappers")
|
||||||
|
|
||||||
|
|
@ -150,7 +154,7 @@ class WrapperNode(Node):
|
||||||
return self._built_object
|
return self._built_object
|
||||||
|
|
||||||
|
|
||||||
class DocumentLoaderNode(Node):
|
class DocumentLoaderVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="documentloaders")
|
super().__init__(data, base_type="documentloaders")
|
||||||
|
|
||||||
|
|
@ -158,17 +162,17 @@ class DocumentLoaderNode(Node):
|
||||||
# This built_object is a list of documents. Maybe we should
|
# This built_object is a list of documents. Maybe we should
|
||||||
# show how many documents are in the list?
|
# show how many documents are in the list?
|
||||||
if self._built_object:
|
if self._built_object:
|
||||||
return f"""{self.node_type}({len(self._built_object)} documents)
|
return f"""{self.vertex_type}({len(self._built_object)} documents)
|
||||||
Documents: {self._built_object[:3]}..."""
|
Documents: {self._built_object[:3]}..."""
|
||||||
return f"{self.node_type}()"
|
return f"{self.vertex_type}()"
|
||||||
|
|
||||||
|
|
||||||
class EmbeddingNode(Node):
|
class EmbeddingVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="embeddings")
|
super().__init__(data, base_type="embeddings")
|
||||||
|
|
||||||
|
|
||||||
class VectorStoreNode(Node):
|
class VectorStoreVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="vectorstores")
|
super().__init__(data, base_type="vectorstores")
|
||||||
|
|
||||||
|
|
@ -176,12 +180,12 @@ class VectorStoreNode(Node):
|
||||||
return "Vector stores can take time to build. It will build on the first query."
|
return "Vector stores can take time to build. It will build on the first query."
|
||||||
|
|
||||||
|
|
||||||
class MemoryNode(Node):
|
class MemoryVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="memory")
|
super().__init__(data, base_type="memory")
|
||||||
|
|
||||||
|
|
||||||
class TextSplitterNode(Node):
|
class TextSplitterVertex(Vertex):
|
||||||
def __init__(self, data: Dict):
|
def __init__(self, data: Dict):
|
||||||
super().__init__(data, base_type="textsplitters")
|
super().__init__(data, base_type="textsplitters")
|
||||||
|
|
||||||
|
|
@ -189,5 +193,6 @@ class TextSplitterNode(Node):
|
||||||
# This built_object is a list of documents. Maybe we should
|
# This built_object is a list of documents. Maybe we should
|
||||||
# show how many documents are in the list?
|
# show how many documents are in the list?
|
||||||
if self._built_object:
|
if self._built_object:
|
||||||
return f"""{self.node_type}({len(self._built_object)} documents)\nDocuments: {self._built_object[:3]}..."""
|
return f"""{self.vertex_type}({len(self._built_object)} documents)
|
||||||
return f"{self.node_type}()"
|
\nDocuments: {self._built_object[:3]}..."""
|
||||||
|
return f"{self.vertex_type}()"
|
||||||
|
|
@ -11,12 +11,14 @@ from langchain import (
|
||||||
text_splitter,
|
text_splitter,
|
||||||
)
|
)
|
||||||
from langchain.agents import agent_toolkits
|
from langchain.agents import agent_toolkits
|
||||||
|
from langchain.chat_models import ChatAnthropic
|
||||||
from langchain.chat_models import ChatOpenAI
|
from langchain.chat_models import ChatOpenAI
|
||||||
|
|
||||||
from langflow.interface.importing.utils import import_class
|
from langflow.interface.importing.utils import import_class
|
||||||
|
|
||||||
## LLMs
|
## LLMs
|
||||||
llm_type_to_cls_dict = llms.type_to_cls_dict
|
llm_type_to_cls_dict = llms.type_to_cls_dict
|
||||||
|
llm_type_to_cls_dict["anthropic-chat"] = ChatAnthropic # type: ignore
|
||||||
llm_type_to_cls_dict["openai-chat"] = ChatOpenAI # type: ignore
|
llm_type_to_cls_dict["openai-chat"] = ChatOpenAI # type: ignore
|
||||||
|
|
||||||
## Chains
|
## Chains
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ from langchain.base_language import BaseLanguageModel
|
||||||
from langchain.chains.base import Chain
|
from langchain.chains.base import Chain
|
||||||
from langchain.chat_models.base import BaseChatModel
|
from langchain.chat_models.base import BaseChatModel
|
||||||
from langchain.tools import BaseTool
|
from langchain.tools import BaseTool
|
||||||
|
from langflow.utils import validate
|
||||||
|
|
||||||
|
|
||||||
def import_module(module_path: str) -> Any:
|
def import_module(module_path: str) -> Any:
|
||||||
|
|
@ -147,3 +148,10 @@ def import_utility(utility: str) -> Any:
|
||||||
if utility == "SQLDatabase":
|
if utility == "SQLDatabase":
|
||||||
return import_class(f"langchain.sql_database.{utility}")
|
return import_class(f"langchain.sql_database.{utility}")
|
||||||
return import_class(f"langchain.utilities.{utility}")
|
return import_class(f"langchain.utilities.{utility}")
|
||||||
|
|
||||||
|
|
||||||
|
def get_function(code):
|
||||||
|
"""Get the function"""
|
||||||
|
function_name = validate.extract_function_name(code)
|
||||||
|
|
||||||
|
return validate.create_function(code, function_name)
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@ from langchain.llms.loading import load_llm_from_config
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
|
|
||||||
from langflow.interface.agents.custom import CUSTOM_AGENTS
|
from langflow.interface.agents.custom import CUSTOM_AGENTS
|
||||||
from langflow.interface.importing.utils import import_by_type
|
from langflow.interface.importing.utils import get_function, import_by_type
|
||||||
from langflow.interface.run import fix_memory_inputs
|
from langflow.interface.run import fix_memory_inputs
|
||||||
from langflow.interface.toolkits.base import toolkits_creator
|
from langflow.interface.toolkits.base import toolkits_creator
|
||||||
from langflow.interface.types import get_type_list
|
from langflow.interface.types import get_type_list
|
||||||
from langflow.interface.utils import load_file_into_dict
|
from langflow.interface.utils import load_file_into_dict
|
||||||
from langflow.utils import util, validate
|
from langflow.utils import util
|
||||||
|
|
||||||
|
|
||||||
def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any:
|
def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any:
|
||||||
|
|
@ -100,11 +100,9 @@ def instantiate_tool(node_type, class_object, params):
|
||||||
if node_type == "JsonSpec":
|
if node_type == "JsonSpec":
|
||||||
params["dict_"] = load_file_into_dict(params.pop("path"))
|
params["dict_"] = load_file_into_dict(params.pop("path"))
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
elif node_type == "PythonFunction":
|
elif node_type == "PythonFunctionTool":
|
||||||
function_string = params["code"]
|
params["func"] = get_function(params.get("code"))
|
||||||
if isinstance(function_string, str):
|
return class_object(**params)
|
||||||
return validate.eval_function(function_string)
|
|
||||||
raise ValueError("Function should be a string")
|
|
||||||
elif node_type.lower() == "tool":
|
elif node_type.lower() == "tool":
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ class ToolCreator(LangChainTypeCreator):
|
||||||
|
|
||||||
for tool, tool_fcn in ALL_TOOLS_NAMES.items():
|
for tool, tool_fcn in ALL_TOOLS_NAMES.items():
|
||||||
tool_params = get_tool_params(tool_fcn)
|
tool_params = get_tool_params(tool_fcn)
|
||||||
tool_name = tool_params.get("name", tool)
|
|
||||||
|
tool_name = tool_params.get("name") or tool
|
||||||
|
|
||||||
if tool_name in settings.tools or settings.dev:
|
if tool_name in settings.tools or settings.dev:
|
||||||
if tool_name == "JsonSpec":
|
if tool_name == "JsonSpec":
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ from langchain.agents.load_tools import (
|
||||||
from langchain.tools.json.tool import JsonSpec
|
from langchain.tools.json.tool import JsonSpec
|
||||||
|
|
||||||
from langflow.interface.importing.utils import import_class
|
from langflow.interface.importing.utils import import_class
|
||||||
from langflow.interface.tools.custom import PythonFunction
|
from langflow.interface.tools.custom import PythonFunctionTool
|
||||||
|
|
||||||
FILE_TOOLS = {"JsonSpec": JsonSpec}
|
FILE_TOOLS = {"JsonSpec": JsonSpec}
|
||||||
CUSTOM_TOOLS = {"Tool": Tool, "PythonFunction": PythonFunction}
|
CUSTOM_TOOLS = {"Tool": Tool, "PythonFunctionTool": PythonFunctionTool}
|
||||||
|
|
||||||
OTHER_TOOLS = {tool: import_class(f"langchain.tools.{tool}") for tool in tools.__all__}
|
OTHER_TOOLS = {tool: import_class(f"langchain.tools.{tool}") for tool in tools.__all__}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
from typing import Callable, Optional
|
from typing import Optional
|
||||||
|
from langflow.interface.importing.utils import get_function
|
||||||
|
|
||||||
from pydantic import BaseModel, validator
|
from pydantic import BaseModel, validator
|
||||||
|
|
||||||
from langflow.utils import validate
|
from langflow.utils import validate
|
||||||
|
from langchain.agents.tools import Tool
|
||||||
|
|
||||||
|
|
||||||
class Function(BaseModel):
|
class Function(BaseModel):
|
||||||
code: str
|
code: str
|
||||||
function: Optional[Callable] = None
|
|
||||||
imports: Optional[str] = None
|
imports: Optional[str] = None
|
||||||
|
|
||||||
# Eval code and store the function
|
# Eval code and store the function
|
||||||
|
|
@ -24,14 +25,17 @@ class Function(BaseModel):
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def get_function(self):
|
|
||||||
"""Get the function"""
|
|
||||||
function_name = validate.extract_function_name(self.code)
|
|
||||||
|
|
||||||
return validate.create_function(self.code, function_name)
|
class PythonFunctionTool(Function, Tool):
|
||||||
|
|
||||||
|
|
||||||
class PythonFunction(Function):
|
|
||||||
"""Python function"""
|
"""Python function"""
|
||||||
|
|
||||||
|
name: str = "Custom Tool"
|
||||||
|
description: str
|
||||||
code: str
|
code: str
|
||||||
|
|
||||||
|
def ___init__(self, name: str, description: str, code: str):
|
||||||
|
self.name = name
|
||||||
|
self.description = description
|
||||||
|
self.code = code
|
||||||
|
self.func = get_function(self.code)
|
||||||
|
super().__init__(name=name, description=description, func=self.func)
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,9 @@ class FrontendNode(BaseModel):
|
||||||
elif name == "ChatOpenAI" and key == "model_name":
|
elif name == "ChatOpenAI" and key == "model_name":
|
||||||
field.options = constants.CHAT_OPENAI_MODELS
|
field.options = constants.CHAT_OPENAI_MODELS
|
||||||
field.is_list = True
|
field.is_list = True
|
||||||
|
elif (name == "Anthropic" or name == "ChatAnthropic") and key == "model_name":
|
||||||
|
field.options = constants.ANTHROPIC_MODELS
|
||||||
|
field.is_list = True
|
||||||
if "api_key" in key and "OpenAI" in str(name):
|
if "api_key" in key and "OpenAI" in str(name):
|
||||||
field.display_name = "OpenAI API Key"
|
field.display_name = "OpenAI API Key"
|
||||||
field.required = False
|
field.required = False
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,33 @@ class ToolNode(FrontendNode):
|
||||||
return super().to_dict()
|
return super().to_dict()
|
||||||
|
|
||||||
|
|
||||||
class PythonFunctionNode(FrontendNode):
|
class PythonFunctionToolNode(FrontendNode):
|
||||||
name: str = "PythonFunction"
|
name: str = "PythonFunctionTool"
|
||||||
template: Template = Template(
|
template: Template = Template(
|
||||||
type_name="python_function",
|
type_name="PythonFunctionTool",
|
||||||
fields=[
|
fields=[
|
||||||
|
TemplateField(
|
||||||
|
field_type="str",
|
||||||
|
required=True,
|
||||||
|
placeholder="",
|
||||||
|
is_list=False,
|
||||||
|
show=True,
|
||||||
|
multiline=False,
|
||||||
|
value="",
|
||||||
|
name="name",
|
||||||
|
advanced=False,
|
||||||
|
),
|
||||||
|
TemplateField(
|
||||||
|
field_type="str",
|
||||||
|
required=True,
|
||||||
|
placeholder="",
|
||||||
|
is_list=False,
|
||||||
|
show=True,
|
||||||
|
multiline=False,
|
||||||
|
value="",
|
||||||
|
name="description",
|
||||||
|
advanced=False,
|
||||||
|
),
|
||||||
TemplateField(
|
TemplateField(
|
||||||
field_type="code",
|
field_type="code",
|
||||||
required=True,
|
required=True,
|
||||||
|
|
@ -73,11 +95,11 @@ class PythonFunctionNode(FrontendNode):
|
||||||
value=DEFAULT_PYTHON_FUNCTION,
|
value=DEFAULT_PYTHON_FUNCTION,
|
||||||
name="code",
|
name="code",
|
||||||
advanced=False,
|
advanced=False,
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
description: str = "Python function to be executed."
|
description: str = "Python function to be executed."
|
||||||
base_classes: list[str] = ["function"]
|
base_classes: list[str] = ["Tool"]
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return super().to_dict()
|
return super().to_dict()
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,20 @@ OPENAI_MODELS = [
|
||||||
]
|
]
|
||||||
CHAT_OPENAI_MODELS = ["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]
|
CHAT_OPENAI_MODELS = ["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]
|
||||||
|
|
||||||
|
ANTHROPIC_MODELS = [
|
||||||
|
"claude-v1", # largest model, ideal for a wide range of more complex tasks.
|
||||||
|
"claude-v1-100k", # An enhanced version of claude-v1 with a 100,000 token (roughly 75,000 word) context window.
|
||||||
|
"claude-instant-v1", # A smaller model with far lower latency, sampling at roughly 40 words/sec!
|
||||||
|
"claude-instant-v1-100k", # Like claude-instant-v1 with a 100,000 token context window but retains its performance.
|
||||||
|
# Specific sub-versions of the above models:
|
||||||
|
"claude-v1.3", # Vs claude-v1.2: better instruction-following, code, and non-English dialogue and writing.
|
||||||
|
"claude-v1.3-100k", # An enhanced version of claude-v1.3 with a 100,000 token (roughly 75,000 word) context window.
|
||||||
|
"claude-v1.2", # Vs claude-v1.1: small adv in general helpfulness, instruction following, coding, and other tasks.
|
||||||
|
"claude-v1.0", # An earlier version of claude-v1.
|
||||||
|
"claude-instant-v1.1", # Latest version of claude-instant-v1. Better than claude-instant-v1.0 at most tasks.
|
||||||
|
"claude-instant-v1.1-100k", # Version of claude-instant-v1.1 with a 100K token context window.
|
||||||
|
"claude-instant-v1.0", # An earlier version of claude-instant-v1.
|
||||||
|
]
|
||||||
|
|
||||||
DEFAULT_PYTHON_FUNCTION = """
|
DEFAULT_PYTHON_FUNCTION = """
|
||||||
def python_function(text: str) -> str:
|
def python_function(text: str) -> str:
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,9 @@ def format_dict(d, name: Optional[str] = None):
|
||||||
elif name == "ChatOpenAI" and key == "model_name":
|
elif name == "ChatOpenAI" and key == "model_name":
|
||||||
value["options"] = constants.CHAT_OPENAI_MODELS
|
value["options"] = constants.CHAT_OPENAI_MODELS
|
||||||
value["list"] = True
|
value["list"] = True
|
||||||
|
elif (name == "Anthropic" or name == "ChatAnthropic") and key == "model_name":
|
||||||
|
value["options"] = constants.ANTHROPIC_MODELS
|
||||||
|
value["list"] = True
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
9
src/frontend/src/icons/Anthropic/anthropic.svg
Normal file
9
src/frontend/src/icons/Anthropic/anthropic.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="-170.333 113.047 600 67.4" width="600" height="67.4">
|
||||||
|
<defs>
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#1F1F1E;}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<path class="st0" d="M -23.533 126.747 L -1.633 126.747 L -1.633 179.347 L 12.367 179.347 L 12.367 126.747 L 34.267 126.747 L 34.267 114.147 L -23.533 114.147 L -23.533 126.747 Z M -48.133 159.747 L -77.433 114.147 L -93.233 114.147 L -93.233 179.247 L -79.733 179.247 L -79.733 133.647 L -50.433 179.347 L -34.633 179.347 L -34.633 114.247 L -48.133 114.247 L -48.133 159.747 Z M 90.067 140.147 L 59.367 140.147 L 59.367 114.147 L 45.367 114.147 L 45.367 179.247 L 59.367 179.247 L 59.367 152.647 L 90.067 152.647 L 90.067 179.247 L 104.067 179.247 L 104.067 114.147 L 90.067 114.147 L 90.067 140.147 Z M -144.333 114.147 L -170.333 179.247 L -155.833 179.247 L -150.533 165.547 L -123.333 165.547 L -118.033 179.247 L -103.533 179.247 L -129.533 114.147 L -144.333 114.147 Z M -145.833 153.547 L -136.933 130.647 L -128.033 153.547 L -145.833 153.547 Z M 219.667 113.047 C 200.867 113.047 187.567 127.047 187.567 146.847 C 187.567 166.447 200.867 180.447 219.667 180.447 C 238.367 180.447 251.567 166.447 251.567 146.847 C 251.567 127.047 238.367 113.047 219.667 113.047 Z M 219.667 167.447 C 208.667 167.447 201.967 159.647 201.967 146.847 C 201.967 133.947 208.667 126.047 219.667 126.047 C 230.567 126.047 237.167 133.847 237.167 146.847 C 237.167 159.547 230.567 167.447 219.667 167.447 Z M 414.767 157.447 C 412.367 163.747 407.467 167.447 400.867 167.447 C 389.867 167.447 383.167 159.647 383.167 146.847 C 383.167 133.947 389.867 126.047 400.867 126.047 C 407.467 126.047 412.267 129.647 414.767 136.047 L 429.567 136.047 C 425.967 122.047 415.067 113.047 400.867 113.047 C 382.067 113.047 368.767 127.047 368.767 146.847 C 368.767 166.447 382.067 180.447 400.867 180.447 C 415.067 180.447 425.967 171.347 429.667 157.447 L 414.767 157.447 Z M 325.867 114.147 L 351.867 179.247 L 366.067 179.247 L 340.067 114.147 L 325.867 114.147 Z M 296.367 114.147 L 264.567 114.147 L 264.567 179.247 L 278.567 179.247 L 278.567 155.647 L 296.467 155.647 C 311.267 155.647 320.267 147.847 320.267 134.847 C 320.267 121.947 311.167 114.147 296.367 114.147 Z M 295.767 143.147 L 278.567 143.147 L 278.567 126.747 L 295.767 126.747 C 302.667 126.747 306.267 129.547 306.267 134.947 C 306.267 140.347 302.667 143.147 295.767 143.147 Z M 176.867 134.047 C 176.867 121.747 167.867 114.247 153.067 114.247 L 121.267 114.247 L 121.267 179.347 L 135.267 179.347 L 135.267 153.847 L 150.767 153.847 L 164.767 179.347 L 180.167 179.347 L 164.667 151.947 C 172.367 148.847 176.867 142.647 176.867 134.047 Z M 135.167 126.747 L 152.367 126.747 C 159.267 126.747 162.867 129.247 162.867 134.047 C 162.867 138.747 159.267 141.347 152.367 141.347 L 135.167 141.347 L 135.167 126.747 Z"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.9 KiB |
11
src/frontend/src/icons/Anthropic/anthropic_box.svg
Normal file
11
src/frontend/src/icons/Anthropic/anthropic_box.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="-126.9 247.9 207.161 212.728" width="207.161" height="212.728">
|
||||||
|
<defs>
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#1F1F1E;}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<path class="st0" d="M 19.9 260.5 L 41.8 260.5 L 41.8 313.1 L 55.8 313.1 L 55.8 260.5 L 77.7 260.5 L 77.7 247.9 L 19.9 247.9 L 19.9 260.5 Z M -4.7 293.5 L -34 247.9 L -49.8 247.9 L -49.8 313 L -36.3 313 L -36.3 267.4 L -7 313.1 L 8.8 313.1 L 8.8 248 L -4.7 248 L -4.7 293.5 Z M -100.9 247.9 L -126.9 313 L -112.4 313 L -107.1 299.3 L -79.9 299.3 L -74.6 313 L -60.1 313 L -86.1 247.9 L -100.9 247.9 Z M -102.4 287.3 L -93.5 264.4 L -84.6 287.3 L -102.4 287.3 Z"></path>
|
||||||
|
<path class="st0" d="M 38.246 437.628 C 35.846 443.928 30.946 447.628 24.346 447.628 C 13.346 447.628 6.646 439.828 6.646 427.028 C 6.646 414.128 13.346 406.228 24.346 406.228 C 30.946 406.228 35.746 409.828 38.246 416.228 L 53.046 416.228 C 49.446 402.228 38.546 393.228 24.346 393.228 C 5.546 393.228 -7.754 407.228 -7.754 427.028 C -7.754 446.628 5.546 460.628 24.346 460.628 C 38.546 460.628 49.446 451.528 53.146 437.628 L 38.246 437.628 Z M -50.654 394.328 L -24.654 459.428 L -10.454 459.428 L -36.454 394.328 L -50.654 394.328 Z M -80.154 394.328 L -111.954 394.328 L -111.954 459.428 L -97.954 459.428 L -97.954 435.828 L -80.054 435.828 C -65.254 435.828 -56.254 428.028 -56.254 415.028 C -56.254 402.128 -65.354 394.328 -80.154 394.328 Z M -80.754 423.328 L -97.954 423.328 L -97.954 406.928 L -80.754 406.928 C -73.854 406.928 -70.254 409.728 -70.254 415.128 C -70.254 420.528 -73.854 423.328 -80.754 423.328 Z"></path>
|
||||||
|
<path class="st0" d="M -81.239 347.704 L -111.939 347.704 L -111.939 321.704 L -125.939 321.704 L -125.939 386.804 L -111.939 386.804 L -111.939 360.204 L -81.239 360.204 L -81.239 386.804 L -67.239 386.804 L -67.239 321.704 L -81.239 321.704 L -81.239 347.704 Z M 48.361 320.604 C 29.561 320.604 16.261 334.604 16.261 354.404 C 16.261 374.004 29.561 388.004 48.361 388.004 C 67.061 388.004 80.261 374.004 80.261 354.404 C 80.261 334.604 67.061 320.604 48.361 320.604 Z M 48.361 375.004 C 37.361 375.004 30.661 367.204 30.661 354.404 C 30.661 341.504 37.361 333.604 48.361 333.604 C 59.261 333.604 65.861 341.404 65.861 354.404 C 65.861 367.104 59.261 375.004 48.361 375.004 Z M 5.561 341.604 C 5.561 329.304 -3.439 321.804 -18.239 321.804 L -50.039 321.804 L -50.039 386.904 L -36.039 386.904 L -36.039 361.404 L -20.539 361.404 L -6.539 386.904 L 8.861 386.904 L -6.639 359.504 C 1.061 356.404 5.561 350.204 5.561 341.604 Z M -36.139 334.304 L -18.939 334.304 C -12.039 334.304 -8.439 336.804 -8.439 341.604 C -8.439 346.304 -12.039 348.904 -18.939 348.904 L -36.139 348.904 L -36.139 334.304 Z"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
9
src/frontend/src/icons/Anthropic/index.tsx
Normal file
9
src/frontend/src/icons/Anthropic/index.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import React, { forwardRef } from "react";
|
||||||
|
import { ReactComponent as AnthropicSVG } from "./anthropic_box.svg";
|
||||||
|
|
||||||
|
export const AnthropicIcon = forwardRef<
|
||||||
|
SVGSVGElement,
|
||||||
|
React.PropsWithChildren<{}>
|
||||||
|
>((props, ref) => {
|
||||||
|
return <AnthropicSVG ref={ref} {...props} />;
|
||||||
|
});
|
||||||
|
|
@ -5,6 +5,7 @@ import { DisclosureComponentType } from "../../../../types/components";
|
||||||
export default function DisclosureComponent({
|
export default function DisclosureComponent({
|
||||||
button: { title, Icon, buttons = [] },
|
button: { title, Icon, buttons = [] },
|
||||||
children,
|
children,
|
||||||
|
openDisc,
|
||||||
}: DisclosureComponentType) {
|
}: DisclosureComponentType) {
|
||||||
return (
|
return (
|
||||||
<Disclosure as="div" key={title}>
|
<Disclosure as="div" key={title}>
|
||||||
|
|
@ -27,14 +28,14 @@ export default function DisclosureComponent({
|
||||||
<div>
|
<div>
|
||||||
<ChevronRightIcon
|
<ChevronRightIcon
|
||||||
className={`${
|
className={`${
|
||||||
open ? "rotate-90 transform" : ""
|
open || openDisc ? "rotate-90 transform" : ""
|
||||||
} h-4 w-4 text-gray-800 dark:text-white`}
|
} h-4 w-4 text-gray-800 dark:text-white`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Disclosure.Button>
|
</Disclosure.Button>
|
||||||
</div>
|
</div>
|
||||||
<Disclosure.Panel as="div" className="-mt-px">
|
<Disclosure.Panel as="div" className="-mt-px" static={openDisc}>
|
||||||
{children}
|
{children}
|
||||||
</Disclosure.Panel>
|
</Disclosure.Panel>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
||||||
export default function ExtraSidebar() {
|
export default function ExtraSidebar() {
|
||||||
const { data } = useContext(typesContext);
|
const { data } = useContext(typesContext);
|
||||||
const [dataFilter, setFilterData] = useState(data);
|
const [dataFilter, setFilterData] = useState(data);
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
|
||||||
function onDragStart(
|
function onDragStart(
|
||||||
event: React.DragEvent<any>,
|
event: React.DragEvent<any>,
|
||||||
|
|
@ -58,6 +59,7 @@ export default function ExtraSidebar() {
|
||||||
className="dark:text-white focus:outline-none block w-full rounded-md py-1.5 ps-3 pr-9 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 sm:text-sm sm:leading-6 dark:ring-0 dark:bg-[#2d3747] dark:focus:outline-none"
|
className="dark:text-white focus:outline-none block w-full rounded-md py-1.5 ps-3 pr-9 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 sm:text-sm sm:leading-6 dark:ring-0 dark:bg-[#2d3747] dark:focus:outline-none"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
handleSearchInput(e.target.value);
|
handleSearchInput(e.target.value);
|
||||||
|
setSearch(e.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="absolute inset-y-0 right-0 flex py-1.5 pr-3 items-center">
|
<div className="absolute inset-y-0 right-0 flex py-1.5 pr-3 items-center">
|
||||||
|
|
@ -71,6 +73,7 @@ export default function ExtraSidebar() {
|
||||||
.map((d: keyof APIObjectType, i) =>
|
.map((d: keyof APIObjectType, i) =>
|
||||||
Object.keys(dataFilter[d]).length > 0 ? (
|
Object.keys(dataFilter[d]).length > 0 ? (
|
||||||
<DisclosureComponent
|
<DisclosureComponent
|
||||||
|
openDisc={search.length == 0 ? false : true}
|
||||||
key={i}
|
key={i}
|
||||||
button={{
|
button={{
|
||||||
title: nodeNames[d] ?? nodeNames.unknown,
|
title: nodeNames[d] ?? nodeNames.unknown,
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ export type FileComponentType = {
|
||||||
|
|
||||||
export type DisclosureComponentType = {
|
export type DisclosureComponentType = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
openDisc: boolean;
|
||||||
button: {
|
button: {
|
||||||
title: string;
|
title: string;
|
||||||
Icon: ForwardRefExoticComponent<React.SVGProps<SVGSVGElement>>;
|
Icon: ForwardRefExoticComponent<React.SVGProps<SVGSVGElement>>;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import { FlowType, NodeType } from "./types/flow";
|
||||||
import { APITemplateType, TemplateVariableType } from "./types/api";
|
import { APITemplateType, TemplateVariableType } from "./types/api";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { ChromaIcon } from "./icons/ChromaIcon";
|
import { ChromaIcon } from "./icons/ChromaIcon";
|
||||||
|
import { AnthropicIcon } from "./icons/Anthropic";
|
||||||
import { AirbyteIcon } from "./icons/Airbyte";
|
import { AirbyteIcon } from "./icons/Airbyte";
|
||||||
import { AzIcon } from "./icons/AzLogo";
|
import { AzIcon } from "./icons/AzLogo";
|
||||||
import { BingIcon } from "./icons/Bing";
|
import { BingIcon } from "./icons/Bing";
|
||||||
|
|
@ -155,6 +156,8 @@ export const nodeIcons: {
|
||||||
AirbyteJSONLoader: AirbyteIcon,
|
AirbyteJSONLoader: AirbyteIcon,
|
||||||
// SerpAPIWrapper: SerperIcon,
|
// SerpAPIWrapper: SerperIcon,
|
||||||
// AZLyricsLoader: AzIcon,
|
// AZLyricsLoader: AzIcon,
|
||||||
|
Anthropic: AnthropicIcon,
|
||||||
|
ChatAnthropic: AnthropicIcon,
|
||||||
BingSearchAPIWrapper: BingIcon,
|
BingSearchAPIWrapper: BingIcon,
|
||||||
BingSearchRun: BingIcon,
|
BingSearchRun: BingIcon,
|
||||||
Cohere: CohereIcon,
|
Cohere: CohereIcon,
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@
|
||||||
"y": 136.29836646158452
|
"y": 136.29836646158452
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
"type": "PythonFunction",
|
"type": "PythonFunctionTool",
|
||||||
"node": {
|
"node": {
|
||||||
"template": {
|
"template": {
|
||||||
"code": {
|
"code": {
|
||||||
|
|
@ -210,6 +210,26 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"list": false
|
"list": false
|
||||||
},
|
},
|
||||||
|
"description": {
|
||||||
|
"required": true,
|
||||||
|
"placeholder": "",
|
||||||
|
"show": true,
|
||||||
|
"multiline": true,
|
||||||
|
"value": "My description",
|
||||||
|
"name": "description",
|
||||||
|
"type": "str",
|
||||||
|
"list": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"required": true,
|
||||||
|
"placeholder": "",
|
||||||
|
"show": true,
|
||||||
|
"multiline": true,
|
||||||
|
"value": "My Tool",
|
||||||
|
"name": "name",
|
||||||
|
"type": "str",
|
||||||
|
"list": false
|
||||||
|
},
|
||||||
"_type": "python_function"
|
"_type": "python_function"
|
||||||
},
|
},
|
||||||
"description": "Python function to be executed.",
|
"description": "Python function to be executed.",
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,23 @@
|
||||||
# Test this:
|
# Test this:
|
||||||
|
from langflow.interface.importing.utils import get_function
|
||||||
import pytest
|
import pytest
|
||||||
from langflow.interface.tools.custom import PythonFunction
|
from langflow.interface.tools.custom import PythonFunctionTool
|
||||||
from langflow.utils import constants
|
from langflow.utils import constants
|
||||||
|
|
||||||
|
|
||||||
def test_python_function():
|
def test_python_function():
|
||||||
"""Test Python function"""
|
"""Test Python function"""
|
||||||
func = PythonFunction(code=constants.DEFAULT_PYTHON_FUNCTION)
|
code = constants.DEFAULT_PYTHON_FUNCTION
|
||||||
assert func.get_function()("text") == "text"
|
func = get_function(code)
|
||||||
|
func = PythonFunctionTool(name="Test", description="Testing", code=code, func=func)
|
||||||
|
assert func("text") == "text"
|
||||||
# the tool decorator should raise an error if
|
# the tool decorator should raise an error if
|
||||||
# the function is not str -> str
|
# the function is not str -> str
|
||||||
|
|
||||||
# This raises ValidationError
|
# This raises ValidationError
|
||||||
with pytest.raises(SyntaxError):
|
with pytest.raises(SyntaxError):
|
||||||
func = PythonFunction(code=pytest.CODE_WITH_SYNTAX_ERROR)
|
code = pytest.CODE_WITH_SYNTAX_ERROR
|
||||||
|
func = get_function(code)
|
||||||
|
func = PythonFunctionTool(
|
||||||
|
name="Test", description="Testing", code=code, func=func
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
from typing import Type, Union
|
from typing import Type, Union
|
||||||
from langflow.graph.edge.base import Edge
|
from langflow.graph.edge.base import Edge
|
||||||
from langflow.graph.node.base import Node
|
from langflow.graph.vertex.base import Vertex
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from langchain.chains.base import Chain
|
from langchain.chains.base import Chain
|
||||||
from langchain.llms.fake import FakeListLLM
|
from langchain.llms.fake import FakeListLLM
|
||||||
from langflow.graph import Graph
|
from langflow.graph import Graph
|
||||||
from langflow.graph.node.types import (
|
from langflow.graph.vertex.types import (
|
||||||
AgentNode,
|
AgentVertex,
|
||||||
ChainNode,
|
ChainVertex,
|
||||||
FileToolNode,
|
FileToolVertex,
|
||||||
LLMNode,
|
LLMVertex,
|
||||||
PromptNode,
|
PromptVertex,
|
||||||
ToolkitNode,
|
ToolkitVertex,
|
||||||
ToolNode,
|
ToolVertex,
|
||||||
WrapperNode,
|
WrapperVertex,
|
||||||
)
|
)
|
||||||
from langflow.interface.run import get_result_and_thought
|
from langflow.interface.run import get_result_and_thought
|
||||||
from langflow.utils.payload import get_root_node
|
from langflow.utils.payload import get_root_node
|
||||||
|
|
@ -25,7 +25,7 @@ from langflow.utils.payload import get_root_node
|
||||||
# BASIC_EXAMPLE_PATH, COMPLEX_EXAMPLE_PATH, OPENAPI_EXAMPLE_PATH
|
# BASIC_EXAMPLE_PATH, COMPLEX_EXAMPLE_PATH, OPENAPI_EXAMPLE_PATH
|
||||||
|
|
||||||
|
|
||||||
def get_node_by_type(graph, node_type: Type[Node]) -> Union[Node, None]:
|
def get_node_by_type(graph, node_type: Type[Vertex]) -> Union[Vertex, None]:
|
||||||
"""Get a node by type"""
|
"""Get a node by type"""
|
||||||
return next((node for node in graph.nodes if isinstance(node, node_type)), None)
|
return next((node for node in graph.nodes if isinstance(node, node_type)), None)
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ def test_graph_structure(basic_graph):
|
||||||
assert len(basic_graph.nodes) > 0
|
assert len(basic_graph.nodes) > 0
|
||||||
assert len(basic_graph.edges) > 0
|
assert len(basic_graph.edges) > 0
|
||||||
for node in basic_graph.nodes:
|
for node in basic_graph.nodes:
|
||||||
assert isinstance(node, Node)
|
assert isinstance(node, Vertex)
|
||||||
for edge in basic_graph.edges:
|
for edge in basic_graph.edges:
|
||||||
assert isinstance(edge, Edge)
|
assert isinstance(edge, Edge)
|
||||||
assert edge.source in basic_graph.nodes
|
assert edge.source in basic_graph.nodes
|
||||||
|
|
@ -158,14 +158,16 @@ def test_get_node_neighbors_complex(complex_graph):
|
||||||
tool_neighbors = complex_graph.get_nodes_with_target(tool)
|
tool_neighbors = complex_graph.get_nodes_with_target(tool)
|
||||||
assert tool_neighbors is not None
|
assert tool_neighbors is not None
|
||||||
# Check if there is a PythonFunction in the tool's neighbors
|
# Check if there is a PythonFunction in the tool's neighbors
|
||||||
assert any("PythonFunction" in neighbor.data["type"] for neighbor in tool_neighbors)
|
assert any(
|
||||||
|
"PythonFunctionTool" in neighbor.data["type"] for neighbor in tool_neighbors
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_get_node(basic_graph):
|
def test_get_node(basic_graph):
|
||||||
"""Test getting a single node"""
|
"""Test getting a single node"""
|
||||||
node_id = basic_graph.nodes[0].id
|
node_id = basic_graph.nodes[0].id
|
||||||
node = basic_graph.get_node(node_id)
|
node = basic_graph.get_node(node_id)
|
||||||
assert isinstance(node, Node)
|
assert isinstance(node, Vertex)
|
||||||
assert node.id == node_id
|
assert node.id == node_id
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -174,7 +176,7 @@ def test_build_nodes(basic_graph):
|
||||||
|
|
||||||
assert len(basic_graph.nodes) == len(basic_graph._nodes)
|
assert len(basic_graph.nodes) == len(basic_graph._nodes)
|
||||||
for node in basic_graph.nodes:
|
for node in basic_graph.nodes:
|
||||||
assert isinstance(node, Node)
|
assert isinstance(node, Vertex)
|
||||||
|
|
||||||
|
|
||||||
def test_build_edges(basic_graph):
|
def test_build_edges(basic_graph):
|
||||||
|
|
@ -182,8 +184,8 @@ def test_build_edges(basic_graph):
|
||||||
assert len(basic_graph.edges) == len(basic_graph._edges)
|
assert len(basic_graph.edges) == len(basic_graph._edges)
|
||||||
for edge in basic_graph.edges:
|
for edge in basic_graph.edges:
|
||||||
assert isinstance(edge, Edge)
|
assert isinstance(edge, Edge)
|
||||||
assert isinstance(edge.source, Node)
|
assert isinstance(edge.source, Vertex)
|
||||||
assert isinstance(edge.target, Node)
|
assert isinstance(edge.target, Vertex)
|
||||||
|
|
||||||
|
|
||||||
def test_get_root_node(basic_graph, complex_graph):
|
def test_get_root_node(basic_graph, complex_graph):
|
||||||
|
|
@ -191,13 +193,13 @@ def test_get_root_node(basic_graph, complex_graph):
|
||||||
assert isinstance(basic_graph, Graph)
|
assert isinstance(basic_graph, Graph)
|
||||||
root = get_root_node(basic_graph)
|
root = get_root_node(basic_graph)
|
||||||
assert root is not None
|
assert root is not None
|
||||||
assert isinstance(root, Node)
|
assert isinstance(root, Vertex)
|
||||||
assert root.data["type"] == "TimeTravelGuideChain"
|
assert root.data["type"] == "TimeTravelGuideChain"
|
||||||
# For complex example, the root node is a ZeroShotAgent too
|
# For complex example, the root node is a ZeroShotAgent too
|
||||||
assert isinstance(complex_graph, Graph)
|
assert isinstance(complex_graph, Graph)
|
||||||
root = get_root_node(complex_graph)
|
root = get_root_node(complex_graph)
|
||||||
assert root is not None
|
assert root is not None
|
||||||
assert isinstance(root, Node)
|
assert isinstance(root, Vertex)
|
||||||
assert root.data["type"] == "ZeroShotAgent"
|
assert root.data["type"] == "ZeroShotAgent"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -257,14 +259,14 @@ def assert_agent_was_built(graph):
|
||||||
|
|
||||||
|
|
||||||
def test_agent_node_build(complex_graph):
|
def test_agent_node_build(complex_graph):
|
||||||
agent_node = get_node_by_type(complex_graph, AgentNode)
|
agent_node = get_node_by_type(complex_graph, AgentVertex)
|
||||||
assert agent_node is not None
|
assert agent_node is not None
|
||||||
built_object = agent_node.build()
|
built_object = agent_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
||||||
|
|
||||||
def test_tool_node_build(complex_graph):
|
def test_tool_node_build(complex_graph):
|
||||||
tool_node = get_node_by_type(complex_graph, ToolNode)
|
tool_node = get_node_by_type(complex_graph, ToolVertex)
|
||||||
assert tool_node is not None
|
assert tool_node is not None
|
||||||
built_object = tool_node.build()
|
built_object = tool_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
@ -272,7 +274,7 @@ def test_tool_node_build(complex_graph):
|
||||||
|
|
||||||
|
|
||||||
def test_chain_node_build(complex_graph):
|
def test_chain_node_build(complex_graph):
|
||||||
chain_node = get_node_by_type(complex_graph, ChainNode)
|
chain_node = get_node_by_type(complex_graph, ChainVertex)
|
||||||
assert chain_node is not None
|
assert chain_node is not None
|
||||||
built_object = chain_node.build()
|
built_object = chain_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
@ -280,7 +282,7 @@ def test_chain_node_build(complex_graph):
|
||||||
|
|
||||||
|
|
||||||
def test_prompt_node_build(complex_graph):
|
def test_prompt_node_build(complex_graph):
|
||||||
prompt_node = get_node_by_type(complex_graph, PromptNode)
|
prompt_node = get_node_by_type(complex_graph, PromptVertex)
|
||||||
assert prompt_node is not None
|
assert prompt_node is not None
|
||||||
built_object = prompt_node.build()
|
built_object = prompt_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
@ -288,7 +290,7 @@ def test_prompt_node_build(complex_graph):
|
||||||
|
|
||||||
|
|
||||||
def test_llm_node_build(basic_graph):
|
def test_llm_node_build(basic_graph):
|
||||||
llm_node = get_node_by_type(basic_graph, LLMNode)
|
llm_node = get_node_by_type(basic_graph, LLMVertex)
|
||||||
assert llm_node is not None
|
assert llm_node is not None
|
||||||
built_object = llm_node.build()
|
built_object = llm_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
@ -296,7 +298,7 @@ def test_llm_node_build(basic_graph):
|
||||||
|
|
||||||
|
|
||||||
def test_toolkit_node_build(openapi_graph):
|
def test_toolkit_node_build(openapi_graph):
|
||||||
toolkit_node = get_node_by_type(openapi_graph, ToolkitNode)
|
toolkit_node = get_node_by_type(openapi_graph, ToolkitVertex)
|
||||||
assert toolkit_node is not None
|
assert toolkit_node is not None
|
||||||
built_object = toolkit_node.build()
|
built_object = toolkit_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
@ -304,7 +306,7 @@ def test_toolkit_node_build(openapi_graph):
|
||||||
|
|
||||||
|
|
||||||
def test_file_tool_node_build(openapi_graph):
|
def test_file_tool_node_build(openapi_graph):
|
||||||
file_tool_node = get_node_by_type(openapi_graph, FileToolNode)
|
file_tool_node = get_node_by_type(openapi_graph, FileToolVertex)
|
||||||
assert file_tool_node is not None
|
assert file_tool_node is not None
|
||||||
built_object = file_tool_node.build()
|
built_object = file_tool_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
@ -312,7 +314,7 @@ def test_file_tool_node_build(openapi_graph):
|
||||||
|
|
||||||
|
|
||||||
def test_wrapper_node_build(openapi_graph):
|
def test_wrapper_node_build(openapi_graph):
|
||||||
wrapper_node = get_node_by_type(openapi_graph, WrapperNode)
|
wrapper_node = get_node_by_type(openapi_graph, WrapperVertex)
|
||||||
assert wrapper_node is not None
|
assert wrapper_node is not None
|
||||||
built_object = wrapper_node.build()
|
built_object = wrapper_node.build()
|
||||||
assert built_object is not None
|
assert built_object is not None
|
||||||
|
|
@ -327,7 +329,7 @@ def test_get_result_and_thought(basic_graph):
|
||||||
message = "Hello"
|
message = "Hello"
|
||||||
# Find the node that is an LLMNode and change the
|
# Find the node that is an LLMNode and change the
|
||||||
# _built_object to a FakeListLLM
|
# _built_object to a FakeListLLM
|
||||||
llm_node = get_node_by_type(basic_graph, LLMNode)
|
llm_node = get_node_by_type(basic_graph, LLMVertex)
|
||||||
assert llm_node is not None
|
assert llm_node is not None
|
||||||
llm_node._built_object = FakeListLLM(responses=responses)
|
llm_node._built_object = FakeListLLM(responses=responses)
|
||||||
llm_node._built = True
|
llm_node._built = True
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue