Compare commits

...
Author SHA1 Message Date
David Asamu 757415f150 implement cache optimization for requirements generation 2026-02-17 16:29:51 +00:00
9f0ae94f27 chore: Re-organize client files. (#6787)
Additional guidelines:

- Make sure optional dependencies are imported within a function.
- Please do not add dependencies to `pyproject.toml` files (even
optional ones) unless they are **required** for unit tests.
- Most PRs should not touch more than one package.
- Changes should be backwards compatible.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:22:59 -05:00
f5e56e200d feat(cli): add keep_latest prune strategy to ThreadTTLConfig (#6784)
## Summary
- Add `"keep_latest"` to `ThreadTTLConfig.strategy` to match
langgraph-api support for pruning old checkpoints while retaining the
thread and its latest state
- Add `sweep_limit` to `ThreadTTLConfig` where the API actually reads it
(was previously a no-op on `CheckpointerConfig`)
- Regenerate `schema.json` / `schema.v0.json`

## Test plan
- [x] `make format && make lint` passes
- [x] `make test` passes (85/85)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:00:48 -08:00
William FHandGitHub f9870bc9ae chore: Drop support for bullseye builds (#6779)
It's EOL for debian.
2026-02-10 15:11:24 -08:00
William FHandGitHub a734f5e6ce chore: server runtime type (#6774)
Main jtbd here:
a) clarify who/how a graph is being accessed and make the factory aware
of the `context` where relevant (and make it obvious when it is
available)
b) make it more clear when you can bypass / defer resources with
expensive lifespans (like MCp connections)
c) make auth access more type-safe.

Gives us room to add other information, like:
- langsmith distributed tracing information



---- old
Can start doing things like this:

```
def my_graph(runtime: ServerRuntime):
     if runtime.ensure_user().permissions not in ("foo"):
         raise ValueError("bar")
```
etc.

Points of expected confusion:
- You won't have a stream_writer in this context.
- This won't be an accessible object within the graph, only the graph
factory.


For maintainers, related draft PR int he server
https://github.com/langchain-ai/langgraph/pull/6774
2026-02-10 08:53:52 -08:00
Luka AladashviliandGitHub 84446f5ad8 refactor: replace bare except with BaseException in AsyncQueue (#6765)
## Description
Replaced a bare `except:` with `except BaseException:` in
`libs/langgraph/langgraph/_internal/_queue.py`.

## Motivation
Using a bare `except:` violates PEP 8 (E722). While functionally
equivalent to `except BaseException:`, making it explicit improves code
readability and satisfies static analysis tools.

This ensures that `asyncio.CancelledError` (which inherits from
`BaseException`) is still caught and handled correctly by the
cancellation logic in the `wait()` method, but without the ambiguity of
a bare except.
2026-02-10 05:08:39 -08:00
Mason DaughertyandGitHub f6d95abbe3 docs(prebuilt): update warning for create_react_agent (#6760) 2026-02-06 15:08:08 -05:00
William FHandGitHub a7a27dd43a release(langgraph): 1.0.8 (#6757) 2026-02-06 07:27:08 -05:00
William FHandGitHub 50238be239 chore: shallow copy futures (#6755) 2026-02-05 19:14:42 -08:00
Sydney RunkleandGitHub 114978b612 fix: pydantic messages double streaming (#6753)
Problem: `StreamMessagesHandler.on_chain_start` only populated the seen
set for dict inputs, so Pydantic/dataclass state, objects were skipped —
causing duplicate messages after interrupt/resume

Solution: Extract a shared `_state_values()` helper that handles dict,
BaseModel, and dataclass inputs uniformly, and use it in both
on_chain_start and on_chain_end
 
Also replaces the fragile dir()/getattr fallback in on_chain_end with
the same helper

Tests: Added test_stream_messages_dedupe_pydantic_subgraph_interrupt —
confirms no duplicate message IDs across interrupt/resume with Pydantic
subgraph state (fails on main, passes with fix)
2026-02-05 17:07:33 -08:00
Rafid SaadandGitHub 0c0a159539 chore: release python sdk (#6754)
- Release cron patch and enabled fields
2026-02-06 00:38:23 +00:00
Mason DaughertyandGitHub f688b068e7 chore(infra): update AGENTS.md for inline code formatting guidelines (#6752) 2026-02-05 18:32:08 -05:00
1fb405bd55 feat(sdk-py): add update method for crons client (#6742)
# Description
- Update Python SDK to add patch method to cron client
- This method lets users modify cron attributes (except assistant ID and
thread ID)

---------

Co-authored-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2026-02-04 08:23:48 -08:00
William FHandGitHub 86b65beb8f chore: Update ThreadTTLConfig (#6730)
Sync with underlying implementation.
2026-02-03 10:52:33 -08:00
Rafid SaadandGitHub 63bd852da9 feat(sdk-py): add support for enabling/disabling crons (#6740)
# Description
- Update Python SDK to support enabling/disabling crons
- Pass `enabled` to cron `create`, `create_for_thread`, and `search`
methods
2026-02-03 10:36:48 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>William Fu-Hinthorn
82f9c09b95 chore(deps-dev): bump ruff from 0.14.7 to 0.14.11 in /libs/sdk-py (#6673)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.14.7 to 0.14.11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.14.11</h2>
<h2>Release Notes</h2>
<p>Released on 2026-01-08.</p>
<h3>Preview features</h3>
<ul>
<li>Consolidate diagnostics for matched disable/enable suppression
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22099">#22099</a>)</li>
<li>Report diagnostics for invalid/unmatched range suppression comments
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/21908">#21908</a>)</li>
<li>[<code>airflow</code>] Passing positional argument into
<code>airflow.lineage.hook.HookLineageCollector.create_asset</code> is
not allowed (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22046">#22046</a>)</li>
<li>[<code>refurb</code>] Mark <code>FURB192</code> fix as always unsafe
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22210">#22210</a>)</li>
<li>[<code>ruff</code>] Add <code>non-empty-init-module</code>
(<code>RUF067</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22143">#22143</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Fix GitHub format for multi-line diagnostics (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22108">#22108</a>)</li>
<li>[<code>flake8-unused-arguments</code>] Mark <code>**kwargs</code> in
<code>TypeVar</code> as used (<code>ARG001</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22214">#22214</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Add <code>help:</code> subdiagnostics for several Ruff rules that
can sometimes appear to disagree with <code>ty</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22331">#22331</a>)</li>
<li>[<code>pylint</code>] Demote <code>PLW1510</code> fix to
display-only (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22318">#22318</a>)</li>
<li>[<code>pylint</code>] Ignore identical members
(<code>PLR1714</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22220">#22220</a>)</li>
<li>[<code>pylint</code>] Improve diagnostic range for
<code>PLC0206</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22312">#22312</a>)</li>
<li>[<code>ruff</code>] Improve fix title for <code>RUF102</code>
invalid rule code (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22100">#22100</a>)</li>
<li>[<code>flake8-simplify</code>]: Avoid unnecessary builtins import
for <code>SIM105</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22358">#22358</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Allow Python 3.15 as valid <code>target-version</code> value in
preview (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22419">#22419</a>)</li>
<li>Check <code>required-version</code> before parsing rules (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22410">#22410</a>)</li>
<li>Include configured <code>src</code> directories when resolving
graphs (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22451">#22451</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Update <code>T201</code> suggestion to not use root logger to
satisfy <code>LOG015</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22059">#22059</a>)</li>
<li>Fix <code>iter</code> example in unsafe fixes doc (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22118">#22118</a>)</li>
<li>[<code>flake8_print</code>] better suggestion for
<code>basicConfig</code> in <code>T201</code> docs (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22101">#22101</a>)</li>
<li>[<code>pylint</code>] Restore the fix safety docs for
<code>PLW0133</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22211">#22211</a>)</li>
<li>Fix Jupyter notebook discovery info for editors (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22447">#22447</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/cenviity"><code>@​cenviity</code></a></li>
<li><a href="https://github.com/njhearp"><code>@​njhearp</code></a></li>
<li><a
href="https://github.com/cbachhuber"><code>@​cbachhuber</code></a></li>
<li><a
href="https://github.com/jelle-openai"><code>@​jelle-openai</code></a></li>
<li><a
href="https://github.com/AlexWaygood"><code>@​AlexWaygood</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.14.11</h2>
<p>Released on 2026-01-08.</p>
<h3>Preview features</h3>
<ul>
<li>Consolidate diagnostics for matched disable/enable suppression
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22099">#22099</a>)</li>
<li>Report diagnostics for invalid/unmatched range suppression comments
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/21908">#21908</a>)</li>
<li>[<code>airflow</code>] Passing positional argument into
<code>airflow.lineage.hook.HookLineageCollector.create_asset</code> is
not allowed (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22046">#22046</a>)</li>
<li>[<code>refurb</code>] Mark <code>FURB192</code> fix as always unsafe
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22210">#22210</a>)</li>
<li>[<code>ruff</code>] Add <code>non-empty-init-module</code>
(<code>RUF067</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22143">#22143</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Fix GitHub format for multi-line diagnostics (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22108">#22108</a>)</li>
<li>[<code>flake8-unused-arguments</code>] Mark <code>**kwargs</code> in
<code>TypeVar</code> as used (<code>ARG001</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22214">#22214</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Add <code>help:</code> subdiagnostics for several Ruff rules that
can sometimes appear to disagree with <code>ty</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22331">#22331</a>)</li>
<li>[<code>pylint</code>] Demote <code>PLW1510</code> fix to
display-only (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22318">#22318</a>)</li>
<li>[<code>pylint</code>] Ignore identical members
(<code>PLR1714</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22220">#22220</a>)</li>
<li>[<code>pylint</code>] Improve diagnostic range for
<code>PLC0206</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22312">#22312</a>)</li>
<li>[<code>ruff</code>] Improve fix title for <code>RUF102</code>
invalid rule code (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22100">#22100</a>)</li>
<li>[<code>flake8-simplify</code>]: Avoid unnecessary builtins import
for <code>SIM105</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22358">#22358</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Allow Python 3.15 as valid <code>target-version</code> value in
preview (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22419">#22419</a>)</li>
<li>Check <code>required-version</code> before parsing rules (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22410">#22410</a>)</li>
<li>Include configured <code>src</code> directories when resolving
graphs (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22451">#22451</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Update <code>T201</code> suggestion to not use root logger to
satisfy <code>LOG015</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22059">#22059</a>)</li>
<li>Fix <code>iter</code> example in unsafe fixes doc (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22118">#22118</a>)</li>
<li>[<code>flake8_print</code>] better suggestion for
<code>basicConfig</code> in <code>T201</code> docs (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22101">#22101</a>)</li>
<li>[<code>pylint</code>] Restore the fix safety docs for
<code>PLW0133</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22211">#22211</a>)</li>
<li>Fix Jupyter notebook discovery info for editors (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22447">#22447</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/cenviity"><code>@​cenviity</code></a></li>
<li><a href="https://github.com/njhearp"><code>@​njhearp</code></a></li>
<li><a
href="https://github.com/cbachhuber"><code>@​cbachhuber</code></a></li>
<li><a
href="https://github.com/jelle-openai"><code>@​jelle-openai</code></a></li>
<li><a
href="https://github.com/AlexWaygood"><code>@​AlexWaygood</code></a></li>
<li><a
href="https://github.com/ValdonVitija"><code>@​ValdonVitija</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/c920cf8cdb247a9fd8e15a4c9d2efa838f7a78a3"><code>c920cf8</code></a>
Bump 0.14.11 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22462">#22462</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/bb757b5a79888f28264f629b5667a0514071f7d6"><code>bb757b5</code></a>
[ty] Don't show diagnostics for excluded files (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22455">#22455</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/1f49e8ef518b75207e155595aba57acd48205078"><code>1f49e8e</code></a>
Include configured <code>src</code> directories when resolving graphs
(<a
href="https://redirect.github.com/astral-sh/ruff/issues/22451">#22451</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/701f5134ab7c1a860145dccc8abb3716a3f89fe7"><code>701f513</code></a>
[ty] Only consider fully static pivots when deriving transitive
constraints (...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eea9ad83528a7f492662f6427cdbb6fc2f655bb5"><code>eea9ad8</code></a>
Pin maturin version (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22454">#22454</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eeac2bd3eed2f4b8f4a71e0c945721481b25efc0"><code>eeac2bd</code></a>
[ty] Optimize union building for unions with many enum-literal members
(<a
href="https://redirect.github.com/astral-sh/ruff/issues/22363">#22363</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/7319c37f4eb063e9590e1f09c8e92d7dabc63403"><code>7319c37</code></a>
docs: fix jupyter notebook discovery info for editors (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22447">#22447</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/805503c19a6b74c5803e10123077997e29a0da37"><code>805503c</code></a>
[<code>ruff</code>] Improve fix title for <code>RUF102</code> invalid
rule code (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22100">#22100</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/68a2f6c57d70052d0805b46b0e3a2538598b856f"><code>68a2f6c</code></a>
[ty] Fix <code>super()</code> with TypeVar-annotated <code>self</code>
and <code>cls</code> parameter (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22208">#22208</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/abaa735e1d027cf458a2ab83d8a422d74111580c"><code>abaa735</code></a>
[ty] Improve <code>UnionBuilder</code> performance by changing
<code>Type::is_subtype_of</code> cal...</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.7...0.14.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ruff&package-manager=pip&previous-version=0.14.7&new-version=0.14.11)](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)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

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 <dependency name> 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)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com>
2026-01-31 00:14:16 -08:00
193e128c20 chore: Omit lock when using connection pool (#6734)
Co-authored-by: Conrad Ludgate <conradludgate@gmail.com>
2026-01-31 00:30:34 +00:00
Mason DaughertyandGitHub c94e7b96ac chore: update contributing/templates (#6732)
Supersedes #6703 -- thanks to @Ramakrishna1967 for flagging
2026-01-30 09:18:18 -08:00
Mason DaughertyandGitHub 2dd39432a3 docs: enhance Runtime and ToolRuntime class descriptions for clarity (#6689) 2026-01-26 13:22:54 -08:00
Mason DaughertyandGitHub 3ff6340379 docs: add clarity to use of thread_id (#6515) 2026-01-26 12:09:01 -08:00
Mason DaughertyandGitHub 0a6145fd72 docs: add docstrings to add_node overloads (#6514)
They were missing `Args` sections, and IDEs don't pick these up from the
canonical.

Each overload now includes the full `Args:` documentation, examples
tailored to that specific signature, and `Returns:` section.
2026-01-26 11:48:34 -08:00
Mason DaughertyandGitHub fbcb8a911b docs: update notebook links and add archival notices for examples (#6720)
Addresses some comments in #6682

- Update links in notebooks to point to the new documentation location.
- Add archival notices indicating that the examples are no longer
updated.
- Remove some obsolete notebooks that have been moved to the new
documentation.

Please comment here if you encounter any issues
2026-01-26 06:00:16 +00:00
William FHandGitHub 2c6f99cbf0 release(cli): 0.4.12 (#6716)
Release Notes: Increase upper bound of `langgraph-ap` to `<0.8`

Closes https://github.com/langchain-ai/langgraph/issues/6706
2026-01-23 05:31:50 -08:00
Sydney RunkleandGitHub 7b9ff6129b release: langgraph and prebuilt 1.0.7 (#6712) 2026-01-22 11:28:22 -05:00
Sydney RunkleandGitHub c1b3598ca8 feat: support dynamic tool calling via tool override in wrap_model_call (#6711)
Allow overriding `tool` impl in `wrap_tool_call` in order to support
dynamically registered tools via middleware
2026-01-22 15:53:43 +00:00
140 changed files with 11768 additions and 8655 deletions
-6
View File
@@ -1,6 +0,0 @@
# Contributing to LangGraph
Hi there! Thank you for even being interested in contributing to LangGraph.
As an open-source project in a rapidly developing field, we are extremely open to contributions, whether they involve new features, improved infrastructure, better documentation, or bug fixes.
To learn how to contribute to LangGraph, please follow the [contribution guide here](https://docs.langchain.com/oss/python/contributing).
+48 -24
View File
@@ -1,43 +1,60 @@
name: "\U0001F41B Bug Report"
description: Report a bug in LangGraph. To report a security issue, please instead use the security option below. For questions, please use the LangChain Forum at forum.langchain.com.
labels: [pending, bug]
description: Report a bug in LangGraph. To report a security issue, please instead use the security option (below). For questions, please use the LangChain forum (below).
labels: ["bug"]
type: bug
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to file a bug report.
Thank you for taking the time to file a bug report.
Use this to report BUGS in LangGraph. For usage questions, feature requests and general design questions, please use the [LangChain Forum](https://forum.langchain.com/).
For usage questions, feature requests and general design questions, please use the [LangChain Forum](https://forum.langchain.com/).
Relevant links to check before filing a bug report to see if your issue has already been reported, fixed or
if there's another way to solve your problem:
Check these before submitting to see if your issue has already been reported, fixed or if there's another way to solve your problem:
* [LangChain Forum](https://forum.langchain.com/),
* [LangGraph Github Issues](https://github.com/langchain-ai/langgraph/issues),
* [LangChain documentation with the integrated search](https://docs.langchain.com/),
* [Documentation](https://docs.langchain.com/oss/python/langgraph/overview),
* [API Reference Documentation](https://reference.langchain.com/python/),
* [LangChain ChatBot](https://chat.langchain.com/)
* [GitHub search](https://github.com/langchain-ai/langgraph),
* [LangChain Forum](https://forum.langchain.com/),
- type: checkboxes
id: checks
attributes:
label: Checked other resources
description: Before submitting this issue, please confirm that you have completed all the steps below by checking each option. These steps help ensure your issue is well-defined, relevant, and actionable.
description: Please confirm and check all the following options.
options:
- label: This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/).
- label: This is a bug, not a usage question.
required: true
- label: I added a clear and detailed title that summarizes the issue.
- label: I added a clear and descriptive title that summarizes this issue.
required: true
- label: I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
- label: I used the GitHub search to find a similar question and didn't find it.
required: true
- label: I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue.
- label: I am sure that this is a bug in LangGraph rather than my code.
required: true
- label: The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package).
required: true
- label: This is not related to the langchain-community package.
required: true
- label: I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.
required: true
- type: textarea
id: reproduction
validations:
required: true
attributes:
label: Example Code
label: Reproduction Steps / Example Code (Python)
description: |
Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case. Replace this code with your own!
Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case.
If a maintainer can copy it, run it, and see it right away, there's a much higher chance that you'll be able to get help.
**Important!**
* Avoid screenshots, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.
* Reduce your code to the minimum required to reproduce the issue if possible.
(This will be automatically formatted into code, so no need for backticks.)
render: python
placeholder: |
from langgraph.graph import StateGraph
@@ -46,17 +63,13 @@ body:
chain = StateGraph(list)
chain.invoke('Hello!')
render: python
- type: textarea
id: error
validations:
required: false
attributes:
label: Error Message and Stack Trace (if applicable)
description: |
If you are reporting an error, please include the full error message and stack trace.
placeholder: |
Exception + full stack trace
If you are reporting an error, please copy and paste the full error message and
stack trace.
(This will be automatically formatted into code, so no need for backticks.)
render: shell
- type: textarea
id: description
@@ -77,7 +90,18 @@ body:
attributes:
label: System Info
description: |
Run on your machine: `python -m langchain_core.sys_info`
Please share your system info with us.
Run the following command in your terminal and paste the output here:
`python -m langchain_core.sys_info`
or if you have an existing python interpreter running:
```python
from langchain_core import sys_info
sys_info.print_sys_info()
```
placeholder: |
python -m langchain_core.sys_info
validations:
+10 -4
View File
@@ -1,9 +1,15 @@
blank_issues_enabled: false
version: 2.1
contact_links:
- name: Documentation
url: https://github.com/langchain-ai/docs/issues/new?template=langgraph.yml
about: Report an issue related to the LangGraph documentation
- name: LangChain Forum
- name: 💬 LangChain Forum
url: https://forum.langchain.com/
about: General community discussions and support
- name: 📚 LangGraph Documentation
url: https://docs.langchain.com/oss/python/langgraph/overview
about: View the official LangGraph documentation
- name: 📚 API Reference Documentation
url: https://reference.langchain.com/python/
about: View the official LangGraph API reference documentation
- name: 📚 Documentation issue
url: https://github.com/langchain-ai/docs/issues/new?template=02-langgraph.yml
about: Report an issue related to the LangGraph documentation
+1 -1
View File
@@ -21,7 +21,7 @@ Thank you for contributing to LangGraph! Follow these steps to mark your pull re
1. A test for the integration, preferably unit tests that do not rely on network access,
2. An example notebook showing its use. It lives in `docs/docs/integrations` directory.
- [ ] **Lint and test**: Run `make format`, `make lint` and `make test` from the root of the package(s) you've modified. We will not consider a PR unless these three are passing in CI. See [contribution guidelines](https://github.com/langchain-ai/langgraph/blob/main/CONTRIBUTING.md) for more.
- [ ] **Lint and test**: Run `make format`, `make lint` and `make test` from the root of the package(s) you've modified. We will not consider a PR unless these three are passing in CI. See [contribution guidelines](https://docs.langchain.com/oss/python/contributing/overview) for more.
Additional guidelines:
+2 -2
View File
@@ -63,7 +63,7 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
try:
sys.stderr.write("\n== docker compose ps ==\n")
runner.run(
subp_exec(*compose_cmd, *args, "ps", input=stdin, verbose=False)
subp_exec(*compose_cmd, *args, "ps", input=stdin, verbose=True)
)
except Exception:
pass
@@ -76,7 +76,7 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
"logs",
"langgraph-api",
input=stdin,
verbose=False,
verbose=True,
)
)
except Exception:
+2 -2
View File
@@ -96,8 +96,8 @@ jobs:
timeout 60 python ../../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-h
echo "Finished starting up langgraph-test-h"
LANGGRAPH_VERSION=$(docker run --rm --entrypoint "" langgraph-test-h python -c "import sys; from importlib.metadata import version; v = version('langgraph'); print(v);")
if [ "$LANGGRAPH_VERSION" != "1.0.2" ]; then
echo "LANGGRAPH_VERSION != 1.0.2; $LANGGRAPH_VERSION"
if [ "$LANGGRAPH_VERSION" != "1.0.8" ]; then
echo "LANGGRAPH_VERSION != 1.0.8; $LANGGRAPH_VERSION"
exit 1
fi
LANGCHAIN_OPENAI_VERSION=$(docker run --rm --entrypoint "" langgraph-test-h python -c "import sys; from importlib.metadata import version; v = version('langchain-openai'); print(v);")
+2
View File
@@ -53,3 +53,5 @@ sdk-js (standalone)
```
Changes to a library may impact all of its dependents shown above.
- Do NOT use Sphinx-style double backtick formatting (` ``code`` `). Use single backticks (`` `code` ``) for inline code references in docstrings and comments.
+2
View File
@@ -53,3 +53,5 @@ sdk-js (standalone)
```
Changes to a library may impact all of its dependents shown above.
- Do NOT use Sphinx-style double backtick formatting (` ``code`` `). Use single backticks (`` `code` ``) for inline code references in docstrings and comments.
+1 -1
View File
@@ -1,3 +1,3 @@
# LangGraph examples
This directory should NOT be used for documentation. All new documentation must be added to `docs/docs/` directory.
This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview). Please refer to the LangChain docs for the most up-to-date examples and usage guidelines for LangGraph.
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "23544406",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/async.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "14f7ca50",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/branching.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -5,7 +5,15 @@
"id": "10251c1c",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "c5fc63df",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -5,7 +5,15 @@
"id": "a4351a24",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/chatbot-simulation-evaluation/langsmith-agent-simulation-evaluation.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/chatbot-simulation-evaluation/langsmith-agent-simulation-evaluation.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "4cc9af1e",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -5,7 +5,15 @@
"id": "a9014f94",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/chatbots/information-gather-prompting.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/chatbots/information-gather-prompting.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "f47ce992",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "2b789e16",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/cloud/how-tos/langgraph_to_langgraph_cloud.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -5,7 +5,15 @@
"id": "1f2f13ca",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/code_assistant/langgraph_code_assistant.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/code_assistant/langgraph_code_assistant.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "5e4c9bfe",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "1d38cbab",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"15d3ac32-cdf3-4800-a30c-f26d828d69c8.png": {
@@ -33,7 +41,9 @@
"id": "e501686f-323f-4b87-8f9c-8ba89133078b",
"metadata": {},
"outputs": [],
"source": ["! pip install -U langchain_community langchain-mistralai langchain langgraph"]
"source": [
"! pip install -U langchain_community langchain-mistralai langchain langgraph"
]
},
{
"cell_type": "markdown",
@@ -51,7 +61,12 @@
"id": "982e4609-86e4-4934-828f-e03d89c20393",
"metadata": {},
"outputs": [],
"source": ["import os\n\nos.environ[\"TOKENIZERS_PARALLELISM\"] = \"true\"\nmistral_api_key = os.getenv(\"MISTRAL_API_KEY\") # Ensure this is set"]
"source": [
"import os\n",
"\n",
"os.environ[\"TOKENIZERS_PARALLELISM\"] = \"true\"\n",
"mistral_api_key = os.getenv(\"MISTRAL_API_KEY\") # Ensure this is set"
]
},
{
"cell_type": "markdown",
@@ -69,7 +84,12 @@
"id": "37b172d2-3a9d-49a8-898c-22ed0cb45c88",
"metadata": {},
"outputs": [],
"source": ["os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\nos.environ[\"LANGCHAIN_ENDPOINT\"] = \"https://api.smith.langchain.com\"\nos.environ[\"LANGCHAIN_API_KEY\"] = \"<your-api-key>\"\nos.environ[\"LANGCHAIN_PROJECT\"] = \"Mistral-code-gen-testing\""]
"source": [
"os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
"os.environ[\"LANGCHAIN_ENDPOINT\"] = \"https://api.smith.langchain.com\"\n",
"os.environ[\"LANGCHAIN_API_KEY\"] = \"<your-api-key>\"\n",
"os.environ[\"LANGCHAIN_PROJECT\"] = \"Mistral-code-gen-testing\""
]
},
{
"cell_type": "markdown",
@@ -87,7 +107,42 @@
"id": "a188c8ca-c053-4e6d-b7af-38a3b6b371c7",
"metadata": {},
"outputs": [],
"source": ["# Select LLM\nfrom langchain_core.prompts import ChatPromptTemplate\nfrom langchain_core.pydantic_v1 import BaseModel, Field\nfrom langchain_mistralai import ChatMistralAI\n\nmistral_model = \"mistral-large-latest\"\nllm = ChatMistralAI(model=mistral_model, temperature=0)\n\n# Prompt\ncode_gen_prompt_claude = ChatPromptTemplate.from_messages(\n [\n (\n \"system\",\n \"\"\"You are a coding assistant. Ensure any code you provide can be executed with all required imports and variables \\n\n defined. Structure your answer: 1) a prefix describing the code solution, 2) the imports, 3) the functioning code block.\n \\n Here is the user question:\"\"\",\n ),\n (\"placeholder\", \"{messages}\"),\n ]\n)\n\n\n# Data model\nclass code(BaseModel):\n \"\"\"Code output\"\"\"\n\n prefix: str = Field(description=\"Description of the problem and approach\")\n imports: str = Field(description=\"Code block import statements\")\n code: str = Field(description=\"Code block not including import statements\")\n description = \"Schema for code solutions to questions about LCEL.\"\n\n\n# LLM\ncode_gen_chain = llm.with_structured_output(code, include_raw=False)"]
"source": [
"# Select LLM\n",
"from langchain_core.prompts import ChatPromptTemplate\n",
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
"from langchain_mistralai import ChatMistralAI\n",
"\n",
"mistral_model = \"mistral-large-latest\"\n",
"llm = ChatMistralAI(model=mistral_model, temperature=0)\n",
"\n",
"# Prompt\n",
"code_gen_prompt_claude = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"\"\"You are a coding assistant. Ensure any code you provide can be executed with all required imports and variables \\n\n",
" defined. Structure your answer: 1) a prefix describing the code solution, 2) the imports, 3) the functioning code block.\n",
" \\n Here is the user question:\"\"\",\n",
" ),\n",
" (\"placeholder\", \"{messages}\"),\n",
" ]\n",
")\n",
"\n",
"\n",
"# Data model\n",
"class code(BaseModel):\n",
" \"\"\"Code output\"\"\"\n",
"\n",
" prefix: str = Field(description=\"Description of the problem and approach\")\n",
" imports: str = Field(description=\"Code block import statements\")\n",
" code: str = Field(description=\"Code block not including import statements\")\n",
" description = \"Schema for code solutions to questions about LCEL.\"\n",
"\n",
"\n",
"# LLM\n",
"code_gen_chain = llm.with_structured_output(code, include_raw=False)"
]
},
{
"cell_type": "code",
@@ -95,7 +150,10 @@
"id": "9fc0290d-5a04-4514-8664-91f9dbf2da7b",
"metadata": {},
"outputs": [],
"source": ["question = \"Write a function for fibonacci.\"\nmessages = [(\"user\", question)]"]
"source": [
"question = \"Write a function for fibonacci.\"\n",
"messages = [(\"user\", question)]"
]
},
{
"cell_type": "code",
@@ -114,7 +172,11 @@
"output_type": "execute_result"
}
],
"source": ["# Test\nresult = code_gen_chain.invoke(messages)\nresult"]
"source": [
"# Test\n",
"result = code_gen_chain.invoke(messages)\n",
"result"
]
},
{
"cell_type": "markdown",
@@ -130,7 +192,28 @@
"id": "183d77b8-f180-4815-b39f-8ef507ec0534",
"metadata": {},
"outputs": [],
"source": ["from typing import Annotated, TypedDict\n\nfrom langgraph.graph.message import AnyMessage, add_messages\n\n\nclass GraphState(TypedDict):\n \"\"\"\n Represents the state of our graph.\n\n Attributes:\n error : Binary flag for control flow to indicate whether test error was tripped\n messages : With user question, error messages, reasoning\n generation : Code solution\n iterations : Number of tries\n \"\"\"\n\n error: str\n messages: Annotated[list[AnyMessage], add_messages]\n generation: str\n iterations: int"]
"source": [
"from typing import Annotated, TypedDict\n",
"\n",
"from langgraph.graph.message import AnyMessage, add_messages\n",
"\n",
"\n",
"class GraphState(TypedDict):\n",
" \"\"\"\n",
" Represents the state of our graph.\n",
"\n",
" Attributes:\n",
" error : Binary flag for control flow to indicate whether test error was tripped\n",
" messages : With user question, error messages, reasoning\n",
" generation : Code solution\n",
" iterations : Number of tries\n",
" \"\"\"\n",
"\n",
" error: str\n",
" messages: Annotated[list[AnyMessage], add_messages]\n",
" generation: str\n",
" iterations: int"
]
},
{
"cell_type": "markdown",
@@ -146,7 +229,163 @@
"id": "14bc89d1-3ca6-4847-a048-1803e0e4600e",
"metadata": {},
"outputs": [],
"source": ["import uuid\n\nfrom langchain_core.pydantic_v1 import BaseModel, Field\n\n### Parameters\nmax_iterations = 3\n\n\n### Nodes\ndef generate(state: GraphState):\n \"\"\"\n Generate a code solution\n\n Args:\n state (dict): The current graph state\n\n Returns:\n state (dict): New key added to state, generation\n \"\"\"\n\n print(\"---GENERATING CODE SOLUTION---\")\n\n # State\n messages = state[\"messages\"]\n iterations = state[\"iterations\"]\n\n # Solution\n code_solution = code_gen_chain.invoke(messages)\n messages += [\n (\n \"assistant\",\n f\"Here is my attempt to solve the problem: {code_solution.prefix} \\n Imports: {code_solution.imports} \\n Code: {code_solution.code}\",\n )\n ]\n\n # Increment\n iterations = iterations + 1\n return {\"generation\": code_solution, \"messages\": messages, \"iterations\": iterations}\n\n\ndef code_check(state: GraphState):\n \"\"\"\n Check code\n\n Args:\n state (dict): The current graph state\n\n Returns:\n state (dict): New key added to state, error\n \"\"\"\n\n print(\"---CHECKING CODE---\")\n\n # State\n messages = state[\"messages\"]\n code_solution = state[\"generation\"]\n iterations = state[\"iterations\"]\n\n # Get solution components\n imports = code_solution.imports\n code = code_solution.code\n\n # Check imports\n try:\n exec(imports)\n except Exception as e:\n print(\"---CODE IMPORT CHECK: FAILED---\")\n error_message = [\n (\n \"user\",\n f\"Your solution failed the import test. Here is the error: {e}. Reflect on this error and your prior attempt to solve the problem. (1) State what you think went wrong with the prior solution and (2) try to solve this problem again. Return the FULL SOLUTION. Use the code tool to structure the output with a prefix, imports, and code block:\",\n )\n ]\n messages += error_message\n return {\n \"generation\": code_solution,\n \"messages\": messages,\n \"iterations\": iterations,\n \"error\": \"yes\",\n }\n\n # Check execution\n try:\n combined_code = f\"{imports}\\n{code}\"\n print(f\"CODE TO TEST: {combined_code}\")\n # Use a shared scope for exec\n global_scope = {}\n exec(combined_code, global_scope)\n except Exception as e:\n print(\"---CODE BLOCK CHECK: FAILED---\")\n error_message = [\n (\n \"user\",\n f\"Your solution failed the code execution test: {e}) Reflect on this error and your prior attempt to solve the problem. (1) State what you think went wrong with the prior solution and (2) try to solve this problem again. Return the FULL SOLUTION. Use the code tool to structure the output with a prefix, imports, and code block:\",\n )\n ]\n messages += error_message\n return {\n \"generation\": code_solution,\n \"messages\": messages,\n \"iterations\": iterations,\n \"error\": \"yes\",\n }\n\n # No errors\n print(\"---NO CODE TEST FAILURES---\")\n return {\n \"generation\": code_solution,\n \"messages\": messages,\n \"iterations\": iterations,\n \"error\": \"no\",\n }\n\n\n### Conditional edges\n\n\ndef decide_to_finish(state: GraphState):\n \"\"\"\n Determines whether to finish.\n\n Args:\n state (dict): The current graph state\n\n Returns:\n str: Next node to call\n \"\"\"\n error = state[\"error\"]\n iterations = state[\"iterations\"]\n\n if error == \"no\" or iterations == max_iterations:\n print(\"---DECISION: FINISH---\")\n return \"end\"\n else:\n print(\"---DECISION: RE-TRY SOLUTION---\")\n return \"generate\"\n\n\n### Utilities\n\n\ndef _print_event(event: dict, _printed: set, max_length=1500):\n current_state = event.get(\"dialog_state\")\n if current_state:\n print(\"Currently in: \", current_state[-1])\n message = event.get(\"messages\")\n if message:\n if isinstance(message, list):\n message = message[-1]\n if message.id not in _printed:\n msg_repr = message.pretty_repr(html=True)\n if len(msg_repr) > max_length:\n msg_repr = msg_repr[:max_length] + \" ... (truncated)\"\n print(msg_repr)\n _printed.add(message.id)"]
"source": [
"import uuid\n",
"\n",
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
"\n",
"### Parameters\n",
"max_iterations = 3\n",
"\n",
"\n",
"### Nodes\n",
"def generate(state: GraphState):\n",
" \"\"\"\n",
" Generate a code solution\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" state (dict): New key added to state, generation\n",
" \"\"\"\n",
"\n",
" print(\"---GENERATING CODE SOLUTION---\")\n",
"\n",
" # State\n",
" messages = state[\"messages\"]\n",
" iterations = state[\"iterations\"]\n",
"\n",
" # Solution\n",
" code_solution = code_gen_chain.invoke(messages)\n",
" messages += [\n",
" (\n",
" \"assistant\",\n",
" f\"Here is my attempt to solve the problem: {code_solution.prefix} \\n Imports: {code_solution.imports} \\n Code: {code_solution.code}\",\n",
" )\n",
" ]\n",
"\n",
" # Increment\n",
" iterations = iterations + 1\n",
" return {\"generation\": code_solution, \"messages\": messages, \"iterations\": iterations}\n",
"\n",
"\n",
"def code_check(state: GraphState):\n",
" \"\"\"\n",
" Check code\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" state (dict): New key added to state, error\n",
" \"\"\"\n",
"\n",
" print(\"---CHECKING CODE---\")\n",
"\n",
" # State\n",
" messages = state[\"messages\"]\n",
" code_solution = state[\"generation\"]\n",
" iterations = state[\"iterations\"]\n",
"\n",
" # Get solution components\n",
" imports = code_solution.imports\n",
" code = code_solution.code\n",
"\n",
" # Check imports\n",
" try:\n",
" exec(imports)\n",
" except Exception as e:\n",
" print(\"---CODE IMPORT CHECK: FAILED---\")\n",
" error_message = [\n",
" (\n",
" \"user\",\n",
" f\"Your solution failed the import test. Here is the error: {e}. Reflect on this error and your prior attempt to solve the problem. (1) State what you think went wrong with the prior solution and (2) try to solve this problem again. Return the FULL SOLUTION. Use the code tool to structure the output with a prefix, imports, and code block:\",\n",
" )\n",
" ]\n",
" messages += error_message\n",
" return {\n",
" \"generation\": code_solution,\n",
" \"messages\": messages,\n",
" \"iterations\": iterations,\n",
" \"error\": \"yes\",\n",
" }\n",
"\n",
" # Check execution\n",
" try:\n",
" combined_code = f\"{imports}\\n{code}\"\n",
" print(f\"CODE TO TEST: {combined_code}\")\n",
" # Use a shared scope for exec\n",
" global_scope = {}\n",
" exec(combined_code, global_scope)\n",
" except Exception as e:\n",
" print(\"---CODE BLOCK CHECK: FAILED---\")\n",
" error_message = [\n",
" (\n",
" \"user\",\n",
" f\"Your solution failed the code execution test: {e}) Reflect on this error and your prior attempt to solve the problem. (1) State what you think went wrong with the prior solution and (2) try to solve this problem again. Return the FULL SOLUTION. Use the code tool to structure the output with a prefix, imports, and code block:\",\n",
" )\n",
" ]\n",
" messages += error_message\n",
" return {\n",
" \"generation\": code_solution,\n",
" \"messages\": messages,\n",
" \"iterations\": iterations,\n",
" \"error\": \"yes\",\n",
" }\n",
"\n",
" # No errors\n",
" print(\"---NO CODE TEST FAILURES---\")\n",
" return {\n",
" \"generation\": code_solution,\n",
" \"messages\": messages,\n",
" \"iterations\": iterations,\n",
" \"error\": \"no\",\n",
" }\n",
"\n",
"\n",
"### Conditional edges\n",
"\n",
"\n",
"def decide_to_finish(state: GraphState):\n",
" \"\"\"\n",
" Determines whether to finish.\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" str: Next node to call\n",
" \"\"\"\n",
" error = state[\"error\"]\n",
" iterations = state[\"iterations\"]\n",
"\n",
" if error == \"no\" or iterations == max_iterations:\n",
" print(\"---DECISION: FINISH---\")\n",
" return \"end\"\n",
" else:\n",
" print(\"---DECISION: RE-TRY SOLUTION---\")\n",
" return \"generate\"\n",
"\n",
"\n",
"### Utilities\n",
"\n",
"\n",
"def _print_event(event: dict, _printed: set, max_length=1500):\n",
" current_state = event.get(\"dialog_state\")\n",
" if current_state:\n",
" print(\"Currently in: \", current_state[-1])\n",
" message = event.get(\"messages\")\n",
" if message:\n",
" if isinstance(message, list):\n",
" message = message[-1]\n",
" if message.id not in _printed:\n",
" msg_repr = message.pretty_repr(html=True)\n",
" if len(msg_repr) > max_length:\n",
" msg_repr = msg_repr[:max_length] + \" ... (truncated)\"\n",
" print(msg_repr)\n",
" _printed.add(message.id)"
]
},
{
"cell_type": "code",
@@ -154,7 +393,31 @@
"id": "2dff2209-44c7-4e2c-b607-ba6675f9e45f",
"metadata": {},
"outputs": [],
"source": ["from langgraph.checkpoint.memory import InMemorySaver\nfrom langgraph.graph import END, StateGraph, START\n\nbuilder = StateGraph(GraphState)\n\n# Define the nodes\nbuilder.add_node(\"generate\", generate) # generation solution\nbuilder.add_node(\"check_code\", code_check) # check code\n\n# Build graph\nbuilder.add_edge(START, \"generate\")\nbuilder.add_edge(\"generate\", \"check_code\")\nbuilder.add_conditional_edges(\n \"check_code\",\n decide_to_finish,\n {\n \"end\": END,\n \"generate\": \"generate\",\n },\n)\n\nmemory = InMemorySaver()\ngraph = builder.compile(checkpointer=memory)"]
"source": [
"from langgraph.checkpoint.memory import InMemorySaver\n",
"from langgraph.graph import END, StateGraph, START\n",
"\n",
"builder = StateGraph(GraphState)\n",
"\n",
"# Define the nodes\n",
"builder.add_node(\"generate\", generate) # generation solution\n",
"builder.add_node(\"check_code\", code_check) # check code\n",
"\n",
"# Build graph\n",
"builder.add_edge(START, \"generate\")\n",
"builder.add_edge(\"generate\", \"check_code\")\n",
"builder.add_conditional_edges(\n",
" \"check_code\",\n",
" decide_to_finish,\n",
" {\n",
" \"end\": END,\n",
" \"generate\": \"generate\",\n",
" },\n",
")\n",
"\n",
"memory = InMemorySaver()\n",
"graph = builder.compile(checkpointer=memory)"
]
},
{
"cell_type": "code",
@@ -173,7 +436,15 @@
"output_type": "display_data"
}
],
"source": ["from IPython.display import Image, display\n\ntry:\n display(Image(graph.get_graph(xray=True).draw_mermaid_png()))\nexcept Exception:\n # This requires some extra dependencies and is optional\n pass"]
"source": [
"from IPython.display import Image, display\n",
"\n",
"try:\n",
" display(Image(graph.get_graph(xray=True).draw_mermaid_png()))\n",
"except Exception:\n",
" # This requires some extra dependencies and is optional\n",
" pass"
]
},
{
"cell_type": "code",
@@ -181,7 +452,23 @@
"id": "242aa2f0-2c31-462f-a958-ff9ae0cf7c62",
"metadata": {},
"outputs": [],
"source": ["_printed = set()\nthread_id = str(uuid.uuid4())\nconfig = {\n \"configurable\": {\n # Checkpoints are accessed by thread_id\n \"thread_id\": thread_id,\n }\n}\n\nquestion = \"Write a Python program that prints 'Hello, World!' to the console.\"\nevents = graph.stream(\n {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n)\nfor event in events:\n _print_event(event, _printed)"]
"source": [
"_printed = set()\n",
"thread_id = str(uuid.uuid4())\n",
"config = {\n",
" \"configurable\": {\n",
" # Checkpoints are accessed by thread_id\n",
" \"thread_id\": thread_id,\n",
" }\n",
"}\n",
"\n",
"question = \"Write a Python program that prints 'Hello, World!' to the console.\"\n",
"events = graph.stream(\n",
" {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n",
")\n",
"for event in events:\n",
" _print_event(event, _printed)"
]
},
{
"cell_type": "markdown",
@@ -199,7 +486,31 @@
"id": "390b2768-f395-4aea-8b0e-9d36212a31ac",
"metadata": {},
"outputs": [],
"source": ["_printed = set()\nthread_id = str(uuid.uuid4())\nconfig = {\n \"configurable\": {\n # Checkpoints are accessed by thread_id\n \"thread_id\": thread_id,\n }\n}\n\nquestion = \"\"\"Create a Python program that checks if a given string is a palindrome. A palindrome is a word, phrase, number, or other sequence of characters that reads the same forward and backward (ignoring spaces, punctuation, and capitalization).\n\nRequirements:\nThe program should define a function is_palindrome(s) that takes a string s as input.\nThe function should return True if the string is a palindrome and False otherwise.\nIgnore spaces, punctuation, and case differences when checking for palindromes.\n\nGive an example of it working on an example input word.\"\"\"\n\nevents = graph.stream(\n {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n)\nfor event in events:\n _print_event(event, _printed)"]
"source": [
"_printed = set()\n",
"thread_id = str(uuid.uuid4())\n",
"config = {\n",
" \"configurable\": {\n",
" # Checkpoints are accessed by thread_id\n",
" \"thread_id\": thread_id,\n",
" }\n",
"}\n",
"\n",
"question = \"\"\"Create a Python program that checks if a given string is a palindrome. A palindrome is a word, phrase, number, or other sequence of characters that reads the same forward and backward (ignoring spaces, punctuation, and capitalization).\n",
"\n",
"Requirements:\n",
"The program should define a function is_palindrome(s) that takes a string s as input.\n",
"The function should return True if the string is a palindrome and False otherwise.\n",
"Ignore spaces, punctuation, and case differences when checking for palindromes.\n",
"\n",
"Give an example of it working on an example input word.\"\"\"\n",
"\n",
"events = graph.stream(\n",
" {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n",
")\n",
"for event in events:\n",
" _print_event(event, _printed)"
]
},
{
"cell_type": "markdown",
@@ -217,7 +528,26 @@
"id": "0a3f946b-e2f2-44d9-905b-09f36980cf9f",
"metadata": {},
"outputs": [],
"source": ["_printed = set()\nthread_id = str(uuid.uuid4())\nconfig = {\n \"configurable\": {\n # Checkpoints are accessed by thread_id\n \"thread_id\": thread_id,\n }\n}\n\nquestion = \"\"\"Write a program that prints the numbers from 1 to 100. \nBut for multiples of three, print \"Fizz\" instead of the number, and for the multiples of five, print \"Buzz\". \nFor numbers which are multiples of both three and five, print \"FizzBuzz\".\"\"\"\n\nevents = graph.stream(\n {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n)\nfor event in events:\n _print_event(event, _printed)"]
"source": [
"_printed = set()\n",
"thread_id = str(uuid.uuid4())\n",
"config = {\n",
" \"configurable\": {\n",
" # Checkpoints are accessed by thread_id\n",
" \"thread_id\": thread_id,\n",
" }\n",
"}\n",
"\n",
"question = \"\"\"Write a program that prints the numbers from 1 to 100. \n",
"But for multiples of three, print \"Fizz\" instead of the number, and for the multiples of five, print \"Buzz\". \n",
"For numbers which are multiples of both three and five, print \"FizzBuzz\".\"\"\"\n",
"\n",
"events = graph.stream(\n",
" {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n",
")\n",
"for event in events:\n",
" _print_event(event, _printed)"
]
},
{
"cell_type": "markdown",
@@ -235,7 +565,37 @@
"id": "2bb883df-540b-46ab-9415-fe27db68456f",
"metadata": {},
"outputs": [],
"source": ["import uuid\n\n_printed = set()\nthread_id = str(uuid.uuid4())\nconfig = {\n \"configurable\": {\n # Checkpoints are accessed by thread_id\n \"thread_id\": thread_id,\n }\n}\n\nquestion = \"\"\"I want to vectorize a function\n\n frame = np.zeros((out_h, out_w, 3), dtype=np.uint8)\n for i, val1 in enumerate(rows):\n for j, val2 in enumerate(cols):\n for j, val3 in enumerate(ch):\n # Assuming you want to store the pair as tuples in the matrix\n frame[i, j, k] = image[val1, val2, val3]\n\n out.write(np.array(frame))\n\nwith a simple numpy function that does something like this what is it called. Show me a test case with this working.\"\"\"\n\nevents = graph.stream(\n {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n)\nfor event in events:\n _print_event(event, _printed)"]
"source": [
"import uuid\n",
"\n",
"_printed = set()\n",
"thread_id = str(uuid.uuid4())\n",
"config = {\n",
" \"configurable\": {\n",
" # Checkpoints are accessed by thread_id\n",
" \"thread_id\": thread_id,\n",
" }\n",
"}\n",
"\n",
"question = \"\"\"I want to vectorize a function\n",
"\n",
" frame = np.zeros((out_h, out_w, 3), dtype=np.uint8)\n",
" for i, val1 in enumerate(rows):\n",
" for j, val2 in enumerate(cols):\n",
" for j, val3 in enumerate(ch):\n",
" # Assuming you want to store the pair as tuples in the matrix\n",
" frame[i, j, k] = image[val1, val2, val3]\n",
"\n",
" out.write(np.array(frame))\n",
"\n",
"with a simple numpy function that does something like this what is it called. Show me a test case with this working.\"\"\"\n",
"\n",
"events = graph.stream(\n",
" {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n",
")\n",
"for event in events:\n",
" _print_event(event, _printed)"
]
},
{
"cell_type": "markdown",
@@ -253,7 +613,34 @@
"id": "ee05da1f-c272-405d-8a7b-552cfc3106e1",
"metadata": {},
"outputs": [],
"source": ["_printed = set()\nthread_id = str(uuid.uuid4())\nconfig = {\n \"configurable\": {\n # Checkpoints are accessed by thread_id\n \"thread_id\": thread_id,\n }\n}\n\nquestion = \"\"\"Create a Python program that allows two players to play a game of Tic-Tac-Toe. The game should be played on a 3x3 grid. The program should:\n\n- Allow players to take turns to input their moves.\n- Check for invalid moves (e.g., placing a marker on an already occupied space).\n- Determine and announce the winner or if the game ends in a draw.\n\nRequirements:\n- Use a 2D list to represent the Tic-Tac-Toe board.\n- Use functions to modularize the code.\n- Validate player input.\n- Check for win conditions and draw conditions after each move.\"\"\"\n\nevents = graph.stream(\n {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n)\nfor event in events:\n _print_event(event, _printed)"]
"source": [
"_printed = set()\n",
"thread_id = str(uuid.uuid4())\n",
"config = {\n",
" \"configurable\": {\n",
" # Checkpoints are accessed by thread_id\n",
" \"thread_id\": thread_id,\n",
" }\n",
"}\n",
"\n",
"question = \"\"\"Create a Python program that allows two players to play a game of Tic-Tac-Toe. The game should be played on a 3x3 grid. The program should:\n",
"\n",
"- Allow players to take turns to input their moves.\n",
"- Check for invalid moves (e.g., placing a marker on an already occupied space).\n",
"- Determine and announce the winner or if the game ends in a draw.\n",
"\n",
"Requirements:\n",
"- Use a 2D list to represent the Tic-Tac-Toe board.\n",
"- Use functions to modularize the code.\n",
"- Validate player input.\n",
"- Check for win conditions and draw conditions after each move.\"\"\"\n",
"\n",
"events = graph.stream(\n",
" {\"messages\": [(\"user\", question)], \"iterations\": 0}, config, stream_mode=\"values\"\n",
")\n",
"for event in events:\n",
" _print_event(event, _printed)"
]
},
{
"cell_type": "markdown",
@@ -271,7 +658,7 @@
"id": "814fc2a4-8e5b-4faa-8f52-3977226bd09a",
"metadata": {},
"outputs": [],
"source": [""]
"source": []
}
],
"metadata": {
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e9a58c69",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/configuration.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "a1e6efeb",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/create-react-agent-hitl.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "1ef41a89",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/create-react-agent-memory.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9e2f7902",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/create-react-agent-system-prompt.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "eb07372e",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/create-react-agent.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -5,7 +5,15 @@
"id": "a8232bc9",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/customer-support/customer-support.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/customer-support/customer-support.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "63da8671",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "8dbdba5b",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/extraction/retries.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/extraction/retries.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "1d444b7f",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -5,7 +5,15 @@
"id": "3ecab357",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/human_in_the_loop/wait-user-input.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/how-tos/human_in_the_loop/wait-user-input.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "3f2866bd",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "fc0793cb",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/input_output_schema.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "09038b53",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/lats/lats.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/lats/lats.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "b1669748",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "85205e97",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/llm-compiler/LLMCompiler.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/llm-compiler/LLMCompiler.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "2fdab366",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "42abb708",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/map-reduce.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "298784f6",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/memory/add-summary-conversation-history.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "3f4370fd",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/memory/delete-messages.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "6ec7cb13",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/memory/manage-conversation-history.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -5,7 +5,15 @@
"id": "5cc8a2ad",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "b9f3508a",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -5,7 +5,15 @@
"id": "d2b507b9",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "41a8f10a",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "017a01f4",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/node-retries.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "env",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "05f6ad0a",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/pass-config-to-tools.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "8f38bec5",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/pass-run-time-values-to-tools.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "4da17088",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/pass_private_state.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "d16e8b9c",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/memory/add-memory.md."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "78217098",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/persistence_mongodb.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "18526f23",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/memory/add-memory.md"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "eee6ecdd",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/persistence_redis.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -5,7 +5,15 @@
"id": "9138f92e",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/plan-and-execute/plan-and-execute.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/plan-and-execute/plan-and-execute.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "093678ba",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "fedd6d23",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"36fa621a-9d3d-4860-a17c-5d20e6987481.png": {
File diff suppressed because one or more lines are too long
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "39b26b09",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"3755396d-c4a8-45bd-87d4-00cb56339fe5.png": {
+11 -3
View File
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "47e3b43b",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"cell_type": "markdown",
"id": "425fb020-e864-40ce-a31f-8da40c73d14b",
@@ -200,11 +208,11 @@
"output_type": "stream",
"text": [
"********************Prompt[rlm/rag-prompt]********************\n",
"================================\u001B[1m Human Message \u001B[0m=================================\n",
"================================\u001b[1m Human Message \u001b[0m=================================\n",
"\n",
"You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.\n",
"Question: \u001B[33;1m\u001B[1;3m{question}\u001B[0m \n",
"Context: \u001B[33;1m\u001B[1;3m{context}\u001B[0m \n",
"Question: \u001b[33;1m\u001b[1;3m{question}\u001b[0m \n",
"Context: \u001b[33;1m\u001b[1;3m{context}\u001b[0m \n",
"Answer:\n"
]
}
+8
View File
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "c71da2ea",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"683fae34-980f-43f0-a9c2-9894bebd9157.png": {
+8
View File
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "ac7db067",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"b77a7d3b-b28a-4dcf-9f1a-861f2f2c5f6c.png": {
+8
View File
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "b3d959ff",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"15cba0ab-a549-4909-8373-fb761e384eff.png": {
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "345488d8",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"5fca0a3e-d13d-4bfa-95ea-58203640cc7a.png": {
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "403aeb6e",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. Please see the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview) for the most current information and resources."
]
},
{
"attachments": {
"15cba0ab-a549-4909-8373-fb761e384eff.png": {
@@ -54,7 +62,11 @@
"metadata": {},
"outputs": [],
"source": [
"import os\n\nos.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\nos.environ[\"LANGCHAIN_ENDPOINT\"] = \"https://api.smith.langchain.com\"\nos.environ[\"LANGCHAIN_API_KEY\"] = \"<your-api-key>\""
"import os\n",
"\n",
"os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
"os.environ[\"LANGCHAIN_ENDPOINT\"] = \"https://api.smith.langchain.com\"\n",
"os.environ[\"LANGCHAIN_API_KEY\"] = \"<your-api-key>\""
]
},
{
@@ -64,7 +76,9 @@
"metadata": {},
"outputs": [],
"source": [
"import os\n\nos.environ[\"LANGCHAIN_PROJECT\"] = \"pinecone-devconnect\""
"import os\n",
"\n",
"os.environ[\"LANGCHAIN_PROJECT\"] = \"pinecone-devconnect\""
]
},
{
@@ -84,7 +98,18 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import OpenAIEmbeddings\nfrom langchain_pinecone import PineconeVectorStore\n\n# use pinecone movies database\n\n# Add to vectorDB\nvectorstore = PineconeVectorStore(\n embedding=OpenAIEmbeddings(),\n index_name=\"sample-movies\",\n text_key=\"summary\",\n)\nretriever = vectorstore.as_retriever()"
"from langchain_openai import OpenAIEmbeddings\n",
"from langchain_pinecone import PineconeVectorStore\n",
"\n",
"# use pinecone movies database\n",
"\n",
"# Add to vectorDB\n",
"vectorstore = PineconeVectorStore(\n",
" embedding=OpenAIEmbeddings(),\n",
" index_name=\"sample-movies\",\n",
" text_key=\"summary\",\n",
")\n",
"retriever = vectorstore.as_retriever()"
]
},
{
@@ -113,7 +138,11 @@
}
],
"source": [
"docs = retriever.invoke(\"James Cameron\")\nfor doc in docs:\n print(\"# \" + doc.metadata[\"title\"])\n print(doc.page_content)\n print()"
"docs = retriever.invoke(\"James Cameron\")\n",
"for doc in docs:\n",
" print(\"# \" + doc.metadata[\"title\"])\n",
" print(doc.page_content)\n",
" print()"
]
},
{
@@ -173,7 +202,12 @@
}
],
"source": [
"# Test the retrieval grader\nquestion = \"movies starring jason momoa\"\ndocs = retriever.invoke(question)\ndoc_txt = docs[0].page_content\nprint(doc_txt)\nprint(retrieval_grader.invoke({\"question\": question, \"document\": doc_txt}))"
"# Test the retrieval grader\n",
"question = \"movies starring jason momoa\"\n",
"docs = retriever.invoke(question)\n",
"doc_txt = docs[0].page_content\n",
"print(doc_txt)\n",
"print(retrieval_grader.invoke({\"question\": question, \"document\": doc_txt}))"
]
},
{
@@ -201,7 +235,23 @@
}
],
"source": [
"### Generate\n\nfrom langchain import hub\nfrom langchain_core.output_parsers import StrOutputParser\n\n# Prompt\nprompt = hub.pull(\"rlm/rag-prompt\")\n\n# LLM\nllm = ChatOpenAI(model_name=\"gpt-3.5-turbo\", temperature=0)\n\n# Chain\nrag_chain = prompt | llm | StrOutputParser()\n\n# Run\ngeneration = rag_chain.invoke({\"context\": docs, \"question\": question})\nprint(generation)"
"### Generate\n",
"\n",
"from langchain import hub\n",
"from langchain_core.output_parsers import StrOutputParser\n",
"\n",
"# Prompt\n",
"prompt = hub.pull(\"rlm/rag-prompt\")\n",
"\n",
"# LLM\n",
"llm = ChatOpenAI(model_name=\"gpt-3.5-turbo\", temperature=0)\n",
"\n",
"# Chain\n",
"rag_chain = prompt | llm | StrOutputParser()\n",
"\n",
"# Run\n",
"generation = rag_chain.invoke({\"context\": docs, \"question\": question})\n",
"print(generation)"
]
},
{
@@ -329,7 +379,17 @@
}
],
"source": [
"### Question Re-writer\n\n# LLM\nllm = ChatOpenAI(model=\"gpt-3.5-turbo-0125\", temperature=0)\n\n# Prompt\nre_write_prompt = hub.pull(\"efriis/self-rag-question-rewriter\")\n\nquestion_rewriter = re_write_prompt | llm | StrOutputParser()\nprint(question)\nquestion_rewriter.invoke({\"question\": question})"
"### Question Re-writer\n",
"\n",
"# LLM\n",
"llm = ChatOpenAI(model=\"gpt-3.5-turbo-0125\", temperature=0)\n",
"\n",
"# Prompt\n",
"re_write_prompt = hub.pull(\"efriis/self-rag-question-rewriter\")\n",
"\n",
"question_rewriter = re_write_prompt | llm | StrOutputParser()\n",
"print(question)\n",
"question_rewriter.invoke({\"question\": question})"
]
},
{
@@ -351,7 +411,24 @@
"metadata": {},
"outputs": [],
"source": [
"from typing import List\n\nfrom typing_extensions import TypedDict\n\n\nclass GraphState(TypedDict):\n \"\"\"\n Represents the state of our graph.\n\n Attributes:\n question: question\n generation: LLM generation\n documents: list of documents\n \"\"\"\n\n question: str\n generation: str\n documents: List[str]"
"from typing import List\n",
"\n",
"from typing_extensions import TypedDict\n",
"\n",
"\n",
"class GraphState(TypedDict):\n",
" \"\"\"\n",
" Represents the state of our graph.\n",
"\n",
" Attributes:\n",
" question: question\n",
" generation: LLM generation\n",
" documents: list of documents\n",
" \"\"\"\n",
"\n",
" question: str\n",
" generation: str\n",
" documents: List[str]"
]
},
{
@@ -361,7 +438,95 @@
"metadata": {},
"outputs": [],
"source": [
"### Nodes\n\n\ndef retrieve(state):\n \"\"\"\n Retrieve documents\n\n Args:\n state (dict): The current graph state\n\n Returns:\n state (dict): New key added to state, documents, that contains retrieved documents\n \"\"\"\n print(\"---RETRIEVE---\")\n question = state[\"question\"]\n\n # Retrieval\n documents = retriever.invoke(question)\n return {\"documents\": documents, \"question\": question}\n\n\ndef generate(state):\n \"\"\"\n Generate answer\n\n Args:\n state (dict): The current graph state\n\n Returns:\n state (dict): New key added to state, generation, that contains LLM generation\n \"\"\"\n print(\"---GENERATE---\")\n question = state[\"question\"]\n documents = state[\"documents\"]\n\n # RAG generation\n generation = rag_chain.invoke({\"context\": documents, \"question\": question})\n return {\"documents\": documents, \"question\": question, \"generation\": generation}\n\n\ndef grade_documents(state):\n \"\"\"\n Determines whether the retrieved documents are relevant to the question.\n\n Args:\n state (dict): The current graph state\n\n Returns:\n state (dict): Updates documents key with only filtered relevant documents\n \"\"\"\n\n print(\"---CHECK DOCUMENT RELEVANCE TO QUESTION---\")\n question = state[\"question\"]\n documents = state[\"documents\"]\n\n # Score each doc\n filtered_docs = []\n for d in documents:\n score = retrieval_grader.invoke(\n {\"question\": question, \"document\": d.page_content}\n )\n grade = score.binary_score\n if grade == \"yes\":\n print(\"---GRADE: DOCUMENT RELEVANT---\")\n filtered_docs.append(d)\n else:\n print(\"---GRADE: DOCUMENT NOT RELEVANT---\")\n continue\n return {\"documents\": filtered_docs, \"question\": question}\n\n\ndef transform_query(state):\n \"\"\"\n Transform the query to produce a better question.\n\n Args:\n state (dict): The current graph state\n\n Returns:\n state (dict): Updates question key with a re-phrased question\n \"\"\"\n\n print(\"---TRANSFORM QUERY---\")\n question = state[\"question\"]\n documents = state[\"documents\"]\n\n # Re-write question\n better_question = question_rewriter.invoke({\"question\": question})\n return {\"documents\": documents, \"question\": better_question}"
"### Nodes\n",
"\n",
"\n",
"def retrieve(state):\n",
" \"\"\"\n",
" Retrieve documents\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" state (dict): New key added to state, documents, that contains retrieved documents\n",
" \"\"\"\n",
" print(\"---RETRIEVE---\")\n",
" question = state[\"question\"]\n",
"\n",
" # Retrieval\n",
" documents = retriever.invoke(question)\n",
" return {\"documents\": documents, \"question\": question}\n",
"\n",
"\n",
"def generate(state):\n",
" \"\"\"\n",
" Generate answer\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" state (dict): New key added to state, generation, that contains LLM generation\n",
" \"\"\"\n",
" print(\"---GENERATE---\")\n",
" question = state[\"question\"]\n",
" documents = state[\"documents\"]\n",
"\n",
" # RAG generation\n",
" generation = rag_chain.invoke({\"context\": documents, \"question\": question})\n",
" return {\"documents\": documents, \"question\": question, \"generation\": generation}\n",
"\n",
"\n",
"def grade_documents(state):\n",
" \"\"\"\n",
" Determines whether the retrieved documents are relevant to the question.\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" state (dict): Updates documents key with only filtered relevant documents\n",
" \"\"\"\n",
"\n",
" print(\"---CHECK DOCUMENT RELEVANCE TO QUESTION---\")\n",
" question = state[\"question\"]\n",
" documents = state[\"documents\"]\n",
"\n",
" # Score each doc\n",
" filtered_docs = []\n",
" for d in documents:\n",
" score = retrieval_grader.invoke(\n",
" {\"question\": question, \"document\": d.page_content}\n",
" )\n",
" grade = score.binary_score\n",
" if grade == \"yes\":\n",
" print(\"---GRADE: DOCUMENT RELEVANT---\")\n",
" filtered_docs.append(d)\n",
" else:\n",
" print(\"---GRADE: DOCUMENT NOT RELEVANT---\")\n",
" continue\n",
" return {\"documents\": filtered_docs, \"question\": question}\n",
"\n",
"\n",
"def transform_query(state):\n",
" \"\"\"\n",
" Transform the query to produce a better question.\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" state (dict): Updates question key with a re-phrased question\n",
" \"\"\"\n",
"\n",
" print(\"---TRANSFORM QUERY---\")\n",
" question = state[\"question\"]\n",
" documents = state[\"documents\"]\n",
"\n",
" # Re-write question\n",
" better_question = question_rewriter.invoke({\"question\": question})\n",
" return {\"documents\": documents, \"question\": better_question}"
]
},
{
@@ -371,7 +536,74 @@
"metadata": {},
"outputs": [],
"source": [
"### Edges\n\n\ndef decide_to_generate(state):\n \"\"\"\n Determines whether to generate an answer, or re-generate a question.\n\n Args:\n state (dict): The current graph state\n\n Returns:\n str: Binary decision for next node to call\n \"\"\"\n\n print(\"---ASSESS GRADED DOCUMENTS---\")\n state[\"question\"]\n filtered_documents = state[\"documents\"]\n\n if not filtered_documents:\n # All documents have been filtered check_relevance\n # We will re-generate a new query\n print(\n \"---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, TRANSFORM QUERY---\"\n )\n return \"transform_query\"\n else:\n # We have relevant documents, so generate answer\n print(\"---DECISION: GENERATE---\")\n return \"generate\"\n\n\ndef grade_generation_v_documents_and_question(state):\n \"\"\"\n Determines whether the generation is grounded in the document and answers question.\n\n Args:\n state (dict): The current graph state\n\n Returns:\n str: Decision for next node to call\n \"\"\"\n\n print(\"---CHECK HALLUCINATIONS---\")\n question = state[\"question\"]\n documents = state[\"documents\"]\n generation = state[\"generation\"]\n\n score = hallucination_grader.invoke(\n {\"documents\": documents, \"generation\": generation}\n )\n grade = score.binary_score\n\n # Check hallucination\n if grade == \"yes\":\n print(\"---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---\")\n # Check question-answering\n print(\"---GRADE GENERATION vs QUESTION---\")\n score = answer_grader.invoke({\"question\": question, \"generation\": generation})\n grade = score.binary_score\n if grade == \"yes\":\n print(\"---DECISION: GENERATION ADDRESSES QUESTION---\")\n return \"useful\"\n else:\n print(\"---DECISION: GENERATION DOES NOT ADDRESS QUESTION---\")\n return \"not useful\"\n else:\n pprint(\"---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\")\n return \"not supported\""
"### Edges\n",
"\n",
"\n",
"def decide_to_generate(state):\n",
" \"\"\"\n",
" Determines whether to generate an answer, or re-generate a question.\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" str: Binary decision for next node to call\n",
" \"\"\"\n",
"\n",
" print(\"---ASSESS GRADED DOCUMENTS---\")\n",
" state[\"question\"]\n",
" filtered_documents = state[\"documents\"]\n",
"\n",
" if not filtered_documents:\n",
" # All documents have been filtered check_relevance\n",
" # We will re-generate a new query\n",
" print(\n",
" \"---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, TRANSFORM QUERY---\"\n",
" )\n",
" return \"transform_query\"\n",
" else:\n",
" # We have relevant documents, so generate answer\n",
" print(\"---DECISION: GENERATE---\")\n",
" return \"generate\"\n",
"\n",
"\n",
"def grade_generation_v_documents_and_question(state):\n",
" \"\"\"\n",
" Determines whether the generation is grounded in the document and answers question.\n",
"\n",
" Args:\n",
" state (dict): The current graph state\n",
"\n",
" Returns:\n",
" str: Decision for next node to call\n",
" \"\"\"\n",
"\n",
" print(\"---CHECK HALLUCINATIONS---\")\n",
" question = state[\"question\"]\n",
" documents = state[\"documents\"]\n",
" generation = state[\"generation\"]\n",
"\n",
" score = hallucination_grader.invoke(\n",
" {\"documents\": documents, \"generation\": generation}\n",
" )\n",
" grade = score.binary_score\n",
"\n",
" # Check hallucination\n",
" if grade == \"yes\":\n",
" print(\"---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---\")\n",
" # Check question-answering\n",
" print(\"---GRADE GENERATION vs QUESTION---\")\n",
" score = answer_grader.invoke({\"question\": question, \"generation\": generation})\n",
" grade = score.binary_score\n",
" if grade == \"yes\":\n",
" print(\"---DECISION: GENERATION ADDRESSES QUESTION---\")\n",
" return \"useful\"\n",
" else:\n",
" print(\"---DECISION: GENERATION DOES NOT ADDRESS QUESTION---\")\n",
" return \"not useful\"\n",
" else:\n",
" pprint(\"---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\")\n",
" return \"not supported\""
]
},
{
@@ -390,7 +622,42 @@
"id": "0e09ca9f-e36d-4ef4-a0d5-79fdbada9fe0",
"metadata": {},
"outputs": [],
"source": ["from langgraph.graph import END, StateGraph, START\n\nworkflow = StateGraph(GraphState)\n\n# Define the nodes\nworkflow.add_node(\"retrieve\", retrieve) # retrieve\nworkflow.add_node(\"grade_documents\", grade_documents) # grade documents\nworkflow.add_node(\"generate\", generate) # generate\nworkflow.add_node(\"transform_query\", transform_query) # transform_query\n\n# Build graph\nworkflow.add_edge(START, \"retrieve\")\nworkflow.add_edge(\"retrieve\", \"grade_documents\")\nworkflow.add_conditional_edges(\n \"grade_documents\",\n decide_to_generate,\n {\n \"transform_query\": \"transform_query\",\n \"generate\": \"generate\",\n },\n)\nworkflow.add_edge(\"transform_query\", \"retrieve\")\nworkflow.add_conditional_edges(\n \"generate\",\n grade_generation_v_documents_and_question,\n {\n \"not supported\": \"generate\",\n \"useful\": END,\n \"not useful\": \"transform_query\",\n },\n)\n\n# Compile\napp = workflow.compile()"]
"source": [
"from langgraph.graph import END, StateGraph, START\n",
"\n",
"workflow = StateGraph(GraphState)\n",
"\n",
"# Define the nodes\n",
"workflow.add_node(\"retrieve\", retrieve) # retrieve\n",
"workflow.add_node(\"grade_documents\", grade_documents) # grade documents\n",
"workflow.add_node(\"generate\", generate) # generate\n",
"workflow.add_node(\"transform_query\", transform_query) # transform_query\n",
"\n",
"# Build graph\n",
"workflow.add_edge(START, \"retrieve\")\n",
"workflow.add_edge(\"retrieve\", \"grade_documents\")\n",
"workflow.add_conditional_edges(\n",
" \"grade_documents\",\n",
" decide_to_generate,\n",
" {\n",
" \"transform_query\": \"transform_query\",\n",
" \"generate\": \"generate\",\n",
" },\n",
")\n",
"workflow.add_edge(\"transform_query\", \"retrieve\")\n",
"workflow.add_conditional_edges(\n",
" \"generate\",\n",
" grade_generation_v_documents_and_question,\n",
" {\n",
" \"not supported\": \"generate\",\n",
" \"useful\": END,\n",
" \"not useful\": \"transform_query\",\n",
" },\n",
")\n",
"\n",
"# Compile\n",
"app = workflow.compile()"
]
},
{
"cell_type": "code",
@@ -426,7 +693,18 @@
}
],
"source": [
"from pprint import pprint\n\n# Run\ninputs = {\"question\": \"Movies that star Daniel Craig\"}\nfor output in app.stream(inputs):\n for key, value in output.items():\n # Node\n pprint(f\"Node '{key}':\")\n pprint(\"\\n---\\n\")\n\n# Final generation\npprint(value[\"generation\"])"
"from pprint import pprint\n",
"\n",
"# Run\n",
"inputs = {\"question\": \"Movies that star Daniel Craig\"}\n",
"for output in app.stream(inputs):\n",
" for key, value in output.items():\n",
" # Node\n",
" pprint(f\"Node '{key}':\")\n",
" pprint(\"\\n---\\n\")\n",
"\n",
"# Final generation\n",
"pprint(value[\"generation\"])"
]
},
{
@@ -436,7 +714,15 @@
"metadata": {},
"outputs": [],
"source": [
"inputs = {\"question\": \"Which movies are about aliens?\"}\nfor output in app.stream(inputs):\n for key, value in output.items():\n # Node\n pprint(f\"Node '{key}':\")\n pprint(\"\\n---\\n\")\n\n# Final generation\npprint(value[\"generation\"])"
"inputs = {\"question\": \"Which movies are about aliens?\"}\n",
"for output in app.stream(inputs):\n",
" for key, value in output.items():\n",
" # Node\n",
" pprint(f\"Node '{key}':\")\n",
" pprint(\"\\n---\\n\")\n",
"\n",
"# Final generation\n",
"pprint(value[\"generation\"])"
]
},
{
@@ -445,9 +731,7 @@
"id": "42369ab8-322d-434a-b5dd-2266e4cb2903",
"metadata": {},
"outputs": [],
"source": [
""
]
"source": []
}
],
"metadata": {
+8 -1
View File
@@ -5,7 +5,14 @@
"id": "294995c4",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/react-agent-from-scratch.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/how-tos/react-agent-from-scratch.ipynb)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+8 -1
View File
@@ -5,7 +5,14 @@
"id": "40f0d107",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/react-agent-structured-output.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/how-tos/react-agent-structured-output.ipynb)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "fa3f7c50",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/recursion-limit.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "658773a2",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/reflection/reflection.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/reflection/reflection.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "1cb60657",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "caf07859",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/reflexion/reflexion.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/reflexion/reflexion.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "cd1df0e0",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "961f43ec",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/rewoo/rewoo.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/rewoo/rewoo.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "7f00c427",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+8 -1
View File
@@ -5,7 +5,14 @@
"id": "bbd6e9b8",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/run-id-langsmith.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/how-tos/run-id-langsmith.md)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "f6db1873",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/self-discover/self-discover.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/self-discover/self-discover.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "219a78f9",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "4149ffcc",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/state-model.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "3e05d7f9",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/storm/storm.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e663f597",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/stream-multiple.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e6829c80",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/stream-updates.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "5ec11895",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/stream-values.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "6619387c",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/streaming-content.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "57b7e303",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/streaming-events-from-within-tools-without-langchain.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "8e71a0c8",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/streaming-events-from-within-tools.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "756e4554",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/streaming-from-final-node.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "47164a72",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/streaming-subgraphs.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "218dfbcb",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/streaming-tokens-without-langchain.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "99eb887e",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/streaming-tokens.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0de7689f",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/subgraph-transform-state.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+8 -1
View File
@@ -5,7 +5,14 @@
"id": "f49876e1",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/subgraph.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/how-tos/subgraph.md)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "5106959e",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/subgraphs-manage-state.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "dc21501d",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/tool-calling-errors.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+8 -1
View File
@@ -5,7 +5,14 @@
"id": "7fd8bd65",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/tool-calling.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/how-tos/tool-calling.md)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "83c2223f",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/sql-agent.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/sql/sql-agent.md)"
]
},
{
"cell_type": "markdown",
"id": "57f924b1",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "11140167",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/tnt-llm/tnt-llm.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/tnt-llm/tnt-llm.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "1a2ba3e6",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "9dffdb54",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/usaco/usaco.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/usaco/usaco.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "579c9959",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
-33
View File
@@ -1,33 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9c9cb15a",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/how-tos/visualization.ipynb"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+9 -1
View File
@@ -5,7 +5,15 @@
"id": "007ea2e9",
"metadata": {},
"source": [
"This file has been moved to https://github.com/langchain-ai/langgraph/blob/main/docs/docs/tutorials/web-navigation/web_voyager.ipynb"
"[This file has been moved](https://github.com/langchain-ai/langgraph/blob/23961cff61a42b52525f3b20b4094d8d2fba1744/docs/docs/tutorials/web-navigation/web_voyager.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "f0d7b895",
"metadata": {},
"source": [
"This directory is retained purely for archival purposes and is no longer updated. The examples previously found here have been moved to the newly [consolidated LangChain documentation](https://docs.langchain.com/oss/python/langgraph/overview)."
]
}
],
@@ -550,6 +550,11 @@ class AsyncPostgresStore(AsyncBatchedBaseStore, BasePostgresStore[_ainternal.Con
Will be applied regardless of whether the PostgresStore instance was initialized with a pipeline.
If pipeline mode is not supported, will fall back to using transaction context manager.
"""
is_pooled_conn = isinstance(self.conn, AsyncConnectionPool)
# With AsyncConnectionPool, each _cursor() call checks out its own connection.
# The pool does not hand out the same connection concurrently, so a shared lock
# across calls is unnecessary here.
lock = asyncio.Lock() if is_pooled_conn else self.lock
async with _ainternal.get_connection(self.conn) as conn:
if self.pipe:
# a connection in pipeline mode can be used concurrently
@@ -566,21 +571,21 @@ class AsyncPostgresStore(AsyncBatchedBaseStore, BasePostgresStore[_ainternal.Con
# thread/coroutine at a time, so we acquire a lock
if self.supports_pipeline:
async with (
self.lock,
lock,
conn.pipeline(),
conn.cursor(binary=True, row_factory=dict_row) as cur,
):
yield cur
else:
async with (
self.lock,
lock,
conn.transaction(),
conn.cursor(binary=True, row_factory=dict_row) as cur,
):
yield cur
else:
async with (
self.lock,
lock,
conn.cursor(binary=True, row_factory=dict_row) as cur,
):
yield cur
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "langgraph-checkpoint-postgres"
version = "3.0.3"
version = "3.0.4"
description = "Library with a Postgres implementation of LangGraph checkpoint saver."
authors = []
requires-python = ">=3.10"
+1 -1
View File
@@ -306,7 +306,7 @@ test = [
[[package]]
name = "langgraph-checkpoint-postgres"
version = "3.0.3"
version = "3.0.4"
source = { editable = "." }
dependencies = [
{ name = "langgraph-checkpoint" },
@@ -119,6 +119,25 @@ class BaseCheckpointSaver(Generic[V]):
Checkpointers allow LangGraph agents to persist their state
within and across multiple interactions.
When a checkpointer is configured, you should pass a `thread_id` in the config when
invoking the graph:
```python
config = {"configurable": {"thread_id": "my-thread"}}
graph.invoke(inputs, config)
```
The `thread_id` is the primary key used to store and retrieve checkpoints. Without
it, the checkpointer cannot save state, resume from interrupts, or enable
time-travel debugging.
How you choose ``thread_id`` depends on your use case:
- **Single-shot workflows**: Use a unique ID (e.g., uuid4) for each run when
executions are independent.
- **Conversational memory**: Reuse the same `thread_id` across invocations
to accumulate state (e.g., chat history) within a conversation.
Attributes:
serde (SerializerProtocol): Serializer for encoding/decoding checkpoints.
@@ -5,5 +5,5 @@ description = "Test for prerelease stuff"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"langgraph==1.0.2"
"langgraph==1.0.8"
]
@@ -7,7 +7,7 @@ requires-python = ">=3.10"
dependencies = [
"langchain-openai==1.0.0a2",
"langchain-anthropic==1.0.0a5",
"langgraph==1.0.2"
"langgraph==1.0.8"
]
[tool.uv]
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.4.11"
__version__ = "0.4.13"
+347 -40
View File
@@ -1,4 +1,5 @@
import json
import logging
import os
import pathlib
import re
@@ -10,9 +11,19 @@ import click
from langgraph_cli.schemas import Config, Distros
logger = logging.getLogger(__name__)
MIN_NODE_VERSION = "20"
DEFAULT_NODE_VERSION = "20"
CONSTRAINTS_PATH = "/api/constraints.txt"
CACHE_OPTIMIZE_LEVELS = {"off", "lock", "pyproject", "all"}
CACHE_OPTIMIZE_ENV_VAR = "LANGGRAPH_CACHE_OPTIMIZE"
DEFAULT_CACHE_OPTIMIZE = "lock"
METADATA_STAGING_DIR = "/tmp/dep_metadata"
MIN_PYTHON_VERSION = "3.11"
DEFAULT_PYTHON_VERSION = "3.11"
@@ -196,6 +207,11 @@ def validate_config(config: Config) -> Config:
f"Python version {pyversion} is not supported. "
f"Minimum required version is {MIN_PYTHON_VERSION}."
)
if "bullseye" in pyversion:
raise click.UsageError(
"Bullseye images were deprecated in version 0.4.13. "
"Please use 'bookworm' or 'debian' instead."
)
if not config["dependencies"]:
raise click.UsageError(
@@ -210,10 +226,15 @@ def validate_config(config: Config) -> Config:
# Validate image_distro config
if image_distro := config.get("image_distro"):
if image_distro == "bullseye":
raise click.UsageError(
"Bullseye images were deprecated in version 0.4.13. "
"Please use 'bookworm' or 'debian' instead."
)
if image_distro not in Distros.__args__:
raise click.UsageError(
f"Invalid image_distro: '{image_distro}'. "
"Must be one of 'debian', 'bullseye', or 'bookworm'."
"Must be one of 'debian', 'wolfi', or 'bookworm'."
)
if pip_installer := config.get("pip_installer"):
@@ -308,6 +329,30 @@ def validate_config_file(config_path: pathlib.Path) -> Config:
return validated
class ReqGenSpec(NamedTuple):
"""Specification for a local package that needs requirements.txt generation.
Created for every real package missing a requirements.txt, regardless of
cache optimization eligibility. The eligibility decision happens later
in ``python_config_to_docker()`` via ``_is_optimizable()``.
Attributes:
host_pkg_path: Absolute host path of the package directory.
container_pkg_path: Target path for the package source in the container.
container_req_path: Full path to requirements.txt inside the container.
package_type: ``"pyproject"`` or ``"setup"``.
has_uv_lock: True if the package includes uv.lock.
stage_name: BuildKit context name if outside the build context, else None.
"""
host_pkg_path: pathlib.Path
container_pkg_path: str
container_req_path: str
package_type: Literal["pyproject", "setup"]
has_uv_lock: bool
stage_name: str | None
class LocalDeps(NamedTuple):
"""A container for referencing and managing local Python dependencies.
@@ -355,6 +400,11 @@ class LocalDeps(NamedTuple):
additional_contexts: A list of paths to directories that contain local
dependencies in parent directories. These directories are added to the
Docker build context to ensure that the Dockerfile can access them.
pkgs_missing_reqs: A list of ``ReqGenSpec`` entries for real packages that
do not have a ``requirements.txt`` file. Populated by
``_assemble_local_deps()`` and consumed by ``python_config_to_docker()``
for cache-optimized Dockerfile generation.
"""
pip_reqs: list[tuple[pathlib.Path, str]]
@@ -364,6 +414,124 @@ class LocalDeps(NamedTuple):
working_dir: str | None = None
# if there are local dependencies in parent directories, use additional_contexts
additional_contexts: list[pathlib.Path] = None
# real packages that need requirements.txt generation for cache optimization
pkgs_missing_reqs: list[ReqGenSpec] | None = None
def _get_cache_optimize_level() -> str:
"""Read the cache optimization level from environment.
Returns one of: "off", "lock", "pyproject", "all".
Falls back to DEFAULT_CACHE_OPTIMIZE on invalid values (with warning).
"""
raw = os.getenv(CACHE_OPTIMIZE_ENV_VAR, DEFAULT_CACHE_OPTIMIZE).strip().lower()
if raw in CACHE_OPTIMIZE_LEVELS:
return raw
logger.warning(
"Invalid %s=%r. Falling back to %r.",
CACHE_OPTIMIZE_ENV_VAR,
raw,
DEFAULT_CACHE_OPTIMIZE,
)
return DEFAULT_CACHE_OPTIMIZE
def _is_optimizable(spec: ReqGenSpec, level: str) -> bool:
"""Determine if a package is eligible for deferred source copy.
Eligibility tiers (cumulative):
- "off": no packages optimized
- "lock": pyproject.toml + uv.lock only (safest, default)
- "pyproject": all pyproject.toml packages (with or without lock)
- "all": all real packages including setup.py
"""
if level == "off":
return False
if level == "lock":
return spec.package_type == "pyproject" and spec.has_uv_lock
if level == "pyproject":
return spec.package_type == "pyproject"
if level == "all":
return spec.package_type in {"pyproject", "setup"}
return False # unknown level — fail safe
def _metadata_files(spec: ReqGenSpec) -> list[str]:
"""Return the list of packaging metadata files to copy for requirements generation."""
files = ["pyproject.toml"] if spec.package_type == "pyproject" else ["setup.py"]
if spec.package_type == "pyproject" and spec.has_uv_lock:
files.append("uv.lock")
if spec.package_type == "setup" and (spec.host_pkg_path / "setup.cfg").exists():
files.append("setup.cfg")
return files
def _get_reqs_gen_cmd(spec: ReqGenSpec) -> str:
"""Return the shell command to generate requirements.txt from packaging metadata."""
if spec.package_type == "pyproject" and spec.has_uv_lock:
return "uv export --no-hashes --no-dev --no-emit-local -o 'requirements.txt'"
if spec.package_type == "pyproject":
return (
f"uv pip compile pyproject.toml -o 'requirements.txt'"
f" --constraint {CONSTRAINTS_PATH}"
)
return (
f"uv pip compile setup.py -o 'requirements.txt' --constraint {CONSTRAINTS_PATH}"
)
def _staging_path(spec: ReqGenSpec) -> str:
"""Return the staging directory path for a spec's metadata files.
Metadata is staged in a temporary directory separate from ``/deps/``
so the install loop does not encounter incomplete package directories.
"""
# Use the last component of container_pkg_path as the staging subdir
name = spec.container_pkg_path.rstrip("/").rsplit("/", 1)[-1]
return f"{METADATA_STAGING_DIR}/{name}"
def _generate_requirements_from_metadata(
config_path: pathlib.Path,
specs: list[ReqGenSpec],
) -> str:
"""Generate Dockerfile lines to create requirements.txt from packaging metadata.
Metadata files are staged under ``METADATA_STAGING_DIR`` (not ``/deps/``)
so the install loop does not find incomplete package directories.
Only processes the given ``specs``. Returns an empty string when the
list is empty.
"""
if not specs:
return ""
resolved_config_parent = config_path.resolve().parent
docker_lines = ["# -- Generate requirements.txt for packages without one --"]
docker_lines.append("# Copy packaging metadata files")
for spec in sorted(specs, key=lambda s: s.container_pkg_path):
staging = _staging_path(spec)
for file_name in _metadata_files(spec):
if spec.stage_name:
docker_lines.append(
f"COPY --from={spec.stage_name} {file_name} {staging}/{file_name}"
)
else:
file_relpath = (spec.host_pkg_path / file_name).relative_to(
resolved_config_parent
)
docker_lines.append(f"ADD {file_relpath} {staging}/{file_name}")
docker_lines.append("")
docker_lines.append("# Generate requirements.txt from packaging metadata")
for spec in sorted(specs, key=lambda s: s.container_pkg_path):
staging = _staging_path(spec)
docker_lines.append(f"RUN cd '{staging}' && {_get_reqs_gen_cmd(spec)}")
docker_lines.append("# -- End of requirements.txt generation --")
return os.linesep.join(docker_lines)
def _assemble_local_deps(config_path: pathlib.Path, config: Config) -> LocalDeps:
@@ -399,6 +567,7 @@ def _assemble_local_deps(config_path: pathlib.Path, config: Config) -> LocalDeps
faux_pkgs = {}
working_dir: str | None = None
additional_contexts: list[pathlib.Path] = []
pkgs_missing_reqs: list[ReqGenSpec] = []
for local_dep in config["dependencies"]:
if not local_dep.startswith("."):
@@ -425,6 +594,8 @@ def _assemble_local_deps(config_path: pathlib.Path, config: Config) -> LocalDeps
# If found, treat as a real package, if not treat as a faux package.
# For faux packages, we'll also check for presence of requirements.txt.
files = os.listdir(resolved)
# requirement_path is set in both branches and used after them
requirement_path: str = ""
if "pyproject.toml" in files or "setup.py" in files:
# real package
@@ -438,6 +609,31 @@ def _assemble_local_deps(config_path: pathlib.Path, config: Config) -> LocalDeps
# set working_dir
if local_dep == ".":
working_dir = f"/deps/{container_name}"
requirement_path = f"/deps/{container_name}/requirements.txt"
# Track real packages that need requirements.txt generation
if "requirements.txt" not in files:
has_pyproject = "pyproject.toml" in files
has_uv_lock = "uv.lock" in files
pkg_type: Literal["pyproject", "setup"] = (
"pyproject" if has_pyproject else "setup"
)
stage_name = None
if resolved in additional_contexts:
stage_name = container_name
pkgs_missing_reqs.append(
ReqGenSpec(
host_pkg_path=resolved,
container_pkg_path=f"/deps/{container_name}",
container_req_path=f"{METADATA_STAGING_DIR}/{container_name}/requirements.txt",
package_type=pkg_type,
has_uv_lock=has_uv_lock if has_pyproject else False,
stage_name=stage_name,
)
)
else:
# We could not find a pyproject.toml or setup.py, so treat as a faux package
if any(file == "__init__.py" for file in files):
@@ -470,18 +666,27 @@ def _assemble_local_deps(config_path: pathlib.Path, config: Config) -> LocalDeps
if local_dep == ".":
working_dir = container_path
# If the faux package has a requirements.txt, we'll add
# the path to the list of requirements to install.
if "requirements.txt" in files:
rfile = resolved / "requirements.txt"
pip_reqs.append(
(
rfile,
f"{container_path}/requirements.txt",
)
)
requirement_path = f"{container_path}/requirements.txt"
return LocalDeps(pip_reqs, real_pkgs, faux_pkgs, working_dir, additional_contexts)
# If the package has a requirements.txt, register it for pre-installation.
# This applies to BOTH real and faux packages.
if "requirements.txt" in files:
rfile = resolved / "requirements.txt"
pip_reqs.append(
(
rfile,
requirement_path,
)
)
return LocalDeps(
pip_reqs,
real_pkgs,
faux_pkgs,
working_dir,
additional_contexts,
pkgs_missing_reqs,
)
def _update_graph_paths(
@@ -873,22 +1078,106 @@ def python_config_to_docker(
pip_pkgs_str = (
f"RUN {local_reqs_pip_install} {' '.join(pypi_deps)}" if pypi_deps else ""
)
if local_deps.pip_reqs:
pip_reqs_str = os.linesep.join(
(
f"COPY --from=outer-{reqpath.name} requirements.txt {destpath}"
if reqpath.parent in local_deps.additional_contexts
else f"ADD {reqpath.relative_to(config_path.parent)} {destpath}"
)
for reqpath, destpath in local_deps.pip_reqs
)
pip_reqs_str += f"{os.linesep}RUN {local_reqs_pip_install} {' '.join('-r ' + r for _, r in local_deps.pip_reqs)}"
pip_reqs_str = f"""# -- Installing local requirements --
{pip_reqs_str}
# -- End of local requirements install --"""
# --- Compute optimized package set ---
optimized_pkg_paths: set[pathlib.Path] = set()
if pip_installer == "uv":
level = _get_cache_optimize_level()
logger.info("Docker cache optimization level: %s", level)
else:
pip_reqs_str = ""
# Source 1: packages with generated requirements
for spec in local_deps.pkgs_missing_reqs or []:
if _is_optimizable(spec, level):
optimized_pkg_paths.add(spec.host_pkg_path)
# Source 2: real packages with existing requirements.txt
# Their deps are already pre-installed via pip_reqs, so deferred copy is safe —
# but still subject to the same tier eligibility as generated-requirements packages.
if level != "off":
for reqpath, _ in local_deps.pip_reqs or []:
for fullpath in local_deps.real_pkgs:
if reqpath.parent != fullpath:
continue
# Build a synthetic spec to reuse the same eligibility check
pkg_files = os.listdir(fullpath)
has_pyproject = "pyproject.toml" in pkg_files
has_setup = "setup.py" in pkg_files
if not has_pyproject and not has_setup:
continue
synthetic = ReqGenSpec(
host_pkg_path=fullpath,
container_pkg_path="", # unused by _is_optimizable
container_req_path="", # unused by _is_optimizable
package_type="pyproject" if has_pyproject else "setup",
has_uv_lock="uv.lock" in pkg_files,
stage_name=None, # unused by _is_optimizable
)
if _is_optimizable(synthetic, level):
optimized_pkg_paths.add(fullpath)
# --- Generate requirements.txt from packaging metadata ---
# Always generate for ALL real packages missing requirements.txt (when using uv).
# This benefits caching even for non-deferred packages because the generated
# requirements.txt install layer is cached and deps are pre-installed before
# the install loop.
all_specs = list(local_deps.pkgs_missing_reqs or [])
generated_reqs_str = (
_generate_requirements_from_metadata(config_path, all_specs)
if pip_installer == "uv"
else ""
)
# --- Build combined requirements install block ---
# Gather all requirement paths: existing pip_reqs + generated specs
copy_lines: list[str] = []
all_req_paths: list[str] = []
# Existing pip_reqs (from packages that already have requirements.txt)
if local_deps.pip_reqs:
for reqpath, destpath in local_deps.pip_reqs:
# For optimized (deferred) packages, redirect the requirements.txt
# copy to the staging directory so we don't create a partial /deps/
# directory that the install loop would trip over.
resolved_pkg = reqpath.parent.resolve()
if resolved_pkg in optimized_pkg_paths:
name = destpath.rstrip("/").rsplit("/", 2)[-2]
effective_dest = f"{METADATA_STAGING_DIR}/{name}/requirements.txt"
else:
effective_dest = destpath
if reqpath.parent in local_deps.additional_contexts:
if reqpath.parent in local_deps.real_pkgs:
stage_name = local_deps.real_pkgs[reqpath.parent][1]
else:
stage_name = f"outer-{reqpath.parent.name}"
copy_lines.append(
f"COPY --from={stage_name} requirements.txt {effective_dest}"
)
else:
copy_lines.append(
f"ADD {reqpath.relative_to(config_path.parent)} {effective_dest}"
)
all_req_paths.append(effective_dest)
# Generated requirements from specs (all real packages with generation, uv only)
if pip_installer == "uv":
for spec in sorted(
local_deps.pkgs_missing_reqs or [], key=lambda s: s.container_req_path
):
all_req_paths.append(spec.container_req_path)
pip_reqs_str = ""
if all_req_paths:
all_req_paths = sorted(set(all_req_paths))
install_lines = [
f"RUN {local_reqs_pip_install} -r '{p}'" for p in all_req_paths
]
pip_reqs_str = f"""# -- Installing from requirements.txt files --
{os.linesep.join(copy_lines)}
{os.linesep.join(install_lines)}
# -- End of requirements.txt install --"""
# Clean up leading/trailing blank lines in case copy_lines is empty
pip_reqs_str = pip_reqs_str.replace(
os.linesep + os.linesep + "RUN", os.linesep + "RUN"
)
# https://setuptools.pypa.io/en/latest/userguide/datafiles.html#package-data
# https://til.simonwillison.net/python/pyproject
@@ -916,18 +1205,34 @@ RUN set -ex && \\
for fullpath, (relpath, destpath) in local_deps.faux_pkgs.items()
)
local_pkgs_str = os.linesep.join(
(
f"""# -- Adding local package {relpath} --
COPY --from={name} . /deps/{name}
# -- End of local package {relpath} --"""
if fullpath in local_deps.additional_contexts
else f"""# -- Adding local package {relpath} --
ADD {relpath} /deps/{name}
# -- End of local package {relpath} --"""
)
for fullpath, (relpath, name) in local_deps.real_pkgs.items()
)
# --- Split real package source copy into pre-loop and post-loop ---
local_pkgs_pre_parts: list[str] = []
local_pkgs_post_parts: list[str] = []
for fullpath, (relpath, name) in local_deps.real_pkgs.items():
if fullpath in local_deps.additional_contexts:
add_line = f"COPY --from={name} . /deps/{name}"
else:
add_line = f"ADD {relpath} /deps/{name}"
if fullpath in optimized_pkg_paths:
# Deferred: full source copy + no-deps editable install after the loop
local_pkgs_post_parts.append(
f"# -- Adding full source for local package {relpath} --\n"
f"{add_line}\n"
f"RUN cd /deps/{name} && {global_reqs_pip_install} --no-deps -e .\n"
f"# -- End of full source for local package {relpath} --"
)
else:
# Non-optimized: keep in pre-loop position (unchanged behavior)
local_pkgs_pre_parts.append(
f"# -- Adding local package {relpath} --\n"
f"{add_line}\n"
f"# -- End of local package {relpath} --"
)
local_pkgs_pre_str = os.linesep.join(local_pkgs_pre_parts)
local_pkgs_post_str = os.linesep.join(local_pkgs_post_parts)
install_node_str: str = (
"RUN /storage/install-node.sh"
@@ -942,8 +1247,9 @@ ADD {relpath} /deps/{name}
install_node_str,
pip_config_file_str,
pip_pkgs_str,
generated_reqs_str,
pip_reqs_str,
local_pkgs_str,
local_pkgs_pre_str,
faux_pkgs_str,
],
)
@@ -1023,6 +1329,7 @@ ADD {relpath} /deps/{name}
fi; \
done""",
"# -- End of local dependencies install --",
local_pkgs_post_str,
os.linesep.join(env_vars),
"",
js_inst_str,
+10 -8
View File
@@ -1,6 +1,6 @@
from typing import Any, Literal, TypedDict
Distros = Literal["debian", "wolfi", "bullseye", "bookworm"]
Distros = Literal["debian", "wolfi", "bookworm"]
MiddlewareOrders = Literal["auth_first", "middleware_first"]
@@ -107,17 +107,19 @@ class StoreConfig(TypedDict, total=False):
class ThreadTTLConfig(TypedDict, total=False):
"""Configure a default TTL for checkpointed data within threads."""
strategy: Literal["delete"]
"""Strategy to use for deleting checkpointed data.
Choices:
- "delete": Delete all checkpoints for a thread after TTL expires.
strategy: Literal["delete", "keep_latest"]
"""Action taken when a thread exceeds its TTL.
- "delete": Remove the thread and all its data entirely.
- "keep_latest": Prune old checkpoints but keep the thread and its latest state.
"""
default_ttl: float | None
"""Default TTL (time-to-live) in minutes for checkpointed data."""
sweep_interval_minutes: int | None
"""Interval in minutes between sweep iterations.
If omitted, a default interval will be used (typically ~ 5 minutes)."""
sweep_limit: int | None
"""Maximum number of threads to process per sweep iteration. Defaults to 1000."""
class SerdeConfig(TypedDict, total=False):
@@ -173,7 +175,7 @@ class CheckpointerConfig(TypedDict, total=False):
"""
serde: SerdeConfig | None
"""Optional. Defines the serde configuration.
If provided, the checkpointer will apply serde settings according to the configuration.
If omitted, no serde behavior is configured.
@@ -557,7 +559,7 @@ class Config(TypedDict, total=False):
image_distro: Distros | None
"""Optional. Linux distribution for the base image.
Must be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.
Must be one of 'wolfi', 'debian', or 'bookworm'.
If omitted, defaults to 'debian' ('latest').
"""
+1 -1
View File
@@ -19,7 +19,7 @@ dependencies = [
path = "langgraph_cli/__init__.py"
[project.optional-dependencies]
inmem = [
"langgraph-api>=0.5.35,<0.7.0 ; python_version >= '3.11'",
"langgraph-api>=0.5.35,<0.8.0 ; python_version >= '3.11'",
"langgraph-runtime-inmem>=0.7 ; python_version >= '3.11'",
"python-dotenv>=0.8.0",
]
+16 -5
View File
@@ -147,7 +147,6 @@
{
"enum": [
"bookworm",
"bullseye",
"debian",
"wolfi"
]
@@ -156,7 +155,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -370,7 +369,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -618,9 +617,10 @@
},
"strategy": {
"enum": [
"delete"
"delete",
"keep_latest"
],
"description": "Strategy to use for deleting checkpointed data.\n"
"description": "Action taken when a thread exceeds its TTL.\n\n"
},
"sweep_interval_minutes": {
"anyOf": [
@@ -632,6 +632,17 @@
}
],
"description": "Interval in minutes between sweep iterations.\nIf omitted, a default interval will be used (typically ~ 5 minutes)."
},
"sweep_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum number of threads to process per sweep iteration. Defaults to 1000."
}
},
"required": []
+16 -5
View File
@@ -147,7 +147,6 @@
{
"enum": [
"bookworm",
"bullseye",
"debian",
"wolfi"
]
@@ -156,7 +155,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -370,7 +369,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -618,9 +617,10 @@
},
"strategy": {
"enum": [
"delete"
"delete",
"keep_latest"
],
"description": "Strategy to use for deleting checkpointed data.\n"
"description": "Action taken when a thread exceeds its TTL.\n\n"
},
"sweep_interval_minutes": {
"anyOf": [
@@ -632,6 +632,17 @@
}
],
"description": "Interval in minutes between sweep iterations.\nIf omitted, a default interval will be used (typically ~ 5 minutes)."
},
"sweep_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum number of threads to process per sweep iteration. Defaults to 1000."
}
},
"required": []
+20 -3
View File
@@ -1,4 +1,5 @@
import json
import os
import pathlib
import re
import shutil
@@ -6,6 +7,7 @@ import tempfile
import textwrap
from contextlib import contextmanager
from pathlib import Path
from unittest.mock import patch
from click.testing import CliRunner
@@ -47,6 +49,7 @@ def temporary_config_folder(config_content: dict, levels: int = 0):
shutil.rmtree(temp_dir)
@patch.dict(os.environ, {"LANGGRAPH_CACHE_OPTIMIZE": "lock"})
def test_prepare_args_and_stdin() -> None:
# this basically serves as an end-to-end test for using config and docker helpers
config_path = pathlib.Path(__file__).parent / "langgraph.json"
@@ -143,15 +146,29 @@ services:
dockerfile_inline: |
# syntax=docker/dockerfile:1.4
FROM langchain/langgraph-api:3.11
# -- Generate requirements.txt for packages without one --
# Copy packaging metadata files
ADD pyproject.toml /tmp/dep_metadata/cli/pyproject.toml
COPY --from=cli_1 pyproject.toml /tmp/dep_metadata/cli_1/pyproject.toml
COPY --from=cli_1 uv.lock /tmp/dep_metadata/cli_1/uv.lock
# Generate requirements.txt from packaging metadata
RUN cd '/tmp/dep_metadata/cli' && uv pip compile pyproject.toml -o 'requirements.txt' --constraint /api/constraints.txt
RUN cd '/tmp/dep_metadata/cli_1' && uv export --no-hashes --no-dev --no-emit-local -o 'requirements.txt'
# -- End of requirements.txt generation --
# -- Installing from requirements.txt files --
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r '/tmp/dep_metadata/cli/requirements.txt'
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r '/tmp/dep_metadata/cli_1/requirements.txt'
# -- End of requirements.txt install --
# -- Adding local package . --
ADD . /deps/cli
# -- End of local package . --
# -- Adding local package ../../.. --
COPY --from=cli_1 . /deps/cli_1
# -- End of local package ../../.. --
# -- Installing all local dependencies --
RUN for dep in /deps/*; do echo "Installing $$dep"; if [ -d "$$dep" ]; then echo "Installing $$dep"; (cd "$$dep" && PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e .); fi; done
# -- End of local dependencies install --
# -- Adding full source for local package ../../.. --
COPY --from=cli_1 . /deps/cli_1
RUN cd /deps/cli_1 && PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt --no-deps -e .
# -- End of full source for local package ../../.. --
ENV LANGSERVE_GRAPHS='{{"agent": "agent.py:graph"}}'
{textwrap.indent(textwrap.dedent(FORMATTED_CLEANUP_LINES), " ")}
WORKDIR /deps/cli
@@ -0,0 +1,100 @@
import json
import os
import pathlib
from unittest.mock import patch
import pytest
from langgraph_cli.config import config_to_docker, validate_config
FIXTURES_ROOT = (
pathlib.Path(__file__).parent.parent / "local_cache_validation" / "projects"
)
CACHE_ENV = "LANGGRAPH_CACHE_OPTIMIZE"
TIERS = ("off", "lock", "pyproject", "all")
pytestmark = pytest.mark.skipif(
os.getenv("RUN_LOCAL_CACHE_VALIDATION") != "1",
reason="Local-only cache optimization TDD tests.",
)
def _dockerfile_for_fixture(fixture_name: str, tier: str) -> str:
config_path = FIXTURES_ROOT / fixture_name / "langgraph.json"
with open(config_path, encoding="utf-8") as f:
raw = json.load(f)
config = validate_config(raw)
with patch.dict(os.environ, {CACHE_ENV: tier}):
dockerfile, _ = config_to_docker(
config_path=config_path,
config=config,
base_image="langchain/langgraph-api",
)
return dockerfile
@pytest.mark.parametrize(
"fixture_name,expected",
[
(
"real_pyproject_lock",
{"off": False, "lock": True, "pyproject": True, "all": True},
),
(
"real_pyproject_no_lock",
{"off": False, "lock": False, "pyproject": True, "all": True},
),
(
"real_setup_py",
{"off": False, "lock": False, "pyproject": False, "all": True},
),
(
"faux_package",
{"off": False, "lock": False, "pyproject": False, "all": False},
),
(
"pip_installer_fallback",
{"off": False, "lock": False, "pyproject": False, "all": False},
),
],
)
def test_tier_deferred_copy_matrix(
fixture_name: str, expected: dict[str, bool]
) -> None:
for tier in TIERS:
dockerfile = _dockerfile_for_fixture(fixture_name, tier)
has_no_deps_editable = "--no-deps -e ." in dockerfile
assert has_no_deps_editable is expected[tier], (
f"{fixture_name=} {tier=} expected deferred copy {expected[tier]}, "
f"got {has_no_deps_editable}"
)
def test_requirements_before_no_deps_for_eligible_tier() -> None:
dockerfile = _dockerfile_for_fixture("real_pyproject_lock", "lock")
reqs_idx = dockerfile.find("Installing from requirements.txt files")
no_deps_idx = dockerfile.find("--no-deps -e .")
assert reqs_idx != -1
assert no_deps_idx != -1
assert reqs_idx < no_deps_idx
def test_generation_command_selection_by_fixture() -> None:
docker_lock = _dockerfile_for_fixture("real_pyproject_lock", "lock")
assert "uv export --no-hashes --no-dev --no-emit-local" in docker_lock
docker_pyproject = _dockerfile_for_fixture("real_pyproject_no_lock", "pyproject")
assert "uv pip compile pyproject.toml" in docker_pyproject
docker_setup = _dockerfile_for_fixture("real_setup_py", "all")
assert "uv pip compile setup.py" in docker_setup
def test_pip_installer_fallback_ignores_tier() -> None:
outputs = {
tier: _dockerfile_for_fixture("pip_installer_fallback", tier) for tier in TIERS
}
first = outputs["off"]
for tier, dockerfile in outputs.items():
assert dockerfile == first, f"Expected identical dockerfile for {tier=}"
+42 -12
View File
@@ -4,6 +4,7 @@ import os
import pathlib
import tempfile
import textwrap
from unittest.mock import patch
import click
import pytest
@@ -120,14 +121,14 @@ def test_validate_config():
validate_config({"python_version": "3.10"})
assert "Minimum required version" in str(exc_info.value)
config = validate_config(
{
"python_version": "3.11-bullseye",
"dependencies": ["."],
"graphs": {"agent": "./agent.py:graph"},
}
)
assert config["python_version"] == "3.11-bullseye"
with pytest.raises(click.UsageError, match="Bullseye images were deprecated"):
validate_config(
{
"python_version": "3.11-bullseye",
"dependencies": ["."],
"graphs": {"agent": "./agent.py:graph"},
}
)
config = validate_config(
{
@@ -181,6 +182,17 @@ def test_validate_config_image_distro():
)
assert config["image_distro"] == "debian"
# Bullseye should raise deprecation error
with pytest.raises(click.UsageError, match="Bullseye images were deprecated"):
validate_config(
{
"python_version": "3.11",
"dependencies": ["."],
"graphs": {"agent": "./agent.py:graph"},
"image_distro": "bullseye",
}
)
# Invalid image_distro values should raise error
with pytest.raises(click.UsageError) as exc_info:
validate_config(
@@ -409,6 +421,7 @@ def test_validate_config_multiplatform():
# config_to_docker
@patch.dict(os.environ, {"LANGGRAPH_CACHE_OPTIMIZE": "lock"})
def test_config_to_docker_simple():
graphs = {"agent": "./agent.py:graph"}
actual_docker_stdin, additional_contexts = config_to_docker(
@@ -425,10 +438,17 @@ def test_config_to_docker_simple():
expected_docker_stdin = f"""\
# syntax=docker/dockerfile:1.4
FROM langchain/langgraph-api:3.11
# -- Installing local requirements --
COPY --from=outer-requirements.txt requirements.txt /deps/outer-graphs_reqs_a/graphs_reqs_a/requirements.txt
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r /deps/outer-graphs_reqs_a/graphs_reqs_a/requirements.txt
# -- End of local requirements install --
# -- Generate requirements.txt for packages without one --
# Copy packaging metadata files
COPY --from=examples pyproject.toml /tmp/dep_metadata/examples/pyproject.toml
# Generate requirements.txt from packaging metadata
RUN cd '/tmp/dep_metadata/examples' && uv pip compile pyproject.toml -o 'requirements.txt' --constraint /api/constraints.txt
# -- End of requirements.txt generation --
# -- Installing from requirements.txt files --
COPY --from=outer-graphs_reqs_a requirements.txt /deps/outer-graphs_reqs_a/graphs_reqs_a/requirements.txt
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r '/deps/outer-graphs_reqs_a/graphs_reqs_a/requirements.txt'
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r '/tmp/dep_metadata/examples/requirements.txt'
# -- End of requirements.txt install --
# -- Adding local package ../../examples --
COPY --from=examples . /deps/examples
# -- End of local package ../../examples --
@@ -636,6 +656,7 @@ ENV LANGSERVE_GRAPHS='{{"agent": "/deps/outer-graphs/src/agent.py:graph"}}'
assert additional_contexts == {}
@patch.dict(os.environ, {"LANGGRAPH_CACHE_OPTIMIZE": "lock"})
def test_config_to_docker_pyproject():
pyproject_str = """[project]
name = "custom"
@@ -659,6 +680,15 @@ dependencies = ["langchain"]"""
os.remove(pyproject_path)
expected_docker_stdin = (
"""FROM langchain/langgraph-api:3.11
# -- Generate requirements.txt for packages without one --
# Copy packaging metadata files
ADD pyproject.toml /tmp/dep_metadata/unit_tests/pyproject.toml
# Generate requirements.txt from packaging metadata
RUN cd '/tmp/dep_metadata/unit_tests' && uv pip compile pyproject.toml -o 'requirements.txt' --constraint /api/constraints.txt
# -- End of requirements.txt generation --
# -- Installing from requirements.txt files --
RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -r '/tmp/dep_metadata/unit_tests/requirements.txt'
# -- End of requirements.txt install --
# -- Adding local package . --
ADD . /deps/unit_tests
# -- End of local package . --
+118 -117
View File
@@ -650,7 +650,7 @@ wheels = [
[[package]]
name = "hatch"
version = "1.16.2"
version = "1.16.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "backports-zstd", marker = "python_full_version < '3.14'" },
@@ -671,9 +671,9 @@ dependencies = [
{ name = "uv" },
{ name = "virtualenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b9/c1/8598996a6f264d430c530799dc65fb13942fb29092e35505039a5f2fb5dc/hatch-1.16.2.tar.gz", hash = "sha256:f288938da85b4b90e47d94788e19e9976dcd6fd53b48343ea251a2a37256a980", size = 5216569, upload-time = "2025-12-06T19:18:12.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/41/c1/976b807478878d31d467dd17b9fe642962f292e16ed13c34b593c0453fde/hatch-1.16.3.tar.gz", hash = "sha256:2a50ecc912adfc8122cd2ccdcc15254cdef829e5d158be9014180cd7f0fb7ea9", size = 5219621, upload-time = "2026-01-21T01:36:19.822Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d4/7c/bbed5611b1cd7b0b42b2dadb0721d9ccfa4fa9d03abc05e0f57c85a319c6/hatch-1.16.2-py3-none-any.whl", hash = "sha256:827eaf9813c63119f172b85975c5c27110a2306b07e5304c9d38527b0239052a", size = 140658, upload-time = "2025-12-06T19:18:10.573Z" },
{ url = "https://files.pythonhosted.org/packages/b8/b4/5c5fa4ca8c59e7ef0a224ff10e6336e73ca61c5e0eff09ee691441c9275f/hatch-1.16.3-py3-none-any.whl", hash = "sha256:f5169025cf1cdfe981366eb96127cab1d1bc59f5f2acb87c4cc308c25d95a4b1", size = 141305, upload-time = "2026-01-21T01:36:18.13Z" },
]
[[package]]
@@ -903,7 +903,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "1.0.6"
version = "1.0.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "langchain-core", marker = "python_full_version >= '3.11'" },
@@ -913,14 +913,14 @@ dependencies = [
{ name = "pydantic", marker = "python_full_version >= '3.11'" },
{ name = "xxhash", marker = "python_full_version >= '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c2/9c/dac99ab1732e9fb2d3b673482ac28f02bee222c0319a3b8f8f73d90727e6/langgraph-1.0.6.tar.gz", hash = "sha256:dd8e754c76d34a07485308d7117221acf63990e7de8f46ddf5fe256b0a22e6c5", size = 495092, upload-time = "2026-01-12T20:33:30.778Z" }
sdist = { url = "https://files.pythonhosted.org/packages/72/5b/f72655717c04e33d3b62f21b166dc063d192b53980e9e3be0e2a117f1c9f/langgraph-1.0.7.tar.gz", hash = "sha256:0cfdfee51e6e8cfe503ecc7367c73933437c505b03fa10a85c710975c8182d9a", size = 497098, upload-time = "2026-01-22T16:57:47.303Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/10/45/9960747781416bed4e531ed0c6b2f2c739bc7b5397d8e92155463735a40e/langgraph-1.0.6-py3-none-any.whl", hash = "sha256:bcfce190974519c72e29f6e5b17f0023914fd6f936bfab8894083215b271eb89", size = 157356, upload-time = "2026-01-12T20:33:29.191Z" },
{ url = "https://files.pythonhosted.org/packages/7e/0e/fe80144e3e4048e5d19ccdb91ac547c1a7dc3da8dbd1443e210048194c14/langgraph-1.0.7-py3-none-any.whl", hash = "sha256:9d68e8f8dd8f3de2fec45f9a06de05766d9b075b78fb03171779893b7a52c4d2", size = 157353, upload-time = "2026-01-22T16:57:45.997Z" },
]
[[package]]
name = "langgraph-api"
version = "0.6.39"
version = "0.7.8"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cloudpickle", marker = "python_full_version >= '3.11'" },
@@ -951,9 +951,9 @@ dependencies = [
{ name = "uvicorn", marker = "python_full_version >= '3.11'" },
{ name = "watchfiles", marker = "python_full_version >= '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b2/52/f7d25b475768e5e0748d4725c64909fc7e56a714e064976a32e7c68f6d9e/langgraph_api-0.6.39.tar.gz", hash = "sha256:052191ec9c49d76b0d5592a60fe6324eafde40e7a1afba65d1ce11a6a074674b", size = 447880, upload-time = "2026-01-16T19:54:07.475Z" }
sdist = { url = "https://files.pythonhosted.org/packages/42/52/649481d27ced9b982166b16dcbf57bf024712830186258bf1d876b7e9361/langgraph_api-0.7.8.tar.gz", hash = "sha256:a399474c783c399d9cc503f5cde34fe2886ba468b59c4c629cfd8e4f05926f59", size = 466146, upload-time = "2026-01-23T00:11:47.204Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ea/a7/5ecccdc0e2a3900e08ac263b6e9cc6c5172c52ce3c4dda7750511e6fecc6/langgraph_api-0.6.39-py3-none-any.whl", hash = "sha256:50464c4983641c8b006a7f452583127ee2819806fc6d04844b08d5d3430df12e", size = 351764, upload-time = "2026-01-16T19:54:05.81Z" },
{ url = "https://files.pythonhosted.org/packages/23/a0/0bb4a47529f4e1a53b690897d756e3da0d3d1ce6990238f71085d1ce3a50/langgraph_api-0.7.8-py3-none-any.whl", hash = "sha256:2f0bfc13674bc3347321064268ecc951c35518de054eedcc9b426ecb269613ae", size = 369565, upload-time = "2026-01-23T00:11:45.729Z" },
]
[[package]]
@@ -1012,7 +1012,7 @@ test = [
[package.metadata]
requires-dist = [
{ name = "click", specifier = ">=8.1.7" },
{ name = "langgraph-api", marker = "python_full_version >= '3.11' and extra == 'inmem'", specifier = ">=0.5.35,<0.7.0" },
{ name = "langgraph-api", marker = "python_full_version >= '3.11' and extra == 'inmem'", specifier = ">=0.5.35,<0.8.0" },
{ name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11' and extra == 'inmem'", specifier = ">=0.7" },
{ name = "langgraph-sdk", marker = "python_full_version >= '3.11'", specifier = ">=0.1.0" },
{ name = "python-dotenv", marker = "extra == 'inmem'", specifier = ">=0.8.0" },
@@ -1046,20 +1046,20 @@ test = [
[[package]]
name = "langgraph-prebuilt"
version = "1.0.6"
version = "1.0.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "langchain-core", marker = "python_full_version >= '3.11'" },
{ name = "langgraph-checkpoint", marker = "python_full_version >= '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3c/f5/8c75dace0d729561dce2966e630c5e312193df7e5df41a7e10cd7378c3a7/langgraph_prebuilt-1.0.6.tar.gz", hash = "sha256:c5f6cf0f5a0ac47643d2e26ae6faa38cb28885ecde67911190df9e30c4f72361", size = 162623, upload-time = "2026-01-12T20:31:28.425Z" }
sdist = { url = "https://files.pythonhosted.org/packages/a7/59/711aecd1a50999456850dc328f3cad72b4372d8218838d8d5326f80cb76f/langgraph_prebuilt-1.0.7.tar.gz", hash = "sha256:38e097e06de810de4d0e028ffc0e432bb56d1fb417620fb1dfdc76c5e03e4bf9", size = 163692, upload-time = "2026-01-22T16:45:22.801Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/26/6c/4045822b0630cfc0f8624c4499ceaf90644142143c063a8dc385a7424fc3/langgraph_prebuilt-1.0.6-py3-none-any.whl", hash = "sha256:9fdc35048ff4ac985a55bd2a019a86d45b8184551504aff6780d096c678b39ae", size = 35322, upload-time = "2026-01-12T20:31:27.161Z" },
{ url = "https://files.pythonhosted.org/packages/47/49/5e37abb3f38a17a3487634abc2a5da87c208cc1d14577eb8d7184b25c886/langgraph_prebuilt-1.0.7-py3-none-any.whl", hash = "sha256:e14923516504405bb5edc3977085bc9622c35476b50c1808544490e13871fe7c", size = 35324, upload-time = "2026-01-22T16:45:21.784Z" },
]
[[package]]
name = "langgraph-runtime-inmem"
version = "0.22.1"
version = "0.23.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "blockbuster", marker = "python_full_version >= '3.11'" },
@@ -1069,9 +1069,9 @@ dependencies = [
{ name = "starlette", marker = "python_full_version >= '3.11'" },
{ name = "structlog", marker = "python_full_version >= '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cb/8d/4b42a852a869c6a60aceae4e6157030c427ae9c07bf28769cc8e2fcec16b/langgraph_runtime_inmem-0.22.1.tar.gz", hash = "sha256:bbd983975dc372ad5cd5288263d3471732b0dff2bab3c6f41e5fe5b3a38ea1ee", size = 104172, upload-time = "2026-01-16T15:17:23.381Z" }
sdist = { url = "https://files.pythonhosted.org/packages/d0/25/f8ce026c9f56678ba3a0ee07456b60643be9ea46860b1b0268fe064bb1a8/langgraph_runtime_inmem-0.23.1.tar.gz", hash = "sha256:f7854bb2742dd797ae8d19a51d3b72d6218b51cb961af4fe9b437bb50710890b", size = 104659, upload-time = "2026-01-22T18:47:47.004Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/b2/336cb642ff4df29d46bb54e21b4ecbc6e2e38e606c1e3584d3ef67621c41/langgraph_runtime_inmem-0.22.1-py3-none-any.whl", hash = "sha256:2a04747db050cd7db878fb0c68fc7dbe8198ed71db35da323a27d1a7b2de3e97", size = 38291, upload-time = "2026-01-16T15:17:21.864Z" },
{ url = "https://files.pythonhosted.org/packages/8a/1e/db6c2a5189793b49c482449cff38ff60df757e7081c209678df4e4693d57/langgraph_runtime_inmem-0.23.1-py3-none-any.whl", hash = "sha256:79763b741d86643b28d6ea4b9b11f3189a64d1e233127339b458efd2f6f647f7", size = 39017, upload-time = "2026-01-22T18:47:45.567Z" },
]
[[package]]
@@ -1492,57 +1492,58 @@ wheels = [
[[package]]
name = "ormsgpack"
version = "1.12.1"
version = "1.12.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/96/34c40d621996c2f377a18decbd3c59f031dde73c3ba47d1e1e8f29a05aaa/ormsgpack-1.12.1.tar.gz", hash = "sha256:a3877fde1e4f27a39f92681a0aab6385af3a41d0c25375d33590ae20410ea2ac", size = 39476, upload-time = "2025-12-14T07:57:43.248Z" }
sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/da/caf25cc54d6870089a0b5614c4c5914dd3fae45f9f7f84a32445ad0612e3/ormsgpack-1.12.1-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:62e3614cab63fa5aa42f5f0ca3cd12899f0bfc5eb8a5a0ebab09d571c89d427d", size = 376182, upload-time = "2025-12-14T07:56:46.094Z" },
{ url = "https://files.pythonhosted.org/packages/fc/02/ccc9170c6bee86f428707f15b5ad68d42c71d43856e1b8e37cdfea50af5b/ormsgpack-1.12.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86d9fbf85c05c69c33c229d2eba7c8c3500a56596cd8348131c918acd040d6af", size = 202339, upload-time = "2025-12-14T07:56:47.609Z" },
{ url = "https://files.pythonhosted.org/packages/86/c7/10309a5a6421adaedab710a72470143d664bb0a043cc095c1311878325a0/ormsgpack-1.12.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d246e66f09d8e0f96e770829149ee83206e90ed12f5987998bb7be84aec99fe", size = 210720, upload-time = "2025-12-14T07:56:48.66Z" },
{ url = "https://files.pythonhosted.org/packages/1b/b4/92a0f7a00c5f0c71b51dc3112e53b1ca937b9891a08979d06524db11b799/ormsgpack-1.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfc2c830a1ed2d00de713d08c9e62efa699e8fd29beafa626aaebe466f583ebb", size = 211264, upload-time = "2025-12-14T07:56:49.976Z" },
{ url = "https://files.pythonhosted.org/packages/33/fa/5cce85c8e58fcaa048c75fbbe37816a1b3fb58ba4289a7dedc4f4ed9ce82/ormsgpack-1.12.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bc892757d8f9eea5208268a527cf93c98409802f6a9f7c8d71a7b8f9ba5cb944", size = 386076, upload-time = "2025-12-14T07:56:51.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/d0/f18d258c733eb22eadad748659f7984d0b6a851fb3deefcb33f50e9a947a/ormsgpack-1.12.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:0de1dbcf11ea739ac4a882b43d5c2055e6d99ce64e8d6502e25d6d881700c017", size = 479570, upload-time = "2025-12-14T07:56:52.912Z" },
{ url = "https://files.pythonhosted.org/packages/3f/3a/b362dff090f4740090fe51d512f24b1e320d1f96497ebf9248e2a04ac88f/ormsgpack-1.12.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d5065dfb9ec4db93241c60847624d9aeef4ccb449c26a018c216b55c69be83c0", size = 387859, upload-time = "2025-12-14T07:56:53.968Z" },
{ url = "https://files.pythonhosted.org/packages/7c/8a/d948965598b2b7872800076da5c02573aa72f716be57a3d4fe60490b2a2a/ormsgpack-1.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d17103c4726181d7000c61b751c881f1b6f401d146df12da028fc730227df19", size = 115906, upload-time = "2025-12-14T07:56:55.068Z" },
{ url = "https://files.pythonhosted.org/packages/57/e2/f5b89365c8dc8025c27d31316038f1c103758ddbf87dc0fa8e3f78f66907/ormsgpack-1.12.1-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4038f59ae0e19dac5e5d9aae4ec17ff84a79e046342ee73ccdecf3547ecf0d34", size = 376180, upload-time = "2025-12-14T07:56:56.521Z" },
{ url = "https://files.pythonhosted.org/packages/ca/87/3f694e06f5e32c6d65066f53b4a025282a5072b6b336c17560b00e04606d/ormsgpack-1.12.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16c63b0c5a3eec467e4bb33a14dabba076b7d934dff62898297b5c0b5f7c3cb3", size = 202338, upload-time = "2025-12-14T07:56:57.585Z" },
{ url = "https://files.pythonhosted.org/packages/e5/f5/6d95d7b7c11f97a92522082fc7e5d1ab34537929f1e13f4c369f392f19d0/ormsgpack-1.12.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74fd6a8e037eb310dda865298e8d122540af00fe5658ec18b97a1d34f4012e4d", size = 210720, upload-time = "2025-12-14T07:56:58.968Z" },
{ url = "https://files.pythonhosted.org/packages/2b/9d/9a49a2686f8b7165dcb2342b8554951263c30c0f0825f1fcc2d56e736a6b/ormsgpack-1.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58ad60308e233dd824a1859eabb5fe092e123e885eafa4ad5789322329c80fb5", size = 211264, upload-time = "2025-12-14T07:57:00.099Z" },
{ url = "https://files.pythonhosted.org/packages/02/31/2fdc36eaeca2182900b96fc7b19755f293283fe681750e3d295733d62f0e/ormsgpack-1.12.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:35127464c941c1219acbe1a220e48d55e7933373d12257202f4042f7044b4c90", size = 386081, upload-time = "2025-12-14T07:57:01.177Z" },
{ url = "https://files.pythonhosted.org/packages/f0/65/0a765432f08ae26b4013c6a9aed97be17a9ef85f1600948a474b518e27dd/ormsgpack-1.12.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:c48d1c50794692d1e6e3f8c3bb65f5c3acfaae9347e506484a65d60b3d91fb50", size = 479572, upload-time = "2025-12-14T07:57:02.738Z" },
{ url = "https://files.pythonhosted.org/packages/4e/4f/f2f15ebef786ad71cea420bf8692448fbddf04d1bf3feaa68bd5ee3172e6/ormsgpack-1.12.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b512b2ad6feaaefdc26e05431ed2843e42483041e354e167c53401afaa83d919", size = 387862, upload-time = "2025-12-14T07:57:03.842Z" },
{ url = "https://files.pythonhosted.org/packages/15/eb/86fbef1d605fa91ecef077f93f9d0e34fc39b23475dfe3ffb92f6c8db28d/ormsgpack-1.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:93f30db95e101a9616323bfc50807ad00e7f6197cea2216d2d24af42afc77d88", size = 115900, upload-time = "2025-12-14T07:57:05.137Z" },
{ url = "https://files.pythonhosted.org/packages/5b/67/7ba1a46e6a6e263fc42a4fafc24afc1ab21a66116553cad670426f0bd9ef/ormsgpack-1.12.1-cp311-cp311-win_arm64.whl", hash = "sha256:d75b5fa14f6abffce2c392ee03b4731199d8a964c81ee8645c4c79af0e80fd50", size = 109868, upload-time = "2025-12-14T07:57:06.834Z" },
{ url = "https://files.pythonhosted.org/packages/17/fe/ab9167ca037406b5703add24049cf3e18021a3b16133ea20615b1f160ea4/ormsgpack-1.12.1-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4d7fb0e1b6fbc701d75269f7405a4f79230a6ce0063fb1092e4f6577e312f86d", size = 376725, upload-time = "2025-12-14T07:57:07.894Z" },
{ url = "https://files.pythonhosted.org/packages/c7/ea/2820e65f506894c459b840d1091ae6e327fde3d5a3f3b002a11a1b9bdf7d/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43a9353e2db5b024c91a47d864ef15eaa62d81824cfc7740fed4cef7db738694", size = 202466, upload-time = "2025-12-14T07:57:09.049Z" },
{ url = "https://files.pythonhosted.org/packages/45/8b/def01c13339c5bbec2ee1469ef53e7fadd66c8d775df974ee4def1572515/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc8fe866b7706fc25af0adf1f600bc06ece5b15ca44e34641327198b821e5c3c", size = 210748, upload-time = "2025-12-14T07:57:10.074Z" },
{ url = "https://files.pythonhosted.org/packages/5d/d2/bf350c92f7f067dd9484499705f2d8366d8d9008a670e3d1d0add1908f85/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:813755b5f598a78242042e05dfd1ada4e769e94b98c9ab82554550f97ff4d641", size = 211510, upload-time = "2025-12-14T07:57:11.165Z" },
{ url = "https://files.pythonhosted.org/packages/74/92/9d689bcb95304a6da26c4d59439c350940c25d1b35f146d402ccc6344c51/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8eea2a13536fae45d78f93f2cc846c9765c7160c85f19cfefecc20873c137cdd", size = 386237, upload-time = "2025-12-14T07:57:12.306Z" },
{ url = "https://files.pythonhosted.org/packages/17/fe/bd3107547f8b6129265dd957f40b9cd547d2445db2292aacb13335a7ea89/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7a02ebda1a863cbc604740e76faca8eee1add322db2dcbe6cf32669fffdff65c", size = 479589, upload-time = "2025-12-14T07:57:13.475Z" },
{ url = "https://files.pythonhosted.org/packages/c1/7c/e8e5cc9edb967d44f6f85e9ebdad440b59af3fae00b137a4327dc5aed9bb/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c0bd63897c439931cdf29348e5e6e8c330d529830e848d10767615c0f3d1b82", size = 388077, upload-time = "2025-12-14T07:57:14.551Z" },
{ url = "https://files.pythonhosted.org/packages/35/6b/5031797e43b58506f28a8760b26dc23f2620fb4f2200c4c1b3045603e67e/ormsgpack-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:362f2e812f8d7035dc25a009171e09d7cc97cb30d3c9e75a16aeae00ca3c1dcf", size = 116190, upload-time = "2025-12-14T07:57:15.575Z" },
{ url = "https://files.pythonhosted.org/packages/1e/fd/9f43ea6425e383a6b2dbfafebb06fd60e8d68c700ef715adfbcdb499f75d/ormsgpack-1.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:6190281e381db2ed0045052208f47a995ccf61eed48f1215ae3cce3fbccd59c5", size = 109990, upload-time = "2025-12-14T07:57:16.419Z" },
{ url = "https://files.pythonhosted.org/packages/11/42/f110dfe7cf23a52a82e23eb23d9a6a76ae495447d474686dfa758f3d71d6/ormsgpack-1.12.1-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9663d6b3ecc917c063d61a99169ce196a80f3852e541ae404206836749459279", size = 376746, upload-time = "2025-12-14T07:57:17.699Z" },
{ url = "https://files.pythonhosted.org/packages/11/76/b386e508a8ae207daec240201a81adb26467bf99b163560724e86bd9ff33/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32e85cfbaf01a94a92520e7fe7851cfcfe21a5698299c28ab86194895f9b9233", size = 202489, upload-time = "2025-12-14T07:57:18.807Z" },
{ url = "https://files.pythonhosted.org/packages/ea/0e/5db7a63f387149024572daa3d9512fe8fb14bf4efa0722d6d491bed280e7/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dabfd2c24b59c7c69870a5ecee480dfae914a42a0c2e7c9d971cf531e2ba471a", size = 210757, upload-time = "2025-12-14T07:57:19.893Z" },
{ url = "https://files.pythonhosted.org/packages/64/79/3a9899e57cb57430bd766fc1b4c9ad410cb2ba6070bc8cf6301e7d385768/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51bbf2b64afeded34ccd8e25402e4bca038757913931fa0d693078d75563f6f9", size = 211518, upload-time = "2025-12-14T07:57:20.972Z" },
{ url = "https://files.pythonhosted.org/packages/d7/cd/4f41710ae9fe50d7fcbe476793b3c487746d0e1cc194cc0fee42ff6d989b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9959a71dde1bd0ced84af17facc06a8afada495a34e9cb1bad8e9b20d4c59cef", size = 386251, upload-time = "2025-12-14T07:57:22.099Z" },
{ url = "https://files.pythonhosted.org/packages/bf/54/ba0c97d6231b1f01daafaa520c8cce1e1b7fceaae6fdc1c763925874a7de/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:e9be0e3b62d758f21f5b20e0e06b3a240ec546c4a327bf771f5825462aa74714", size = 479607, upload-time = "2025-12-14T07:57:23.525Z" },
{ url = "https://files.pythonhosted.org/packages/18/75/19a9a97a462776d525baf41cfb7072734528775f0a3d5fbfab3aa7756b9b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a29d49ab7fdd77ea787818e60cb4ef491708105b9c4c9b0f919201625eb036b5", size = 388062, upload-time = "2025-12-14T07:57:24.616Z" },
{ url = "https://files.pythonhosted.org/packages/a8/6a/ec26e3f44e9632ecd2f43638b7b37b500eaea5d79cab984ad0b94be14f82/ormsgpack-1.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:c418390b47a1d367e803f6c187f77e4d67c7ae07ba962e3a4a019001f4b0291a", size = 116195, upload-time = "2025-12-14T07:57:25.626Z" },
{ url = "https://files.pythonhosted.org/packages/7d/64/bfa5f4a34d0f15c6aba1b73e73f7441a66d635bd03249d334a4796b7a924/ormsgpack-1.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:cfa22c91cffc10a7fbd43729baff2de7d9c28cef2509085a704168ae31f02568", size = 109986, upload-time = "2025-12-14T07:57:26.569Z" },
{ url = "https://files.pythonhosted.org/packages/87/0e/78e5697164e3223b9b216c13e99f1acbc1ee9833490d68842b13da8ba883/ormsgpack-1.12.1-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b93c91efb1a70751a1902a5b43b27bd8fd38e0ca0365cf2cde2716423c15c3a6", size = 376758, upload-time = "2025-12-14T07:57:27.641Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0e/3a3cbb64703263d7bbaed7effa3ce78cb9add360a60aa7c544d7df28b641/ormsgpack-1.12.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf0ea0389167b5fa8d2933dd3f33e887ec4ba68f89c25214d7eec4afd746d22", size = 202487, upload-time = "2025-12-14T07:57:29.051Z" },
{ url = "https://files.pythonhosted.org/packages/d7/2c/807ebe2b77995599bbb1dec8c3f450d5d7dddee14ce3e1e71dc60e2e2a74/ormsgpack-1.12.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4c29af837f35af3375070689e781161e7cf019eb2f7cd641734ae45cd001c0d", size = 210853, upload-time = "2025-12-14T07:57:30.508Z" },
{ url = "https://files.pythonhosted.org/packages/25/57/2cdfc354e3ad8e847628f511f4d238799d90e9e090941e50b9d5ba955ae2/ormsgpack-1.12.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:336fc65aa0fe65896a3dabaae31e332a0a98b4a00ad7b0afde21a7505fd23ff3", size = 211545, upload-time = "2025-12-14T07:57:31.585Z" },
{ url = "https://files.pythonhosted.org/packages/76/1d/c6fda560e4a8ff865b3aec8a86f7c95ab53f4532193a6ae4ab9db35f85aa/ormsgpack-1.12.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:940f60aabfefe71dd6b82cb33f4ff10b2e7f5fcfa5f103cdb0a23b6aae4c713c", size = 386333, upload-time = "2025-12-14T07:57:32.957Z" },
{ url = "https://files.pythonhosted.org/packages/fc/3e/715081b36fceb8b497c68b87d384e1cc6d9c9c130ce3b435634d3d785b86/ormsgpack-1.12.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:596ad9e1b6d4c95595c54aaf49b1392609ca68f562ce06f4f74a5bc4053bcda4", size = 479701, upload-time = "2025-12-14T07:57:34.686Z" },
{ url = "https://files.pythonhosted.org/packages/6d/cf/01ad04def42b3970fc1a302c07f4b46339edf62ef9650247097260471f40/ormsgpack-1.12.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:575210e8fcbc7b0375026ba040a5eef223e9f66a4453d9623fc23282ae09c3c8", size = 388148, upload-time = "2025-12-14T07:57:35.771Z" },
{ url = "https://files.pythonhosted.org/packages/15/91/1fff2fc2b5943c740028f339154e7103c8f2edf1a881d9fbba2ce11c3b1d/ormsgpack-1.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:647daa3718572280893456be44c60aea6690b7f2edc54c55648ee66e8f06550f", size = 116201, upload-time = "2025-12-14T07:57:36.763Z" },
{ url = "https://files.pythonhosted.org/packages/ed/66/142b542aed3f96002c7d1c33507ca6e1e0d0a42b9253ab27ef7ed5793bd9/ormsgpack-1.12.1-cp314-cp314-win_arm64.whl", hash = "sha256:a8b3ab762a6deaf1b6490ab46dda0c51528cf8037e0246c40875c6fe9e37b699", size = 110029, upload-time = "2025-12-14T07:57:37.703Z" },
{ url = "https://files.pythonhosted.org/packages/38/b3/ef4494438c90359e1547eaed3c5ec46e2c431d59a3de2af4e70ebd594c49/ormsgpack-1.12.1-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:12087214e436c1f6c28491949571abea759a63111908c4f7266586d78144d7a8", size = 376777, upload-time = "2025-12-14T07:57:38.795Z" },
{ url = "https://files.pythonhosted.org/packages/05/a0/1149a7163f8b0dfbc64bf9099b6f16d102ad3b03bcc11afee198d751da2d/ormsgpack-1.12.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e6d54c14cf86ef13f10ccade94d1e7de146aa9b17d371e18b16e95f329393b7", size = 202490, upload-time = "2025-12-14T07:57:40.168Z" },
{ url = "https://files.pythonhosted.org/packages/68/82/f2ec5e758d6a7106645cca9bb7137d98bce5d363789fa94075be6572057c/ormsgpack-1.12.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f3584d07882b7ea2a1a589f795a3af97fe4c2932b739408e6d1d9d286cad862", size = 211733, upload-time = "2025-12-14T07:57:42.253Z" },
{ url = "https://files.pythonhosted.org/packages/93/fa/a91f70829ebccf6387c4946e0a1a109f6ba0d6a28d65f628bedfad94b890/ormsgpack-1.12.2-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c1429217f8f4d7fcb053523bbbac6bed5e981af0b85ba616e6df7cce53c19657", size = 378262, upload-time = "2026-01-18T20:55:22.284Z" },
{ url = "https://files.pythonhosted.org/packages/5f/62/3698a9a0c487252b5c6a91926e5654e79e665708ea61f67a8bdeceb022bf/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f13034dc6c84a6280c6c33db7ac420253852ea233fc3ee27c8875f8dd651163", size = 203034, upload-time = "2026-01-18T20:55:53.324Z" },
{ url = "https://files.pythonhosted.org/packages/66/3a/f716f64edc4aec2744e817660b317e2f9bb8de372338a95a96198efa1ac1/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:59f5da97000c12bc2d50e988bdc8576b21f6ab4e608489879d35b2c07a8ab51a", size = 210538, upload-time = "2026-01-18T20:55:20.097Z" },
{ url = "https://files.pythonhosted.org/packages/72/30/a436be9ce27d693d4e19fa94900028067133779f09fc45776db3f689c822/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e4459c3f27066beadb2b81ea48a076a417aafffff7df1d3c11c519190ed44f2", size = 212401, upload-time = "2026-01-18T20:55:46.447Z" },
{ url = "https://files.pythonhosted.org/packages/10/c5/cde98300fd33fee84ca71de4751b19aeeca675f0cf3c0ec4b043f40f3b76/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a1c460655d7288407ffa09065e322a7231997c0d62ce914bf3a96ad2dc6dedd", size = 387080, upload-time = "2026-01-18T20:56:00.884Z" },
{ url = "https://files.pythonhosted.org/packages/6a/31/30bf445ef827546747c10889dd254b3d84f92b591300efe4979d792f4c41/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:458e4568be13d311ef7d8877275e7ccbe06c0e01b39baaac874caaa0f46d826c", size = 482346, upload-time = "2026-01-18T20:55:39.831Z" },
{ url = "https://files.pythonhosted.org/packages/2e/f5/e1745ddf4fa246c921b5ca253636c4c700ff768d78032f79171289159f6e/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8cde5eaa6c6cbc8622db71e4a23de56828e3d876aeb6460ffbcb5b8aff91093b", size = 425178, upload-time = "2026-01-18T20:55:27.106Z" },
{ url = "https://files.pythonhosted.org/packages/8d/a2/e6532ed7716aed03dede8df2d0d0d4150710c2122647d94b474147ccd891/ormsgpack-1.12.2-cp310-cp310-win_amd64.whl", hash = "sha256:dc7a33be14c347893edbb1ceda89afbf14c467d593a5ee92c11de4f1666b4d4f", size = 117183, upload-time = "2026-01-18T20:55:55.52Z" },
{ url = "https://files.pythonhosted.org/packages/4b/08/8b68f24b18e69d92238aa8f258218e6dfeacf4381d9d07ab8df303f524a9/ormsgpack-1.12.2-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bd5f4bf04c37888e864f08e740c5a573c4017f6fd6e99fa944c5c935fabf2dd9", size = 378266, upload-time = "2026-01-18T20:55:59.876Z" },
{ url = "https://files.pythonhosted.org/packages/0d/24/29fc13044ecb7c153523ae0a1972269fcd613650d1fa1a9cec1044c6b666/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d5b28b3570e9fed9a5a76528fc7230c3c76333bc214798958e58e9b79cc18a", size = 203035, upload-time = "2026-01-18T20:55:30.59Z" },
{ url = "https://files.pythonhosted.org/packages/ad/c2/00169fb25dd8f9213f5e8a549dfb73e4d592009ebc85fbbcd3e1dcac575b/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3708693412c28f3538fb5a65da93787b6bbab3484f6bc6e935bfb77a62400ae5", size = 210539, upload-time = "2026-01-18T20:55:48.569Z" },
{ url = "https://files.pythonhosted.org/packages/1b/33/543627f323ff3c73091f51d6a20db28a1a33531af30873ea90c5ac95a9b5/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43013a3f3e2e902e1d05e72c0f1aeb5bedbb8e09240b51e26792a3c89267e181", size = 212401, upload-time = "2026-01-18T20:56:10.101Z" },
{ url = "https://files.pythonhosted.org/packages/e8/5d/f70e2c3da414f46186659d24745483757bcc9adccb481a6eb93e2b729301/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7c8b1667a72cbba74f0ae7ecf3105a5e01304620ed14528b2cb4320679d2869b", size = 387082, upload-time = "2026-01-18T20:56:12.047Z" },
{ url = "https://files.pythonhosted.org/packages/c0/d6/06e8dc920c7903e051f30934d874d4afccc9bb1c09dcaf0bc03a7de4b343/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:df6961442140193e517303d0b5d7bc2e20e69a879c2d774316125350c4a76b92", size = 482346, upload-time = "2026-01-18T20:56:05.152Z" },
{ url = "https://files.pythonhosted.org/packages/66/c4/f337ac0905eed9c393ef990c54565cd33644918e0a8031fe48c098c71dbf/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c6a4c34ddef109647c769d69be65fa1de7a6022b02ad45546a69b3216573eb4a", size = 425181, upload-time = "2026-01-18T20:55:37.83Z" },
{ url = "https://files.pythonhosted.org/packages/78/29/6d5758fabef3babdf4bbbc453738cc7de9cd3334e4c38dd5737e27b85653/ormsgpack-1.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:73670ed0375ecc303858e3613f407628dd1fca18fe6ac57b7b7ce66cc7bb006c", size = 117182, upload-time = "2026-01-18T20:55:31.472Z" },
{ url = "https://files.pythonhosted.org/packages/c4/57/17a15549233c37e7fd054c48fe9207492e06b026dbd872b826a0b5f833b6/ormsgpack-1.12.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2be829954434e33601ae5da328cccce3266b098927ca7a30246a0baec2ce7bd", size = 111464, upload-time = "2026-01-18T20:55:38.811Z" },
{ url = "https://files.pythonhosted.org/packages/4c/36/16c4b1921c308a92cef3bf6663226ae283395aa0ff6e154f925c32e91ff5/ormsgpack-1.12.2-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7a29d09b64b9694b588ff2f80e9826bdceb3a2b91523c5beae1fab27d5c940e7", size = 378618, upload-time = "2026-01-18T20:55:50.835Z" },
{ url = "https://files.pythonhosted.org/packages/c0/68/468de634079615abf66ed13bb5c34ff71da237213f29294363beeeca5306/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b39e629fd2e1c5b2f46f99778450b59454d1f901bc507963168985e79f09c5d", size = 203186, upload-time = "2026-01-18T20:56:11.163Z" },
{ url = "https://files.pythonhosted.org/packages/73/a9/d756e01961442688b7939bacd87ce13bfad7d26ce24f910f6028178b2cc8/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:958dcb270d30a7cb633a45ee62b9444433fa571a752d2ca484efdac07480876e", size = 210738, upload-time = "2026-01-18T20:56:09.181Z" },
{ url = "https://files.pythonhosted.org/packages/7b/ba/795b1036888542c9113269a3f5690ab53dd2258c6fb17676ac4bd44fcf94/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d379d72b6c5e964851c77cfedfb386e474adee4fd39791c2c5d9efb53505cc", size = 212569, upload-time = "2026-01-18T20:56:06.135Z" },
{ url = "https://files.pythonhosted.org/packages/6c/aa/bff73c57497b9e0cba8837c7e4bcab584b1a6dbc91a5dd5526784a5030c8/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8463a3fc5f09832e67bdb0e2fda6d518dc4281b133166146a67f54c08496442e", size = 387166, upload-time = "2026-01-18T20:55:36.738Z" },
{ url = "https://files.pythonhosted.org/packages/d3/cf/f8283cba44bcb7b14f97b6274d449db276b3a86589bdb363169b51bc12de/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:eddffb77eff0bad4e67547d67a130604e7e2dfbb7b0cde0796045be4090f35c6", size = 482498, upload-time = "2026-01-18T20:55:29.626Z" },
{ url = "https://files.pythonhosted.org/packages/05/be/71e37b852d723dfcbe952ad04178c030df60d6b78eba26bfd14c9a40575e/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcd55e5f6ba0dbce624942adf9f152062135f991a0126064889f68eb850de0dd", size = 425518, upload-time = "2026-01-18T20:55:49.556Z" },
{ url = "https://files.pythonhosted.org/packages/7a/0c/9803aa883d18c7ef197213cd2cbf73ba76472a11fe100fb7dab2884edf48/ormsgpack-1.12.2-cp312-cp312-win_amd64.whl", hash = "sha256:d024b40828f1dde5654faebd0d824f9cc29ad46891f626272dd5bfd7af2333a4", size = 117462, upload-time = "2026-01-18T20:55:47.726Z" },
{ url = "https://files.pythonhosted.org/packages/c8/9e/029e898298b2cc662f10d7a15652a53e3b525b1e7f07e21fef8536a09bb8/ormsgpack-1.12.2-cp312-cp312-win_arm64.whl", hash = "sha256:da538c542bac7d1c8f3f2a937863dba36f013108ce63e55745941dda4b75dbb6", size = 111559, upload-time = "2026-01-18T20:55:54.273Z" },
{ url = "https://files.pythonhosted.org/packages/eb/29/bb0eba3288c0449efbb013e9c6f58aea79cf5cb9ee1921f8865f04c1a9d7/ormsgpack-1.12.2-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5ea60cb5f210b1cfbad8c002948d73447508e629ec375acb82910e3efa8ff355", size = 378661, upload-time = "2026-01-18T20:55:57.765Z" },
{ url = "https://files.pythonhosted.org/packages/6e/31/5efa31346affdac489acade2926989e019e8ca98129658a183e3add7af5e/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3601f19afdbea273ed70b06495e5794606a8b690a568d6c996a90d7255e51c1", size = 203194, upload-time = "2026-01-18T20:56:08.252Z" },
{ url = "https://files.pythonhosted.org/packages/eb/56/d0087278beef833187e0167f8527235ebe6f6ffc2a143e9de12a98b1ce87/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29a9f17a3dac6054c0dce7925e0f4995c727f7c41859adf9b5572180f640d172", size = 210778, upload-time = "2026-01-18T20:55:17.694Z" },
{ url = "https://files.pythonhosted.org/packages/1c/a2/072343e1413d9443e5a252a8eb591c2d5b1bffbe5e7bfc78c069361b92eb/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39c1bd2092880e413902910388be8715f70b9f15f20779d44e673033a6146f2d", size = 212592, upload-time = "2026-01-18T20:55:32.747Z" },
{ url = "https://files.pythonhosted.org/packages/a2/8b/a0da3b98a91d41187a63b02dda14267eefc2a74fcb43cc2701066cf1510e/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:50b7249244382209877deedeee838aef1542f3d0fc28b8fe71ca9d7e1896a0d7", size = 387164, upload-time = "2026-01-18T20:55:40.853Z" },
{ url = "https://files.pythonhosted.org/packages/19/bb/6d226bc4cf9fc20d8eb1d976d027a3f7c3491e8f08289a2e76abe96a65f3/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:5af04800d844451cf102a59c74a841324868d3f1625c296a06cc655c542a6685", size = 482516, upload-time = "2026-01-18T20:55:42.033Z" },
{ url = "https://files.pythonhosted.org/packages/fb/f1/bb2c7223398543dedb3dbf8bb93aaa737b387de61c5feaad6f908841b782/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cec70477d4371cd524534cd16472d8b9cc187e0e3043a8790545a9a9b296c258", size = 425539, upload-time = "2026-01-18T20:55:24.727Z" },
{ url = "https://files.pythonhosted.org/packages/7b/e8/0fb45f57a2ada1fed374f7494c8cd55e2f88ccd0ab0a669aa3468716bf5f/ormsgpack-1.12.2-cp313-cp313-win_amd64.whl", hash = "sha256:21f4276caca5c03a818041d637e4019bc84f9d6ca8baa5ea03e5cc8bf56140e9", size = 117459, upload-time = "2026-01-18T20:55:56.876Z" },
{ url = "https://files.pythonhosted.org/packages/7a/d4/0cfeea1e960d550a131001a7f38a5132c7ae3ebde4c82af1f364ccc5d904/ormsgpack-1.12.2-cp313-cp313-win_arm64.whl", hash = "sha256:baca4b6773d20a82e36d6fd25f341064244f9f86a13dead95dd7d7f996f51709", size = 111577, upload-time = "2026-01-18T20:55:43.605Z" },
{ url = "https://files.pythonhosted.org/packages/94/16/24d18851334be09c25e87f74307c84950f18c324a4d3c0b41dabdbf19c29/ormsgpack-1.12.2-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bc68dd5915f4acf66ff2010ee47c8906dc1cf07399b16f4089f8c71733f6e36c", size = 378717, upload-time = "2026-01-18T20:55:26.164Z" },
{ url = "https://files.pythonhosted.org/packages/b5/a2/88b9b56f83adae8032ac6a6fa7f080c65b3baf9b6b64fd3d37bd202991d4/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46d084427b4132553940070ad95107266656cb646ea9da4975f85cb1a6676553", size = 203183, upload-time = "2026-01-18T20:55:18.815Z" },
{ url = "https://files.pythonhosted.org/packages/a9/80/43e4555963bf602e5bdc79cbc8debd8b6d5456c00d2504df9775e74b450b/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c010da16235806cf1d7bc4c96bf286bfa91c686853395a299b3ddb49499a3e13", size = 210814, upload-time = "2026-01-18T20:55:33.973Z" },
{ url = "https://files.pythonhosted.org/packages/78/e1/7cfbf28de8bca6efe7e525b329c31277d1b64ce08dcba723971c241a9d60/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18867233df592c997154ff942a6503df274b5ac1765215bceba7a231bea2745d", size = 212634, upload-time = "2026-01-18T20:55:28.634Z" },
{ url = "https://files.pythonhosted.org/packages/95/f8/30ae5716e88d792a4e879debee195653c26ddd3964c968594ddef0a3cc7e/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b009049086ddc6b8f80c76b3955df1aa22a5fbd7673c525cd63bf91f23122ede", size = 387139, upload-time = "2026-01-18T20:56:02.013Z" },
{ url = "https://files.pythonhosted.org/packages/dc/81/aee5b18a3e3a0e52f718b37ab4b8af6fae0d9d6a65103036a90c2a8ffb5d/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1dcc17d92b6390d4f18f937cf0b99054824a7815818012ddca925d6e01c2e49e", size = 482578, upload-time = "2026-01-18T20:55:35.117Z" },
{ url = "https://files.pythonhosted.org/packages/bd/17/71c9ba472d5d45f7546317f467a5fc941929cd68fb32796ca3d13dcbaec2/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f04b5e896d510b07c0ad733d7fce2d44b260c5e6c402d272128f8941984e4285", size = 425539, upload-time = "2026-01-18T20:56:04.009Z" },
{ url = "https://files.pythonhosted.org/packages/2e/a6/ac99cd7fe77e822fed5250ff4b86fa66dd4238937dd178d2299f10b69816/ormsgpack-1.12.2-cp314-cp314-win_amd64.whl", hash = "sha256:ae3aba7eed4ca7cb79fd3436eddd29140f17ea254b91604aa1eb19bfcedb990f", size = 117493, upload-time = "2026-01-18T20:56:07.343Z" },
{ url = "https://files.pythonhosted.org/packages/3a/67/339872846a1ae4592535385a1c1f93614138566d7af094200c9c3b45d1e5/ormsgpack-1.12.2-cp314-cp314-win_arm64.whl", hash = "sha256:118576ea6006893aea811b17429bfc561b4778fad393f5f538c84af70b01260c", size = 111579, upload-time = "2026-01-18T20:55:21.161Z" },
{ url = "https://files.pythonhosted.org/packages/49/c2/6feb972dc87285ad381749d3882d8aecbde9f6ecf908dd717d33d66df095/ormsgpack-1.12.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7121b3d355d3858781dc40dafe25a32ff8a8242b9d80c692fd548a4b1f7fd3c8", size = 378721, upload-time = "2026-01-18T20:55:52.12Z" },
{ url = "https://files.pythonhosted.org/packages/a3/9a/900a6b9b413e0f8a471cf07830f9cf65939af039a362204b36bd5b581d8b/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ee766d2e78251b7a63daf1cddfac36a73562d3ddef68cacfb41b2af64698033", size = 203170, upload-time = "2026-01-18T20:55:44.469Z" },
{ url = "https://files.pythonhosted.org/packages/87/4c/27a95466354606b256f24fad464d7c97ab62bce6cc529dd4673e1179b8fb/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292410a7d23de9b40444636b9b8f1e4e4b814af7f1ef476e44887e52a123f09d", size = 212816, upload-time = "2026-01-18T20:55:23.501Z" },
{ url = "https://files.pythonhosted.org/packages/73/cd/29cee6007bddf7a834e6cd6f536754c0535fcb939d384f0f37a38b1cddb8/ormsgpack-1.12.2-cp314-cp314t-win_amd64.whl", hash = "sha256:837dd316584485b72ef451d08dd3e96c4a11d12e4963aedb40e08f89685d8ec2", size = 117232, upload-time = "2026-01-18T20:55:45.448Z" },
]
[[package]]
@@ -1619,11 +1620,11 @@ wheels = [
[[package]]
name = "pycparser"
version = "2.23"
version = "3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" }
sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" },
{ url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
]
[[package]]
@@ -1966,28 +1967,28 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.13"
version = "0.14.14"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" }
sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" },
{ url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" },
{ url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" },
{ url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" },
{ url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" },
{ url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" },
{ url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" },
{ url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" },
{ url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" },
{ url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" },
{ url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" },
{ url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" },
{ url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" },
{ url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" },
{ url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" },
{ url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" },
{ url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" },
{ url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" },
{ url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" },
{ url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" },
{ url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" },
{ url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" },
{ url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" },
{ url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" },
{ url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" },
{ url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" },
{ url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" },
{ url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" },
{ url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" },
{ url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" },
{ url = "https://files.pythonhosted.org/packages/2c/aa/9f89c719c467dfaf8ad799b9bae0df494513fb21d31a6059cb5870e57e74/ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167", size = 10502442, upload-time = "2026-01-22T22:30:38.93Z" },
{ url = "https://files.pythonhosted.org/packages/87/44/90fa543014c45560cae1fffc63ea059fb3575ee6e1cb654562197e5d16fb/ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd", size = 11630486, upload-time = "2026-01-22T22:30:10.852Z" },
{ url = "https://files.pythonhosted.org/packages/9e/6a/40fee331a52339926a92e17ae748827270b288a35ef4a15c9c8f2ec54715/ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c", size = 10920448, upload-time = "2026-01-22T22:30:15.417Z" },
]
[[package]]
@@ -2005,11 +2006,11 @@ wheels = [
[[package]]
name = "setuptools"
version = "80.9.0"
version = "80.10.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" }
sdist = { url = "https://files.pythonhosted.org/packages/86/ff/f75651350db3cf2ef767371307eb163f3cc1ac03e16fdf3ac347607f7edb/setuptools-80.10.1.tar.gz", hash = "sha256:bf2e513eb8144c3298a3bd28ab1a5edb739131ec5c22e045ff93cd7f5319703a", size = 1229650, upload-time = "2026-01-21T09:42:03.061Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
{ url = "https://files.pythonhosted.org/packages/e0/76/f963c61683a39084aa575f98089253e1e852a4417cb8a3a8a422923a5246/setuptools-80.10.1-py3-none-any.whl", hash = "sha256:fc30c51cbcb8199a219c12cc9c281b5925a4978d212f84229c909636d9f6984e", size = 1099859, upload-time = "2026-01-21T09:42:00.688Z" },
]
[[package]]
@@ -2037,15 +2038,15 @@ wheels = [
[[package]]
name = "starlette"
version = "0.51.0"
version = "0.52.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio", marker = "python_full_version >= '3.11'" },
{ name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e7/65/5a1fadcc40c5fdc7df421a7506b79633af8f5d5e3a95c3e72acacec644b9/starlette-0.51.0.tar.gz", hash = "sha256:4c4fda9b1bc67f84037d3d14a5112e523509c369d9d47b111b2f984b0cc5ba6c", size = 2647658, upload-time = "2026-01-10T20:23:15.043Z" }
sdist = { url = "https://files.pythonhosted.org/packages/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/18/c4/09985a03dba389d4fe16a9014147a7b02fa76ef3519bf5846462a485876d/starlette-0.51.0-py3-none-any.whl", hash = "sha256:fb460a3d6fd3c958d729fdd96aee297f89a51b0181f16401fe8fd4cb6129165d", size = 74133, upload-time = "2026-01-10T20:23:13.445Z" },
{ url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" },
]
[[package]]
@@ -2200,31 +2201,31 @@ wheels = [
[[package]]
name = "uuid-utils"
version = "0.13.0"
version = "0.14.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/8a/17b11768dcb473d3a255c02ffdd94fbd1b345c906efea0a39124dcbaed52/uuid_utils-0.13.0.tar.gz", hash = "sha256:4c17df6427a9e23a4cd7fb9ee1efb53b8abb078660b9bdb2524ca8595022dfe1", size = 21921, upload-time = "2026-01-08T15:48:10.841Z" }
sdist = { url = "https://files.pythonhosted.org/packages/57/7c/3a926e847516e67bc6838634f2e54e24381105b4e80f9338dc35cca0086b/uuid_utils-0.14.0.tar.gz", hash = "sha256:fc5bac21e9933ea6c590433c11aa54aaca599f690c08069e364eb13a12f670b4", size = 22072, upload-time = "2026-01-20T20:37:15.729Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/85/b8/d40848ca22781f206c60a1885fc737d2640392bd6b5792d455525accd89c/uuid_utils-0.13.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:83628283e977fb212e756bc055df8fdd2f9f589a2e539ba1abe755b8ce8df7a4", size = 602130, upload-time = "2026-01-08T15:47:34.877Z" },
{ url = "https://files.pythonhosted.org/packages/40/b9/00a944b8096632ea12638181f8e294abcde3e3b8b5e29b777f809896f6ae/uuid_utils-0.13.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c47638ed6334ab19d80f73664f153b04bbb04ab8ce4298d10da6a292d4d21c47", size = 304213, upload-time = "2026-01-08T15:47:36.807Z" },
{ url = "https://files.pythonhosted.org/packages/da/d7/07b36c33aef683b81c9afff3ec178d5eb39d325447a68c3c68a62e4abb32/uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:b276b538c57733ed406948584912da422a604313c71479654848b84b9e19c9b0", size = 340624, upload-time = "2026-01-08T15:47:38.821Z" },
{ url = "https://files.pythonhosted.org/packages/7d/55/fcff2fff02a27866cb1a6614c9df2b3ace721f0a0aab2b7b8f5a7d4e4221/uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_armv7l.whl", hash = "sha256:bdaf2b77e34b199cf04cde28399495fd1ed951de214a4ece1f3919b2f945bb06", size = 346705, upload-time = "2026-01-08T15:47:40.397Z" },
{ url = "https://files.pythonhosted.org/packages/41/48/67438506c2bb8bee1b4b00d7c0b3ff866401b4790849bf591d654d4ea0bc/uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_i686.whl", hash = "sha256:eb2f0baf81e82f9769a7684022dca8f3bf801ca1574a3e94df1876e9d6f9271e", size = 366023, upload-time = "2026-01-08T15:47:42.662Z" },
{ url = "https://files.pythonhosted.org/packages/8b/d7/2d91ce17f62fd764d593430de296b70843cc25229c772453f7261de9e6a8/uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_ppc64le.whl", hash = "sha256:6be6c4d11275f5cc402a4fdba6c2b1ce45fd3d99bb78716cd1cc2cbf6802b2ce", size = 471149, upload-time = "2026-01-08T15:47:44.963Z" },
{ url = "https://files.pythonhosted.org/packages/2e/9a/aa0756186073ba84daf5704c150d41ede10eb3185d510e02532e2071550e/uuid_utils-0.13.0-cp39-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:77621cf6ceca7f42173a642a01c01c216f9eaec3b7b65d093d2d6a433ca0a83d", size = 342130, upload-time = "2026-01-08T15:47:46.331Z" },
{ url = "https://files.pythonhosted.org/packages/74/b4/3191789f4dc3bed59d79cec90559821756297a25d7dc34d1bf7781577a75/uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a5a9eb06c2bb86dd876cd7b2fe927fc8543d14c90d971581db6ffda4a02526f", size = 524128, upload-time = "2026-01-08T15:47:47.628Z" },
{ url = "https://files.pythonhosted.org/packages/b2/30/29839210a8fff9fc219bfa7c8d8cd115324e92618cba0cda090d54d3d321/uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:775347c6110fb71360df17aac74132d8d47c1dbe71233ac98197fc872a791fd2", size = 615872, upload-time = "2026-01-08T15:47:50.61Z" },
{ url = "https://files.pythonhosted.org/packages/99/ed/15000c96a8bd8f5fd8efd622109bf52549ea0b366f8ce71c45580fa55878/uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf95f6370ad1a0910ee7b5ad5228fd19c4ae32fe3627389006adaf519408c41e", size = 581023, upload-time = "2026-01-08T15:47:52.776Z" },
{ url = "https://files.pythonhosted.org/packages/67/c8/3f809fa2dc2ca4bd331c792a3c7d3e45ae2b709d85847a12b8b27d1d5f19/uuid_utils-0.13.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5a88e23e0b2f4203fefe2ccbca5736ee06fcad10e61b5e7e39c8d7904bc13300", size = 546715, upload-time = "2026-01-08T15:47:54.415Z" },
{ url = "https://files.pythonhosted.org/packages/f5/80/4f7c7efd734d1494397c781bd3d421688e9c187ae836e3174625b1ddf8b0/uuid_utils-0.13.0-cp39-abi3-win32.whl", hash = "sha256:3e4f2cc54e6a99c0551158100ead528479ad2596847478cbad624977064ffce3", size = 177650, upload-time = "2026-01-08T15:47:55.679Z" },
{ url = "https://files.pythonhosted.org/packages/6c/94/d05ab68622e66ad787a241dfe5ccc649b3af09f30eae977b9ee8f7046aaa/uuid_utils-0.13.0-cp39-abi3-win_amd64.whl", hash = "sha256:046cb2756e1597b3de22d24851b769913e192135830486a0a70bf41327f0360c", size = 183211, upload-time = "2026-01-08T15:47:57.604Z" },
{ url = "https://files.pythonhosted.org/packages/69/37/674b3ce25cd715b831ea8ebbd828b74c40159f04c95d1bb963b2c876fe79/uuid_utils-0.13.0-cp39-abi3-win_arm64.whl", hash = "sha256:5447a680df6ef8a5a353976aaf4c97cc3a3a22b1ee13671c44227b921e3ae2a9", size = 183518, upload-time = "2026-01-08T15:47:59.148Z" },
{ url = "https://files.pythonhosted.org/packages/99/fa/1d92de9538463859228e68db679b766fd300770c9a2db849dcba0c0c5a57/uuid_utils-0.13.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e5182e2d95f38e65f2e5bce90648ef56987443da13e145afcd747e584f9bc69c", size = 587641, upload-time = "2026-01-08T15:48:00.433Z" },
{ url = "https://files.pythonhosted.org/packages/ca/07/6bd9e6f5367e38c2ee7178ad882d2bd1b0d17c5393974b09ab027a215eba/uuid_utils-0.13.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e3909a8a1fbd79d7c8bdc874eeb83e23ccb7a7cb0aa821a49596cc96c0cce84b", size = 298273, upload-time = "2026-01-08T15:48:02.063Z" },
{ url = "https://files.pythonhosted.org/packages/dc/14/7061b868a8a6799c8df83768a23f313d4e22075069f01ee3c28fa82aa2c6/uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.whl", hash = "sha256:5dc4c9f749bd2511b8dcbf0891e658d7d86880022963db050722ad7b502b5e22", size = 333618, upload-time = "2026-01-08T15:48:03.503Z" },
{ url = "https://files.pythonhosted.org/packages/bc/f1/f48c3c9c343c9071ade5f355403e344d817412d9cf379a2d04b181282e74/uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_armv7l.whl", hash = "sha256:516adf07f5b2cdb88d50f489c702b5f1a75ae8b2639bfd254f4192d5f7ee261f", size = 339104, upload-time = "2026-01-08T15:48:05.02Z" },
{ url = "https://files.pythonhosted.org/packages/47/22/8e3142b4baffee77ce533fe956446d3699ec42f1d5252911208cbef4501e/uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_i686.whl", hash = "sha256:aeee3bd89e8de6184a3ab778ce19f5ce9ad32849d1be549516e0ddb257562d8d", size = 359503, upload-time = "2026-01-08T15:48:06.347Z" },
{ url = "https://files.pythonhosted.org/packages/bd/1a/756f1f9e31b15019c87cd2becb1c596351c50967cd143443da38df8818d1/uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_ppc64le.whl", hash = "sha256:97985256c2e59b7caa51f5c8515f64d777328562a9c900ec65e9d627baf72737", size = 467480, upload-time = "2026-01-08T15:48:07.681Z" },
{ url = "https://files.pythonhosted.org/packages/0a/20/a6929e98d9a461ca49e96194a82a1cc3fd5420f3a2f53cbb34fca438549e/uuid_utils-0.13.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:b7ccaa20e24c5f60f41a69ef571ed820737f9b0ade4cbeef56aaa8f80f5aa475", size = 333610, upload-time = "2026-01-08T15:48:09.375Z" },
{ url = "https://files.pythonhosted.org/packages/a7/42/42d003f4a99ddc901eef2fd41acb3694163835e037fb6dde79ad68a72342/uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f6695c0bed8b18a904321e115afe73b34444bc8451d0ce3244a1ec3b84deb0e5", size = 601786, upload-time = "2026-01-20T20:37:09.843Z" },
{ url = "https://files.pythonhosted.org/packages/96/e6/775dfb91f74b18f7207e3201eb31ee666d286579990dc69dd50db2d92813/uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:4f0a730bbf2d8bb2c11b93e1005e91769f2f533fa1125ed1f00fd15b6fcc732b", size = 303943, upload-time = "2026-01-20T20:37:18.767Z" },
{ url = "https://files.pythonhosted.org/packages/17/82/ea5f5e85560b08a1f30cdc65f75e76494dc7aba9773f679e7eaa27370229/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40ce3fd1a4fdedae618fc3edc8faf91897012469169d600133470f49fd699ed3", size = 340467, upload-time = "2026-01-20T20:37:11.794Z" },
{ url = "https://files.pythonhosted.org/packages/ca/33/54b06415767f4569882e99b6470c6c8eeb97422686a6d432464f9967fd91/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:09ae4a98416a440e78f7d9543d11b11cae4bab538b7ed94ec5da5221481748f2", size = 346333, upload-time = "2026-01-20T20:37:12.818Z" },
{ url = "https://files.pythonhosted.org/packages/cb/10/a6bce636b8f95e65dc84bf4a58ce8205b8e0a2a300a38cdbc83a3f763d27/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:971e8c26b90d8ae727e7f2ac3ee23e265971d448b3672882f2eb44828b2b8c3e", size = 470859, upload-time = "2026-01-20T20:37:01.512Z" },
{ url = "https://files.pythonhosted.org/packages/8a/27/84121c51ea72f013f0e03d0886bcdfa96b31c9b83c98300a7bd5cc4fa191/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5cde1fa82804a8f9d2907b7aec2009d440062c63f04abbdb825fce717a5e860", size = 341988, upload-time = "2026-01-20T20:37:22.881Z" },
{ url = "https://files.pythonhosted.org/packages/90/a4/01c1c7af5e6a44f20b40183e8dac37d6ed83e7dc9e8df85370a15959b804/uuid_utils-0.14.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c7343862a2359e0bd48a7f3dfb5105877a1728677818bb694d9f40703264a2db", size = 365784, upload-time = "2026-01-20T20:37:10.808Z" },
{ url = "https://files.pythonhosted.org/packages/04/f0/65ee43ec617b8b6b1bf2a5aecd56a069a08cca3d9340c1de86024331bde3/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c51e4818fdb08ccec12dc7083a01f49507b4608770a0ab22368001685d59381b", size = 523750, upload-time = "2026-01-20T20:37:06.152Z" },
{ url = "https://files.pythonhosted.org/packages/95/d3/6bf503e3f135a5dfe705a65e6f89f19bccd55ac3fb16cb5d3ec5ba5388b8/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:181bbcccb6f93d80a8504b5bd47b311a1c31395139596edbc47b154b0685b533", size = 615818, upload-time = "2026-01-20T20:37:21.816Z" },
{ url = "https://files.pythonhosted.org/packages/df/6c/99937dd78d07f73bba831c8dc9469dfe4696539eba2fc269ae1b92752f9e/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:5c8ae96101c3524ba8dbf762b6f05e9e9d896544786c503a727c5bf5cb9af1a7", size = 580831, upload-time = "2026-01-20T20:37:19.691Z" },
{ url = "https://files.pythonhosted.org/packages/44/fa/bbc9e2c25abd09a293b9b097a0d8fc16acd6a92854f0ec080f1ea7ad8bb3/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00ac3c6edfdaff7e1eed041f4800ae09a3361287be780d7610a90fdcde9befdc", size = 546333, upload-time = "2026-01-20T20:37:03.117Z" },
{ url = "https://files.pythonhosted.org/packages/e7/9b/e5e99b324b1b5f0c62882230455786df0bc66f67eff3b452447e703f45d2/uuid_utils-0.14.0-cp39-abi3-win32.whl", hash = "sha256:ec2fd80adf8e0e6589d40699e6f6df94c93edcc16dd999be0438dd007c77b151", size = 177319, upload-time = "2026-01-20T20:37:04.208Z" },
{ url = "https://files.pythonhosted.org/packages/d3/28/2c7d417ea483b6ff7820c948678fdf2ac98899dc7e43bb15852faa95acaf/uuid_utils-0.14.0-cp39-abi3-win_amd64.whl", hash = "sha256:efe881eb43a5504fad922644cb93d725fd8a6a6d949bd5a4b4b7d1a1587c7fd1", size = 182566, upload-time = "2026-01-20T20:37:16.868Z" },
{ url = "https://files.pythonhosted.org/packages/b8/86/49e4bdda28e962fbd7266684171ee29b3d92019116971d58783e51770745/uuid_utils-0.14.0-cp39-abi3-win_arm64.whl", hash = "sha256:32b372b8fd4ebd44d3a219e093fe981af4afdeda2994ee7db208ab065cfcd080", size = 182809, upload-time = "2026-01-20T20:37:05.139Z" },
{ url = "https://files.pythonhosted.org/packages/f1/03/1f1146e32e94d1f260dfabc81e1649102083303fb4ad549775c943425d9a/uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:762e8d67992ac4d2454e24a141a1c82142b5bde10409818c62adbe9924ebc86d", size = 587430, upload-time = "2026-01-20T20:37:24.998Z" },
{ url = "https://files.pythonhosted.org/packages/87/ba/d5a7469362594d885fd9219fe9e851efbe65101d3ef1ef25ea321d7ce841/uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:40be5bf0b13aa849d9062abc86c198be6a25ff35316ce0b89fc25f3bac6d525e", size = 298106, upload-time = "2026-01-20T20:37:23.896Z" },
{ url = "https://files.pythonhosted.org/packages/8a/11/3dafb2a5502586f59fd49e93f5802cd5face82921b3a0f3abb5f357cb879/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:191a90a6f3940d1b7322b6e6cceff4dd533c943659e0a15f788674407856a515", size = 333423, upload-time = "2026-01-20T20:37:17.828Z" },
{ url = "https://files.pythonhosted.org/packages/7c/f2/c8987663f0cdcf4d717a36d85b5db2a5589df0a4e129aa10f16f4380ef48/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4aa4525f4ad82f9d9c842f9a3703f1539c1808affbaec07bb1b842f6b8b96aa5", size = 338659, upload-time = "2026-01-20T20:37:14.286Z" },
{ url = "https://files.pythonhosted.org/packages/d1/c8/929d81665d83f0b2ffaecb8e66c3091a50f62c7cb5b65e678bd75a96684e/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdbd82ff20147461caefc375551595ecf77ebb384e46267f128aca45a0f2cdfc", size = 467029, upload-time = "2026-01-20T20:37:08.277Z" },
{ url = "https://files.pythonhosted.org/packages/8e/a0/27d7daa1bfed7163f4ccaf52d7d2f4ad7bb1002a85b45077938b91ee584f/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff57e8a5d540006ce73cf0841a643d445afe78ba12e75ac53a95ca2924a56be", size = 333298, upload-time = "2026-01-20T20:37:07.271Z" },
{ url = "https://files.pythonhosted.org/packages/63/d4/acad86ce012b42ce18a12f31ee2aa3cbeeb98664f865f05f68c882945913/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3fd9112ca96978361201e669729784f26c71fecc9c13a7f8a07162c31bd4d1e2", size = 359217, upload-time = "2026-01-20T20:36:59.687Z" },
]
[[package]]
+1 -1
View File
@@ -25,7 +25,7 @@ class AsyncQueue(asyncio.Queue):
self._getters.append(getter)
try:
await getter
except:
except BaseException:
getter.cancel() # Just in case getter is not done yet.
try:
# Clean self._getters from canceled getters.
+228 -4
View File
@@ -300,7 +300,56 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
**kwargs: Unpack[DeprecatedKwargs],
) -> Self:
"""Add a new node to the `StateGraph`, input schema is inferred as the state schema.
Will take the name of the function/runnable as the node name.
Args:
node: The function or runnable this node will run.
defer: Whether to defer the execution of the node until the run is about to end.
metadata: The metadata associated with the node.
input_schema: The input schema for the node. (Default: the graph's state schema)
retry_policy: The retry policy for the node.
If a sequence is provided, the first matching policy will be applied.
cache_policy: The cache policy for the node.
destinations: Destinations that indicate where a node can route to.
Useful for edgeless graphs with nodes that return `Command` objects.
If a `dict` is provided, the keys will be used as the target node names and the values will be used as the labels for the edges.
If a `tuple` is provided, the values will be used as the target node names.
!!! warning
This is only used for graph rendering and doesn't have any effect on the graph execution.
Example:
```python
from typing_extensions import TypedDict
from langchain_core.runnables import RunnableConfig
from langgraph.graph import START, StateGraph
class State(TypedDict):
x: int
def my_node(state: State, config: RunnableConfig) -> State:
return {"x": state["x"] + 1}
builder = StateGraph(State)
builder.add_node(my_node) # node name will be 'my_node'
builder.add_edge(START, "my_node")
graph = builder.compile()
graph.invoke({"x": 1})
# {'x': 2}
```
Returns:
Self: The instance of the `StateGraph`, allowing for method chaining.
"""
...
@@ -317,8 +366,61 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
destinations: dict[str, str] | tuple[str, ...] | None = None,
**kwargs: Unpack[DeprecatedKwargs],
) -> Self:
"""Add a new node to the `StateGraph`, input schema is specified.
"""Add a new node to the `StateGraph` where input schema is specified.
Will take the name of the function/runnable as the node name.
Args:
node: The function or runnable this node will run.
defer: Whether to defer the execution of the node until the run is about to end.
metadata: The metadata associated with the node.
input_schema: The input schema for the node.
retry_policy: The retry policy for the node.
If a sequence is provided, the first matching policy will be applied.
cache_policy: The cache policy for the node.
destinations: Destinations that indicate where a node can route to.
Useful for edgeless graphs with nodes that return `Command` objects.
If a `dict` is provided, the keys will be used as the target node names and the values will be used as the labels for the edges.
If a `tuple` is provided, the values will be used as the target node names.
!!! warning
This is only used for graph rendering and doesn't have any effect on the graph execution.
Example:
```python
from typing_extensions import TypedDict
from langchain_core.runnables import RunnableConfig
from langgraph.graph import START, StateGraph
class State(TypedDict):
x: int
class NodeInput(TypedDict):
x: int
def my_node(state: NodeInput, config: RunnableConfig) -> State:
return {"x": state["x"] + 1}
builder = StateGraph(State)
builder.add_node(my_node, input_schema=NodeInput) # node name will be 'my_node'
builder.add_edge(START, "my_node")
graph = builder.compile()
graph.invoke({"x": 1})
# {'x': 2}
```
Returns:
Self: The instance of the `StateGraph`, allowing for method chaining.
"""
...
@@ -336,7 +438,57 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
destinations: dict[str, str] | tuple[str, ...] | None = None,
**kwargs: Unpack[DeprecatedKwargs],
) -> Self:
"""Add a new node to the `StateGraph`, input schema is inferred as the state schema."""
"""Add a new node to the `StateGraph`, input schema is inferred as the state schema.
Args:
node: The name of the node.
action: The function or runnable this node will run.
defer: Whether to defer the execution of the node until the run is about to end.
metadata: The metadata associated with the node.
input_schema: The input schema for the node. (Default: the graph's state schema)
retry_policy: The retry policy for the node.
If a sequence is provided, the first matching policy will be applied.
cache_policy: The cache policy for the node.
destinations: Destinations that indicate where a node can route to.
Useful for edgeless graphs with nodes that return `Command` objects.
If a `dict` is provided, the keys will be used as the target node names and the values will be used as the labels for the edges.
If a `tuple` is provided, the values will be used as the target node names.
!!! warning
This is only used for graph rendering and doesn't have any effect on the graph execution.
Example:
```python
from typing_extensions import TypedDict
from langchain_core.runnables import RunnableConfig
from langgraph.graph import START, StateGraph
class State(TypedDict):
x: int
def my_node(state: State, config: RunnableConfig) -> State:
return {"x": state["x"] + 1}
builder = StateGraph(State)
builder.add_node("my_fair_node", my_node)
builder.add_edge(START, "my_fair_node")
graph = builder.compile()
graph.invoke({"x": 1})
# {'x': 2}
```
Returns:
Self: The instance of the `StateGraph`, allowing for method chaining.
"""
...
@overload
@@ -353,7 +505,65 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
destinations: dict[str, str] | tuple[str, ...] | None = None,
**kwargs: Unpack[DeprecatedKwargs],
) -> Self:
"""Add a new node to the `StateGraph`, input schema is specified."""
"""Add a new node to the `StateGraph`, input schema is specified.
Args:
node: The function or runnable this node will run.
If a string is provided, it will be used as the node name, and action will be used as the function or runnable.
action: The action associated with the node.
Will be used as the node function or runnable if `node` is a string (node name).
defer: Whether to defer the execution of the node until the run is about to end.
metadata: The metadata associated with the node.
input_schema: The input schema for the node.
retry_policy: The retry policy for the node.
If a sequence is provided, the first matching policy will be applied.
cache_policy: The cache policy for the node.
destinations: Destinations that indicate where a node can route to.
Useful for edgeless graphs with nodes that return `Command` objects.
If a `dict` is provided, the keys will be used as the target node names and the values will be used as the labels for the edges.
If a `tuple` is provided, the values will be used as the target node names.
!!! warning
This is only used for graph rendering and doesn't have any effect on the graph execution.
Example:
```python
from typing_extensions import TypedDict
from langchain_core.runnables import RunnableConfig
from langgraph.graph import START, StateGraph
class State(TypedDict):
x: int
class NodeInput(TypedDict):
x: int
def my_node(state: NodeInput, config: RunnableConfig) -> State:
return {"x": state["x"] + 1}
builder = StateGraph(State)
builder.add_node("my_fair_node", my_node, input_schema=NodeInput)
builder.add_edge(START, "my_fair_node")
graph = builder.compile()
graph.invoke({"x": 1})
# {'x': 2}
```
Returns:
Self: The instance of the `StateGraph`, allowing for method chaining.
"""
...
def add_node(
@@ -376,6 +586,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
If a string is provided, it will be used as the node name, and action will be used as the function or runnable.
action: The action associated with the node.
Will be used as the node function or runnable if `node` is a string (node name).
defer: Whether to defer the execution of the node until the run is about to end.
metadata: The metadata associated with the node.
@@ -392,7 +603,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
If a `tuple` is provided, the values will be used as the target node names.
!!! note
!!! warning
This is only used for graph rendering and doesn't have any effect on the graph execution.
@@ -846,6 +1057,19 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
If `None`, it may inherit the parent graph's checkpointer when used as a subgraph.
If `False`, it will not use or inherit any checkpointer.
**Important**: When a checkpointer is enabled, you should pass a `thread_id`
in the config when invoking the graph:
```python
config = {"configurable": {"thread_id": "my-thread"}}
graph.invoke(inputs, config)
```
The `thread_id` is the key used to store and retrieve checkpoints. Use a
unique ID for independent runs, or reuse the same ID to accumulate state
across invocations (e.g., for conversation memory).
interrupt_before: An optional list of node names to interrupt before.
interrupt_after: An optional list of node names to interrupt after.
debug: A flag indicating whether to enable debug mode.

Some files were not shown because too many files have changed in this diff Show More