diff --git a/docs/docs/Integrations/integrations-langwatch.mdx b/docs/docs/Integrations/integrations-langwatch.mdx
new file mode 100644
index 000000000..8060ad480
--- /dev/null
+++ b/docs/docs/Integrations/integrations-langwatch.mdx
@@ -0,0 +1,46 @@
+import Admonition from "@theme/Admonition";
+import ThemedImage from "@theme/ThemedImage";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import ZoomableImage from "/src/theme/ZoomableImage.js";
+
+# LangWatch
+
+LangWatch is an all-in-one LLMOps platform for monitoring, observability, analytics, evaluations and alerting for getting user insights and improve your LLM workflows.
+
+To integrate with Langflow, just add your LangWatch API as a Langflow environment variable and you are good to go!
+
+## Step-by-step Configuration
+
+1. Obtain your LangWatch API key from https://app.langwatch.com/
+2. Add the following key to Langflow .env file:
+
+```bash
+LANGWATCH_API_KEY="your-api-key"
+```
+
+or export it in your terminal:
+
+```bash
+export LANGWATCH_API_KEY="your-api-key"
+```
+
+3. Restart Langflow using `langflow run --env-file .env`
+4. Run any project and check the LangWatch dashboard for monitoring and observability.
+
+
+
+
diff --git a/docs/static/img/langwatch-flow.png b/docs/static/img/langwatch-flow.png
new file mode 100644
index 000000000..50f17c9fa
Binary files /dev/null and b/docs/static/img/langwatch-flow.png differ
diff --git a/docs/static/img/langwatch-trace.png b/docs/static/img/langwatch-trace.png
new file mode 100644
index 000000000..9cf362a49
Binary files /dev/null and b/docs/static/img/langwatch-trace.png differ
diff --git a/poetry.lock b/poetry.lock
index 0bf920865..cd1c9a441 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1083,13 +1083,13 @@ all = ["pycocotools (==2.0.6)"]
[[package]]
name = "clarifai-grpc"
-version = "10.6.3"
+version = "10.6.4"
description = "Clarifai gRPC API Client"
optional = false
python-versions = ">=3.8"
files = [
- {file = "clarifai_grpc-10.6.3-py3-none-any.whl", hash = "sha256:304a8123dfe6fb41953026e0e4b800bffc3998a75408f51f3ab2a6eacfb1781e"},
- {file = "clarifai_grpc-10.6.3.tar.gz", hash = "sha256:6be24d21f124678384902e693eb9b5d2e5c57aeef57c098e3a2b94e40a79c198"},
+ {file = "clarifai_grpc-10.6.4-py3-none-any.whl", hash = "sha256:9fb8c94e6ede5e1005010643f516aa7c1dd3c59ab9282e03ba4932fd929d7584"},
+ {file = "clarifai_grpc-10.6.4.tar.gz", hash = "sha256:84d92b10fc32c17ecf0c0fc30ec4c9960a6a9ee701f2829f0c372892ae761d14"},
]
[package.dependencies]
@@ -1232,13 +1232,13 @@ types = ["chardet (>=5.1.0)", "mypy", "pytest", "pytest-cov", "pytest-dependency
[[package]]
name = "cohere"
-version = "5.5.8"
+version = "5.6.1"
description = ""
optional = false
python-versions = "<4.0,>=3.8"
files = [
- {file = "cohere-5.5.8-py3-none-any.whl", hash = "sha256:e1ed84b90eadd13c6a68ee28e378a0bb955f8945eadc6eb7ee126b3399cafd54"},
- {file = "cohere-5.5.8.tar.gz", hash = "sha256:84ce7666ff8fbdf4f41fb5f6ca452ab2639a514bc88967a2854a9b1b820d6ea0"},
+ {file = "cohere-5.6.1-py3-none-any.whl", hash = "sha256:1c8bcd39a54622d64b83cafb865f102cd2565ce091b0856fd5ce11bf7169109a"},
+ {file = "cohere-5.6.1.tar.gz", hash = "sha256:5d7efda64f0e512d4cc35aa04b17a6f74b3d8c175a99f2797991a7f31dfac349"},
]
[package.dependencies]
@@ -1341,6 +1341,17 @@ files = [
{file = "contextlib2-21.6.0.tar.gz", hash = "sha256:ab1e2bfe1d01d968e1b7e8d9023bc51ef3509bba217bb730cee3827e1ee82869"},
]
+[[package]]
+name = "coolname"
+version = "2.2.0"
+description = "Random name and slug generator"
+optional = false
+python-versions = "*"
+files = [
+ {file = "coolname-2.2.0-py2.py3-none-any.whl", hash = "sha256:4d1563186cfaf71b394d5df4c744f8c41303b6846413645e31d31915cdeb13e8"},
+ {file = "coolname-2.2.0.tar.gz", hash = "sha256:6c5d5731759104479e7ca195a9b64f7900ac5bead40183c09323c7d0be9e75c7"},
+]
+
[[package]]
name = "couchbase"
version = "4.3.0"
@@ -4824,13 +4835,13 @@ pymongo = ">=4.6.1,<5.0"
[[package]]
name = "langchain-nvidia-ai-endpoints"
-version = "0.1.3"
+version = "0.1.4"
description = "An integration package connecting NVIDIA AI Endpoints and LangChain"
optional = false
python-versions = "<4.0,>=3.8.1"
files = [
- {file = "langchain_nvidia_ai_endpoints-0.1.3-py3-none-any.whl", hash = "sha256:16d5a5862156d7e177a55727dc6411356529dda35b729344d7157f6cf8315a24"},
- {file = "langchain_nvidia_ai_endpoints-0.1.3.tar.gz", hash = "sha256:a68f53ef2bcbb3360a6217a4a4dad014efc50c73a2bd0fe6896818288d456283"},
+ {file = "langchain_nvidia_ai_endpoints-0.1.4-py3-none-any.whl", hash = "sha256:e65e21b4ecdd1e5add44520399bffcd4a158194d28021a6e789f76e895fe27d6"},
+ {file = "langchain_nvidia_ai_endpoints-0.1.4.tar.gz", hash = "sha256:8b2c8b80f00d1d64f5ee25a93df0692cbb6d13e51f00e45332c2851fef77f9f3"},
]
[package.dependencies]
@@ -4943,6 +4954,7 @@ jq = {version = "^1.7.0", markers = "sys_platform != \"win32\""}
langchain = "~0.2.0"
langchain-experimental = "^0.0.61"
langchainhub = "~0.1.15"
+langwatch = "^0.1.3"
loguru = "^0.7.1"
multiprocess = "^0.70.14"
nest-asyncio = "^1.6.0"
@@ -4950,7 +4962,7 @@ opentelemetry-api = "^1.25.0"
opentelemetry-exporter-prometheus = "^0.46b0"
opentelemetry-sdk = "^1.25.0"
orjson = "3.10.0"
-pandas = "2.2.0"
+pandas = "2.2.2"
passlib = "^1.7.4"
pillow = "^10.2.0"
platformdirs = "^4.2.0"
@@ -5007,13 +5019,13 @@ openai = ["openai (>=0.27.8)"]
[[package]]
name = "langsmith"
-version = "0.1.85"
+version = "0.1.86"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
optional = false
python-versions = "<4.0,>=3.8.1"
files = [
- {file = "langsmith-0.1.85-py3-none-any.whl", hash = "sha256:c1f94384f10cea96f7b4d33fd3db7ec180c03c7468877d50846f881d2017ff94"},
- {file = "langsmith-0.1.85.tar.gz", hash = "sha256:acff31f9e53efa48586cf8e32f65625a335c74d7c4fa306d1655ac18452296f6"},
+ {file = "langsmith-0.1.86-py3-none-any.whl", hash = "sha256:55ed80cc6e98f9761f9b3ec3c49e01f6745d13e40bef80d9f831acabfd9a8a1e"},
+ {file = "langsmith-0.1.86.tar.gz", hash = "sha256:2e66577817253327b99b727588c3173fbba217fe0ca07ac6b7cdd23fc4894104"},
]
[package.dependencies]
@@ -5024,15 +5036,43 @@ pydantic = [
]
requests = ">=2,<3"
+[[package]]
+name = "langwatch"
+version = "0.1.8"
+description = "Python SDK for LangWatch for monitoring your LLMs"
+optional = false
+python-versions = "<4.0,>=3.9"
+files = [
+ {file = "langwatch-0.1.8-py3-none-any.whl", hash = "sha256:e6e7ffe2f3cd61c477e8ff6de4ad3d1e06f63b0c8f02880d68293fc126ec2bf7"},
+ {file = "langwatch-0.1.8.tar.gz", hash = "sha256:2ccc3a741ef9bf493946264ab8fff5cb33845e51d4426136218d62b1a4cbd26d"},
+]
+
+[package.dependencies]
+coolname = ">=2.2.0,<3.0.0"
+deprecated = ">=1.2.14,<2.0.0"
+httpx = ">=0.27.0,<0.28.0"
+nanoid = ">=2.0.0,<3.0.0"
+pandas = ">=2.2.2,<3.0.0"
+pydantic = ">=2.5.2"
+requests = ">=2.31.0,<3.0.0"
+retry = ">=0.9.2,<0.10.0"
+tqdm = ">=4.66.2,<5.0.0"
+
+[package.extras]
+dspy = ["dspy-ai (>=2.4.12,<3.0.0)"]
+langchain = ["langchain (>=0.2.0,<0.3.0)"]
+litellm = ["litellm (>=1.40.15,<2.0.0)"]
+openai = ["openai (>=1.3.7,<2.0.0)"]
+
[[package]]
name = "litellm"
-version = "1.41.22"
+version = "1.41.23"
description = "Library to easily interface with LLM API providers"
optional = false
python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8"
files = [
- {file = "litellm-1.41.22-py3-none-any.whl", hash = "sha256:b7560a5487ad23a2d8d5ce0d810d640488e6264f22f35041c1e3f9ca8933e71b"},
- {file = "litellm-1.41.22.tar.gz", hash = "sha256:1cdfffc792535e87a40463fe04205353ebe681ce87fc3245a0436f4c124f6ed6"},
+ {file = "litellm-1.41.23-py3-none-any.whl", hash = "sha256:ccfe7763e694ae43b50229fc78bb999a18507b654ec2046c55c6e2a2ea48bf96"},
+ {file = "litellm-1.41.23.tar.gz", hash = "sha256:320afcd172fb936f1297ce135075e3397141cf245cdb936f01871c9d6ed56516"},
]
[package.dependencies]
@@ -5917,6 +5957,17 @@ files = [
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
]
+[[package]]
+name = "nanoid"
+version = "2.0.0"
+description = "A tiny, secure, URL-friendly, unique string ID generator for Python"
+optional = false
+python-versions = "*"
+files = [
+ {file = "nanoid-2.0.0-py3-none-any.whl", hash = "sha256:90aefa650e328cffb0893bbd4c236cfd44c48bc1f2d0b525ecc53c3187b653bb"},
+ {file = "nanoid-2.0.0.tar.gz", hash = "sha256:5a80cad5e9c6e9ae3a41fa2fb34ae189f7cb420b2a5d8f82bd9d23466e4efa68"},
+]
+
[[package]]
name = "nest-asyncio"
version = "1.6.0"
@@ -6270,13 +6321,13 @@ sympy = "*"
[[package]]
name = "openai"
-version = "1.35.13"
+version = "1.35.14"
description = "The official Python library for the openai API"
optional = false
python-versions = ">=3.7.1"
files = [
- {file = "openai-1.35.13-py3-none-any.whl", hash = "sha256:36ec3e93e0d1f243f69be85c89b9221a471c3e450dfd9df16c9829e3cdf63e60"},
- {file = "openai-1.35.13.tar.gz", hash = "sha256:c684f3945608baf7d2dcc0ef3ee6f3e27e4c66f21076df0b47be45d57e6ae6e4"},
+ {file = "openai-1.35.14-py3-none-any.whl", hash = "sha256:adadf8c176e0b8c47ad782ed45dc20ef46438ee1f02c7103c4155cff79c8f68b"},
+ {file = "openai-1.35.14.tar.gz", hash = "sha256:394ba1dfd12ecec1d634c50e512d24ff1858bbc2674ffcce309b822785a058de"},
]
[package.dependencies]
@@ -6628,47 +6679,47 @@ files = [
[[package]]
name = "pandas"
-version = "2.2.0"
+version = "2.2.2"
description = "Powerful data structures for data analysis, time series, and statistics"
optional = false
python-versions = ">=3.9"
files = [
- {file = "pandas-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8108ee1712bb4fa2c16981fba7e68b3f6ea330277f5ca34fa8d557e986a11670"},
- {file = "pandas-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:736da9ad4033aeab51d067fc3bd69a0ba36f5a60f66a527b3d72e2030e63280a"},
- {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e0b4fc3ddceb56ec8a287313bc22abe17ab0eb184069f08fc6a9352a769b18"},
- {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20404d2adefe92aed3b38da41d0847a143a09be982a31b85bc7dd565bdba0f4e"},
- {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ea3ee3f125032bfcade3a4cf85131ed064b4f8dd23e5ce6fa16473e48ebcaf5"},
- {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1"},
- {file = "pandas-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a946f210383c7e6d16312d30b238fd508d80d927014f3b33fb5b15c2f895430"},
- {file = "pandas-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a1b438fa26b208005c997e78672f1aa8138f67002e833312e6230f3e57fa87d5"},
- {file = "pandas-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ce2fbc8d9bf303ce54a476116165220a1fedf15985b09656b4b4275300e920b"},
- {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2707514a7bec41a4ab81f2ccce8b382961a29fbe9492eab1305bb075b2b1ff4f"},
- {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85793cbdc2d5bc32620dc8ffa715423f0c680dacacf55056ba13454a5be5de88"},
- {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfd6c2491dc821b10c716ad6776e7ab311f7df5d16038d0b7458bc0b67dc10f3"},
- {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a146b9dcacc3123aa2b399df1a284de5f46287a4ab4fbfc237eac98a92ebcb71"},
- {file = "pandas-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9"},
- {file = "pandas-2.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a41d06f308a024981dcaa6c41f2f2be46a6b186b902c94c2674e8cb5c42985bc"},
- {file = "pandas-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:159205c99d7a5ce89ecfc37cb08ed179de7783737cea403b295b5eda8e9c56d1"},
- {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1e1f3861ea9132b32f2133788f3b14911b68102d562715d71bd0013bc45440"},
- {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:761cb99b42a69005dec2b08854fb1d4888fdf7b05db23a8c5a099e4b886a2106"},
- {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a20628faaf444da122b2a64b1e5360cde100ee6283ae8effa0d8745153809a2e"},
- {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f5be5d03ea2073627e7111f61b9f1f0d9625dc3c4d8dda72cc827b0c58a1d042"},
- {file = "pandas-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a626795722d893ed6aacb64d2401d017ddc8a2341b49e0384ab9bf7112bdec30"},
- {file = "pandas-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f66419d4a41132eb7e9a73dcec9486cf5019f52d90dd35547af11bc58f8637d"},
- {file = "pandas-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57abcaeda83fb80d447f28ab0cc7b32b13978f6f733875ebd1ed14f8fbc0f4ab"},
- {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60f1f7dba3c2d5ca159e18c46a34e7ca7247a73b5dd1a22b6d59707ed6b899a"},
- {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb61dc8567b798b969bcc1fc964788f5a68214d333cade8319c7ab33e2b5d88a"},
- {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:52826b5f4ed658fa2b729264d63f6732b8b29949c7fd234510d57c61dbeadfcd"},
- {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bde2bc699dbd80d7bc7f9cab1e23a95c4375de615860ca089f34e7c64f4a8de7"},
- {file = "pandas-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:3de918a754bbf2da2381e8a3dcc45eede8cd7775b047b923f9006d5f876802ae"},
- {file = "pandas-2.2.0.tar.gz", hash = "sha256:30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2"},
+ {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"},
+ {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"},
+ {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"},
+ {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"},
+ {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"},
+ {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"},
+ {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"},
+ {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"},
+ {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"},
+ {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"},
+ {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"},
+ {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"},
+ {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"},
+ {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"},
+ {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"},
+ {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"},
+ {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"},
+ {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"},
+ {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"},
+ {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"},
+ {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"},
+ {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"},
+ {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"},
+ {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"},
+ {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"},
+ {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"},
+ {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"},
+ {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"},
+ {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"},
]
[package.dependencies]
numpy = [
- {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""},
- {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""},
- {version = ">=1.26.0,<2", 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"
@@ -6693,6 +6744,7 @@ parquet = ["pyarrow (>=10.0.1)"]
performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"]
plot = ["matplotlib (>=3.6.3)"]
postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"]
+pyarrow = ["pyarrow (>=10.0.1)"]
spss = ["pyreadstat (>=1.2.0)"]
sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"]
test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
@@ -6975,18 +7027,18 @@ tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "p
[[package]]
name = "postgrest"
-version = "0.16.8"
+version = "0.16.9"
description = "PostgREST client for Python. This library provides an ORM interface to PostgREST."
optional = false
python-versions = "<4.0,>=3.8"
files = [
- {file = "postgrest-0.16.8-py3-none-any.whl", hash = "sha256:c353a24452f51ab9760cf2b884c4b7457a2653ff36444e66b12615bc4cc8e23e"},
- {file = "postgrest-0.16.8.tar.gz", hash = "sha256:7b3802a514dc1e0fc8b5bbdeb2c99af35a0bd910e4ddb17855ca4e3422350c84"},
+ {file = "postgrest-0.16.9-py3-none-any.whl", hash = "sha256:8a20a256e86c4181575d271ddd77152b305313890ecc7d2df5b25aeb330bd9a4"},
+ {file = "postgrest-0.16.9.tar.gz", hash = "sha256:fee42e89d265e904e823d9602803980016128ff7dde0ce1e869014cf1fd2c19d"},
]
[package.dependencies]
deprecation = ">=2.1.0,<3.0.0"
-httpx = ">=0.24,<0.28"
+httpx = {version = ">=0.24,<0.28", extras = ["http2"]}
pydantic = ">=1.9,<3.0"
strenum = ">=0.4.9,<0.5.0"
@@ -9765,13 +9817,13 @@ typing = ["mypy (>=1.4)", "rich", "twisted"]
[[package]]
name = "supabase"
-version = "2.5.1"
+version = "2.5.2"
description = "Supabase client for Python."
optional = false
python-versions = "<4.0,>=3.8"
files = [
- {file = "supabase-2.5.1-py3-none-any.whl", hash = "sha256:74a1f24f04fede1967ef084b50dea688228f7b10eb2f9d73350fe2251a865188"},
- {file = "supabase-2.5.1.tar.gz", hash = "sha256:c50e0eba5b03de3abd5ac0f887957ca43558ba44c4d17bb44e73ec454b41734c"},
+ {file = "supabase-2.5.2-py3-none-any.whl", hash = "sha256:321b2278f6f71bdb2ac13f3f36e565f4045a3c099d44aa4f8454ef12c743b445"},
+ {file = "supabase-2.5.2.tar.gz", hash = "sha256:f97e06d9b821f972e50cfe188e49b2a657cd817d48a5b4604304ebd61b7b87ef"},
]
[package.dependencies]
@@ -11685,4 +11737,4 @@ local = ["ctransformers", "llama-cpp-python", "sentence-transformers"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<3.13"
-content-hash = "3561ffbe8cc249b7ca946135d550991879ce9767e607f4a474f80119d2ffd5b2"
+content-hash = "afe38792a9e202ab55558389026b64beb95d1437b2fd4bccfbb300cbc7ad0677"
diff --git a/pyproject.toml b/pyproject.toml
index dfe0b9af8..c66d09dbe 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -99,6 +99,7 @@ langchain-nvidia-ai-endpoints = "^0.1.2"
langchain-google-calendar-tools = "^0.0.1"
langchain-milvus = "^0.1.1"
crewai = {extras = ["tools"], version = "^0.36.0"}
+langwatch = "^0.1.7"
[tool.poetry.group.dev.dependencies]
diff --git a/src/backend/base/langflow/api/v1/chat.py b/src/backend/base/langflow/api/v1/chat.py
index e494288c5..c5ee33179 100644
--- a/src/backend/base/langflow/api/v1/chat.py
+++ b/src/backend/base/langflow/api/v1/chat.py
@@ -221,7 +221,7 @@ async def build_vertex(
outputs = {output_label: OutputLog(message=message, type="error")}
result_data_response = ResultDataResponse(results={}, outputs=outputs)
artifacts = {}
- background_tasks.add_task(graph.end_all_traces, error=message["errorMessage"])
+ background_tasks.add_task(graph.end_all_traces, error=exc)
# If there's an error building the vertex
# we need to clear the cache
await chat_service.clear_cache(flow_id_str)
diff --git a/src/backend/base/langflow/custom/custom_component/component.py b/src/backend/base/langflow/custom/custom_component/component.py
index 254c9fe7e..002a9a8b1 100644
--- a/src/backend/base/langflow/custom/custom_component/component.py
+++ b/src/backend/base/langflow/custom/custom_component/component.py
@@ -123,10 +123,9 @@ class Component(CustomComponent):
async def _build_with_tracing(self):
inputs = self.get_trace_as_inputs()
metadata = self.get_trace_as_metadata()
- async with self.tracing_service.trace_context(self.trace_name, self.trace_type, inputs, metadata):
+ async with self.tracing_service.trace_context(self, self.trace_name, inputs, metadata):
_results, _artifacts = await self._build_results()
- trace_name = self.tracing_service.run_name
- self.tracing_service.set_outputs(trace_name, _results)
+ self.tracing_service.set_outputs(self.trace_name, _results)
return _results, _artifacts
diff --git a/src/backend/base/langflow/graph/graph/base.py b/src/backend/base/langflow/graph/graph/base.py
index 3d86cc530..9d46908cf 100644
--- a/src/backend/base/langflow/graph/graph/base.py
+++ b/src/backend/base/langflow/graph/graph/base.py
@@ -1,5 +1,4 @@
import asyncio
-import traceback
import uuid
from collections import defaultdict, deque
from datetime import datetime, timezone
@@ -257,7 +256,7 @@ class Graph:
async def initialize_run(self):
await self.tracing_service.initialize_tracers()
- async def end_all_traces(self, outputs: dict[str, Any] | None = None, error: str | None = None):
+ async def end_all_traces(self, outputs: dict[str, Any] | None = None, error: Exception | None = None):
if not self.tracing_service:
return
self._end_time = datetime.now(timezone.utc)
@@ -354,9 +353,7 @@ class Graph:
await self.process(start_component_id=start_component_id, fallback_to_env_vars=fallback_to_env_vars)
self.increment_run_count()
except Exception as exc:
- logger.exception(exc)
- tb = traceback.format_exc()
- asyncio.create_task(self.end_all_traces(error=f"{exc.__class__.__name__}: {exc}\n\n{tb}"))
+ asyncio.create_task(self.end_all_traces(error=exc))
raise ValueError(f"Error running graph: {exc}") from exc
finally:
asyncio.create_task(self.end_all_traces())
diff --git a/src/backend/base/langflow/services/tracing/base.py b/src/backend/base/langflow/services/tracing/base.py
index 2ec2eea26..5da28f744 100644
--- a/src/backend/base/langflow/services/tracing/base.py
+++ b/src/backend/base/langflow/services/tracing/base.py
@@ -1,6 +1,10 @@
from abc import ABC, abstractmethod
-from typing import Any, Dict
+from typing import TYPE_CHECKING, Any, Dict, Optional
from uuid import UUID
+from langflow.services.tracing.schema import Log
+
+if TYPE_CHECKING:
+ from langflow.graph.vertex.base import Vertex
class BaseTracer(ABC):
@@ -9,17 +13,30 @@ class BaseTracer(ABC):
raise NotImplementedError
@abstractmethod
- def ready(self):
+ def ready(self) -> bool:
raise NotImplementedError
@abstractmethod
def add_trace(
- self, trace_name: str, trace_type: str, inputs: Dict[str, Any], metadata: Dict[str, Any] | None = None
+ self,
+ trace_id: str,
+ trace_name: str,
+ trace_type: str,
+ inputs: Dict[str, Any],
+ metadata: Dict[str, Any] | None = None,
+ vertex: Optional["Vertex"] = None,
):
raise NotImplementedError
@abstractmethod
- def end_trace(self, trace_name: str, outputs: Dict[str, Any] | None = None, error: str | None = None):
+ def end_trace(
+ self,
+ trace_id: str,
+ trace_name: str,
+ outputs: Dict[str, Any] | None = None,
+ error: Exception | None = None,
+ logs: list[Log | dict] = [],
+ ):
raise NotImplementedError
@abstractmethod
@@ -27,7 +44,7 @@ class BaseTracer(ABC):
self,
inputs: dict[str, Any],
outputs: Dict[str, Any],
- error: str | None = None,
+ error: Exception | None = None,
metadata: dict[str, Any] | None = None,
):
raise NotImplementedError
diff --git a/src/backend/base/langflow/services/tracing/service.py b/src/backend/base/langflow/services/tracing/service.py
index 72e73a50c..3b31ced6c 100644
--- a/src/backend/base/langflow/services/tracing/service.py
+++ b/src/backend/base/langflow/services/tracing/service.py
@@ -5,7 +5,7 @@ import types
from collections import defaultdict
from contextlib import asynccontextmanager
from datetime import datetime, timezone
-from typing import TYPE_CHECKING, Any, Dict, Optional
+from typing import TYPE_CHECKING, Any, Dict, Optional, cast
from uuid import UUID
from loguru import logger
@@ -18,6 +18,10 @@ from langflow.services.tracing.schema import Log
if TYPE_CHECKING:
from langflow.services.monitor.service import MonitorService
from langflow.services.settings.service import SettingsService
+ from langflow.custom.custom_component.component import Component
+ from langflow.graph.vertex.base import Vertex
+ from langwatch.tracer import ContextSpan
+ from langwatch.types import SpanTypes
class TracingService(Service):
@@ -33,7 +37,7 @@ class TracingService(Service):
self.run_name: str | None = None
self.run_id: UUID | None = None
self.project_name = None
- self._tracers: dict[str, LangSmithTracer] = {}
+ self._tracers: dict[str, BaseTracer] = {}
self._logs: dict[str, list[Log | dict[Any, Any]]] = defaultdict(list)
self.logs_queue: asyncio.Queue = asyncio.Queue()
self.running = False
@@ -88,6 +92,7 @@ class TracingService(Service):
try:
await self.start()
self._initialize_langsmith_tracer()
+ self._initialize_langwatch_tracer()
except Exception as e:
logger.debug(f"Error initializing tracers: {e}")
@@ -101,6 +106,19 @@ class TracingService(Service):
trace_id=self.run_id,
)
+ def _initialize_langwatch_tracer(self):
+ if (
+ os.getenv("LANGWATCH_API_KEY")
+ and "langwatch" not in self._tracers
+ or self._tracers["langwatch"].trace_id != self.run_id # type: ignore
+ ):
+ self._tracers["langwatch"] = LangWatchTracer(
+ trace_name=self.run_name,
+ trace_type="chain",
+ project_name=self.project_name,
+ trace_id=self.run_id,
+ )
+
def set_run_name(self, name: str):
self.run_name = name
@@ -108,39 +126,50 @@ class TracingService(Service):
self.run_id = run_id
def _start_traces(
- self, trace_name: str, trace_type: str, inputs: Dict[str, Any], metadata: Optional[Dict[str, Any]] = None
+ self,
+ trace_id: str,
+ trace_name: str,
+ trace_type: str,
+ inputs: Dict[str, Any],
+ metadata: Optional[Dict[str, Any]] = None,
+ vertex: Optional["Vertex"] = None,
):
+ inputs = self._cleanup_inputs(inputs)
self.inputs[trace_name] = inputs
self.inputs_metadata[trace_name] = metadata or {}
for tracer in self._tracers.values():
- if not tracer.ready:
+ if not tracer.ready: # type: ignore
continue
try:
- tracer.add_trace(trace_name, trace_type, inputs, metadata)
+ tracer.add_trace(trace_id, trace_name, trace_type, inputs, metadata, vertex)
except Exception as e:
logger.error(f"Error starting trace {trace_name}: {e}")
- def _end_traces(self, trace_name: str, error: str | None = None):
+ def _end_traces(self, trace_id: str, trace_name: str, error: Exception | None = None):
for tracer in self._tracers.values():
- if not tracer.ready:
+ if not tracer.ready: # type: ignore
continue
try:
tracer.end_trace(
- trace_name=trace_name, outputs=self.outputs[trace_name], error=error, logs=self._logs[trace_name]
+ trace_id=trace_id,
+ trace_name=trace_name,
+ outputs=self.outputs[trace_name],
+ error=error,
+ logs=self._logs[trace_name],
)
except Exception as e:
logger.error(f"Error ending trace {trace_name}: {e}")
- def _end_all_traces(self, outputs: dict, error: str | None = None):
+ def _end_all_traces(self, outputs: dict, error: Exception | None = None):
for tracer in self._tracers.values():
- if not tracer.ready:
+ if not tracer.ready: # type: ignore
continue
try:
tracer.end(self.inputs, outputs=self.outputs, error=error, metadata=outputs)
except Exception as e:
logger.error(f"Error ending all traces: {e}")
- async def end(self, outputs: dict, error: str | None = None):
+ async def end(self, outputs: dict, error: Exception | None = None):
self._end_all_traces(outputs, error)
self._reset_io()
await self.stop()
@@ -151,27 +180,48 @@ class TracingService(Service):
@asynccontextmanager
async def trace_context(
self,
+ component: "Component",
trace_name: str,
- trace_type: str,
inputs: Dict[str, Any],
metadata: Optional[Dict[str, Any]] = None,
):
- self._start_traces(trace_name, trace_type, inputs, metadata)
+ trace_id = trace_name
+ if component.vertex:
+ trace_id = component.vertex.id
+ trace_type = component.trace_type
+ self._start_traces(
+ trace_id,
+ trace_name,
+ trace_type,
+ self._cleanup_inputs(inputs),
+ metadata,
+ component.vertex,
+ )
try:
yield self
except Exception as e:
- tb = traceback.format_exc()
- error_message = f"{e.__class__.__name__}: {e}\n\n{tb}"
- self._end_traces(trace_name, error_message)
+ self._end_traces(trace_id, trace_name, e)
raise e
finally:
- self._end_traces(trace_name, None)
+ self._end_traces(trace_id, trace_name, None)
self._reset_io()
- def set_outputs(self, trace_name: str, outputs: Dict[str, Any], output_metadata: Dict[str, Any] | None = None):
+ def set_outputs(
+ self,
+ trace_name: str,
+ outputs: Dict[str, Any],
+ output_metadata: Dict[str, Any] | None = None,
+ ):
self.outputs[trace_name] |= outputs or {}
self.outputs_metadata[trace_name] |= output_metadata or {}
+ def _cleanup_inputs(self, inputs: Dict[str, Any]):
+ inputs = inputs.copy()
+ for key in inputs.keys():
+ if "api_key" in key:
+ inputs[key] = "*****" # avoid logging api_keys for security reasons
+ return inputs
+
class LangSmithTracer(BaseTracer):
def __init__(self, trace_name: str, trace_type: str, project_name: str, trace_id: UUID):
@@ -211,7 +261,13 @@ class LangSmithTracer(BaseTracer):
return True
def add_trace(
- self, trace_name: str, trace_type: str, inputs: Dict[str, Any], metadata: Dict[str, Any] | None = None
+ self,
+ trace_id: str,
+ trace_name: str,
+ trace_type: str,
+ inputs: Dict[str, Any],
+ metadata: Dict[str, Any] | None = None,
+ vertex: Optional["Vertex"] = None,
):
if not self._ready:
return
@@ -259,9 +315,10 @@ class LangSmithTracer(BaseTracer):
def end_trace(
self,
+ trace_id: str,
trace_name: str,
outputs: Dict[str, Any] | None = None,
- error: str | None = None,
+ error: Exception | None = None,
logs: list[Log | dict] = [],
):
child = self._children[trace_name]
@@ -273,23 +330,196 @@ class LangSmithTracer(BaseTracer):
if logs:
child.add_metadata(self._convert_to_langchain_types({"logs": {log.get("name"): log for log in logs}}))
child.add_metadata(self._convert_to_langchain_types({"outputs": raw_outputs}))
- child.end(outputs=processed_outputs, error=error)
+ child.end(outputs=processed_outputs, error=self._error_to_string(error))
if error:
child.patch()
else:
child.post()
self._child_link[trace_name] = child.get_url()
+ def _error_to_string(self, error: Optional[Exception]):
+ error_message = None
+ if error:
+ string_stacktrace = traceback.format_exception(error)
+ error_message = f"{error.__class__.__name__}: {error}\n\n{string_stacktrace}"
+ return error_message
+
def end(
self,
inputs: dict[str, Any],
outputs: Dict[str, Any],
- error: str | None = None,
+ error: Exception | None = None,
metadata: dict[str, Any] | None = None,
):
self._run_tree.add_metadata({"inputs": inputs})
if metadata:
self._run_tree.add_metadata(metadata)
- self._run_tree.end(outputs=outputs, error=error)
+ self._run_tree.end(outputs=outputs, error=self._error_to_string(error))
self._run_tree.post()
self._run_link = self._run_tree.get_url()
+
+
+class LangWatchTracer(BaseTracer):
+ flow_id: str
+
+ def __init__(self, trace_name: str, trace_type: str, project_name: str, trace_id: UUID):
+ self.trace_name = trace_name
+ self.trace_type = trace_type
+ self.project_name = project_name
+ self.trace_id = trace_id
+ self.flow_id = trace_name.split(" - ")[-1]
+
+ try:
+ self._ready = self.setup_langwatch()
+
+ # import after setting up langwatch so we are sure to be available
+ import nanoid # type: ignore
+
+ self.trace = self._client.trace(
+ trace_id=str(self.trace_id),
+ )
+ self.spans: dict[str, "ContextSpan"] = {}
+
+ name_without_id = " - ".join(trace_name.split(" - ")[0:-1])
+ self.trace.root_span.update(
+ span_id=f"{self.flow_id}-{nanoid.generate(size=6)}", # nanoid to make the span_id globally unique, which is required for LangWatch for now
+ name=name_without_id,
+ type=self._convert_trace_type(trace_type),
+ )
+ except Exception as e:
+ logger.debug(f"Error setting up LangWatch tracer: {e}")
+ self._ready = False
+
+ @property
+ def ready(self):
+ return self._ready
+
+ def setup_langwatch(self):
+ try:
+ import langwatch
+
+ self._client = langwatch
+ except ImportError:
+ logger.error("Could not import langwatch. Please install it with `pip install langwatch`.")
+ return False
+ return True
+
+ def _convert_trace_type(self, trace_type: str):
+ trace_type_: "SpanTypes" = (
+ cast("SpanTypes", trace_type)
+ if trace_type in ["span", "llm", "chain", "tool", "agent", "guardrail", "rag"]
+ else "span"
+ )
+ return trace_type_
+
+ def add_trace(
+ self,
+ trace_id: str,
+ trace_name: str,
+ trace_type: str,
+ inputs: Dict[str, Any],
+ metadata: Dict[str, Any] | None = None,
+ vertex: Optional["Vertex"] = None,
+ ):
+ import nanoid
+
+ # If user is not using session_id, then it becomes the same as flow_id, but
+ # we don't want to have an infinite thread with all the flow messages
+ if "session_id" in inputs and inputs["session_id"] != self.flow_id:
+ self.trace.update(metadata=(self.trace.metadata or {}) | {"thread_id": inputs["session_id"]})
+
+ name_without_id = " (".join(trace_name.split(" (")[0:-1])
+
+ trace_type_ = self._convert_trace_type(trace_type)
+ self.spans[trace_id] = self.trace.span(
+ span_id=f"{trace_id}-{nanoid.generate(size=6)}", # Add a nanoid to make the span_id globally unique, which is required for LangWatch for now
+ name=name_without_id,
+ type=trace_type_,
+ parent=(
+ [span for key, span in self.spans.items() for edge in vertex.incoming_edges if key == edge.source_id][
+ -1
+ ]
+ if vertex and len(vertex.incoming_edges) > 0
+ else self.trace.root_span
+ ),
+ input=self._convert_to_langwatch_types(inputs),
+ )
+
+ if trace_type_ == "llm" and "model_name" in inputs:
+ self.spans[trace_id].update(model=inputs["model_name"])
+
+ def end_trace(
+ self,
+ trace_id: str,
+ trace_name: str,
+ outputs: Dict[str, Any] | None = None,
+ error: Exception | None = None,
+ logs: list[Log | dict] = [],
+ ):
+ if self.spans.get(trace_id):
+ # Workaround for when model is used just as a component not actually called as an LLM,
+ # to prevent LangWatch from calculating the cost based on it when it was in fact never called
+ if (
+ self.spans[trace_id].type == "llm"
+ and outputs
+ and "model_output" in outputs
+ and "text_output" not in outputs
+ ):
+ self.spans[trace_id].update(metrics={"prompt_tokens": 0, "completion_tokens": 0})
+
+ self.spans[trace_id].end(output=self._convert_to_langwatch_types(outputs), error=error)
+
+ def end(
+ self,
+ inputs: dict[str, Any],
+ outputs: Dict[str, Any],
+ error: Exception | None = None,
+ metadata: dict[str, Any] | None = None,
+ ):
+ self.trace.root_span.end(
+ input=self._convert_to_langwatch_types(inputs),
+ output=self._convert_to_langwatch_types(outputs),
+ error=error,
+ )
+
+ if metadata and "flow_name" in metadata:
+ self.trace.update(metadata=(self.trace.metadata or {}) | {"labels": [f"Flow: {metadata['flow_name']}"]})
+ self.trace.deferred_send_spans()
+
+ def _convert_to_langwatch_types(self, io_dict: Optional[Dict[str, Any]]):
+ from langwatch.utils import autoconvert_typed_values
+
+ if io_dict is None:
+ return None
+ converted = {}
+ for key, value in io_dict.items():
+ converted[key] = self._convert_to_langwatch_type(value)
+ return autoconvert_typed_values(converted)
+
+ def _convert_to_langwatch_type(self, value):
+ from langflow.schema.message import Message, BaseMessage
+ from langwatch.langchain import (
+ langchain_messages_to_chat_messages,
+ langchain_message_to_chat_message,
+ )
+
+ if isinstance(value, dict):
+ for key, _value in value.copy().items():
+ _value = self._convert_to_langwatch_type(_value)
+ value[key] = _value
+ elif isinstance(value, list):
+ value = [self._convert_to_langwatch_type(v) for v in value]
+ elif isinstance(value, Message):
+ if "prompt" in value:
+ prompt = value.load_lc_prompt()
+ if len(prompt.input_variables) == 0 and all(isinstance(m, BaseMessage) for m in prompt.messages):
+ value = langchain_messages_to_chat_messages([cast(list[BaseMessage], prompt.messages)])
+ else:
+ value = cast(dict, value.load_lc_prompt())
+ elif value.sender:
+ value = langchain_message_to_chat_message(value.to_lc_message())
+ else:
+ value = cast(dict, value.to_lc_document())
+ elif isinstance(value, Data):
+ value = cast(dict, value.to_lc_document())
+ return value
diff --git a/src/backend/base/poetry.lock b/src/backend/base/poetry.lock
index 5b6a51ca7..d606edd69 100644
--- a/src/backend/base/poetry.lock
+++ b/src/backend/base/poetry.lock
@@ -676,13 +676,13 @@ all = ["pycocotools (==2.0.6)"]
[[package]]
name = "clarifai-grpc"
-version = "10.6.3"
+version = "10.6.4"
description = "Clarifai gRPC API Client"
optional = false
python-versions = ">=3.8"
files = [
- {file = "clarifai_grpc-10.6.3-py3-none-any.whl", hash = "sha256:304a8123dfe6fb41953026e0e4b800bffc3998a75408f51f3ab2a6eacfb1781e"},
- {file = "clarifai_grpc-10.6.3.tar.gz", hash = "sha256:6be24d21f124678384902e693eb9b5d2e5c57aeef57c098e3a2b94e40a79c198"},
+ {file = "clarifai_grpc-10.6.4-py3-none-any.whl", hash = "sha256:9fb8c94e6ede5e1005010643f516aa7c1dd3c59ab9282e03ba4932fd929d7584"},
+ {file = "clarifai_grpc-10.6.4.tar.gz", hash = "sha256:84d92b10fc32c17ecf0c0fc30ec4c9960a6a9ee701f2829f0c372892ae761d14"},
]
[package.dependencies]
@@ -707,13 +707,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "cohere"
-version = "5.5.8"
+version = "5.6.1"
description = ""
optional = false
python-versions = "<4.0,>=3.8"
files = [
- {file = "cohere-5.5.8-py3-none-any.whl", hash = "sha256:e1ed84b90eadd13c6a68ee28e378a0bb955f8945eadc6eb7ee126b3399cafd54"},
- {file = "cohere-5.5.8.tar.gz", hash = "sha256:84ce7666ff8fbdf4f41fb5f6ca452ab2639a514bc88967a2854a9b1b820d6ea0"},
+ {file = "cohere-5.6.1-py3-none-any.whl", hash = "sha256:1c8bcd39a54622d64b83cafb865f102cd2565ce091b0856fd5ce11bf7169109a"},
+ {file = "cohere-5.6.1.tar.gz", hash = "sha256:5d7efda64f0e512d4cc35aa04b17a6f74b3d8c175a99f2797991a7f31dfac349"},
]
[package.dependencies]
@@ -767,6 +767,17 @@ files = [
{file = "contextlib2-21.6.0.tar.gz", hash = "sha256:ab1e2bfe1d01d968e1b7e8d9023bc51ef3509bba217bb730cee3827e1ee82869"},
]
+[[package]]
+name = "coolname"
+version = "2.2.0"
+description = "Random name and slug generator"
+optional = false
+python-versions = "*"
+files = [
+ {file = "coolname-2.2.0-py2.py3-none-any.whl", hash = "sha256:4d1563186cfaf71b394d5df4c744f8c41303b6846413645e31d31915cdeb13e8"},
+ {file = "coolname-2.2.0.tar.gz", hash = "sha256:6c5d5731759104479e7ca195a9b64f7900ac5bead40183c09323c7d0be9e75c7"},
+]
+
[[package]]
name = "crewai"
version = "0.36.1"
@@ -866,6 +877,17 @@ files = [
marshmallow = ">=3.18.0,<4.0.0"
typing-inspect = ">=0.4.0,<1"
+[[package]]
+name = "decorator"
+version = "5.1.1"
+description = "Decorators for Humans"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
+ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
+]
+
[[package]]
name = "deprecated"
version = "1.2.14"
@@ -1999,13 +2021,13 @@ files = [
[[package]]
name = "huggingface-hub"
-version = "0.23.4"
+version = "0.23.5"
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
optional = false
python-versions = ">=3.8.0"
files = [
- {file = "huggingface_hub-0.23.4-py3-none-any.whl", hash = "sha256:3a0b957aa87150addf0cc7bd71b4d954b78e749850e1e7fb29ebbd2db64ca037"},
- {file = "huggingface_hub-0.23.4.tar.gz", hash = "sha256:35d99016433900e44ae7efe1c209164a5a81dbbcd53a52f99c281dcd7ce22431"},
+ {file = "huggingface_hub-0.23.5-py3-none-any.whl", hash = "sha256:d7a7d337615e11a45cc14a0ce5a605db6b038dc24af42866f731684825226e90"},
+ {file = "huggingface_hub-0.23.5.tar.gz", hash = "sha256:67a9caba79b71235be3752852ca27da86bd54311d2424ca8afdb8dda056edf98"},
]
[package.dependencies]
@@ -2552,13 +2574,13 @@ types-requests = ">=2.31.0.2,<3.0.0.0"
[[package]]
name = "langsmith"
-version = "0.1.85"
+version = "0.1.86"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
optional = false
python-versions = "<4.0,>=3.8.1"
files = [
- {file = "langsmith-0.1.85-py3-none-any.whl", hash = "sha256:c1f94384f10cea96f7b4d33fd3db7ec180c03c7468877d50846f881d2017ff94"},
- {file = "langsmith-0.1.85.tar.gz", hash = "sha256:acff31f9e53efa48586cf8e32f65625a335c74d7c4fa306d1655ac18452296f6"},
+ {file = "langsmith-0.1.86-py3-none-any.whl", hash = "sha256:55ed80cc6e98f9761f9b3ec3c49e01f6745d13e40bef80d9f831acabfd9a8a1e"},
+ {file = "langsmith-0.1.86.tar.gz", hash = "sha256:2e66577817253327b99b727588c3173fbba217fe0ca07ac6b7cdd23fc4894104"},
]
[package.dependencies]
@@ -2569,6 +2591,34 @@ pydantic = [
]
requests = ">=2,<3"
+[[package]]
+name = "langwatch"
+version = "0.1.8"
+description = "Python SDK for LangWatch for monitoring your LLMs"
+optional = false
+python-versions = "<4.0,>=3.9"
+files = [
+ {file = "langwatch-0.1.8-py3-none-any.whl", hash = "sha256:e6e7ffe2f3cd61c477e8ff6de4ad3d1e06f63b0c8f02880d68293fc126ec2bf7"},
+ {file = "langwatch-0.1.8.tar.gz", hash = "sha256:2ccc3a741ef9bf493946264ab8fff5cb33845e51d4426136218d62b1a4cbd26d"},
+]
+
+[package.dependencies]
+coolname = ">=2.2.0,<3.0.0"
+deprecated = ">=1.2.14,<2.0.0"
+httpx = ">=0.27.0,<0.28.0"
+nanoid = ">=2.0.0,<3.0.0"
+pandas = ">=2.2.2,<3.0.0"
+pydantic = ">=2.5.2"
+requests = ">=2.31.0,<3.0.0"
+retry = ">=0.9.2,<0.10.0"
+tqdm = ">=4.66.2,<5.0.0"
+
+[package.extras]
+dspy = ["dspy-ai (>=2.4.12,<3.0.0)"]
+langchain = ["langchain (>=0.2.0,<0.3.0)"]
+litellm = ["litellm (>=1.40.15,<2.0.0)"]
+openai = ["openai (>=1.3.7,<2.0.0)"]
+
[[package]]
name = "loguru"
version = "0.7.2"
@@ -3157,6 +3207,17 @@ files = [
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
]
+[[package]]
+name = "nanoid"
+version = "2.0.0"
+description = "A tiny, secure, URL-friendly, unique string ID generator for Python"
+optional = false
+python-versions = "*"
+files = [
+ {file = "nanoid-2.0.0-py3-none-any.whl", hash = "sha256:90aefa650e328cffb0893bbd4c236cfd44c48bc1f2d0b525ecc53c3187b653bb"},
+ {file = "nanoid-2.0.0.tar.gz", hash = "sha256:5a80cad5e9c6e9ae3a41fa2fb34ae189f7cb420b2a5d8f82bd9d23466e4efa68"},
+]
+
[[package]]
name = "nest-asyncio"
version = "1.6.0"
@@ -3273,13 +3334,13 @@ sympy = "*"
[[package]]
name = "openai"
-version = "1.35.13"
+version = "1.35.14"
description = "The official Python library for the openai API"
optional = false
python-versions = ">=3.7.1"
files = [
- {file = "openai-1.35.13-py3-none-any.whl", hash = "sha256:36ec3e93e0d1f243f69be85c89b9221a471c3e450dfd9df16c9829e3cdf63e60"},
- {file = "openai-1.35.13.tar.gz", hash = "sha256:c684f3945608baf7d2dcc0ef3ee6f3e27e4c66f21076df0b47be45d57e6ae6e4"},
+ {file = "openai-1.35.14-py3-none-any.whl", hash = "sha256:adadf8c176e0b8c47ad782ed45dc20ef46438ee1f02c7103c4155cff79c8f68b"},
+ {file = "openai-1.35.14.tar.gz", hash = "sha256:394ba1dfd12ecec1d634c50e512d24ff1858bbc2674ffcce309b822785a058de"},
]
[package.dependencies]
@@ -3576,47 +3637,47 @@ files = [
[[package]]
name = "pandas"
-version = "2.2.0"
+version = "2.2.2"
description = "Powerful data structures for data analysis, time series, and statistics"
optional = false
python-versions = ">=3.9"
files = [
- {file = "pandas-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8108ee1712bb4fa2c16981fba7e68b3f6ea330277f5ca34fa8d557e986a11670"},
- {file = "pandas-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:736da9ad4033aeab51d067fc3bd69a0ba36f5a60f66a527b3d72e2030e63280a"},
- {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e0b4fc3ddceb56ec8a287313bc22abe17ab0eb184069f08fc6a9352a769b18"},
- {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20404d2adefe92aed3b38da41d0847a143a09be982a31b85bc7dd565bdba0f4e"},
- {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ea3ee3f125032bfcade3a4cf85131ed064b4f8dd23e5ce6fa16473e48ebcaf5"},
- {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1"},
- {file = "pandas-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a946f210383c7e6d16312d30b238fd508d80d927014f3b33fb5b15c2f895430"},
- {file = "pandas-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a1b438fa26b208005c997e78672f1aa8138f67002e833312e6230f3e57fa87d5"},
- {file = "pandas-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ce2fbc8d9bf303ce54a476116165220a1fedf15985b09656b4b4275300e920b"},
- {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2707514a7bec41a4ab81f2ccce8b382961a29fbe9492eab1305bb075b2b1ff4f"},
- {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85793cbdc2d5bc32620dc8ffa715423f0c680dacacf55056ba13454a5be5de88"},
- {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfd6c2491dc821b10c716ad6776e7ab311f7df5d16038d0b7458bc0b67dc10f3"},
- {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a146b9dcacc3123aa2b399df1a284de5f46287a4ab4fbfc237eac98a92ebcb71"},
- {file = "pandas-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9"},
- {file = "pandas-2.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a41d06f308a024981dcaa6c41f2f2be46a6b186b902c94c2674e8cb5c42985bc"},
- {file = "pandas-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:159205c99d7a5ce89ecfc37cb08ed179de7783737cea403b295b5eda8e9c56d1"},
- {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1e1f3861ea9132b32f2133788f3b14911b68102d562715d71bd0013bc45440"},
- {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:761cb99b42a69005dec2b08854fb1d4888fdf7b05db23a8c5a099e4b886a2106"},
- {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a20628faaf444da122b2a64b1e5360cde100ee6283ae8effa0d8745153809a2e"},
- {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f5be5d03ea2073627e7111f61b9f1f0d9625dc3c4d8dda72cc827b0c58a1d042"},
- {file = "pandas-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a626795722d893ed6aacb64d2401d017ddc8a2341b49e0384ab9bf7112bdec30"},
- {file = "pandas-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f66419d4a41132eb7e9a73dcec9486cf5019f52d90dd35547af11bc58f8637d"},
- {file = "pandas-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57abcaeda83fb80d447f28ab0cc7b32b13978f6f733875ebd1ed14f8fbc0f4ab"},
- {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60f1f7dba3c2d5ca159e18c46a34e7ca7247a73b5dd1a22b6d59707ed6b899a"},
- {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb61dc8567b798b969bcc1fc964788f5a68214d333cade8319c7ab33e2b5d88a"},
- {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:52826b5f4ed658fa2b729264d63f6732b8b29949c7fd234510d57c61dbeadfcd"},
- {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bde2bc699dbd80d7bc7f9cab1e23a95c4375de615860ca089f34e7c64f4a8de7"},
- {file = "pandas-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:3de918a754bbf2da2381e8a3dcc45eede8cd7775b047b923f9006d5f876802ae"},
- {file = "pandas-2.2.0.tar.gz", hash = "sha256:30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2"},
+ {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"},
+ {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"},
+ {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"},
+ {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"},
+ {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"},
+ {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"},
+ {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"},
+ {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"},
+ {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"},
+ {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"},
+ {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"},
+ {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"},
+ {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"},
+ {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"},
+ {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"},
+ {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"},
+ {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"},
+ {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"},
+ {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"},
+ {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"},
+ {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"},
+ {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"},
+ {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"},
+ {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"},
+ {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"},
+ {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"},
+ {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"},
+ {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"},
+ {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"},
]
[package.dependencies]
numpy = [
- {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""},
- {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""},
- {version = ">=1.26.0,<2", 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"
@@ -3641,6 +3702,7 @@ parquet = ["pyarrow (>=10.0.1)"]
performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"]
plot = ["matplotlib (>=3.6.3)"]
postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"]
+pyarrow = ["pyarrow (>=10.0.1)"]
spss = ["pyreadstat (>=1.2.0)"]
sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"]
test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
@@ -3954,6 +4016,17 @@ all = ["apache-bookkeeper-client (>=4.16.1)", "fastavro (>=1.9.2)", "grpcio (>=1
avro = ["fastavro (>=1.9.2)"]
functions = ["apache-bookkeeper-client (>=4.16.1)", "grpcio (>=1.60.0)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+
[[package]]
name = "pyasn1"
version = "0.6.0"
@@ -4624,6 +4697,21 @@ requests = ">=2.0.0"
[package.extras]
rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
+[[package]]
+name = "retry"
+version = "0.9.2"
+description = "Easy to use retry decorator."
+optional = false
+python-versions = "*"
+files = [
+ {file = "retry-0.9.2-py2.py3-none-any.whl", hash = "sha256:ccddf89761fa2c726ab29391837d4327f819ea14d244c232a1d24c67a2f98606"},
+ {file = "retry-0.9.2.tar.gz", hash = "sha256:f8bfa8b99b69c4506d6f5bd3b0aabf77f98cdb17f3c9fc3f5ca820033336fba4"},
+]
+
+[package.dependencies]
+decorator = ">=3.4.2"
+py = ">=1.4.26,<2.0.0"
+
[[package]]
name = "rich"
version = "13.7.1"
@@ -5822,4 +5910,4 @@ local = []
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<3.13"
-content-hash = "3bae2ded5bb5a16aadb39c90e5e8d5e4ef072c0b112fd62f5f95efabbfbc594d"
+content-hash = "8e59c93824c2f9ddeb114af3bc07e0a8ab351d1fa19c20c40ca8d110face8452"
diff --git a/src/backend/base/pyproject.toml b/src/backend/base/pyproject.toml
index 88d1a870e..9653415e6 100644
--- a/src/backend/base/pyproject.toml
+++ b/src/backend/base/pyproject.toml
@@ -51,7 +51,7 @@ bcrypt = "4.0.1"
pillow = "^10.2.0"
docstring-parser = "^0.16"
python-jose = "^3.3.0"
-pandas = "2.2.0"
+pandas = "2.2.2"
multiprocess = "^0.70.14"
duckdb = "^1.0.0"
python-docx = "^1.1.0"
@@ -73,6 +73,7 @@ prometheus-client = "^0.20.0"
aiofiles = "^24.1.0"
crewai = "^0.36.0"
setuptools = ">=70"
+langwatch = "^0.1.3"
[tool.poetry.extras]
deploy = ["celery", "redis", "flower"]