diff --git a/poetry.lock b/poetry.lock index 1f0c75e5c..53fdc1c9c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -178,13 +178,13 @@ files = [ [[package]] name = "anthropic" -version = "0.31.1" +version = "0.31.2" description = "The official Python library for the anthropic API" optional = false python-versions = ">=3.7" files = [ - {file = "anthropic-0.31.1-py3-none-any.whl", hash = "sha256:d18809cbdecee2296f418e30beb2d0a8ecc225c065a1494cb02348af48794ff8"}, - {file = "anthropic-0.31.1.tar.gz", hash = "sha256:d2248dfc15f7fc7823ac0bb9d48e73429e9b1ed8327ac66839d00cdb2f29d3cb"}, + {file = "anthropic-0.31.2-py3-none-any.whl", hash = "sha256:28d176b98c72615bfae30f0a9eee6297cc33bf52535d38156fc2805556e2f09b"}, + {file = "anthropic-0.31.2.tar.gz", hash = "sha256:0134b73df8d1f142fc68675fbadb75e920054e9e3437b99df63f10f0fc6ac26f"}, ] [package.dependencies] @@ -388,6 +388,21 @@ files = [ {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, ] +[[package]] +name = "backports-tarfile" +version = "1.2.0" +description = "Backport of CPython tarfile module" +optional = false +python-versions = ">=3.8" +files = [ + {file = "backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34"}, + {file = "backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["jaraco.test", "pytest (!=8.0.*)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)"] + [[package]] name = "bce-python-sdk" version = "0.9.17" @@ -2726,8 +2741,8 @@ files = [ [package.dependencies] cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""} greenlet = [ - {version = ">=3.0rc3", markers = "platform_python_implementation == \"CPython\" and python_version >= \"3.11\""}, {version = ">=2.0.0", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}, + {version = ">=3.0rc3", markers = "platform_python_implementation == \"CPython\" and python_version >= \"3.11\""}, ] "zope.event" = "*" "zope.interface" = "*" @@ -2886,12 +2901,12 @@ files = [ google-auth = ">=2.14.1,<3.0.dev0" googleapis-common-protos = ">=1.56.2,<2.0.dev0" grpcio = [ - {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] grpcio-status = [ - {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" @@ -4162,6 +4177,24 @@ files = [ {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, ] +[[package]] +name = "jaraco-context" +version = "5.3.0" +description = "Useful decorators and context managers" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jaraco.context-5.3.0-py3-none-any.whl", hash = "sha256:3e16388f7da43d384a1a7cd3452e72e14732ac9fe459678773a3608a812bf266"}, + {file = "jaraco.context-5.3.0.tar.gz", hash = "sha256:c2f67165ce1f9be20f32f650f25d8edfc1646a8aeee48ae06fb35f90763576d2"}, +] + +[package.dependencies] +"backports.tarfile" = {version = "*", markers = "python_version < \"3.12\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["portend", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + [[package]] name = "jedi" version = "0.19.1" @@ -4600,19 +4633,19 @@ tests = ["aiohttp", "duckdb", "pandas (>=1.4)", "polars (>=0.19)", "pytest", "py [[package]] name = "langchain" -version = "0.2.8" +version = "0.2.9" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.2.8-py3-none-any.whl", hash = "sha256:53e7dfe50294a14200f33bec22b4e14cb63857ccf0a5500b0d18b0fd51285d58"}, - {file = "langchain-0.2.8.tar.gz", hash = "sha256:7fecb309e3558cde4e5cf7e9ffb7c1ab3f07121c40a7ff3b0c27135f8120c296"}, + {file = "langchain-0.2.9-py3-none-any.whl", hash = "sha256:be23fcb29adbd5059944f1fed08fa575f0739d420b1c4127531e0fbf5663fcca"}, + {file = "langchain-0.2.9.tar.gz", hash = "sha256:cc326a7f6347787a19882928c324433b1a79df629bba45604b2d26495ee5d69c"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -langchain-core = ">=0.2.19,<0.3.0" +langchain-core = ">=0.2.20,<0.3.0" langchain-text-splitters = ">=0.2.0,<0.3.0" langsmith = ">=0.1.17,<0.2.0" numpy = [ @@ -4795,6 +4828,39 @@ langchain = ">=0.0.335" protobuf = ">=4.25.0" pytz = ">=2023.3.post1" +[[package]] +name = "langchain-google-community" +version = "1.0.6" +description = "An integration package connecting miscellaneous Google's products and LangChain" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_google_community-1.0.6-py3-none-any.whl", hash = "sha256:5c2f18aebfb60b51f68dc1608d09ac3e8231743d75c545f409230f7bee641faf"}, + {file = "langchain_google_community-1.0.6.tar.gz", hash = "sha256:081ed78702426a62187c86984c169508c432fc13cd2b08dbf5b553b40bb160b3"}, +] + +[package.dependencies] +google-api-core = ">=2.17.1,<3.0.0" +google-api-python-client = ">=2.122.0,<3.0.0" +grpcio = ">=1.62.0,<2.0.0" +langchain-community = ">=0.2.1,<0.3.0" +langchain-core = ">=0.2.9,<0.3" +tenacity = ">=8.3.0,<8.4.0" + +[package.extras] +bigquery = ["google-cloud-bigquery (>=3.21.0,<4.0.0)"] +docai = ["gapic-google-longrunning (>=0.11.2,<0.12.0)", "google-cloud-contentwarehouse (>=0.7.7,<0.8.0)", "google-cloud-documentai (>=2.26.0,<3.0.0)", "google-cloud-documentai-toolbox (>=0.13.3a0,<0.14.0)"] +drive = ["google-auth-httplib2 (>=0.2.0,<0.3.0)", "google-auth-oauthlib (>=1.2.0,<2.0.0)"] +featurestore = ["db-dtypes (>=1.2.0,<2.0.0)", "google-cloud-aiplatform (>=1.56.0,<2.0.0)", "google-cloud-bigquery-storage (>=2.6.0,<3)", "pandas (>=1.0.0)", "pandas (>=2.0.0,<3.0)", "pyarrow (>=6.0.1)", "pydantic (>=2.7.4,<3.0.0)"] +gcs = ["google-cloud-storage (>=2.16.0,<3.0.0)"] +gmail = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "google-auth-httplib2 (>=0.2.0,<0.3.0)", "google-auth-oauthlib (>=1.2.0,<2.0.0)"] +places = ["googlemaps (>=4.10.0,<5.0.0)"] +speech = ["google-cloud-speech (>=2.26.0,<3.0.0)"] +texttospeech = ["google-cloud-texttospeech (>=2.16.3,<3.0.0)"] +translate = ["google-cloud-translate (>=3.15.3,<4.0.0)"] +vertexaisearch = ["google-cloud-discoveryengine (>=0.11.13,<0.12.0)"] +vision = ["google-cloud-vision (>=3.7.2,<4.0.0)"] + [[package]] name = "langchain-google-genai" version = "1.0.7" @@ -5100,13 +5166,13 @@ requests = ">=2,<3" [[package]] name = "langwatch" -version = "0.1.9" +version = "0.1.10" description = "Python SDK for LangWatch for monitoring your LLMs" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "langwatch-0.1.9-py3-none-any.whl", hash = "sha256:d082f70bb7f6aa67623281e3e624065932bc6e5729322637d8957cc63942a007"}, - {file = "langwatch-0.1.9.tar.gz", hash = "sha256:3f044b668239b0e4cc244635f8ceeb7e10948c736f6b60bcda7c26852308b2f8"}, + {file = "langwatch-0.1.10-py3-none-any.whl", hash = "sha256:271902080b6e0e5ee5aca7e244995b7737bbc54ead956bc16da50445c53d4dce"}, + {file = "langwatch-0.1.10.tar.gz", hash = "sha256:4350aefbbe4ba5ff5f614f10bbf73ca36ccab4f010f66fd66fc826a1a14ade4b"}, ] [package.dependencies] @@ -5199,8 +5265,8 @@ psutil = ">=5.9.1" pywin32 = {version = "*", markers = "platform_system == \"Windows\""} pyzmq = ">=25.0.0" requests = [ - {version = ">=2.32.2", markers = "python_version > \"3.11\""}, {version = ">=2.26.0", markers = "python_version <= \"3.11\""}, + {version = ">=2.32.2", markers = "python_version > \"3.11\""}, ] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.11\""} @@ -5752,6 +5818,17 @@ files = [ {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, ] +[[package]] +name = "more-itertools" +version = "10.3.0" +description = "More routines for operating on iterables, beyond itertools" +optional = false +python-versions = ">=3.8" +files = [ + {file = "more-itertools-10.3.0.tar.gz", hash = "sha256:e5d93ef411224fbcef366a6e8ddc4c5781bc6359d43412a65dd5964e46111463"}, + {file = "more_itertools-10.3.0-py3-none-any.whl", hash = "sha256:ea6a02e24a9161e51faad17a8782b92a0df82c12c1c8886fec7f0c3fa1a1b320"}, +] + [[package]] name = "mpmath" version = "1.3.0" @@ -6790,9 +6867,9 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.22.4", markers = "python_version < \"3.11\""}, {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -9883,18 +9960,18 @@ test = ["pylint", "pytest", "pytest-black", "pytest-cov", "pytest-pylint"] [[package]] name = "structlog" -version = "24.3.0" +version = "24.4.0" description = "Structured Logging for Python" optional = false python-versions = ">=3.8" files = [ - {file = "structlog-24.3.0-py3-none-any.whl", hash = "sha256:ee4c2c7ef7971201f89f85893a4470ecd03bbd97bb54d75581225fdb894689a4"}, - {file = "structlog-24.3.0.tar.gz", hash = "sha256:bcf6b890cf8b48c35fa127ea79c155c79b9e6a4a826f4ce9dfc3bebd72f07fa8"}, + {file = "structlog-24.4.0-py3-none-any.whl", hash = "sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610"}, + {file = "structlog-24.4.0.tar.gz", hash = "sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4"}, ] [package.extras] dev = ["freezegun (>=0.2.8)", "mypy (>=1.4)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "rich", "simplejson", "twisted"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "sphinxext-opengraph", "twisted"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "sphinxext-opengraph", "twisted"] tests = ["freezegun (>=0.2.8)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "simplejson"] typing = ["mypy (>=1.4)", "rich", "twisted"] @@ -9977,13 +10054,13 @@ files = [ [[package]] name = "tenacity" -version = "8.5.0" +version = "8.3.0" description = "Retry code until it succeeds" optional = false python-versions = ">=3.8" files = [ - {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, - {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, + {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, + {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, ] [package.extras] @@ -11383,6 +11460,28 @@ files = [ [package.extras] dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] +[[package]] +name = "wolframalpha" +version = "5.1.3" +description = "Wolfram|Alpha 2.0 API client" +optional = false +python-versions = ">=3.8" +files = [ + {file = "wolframalpha-5.1.3-py3-none-any.whl", hash = "sha256:549b44e64595c5845be4c94f2b306a84832157bef422b20937cbca44b48ee117"}, + {file = "wolframalpha-5.1.3.tar.gz", hash = "sha256:56226efeca0f55acec5e17dd2f6537a178d0bf4feec4df0615165e2968bb49b8"}, +] + +[package.dependencies] +httpx = "*" +"jaraco.context" = "*" +more-itertools = "*" +multidict = "*" +xmltodict = "*" + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["keyring", "pmxbot", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + [[package]] name = "wrapt" version = "1.16.0" @@ -11487,6 +11586,17 @@ files = [ {file = "XlsxWriter-3.2.0.tar.gz", hash = "sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c"}, ] +[[package]] +name = "xmltodict" +version = "0.13.0" +description = "Makes working with XML feel like you are working with JSON" +optional = false +python-versions = ">=3.4" +files = [ + {file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"}, + {file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"}, +] + [[package]] name = "xxhash" version = "3.4.1" @@ -11859,4 +11969,4 @@ local = ["ctransformers", "llama-cpp-python", "sentence-transformers"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "180a20c1cc6b75974734c6d7f2e623c48528669622e1acb3ff22fee39eb6f24a" +content-hash = "56dbd5894cb81a0c9b0ae7bae0f2664b276a25b3f936ac33e44367ecbfdc8b73" diff --git a/pyproject.toml b/pyproject.toml index 7df516955..2c2876ad4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,8 @@ crewai = {extras = ["tools"], version = "^0.36.0"} langwatch = "^0.1.9" langsmith = "^0.1.86" yfinance = "^0.2.40" +langchain-google-community = "^1.0.6" +wolframalpha = "^5.1.3" [tool.poetry.group.dev.dependencies] diff --git a/src/backend/base/langflow/base/agents/agent.py b/src/backend/base/langflow/base/agents/agent.py index 5475e77e8..e4e9a47bf 100644 --- a/src/backend/base/langflow/base/agents/agent.py +++ b/src/backend/base/langflow/base/agents/agent.py @@ -71,7 +71,7 @@ class LCToolsAgentComponent(LCAgentComponent): HandleInput( name="tools", display_name="Tools", - input_types=["Tool"], + input_types=["Tool", "BaseTool"], is_list=True, ), HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), diff --git a/src/backend/base/langflow/base/langchain_utilities/__init__.py b/src/backend/base/langflow/base/langchain_utilities/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/base/langchain_utilities/model.py b/src/backend/base/langflow/base/langchain_utilities/model.py new file mode 100644 index 000000000..9a32c3c68 --- /dev/null +++ b/src/backend/base/langflow/base/langchain_utilities/model.py @@ -0,0 +1,39 @@ +from abc import abstractmethod +from typing import Union + + +from langflow.custom import Component +from langflow.io import Output +from langflow.schema import Data +from langchain_core.tools import BaseTool + + +class LCToolComponent(Component): + trace_type = "tool" + outputs = [ + Output(name="api_run_model", display_name="Data", method="run_model"), + Output(name="api_build_tool", display_name="Tool", method="build_tool"), + ] + + def _validate_outputs(self): + required_output_methods = ["run_model", "build_tool"] + output_names = [output.name for output in self.outputs] + for method_name in required_output_methods: + if method_name not in output_names: + raise ValueError(f"Output with name '{method_name}' must be defined.") + elif not hasattr(self, method_name): + raise ValueError(f"Method '{method_name}' must be defined.") + + @abstractmethod + def run_model(self) -> Union[Data, list[Data]]: + """ + Run model and return the output. + """ + pass + + @abstractmethod + def build_tool(self) -> BaseTool: + """ + Build the tool. + """ + pass diff --git a/src/backend/base/langflow/components/langchain_utilities/BingSearchAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/BingSearchAPIWrapper.py deleted file mode 100644 index 04520dd33..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/BingSearchAPIWrapper.py +++ /dev/null @@ -1,32 +0,0 @@ -# Assuming `BingSearchAPIWrapper` is a class that exists in the context -# and has the appropriate methods and attributes. -# We need to make sure this class is importable from the context where this code will be running. -from langchain_community.utilities.bing_search import BingSearchAPIWrapper - -from langflow.custom import CustomComponent - - -class BingSearchAPIWrapperComponent(CustomComponent): - display_name = "BingSearchAPIWrapper" - description = "Wrapper for Bing Search API." - name = "BingSearchAPIWrapper" - - def build_config(self): - return { - "bing_search_url": {"display_name": "Bing Search URL"}, - "bing_subscription_key": { - "display_name": "Bing Subscription Key", - "password": True, - }, - "k": {"display_name": "Number of results", "advanced": True}, - # 'k' is not included as it is not shown (show=False) - } - - def build( - self, - bing_search_url: str, - bing_subscription_key: str, - k: int = 10, - ) -> BingSearchAPIWrapper: - # 'k' has a default value and is not shown (show=False), so it is hardcoded here - return BingSearchAPIWrapper(bing_search_url=bing_search_url, bing_subscription_key=bing_subscription_key, k=k) diff --git a/src/backend/base/langflow/components/langchain_utilities/GoogleSearchAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/GoogleSearchAPIWrapper.py deleted file mode 100644 index fe804961e..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/GoogleSearchAPIWrapper.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Callable, Union - -from langchain_community.utilities.google_search import GoogleSearchAPIWrapper - -from langflow.custom import CustomComponent - - -class GoogleSearchAPIWrapperComponent(CustomComponent): - display_name = "GoogleSearchAPIWrapper" - description = "Wrapper for Google Search API." - name = "GoogleSearchAPIWrapper" - - def build_config(self): - return { - "google_api_key": {"display_name": "Google API Key", "password": True}, - "google_cse_id": {"display_name": "Google CSE ID", "password": True}, - } - - def build( - self, - google_api_key: str, - google_cse_id: str, - ) -> Union[GoogleSearchAPIWrapper, Callable]: - return GoogleSearchAPIWrapper(google_api_key=google_api_key, google_cse_id=google_cse_id) # type: ignore diff --git a/src/backend/base/langflow/components/langchain_utilities/GoogleSerperAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/GoogleSerperAPIWrapper.py deleted file mode 100644 index 2f5261411..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/GoogleSerperAPIWrapper.py +++ /dev/null @@ -1,51 +0,0 @@ -from typing import Dict - -# Assuming the existence of GoogleSerperAPIWrapper class in the serper module -# If this class does not exist, you would need to create it or import the appropriate class from another module -from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper - -from langflow.custom import CustomComponent - - -class GoogleSerperAPIWrapperComponent(CustomComponent): - display_name = "GoogleSerperAPIWrapper" - description = "Wrapper around the Serper.dev Google Search API." - name = "GoogleSerperAPIWrapper" - - def build_config(self) -> Dict[str, Dict]: - return { - "result_key_for_type": { - "display_name": "Result Key for Type", - "show": True, - "multiline": False, - "password": False, - "advanced": False, - "dynamic": False, - "info": "", - "field_type": "dict", - "list": False, - "value": { - "news": "news", - "places": "places", - "images": "images", - "search": "organic", - }, - }, - "serper_api_key": { - "display_name": "Serper API Key", - "show": True, - "multiline": False, - "password": True, - "advanced": False, - "dynamic": False, - "info": "", - "type": "str", - "list": False, - }, - } - - def build( - self, - serper_api_key: str, - ) -> GoogleSerperAPIWrapper: - return GoogleSerperAPIWrapper(serper_api_key=serper_api_key) diff --git a/src/backend/base/langflow/components/langchain_utilities/SearchApi.py b/src/backend/base/langflow/components/langchain_utilities/SearchApi.py deleted file mode 100644 index 2b6f54de7..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/SearchApi.py +++ /dev/null @@ -1,55 +0,0 @@ -from typing import Optional - -from langchain_community.utilities.searchapi import SearchApiAPIWrapper - -from langflow.custom import CustomComponent -from langflow.schema import Data -from langflow.services.database.models.base import orjson_dumps - - -class SearchApi(CustomComponent): - display_name: str = "SearchApi" - description: str = "Real-time search engine results API." - name = "SearchApi" - - output_types: list[str] = ["Document"] - documentation: str = "https://www.searchapi.io/docs/google" - field_config = { - "engine": { - "display_name": "Engine", - "field_type": "str", - "info": "The search engine to use.", - }, - "params": { - "display_name": "Parameters", - "info": "The parameters to send with the request.", - }, - "code": {"show": False}, - "api_key": { - "display_name": "API Key", - "field_type": "str", - "required": True, - "password": True, - "info": "The API key to use SearchApi.", - }, - } - - def build( - self, - engine: str, - api_key: str, - params: Optional[dict] = None, - ) -> Data: - if params is None: - params = {} - - search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key) - - q = params.pop("q", "SearchApi Langflow") - results = search_api_wrapper.results(q, **params) - - result = orjson_dumps(results, indent_2=False) - - record = Data(data=result) - self.status = record - return record diff --git a/src/backend/base/langflow/components/langchain_utilities/SearxSearchWrapper.py b/src/backend/base/langflow/components/langchain_utilities/SearxSearchWrapper.py deleted file mode 100644 index 90c1f6b55..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/SearxSearchWrapper.py +++ /dev/null @@ -1,36 +0,0 @@ -from typing import Dict, Optional - -from langchain_community.utilities.searx_search import SearxSearchWrapper - -from langflow.custom import CustomComponent - - -class SearxSearchWrapperComponent(CustomComponent): - display_name = "SearxSearchWrapper" - description = "Wrapper for Searx API." - name = "SearxSearchWrapper" - - def build_config(self): - return { - "headers": { - "field_type": "dict", - "display_name": "Headers", - "multiline": True, - "value": '{"Authorization": "Bearer "}', - }, - "k": {"display_name": "k", "advanced": True, "field_type": "int", "value": 10}, - "searx_host": { - "display_name": "Searx Host", - "field_type": "str", - "value": "https://searx.example.com", - "advanced": True, - }, - } - - def build( - self, - k: int = 10, - headers: Optional[Dict[str, str]] = None, - searx_host: str = "https://searx.example.com", - ) -> SearxSearchWrapper: - return SearxSearchWrapper(headers=headers, k=k, searx_host=searx_host) diff --git a/src/backend/base/langflow/components/langchain_utilities/SerpAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/SerpAPIWrapper.py deleted file mode 100644 index 7bd8d911b..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/SerpAPIWrapper.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Callable, Union - -from langchain_community.utilities.serpapi import SerpAPIWrapper - -from langflow.custom import CustomComponent - - -class SerpAPIWrapperComponent(CustomComponent): - display_name = "SerpAPIWrapper" - description = "Wrapper around SerpAPI" - name = "SerpAPIWrapper" - - def build_config(self): - return { - "serpapi_api_key": {"display_name": "SerpAPI API Key", "type": "str", "password": True}, - "params": { - "display_name": "Parameters", - "type": "dict", - "advanced": True, - "multiline": True, - "value": '{"engine": "google","google_domain": "google.com","gl": "us","hl": "en"}', - }, - } - - def build( - self, - serpapi_api_key: str, - params: dict, - ) -> Union[SerpAPIWrapper, Callable]: # Removed quotes around SerpAPIWrapper - return SerpAPIWrapper( # type: ignore - serpapi_api_key=serpapi_api_key, - params=params, - ) diff --git a/src/backend/base/langflow/components/langchain_utilities/WikipediaAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/WikipediaAPIWrapper.py deleted file mode 100644 index ef1485532..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/WikipediaAPIWrapper.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Callable, Union - -from langchain_community.utilities.wikipedia import WikipediaAPIWrapper - -from langflow.custom import CustomComponent - -# Assuming WikipediaAPIWrapper is a class that needs to be imported. -# The import statement is not included as it is not provided in the JSON -# and the actual implementation details are unknown. - - -class WikipediaAPIWrapperComponent(CustomComponent): - display_name = "WikipediaAPIWrapper" - description = "Wrapper around WikipediaAPI." - name = "WikipediaAPIWrapper" - - def build_config(self): - return {} - - def build( - self, - top_k_results: int = 3, - lang: str = "en", - load_all_available_meta: bool = False, - doc_content_chars_max: int = 4000, - ) -> Union[WikipediaAPIWrapper, Callable]: - return WikipediaAPIWrapper( # type: ignore - top_k_results=top_k_results, - lang=lang, - load_all_available_meta=load_all_available_meta, - doc_content_chars_max=doc_content_chars_max, - ) diff --git a/src/backend/base/langflow/components/langchain_utilities/WolframAlphaAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/WolframAlphaAPIWrapper.py deleted file mode 100644 index f8771d0ce..000000000 --- a/src/backend/base/langflow/components/langchain_utilities/WolframAlphaAPIWrapper.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Callable, Union - -from langchain_community.utilities.wolfram_alpha import WolframAlphaAPIWrapper - -from langflow.custom import CustomComponent - -# Since all the fields in the JSON have show=False, we will only create a basic component -# without any configurable fields. - - -class WolframAlphaAPIWrapperComponent(CustomComponent): - display_name = "WolframAlphaAPIWrapper" - description = "Wrapper for Wolfram Alpha." - name = "WolframAlphaAPIWrapper" - - def build_config(self): - return {"appid": {"display_name": "App ID", "type": "str", "password": True}} - - def build(self, appid: str) -> Union[Callable, WolframAlphaAPIWrapper]: - return WolframAlphaAPIWrapper(wolfram_alpha_appid=appid) # type: ignore diff --git a/src/backend/base/langflow/components/tools/BingSearchAPI.py b/src/backend/base/langflow/components/tools/BingSearchAPI.py new file mode 100644 index 000000000..7d9c0c453 --- /dev/null +++ b/src/backend/base/langflow/components/tools/BingSearchAPI.py @@ -0,0 +1,46 @@ +from typing import List + +from langchain_community.tools.bing_search import BingSearchResults +from langchain_community.utilities import BingSearchAPIWrapper +from langchain_core.tools import BaseTool + +from langflow.base.langchain_utilities.model import LCToolComponent +from langflow.inputs import IntInput, MessageTextInput, MultilineInput, SecretStrInput +from langflow.schema import Data + + +class BingSearchAPIComponent(LCToolComponent): + display_name = "Bing Search API" + description = "Call the Bing Search API." + name = "BingSearchAPI" + + inputs = [ + SecretStrInput(name="bing_subscription_key", display_name="Bing Subscription Key"), + MultilineInput( + name="input_value", + display_name="Input", + ), + MessageTextInput(name="bing_search_url", display_name="Bing Search URL", advanced=True), + IntInput(name="k", display_name="Number of results", value=4, required=True), + ] + + def run_model(self) -> List[Data]: + if self.bing_search_url: + wrapper = BingSearchAPIWrapper( + bing_search_url=self.bing_search_url, bing_subscription_key=self.bing_subscription_key + ) + else: + wrapper = BingSearchAPIWrapper(bing_subscription_key=self.bing_subscription_key) # type: ignore + results = wrapper.results(query=self.input_value, num_results=self.k) + data = [Data(data=result, text=result["snippet"]) for result in results] + self.status = data + return data + + def build_tool(self) -> BaseTool: + if self.bing_search_url: + wrapper = BingSearchAPIWrapper( + bing_search_url=self.bing_search_url, bing_subscription_key=self.bing_subscription_key + ) + else: + wrapper = BingSearchAPIWrapper(bing_subscription_key=self.bing_subscription_key) # type: ignore + return BingSearchResults(api_wrapper=wrapper, num_results=self.k) diff --git a/src/backend/base/langflow/components/tools/GoogleSearchAPI.py b/src/backend/base/langflow/components/tools/GoogleSearchAPI.py new file mode 100644 index 000000000..25d79f775 --- /dev/null +++ b/src/backend/base/langflow/components/tools/GoogleSearchAPI.py @@ -0,0 +1,45 @@ +from typing import Union + +from langchain_core.tools import BaseTool, Tool + +from langflow.base.langchain_utilities.model import LCToolComponent +from langflow.inputs import SecretStrInput, MultilineInput, IntInput +from langflow.schema import Data + + +class GoogleSearchAPIComponent(LCToolComponent): + display_name = "Google Search API" + description = "Call Google Search API." + name = "GoogleSearchAPI" + + inputs = [ + SecretStrInput(name="google_api_key", display_name="Google API Key", required=True), + SecretStrInput(name="google_cse_id", display_name="Google CSE ID", required=True), + MultilineInput( + name="input_value", + display_name="Input", + ), + IntInput(name="k", display_name="Number of results", value=4, required=True), + ] + + def run_model(self) -> Union[Data, list[Data]]: + wrapper = self._build_wrapper() + results = wrapper.results(query=self.input_value, num_results=self.k) + data = [Data(data=result, text=result["snippet"]) for result in results] + self.status = data + return data + + def build_tool(self) -> BaseTool: + wrapper = self._build_wrapper() + return Tool( + name="google_search", + description="Search Google for recent results.", + func=wrapper.run, + ) + + def _build_wrapper(self): + try: + from langchain_google_community import GoogleSearchAPIWrapper # type: ignore + except ImportError: + raise ImportError("Please install langchain-google-community to use GoogleSearchAPIWrapper.") + return GoogleSearchAPIWrapper(google_api_key=self.google_api_key, google_cse_id=self.google_cse_id, k=self.k) diff --git a/src/backend/base/langflow/components/tools/GoogleSerperAPI.py b/src/backend/base/langflow/components/tools/GoogleSerperAPI.py new file mode 100644 index 000000000..66b4cebd3 --- /dev/null +++ b/src/backend/base/langflow/components/tools/GoogleSerperAPI.py @@ -0,0 +1,42 @@ +from typing import Union + +from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper + +from langchain_core.tools import BaseTool, Tool +from langflow.base.langchain_utilities.model import LCToolComponent +from langflow.inputs import SecretStrInput, MultilineInput, IntInput +from langflow.schema import Data + + +class GoogleSerperAPIComponent(LCToolComponent): + display_name = "Google Serper API" + description = "Call the Serper.dev Google Search API." + name = "GoogleSerperAPI" + + inputs = [ + SecretStrInput(name="serper_api_key", display_name="Serper API Key", required=True), + MultilineInput( + name="input_value", + display_name="Input", + ), + IntInput(name="k", display_name="Number of results", value=4, required=True), + ] + + def run_model(self) -> Union[Data, list[Data]]: + wrapper = self._build_wrapper() + results = wrapper.results(query=self.input_value) + list_results = results.get("organic", []) + data = [Data(data=result, text=result["snippet"]) for result in list_results] + self.status = data + return data + + def build_tool(self) -> BaseTool: + wrapper = self._build_wrapper() + return Tool( + name="google_search", + description="Search Google for recent results.", + func=wrapper.run, + ) + + def _build_wrapper(self): + return GoogleSerperAPIWrapper(serper_api_key=self.serper_api_key, k=self.k) diff --git a/src/backend/base/langflow/components/tools/SearchAPI.py b/src/backend/base/langflow/components/tools/SearchAPI.py new file mode 100644 index 000000000..42c940589 --- /dev/null +++ b/src/backend/base/langflow/components/tools/SearchAPI.py @@ -0,0 +1,44 @@ +from typing import Union + +from langchain_community.utilities.searchapi import SearchApiAPIWrapper + +from langflow.base.langchain_utilities.model import LCToolComponent +from langchain_core.tools import BaseTool, Tool +from langflow.inputs import SecretStrInput, MultilineInput, DictInput, MessageTextInput +from langflow.schema import Data + + +class SearchAPIComponent(LCToolComponent): + display_name: str = "Search API" + description: str = "Call the searchapi.io API" + name = "SearchAPI" + documentation: str = "https://www.searchapi.io/docs/google" + + inputs = [ + MessageTextInput(name="engine", display_name="Engine", value="google"), + SecretStrInput(name="api_key", display_name="SearchAPI API Key", required=True), + MultilineInput( + name="input_value", + display_name="Input", + ), + DictInput(name="search_params", display_name="Search parameters", advanced=True, is_list=True), + ] + + def run_model(self) -> Union[Data, list[Data]]: + wrapper = self._build_wrapper() + results = wrapper.results(query=self.input_value, **(self.search_params or {})) + list_results = results.get("organic_results", []) + data = [Data(data=result, text=result["snippet"]) for result in list_results] + self.status = data + return data + + def build_tool(self) -> BaseTool: + wrapper = self._build_wrapper() + return Tool( + name="search_api", + description="Search for recent results.", + func=lambda x: wrapper.run(query=x, **(self.search_params or {})), + ) + + def _build_wrapper(self): + return SearchApiAPIWrapper(engine=self.engine, searchapi_api_key=self.api_key) diff --git a/src/backend/base/langflow/components/tools/SearchAPITool.py b/src/backend/base/langflow/components/tools/SearchAPITool.py deleted file mode 100644 index 3c8058ee9..000000000 --- a/src/backend/base/langflow/components/tools/SearchAPITool.py +++ /dev/null @@ -1,38 +0,0 @@ -from langchain_community.tools.searchapi import SearchAPIRun -from langchain_community.utilities.searchapi import SearchApiAPIWrapper - -from langflow.custom import CustomComponent -from langflow.field_typing import Tool - - -class SearchApiToolComponent(CustomComponent): - display_name: str = "SearchApi Tool" - description: str = "Real-time search engine results API." - name = "SearchAPITool" - documentation: str = "https://www.searchapi.io/docs/google" - field_config = { - "engine": { - "display_name": "Engine", - "field_type": "str", - "info": "The search engine to use.", - }, - "api_key": { - "display_name": "API Key", - "field_type": "str", - "required": True, - "password": True, - "info": "The API key to use SearchApi.", - }, - } - - def build( - self, - engine: str, - api_key: str, - ) -> Tool: - search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key) - - tool = SearchAPIRun(api_wrapper=search_api_wrapper) - - self.status = tool - return tool # type: ignore diff --git a/src/backend/base/langflow/components/tools/SearchApi.py b/src/backend/base/langflow/components/tools/SearchApi.py deleted file mode 100644 index 2b6f54de7..000000000 --- a/src/backend/base/langflow/components/tools/SearchApi.py +++ /dev/null @@ -1,55 +0,0 @@ -from typing import Optional - -from langchain_community.utilities.searchapi import SearchApiAPIWrapper - -from langflow.custom import CustomComponent -from langflow.schema import Data -from langflow.services.database.models.base import orjson_dumps - - -class SearchApi(CustomComponent): - display_name: str = "SearchApi" - description: str = "Real-time search engine results API." - name = "SearchApi" - - output_types: list[str] = ["Document"] - documentation: str = "https://www.searchapi.io/docs/google" - field_config = { - "engine": { - "display_name": "Engine", - "field_type": "str", - "info": "The search engine to use.", - }, - "params": { - "display_name": "Parameters", - "info": "The parameters to send with the request.", - }, - "code": {"show": False}, - "api_key": { - "display_name": "API Key", - "field_type": "str", - "required": True, - "password": True, - "info": "The API key to use SearchApi.", - }, - } - - def build( - self, - engine: str, - api_key: str, - params: Optional[dict] = None, - ) -> Data: - if params is None: - params = {} - - search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key) - - q = params.pop("q", "SearchApi Langflow") - results = search_api_wrapper.results(q, **params) - - result = orjson_dumps(results, indent_2=False) - - record = Data(data=result) - self.status = record - return record diff --git a/src/backend/base/langflow/components/tools/SerpAPI.py b/src/backend/base/langflow/components/tools/SerpAPI.py new file mode 100644 index 000000000..302ecf831 --- /dev/null +++ b/src/backend/base/langflow/components/tools/SerpAPI.py @@ -0,0 +1,43 @@ +from langchain_community.utilities.serpapi import SerpAPIWrapper + +from langflow.base.langchain_utilities.model import LCToolComponent +from langchain_core.tools import BaseTool, Tool +from langflow.inputs import SecretStrInput, DictInput, MultilineInput +from langflow.schema import Data + + +class SerpAPIComponent(LCToolComponent): + display_name = "Serp Search API" + description = "Call Serp Search API" + name = "SerpAPI" + + inputs = [ + SecretStrInput(name="serpapi_api_key", display_name="SerpAPI API Key", required=True), + MultilineInput( + name="input_value", + display_name="Input", + ), + DictInput(name="search_params", display_name="Parameters", advanced=True, is_list=True), + ] + + def run_model(self) -> list[Data]: + wrapper = self._build_wrapper() + results = wrapper.results(self.input_value) + list_results = results.get("organic_results", []) + data = [Data(data=result, text=result["snippet"]) for result in list_results] + self.status = data + return data + + def build_tool(self) -> BaseTool: + wrapper = self._build_wrapper() + return Tool(name="search_api", description="Search for recent results.", func=wrapper.run) + + def _build_wrapper(self) -> SerpAPIWrapper: + if self.search_params: + return SerpAPIWrapper( # type: ignore + serpapi_api_key=self.serpapi_api_key, + params=self.search_params, + ) + return SerpAPIWrapper( # type: ignore + serpapi_api_key=self.serpapi_api_key + ) diff --git a/src/backend/base/langflow/components/tools/WikipediaAPI.py b/src/backend/base/langflow/components/tools/WikipediaAPI.py new file mode 100644 index 000000000..914dee8c8 --- /dev/null +++ b/src/backend/base/langflow/components/tools/WikipediaAPI.py @@ -0,0 +1,44 @@ +from langchain_community.utilities.wikipedia import WikipediaAPIWrapper + +from langflow.base.langchain_utilities.model import LCToolComponent +from langchain.tools import WikipediaQueryRun, BaseTool +from langflow.inputs import IntInput, MessageTextInput, BoolInput, MultilineInput +from langflow.schema import Data + + +class WikipediaAPIComponent(LCToolComponent): + display_name = "Wikipedia API" + description = "Call Wikipedia API." + name = "WikipediaAPI" + + inputs = [ + MultilineInput( + name="input_value", + display_name="Input", + ), + MessageTextInput(name="lang", display_name="Language", value="en"), + IntInput(name="k", display_name="Number of results", value=4, required=True), + BoolInput(name="load_all_available_meta", display_name="Load all available meta", value=False, advanced=True), + IntInput( + name="doc_content_chars_max", display_name="Document content characters max", value=4000, advanced=True + ), + ] + + def run_model(self) -> list[Data]: + wrapper = self._build_wrapper() + docs = wrapper.load(self.input_value) + data = [Data.from_document(doc) for doc in docs] + self.status = data + return data + + def build_tool(self) -> BaseTool: + wrapper = self._build_wrapper() + return WikipediaQueryRun(api_wrapper=wrapper) + + def _build_wrapper(self) -> WikipediaAPIWrapper: + return WikipediaAPIWrapper( # type: ignore + top_k_results=self.k, + lang=self.lang, + load_all_available_meta=self.load_all_available_meta, + doc_content_chars_max=self.doc_content_chars_max, + ) diff --git a/src/backend/base/langflow/components/tools/WolframAlphaAPI.py b/src/backend/base/langflow/components/tools/WolframAlphaAPI.py new file mode 100644 index 000000000..faaa1fc7e --- /dev/null +++ b/src/backend/base/langflow/components/tools/WolframAlphaAPI.py @@ -0,0 +1,34 @@ +from langchain_community.utilities.wolfram_alpha import WolframAlphaAPIWrapper + +from langflow.base.langchain_utilities.model import LCToolComponent +from langchain.tools import BaseTool, Tool +from langflow.inputs import MultilineInput, SecretStrInput +from langflow.schema import Data + + +class WolframAlphaAPIComponent(LCToolComponent): + display_name = "WolframAlphaAPI" + description = "Call Wolfram Alpha API." + name = "WolframAlphaAPI" + + inputs = [ + MultilineInput( + name="input_value", + display_name="Input", + ), + SecretStrInput(name="app_id", display_name="App ID", required=True), + ] + + def run_model(self) -> list[Data]: + wrapper = self._build_wrapper() + result_str = wrapper.run(self.input_value) + data = [Data(text=result_str)] + self.status = data + return data + + def build_tool(self) -> BaseTool: + wrapper = self._build_wrapper() + return Tool(name="wolfram_alpha_api", description="Answers mathematical questions.", func=wrapper.run) + + def _build_wrapper(self) -> WolframAlphaAPIWrapper: + return WolframAlphaAPIWrapper(wolfram_alpha_appid=self.app_id) # type: ignore diff --git a/src/backend/base/langflow/components/tools/__init__.py b/src/backend/base/langflow/components/tools/__init__.py index 3d64a723c..3ebec76ee 100644 --- a/src/backend/base/langflow/components/tools/__init__.py +++ b/src/backend/base/langflow/components/tools/__init__.py @@ -1,7 +1,24 @@ from .PythonREPLTool import PythonREPLToolComponent from .RetrieverTool import RetrieverToolComponent -from .SearchApi import SearchApi -from .SearchAPITool import SearchApiToolComponent +from .BingSearchAPI import BingSearchAPIComponent +from .GoogleSearchAPI import GoogleSearchAPIComponent +from .GoogleSerperAPI import GoogleSerperAPIComponent +from .PythonCodeStructuredTool import PythonCodeStructuredTool +from .SearchAPI import SearchAPIComponent +from .SerpAPI import SerpAPIComponent +from .WikipediaAPI import WikipediaAPIComponent +from .WolframAlphaAPI import WolframAlphaAPIComponent -__all__ = ["RetrieverToolComponent", "SearchApiToolComponent", "SearchApi", "PythonREPLToolComponent"] +__all__ = [ + "RetrieverToolComponent", + "BingSearchAPIComponent", + "GoogleSearchAPIComponent", + "GoogleSerperAPIComponent", + "PythonCodeStructuredTool", + "PythonREPLToolComponent", + "SearchAPIComponent", + "SerpAPIComponent", + "WikipediaAPIComponent", + "WolframAlphaAPIComponent", +] diff --git a/src/backend/base/langflow/field_typing/constants.py b/src/backend/base/langflow/field_typing/constants.py index 9ac0a1a3f..cff143fc5 100644 --- a/src/backend/base/langflow/field_typing/constants.py +++ b/src/backend/base/langflow/field_typing/constants.py @@ -13,7 +13,7 @@ from langchain_core.memory import BaseMemory from langchain_core.output_parsers import BaseOutputParser from langchain_core.prompts import BasePromptTemplate, ChatPromptTemplate, PromptTemplate from langchain_core.retrievers import BaseRetriever -from langchain_core.tools import Tool +from langchain_core.tools import Tool, BaseTool from langchain_core.vectorstores import VectorStore, VectorStoreRetriever from langchain_text_splitters import TextSplitter @@ -43,6 +43,7 @@ class Code: LANGCHAIN_BASE_TYPES = { "Chain": Chain, "AgentExecutor": AgentExecutor, + "BaseTool": BaseTool, "Tool": Tool, "BaseLLM": BaseLLM, "BaseLanguageModel": BaseLanguageModel, diff --git a/src/backend/base/poetry.lock b/src/backend/base/poetry.lock index 26c2287fb..a2666a105 100644 --- a/src/backend/base/poetry.lock +++ b/src/backend/base/poetry.lock @@ -1245,19 +1245,19 @@ files = [ [[package]] name = "langchain" -version = "0.2.8" +version = "0.2.9" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.2.8-py3-none-any.whl", hash = "sha256:53e7dfe50294a14200f33bec22b4e14cb63857ccf0a5500b0d18b0fd51285d58"}, - {file = "langchain-0.2.8.tar.gz", hash = "sha256:7fecb309e3558cde4e5cf7e9ffb7c1ab3f07121c40a7ff3b0c27135f8120c296"}, + {file = "langchain-0.2.9-py3-none-any.whl", hash = "sha256:be23fcb29adbd5059944f1fed08fa575f0739d420b1c4127531e0fbf5663fcca"}, + {file = "langchain-0.2.9.tar.gz", hash = "sha256:cc326a7f6347787a19882928c324433b1a79df629bba45604b2d26495ee5d69c"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -langchain-core = ">=0.2.19,<0.3.0" +langchain-core = ">=0.2.20,<0.3.0" langchain-text-splitters = ">=0.2.0,<0.3.0" langsmith = ">=0.1.17,<0.2.0" numpy = [