mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-22 23:52:23 +02:00
Merge pull request #123 from langchain-ai/nc/19feb/get-graph
Implement get_input_schema(), get_output_schema(), get_graph() for StateGraph, MessageGraph
This commit is contained in:
@@ -9,6 +9,8 @@ from langchain_core.runnables.base import (
|
||||
RunnableLike,
|
||||
coerce_to_runnable,
|
||||
)
|
||||
from langchain_core.runnables.config import RunnableConfig
|
||||
from langchain_core.runnables.graph import Graph as RunnableGraph
|
||||
|
||||
from langgraph.checkpoint import BaseCheckpointSaver
|
||||
from langgraph.pregel import Channel, Pregel
|
||||
@@ -150,7 +152,7 @@ class Graph:
|
||||
checkpointer: Optional[BaseCheckpointSaver] = None,
|
||||
interrupt_before: Optional[Sequence[str]] = None,
|
||||
interrupt_after: Optional[Sequence[str]] = None,
|
||||
) -> Pregel:
|
||||
) -> "CompiledGraph":
|
||||
interrupt_before = interrupt_before or []
|
||||
interrupt_after = interrupt_after or []
|
||||
self.validate(interrupt=interrupt_before + interrupt_after)
|
||||
@@ -177,7 +179,8 @@ class Graph:
|
||||
branch.runnable, name=f"{key}_condition"
|
||||
)
|
||||
|
||||
return Pregel(
|
||||
return CompiledGraph(
|
||||
graph=self,
|
||||
nodes=nodes,
|
||||
input=f"{self.entry_point}:inbox",
|
||||
output=END,
|
||||
@@ -188,3 +191,32 @@ class Graph:
|
||||
+ [node for node in interrupt_after]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class CompiledGraph(Pregel):
|
||||
graph: Graph
|
||||
|
||||
def get_graph(self, config: Optional[RunnableConfig] = None) -> RunnableGraph:
|
||||
graph = RunnableGraph()
|
||||
graph.add_node(self.get_input_schema(config), "__start__")
|
||||
graph.add_node(self.get_output_schema(config), END)
|
||||
|
||||
for key, node in self.graph.nodes.items():
|
||||
graph.add_node(node, key)
|
||||
for start, end in self.graph.edges:
|
||||
graph.add_edge(graph.nodes[start], graph.nodes[end])
|
||||
for start, branches in self.graph.branches.items():
|
||||
for i, branch in enumerate(branches):
|
||||
name = f"{start}_{branch.condition.__name__}"
|
||||
if i > 0:
|
||||
name += f"_{i}"
|
||||
graph.add_node(
|
||||
RunnableLambda(branch.runnable, name=branch.condition.__name__),
|
||||
name,
|
||||
)
|
||||
graph.add_edge(graph.nodes[start], graph.nodes[name])
|
||||
for label, end in branch.ends.items():
|
||||
graph.add_edge(graph.nodes[name], graph.nodes[end], label)
|
||||
graph.add_edge(graph.nodes["__start__"], graph.nodes[self.graph.entry_point])
|
||||
|
||||
return graph
|
||||
|
||||
@@ -12,8 +12,8 @@ from langgraph.channels.binop import BinaryOperatorAggregate
|
||||
from langgraph.channels.ephemeral_value import EphemeralValue
|
||||
from langgraph.channels.last_value import LastValue
|
||||
from langgraph.checkpoint import BaseCheckpointSaver
|
||||
from langgraph.graph.graph import END, Graph
|
||||
from langgraph.pregel import Channel, Pregel
|
||||
from langgraph.graph.graph import END, CompiledGraph, Graph
|
||||
from langgraph.pregel import Channel
|
||||
from langgraph.pregel.read import ChannelRead
|
||||
from langgraph.pregel.write import SKIP_WRITE, ChannelWrite
|
||||
|
||||
@@ -41,7 +41,7 @@ class StateGraph(Graph):
|
||||
checkpointer: Optional[BaseCheckpointSaver] = None,
|
||||
interrupt_before: Optional[Sequence[str]] = None,
|
||||
interrupt_after: Optional[Sequence[str]] = None,
|
||||
) -> Pregel:
|
||||
) -> CompiledGraph:
|
||||
interrupt_before = interrupt_before or []
|
||||
interrupt_after = interrupt_after or []
|
||||
self.validate(interrupt=interrupt_before + interrupt_after)
|
||||
@@ -78,13 +78,13 @@ class StateGraph(Graph):
|
||||
node_inboxes = {
|
||||
# we take any value written to channel because all writers
|
||||
# write the entire state as of that step, which is equal for all
|
||||
f"{key}:inbox": AnyValue(Any)
|
||||
for key in self.nodes
|
||||
f"{key}:inbox": AnyValue(self.schema)
|
||||
for key in list(self.nodes) + [START]
|
||||
}
|
||||
node_outboxes = {
|
||||
# we clear outbox channels after each step
|
||||
key: EphemeralValue(Any)
|
||||
for key in self.nodes
|
||||
for key in list(self.nodes) + [START]
|
||||
}
|
||||
|
||||
for key in self.nodes:
|
||||
@@ -111,9 +111,15 @@ class StateGraph(Graph):
|
||||
| Channel.write_to(f"{self.entry_point}:inbox")
|
||||
)
|
||||
|
||||
return Pregel(
|
||||
return CompiledGraph(
|
||||
graph=self,
|
||||
nodes=nodes,
|
||||
channels={**self.channels, **node_inboxes, **node_outboxes},
|
||||
channels={
|
||||
**self.channels,
|
||||
**node_inboxes,
|
||||
**node_outboxes,
|
||||
END: LastValue(self.schema),
|
||||
},
|
||||
input=f"{START}:inbox",
|
||||
output=END,
|
||||
hidden=[f"{node}:inbox" for node in self.nodes] + [START] + state_keys,
|
||||
|
||||
Generated
+52
-21
@@ -843,6 +843,23 @@ files = [
|
||||
{file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grandalf"
|
||||
version = "0.8"
|
||||
description = "Graph and drawing algorithms framework"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "grandalf-0.8-py3-none-any.whl", hash = "sha256:793ca254442f4a79252ea9ff1ab998e852c1e071b863593e5383afee906b4185"},
|
||||
{file = "grandalf-0.8.tar.gz", hash = "sha256:2813f7aab87f0d20f334a3162ccfbcbf085977134a17a5b516940a93a77ea974"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pyparsing = "*"
|
||||
|
||||
[package.extras]
|
||||
full = ["numpy", "ply"]
|
||||
|
||||
[[package]]
|
||||
name = "greenlet"
|
||||
version = "3.0.3"
|
||||
@@ -1498,13 +1515,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "langchain"
|
||||
version = "0.1.4"
|
||||
version = "0.1.8"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain-0.1.4-py3-none-any.whl", hash = "sha256:6befdd6221f5f326092e31a3c19efdc7ce3d7d1f2e2cab065141071451730ed7"},
|
||||
{file = "langchain-0.1.4.tar.gz", hash = "sha256:8767a9461e2b717ce9a35b1fa20659de89ea86ba9c2a4ff516e05d47ab2d195d"},
|
||||
{file = "langchain-0.1.8-py3-none-any.whl", hash = "sha256:19e951b0e2be099ff048ee483acecb47e1a39c33a47dadfee70fcfa20f45cc19"},
|
||||
{file = "langchain-0.1.8.tar.gz", hash = "sha256:c8b1c2954a07cd6422c9027459473bafae90c78f07015bf2fc6262fadf97ea44"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1512,9 +1529,9 @@ aiohttp = ">=3.8.3,<4.0.0"
|
||||
async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""}
|
||||
dataclasses-json = ">=0.5.7,<0.7"
|
||||
jsonpatch = ">=1.33,<2.0"
|
||||
langchain-community = ">=0.0.14,<0.1"
|
||||
langchain-core = ">=0.1.16,<0.2"
|
||||
langsmith = ">=0.0.83,<0.1"
|
||||
langchain-community = ">=0.0.21,<0.1"
|
||||
langchain-core = ">=0.1.24,<0.2"
|
||||
langsmith = ">=0.1.0,<0.2.0"
|
||||
numpy = ">=1,<2"
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
@@ -1529,7 +1546,7 @@ cli = ["typer (>=0.9.0,<0.10.0)"]
|
||||
cohere = ["cohere (>=4,<5)"]
|
||||
docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"]
|
||||
embeddings = ["sentence-transformers (>=2,<3)"]
|
||||
extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"]
|
||||
extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"]
|
||||
javascript = ["esprima (>=4.0.1,<5.0.0)"]
|
||||
llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"]
|
||||
openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"]
|
||||
@@ -1538,20 +1555,20 @@ text-helpers = ["chardet (>=5.1.0,<6.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "langchain-community"
|
||||
version = "0.0.16"
|
||||
version = "0.0.21"
|
||||
description = "Community contributed LangChain integrations."
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain_community-0.0.16-py3-none-any.whl", hash = "sha256:0f1dfc1a6205ce8d39931d3515974a208a9f69c16157c649f83490a7cc830b73"},
|
||||
{file = "langchain_community-0.0.16.tar.gz", hash = "sha256:c06512a93013a06fba7679cd5a1254ff8b927cddd2d1fbe0cc444bf7bbdf0b8c"},
|
||||
{file = "langchain_community-0.0.21-py3-none-any.whl", hash = "sha256:120977485d244eb472ad3618a31222fe6c2bce08026f4caa96bd6dae2e316ac0"},
|
||||
{file = "langchain_community-0.0.21.tar.gz", hash = "sha256:1c310a7e2663d5f6464a433981504894f97c12783cbeb8bdf4159a574f88c18d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
aiohttp = ">=3.8.3,<4.0.0"
|
||||
dataclasses-json = ">=0.5.7,<0.7"
|
||||
langchain-core = ">=0.1.16,<0.2"
|
||||
langsmith = ">=0.0.83,<0.1"
|
||||
langchain-core = ">=0.1.24,<0.2"
|
||||
langsmith = ">=0.1.0,<0.2.0"
|
||||
numpy = ">=1,<2"
|
||||
PyYAML = ">=5.3"
|
||||
requests = ">=2,<3"
|
||||
@@ -1560,23 +1577,23 @@ tenacity = ">=8.1.0,<9.0.0"
|
||||
|
||||
[package.extras]
|
||||
cli = ["typer (>=0.9.0,<0.10.0)"]
|
||||
extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"]
|
||||
extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "langchain-core"
|
||||
version = "0.1.17"
|
||||
version = "0.1.25"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain_core-0.1.17-py3-none-any.whl", hash = "sha256:026155cf97867bde410ab1834799ab4c5ba64c39380f2a4328bcf9c78623ca64"},
|
||||
{file = "langchain_core-0.1.17.tar.gz", hash = "sha256:59016e457cd6a1708d83a3a454acc97cf02c2a2c3af95626d13f83894fd4e777"},
|
||||
{file = "langchain_core-0.1.25-py3-none-any.whl", hash = "sha256:ff0a0ad1ed877878e7b9c7601870cd12145abf3c814aae41995968d05ea6c09d"},
|
||||
{file = "langchain_core-0.1.25.tar.gz", hash = "sha256:065ff8b4e383c5645d175b20ae44b258330ed06457b0fc0179efee310b6f2af6"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anyio = ">=3,<5"
|
||||
jsonpatch = ">=1.33,<2.0"
|
||||
langsmith = ">=0.0.83,<0.1"
|
||||
langsmith = ">=0.1.0,<0.2.0"
|
||||
packaging = ">=23.2,<24.0"
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
@@ -1620,13 +1637,13 @@ types-requests = ">=2.31.0.2,<3.0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
version = "0.0.85"
|
||||
version = "0.1.4"
|
||||
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langsmith-0.0.85-py3-none-any.whl", hash = "sha256:9d0ccbcda7b69c83828060603a51bb4319e43b8dc807fbd90b6355f8ec709500"},
|
||||
{file = "langsmith-0.0.85.tar.gz", hash = "sha256:fefc631fc30d836b54d4e3f99961c41aea497633898b8f09e305b6c7216c2c54"},
|
||||
{file = "langsmith-0.1.4-py3-none-any.whl", hash = "sha256:13ea90c030a3ef472e00f4dd31b9c89f165f98f0c870309eca3366c93fcaa29f"},
|
||||
{file = "langsmith-0.1.4.tar.gz", hash = "sha256:b45ea1001f67c4c233b3521eb578326863e32e0eb738e52900c035261deec368"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2397,6 +2414,20 @@ files = [
|
||||
plugins = ["importlib-metadata"]
|
||||
windows-terminal = ["colorama (>=0.4.6)"]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.1.1"
|
||||
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
|
||||
optional = false
|
||||
python-versions = ">=3.6.8"
|
||||
files = [
|
||||
{file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"},
|
||||
{file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
diagrams = ["jinja2", "railroad-diagrams"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.4.4"
|
||||
@@ -3729,4 +3760,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.9.0,<4.0"
|
||||
content-hash = "f489f2e9159e8db255a43027617c41a389afb5fe84ff94bf8521c0f98de8cd38"
|
||||
content-hash = "0e7777d77d3b34acbfdead224a2b5c5e65ecbf890c57c29bf43f5ebff09d4c0d"
|
||||
|
||||
+2
-1
@@ -9,7 +9,7 @@ repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9.0,<4.0"
|
||||
langchain-core = "^0.1.16"
|
||||
langchain-core = "^0.1.25"
|
||||
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
@@ -26,6 +26,7 @@ httpx = "^0.26.0"
|
||||
pytest-watcher = "^0.3.4"
|
||||
langchain = "^0.1.0"
|
||||
aiosqlite = "^0.19.0"
|
||||
grandalf = "^0.8"
|
||||
|
||||
[tool.poetry.group.lint.dependencies]
|
||||
ruff = "^0.1.4"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+30
-6
@@ -9,6 +9,7 @@ from typing import Annotated, Generator, Optional, TypedDict, Union
|
||||
import pytest
|
||||
from langchain_core.runnables import RunnablePassthrough
|
||||
from pytest_mock import MockerFixture
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from langgraph.channels.base import InvalidUpdateError
|
||||
from langgraph.channels.binop import BinaryOperatorAggregate
|
||||
@@ -659,7 +660,7 @@ def test_channel_enter_exit_timing(mocker: MockerFixture) -> None:
|
||||
assert cleanup.call_count == 1, "Expected cleanup to be called once"
|
||||
|
||||
|
||||
def test_conditional_graph() -> None:
|
||||
def test_conditional_graph(snapshot: SnapshotAssertion) -> None:
|
||||
from copy import deepcopy
|
||||
|
||||
from langchain.llms.fake import FakeStreamingListLLM
|
||||
@@ -732,6 +733,9 @@ def test_conditional_graph() -> None:
|
||||
|
||||
app = workflow.compile()
|
||||
|
||||
assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot
|
||||
assert app.get_graph().draw_ascii() == snapshot
|
||||
|
||||
assert app.invoke({"input": "what is weather in sf"}) == {
|
||||
"input": "what is weather in sf",
|
||||
"intermediate_steps": [
|
||||
@@ -879,13 +883,13 @@ def test_conditional_graph() -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_conditional_graph_state() -> None:
|
||||
def test_conditional_graph_state(snapshot: SnapshotAssertion) -> None:
|
||||
from langchain.llms.fake import FakeStreamingListLLM
|
||||
from langchain_community.tools import tool
|
||||
from langchain_core.agents import AgentAction, AgentFinish
|
||||
from langchain_core.prompts import PromptTemplate
|
||||
|
||||
class AgentState(TypedDict):
|
||||
class AgentState(TypedDict, total=False):
|
||||
input: str
|
||||
agent_outcome: Optional[Union[AgentAction, AgentFinish]]
|
||||
intermediate_steps: Annotated[list[tuple[AgentAction, str]], operator.add]
|
||||
@@ -959,6 +963,11 @@ def test_conditional_graph_state() -> None:
|
||||
|
||||
app = workflow.compile()
|
||||
|
||||
assert app.get_input_schema().schema_json() == snapshot
|
||||
assert app.get_output_schema().schema_json() == snapshot
|
||||
assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot
|
||||
assert app.get_graph().draw_ascii() == snapshot
|
||||
|
||||
assert app.invoke({"input": "what is weather in sf"}) == {
|
||||
"input": "what is weather in sf",
|
||||
"intermediate_steps": [
|
||||
@@ -1065,7 +1074,7 @@ def test_conditional_graph_state() -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_prebuilt_tool_chat() -> None:
|
||||
def test_prebuilt_tool_chat(snapshot: SnapshotAssertion) -> None:
|
||||
from langchain.chat_models.fake import FakeMessagesListChatModel
|
||||
from langchain_community.tools import tool
|
||||
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
|
||||
@@ -1128,6 +1137,11 @@ def test_prebuilt_tool_chat() -> None:
|
||||
tools,
|
||||
)
|
||||
|
||||
assert app.get_input_schema().schema_json() == snapshot
|
||||
assert app.get_output_schema().schema_json() == snapshot
|
||||
assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot
|
||||
assert app.get_graph().draw_ascii() == snapshot
|
||||
|
||||
assert app.invoke(
|
||||
{"messages": [HumanMessage(content="what is weather in sf")]}
|
||||
) == {
|
||||
@@ -1309,7 +1323,7 @@ def test_prebuilt_tool_chat() -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_prebuilt_chat() -> None:
|
||||
def test_prebuilt_chat(snapshot: SnapshotAssertion) -> None:
|
||||
from langchain.chat_models.fake import FakeMessagesListChatModel
|
||||
from langchain_community.tools import tool
|
||||
from langchain_core.messages import AIMessage, FunctionMessage, HumanMessage
|
||||
@@ -1352,6 +1366,11 @@ def test_prebuilt_chat() -> None:
|
||||
tools,
|
||||
)
|
||||
|
||||
assert app.get_input_schema().schema_json() == snapshot
|
||||
assert app.get_output_schema().schema_json() == snapshot
|
||||
assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot
|
||||
assert app.get_graph().draw_ascii() == snapshot
|
||||
|
||||
assert app.invoke(
|
||||
{"messages": [HumanMessage(content="what is weather in sf")]}
|
||||
) == {
|
||||
@@ -1454,7 +1473,7 @@ def test_prebuilt_chat() -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_message_graph() -> None:
|
||||
def test_message_graph(snapshot: SnapshotAssertion) -> None:
|
||||
from langchain.chat_models.fake import FakeMessagesListChatModel
|
||||
from langchain_community.tools import tool
|
||||
from langchain_core.agents import AgentAction
|
||||
@@ -1565,6 +1584,11 @@ def test_message_graph() -> None:
|
||||
# meaning you can use it as you would any other runnable
|
||||
app = workflow.compile()
|
||||
|
||||
assert app.get_input_schema().schema_json() == snapshot
|
||||
assert app.get_output_schema().schema_json() == snapshot
|
||||
assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot
|
||||
assert app.get_graph().draw_ascii() == snapshot
|
||||
|
||||
assert app.invoke(HumanMessage(content="what is weather in sf")) == [
|
||||
HumanMessage(content="what is weather in sf"),
|
||||
AIMessage(
|
||||
|
||||
Reference in New Issue
Block a user