mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-28 10:49:56 +02:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b45bbc1ba |
@@ -2,13 +2,13 @@
|
||||
packages:
|
||||
- name: "trustcall"
|
||||
repo: "hinthornw/trustcall"
|
||||
description: "Tenacious tool calling built on LangGraph."
|
||||
description: "Tenacious tool calling built on LangGraph"
|
||||
- name: "breeze-agent"
|
||||
repo: "andrestorres123/breeze-agent"
|
||||
description: "A streamlined research system built inspired on STORM and built on LangGraph."
|
||||
description: "A streamlined research system built inspired on STORM and built on LangGraph"
|
||||
- name: "langgraph-supervisor"
|
||||
repo: "langchain-ai/langgraph-supervisor-py"
|
||||
description: "Build supervisor multi-agent systems with LangGraph."
|
||||
repo: "langchain-ai/langgraph-supervisor"
|
||||
description: "Build supervisor multi-agent systems with LangGraph"
|
||||
- name: "langmem"
|
||||
repo: "langchain-ai/langmem"
|
||||
description: "Build agents that learn and adapt from interactions over time."
|
||||
@@ -18,6 +18,3 @@ packages:
|
||||
- name: "open-deep-research"
|
||||
repo: "langchain-ai/open_deep_research"
|
||||
description: "Open source assistant for iterative web research and report writing."
|
||||
- name: "langgraph-swarm"
|
||||
repo: "langchain-ai/langgraph-swarm-py"
|
||||
description: "Build swarm-style multi-agent systems using LangGraph."
|
||||
|
||||
@@ -9,7 +9,6 @@ This list of companies using LangGraph and their success stories is compiled fro
|
||||
| [AppFolio](https://www.appfolio.com/) | Real Estate | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-appfolio/) |
|
||||
| [Athena Intelligence](https://www.athenaintel.com/) | Software & Technology (GenAI Native) | Research & summarization | [Case study, 2024](https://blog.langchain.dev/customers-athena-intelligence/) |
|
||||
| [Captide](https://www.captide.co/) | Software & Technology (GenAI Native) | Data extraction | [Case study, 2025](https://blog.langchain.dev/how-captide-is-redefining-equity-research-with-agentic-workflows-built-on-langgraph-and-langsmith/) |
|
||||
| [Cisco Outshift](https://outshift.cisco.com/) | Software & Technology | DevOps | [Blog post, 2025](https://outshift.cisco.com/blog/build-react-agent-application-for-devops-tasks-using-rest-apis) |
|
||||
| [Elastic](https://www.elastic.co/) | Software & Technology | Copilot for domain-specific task | [Blog post, 2025](https://www.elastic.co/blog/elastic-security-generative-ai-features) |
|
||||
| [GitLab](https://about.gitlab.com/) | Software & Technology | Code generation | [Duo workflow docs](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/duo_workflow/) |
|
||||
| [Infor](https://infor.com/) | Software & Technology | GenAI embedded product experiences; customer support; copilot | [Case study, 2025](https://blog.langchain.dev/customers-infor/) |
|
||||
|
||||
@@ -2,12 +2,6 @@
|
||||
|
||||
The LangGraph Cloud Server supports specific environment variables for configuring a deployment.
|
||||
|
||||
## `DD_API_KEY`
|
||||
|
||||
Specify `DD_API_KEY` (your [Datadog API Key](https://docs.datadoghq.com/account_management/api-app-keys/)) to automatically enable Datadog tracing for the deployment. Specify other [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) to configure the tracing instrumentation.
|
||||
|
||||
If `DD_API_KEY` is specified, the application process is wrapped in the [`ddtrace-run` command](https://ddtrace.readthedocs.io/en/stable/installation_quickstart.html). Other `DD_*` environment variables (e.g. `DD_SITE`, `DD_ENV`, `DD_SERVICE`, `DD_TRACE_ENABLED`) are typically needed to properly configure the tracing instrumentation. See [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) for more details.
|
||||
|
||||
## `LANGCHAIN_TRACING_SAMPLING_RATE`
|
||||
|
||||
Sampling rate for traces sent to LangSmith. Valid values: Any float between `0` and `1`.
|
||||
|
||||
@@ -62,9 +62,3 @@ Yes! You can use LangGraph with any LLMs. The main reason we use LLMs that suppo
|
||||
## Does LangGraph work with OSS LLMs?
|
||||
|
||||
Yes! LangGraph is totally ambivalent to what LLMs are used under the hood. The main reason we use closed LLMs in most of the tutorials is that they seamlessly support tool calling, while OSS LLMs often don't. But tool calling is not necessary (see [this section](#does-langgraph-work-with-llms-that-dont-support-tool-calling)) so you can totally use LangGraph with OSS LLMs.
|
||||
|
||||
## Can I use LangGraph Studio without logging to LangSmith
|
||||
|
||||
Yes! You can use the [development version of LangGraph Server](../tutorials/langgraph-platform/local-server.md) to run the backend locally.
|
||||
This will connect to the studio frontend hosted as part of LangSmith.
|
||||
If you set an environment variable of `LANGSMITH_TRACING=false` then no traces will be sent to LangSmith.
|
||||
@@ -71,7 +71,7 @@ If you navigate to `localhost:2024/hello` in your browser (2024 is the default d
|
||||
|
||||
## Deploying
|
||||
|
||||
You can deploy this app as-is to the managed langgraph cloud or to your self-hosted platform.
|
||||
You can deploy this app as-is to the managed langgraph cloud or to your self-hsoted platform.
|
||||
|
||||
## Next steps
|
||||
|
||||
|
||||
Generated
+28
-25
@@ -169,15 +169,15 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "anthropic"
|
||||
version = "0.47.2"
|
||||
version = "0.45.2"
|
||||
description = "The official Python library for the anthropic API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["test"]
|
||||
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
|
||||
files = [
|
||||
{file = "anthropic-0.47.2-py3-none-any.whl", hash = "sha256:61b712a56308fce69f04d92ba0230ab2bc187b5bce17811d400843a8976bb67f"},
|
||||
{file = "anthropic-0.47.2.tar.gz", hash = "sha256:452f4ca0c56ffab8b6ce9928bf8470650f88106a7001b250895eb65c54cfa44c"},
|
||||
{file = "anthropic-0.45.2-py3-none-any.whl", hash = "sha256:ecd746f7274451dfcb7e1180571ead624c7e1195d1d46cb7c70143d2aedb4d35"},
|
||||
{file = "anthropic-0.45.2.tar.gz", hash = "sha256:32a18b9ecd12c91b2be4cae6ca2ab46a06937b5aa01b21308d97a6d29794fb5e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1299,7 +1299,7 @@ version = "0.7.1"
|
||||
description = "XML bomb protection for Python stdlib modules"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
groups = ["docs"]
|
||||
groups = ["docs", "test"]
|
||||
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
|
||||
files = [
|
||||
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
|
||||
@@ -3288,20 +3288,21 @@ together = ["langchain-together"]
|
||||
|
||||
[[package]]
|
||||
name = "langchain-anthropic"
|
||||
version = "0.3.8"
|
||||
version = "0.2.4"
|
||||
description = "An integration package connecting AnthropicMessages and LangChain"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["test"]
|
||||
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
|
||||
files = [
|
||||
{file = "langchain_anthropic-0.3.8-py3-none-any.whl", hash = "sha256:05a70f51500d3c4e0f3e463730e193a25b6244e06b3bda3d7b2ec21d83d081ae"},
|
||||
{file = "langchain_anthropic-0.3.8.tar.gz", hash = "sha256:1932977b8105744739ffdcb39861b041b73ae93846d0896a775fcea9a29e4b2b"},
|
||||
{file = "langchain_anthropic-0.2.4-py3-none-any.whl", hash = "sha256:bcb6c2d0df4a67aff52816621079d6e743b260911caccf313a72b33b7edece6f"},
|
||||
{file = "langchain_anthropic-0.2.4.tar.gz", hash = "sha256:0382d4c7b5236839b703f7b72b3e06de4bb5be99104b193f719adbe34c49562b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anthropic = ">=0.47.0,<1"
|
||||
langchain-core = ">=0.3.39,<1.0.0"
|
||||
anthropic = ">=0.30.0,<1"
|
||||
defusedxml = ">=0.7.1,<0.8.0"
|
||||
langchain-core = ">=0.3.15,<0.4.0"
|
||||
pydantic = ">=2.7.4,<3.0.0"
|
||||
|
||||
[[package]]
|
||||
@@ -3356,15 +3357,15 @@ tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10"
|
||||
|
||||
[[package]]
|
||||
name = "langchain-core"
|
||||
version = "0.3.40"
|
||||
version = "0.3.34"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["docs", "test"]
|
||||
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
|
||||
files = [
|
||||
{file = "langchain_core-0.3.40-py3-none-any.whl", hash = "sha256:9f31358741f10a13db8531e8288b8a5ae91904018c5c2e6f739d6645a98fca03"},
|
||||
{file = "langchain_core-0.3.40.tar.gz", hash = "sha256:893a238b38491967c804662c1ec7c3e6ebaf223d1125331249c3cf3862ff2746"},
|
||||
{file = "langchain_core-0.3.34-py3-none-any.whl", hash = "sha256:a057ebeddd2158d3be14bde341b25640ddf958b6989bd6e47160396f5a8202ae"},
|
||||
{file = "langchain_core-0.3.34.tar.gz", hash = "sha256:26504cf1e8e6c310adad907b890d4e3c147581cfa7434114f6dc1134fe4bc6d3"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -3473,19 +3474,19 @@ ollama = ">=0.4.4,<1"
|
||||
|
||||
[[package]]
|
||||
name = "langchain-openai"
|
||||
version = "0.3.7"
|
||||
version = "0.3.4"
|
||||
description = "An integration package connecting OpenAI and LangChain"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["test"]
|
||||
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
|
||||
files = [
|
||||
{file = "langchain_openai-0.3.7-py3-none-any.whl", hash = "sha256:0aefc7bdf8e7398d41e09c4313cace816df6438f2aa93d34f79523487310f0da"},
|
||||
{file = "langchain_openai-0.3.7.tar.gz", hash = "sha256:b8b51a3aaa1cc3bda060651ea41145f7728219e8a7150b5404fb1e8446de9cef"},
|
||||
{file = "langchain_openai-0.3.4-py3-none-any.whl", hash = "sha256:58d0c014620eb92f4f46ff9daf584c2a7794896b1379eb85ad7be8d9f3493b61"},
|
||||
{file = "langchain_openai-0.3.4.tar.gz", hash = "sha256:c6645745a1d1bf19f21ea6fa473a746bd464053ff57ce563215e6165a0c4b9f1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
langchain-core = ">=0.3.39,<1.0.0"
|
||||
langchain-core = ">=0.3.34,<1.0.0"
|
||||
openai = ">=1.58.1,<2.0.0"
|
||||
tiktoken = ">=0.7,<1"
|
||||
|
||||
@@ -3507,7 +3508,7 @@ langchain-core = ">=0.3.34,<1.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "langgraph"
|
||||
version = "0.2.74"
|
||||
version = "0.2.71"
|
||||
description = "Building stateful, multi-actor applications with LLMs"
|
||||
optional = false
|
||||
python-versions = ">=3.9.0,<4.0"
|
||||
@@ -3527,7 +3528,7 @@ url = "../libs/langgraph"
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint"
|
||||
version = "2.0.16"
|
||||
version = "2.0.13"
|
||||
description = "Library with base interfaces for LangGraph checkpoint savers."
|
||||
optional = false
|
||||
python-versions = "^3.9.0,<4.0"
|
||||
@@ -3565,7 +3566,7 @@ pymongo = ">=4.9.0,<4.10.0"
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint-postgres"
|
||||
version = "2.0.15"
|
||||
version = "2.0.14"
|
||||
description = "Library with a Postgres implementation of LangGraph checkpoint saver."
|
||||
optional = false
|
||||
python-versions = "^3.9.0,<4.0"
|
||||
@@ -3575,7 +3576,7 @@ files = []
|
||||
develop = true
|
||||
|
||||
[package.dependencies]
|
||||
langgraph-checkpoint = "^2.0.15"
|
||||
langgraph-checkpoint = "^2.0.10"
|
||||
orjson = ">=3.10.1"
|
||||
psycopg = "^3.2.0"
|
||||
psycopg-pool = "^3.2.0"
|
||||
@@ -3586,7 +3587,7 @@ url = "../libs/checkpoint-postgres"
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint-sqlite"
|
||||
version = "2.0.5"
|
||||
version = "2.0.4"
|
||||
description = "Library with a SQLite implementation of LangGraph checkpoint saver."
|
||||
optional = false
|
||||
python-versions = "^3.9.0"
|
||||
@@ -3596,8 +3597,8 @@ files = []
|
||||
develop = true
|
||||
|
||||
[package.dependencies]
|
||||
aiosqlite = ">=0.20,<0.22"
|
||||
langgraph-checkpoint = "^2.0.15"
|
||||
aiosqlite = "^0.20.0"
|
||||
langgraph-checkpoint = "^2.0.10"
|
||||
|
||||
[package.source]
|
||||
type = "directory"
|
||||
@@ -3605,7 +3606,7 @@ url = "../libs/checkpoint-sqlite"
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-sdk"
|
||||
version = "0.1.53"
|
||||
version = "0.1.51"
|
||||
description = "SDK for interacting with LangGraph API"
|
||||
optional = false
|
||||
python-versions = "^3.9.0,<4.0"
|
||||
@@ -5938,6 +5939,7 @@ python-versions = ">=3.8"
|
||||
groups = ["test"]
|
||||
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
|
||||
files = [
|
||||
{file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"},
|
||||
{file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"},
|
||||
]
|
||||
|
||||
@@ -5950,6 +5952,7 @@ python-versions = ">=3.8"
|
||||
groups = ["test"]
|
||||
markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
|
||||
files = [
|
||||
{file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"},
|
||||
{file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"},
|
||||
]
|
||||
|
||||
@@ -8631,4 +8634,4 @@ type = ["pytest-mypy"]
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "6dce741bb0e3d73af45d234fb1605d97f1bbf23c2e71e0a456cc6987d67554e7"
|
||||
content-hash = "06debb82135affdb2baf1fdcc028c062c236121508d787588cd0de1db2da11e4"
|
||||
|
||||
+2
-2
@@ -40,8 +40,8 @@ langchain-cohere = "^0.4.2"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
langchain = "^0.3.8"
|
||||
langchain-openai = "^0.3.7"
|
||||
langchain-anthropic = "^0.3.8"
|
||||
langchain-openai = "^0.3.0"
|
||||
langchain-anthropic = "^0.2.1"
|
||||
langchain-nomic = "^0.1.3"
|
||||
langchain-fireworks = "^0.2.0"
|
||||
langchain-community = "^0.3.0"
|
||||
|
||||
Generated
+8
-8
@@ -1,23 +1,23 @@
|
||||
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiosqlite"
|
||||
version = "0.21.0"
|
||||
version = "0.20.0"
|
||||
description = "asyncio bridge to the standard sqlite3 module"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "aiosqlite-0.21.0-py3-none-any.whl", hash = "sha256:2549cf4057f95f53dcba16f2b64e8e2791d7e1adedb13197dd8ed77bb226d7d0"},
|
||||
{file = "aiosqlite-0.21.0.tar.gz", hash = "sha256:131bb8056daa3bc875608c631c678cda73922a2d4ba8aec373b19f18c17e7aa3"},
|
||||
{file = "aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6"},
|
||||
{file = "aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing_extensions = ">=4.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["attribution (==1.7.1)", "black (==24.3.0)", "build (>=1.2)", "coverage[toml] (==7.6.10)", "flake8 (==7.0.0)", "flake8-bugbear (==24.12.12)", "flit (==3.10.1)", "mypy (==1.14.1)", "ufmt (==2.5.1)", "usort (==1.0.8.post1)"]
|
||||
docs = ["sphinx (==8.1.3)", "sphinx-mdinclude (==0.6.1)"]
|
||||
dev = ["attribution (==1.7.0)", "black (==24.2.0)", "coverage[toml] (==7.4.1)", "flake8 (==7.0.0)", "flake8-bugbear (==24.2.6)", "flit (==3.9.0)", "mypy (==1.8.0)", "ufmt (==2.3.0)", "usort (==1.0.8.post1)"]
|
||||
docs = ["sphinx (==7.2.6)", "sphinx-mdinclude (==0.5.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
@@ -1043,4 +1043,4 @@ watchmedo = ["PyYAML (>=3.10)"]
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "^3.9.0"
|
||||
content-hash = "21896b8d3d283d95bc3988aa93f06faf5c47dadc2a8822e5a35672b9cb054693"
|
||||
content-hash = "e6d3ca9bce723c05f4c5ae9dc4bee872f7581b7763680b34112f1d280f5a9b0a"
|
||||
|
||||
@@ -11,7 +11,7 @@ packages = [{ include = "langgraph" }]
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9.0"
|
||||
langgraph-checkpoint = "^2.0.15"
|
||||
aiosqlite = ">=0.20,<0.22"
|
||||
aiosqlite = "^0.20.0"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
ruff = "^0.6.2"
|
||||
|
||||
@@ -127,16 +127,6 @@ class StreamMessagesHandler(BaseCallbackHandler, _StreamingCallbackHandler):
|
||||
tuple(cast(str, metadata["langgraph_checkpoint_ns"]).split(NS_SEP)),
|
||||
metadata,
|
||||
)
|
||||
if isinstance(inputs, dict):
|
||||
for key, value in inputs.items():
|
||||
if isinstance(value, BaseMessage):
|
||||
if value.id is not None:
|
||||
self.seen.add(value.id)
|
||||
elif isinstance(value, Sequence) and not isinstance(value, str):
|
||||
for item in value:
|
||||
if isinstance(item, BaseMessage):
|
||||
if item.id is not None:
|
||||
self.seen.add(item.id)
|
||||
|
||||
def on_chain_end(
|
||||
self,
|
||||
|
||||
@@ -32,17 +32,11 @@ def validate_graph(
|
||||
|
||||
for chan in subscribed_channels:
|
||||
if chan not in channels:
|
||||
raise ValueError(
|
||||
f"Subscribed channel '{chan}' not "
|
||||
f"in known channels: '{repr(sorted(channels))[:100]}'"
|
||||
)
|
||||
raise ValueError(f"Subscribed channel '{chan}' not in 'channels'")
|
||||
|
||||
if isinstance(input_channels, str):
|
||||
if input_channels not in channels:
|
||||
raise ValueError(
|
||||
f"Input channel '{input_channels}' not "
|
||||
f"in known channels: '{repr(sorted(channels))[:100]}'"
|
||||
)
|
||||
raise ValueError(f"Input channel '{input_channels}' not in 'channels'")
|
||||
if input_channels not in subscribed_channels:
|
||||
raise ValueError(
|
||||
f"Input channel {input_channels} is not subscribed to by any node"
|
||||
@@ -50,13 +44,10 @@ def validate_graph(
|
||||
else:
|
||||
for chan in input_channels:
|
||||
if chan not in channels:
|
||||
raise ValueError(
|
||||
f"Input channel '{chan}' not in '{repr(sorted(channels))[:100]}'"
|
||||
)
|
||||
raise ValueError(f"Input channel '{chan}' not in 'channels'")
|
||||
if all(chan not in subscribed_channels for chan in input_channels):
|
||||
raise ValueError(
|
||||
f"None of the input channels {input_channels} "
|
||||
f"are subscribed to by any node"
|
||||
f"None of the input channels {input_channels} are subscribed to by any node"
|
||||
)
|
||||
|
||||
all_output_channels = set[str]()
|
||||
@@ -71,10 +62,7 @@ def validate_graph(
|
||||
|
||||
for chan in all_output_channels:
|
||||
if chan not in channels:
|
||||
raise ValueError(
|
||||
f"Output channel '{chan}' not "
|
||||
f"in known channels: '{repr(sorted(channels))[:100]}'"
|
||||
)
|
||||
raise ValueError(f"Output channel '{chan}' not in 'channels'")
|
||||
|
||||
if interrupt_after_nodes != "*":
|
||||
for n in interrupt_after_nodes:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "langgraph"
|
||||
version = "0.2.75"
|
||||
version = "0.2.74"
|
||||
description = "Building stateful, multi-actor applications with LLMs"
|
||||
authors = []
|
||||
license = "MIT"
|
||||
|
||||
@@ -6588,101 +6588,3 @@ def test_get_stream_writer() -> None:
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def test_stream_messages_dedupe_inputs() -> None:
|
||||
from langchain_core.messages import AIMessage
|
||||
|
||||
def call_model(state):
|
||||
return {"messages": AIMessage("hi", id="1")}
|
||||
|
||||
def route(state):
|
||||
return Command(goto="node_2", graph=Command.PARENT)
|
||||
|
||||
subgraph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node(call_model)
|
||||
.add_node(route)
|
||||
.add_edge(START, "call_model")
|
||||
.add_edge("call_model", "route")
|
||||
.compile()
|
||||
)
|
||||
|
||||
graph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node("node_1", subgraph)
|
||||
.add_node("node_2", lambda state: state)
|
||||
.add_edge(START, "node_1")
|
||||
.compile()
|
||||
)
|
||||
|
||||
chunks = [
|
||||
chunk
|
||||
for ns, chunk in graph.stream(
|
||||
{"messages": "hi"}, stream_mode="messages", subgraphs=True
|
||||
)
|
||||
]
|
||||
|
||||
assert len(chunks) == 1
|
||||
assert chunks[0][0] == AIMessage("hi", id="1")
|
||||
assert chunks[0][1]["langgraph_node"] == "call_model"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_SYNC)
|
||||
def test_stream_messages_dedupe_state(
|
||||
request: pytest.FixtureRequest, checkpointer_name: str
|
||||
) -> None:
|
||||
from langchain_core.messages import AIMessage
|
||||
|
||||
checkpointer = request.getfixturevalue(f"checkpointer_{checkpointer_name}")
|
||||
to_emit = [AIMessage("bye", id="1"), AIMessage("bye again", id="2")]
|
||||
|
||||
def call_model(state):
|
||||
return {"messages": to_emit.pop(0)}
|
||||
|
||||
def route(state):
|
||||
return Command(goto="node_2", graph=Command.PARENT)
|
||||
|
||||
subgraph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node(call_model)
|
||||
.add_node(route)
|
||||
.add_edge(START, "call_model")
|
||||
.add_edge("call_model", "route")
|
||||
.compile()
|
||||
)
|
||||
|
||||
graph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node("node_1", subgraph)
|
||||
.add_node("node_2", lambda state: state)
|
||||
.add_edge(START, "node_1")
|
||||
.compile(checkpointer=checkpointer)
|
||||
)
|
||||
|
||||
thread1 = {"configurable": {"thread_id": "1"}}
|
||||
|
||||
chunks = [
|
||||
chunk
|
||||
for ns, chunk in graph.stream(
|
||||
{"messages": "hi"}, thread1, stream_mode="messages", subgraphs=True
|
||||
)
|
||||
]
|
||||
|
||||
assert len(chunks) == 1
|
||||
assert chunks[0][0] == AIMessage("bye", id="1")
|
||||
assert chunks[0][1]["langgraph_node"] == "call_model"
|
||||
|
||||
chunks = [
|
||||
chunk
|
||||
for ns, chunk in graph.stream(
|
||||
{"messages": "hi again"},
|
||||
thread1,
|
||||
stream_mode="messages",
|
||||
subgraphs=True,
|
||||
)
|
||||
]
|
||||
|
||||
assert len(chunks) == 1
|
||||
assert chunks[0][0] == AIMessage("bye again", id="2")
|
||||
assert chunks[0][1]["langgraph_node"] == "call_model"
|
||||
|
||||
@@ -7282,7 +7282,9 @@ async def test_multiple_subgraphs_mixed_state_graph(
|
||||
|
||||
@NEEDS_CONTEXTVARS
|
||||
@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC)
|
||||
async def test_multiple_subgraphs_checkpointer(checkpointer_name: str) -> None:
|
||||
async def test_multiple_subgraphs_checkpointer(
|
||||
request: pytest.FixtureRequest, checkpointer_name: str
|
||||
) -> None:
|
||||
async with awith_checkpointer(checkpointer_name) as checkpointer:
|
||||
|
||||
class SubgraphState(TypedDict):
|
||||
@@ -7511,99 +7513,3 @@ async def test_tags_stream_mode_messages() -> None:
|
||||
},
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
async def test_stream_messages_dedupe_inputs() -> None:
|
||||
from langchain_core.messages import AIMessage
|
||||
|
||||
async def call_model(state):
|
||||
return {"messages": AIMessage("hi", id="1")}
|
||||
|
||||
async def route(state):
|
||||
return Command(goto="node_2", graph=Command.PARENT)
|
||||
|
||||
subgraph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node(call_model)
|
||||
.add_node(route)
|
||||
.add_edge(START, "call_model")
|
||||
.add_edge("call_model", "route")
|
||||
.compile()
|
||||
)
|
||||
|
||||
graph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node("node_1", subgraph)
|
||||
.add_node("node_2", lambda state: state)
|
||||
.add_edge(START, "node_1")
|
||||
.compile()
|
||||
)
|
||||
|
||||
chunks = [
|
||||
chunk
|
||||
async for ns, chunk in graph.astream(
|
||||
{"messages": "hi"}, stream_mode="messages", subgraphs=True
|
||||
)
|
||||
]
|
||||
|
||||
assert len(chunks) == 1
|
||||
assert chunks[0][0] == AIMessage("hi", id="1")
|
||||
assert chunks[0][1]["langgraph_node"] == "call_model"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("checkpointer_name", ALL_CHECKPOINTERS_ASYNC)
|
||||
async def test_stream_messages_dedupe_state(checkpointer_name: str) -> None:
|
||||
async with awith_checkpointer(checkpointer_name) as checkpointer:
|
||||
from langchain_core.messages import AIMessage
|
||||
|
||||
to_emit = [AIMessage("bye", id="1"), AIMessage("bye again", id="2")]
|
||||
|
||||
async def call_model(state):
|
||||
return {"messages": to_emit.pop(0)}
|
||||
|
||||
async def route(state):
|
||||
return Command(goto="node_2", graph=Command.PARENT)
|
||||
|
||||
subgraph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node(call_model)
|
||||
.add_node(route)
|
||||
.add_edge(START, "call_model")
|
||||
.add_edge("call_model", "route")
|
||||
.compile()
|
||||
)
|
||||
|
||||
graph = (
|
||||
StateGraph(MessagesState)
|
||||
.add_node("node_1", subgraph)
|
||||
.add_node("node_2", lambda state: state)
|
||||
.add_edge(START, "node_1")
|
||||
.compile(checkpointer=checkpointer)
|
||||
)
|
||||
|
||||
thread1 = {"configurable": {"thread_id": "1"}}
|
||||
|
||||
chunks = [
|
||||
chunk
|
||||
async for ns, chunk in graph.astream(
|
||||
{"messages": "hi"}, thread1, stream_mode="messages", subgraphs=True
|
||||
)
|
||||
]
|
||||
|
||||
assert len(chunks) == 1
|
||||
assert chunks[0][0] == AIMessage("bye", id="1")
|
||||
assert chunks[0][1]["langgraph_node"] == "call_model"
|
||||
|
||||
chunks = [
|
||||
chunk
|
||||
async for ns, chunk in graph.astream(
|
||||
{"messages": "hi again"},
|
||||
thread1,
|
||||
stream_mode="messages",
|
||||
subgraphs=True,
|
||||
)
|
||||
]
|
||||
|
||||
assert len(chunks) == 1
|
||||
assert chunks[0][0] == AIMessage("bye again", id="2")
|
||||
assert chunks[0][1]["langgraph_node"] == "call_model"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@langchain/langgraph-sdk",
|
||||
"version": "0.0.45",
|
||||
"version": "0.0.46",
|
||||
"description": "Client library for interacting with the LangGraph API",
|
||||
"type": "module",
|
||||
"packageManager": "yarn@1.22.19",
|
||||
|
||||
Reference in New Issue
Block a user