From d71718060734354ea21528e887711342635c457e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 14:12:57 -0700 Subject: [PATCH 01/19] Bump @babel/traverse from 7.22.4 to 7.23.2 in /js (#256) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.4 to 7.23.2.
Release notes

Sourced from @​babel/traverse's releases.

v7.23.2 (2023-10-11)

NOTE: This release also re-publishes @babel/core, even if it does not appear in the linked release commit.

Thanks @​jimmydief for your first PR!

:bug: Bug Fix

Committers: 5

v7.23.1 (2023-09-25)

Re-publishing @babel/helpers due to a publishing error in 7.23.0.

v7.23.0 (2023-09-25)

Thanks @​lorenzoferre and @​RajShukla1 for your first PRs!

:rocket: New Feature

... (truncated)

Changelog

Sourced from @​babel/traverse's changelog.

v7.23.2 (2023-10-11)

:bug: Bug Fix

v7.23.0 (2023-09-25)

:rocket: New Feature

:bug: Bug Fix

:nail_care: Polish

:microscope: Output optimization

v7.22.20 (2023-09-16)

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@babel/traverse&package-manager=npm_and_yarn&previous-version=7.22.4&new-version=7.23.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/langchain-ai/langsmith-sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- js/yarn.lock | 117 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/js/yarn.lock b/js/yarn.lock index c12183e82..8a4570e88 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -31,6 +31,14 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.22.0", "@babel/compat-data@^7.22.3": version "7.22.3" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz" @@ -57,7 +65,7 @@ json5 "^2.2.2" semver "^6.3.0" -"@babel/generator@^7.22.0", "@babel/generator@^7.22.3", "@babel/generator@^7.7.2": +"@babel/generator@^7.22.0", "@babel/generator@^7.7.2": version "7.22.3" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz" integrity sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A== @@ -67,6 +75,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" @@ -133,6 +151,11 @@ resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz" integrity sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA== +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0": version "7.21.0" resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz" @@ -141,6 +164,14 @@ "@babel/template" "^7.20.7" "@babel/types" "^7.21.0" +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" @@ -148,6 +179,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-member-expression-to-functions@^7.22.0": version "7.22.3" resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.3.tgz" @@ -231,16 +269,33 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-string-parser@^7.21.5": version "7.21.5" resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz" integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w== +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-option@^7.21.0": version "7.21.0" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz" @@ -274,11 +329,25 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.9", "@babel/parser@^7.22.0", "@babel/parser@^7.22.4": +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.9", "@babel/parser@^7.22.0": version "7.22.4" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz" integrity sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA== +"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" @@ -967,19 +1036,28 @@ "@babel/parser" "^7.21.9" "@babel/types" "^7.21.5" -"@babel/traverse@^7.20.5", "@babel/traverse@^7.22.1", "@babel/traverse@^7.7.2": - version "7.22.4" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.4.tgz" - integrity sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ== +"@babel/template@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== dependencies: - "@babel/code-frame" "^7.21.4" - "@babel/generator" "^7.22.3" - "@babel/helper-environment-visitor" "^7.22.1" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.22.4" - "@babel/types" "^7.22.4" + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.20.5", "@babel/traverse@^7.22.1", "@babel/traverse@^7.7.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" debug "^4.1.0" globals "^11.1.0" @@ -992,6 +1070,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" @@ -1919,7 +2006,7 @@ caniuse-lite@^1.0.30001489: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001491.tgz" integrity sha512-17EYIi4TLnPiTzVKMveIxU5ETlxbSO3B6iPvMbprqnKh4qJsQGk5Nh1Lp4jIMAE0XfrujsJuWZAM3oJdMHaKBA== -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== From 142120aabdf7b3d79794ab506d6a1f7a27e3ac67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 14:13:18 -0700 Subject: [PATCH 02/19] Bump zod from 3.22.2 to 3.22.4 in /js (#257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [zod](https://github.com/colinhacks/zod) from 3.22.2 to 3.22.4.
Release notes

Sourced from zod's releases.

v3.22.4

Commits:

  • d931ea3f0f15a6ae64f5f68e3c03912dffb2269d Lint
  • 8e634bd600093b7161487bed705279c892395118 Fix prettier
  • 4018d88f0e94992b2987428c4fda387b99ae2a53 docs: add @​sanity-typed/zod to ecosystem (#2731)
  • 15ba5a4d4cb5be5af23771de0ba1346b4ba20a0e docs: add zod-sandbox to README ecosystem links (#2707)
  • 699ccae13b875d4fcadac268fd789c93b6ce8aef Export jsdoc with @deprecated when building (#2717)
  • dfe3719eae250ab3eca2d276da6c292867899cc6 Fix sanity-typed links (#2840)
  • cd7991e04a550868bfcb5b5d46e5eb5bc7edf5f3 fix ulid regex (#2225)
  • 7cb4ba2f85dd6b28290dda5de80ed54dfd2a793c Remove stalebot
  • 9340fd51e48576a75adc919bff65dbc4a5d4c99b Lazy emojiRegex
  • e7a9b9b3033991be6b4225f1be21da39c250bbb0 3.22.4

v3.22.3

Commits:

  • 1e23990bcdd33d1e81b31e40e77a031fcfd87ce1 Commit
  • 9bd3879b482f139fd03d5025813ee66a04195cdd docs: remove obsolete text about readonly types (#2676)
  • f59be093ec21430d9f32bbcb628d7e39116adf34 clarify datetime ISO 8601 (#2673)
  • 64dcc8e2b16febe48fa8e3c82c47c92643e6c9e3 Update sponsors
  • 18115a8f128680b4526df58ce96deab7dce93b93 Formatting
  • 28c19273658b164c53c149785fa7a8187c428ad4 Update sponsors
  • ad2ee9ccf723c4388158ff6b8669c2a6cdc85643 2718 Updated Custom Schemas documentation example to use type narrowing (#2778)
  • ae0f7a2c15e7741ee1b23c03a3bfb9acebd86551 docs: update ref to discriminated-unions docs (#2485)
  • 2ba00fe2377f4d53947a84b8cdb314a63bbd6dd4 [2609] fix ReDoS vulnerability in email regex (#2824)
  • 1e61d76cdec05de9271fc0df58798ddf9ce94923 3.22.3
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=zod&package-manager=npm_and_yarn&previous-version=3.22.2&new-version=3.22.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/langchain-ai/langsmith-sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- js/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/yarn.lock b/js/yarn.lock index 8a4570e88..ba8acc011 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -4728,6 +4728,6 @@ zod-to-json-schema@^3.20.4: integrity sha512-fjUZh4nQ1s6HMccgIeE0VP4QG/YRGPmyjO9sAh890aQKPEk3nqbfUXhMFaC+Dr5KvYBm8BCyvfpZf2jY9aGSsw== zod@^3.21.4: - version "3.22.2" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.2.tgz#3add8c682b7077c05ac6f979fea6998b573e157b" - integrity sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg== + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== From 2572ebd346a88f4c1e95de51b2e4866c185acfdf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 14:14:41 -0700 Subject: [PATCH 03/19] Bump urllib3 from 2.0.2 to 2.0.7 in /python (#258) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.2 to 2.0.7.
Release notes

Sourced from urllib3's releases.

2.0.7

  • Made body stripped from HTTP requests changing the request method to GET after HTTP 303 "See Other" redirect responses. (GHSA-g4mx-q9vg-27p4)

2.0.6

  • Added the Cookie header to the list of headers to strip from requests when redirecting to a different host. As before, different headers can be set via Retry.remove_headers_on_redirect. (GHSA-v845-jxx5-vc9f)

2.0.5

  • Allowed pyOpenSSL third-party module without any deprecation warning. #3126
  • Fixed default blocksize of HTTPConnection classes to match high-level classes. Previously was 8KiB, now 16KiB. #3066

2.0.4

  • Added support for union operators to HTTPHeaderDict (#2254)
  • Added BaseHTTPResponse to urllib3.__all__ (#3078)
  • Fixed urllib3.connection.HTTPConnection to raise the http.client.connect audit event to have the same behavior as the standard library HTTP client (#2757)
  • Relied on the standard library for checking hostnames in supported PyPy releases (#3087)

2.0.3

  • Allowed alternative SSL libraries such as LibreSSL, while still issuing a warning as we cannot help users facing issues with implementations other than OpenSSL. #3020
  • Deprecated URLs which don't have an explicit scheme #2950
  • Fixed response decoding with Zstandard when compressed data is made of several frames. #3008
  • Fixed assert_hostname=False to correctly skip hostname check. #3051
Changelog

Sourced from urllib3's changelog.

2.0.7 (2023-10-17)

  • Made body stripped from HTTP requests changing the request method to GET after HTTP 303 "See Other" redirect responses.

2.0.6 (2023-10-02)

  • Added the Cookie header to the list of headers to strip from requests when redirecting to a different host. As before, different headers can be set via Retry.remove_headers_on_redirect.

2.0.5 (2023-09-20)

  • Allowed pyOpenSSL third-party module without any deprecation warning. ([#3126](https://github.com/urllib3/urllib3/issues/3126) <https://github.com/urllib3/urllib3/issues/3126>__)
  • Fixed default blocksize of HTTPConnection classes to match high-level classes. Previously was 8KiB, now 16KiB. ([#3066](https://github.com/urllib3/urllib3/issues/3066) <https://github.com/urllib3/urllib3/issues/3066>__)

2.0.4 (2023-07-19)

  • Added support for union operators to HTTPHeaderDict ([#2254](https://github.com/urllib3/urllib3/issues/2254) <https://github.com/urllib3/urllib3/issues/2254>__)
  • Added BaseHTTPResponse to urllib3.__all__ ([#3078](https://github.com/urllib3/urllib3/issues/3078) <https://github.com/urllib3/urllib3/issues/3078>__)
  • Fixed urllib3.connection.HTTPConnection to raise the http.client.connect audit event to have the same behavior as the standard library HTTP client ([#2757](https://github.com/urllib3/urllib3/issues/2757) <https://github.com/urllib3/urllib3/issues/2757>__)
  • Relied on the standard library for checking hostnames in supported PyPy releases ([#3087](https://github.com/urllib3/urllib3/issues/3087) <https://github.com/urllib3/urllib3/issues/3087>__)

2.0.3 (2023-06-07)

  • Allowed alternative SSL libraries such as LibreSSL, while still issuing a warning as we cannot help users facing issues with implementations other than OpenSSL. ([#3020](https://github.com/urllib3/urllib3/issues/3020) <https://github.com/urllib3/urllib3/issues/3020>__)
  • Deprecated URLs which don't have an explicit scheme ([#2950](https://github.com/urllib3/urllib3/issues/2950) <https://github.com/urllib3/urllib3/pull/2950>_)
  • Fixed response decoding with Zstandard when compressed data is made of several frames. ([#3008](https://github.com/urllib3/urllib3/issues/3008) <https://github.com/urllib3/urllib3/issues/3008>__)
  • Fixed assert_hostname=False to correctly skip hostname check. ([#3051](https://github.com/urllib3/urllib3/issues/3051) <https://github.com/urllib3/urllib3/issues/3051>__)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=pip&previous-version=2.0.2&new-version=2.0.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/langchain-ai/langsmith-sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: William FH <13333726+hinthornw@users.noreply.github.com> --- python/poetry.lock | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/python/poetry.lock b/python/poetry.lock index d84a98ce8..c96f612e9 100644 --- a/python/poetry.lock +++ b/python/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -449,6 +449,7 @@ files = [ {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, + {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d967650d3f56af314b72df7089d96cda1083a7fc2da05b375d2bc48c82ab3f3c"}, {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, @@ -457,6 +458,7 @@ files = [ {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, + {file = "greenlet-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d4606a527e30548153be1a9f155f4e283d109ffba663a15856089fb55f933e47"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, @@ -486,6 +488,7 @@ files = [ {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, + {file = "greenlet-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1087300cf9700bbf455b1b97e24db18f2f77b55302a68272c56209d5587c12d1"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, @@ -494,6 +497,7 @@ files = [ {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, + {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8512a0c38cfd4e66a858ddd1b17705587900dd760c6003998e9472b77b56d417"}, {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, @@ -1033,6 +1037,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1040,8 +1045,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1058,6 +1070,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1065,6 +1078,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -1179,7 +1193,7 @@ files = [ ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} typing-extensions = ">=4.2.0" [package.extras] @@ -1317,13 +1331,13 @@ typing-extensions = ">=3.7.4" [[package]] name = "urllib3" -version = "2.0.2" +version = "2.0.7" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, - {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, ] [package.extras] From 81100a2711fa7464646e477dd5b9abac930e0c90 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Fri, 20 Oct 2023 06:16:02 +0900 Subject: [PATCH 04/19] Bump dev dep (#259) --- python/poetry.lock | 134 +++++++++++++++++++++--------------------- python/pyproject.toml | 2 +- 2 files changed, 69 insertions(+), 67 deletions(-) diff --git a/python/poetry.lock b/python/poetry.lock index c96f612e9..55723cfca 100644 --- a/python/poetry.lock +++ b/python/poetry.lock @@ -122,6 +122,27 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "anyio" +version = "3.7.1" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, +] + +[package.dependencies] +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] + [[package]] name = "async-timeout" version = "4.0.2" @@ -449,7 +470,6 @@ files = [ {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, - {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d967650d3f56af314b72df7089d96cda1083a7fc2da05b375d2bc48c82ab3f3c"}, {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, @@ -458,7 +478,6 @@ files = [ {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, - {file = "greenlet-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d4606a527e30548153be1a9f155f4e283d109ffba663a15856089fb55f933e47"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, @@ -488,7 +507,6 @@ files = [ {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, - {file = "greenlet-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1087300cf9700bbf455b1b97e24db18f2f77b55302a68272c56209d5587c12d1"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, @@ -497,7 +515,6 @@ files = [ {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, - {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8512a0c38cfd4e66a858ddd1b17705587900dd760c6003998e9472b77b56d417"}, {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, @@ -536,23 +553,48 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "jsonpatch" +version = "1.33" +description = "Apply JSON-Patches (RFC 6902)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, + {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, +] + +[package.dependencies] +jsonpointer = ">=1.9" + +[[package]] +name = "jsonpointer" +version = "2.4" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, +] + [[package]] name = "langchain" -version = "0.0.295" +version = "0.0.319" description = "Building applications with LLMs through composability" optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langchain-0.0.295-py3-none-any.whl", hash = "sha256:eb7fad53c2af68771369dfb6d1242b38ab413994491d9b9a49027aafeb22220a"}, - {file = "langchain-0.0.295.tar.gz", hash = "sha256:e91d2df38bbbecc513b6c6e22090371862450ec8dba22fa9433e2ac71dba106b"}, + {file = "langchain-0.0.319-py3-none-any.whl", hash = "sha256:a61448fd418ff9478f2be3477c9c92acbf6b6acd8163c58c994a6158d4d116f8"}, + {file = "langchain-0.0.319.tar.gz", hash = "sha256:4fe5025e5fd48dcf8e02107fefe173ba997af3c8960871cc4a4467e24bb89375"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" +anyio = "<4.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -dataclasses-json = ">=0.5.7,<0.6.0" -langsmith = ">=0.0.38,<0.1.0" -numexpr = ">=2.8.4,<3.0.0" +dataclasses-json = ">=0.5.7,<0.7" +jsonpatch = ">=1.33,<2.0" +langsmith = ">=0.0.43,<0.1.0" numpy = ">=1,<2" pydantic = ">=1,<3" PyYAML = ">=5.3" @@ -561,16 +603,17 @@ SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" [package.extras] -all = ["O365 (>=2.0.26,<3.0.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "amadeus (>=8.1.0)", "arxiv (>=1.4,<2.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "awadb (>=0.3.9,<0.4.0)", "azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "beautifulsoup4 (>=4,<5)", "clarifai (>=9.1.0)", "clickhouse-connect (>=0.5.14,<0.6.0)", "cohere (>=4,<5)", "deeplake (>=3.6.8,<4.0.0)", "docarray[hnswlib] (>=0.32.0,<0.33.0)", "duckduckgo-search (>=3.8.3,<4.0.0)", "elasticsearch (>=8,<9)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "google-api-python-client (==2.70.0)", "google-auth (>=2.18.1,<3.0.0)", "google-search-results (>=2,<3)", "gptcache (>=0.1.7)", "html2text (>=2020.1.16,<2021.0.0)", "huggingface_hub (>=0,<1)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lancedb (>=0.1,<0.2)", "langkit (>=0.0.6,<0.1.0)", "lark (>=1.1.5,<2.0.0)", "libdeeplake (>=0.0.60,<0.0.61)", "librosa (>=0.10.0.post2,<0.11.0)", "lxml (>=4.9.2,<5.0.0)", "manifest-ml (>=0.0.1,<0.0.2)", "marqo (>=1.2.4,<2.0.0)", "momento (>=1.5.0,<2.0.0)", "nebula3-python (>=3.4.0,<4.0.0)", "neo4j (>=5.8.1,<6.0.0)", "networkx (>=2.6.3,<3.0.0)", "nlpcloud (>=1,<2)", "nltk (>=3,<4)", "nomic (>=1.0.43,<2.0.0)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "opensearch-py (>=2.0.0,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pexpect (>=4.8.0,<5.0.0)", "pgvector (>=0.1.6,<0.2.0)", "pinecone-client (>=2,<3)", "pinecone-text (>=0.4.2,<0.5.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pymongo (>=4.3.3,<5.0.0)", "pyowm (>=3.3.0,<4.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pytesseract (>=0.3.10,<0.4.0)", "python-arango (>=7.5.9,<8.0.0)", "pyvespa (>=0.33.0,<0.34.0)", "qdrant-client (>=1.3.1,<2.0.0)", "rdflib (>=6.3.2,<7.0.0)", "redis (>=4,<5)", "requests-toolbelt (>=1.0.0,<2.0.0)", "sentence-transformers (>=2,<3)", "singlestoredb (>=0.7.1,<0.8.0)", "tensorflow-text (>=2.11.0,<3.0.0)", "tigrisdb (>=1.0.0b6,<2.0.0)", "tiktoken (>=0.3.2,<0.4.0)", "torch (>=1,<3)", "transformers (>=4,<5)", "weaviate-client (>=3,<4)", "wikipedia (>=1,<2)", "wolframalpha (==5.0.0)"] +all = ["O365 (>=2.0.26,<3.0.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "amadeus (>=8.1.0)", "arxiv (>=1.4,<2.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "awadb (>=0.3.9,<0.4.0)", "azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "beautifulsoup4 (>=4,<5)", "clarifai (>=9.1.0)", "clickhouse-connect (>=0.5.14,<0.6.0)", "cohere (>=4,<5)", "deeplake (>=3.6.8,<4.0.0)", "docarray[hnswlib] (>=0.32.0,<0.33.0)", "duckduckgo-search (>=3.8.3,<4.0.0)", "elasticsearch (>=8,<9)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "google-api-python-client (==2.70.0)", "google-auth (>=2.18.1,<3.0.0)", "google-search-results (>=2,<3)", "gptcache (>=0.1.7)", "html2text (>=2020.1.16,<2021.0.0)", "huggingface_hub (>=0,<1)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lancedb (>=0.1,<0.2)", "langkit (>=0.0.6,<0.1.0)", "lark (>=1.1.5,<2.0.0)", "libdeeplake (>=0.0.60,<0.0.61)", "librosa (>=0.10.0.post2,<0.11.0)", "lxml (>=4.9.2,<5.0.0)", "manifest-ml (>=0.0.1,<0.0.2)", "marqo (>=1.2.4,<2.0.0)", "momento (>=1.10.1,<2.0.0)", "nebula3-python (>=3.4.0,<4.0.0)", "neo4j (>=5.8.1,<6.0.0)", "networkx (>=2.6.3,<4)", "nlpcloud (>=1,<2)", "nltk (>=3,<4)", "nomic (>=1.0.43,<2.0.0)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "opensearch-py (>=2.0.0,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pexpect (>=4.8.0,<5.0.0)", "pgvector (>=0.1.6,<0.2.0)", "pinecone-client (>=2,<3)", "pinecone-text (>=0.4.2,<0.5.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pymongo (>=4.3.3,<5.0.0)", "pyowm (>=3.3.0,<4.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pytesseract (>=0.3.10,<0.4.0)", "python-arango (>=7.5.9,<8.0.0)", "pyvespa (>=0.33.0,<0.34.0)", "qdrant-client (>=1.3.1,<2.0.0)", "rdflib (>=6.3.2,<7.0.0)", "redis (>=4,<5)", "requests-toolbelt (>=1.0.0,<2.0.0)", "sentence-transformers (>=2,<3)", "singlestoredb (>=0.7.1,<0.8.0)", "tensorflow-text (>=2.11.0,<3.0.0)", "tigrisdb (>=1.0.0b6,<2.0.0)", "tiktoken (>=0.3.2,<0.6.0)", "torch (>=1,<3)", "transformers (>=4,<5)", "weaviate-client (>=3,<4)", "wikipedia (>=1,<2)", "wolframalpha (==5.0.0)"] azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (>=0,<1)"] clarifai = ["clarifai (>=9.1.0)"] +cli = ["typer (>=0.9.0,<0.10.0)"] cohere = ["cohere (>=4,<5)"] docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["amazon-textract-caller (<2)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "dashvector (>=1.0.1,<2.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "gql (>=3.4.1,<4.0.0)", "html2text (>=2020.1.16,<2021.0.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "openai (>=0,<1)", "openapi-schema-pydantic (>=1.2,<2.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tqdm (>=4.48.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "amazon-textract-caller (<2)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "dashvector (>=1.0.1,<2.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "gql (>=3.4.1,<4.0.0)", "html2text (>=2020.1.16,<2021.0.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (>=0,<1)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] javascript = ["esprima (>=4.0.1,<5.0.0)"] llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (>=0,<1)", "tiktoken (>=0.3.2,<0.4.0)"] +openai = ["openai (>=0,<1)", "tiktoken (>=0.3.2,<0.6.0)"] qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] @@ -748,48 +791,6 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -[[package]] -name = "numexpr" -version = "2.8.4" -description = "Fast numerical expression evaluator for NumPy" -optional = false -python-versions = ">=3.7" -files = [ - {file = "numexpr-2.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a75967d46b6bd56455dd32da6285e5ffabe155d0ee61eef685bbfb8dafb2e484"}, - {file = "numexpr-2.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db93cf1842f068247de631bfc8af20118bf1f9447cd929b531595a5e0efc9346"}, - {file = "numexpr-2.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bca95f4473b444428061d4cda8e59ac564dc7dc6a1dea3015af9805c6bc2946"}, - {file = "numexpr-2.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e34931089a6bafc77aaae21f37ad6594b98aa1085bb8b45d5b3cd038c3c17d9"}, - {file = "numexpr-2.8.4-cp310-cp310-win32.whl", hash = "sha256:f3a920bfac2645017110b87ddbe364c9c7a742870a4d2f6120b8786c25dc6db3"}, - {file = "numexpr-2.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:6931b1e9d4f629f43c14b21d44f3f77997298bea43790cfcdb4dd98804f90783"}, - {file = "numexpr-2.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9400781553541f414f82eac056f2b4c965373650df9694286b9bd7e8d413f8d8"}, - {file = "numexpr-2.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ee9db7598dd4001138b482342b96d78110dd77cefc051ec75af3295604dde6a"}, - {file = "numexpr-2.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff5835e8af9a212e8480003d731aad1727aaea909926fd009e8ae6a1cba7f141"}, - {file = "numexpr-2.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:655d84eb09adfee3c09ecf4a89a512225da153fdb7de13c447404b7d0523a9a7"}, - {file = "numexpr-2.8.4-cp311-cp311-win32.whl", hash = "sha256:5538b30199bfc68886d2be18fcef3abd11d9271767a7a69ff3688defe782800a"}, - {file = "numexpr-2.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:3f039321d1c17962c33079987b675fb251b273dbec0f51aac0934e932446ccc3"}, - {file = "numexpr-2.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c867cc36cf815a3ec9122029874e00d8fbcef65035c4a5901e9b120dd5d626a2"}, - {file = "numexpr-2.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:059546e8f6283ccdb47c683101a890844f667fa6d56258d48ae2ecf1b3875957"}, - {file = "numexpr-2.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:845a6aa0ed3e2a53239b89c1ebfa8cf052d3cc6e053c72805e8153300078c0b1"}, - {file = "numexpr-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:a38664e699526cb1687aefd9069e2b5b9387da7feac4545de446141f1ef86f46"}, - {file = "numexpr-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eaec59e9bf70ff05615c34a8b8d6c7bd042bd9f55465d7b495ea5436f45319d0"}, - {file = "numexpr-2.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b318541bf3d8326682ebada087ba0050549a16d8b3fa260dd2585d73a83d20a7"}, - {file = "numexpr-2.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b076db98ca65eeaf9bd224576e3ac84c05e451c0bd85b13664b7e5f7b62e2c70"}, - {file = "numexpr-2.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f12cc851240f7911a47c91aaf223dba753e98e46dff3017282e633602e76a7"}, - {file = "numexpr-2.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c368aa35ae9b18840e78b05f929d3a7b3abccdba9630a878c7db74ca2368339"}, - {file = "numexpr-2.8.4-cp38-cp38-win32.whl", hash = "sha256:b96334fc1748e9ec4f93d5fadb1044089d73fb08208fdb8382ed77c893f0be01"}, - {file = "numexpr-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:a6d2d7740ae83ba5f3531e83afc4b626daa71df1ef903970947903345c37bd03"}, - {file = "numexpr-2.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:77898fdf3da6bb96aa8a4759a8231d763a75d848b2f2e5c5279dad0b243c8dfe"}, - {file = "numexpr-2.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df35324666b693f13a016bc7957de7cc4d8801b746b81060b671bf78a52b9037"}, - {file = "numexpr-2.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ac9cfe6d0078c5fc06ba1c1bbd20b8783f28c6f475bbabd3cad53683075cab"}, - {file = "numexpr-2.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df3a1f6b24214a1ab826e9c1c99edf1686c8e307547a9aef33910d586f626d01"}, - {file = "numexpr-2.8.4-cp39-cp39-win32.whl", hash = "sha256:7d71add384adc9119568d7e9ffa8a35b195decae81e0abf54a2b7779852f0637"}, - {file = "numexpr-2.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:9f096d707290a6a00b6ffdaf581ee37331109fb7b6c8744e9ded7c779a48e517"}, - {file = "numexpr-2.8.4.tar.gz", hash = "sha256:d5432537418d18691b9115d615d6daa17ee8275baef3edf1afbbf8bc69806147"}, -] - -[package.dependencies] -numpy = ">=1.13.3" - [[package]] name = "numpy" version = "1.24.4" @@ -1037,7 +1038,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1045,15 +1045,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1070,7 +1063,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1078,7 +1070,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -1142,6 +1133,17 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + [[package]] name = "sqlalchemy" version = "2.0.19" @@ -1436,4 +1438,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.8.1,<4.0" -content-hash = "1c2959041fd8df3a2c9e4dff1465355acbd95b0a10535e6a6cf54ca36f01c276" +content-hash = "2888e2d6180b1e74d377a4a6dd459d70cc745f0717aa8584023633e169508c07" diff --git a/python/pyproject.toml b/python/pyproject.toml index c1049ffce..46e04df2f 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -39,7 +39,7 @@ types-requests = "^2.31.0.1" pandas-stubs = "^2.0.1.230501" types-pyyaml = "^6.0.12.10" pytest-asyncio = "^0.21.0" -langchain = "^0.0.295" +langchain = "^0.0.319" types-psutil = "^5.9.5.16" psutil = "^5.9.5" freezegun = "^1.2.2" From 2ac0e62409dad89007b072447e5c325e7ddcfcd2 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Fri, 20 Oct 2023 07:21:09 +0900 Subject: [PATCH 05/19] Wfh/share dataset (#261) --- js/src/client.ts | 86 +++++++++++++++++++++++++++++++++++++ js/src/schemas.ts | 8 ++++ python/langsmith/client.py | 85 ++++++++++++++++++++++++++++++++++++ python/langsmith/schemas.py | 20 ++++++++- 4 files changed, 198 insertions(+), 1 deletion(-) diff --git a/js/src/client.ts b/js/src/client.ts index a52a67727..a26991279 100644 --- a/js/src/client.ts +++ b/js/src/client.ts @@ -4,6 +4,7 @@ import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js"; import { DataType, Dataset, + DatasetShareSchema, Example, ExampleCreate, ExampleUpdate, @@ -584,6 +585,91 @@ export class Client { return runs as Run[]; } + public async readDatasetSharedSchema( + datasetId?: string, + datasetName?: string + ): Promise { + if (!datasetId && !datasetName) { + throw new Error("Either datasetId or datasetName must be given"); + } + if (!datasetId) { + const dataset = await this.readDataset({ datasetName }); + datasetId = dataset.id; + } + const response = await this.caller.call( + fetch, + `${this.apiUrl}/datasets/${datasetId}/share`, + { + method: "GET", + headers: this.headers, + signal: AbortSignal.timeout(this.timeout_ms), + } + ); + const shareSchema = await response.json(); + shareSchema.url = `${this.getHostUrl()}/public/${ + shareSchema.share_token + }/d`; + return shareSchema as DatasetShareSchema; + } + + public async shareDataset( + datasetId?: string, + datasetName?: string + ): Promise { + if (!datasetId && !datasetName) { + throw new Error("Either datasetId or datasetName must be given"); + } + if (!datasetId) { + const dataset = await this.readDataset({ datasetName }); + datasetId = dataset.id; + } + const data = { + dataset_id: datasetId, + }; + const response = await this.caller.call( + fetch, + `${this.apiUrl}/datasets/${datasetId}/share`, + { + method: "PUT", + headers: this.headers, + body: JSON.stringify(data), + signal: AbortSignal.timeout(this.timeout_ms), + } + ); + const shareSchema = await response.json(); + shareSchema.url = `${this.getHostUrl()}/public/${ + shareSchema.share_token + }/d`; + return shareSchema as DatasetShareSchema; + } + + public async unshareDataset(datasetId: string): Promise { + const response = await this.caller.call( + fetch, + `${this.apiUrl}/datasets/${datasetId}/share`, + { + method: "DELETE", + headers: this.headers, + signal: AbortSignal.timeout(this.timeout_ms), + } + ); + await raiseForStatus(response, "unshare dataset"); + } + + public async readSharedDataset(shareToken: string): Promise { + const response = await this.caller.call( + fetch, + `${this.apiUrl}/public/${shareToken}/datasets`, + { + method: "GET", + headers: this.headers, + signal: AbortSignal.timeout(this.timeout_ms), + } + ); + const dataset = await response.json(); + return dataset as Dataset; + } + public async createProject({ projectName, projectExtra, diff --git a/js/src/schemas.ts b/js/src/schemas.ts index 168175bca..24ff7e361 100644 --- a/js/src/schemas.ts +++ b/js/src/schemas.ts @@ -211,6 +211,14 @@ export interface Dataset extends BaseDataset { id: string; created_at: string; modified_at: string; + example_count?: number; + session_count?: number; + last_session_start_time?: number; +} +export interface DatasetShareSchema { + dataset_id: string; + share_token: string; + url: string; } export interface FeedbackSourceBase { diff --git a/python/langsmith/client.py b/python/langsmith/client.py index 450d9121a..de43028c1 100644 --- a/python/langsmith/client.py +++ b/python/langsmith/client.py @@ -969,6 +969,91 @@ def list_shared_runs( ls_schemas.Run(**run, _host_url=self._host_url) for run in response.json() ] + def read_dataset_shared_schema( + self, + dataset_id: Optional[ID_TYPE] = None, + *, + dataset_name: Optional[str] = None, + ) -> ls_schemas.DatasetShareSchema: + if dataset_id is None and dataset_name is None: + raise ValueError("Either dataset_id or dataset_name must be given") + if dataset_id is None: + dataset_id = self.read_dataset(dataset_name=dataset_name).id + response = self.session.get( + f"{self.api_url}/datasets/{dataset_id}/share", + headers=self._headers, + ) + ls_utils.raise_for_status_with_text(response) + d = response.json() + return cast( + ls_schemas.DatasetShareSchema, + {**d, "url": f"{self._host_url}/public/{d['share_token']}/d"}, + ) + + def share_dataset( + self, + dataset_id: Optional[ID_TYPE] = None, + *, + dataset_name: Optional[str] = None, + ) -> ls_schemas.DatasetShareSchema: + """Get a share link for a dataset.""" + if dataset_id is None and dataset_name is None: + raise ValueError("Either dataset_id or dataset_name must be given") + if dataset_id is None: + dataset_id = self.read_dataset(dataset_name=dataset_name).id + data = { + "dataset_id": str(dataset_id), + } + response = self.session.put( + f"{self.api_url}/datasets/{dataset_id}/share", + headers=self._headers, + json=data, + ) + ls_utils.raise_for_status_with_text(response) + d: dict = response.json() + return cast( + ls_schemas.DatasetShareSchema, + {**d, "url": f"{self._host_url}/public/{d['share_token']}/d"}, + ) + + def unshare_dataset(self, dataset_id: ID_TYPE) -> None: + """Delete share link for a dataset.""" + response = self.session.delete( + f"{self.api_url}/datasets/{dataset_id}/share", + headers=self._headers, + ) + ls_utils.raise_for_status_with_text(response) + + def read_shared_dataset( + self, + share_token: str, + ) -> ls_schemas.Dataset: + """Get shared datasets.""" + response = self.session.get( + f"{self.api_url}/public/{share_token}/datasets", + headers=self._headers, + ) + ls_utils.raise_for_status_with_text(response) + return ls_schemas.Dataset(**response.json(), _host_url=self._host_url) + + def list_shared_examples( + self, share_token: str, *, example_ids: Optional[List[ID_TYPE]] = None + ) -> List[ls_schemas.Example]: + """Get shared examples.""" + params = {} + if example_ids is not None: + params["id"] = [str(id) for id in example_ids] + response = self.session.get( + f"{self.api_url}/public/{share_token}/examples", + headers=self._headers, + params=params, + ) + ls_utils.raise_for_status_with_text(response) + return [ + ls_schemas.Example(**dataset, _host_url=self._host_url) + for dataset in response.json() + ] + def create_project( self, project_name: str, diff --git a/python/langsmith/schemas.py b/python/langsmith/schemas.py index a13cb80ef..1486726d9 100644 --- a/python/langsmith/schemas.py +++ b/python/langsmith/schemas.py @@ -3,7 +3,16 @@ from datetime import datetime, timedelta from enum import Enum -from typing import Any, Dict, List, Optional, Protocol, Union, runtime_checkable +from typing import ( + Any, + Dict, + List, + Optional, + Protocol, + TypedDict, + Union, + runtime_checkable, +) from uuid import UUID try: @@ -101,6 +110,9 @@ class Dataset(DatasetBase): id: UUID created_at: datetime modified_at: Optional[datetime] = Field(default=None) + example_count: Optional[int] = None + session_count: Optional[int] = None + last_session_start_time: Optional[datetime] = None _host_url: Optional[str] = PrivateAttr(default=None) def __init__(self, _host_url: Optional[str] = None, **kwargs: Any) -> None: @@ -381,3 +393,9 @@ class BaseMessageLike(Protocol): @property def type(self) -> str: """Type of the Message, used for serialization.""" + + +class DatasetShareSchema(TypedDict, total=False): + dataset_id: UUID + share_token: UUID + url: str From 3e884763d58d38fd8d3a945f9858881763eeeee2 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Fri, 20 Oct 2023 07:22:15 +0900 Subject: [PATCH 06/19] Wfh/update js license (#260) --- js/src/cli/docker-compose.beta.yaml | 1 + js/src/cli/docker-compose.dev.yaml | 2 ++ js/src/cli/docker-compose.yaml | 3 +++ js/src/cli/main.ts | 15 +++++++++++++-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/js/src/cli/docker-compose.beta.yaml b/js/src/cli/docker-compose.beta.yaml index 3b4796ce3..8d5ecc31f 100644 --- a/js/src/cli/docker-compose.beta.yaml +++ b/js/src/cli/docker-compose.beta.yaml @@ -7,6 +7,7 @@ services: - PORT=1985 - LANGCHAIN_ENV=local_docker - LOG_LEVEL=warning + - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY} ports: - 1985:1985 depends_on: diff --git a/js/src/cli/docker-compose.dev.yaml b/js/src/cli/docker-compose.dev.yaml index 90541d585..6e480093f 100644 --- a/js/src/cli/docker-compose.dev.yaml +++ b/js/src/cli/docker-compose.dev.yaml @@ -1,11 +1,13 @@ version: '3' services: + # TODO: Move to the regular docker-compose.yaml once deployed langchain-hub: image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainhub-backend:latest environment: - PORT=1985 - LANGCHAIN_ENV=local_docker - LOG_LEVEL=warning + - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY} ports: - 1985:1985 depends_on: diff --git a/js/src/cli/docker-compose.yaml b/js/src/cli/docker-compose.yaml index b5824a798..7bd152d44 100644 --- a/js/src/cli/docker-compose.yaml +++ b/js/src/cli/docker-compose.yaml @@ -16,6 +16,7 @@ services: - LANGCHAIN_ENV=local_docker - LOG_LEVEL=warning - OPENAI_API_KEY=${OPENAI_API_KEY} + - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY} ports: - 1984:1984 depends_on: @@ -26,6 +27,7 @@ services: environment: - LANGCHAIN_ENV=local_docker - LOG_LEVEL=warning + - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY} entrypoint: "rq worker --with-scheduler -u redis://langchain-redis:6379 --serializer lc_database.queue.serializer.ORJSONSerializer --worker-class lc_database.queue.worker.Worker --connection-class lc_database.queue.connection.RedisRetry --job-class lc_database.queue.job.AsyncJob" langchain-hub: image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainhub-backend:latest @@ -33,6 +35,7 @@ services: - PORT=1985 - LANGCHAIN_ENV=local_docker - LOG_LEVEL=warning + - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY} ports: - 1985:1985 depends_on: diff --git a/js/src/cli/main.ts b/js/src/cli/main.ts index 873f9f94f..099d5c93b 100644 --- a/js/src/cli/main.ts +++ b/js/src/cli/main.ts @@ -1,13 +1,15 @@ +import * as child_process from "child_process"; import * as fs from "fs"; import * as path from "path"; import * as util from "util"; -import { Command } from "commander"; -import * as child_process from "child_process"; + import { getLangChainEnvVars, getRuntimeEnvironment, setEnvironmentVariable, } from "../utils/env.js"; + +import { Command } from "commander"; import { spawn } from "child_process"; const currentFileName = __filename; @@ -330,6 +332,12 @@ const startCommand = new Command("start") " from the OPENAI_API_KEY environment variable. If neither are provided," + " some features of LangSmith will not be available." ) + .option( + "--langsmith-license-key ", + "The LangSmith license key to use for LangSmith. If not provided, the LangSmith" + + " License Key will be read from the LANGSMITH_LICENSE_KEY environment variable." + + " If neither are provided, the Langsmith application will not spin up." + ) .action(async (args) => { const smith = await SmithCommand.create(); if (args.stage === "dev") { @@ -340,6 +348,9 @@ const startCommand = new Command("start") if (args.openaiApiKey) { setEnvironmentVariable("OPENAI_API_KEY", args.openaiApiKey); } + if (args.langsmithLicenseKey) { + setEnvironmentVariable("LANGSMITH_LICENSE_KEY", args.langsmithLicenseKey); + } await smith.pull({ stage: args.stage }); if (args.expose) { await smith.startAndExpose(args.ngrokAuthtoken, args.stage); From 97f835f3b5a75631fa1ac5024998a2c49721463d Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:07:10 +0900 Subject: [PATCH 07/19] Add eager flag; bump (#264) --- js/package.json | 2 +- js/src/client.ts | 5 ++++- python/langsmith/client.py | 25 ++++++++++++++++++++++++- python/pyproject.toml | 2 +- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/js/package.json b/js/package.json index 1d8ec9691..c82f4a20d 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "langsmith", - "version": "0.0.43", + "version": "0.0.44", "description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.", "files": [ "dist/", diff --git a/js/src/client.ts b/js/src/client.ts index a26991279..1fd564cee 100644 --- a/js/src/client.ts +++ b/js/src/client.ts @@ -1244,6 +1244,7 @@ export class Client { feedbackSourceType = "api", sourceRunId, feedbackId, + eager = false, }: { score?: ScoreType; value?: ValueType; @@ -1253,6 +1254,7 @@ export class Client { feedbackSourceType?: FeedbackSourceType; sourceRunId?: string; feedbackId?: string; + eager?: boolean; } ): Promise { const feedback_source: feedback_source = { @@ -1276,7 +1278,8 @@ export class Client { comment, feedback_source: feedback_source, }; - const response = await this.caller.call(fetch, `${this.apiUrl}/feedback`, { + const url = `${this.apiUrl}/feedback` + (eager ? "/eager" : ""); + const response = await this.caller.call(fetch, url, { method: "POST", headers: { ...this.headers, "Content-Type": "application/json" }, body: JSON.stringify(feedback), diff --git a/python/langsmith/client.py b/python/langsmith/client.py index de43028c1..957973bdd 100644 --- a/python/langsmith/client.py +++ b/python/langsmith/client.py @@ -1054,6 +1054,23 @@ def list_shared_examples( for dataset in response.json() ] + def list_shared_projects( + self, + *, + dataset_share_token: Optional[str] = None, + project_ids: Optional[List[ID_TYPE]] = None, + name: Optional[str] = None, + name_contains: Optional[str] = None, + ) -> Iterator[ls_schemas.TracerSession]: + params = {"id": project_ids, "name": name, "name_contains": name_contains} + yield from [ + ls_schemas.TracerSession(**dataset, _host_url=self._host_url) + for dataset in self._get_paginated_list( + f"/public/{dataset_share_token}/datasets/sessions", + params=params, + ) + ] + def create_project( self, project_name: str, @@ -1935,6 +1952,7 @@ def create_feedback( ] = ls_schemas.FeedbackSourceType.API, source_run_id: Optional[ID_TYPE] = None, feedback_id: Optional[ID_TYPE] = None, + eager: bool = False, ) -> ls_schemas.Feedback: """Create a feedback in the LangSmith API. @@ -1962,6 +1980,11 @@ def create_feedback( feedback_id : str or UUID or None, default=None The ID of the feedback to create. If not provided, a random UUID will be generated. + eager : bool, default=False + Whether to skip the write queue when creating the feedback. This means + that the feedback will be immediately available for reading, but may + cause the write to fail if the API is under heavy load, since the target + run_id may have not been created yet. """ if not isinstance(feedback_source_type, ls_schemas.FeedbackSourceType): feedback_source_type = ls_schemas.FeedbackSourceType(feedback_source_type) @@ -1992,7 +2015,7 @@ def create_feedback( ) self.request_with_retries( "POST", - self.api_url + "/feedback", + self.api_url + "/feedback" + ("/eager" if eager else ""), request_kwargs={ "data": json.dumps( feedback.dict(exclude_none=True), default=_serialize_json diff --git a/python/pyproject.toml b/python/pyproject.toml index 46e04df2f..a008a4cbc 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.0.47" +version = "0.0.48" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT" From f214b87456ae80d5c871aaac5af44aad0b63a6d6 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Sat, 21 Oct 2023 02:12:34 +0900 Subject: [PATCH 08/19] Wfh/retry (#265) --- python/langsmith/client.py | 138 +++++++++++++++++++------------------ python/langsmith/utils.py | 4 ++ python/pyproject.toml | 2 +- 3 files changed, 76 insertions(+), 68 deletions(-) diff --git a/python/langsmith/client.py b/python/langsmith/client.py index 957973bdd..44a24200c 100644 --- a/python/langsmith/client.py +++ b/python/langsmith/client.py @@ -10,7 +10,9 @@ import json import logging import os +import random import socket +import time import uuid import weakref from typing import ( @@ -25,6 +27,7 @@ Optional, Sequence, Tuple, + Type, Union, cast, ) @@ -336,6 +339,8 @@ def request_with_retries( request_method: str, url: str, request_kwargs: Mapping, + stop_after_attempt: int = 1, + retry_on: Optional[Sequence[Type[BaseException]]] = None, ) -> requests.Response: """Send a request with retries. @@ -364,79 +369,73 @@ def request_with_retries( LangSmithError If the request fails. """ - try: - response = self.session.request( - request_method, url, stream=False, **request_kwargs - ) - ls_utils.raise_for_status_with_text(response) - return response - except requests.HTTPError as e: - if response is not None: - if response.status_code == 500: - raise ls_utils.LangSmithAPIError( - f"Server error caused failure to {request_method} {url} in" - f" LangSmith API. {repr(e)}" - ) - elif response.status_code == 429: - raise ls_utils.LangSmithRateLimitError( - f"Rate limit exceeded for {url}. {repr(e)}" - ) - elif response is not None and response.status_code == 401: - raise ls_utils.LangSmithAuthError( - f"Authentication failed for {url}. {repr(e)}" + for idx in range(stop_after_attempt): + try: + try: + response = self.session.request( + request_method, url, stream=False, **request_kwargs ) - else: + ls_utils.raise_for_status_with_text(response) + return response + except requests.HTTPError as e: + if response is not None: + if response.status_code == 500: + raise ls_utils.LangSmithAPIError( + f"Server error caused failure to {request_method}" + f" {url} in" + f" LangSmith API. {repr(e)}" + ) + elif response.status_code == 429: + raise ls_utils.LangSmithRateLimitError( + f"Rate limit exceeded for {url}. {repr(e)}" + ) + elif response.status_code == 401: + raise ls_utils.LangSmithAuthError( + f"Authentication failed for {url}. {repr(e)}" + ) + elif response.status_code == 404: + raise ls_utils.LangSmithNotFoundError( + f"Resource not found for {url}. {repr(e)}" + ) + else: + raise ls_utils.LangSmithError( + f"Failed to {request_method} {url} in LangSmith" + f" API. {repr(e)}" + ) + + else: + raise ls_utils.LangSmithUserError( + f"Failed to {request_method} {url} in LangSmith API." + f" {repr(e)}" + ) + except requests.ConnectionError as e: + raise ls_utils.LangSmithConnectionError( + f"Connection error caused failure to {request_method} {url}" + " in LangSmith API. Please confirm your LANGCHAIN_ENDPOINT." + f" {repr(e)}" + ) from e + except Exception as e: + args = list(e.args) + msg = args[1] if len(args) > 1 else "" + msg = msg.replace("session", "session (project)") + emsg = "\n".join([args[0]] + [msg] + args[2:]) raise ls_utils.LangSmithError( - f"Failed to {request_method} {url} in LangSmith API. {repr(e)}" - ) - - else: - raise ls_utils.LangSmithUserError( - f"Failed to {request_method} {url} in LangSmith API. {repr(e)}" - ) - except requests.ConnectionError as e: - raise ls_utils.LangSmithConnectionError( - f"Connection error caused failure to {request_method} {url}" - " in LangSmith API. Please confirm your LANGCHAIN_ENDPOINT." - f" {repr(e)}" - ) from e - except Exception as e: - args = list(e.args) - msg = args[1] if len(args) > 1 else "" - msg = msg.replace("session", "session (project)") - emsg = "\n".join([args[0]] + [msg] + args[2:]) - raise ls_utils.LangSmithError( - f"Failed to {request_method} {url} in LangSmith API. {emsg}" - ) from e + f"Failed to {request_method} {url} in LangSmith API. {emsg}" + ) from e + except tuple(retry_on or []): + if idx + 1 == stop_after_attempt: + raise + sleep_time = 2**idx + (random.random() * 0.5) + time.sleep(sleep_time) + continue + + raise ls_utils.LangSmithError( + f"Failed to {request_method} {url} in LangSmith API." + ) def _get_with_retries( self, path: str, params: Optional[Dict[str, Any]] = None ) -> requests.Response: - """Send a GET request with retries. - - Parameters - ---------- - path : str - The path of the request URL. - params : Dict[str, Any] or None, default=None - The query parameters. - - Returns - ------- - Response - The response object. - - Raises - ------ - LangSmithAPIError - If a server error occurs. - LangSmithUserError - If the request fails. - LangSmithConnectionError - If a connection error occurs. - LangSmithError - If the request fails. - """ return self.request_with_retries( "get", f"{self.api_url}{path}", @@ -1953,6 +1952,7 @@ def create_feedback( source_run_id: Optional[ID_TYPE] = None, feedback_id: Optional[ID_TYPE] = None, eager: bool = False, + stop_after_attempt: int = 10, ) -> ls_schemas.Feedback: """Create a feedback in the LangSmith API. @@ -1985,6 +1985,8 @@ def create_feedback( that the feedback will be immediately available for reading, but may cause the write to fail if the API is under heavy load, since the target run_id may have not been created yet. + stop_after_attempt : int, default=10 + The number of times to retry the request before giving up. """ if not isinstance(feedback_source_type, ls_schemas.FeedbackSourceType): feedback_source_type = ls_schemas.FeedbackSourceType(feedback_source_type) @@ -2027,6 +2029,8 @@ def create_feedback( }, "timeout": self.timeout_ms / 1000, }, + stop_after_attempt=stop_after_attempt, + retry_on=(ls_utils.LangSmithNotFoundError,), ) return ls_schemas.Feedback(**feedback.dict()) diff --git a/python/langsmith/utils.py b/python/langsmith/utils.py index eb79fd867..877d82a33 100644 --- a/python/langsmith/utils.py +++ b/python/langsmith/utils.py @@ -29,6 +29,10 @@ class LangSmithAuthError(Exception): """Couldn't authenticate with the LangSmith API.""" +class LangSmithNotFoundError(Exception): + """Couldn't find the requested resource.""" + + class LangSmithError(Exception): """An error occurred while communicating with the LangSmith API.""" diff --git a/python/pyproject.toml b/python/pyproject.toml index a008a4cbc..f1b9d8b7e 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.0.48" +version = "0.0.49" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT" From 0c6b177ad92458c7a763dfba1c77ab51b7f62adb Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Wed, 25 Oct 2023 06:49:26 +0900 Subject: [PATCH 09/19] Wfh/add traceable dunder (#266) --- python/Makefile | 1 + python/langsmith/run_helpers.py | 15 +++++++++++---- python/pyproject.toml | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/python/Makefile b/python/Makefile index 8480596eb..9233c2cb6 100644 --- a/python/Makefile +++ b/python/Makefile @@ -12,6 +12,7 @@ lint: poetry run black . --check format: + poetry run ruff format poetry run ruff --fix . poetry run black . diff --git a/python/langsmith/run_helpers.py b/python/langsmith/run_helpers.py index b21185a16..3b809577a 100644 --- a/python/langsmith/run_helpers.py +++ b/python/langsmith/run_helpers.py @@ -36,6 +36,11 @@ def get_run_tree_context() -> Optional[run_trees.RunTree]: return _PARENT_RUN_TREE.get() +def is_traceable_function(func: Callable) -> bool: + """Check if a function is @traceable decorated.""" + return getattr(func, "__langsmith_traceable__", False) + + def _get_inputs( signature: inspect.Signature, *args: Any, **kwargs: Any ) -> Dict[str, Any]: @@ -443,13 +448,15 @@ def generator_wrapper( run_container["new_run"].patch() if inspect.isasyncgenfunction(func): - return async_generator_wrapper + selected_wrapper: Callable = async_generator_wrapper elif inspect.iscoroutinefunction(func): - return async_wrapper + selected_wrapper = async_wrapper elif inspect.isgeneratorfunction(func): - return generator_wrapper + selected_wrapper = generator_wrapper else: - return wrapper + selected_wrapper = wrapper + setattr(selected_wrapper, "__langsmith_traceable__", True) + return selected_wrapper return decorator diff --git a/python/pyproject.toml b/python/pyproject.toml index f1b9d8b7e..be5d78ca9 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.0.49" +version = "0.0.50" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT" From 0cf8462a7b57697781493666afe69301bb056283 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Wed, 25 Oct 2023 10:12:20 +0900 Subject: [PATCH 10/19] Change which parent run tree is re-assigned (#267) The outer context should be re-assigned to whatever it was before and not overwritted to whatever was manually passed in --- python/langsmith/run_helpers.py | 28 ++++++++++++++-------------- python/pyproject.toml | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/python/langsmith/run_helpers.py b/python/langsmith/run_helpers.py index 3b809577a..b3b5648be 100644 --- a/python/langsmith/run_helpers.py +++ b/python/langsmith/run_helpers.py @@ -222,7 +222,7 @@ async def async_wrapper( **kwargs: Any, ) -> Any: """Async version of wrapper function""" - + context_run = _PARENT_RUN_TREE.get() run_container = _setup_run( func, run_type=run_type, @@ -251,10 +251,10 @@ async def async_wrapper( except Exception as e: run_container["new_run"].end(error=str(e)) run_container["new_run"].patch() - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) raise e - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) if isinstance(function_result, dict): run_container["new_run"].end(outputs=function_result) @@ -267,6 +267,7 @@ async def async_wrapper( async def async_generator_wrapper( *args: Any, langsmith_extra: Optional[LangSmithExtra] = None, **kwargs: Any ) -> AsyncGenerator: + context_run = _PARENT_RUN_TREE.get() run_container = _setup_run( func, run_type=run_type, @@ -296,7 +297,7 @@ async def async_generator_wrapper( # called mid-generation. Need to explicitly accept run_tree to get # around this. async_gen_result = func(*args, **kwargs) - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) @@ -307,7 +308,7 @@ async def async_generator_wrapper( stacktrace = traceback.format_exc() run_container["new_run"].end(error=stacktrace) run_container["new_run"].patch() - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) @@ -336,6 +337,7 @@ def wrapper( **kwargs: Any, ) -> Any: """Create a new run or create_child() if run is passed in kwargs.""" + context_run = _PARENT_RUN_TREE.get() run_container = _setup_run( func, run_type=run_type, @@ -365,12 +367,12 @@ def wrapper( stacktrace = traceback.format_exc() run_container["new_run"].end(error=stacktrace) run_container["new_run"].patch() - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) raise e - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) @@ -385,6 +387,7 @@ def wrapper( def generator_wrapper( *args: Any, langsmith_extra: Optional[LangSmithExtra] = None, **kwargs: Any ) -> Any: + context_run = _PARENT_RUN_TREE.get() run_container = _setup_run( func, run_type=run_type, @@ -414,7 +417,7 @@ def generator_wrapper( # called mid-generation. Need to explicitly accept run_tree to get # around this. generator_result = func(*args, **kwargs) - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) @@ -425,7 +428,7 @@ def generator_wrapper( stacktrace = traceback.format_exc() run_container["new_run"].end(error=stacktrace) run_container["new_run"].patch() - _PARENT_RUN_TREE.set(run_container["new_run"].parent_run) + _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) @@ -519,15 +522,12 @@ def trace( tb = traceback.format_exc() new_run.end(error=tb) new_run.patch() + raise e + finally: _PARENT_RUN_TREE.set(parent_run_) _PROJECT_NAME.set(outer_project) _TAGS.set(outer_tags) _METADATA.set(outer_metadata) - raise e - _PARENT_RUN_TREE.set(parent_run_) - _PROJECT_NAME.set(outer_project) - _TAGS.set(outer_tags) - _METADATA.set(outer_metadata) if new_run.end_time is None: # User didn't call end() on the run, so we'll do it for them new_run.end() diff --git a/python/pyproject.toml b/python/pyproject.toml index be5d78ca9..694325171 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.0.50" +version = "0.0.51" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT" From dcb384644734f30ca056ca50ee3733340f8c021c Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 26 Oct 2023 06:20:55 +0900 Subject: [PATCH 11/19] Add as_runnable function (#268) --- python/langsmith/run_helpers.py | 157 +++++++++++++++++++- python/tests/unit_tests/test_run_helpers.py | 73 ++++++++- 2 files changed, 228 insertions(+), 2 deletions(-) diff --git a/python/langsmith/run_helpers.py b/python/langsmith/run_helpers.py index b3b5648be..1fcd04446 100644 --- a/python/langsmith/run_helpers.py +++ b/python/langsmith/run_helpers.py @@ -1,4 +1,6 @@ """Decorator for creating a run tree from functions.""" +from __future__ import annotations + import contextlib import contextvars import functools @@ -9,8 +11,10 @@ import uuid from concurrent import futures from typing import ( + TYPE_CHECKING, Any, AsyncGenerator, + Awaitable, Callable, Dict, Generator, @@ -18,10 +22,14 @@ Mapping, Optional, TypedDict, + cast, ) from langsmith import client, run_trees, utils +if TYPE_CHECKING: + from langchain.schema.runnable import Runnable + logger = logging.getLogger(__name__) _PARENT_RUN_TREE = contextvars.ContextVar[Optional[run_trees.RunTree]]( "_PARENT_RUN_TREE", default=None @@ -210,10 +218,34 @@ def traceable( def decorator(func: Callable): if not utils.tracing_is_enabled(): + if inspect.iscoroutinefunction(func): + + @functools.wraps(func) + async def anoop_wrapper( + *args: Any, + langsmith_extra: Optional[LangSmithExtra] = None, + **kwargs: Any, + ) -> Any: + return await func(*args, **kwargs) + + fn = anoop_wrapper + else: + + @functools.wraps(func) + def noop_wrapper( + *args: Any, + langsmith_extra: Optional[LangSmithExtra] = None, + **kwargs: Any, + ) -> Any: + return func(*args, **kwargs) + + fn = noop_wrapper + utils.log_once( logging.DEBUG, "Tracing is disabled, returning original function" ) - return func + setattr(fn, "__langsmith_traceable__", True) + return fn @functools.wraps(func) async def async_wrapper( @@ -532,3 +564,126 @@ def trace( # User didn't call end() on the run, so we'll do it for them new_run.end() new_run.patch() + + +def as_runnable(traceable_fn: Callable) -> Runnable: + try: + from langchain.callbacks.manager import ( + AsyncCallbackManager, + CallbackManager, + ) + from langchain.callbacks.tracers.langchain import LangChainTracer + from langchain.schema.runnable import RunnableConfig, RunnableLambda + from langchain.schema.runnable.utils import Input, Output + except ImportError as e: + raise ImportError( + "as_runnable requires langchain to be installed. " + "You can install it with `pip install langchain`." + ) from e + if not is_traceable_function(traceable_fn): + fn_src = inspect.getsource(traceable_fn) + raise ValueError( + f"as_runnable expects a function wrapped by the LangSmith" + f" @traceable decorator. Got {traceable_fn} defined as:\n{fn_src}" + ) + + class RunnableTraceable(RunnableLambda): + """RunnableTraceable converts a @traceable decorated function + to a Runnable in a way that hands off the LangSmith tracing context. + """ + + def __init__( + self, + func: Callable, + afunc: Optional[Callable[..., Awaitable[Output]]] = None, + ) -> None: + wrapped: Optional[Callable[[Input], Output]] = None + awrapped = self._wrap_async(afunc) + if inspect.iscoroutinefunction(func): + if awrapped is not None: + raise TypeError( + "Func was provided as a coroutine function, but afunc was " + "also provided. If providing both, func should be a regular " + "function to avoid ambiguity." + ) + wrapped = cast(Callable[[Input], Output], self._wrap_async(func)) + elif is_traceable_function(func): + wrapped = cast(Callable[[Input], Output], self._wrap_sync(func)) + if wrapped is None: + raise ValueError( + f"{self.__class__.__name__} expects a function wrapped by" + " the LangSmith" + f" @traceable decorator. Got {func}" + ) + + super().__init__( + wrapped, + cast( + Optional[Callable[[Input], Awaitable[Output]]], + awrapped, + ), + ) + + @staticmethod + def _configure_run_tree(callback_manager: Any) -> Optional[run_trees.RunTree]: + run_tree: Optional[run_trees.RunTree] = None + if isinstance(callback_manager, (CallbackManager, AsyncCallbackManager)): + lc_tracers = [ + handler + for handler in callback_manager.handlers + if isinstance(handler, LangChainTracer) + ] + if lc_tracers: + lc_tracer = lc_tracers[0] + run_tree = run_trees.RunTree( + id=callback_manager.parent_run_id, + session_name=lc_tracer.project_name, + name="Wrapping", + run_type="chain", + inputs={}, + tags=callback_manager.tags, + extra={"metadata": callback_manager.metadata}, + ) + return run_tree + + @staticmethod + def _wrap_sync( + func: Callable[..., Output] + ) -> Callable[[Input, RunnableConfig], Output]: + """Wrap a synchronous function to make it asynchronous.""" + + def wrap_traceable(inputs: dict, config: RunnableConfig) -> Any: + run_tree = RunnableTraceable._configure_run_tree( + config.get("callbacks") + ) + return func(**inputs, langsmith_extra={"run_tree": run_tree}) + + return cast(Callable[[Input, RunnableConfig], Output], wrap_traceable) + + @staticmethod + def _wrap_async( + afunc: Optional[Callable[..., Awaitable[Output]]] + ) -> Optional[Callable[[Input, RunnableConfig], Awaitable[Output]]]: + """Wrap an async function to make it synchronous.""" + + if afunc is None: + return None + + if not is_traceable_function(afunc): + raise ValueError( + "RunnableTraceable expects a function wrapped by the LangSmith" + f" @traceable decorator. Got {afunc}" + ) + afunc_ = cast(Callable[..., Awaitable[Output]], afunc) + + async def awrap_traceable(inputs: dict, config: RunnableConfig) -> Any: + run_tree = RunnableTraceable._configure_run_tree( + config.get("callbacks") + ) + return await afunc_(**inputs, langsmith_extra={"run_tree": run_tree}) + + return cast( + Callable[[Input, RunnableConfig], Awaitable[Output]], awrap_traceable + ) + + return RunnableTraceable(traceable_fn) diff --git a/python/tests/unit_tests/test_run_helpers.py b/python/tests/unit_tests/test_run_helpers.py index 00a022f82..6bcf6a128 100644 --- a/python/tests/unit_tests/test_run_helpers.py +++ b/python/tests/unit_tests/test_run_helpers.py @@ -1,7 +1,9 @@ import inspect from typing import Any -from langsmith.run_helpers import _get_inputs +import pytest + +from langsmith.run_helpers import _get_inputs, as_runnable, traceable def test__get_inputs_with_no_args() -> None: @@ -141,3 +143,72 @@ def foo(kwargs: int, *, b: int, c: int, **some_other_kwargs: Any) -> None: "e": 5, "other_kwargs": {"f": 6}, } + + +def test_traceable_iterator() -> None: + @traceable() + def my_iterator_fn(a, b, d): + for i in range(a + b + d): + yield i + + assert list(my_iterator_fn(1, 2, 3)) == [0, 1, 2, 3, 4, 5] + + +@pytest.mark.asyncio +async def test_traceable_async_iterator() -> None: + @traceable() + async def my_iterator_fn(a, b, d): + for i in range(a + b + d): + yield i + + assert [i async for i in my_iterator_fn(1, 2, 3)] == [0, 1, 2, 3, 4, 5] + + +def test_as_runnable() -> None: + @traceable() + def my_function(a, b, d): + return a + b + d + + runnable = as_runnable(my_function) + assert runnable.invoke({"a": 1, "b": 2, "d": 3}) == 6 + + +def test_as_runnable_batch() -> None: + @traceable() + def my_function(a, b, d): + return a + b + d + + runnable = as_runnable(my_function) + assert runnable.batch( + [ + {"a": 1, "b": 2, "d": 3}, + {"a": 1, "b": 2, "d": 4}, + ] + ) == [6, 7] + + +@pytest.mark.asyncio +async def test_as_runnable_async() -> None: + @traceable() + async def my_function(a, b, d): + return a + b + d + + runnable = as_runnable(my_function) + result = await runnable.ainvoke({"a": 1, "b": 2, "d": 3}) + assert result == 6 + + +@pytest.mark.asyncio +async def test_as_runnable_async_batch() -> None: + @traceable() + async def my_function(a, b, d): + return a + b + d + + runnable = as_runnable(my_function) + result = await runnable.abatch( + [ + {"a": 1, "b": 2, "d": 3}, + {"a": 1, "b": 2, "d": 4}, + ] + ) + assert result == [6, 7] From 0011b4789b7bd45f4fe07ccce14a77e9dccfca3c Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 26 Oct 2023 06:27:26 +0900 Subject: [PATCH 12/19] Add py.typed (#269) --- python/langsmith/py.typed | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 python/langsmith/py.typed diff --git a/python/langsmith/py.typed b/python/langsmith/py.typed new file mode 100644 index 000000000..e69de29bb From 3059fb0ee918fdb05e33cc4872d808ad83f0883b Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 26 Oct 2023 06:31:02 +0900 Subject: [PATCH 13/19] 0.0.52 (#270) --- python/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index 694325171..eb7341663 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.0.51" +version = "0.0.52" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT" From 464debed521de0d52dc414c364a0988a2887a411 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 26 Oct 2023 07:27:27 +0900 Subject: [PATCH 14/19] catch (#271) --- python/langsmith/run_helpers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/langsmith/run_helpers.py b/python/langsmith/run_helpers.py index 1fcd04446..71effb6d6 100644 --- a/python/langsmith/run_helpers.py +++ b/python/langsmith/run_helpers.py @@ -581,7 +581,10 @@ def as_runnable(traceable_fn: Callable) -> Runnable: "You can install it with `pip install langchain`." ) from e if not is_traceable_function(traceable_fn): - fn_src = inspect.getsource(traceable_fn) + try: + fn_src = inspect.getsource(traceable_fn) + except Exception: + fn_src = "" raise ValueError( f"as_runnable expects a function wrapped by the LangSmith" f" @traceable decorator. Got {traceable_fn} defined as:\n{fn_src}" From 07b4cebe1a5070fc75f051fdc398954d6ed2ebd7 Mon Sep 17 00:00:00 2001 From: Chase McDougall Date: Thu, 26 Oct 2023 13:55:59 -0400 Subject: [PATCH 15/19] fix(TS LangSmith without LangChain): import fails (#272) Fix imports for TS RunTree, outlined in: - #273 --- js/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/index.ts b/js/src/index.ts index 0eb116d4d..6bbee102e 100644 --- a/js/src/index.ts +++ b/js/src/index.ts @@ -2,4 +2,4 @@ export { Client } from "./client.js"; export { Dataset, Example, TracerSession, Run, Feedback } from "./schemas.js"; -export { RunTree } from "./run_trees.js"; +export { RunTree, RunTreeConfig } from "./run_trees.js"; From 7bd7a8596ec3f95707cc5ad0538360db5c9c75d6 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Sat, 28 Oct 2023 06:31:14 +0900 Subject: [PATCH 16/19] Trace if explicitly set (#274) --- python/langsmith/run_helpers.py | 142 +++++++----------- python/tests/integration_tests/test_client.py | 12 +- 2 files changed, 63 insertions(+), 91 deletions(-) diff --git a/python/langsmith/run_helpers.py b/python/langsmith/run_helpers.py index 71effb6d6..cb19cbbdf 100644 --- a/python/langsmith/run_helpers.py +++ b/python/langsmith/run_helpers.py @@ -85,13 +85,28 @@ class LangSmithExtra(TypedDict, total=False): class _TraceableContainer(TypedDict, total=False): """Typed response when initializing a run a traceable.""" - new_run: run_trees.RunTree + new_run: Optional[run_trees.RunTree] project_name: Optional[str] outer_project: Optional[str] outer_metadata: Optional[Dict[str, Any]] outer_tags: Optional[List[str]] +def _container_end( + container: _TraceableContainer, + outputs: Optional[Any] = None, + error: Optional[str] = None, +): + """End the run.""" + run_tree = container.get("new_run") + if run_tree is None: + # Tracing disabled + return + outputs_ = outputs if isinstance(outputs, dict) else {"output": outputs} + run_tree.end(outputs=outputs_, error=error) + run_tree.patch() + + def _collect_extra(extra_outer: dict, langsmith_extra: LangSmithExtra) -> dict: run_extra = langsmith_extra.get("run_extra", None) if run_extra: @@ -119,6 +134,19 @@ def _setup_run( ) langsmith_extra = langsmith_extra or LangSmithExtra() parent_run_ = langsmith_extra.get("run_tree") or _PARENT_RUN_TREE.get() + if not parent_run_ and not utils.tracing_is_enabled(): + utils.log_once( + logging.DEBUG, "LangSmith tracing is disabled, returning original function." + ) + return _TraceableContainer( + new_run=None, + project_name=outer_project, + outer_project=outer_project, + outer_metadata=None, + outer_tags=None, + ) + # Else either the env var is set OR a parent run was explicitly set, + # which occurs in the `as_runnable()` flow project_name_ = langsmith_extra.get("project_name", outer_project) signature = inspect.signature(func) name_ = name or func.__name__ @@ -172,14 +200,18 @@ def _setup_run( executor=executor, client=client_, ) + new_run.post() - return _TraceableContainer( + response_container = _TraceableContainer( new_run=new_run, project_name=project_name_, outer_project=outer_project, outer_metadata=outer_metadata, outer_tags=outer_tags, ) + _PROJECT_NAME.set(response_container["project_name"]) + _PARENT_RUN_TREE.set(response_container["new_run"]) + return response_container def traceable( @@ -217,36 +249,6 @@ def traceable( extra_outer = extra or {} def decorator(func: Callable): - if not utils.tracing_is_enabled(): - if inspect.iscoroutinefunction(func): - - @functools.wraps(func) - async def anoop_wrapper( - *args: Any, - langsmith_extra: Optional[LangSmithExtra] = None, - **kwargs: Any, - ) -> Any: - return await func(*args, **kwargs) - - fn = anoop_wrapper - else: - - @functools.wraps(func) - def noop_wrapper( - *args: Any, - langsmith_extra: Optional[LangSmithExtra] = None, - **kwargs: Any, - ) -> Any: - return func(*args, **kwargs) - - fn = noop_wrapper - - utils.log_once( - logging.DEBUG, "Tracing is disabled, returning original function" - ) - setattr(fn, "__langsmith_traceable__", True) - return fn - @functools.wraps(func) async def async_wrapper( *args: Any, @@ -268,8 +270,6 @@ async def async_wrapper( args=args, kwargs=kwargs, ) - _PROJECT_NAME.set(run_container["project_name"]) - _PARENT_RUN_TREE.set(run_container["new_run"]) func_accepts_parent_run = ( inspect.signature(func).parameters.get("run_tree", None) is not None ) @@ -281,18 +281,15 @@ async def async_wrapper( else: function_result = await func(*args, **kwargs) except Exception as e: - run_container["new_run"].end(error=str(e)) - run_container["new_run"].patch() + stacktrace = traceback.format_exc() + _container_end(run_container, error=stacktrace) + raise e + finally: _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) - raise e - _PARENT_RUN_TREE.set(context_run) - _PROJECT_NAME.set(run_container["outer_project"]) - if isinstance(function_result, dict): - run_container["new_run"].end(outputs=function_result) - else: - run_container["new_run"].end(outputs={"output": function_result}) - run_container["new_run"].patch() + _TAGS.set(run_container["outer_tags"]) + _METADATA.set(run_container["outer_metadata"]) + _container_end(run_container, outputs=function_result) return function_result @functools.wraps(func) @@ -313,8 +310,6 @@ async def async_generator_wrapper( args=args, kwargs=kwargs, ) - _PROJECT_NAME.set(run_container["project_name"]) - _PARENT_RUN_TREE.set(run_container["new_run"]) func_accepts_parent_run = ( inspect.signature(func).parameters.get("run_tree", None) is not None ) @@ -336,15 +331,15 @@ async def async_generator_wrapper( async for item in async_gen_result: results.append(item) yield item - except (BaseException, Exception, KeyboardInterrupt) as e: + except BaseException as e: stacktrace = traceback.format_exc() - run_container["new_run"].end(error=stacktrace) - run_container["new_run"].patch() + _container_end(run_container, error=stacktrace) + raise e + finally: _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) - raise e if results: if reduce_fn: try: @@ -356,11 +351,7 @@ async def async_generator_wrapper( function_result = results else: function_result = None - if isinstance(function_result, dict): - run_container["new_run"].end(outputs=function_result) - else: - run_container["new_run"].end(outputs={"output": function_result}) - run_container["new_run"].patch() + _container_end(run_container, outputs=function_result) @functools.wraps(func) def wrapper( @@ -383,8 +374,6 @@ def wrapper( args=args, kwargs=kwargs, ) - _PROJECT_NAME.set(run_container["project_name"]) - _PARENT_RUN_TREE.set(run_container["new_run"]) func_accepts_parent_run = ( inspect.signature(func).parameters.get("run_tree", None) is not None ) @@ -395,24 +384,16 @@ def wrapper( ) else: function_result = func(*args, **kwargs) - except (BaseException, Exception, KeyboardInterrupt) as e: + except BaseException as e: stacktrace = traceback.format_exc() - run_container["new_run"].end(error=stacktrace) - run_container["new_run"].patch() + _container_end(run_container, error=stacktrace) + raise e + finally: _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) - raise e - _PARENT_RUN_TREE.set(context_run) - _PROJECT_NAME.set(run_container["outer_project"]) - _TAGS.set(run_container["outer_tags"]) - _METADATA.set(run_container["outer_metadata"]) - if isinstance(function_result, dict): - run_container["new_run"].end(outputs=function_result) - else: - run_container["new_run"].end(outputs={"output": function_result}) - run_container["new_run"].patch() + _container_end(run_container, outputs=function_result) return function_result @functools.wraps(func) @@ -433,8 +414,7 @@ def generator_wrapper( args=args, kwargs=kwargs, ) - _PROJECT_NAME.set(run_container["project_name"]) - _PARENT_RUN_TREE.set(run_container["new_run"]) + func_accepts_parent_run = ( inspect.signature(func).parameters.get("run_tree", None) is not None ) @@ -449,22 +429,18 @@ def generator_wrapper( # called mid-generation. Need to explicitly accept run_tree to get # around this. generator_result = func(*args, **kwargs) - _PARENT_RUN_TREE.set(context_run) - _PROJECT_NAME.set(run_container["outer_project"]) - _TAGS.set(run_container["outer_tags"]) - _METADATA.set(run_container["outer_metadata"]) for item in generator_result: results.append(item) yield item - except (BaseException, Exception, KeyboardInterrupt) as e: + except BaseException as e: stacktrace = traceback.format_exc() - run_container["new_run"].end(error=stacktrace) - run_container["new_run"].patch() + _container_end(run_container, error=stacktrace) + raise e + finally: _PARENT_RUN_TREE.set(context_run) _PROJECT_NAME.set(run_container["outer_project"]) _TAGS.set(run_container["outer_tags"]) _METADATA.set(run_container["outer_metadata"]) - raise e if results: if reduce_fn: try: @@ -476,11 +452,7 @@ def generator_wrapper( function_result = results else: function_result = None - if isinstance(function_result, dict) or function_result is None: - run_container["new_run"].end(outputs=function_result) - else: - run_container["new_run"].end(outputs={"output": function_result}) - run_container["new_run"].patch() + _container_end(run_container, outputs=function_result) if inspect.isasyncgenfunction(func): selected_wrapper: Callable = async_generator_wrapper diff --git a/python/tests/integration_tests/test_client.py b/python/tests/integration_tests/test_client.py index d0b92ca60..638aaf7ec 100644 --- a/python/tests/integration_tests/test_client.py +++ b/python/tests/integration_tests/test_client.py @@ -150,12 +150,12 @@ def test_persist_update_run( run["outputs"] = {"output": ["Hi"]} run["extra"]["foo"] = "bar" langchain_client.update_run(run["id"], **run) - for _ in range(3): + for _ in range(5): try: stored_run = langchain_client.read_run(run["id"]) break except LangSmithError: - time.sleep(1) + time.sleep(2) assert stored_run.id == run["id"] assert stored_run.outputs == run["outputs"] @@ -217,8 +217,8 @@ def grader(run_input: str, run_output: str, answer: Optional[str]) -> dict: return dict(score=score, value=value) evaluator = StringEvaluator(evaluation_name="Jaccard", grading_function=grader) - - for _ in range(3): + runs = None + for _ in range(5): try: runs = list( langchain_client.list_runs( @@ -229,8 +229,8 @@ def grader(run_input: str, run_output: str, answer: Optional[str]) -> dict: ) break except LangSmithError: - time.sleep(1) - + time.sleep(2) + assert runs is not None all_eval_results: List[EvaluationResult] = [] for run in runs: all_eval_results.append(langchain_client.evaluate_run(run, evaluator)) From 7a139705d7a4c389c971b43c600f6d222f4feec1 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Sat, 28 Oct 2023 06:33:48 +0900 Subject: [PATCH 17/19] Next version (#275) --- js/package.json | 2 +- python/pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/package.json b/js/package.json index c82f4a20d..2060fe9c8 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "langsmith", - "version": "0.0.44", + "version": "0.0.45", "description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.", "files": [ "dist/", diff --git a/python/pyproject.toml b/python/pyproject.toml index eb7341663..91e1bdc64 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.0.52" +version = "0.0.53" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT" From 9402c0401ce85a8c096832e26a56c4d88aaa3642 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Sun, 29 Oct 2023 16:26:35 +0900 Subject: [PATCH 18/19] Add target ID support (#276) --- python/langsmith/client.py | 82 ++++++++++++++++-------- python/langsmith/evaluation/evaluator.py | 21 ++++-- python/tests/unit_tests/test_client.py | 6 +- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/python/langsmith/client.py b/python/langsmith/client.py index 44a24200c..421217e0b 100644 --- a/python/langsmith/client.py +++ b/python/langsmith/client.py @@ -1826,6 +1826,21 @@ def _resolve_example_id( reference_example_ = None return reference_example_ + def _select_eval_results( + self, + results: Union[ls_evaluator.EvaluationResult, ls_evaluator.EvaluationResults], + ) -> List[ls_evaluator.EvaluationResult]: + if isinstance(results, ls_evaluator.EvaluationResult): + results_ = [results] + elif isinstance(results, dict) and "results" in results: + results_ = cast(List[ls_evaluator.EvaluationResult], results["results"]) + else: + raise TypeError( + f"Invalid evaluation result type {type(results)}." + " Expected EvaluationResult or EvaluationResults." + ) + return results_ + def evaluate_run( self, run: Union[ls_schemas.Run, ls_schemas.RunBase, str, uuid.UUID], @@ -1861,25 +1876,44 @@ def evaluate_run( """ run_ = self._resolve_run_id(run, load_child_runs=load_child_runs) reference_example_ = self._resolve_example_id(reference_example, run_) - evaluation_result = evaluator.evaluate_run( + evaluator_response = evaluator.evaluate_run( run_, example=reference_example_, ) - source_info = source_info or {} - if evaluation_result.evaluator_info: - source_info = {**evaluation_result.evaluator_info, **source_info} - self.create_feedback( - run_.id, - evaluation_result.key, - score=evaluation_result.score, - value=evaluation_result.value, - comment=evaluation_result.comment, - correction=evaluation_result.correction, + results = self._log_evaluation_feedback( + evaluator_response, + run_, source_info=source_info, - source_run_id=evaluation_result.source_run_id, - feedback_source_type=ls_schemas.FeedbackSourceType.MODEL, ) - return evaluation_result + # TODO: Return all results + return results[0] + + def _log_evaluation_feedback( + self, + evaluator_response: Union[ + ls_evaluator.EvaluationResult, ls_evaluator.EvaluationResults + ], + run: ls_schemas.Run, + source_info: Optional[Dict[str, Any]] = None, + ) -> List[ls_evaluator.EvaluationResult]: + results = self._select_eval_results(evaluator_response) + for res in results: + source_info_ = source_info or {} + if res.evaluator_info: + source_info_ = {**res.evaluator_info, **source_info_} + run_id_ = res.target_run_id if res.target_run_id else run.id + self.create_feedback( + run_id_, + res.key, + score=res.score, + value=res.value, + comment=res.comment, + correction=res.correction, + source_info=source_info_, + source_run_id=res.source_run_id, + feedback_source_type=ls_schemas.FeedbackSourceType.MODEL, + ) + return results async def aevaluate_run( self, @@ -1916,25 +1950,17 @@ async def aevaluate_run( """ run_ = self._resolve_run_id(run, load_child_runs=load_child_runs) reference_example_ = self._resolve_example_id(reference_example, run_) - evaluation_result = await evaluator.aevaluate_run( + evaluator_response = await evaluator.aevaluate_run( run_, example=reference_example_, ) - source_info = source_info or {} - if evaluation_result.evaluator_info: - source_info = {**evaluation_result.evaluator_info, **source_info} - self.create_feedback( - run_.id, - evaluation_result.key, - score=evaluation_result.score, - value=evaluation_result.value, - comment=evaluation_result.comment, - correction=evaluation_result.correction, + # TODO: Return all results and use async API + results = self._log_evaluation_feedback( + evaluator_response, + run_, source_info=source_info, - source_run_id=evaluation_result.source_run_id, - feedback_source_type=ls_schemas.FeedbackSourceType.MODEL, ) - return evaluation_result + return results[0] def create_feedback( self, diff --git a/python/langsmith/evaluation/evaluator.py b/python/langsmith/evaluation/evaluator.py index 527a8a535..0022a012e 100644 --- a/python/langsmith/evaluation/evaluator.py +++ b/python/langsmith/evaluation/evaluator.py @@ -1,7 +1,7 @@ import asyncio import uuid from abc import abstractmethod -from typing import Dict, Optional, Union +from typing import Dict, Optional, TypedDict, Union try: from pydantic.v1 import BaseModel, Field # type: ignore[import] @@ -27,26 +27,39 @@ class EvaluationResult(BaseModel): evaluator_info: Dict = Field(default_factory=dict) """Additional information about the evaluator.""" source_run_id: Optional[Union[uuid.UUID, str]] = None + """The ID of the trace of the evaluator itself.""" + target_run_id: Optional[Union[uuid.UUID, str]] = None + """The ID of the trace this evaluation is applied to. + + If none provided, the evaluation feedback is applied to the + root trace being.""" class Config: """Pydantic model configuration.""" - frozen = True allow_extra = False +class EvaluationResults(TypedDict, total=False): + """Batch evaluation results, if your evaluator wishes + to return multiple scores.""" + + results: Dict[str, EvaluationResult] + """The evaluation results.""" + + class RunEvaluator: """Evaluator interface class.""" @abstractmethod def evaluate_run( self, run: Run, example: Optional[Example] = None - ) -> EvaluationResult: + ) -> Union[EvaluationResult, EvaluationResults]: """Evaluate an example.""" async def aevaluate_run( self, run: Run, example: Optional[Example] = None - ) -> EvaluationResult: + ) -> Union[EvaluationResult, EvaluationResults]: """Evaluate an example asynchronously.""" return await asyncio.get_running_loop().run_in_executor( None, self.evaluate_run, run, example diff --git a/python/tests/unit_tests/test_client.py b/python/tests/unit_tests/test_client.py index ad0ebe266..b4732fb38 100644 --- a/python/tests/unit_tests/test_client.py +++ b/python/tests/unit_tests/test_client.py @@ -128,7 +128,11 @@ def test_async_methods(): assert sync_method in sync_methods sync_args = set(Client.__dict__[sync_method].__code__.co_varnames) async_args = set(Client.__dict__[async_method].__code__.co_varnames) - assert sync_args.issubset(async_args) + extra_args = sync_args - async_args + assert not extra_args, ( + f"Extra args for {async_method} " + f"(compared to {sync_method}): {extra_args}" + ) def test_get_api_key(): From 0c04410bc9d3184d9ee7a4733334cefe0c35ef07 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Tue, 31 Oct 2023 01:08:39 +0900 Subject: [PATCH 19/19] py0.0.54 (#277) --- python/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index 91e1bdc64..3310af549 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.0.53" +version = "0.0.54" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT"