mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-07 18:27:52 +02:00
fmt
This commit is contained in:
@@ -109,14 +109,26 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 26,
|
||||
"id": "d7ef57dd-5d6e-4ad3-9377-a92201c1310e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain_community.tools.tavily_search import TavilySearchResults\n",
|
||||
"from langchain_core.tools import tool\n",
|
||||
"\n",
|
||||
"tools = [TavilySearchResults(max_results=1)]"
|
||||
"@tool\n",
|
||||
"def multiply(x: int, y: int) -> int:\n",
|
||||
" \"\"\"Multiply two ints\"\"\"\n",
|
||||
" return x * y\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def add(x: int, y: int) -> int:\n",
|
||||
" \"\"\"Add two ints\"\"\"\n",
|
||||
" return x + y\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"tools = [multiply, add]"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -131,7 +143,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 27,
|
||||
"id": "5cf3331e-ccb3-41c8-aeb9-a840a94d41e7",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -163,7 +175,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 28,
|
||||
"id": "892b54b9-75f0-4804-9ed0-88b5e5532989",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -187,7 +199,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 29,
|
||||
"id": "cd3cbae5-d92c-4559-a4aa-44721b80d107",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -218,7 +230,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 30,
|
||||
"id": "ea793afa-2eab-4901-910d-6eed90cd6564",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -265,7 +277,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 31,
|
||||
"id": "3b541bb9-900c-40d0-964d-7b5dfee30667",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -283,6 +295,8 @@
|
||||
" return \"end\"\n",
|
||||
" # Otherwise if there is, we continue\n",
|
||||
" else:\n",
|
||||
" if last_message.additional_kwargs[\"function_call\"][\"name\"] == \"add\":\n",
|
||||
" return \"add\"\n",
|
||||
" return \"continue\"\n",
|
||||
"\n",
|
||||
"# Define the function that calls the model\n",
|
||||
@@ -323,18 +337,21 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"execution_count": 32,
|
||||
"id": "813ae66c-3b58-4283-a02a-36da72a2ab90",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langgraph.graph import StateGraph, END\n",
|
||||
"from langgraph.checkpoint.memory import MemorySaver\n",
|
||||
"\n",
|
||||
"# Define a new graph\n",
|
||||
"workflow = StateGraph(AgentState)\n",
|
||||
"\n",
|
||||
"# Define the two nodes we will cycle between\n",
|
||||
"workflow.add_node(\"agent\", call_model)\n",
|
||||
"workflow.add_node(\"action\", call_tool)\n",
|
||||
"workflow.add_node(\"add\", call_tool)\n",
|
||||
"\n",
|
||||
"# Set the entrypoint as `agent`\n",
|
||||
"# This means that this node is the first one called\n",
|
||||
@@ -356,6 +373,7 @@
|
||||
" {\n",
|
||||
" # If `tools`, then we call the tool node.\n",
|
||||
" \"continue\": \"action\",\n",
|
||||
" \"add\": \"add\",\n",
|
||||
" # Otherwise we finish.\n",
|
||||
" \"end\": END\n",
|
||||
" }\n",
|
||||
@@ -364,11 +382,14 @@
|
||||
"# We now add a normal edge from `tools` to `agent`.\n",
|
||||
"# This means that after `tools` is called, `agent` node is called next.\n",
|
||||
"workflow.add_edge('action', 'agent')\n",
|
||||
"workflow.add_edge('add', END)\n",
|
||||
"\n",
|
||||
"# Finally, we compile it!\n",
|
||||
"# This compiles it into a LangChain Runnable,\n",
|
||||
"# meaning you can use it as you would any other runnable\n",
|
||||
"app = workflow.compile()"
|
||||
"app = workflow.compile()\n",
|
||||
"app.interrupt=[\"agent\"]\n",
|
||||
"app.checkpointer=MemorySaver()"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -385,90 +406,40 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"id": "cfd140f0-a5a6-4697-8115-322242f197b5",
|
||||
"execution_count": 34,
|
||||
"id": "81633bc1-b136-40e9-b8be-9961adb38183",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"content='' additional_kwargs={'function_call': {'arguments': '', 'name': 'tavily_search_results_json'}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': '{\\n', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': ' ', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': ' \"', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': 'query', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': '\":', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': ' \"', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': 'weather', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': ' in', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': ' San', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': ' Francisco', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': '\"\\n', 'name': ''}}\n",
|
||||
"content='' additional_kwargs={'function_call': {'arguments': '}', 'name': ''}}\n",
|
||||
"content=''\n",
|
||||
"content=''\n",
|
||||
"content='I'\n",
|
||||
"content=\"'m\"\n",
|
||||
"content=' sorry'\n",
|
||||
"content=','\n",
|
||||
"content=' but'\n",
|
||||
"content=' I'\n",
|
||||
"content=' couldn'\n",
|
||||
"content=\"'t\"\n",
|
||||
"content=' find'\n",
|
||||
"content=' the'\n",
|
||||
"content=' current'\n",
|
||||
"content=' weather'\n",
|
||||
"content=' in'\n",
|
||||
"content=' San'\n",
|
||||
"content=' Francisco'\n",
|
||||
"content='.'\n",
|
||||
"content=' However'\n",
|
||||
"content=','\n",
|
||||
"content=' you'\n",
|
||||
"content=' can'\n",
|
||||
"content=' check'\n",
|
||||
"content=' the'\n",
|
||||
"content=' weather'\n",
|
||||
"content=' forecast'\n",
|
||||
"content=' for'\n",
|
||||
"content=' San'\n",
|
||||
"content=' Francisco'\n",
|
||||
"content=' on'\n",
|
||||
"content=' websites'\n",
|
||||
"content=' like'\n",
|
||||
"content=' Weather'\n",
|
||||
"content='.com'\n",
|
||||
"content=' or'\n",
|
||||
"content=' Acc'\n",
|
||||
"content='u'\n",
|
||||
"content='Weather'\n",
|
||||
"content='.'\n",
|
||||
"content=''\n"
|
||||
]
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'messages': [AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\\n \"x\": 5,\\n \"y\": 4\\n}', 'name': 'multiply'}})]}"
|
||||
]
|
||||
},
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from langchain_core.messages import HumanMessage\n",
|
||||
"inputs = {\"messages\": [HumanMessage(content=\"what is the weather in sf\")]}\n",
|
||||
"async for output in app.astream_log(inputs, include_types=[\"llm\"]):\n",
|
||||
" # astream_log() yields the requested logs (here LLMs) in JSONPatch format\n",
|
||||
" for op in output.ops:\n",
|
||||
" if op[\"path\"] == \"/streamed_output/-\":\n",
|
||||
" # this is the output from .stream()\n",
|
||||
" ...\n",
|
||||
" elif op[\"path\"].startswith(\"/logs/\") and op[\"path\"].endswith(\n",
|
||||
" \"/streamed_output/-\"\n",
|
||||
" ):\n",
|
||||
" # because we chose to only include LLMs, these are LLM tokens\n",
|
||||
" print(op[\"value\"])"
|
||||
"inputs = {\"messages\": [HumanMessage(content=\"what is 5 times 4\")]}\n",
|
||||
"await app.ainvoke(inputs, output_keys=\"agent\", config={\"configurable\": {\"thread_id\": \"foo\"}})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"id": "08ae8246-11d5-40e1-8567-361e5bef8917",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await app.ainvoke({\"messages\": [HumanMessage(content=\"how about the sum of those two numbers\")]},config={\"configurable\": {\"thread_id\": \"foo\"}})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "08ae8246-11d5-40e1-8567-361e5bef8917",
|
||||
"id": "371cb452-2508-46c8-878f-2249a0dae93a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
@@ -476,9 +447,9 @@
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"display_name": "langgraph",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
"name": "langgraph"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
@@ -490,7 +461,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.1"
|
||||
"version": "3.11.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
+20
-13
@@ -90,23 +90,30 @@ class Graph:
|
||||
|
||||
def validate(self) -> None:
|
||||
all_starts = {src for src, _ in self.edges} | {src for src in self.branches}
|
||||
all_ends = (
|
||||
{end for _, end in self.edges}
|
||||
| {
|
||||
end
|
||||
for branch_list in self.branches.values()
|
||||
for branch in branch_list
|
||||
for end in branch.ends.values()
|
||||
}
|
||||
| {self.entry_point}
|
||||
)
|
||||
|
||||
for node in self.nodes:
|
||||
if node not in all_ends:
|
||||
raise ValueError(f"Node `{node}` is not reachable")
|
||||
if node not in all_starts:
|
||||
raise ValueError(f"Node `{node}` is a dead-end")
|
||||
|
||||
if all(
|
||||
branch.ends is not None
|
||||
for branch_list in self.branches.values()
|
||||
for branch in branch_list
|
||||
):
|
||||
all_ends = (
|
||||
{end for _, end in self.edges}
|
||||
| {
|
||||
end
|
||||
for branch_list in self.branches.values()
|
||||
for branch in branch_list
|
||||
for end in branch.ends.values()
|
||||
}
|
||||
| {self.entry_point}
|
||||
)
|
||||
|
||||
for node in self.nodes:
|
||||
if node not in all_ends:
|
||||
raise ValueError(f"Node `{node}` is not reachable")
|
||||
|
||||
def compile(self, checkpointer: Optional[BaseCheckpointSaver] = None) -> Pregel:
|
||||
self.validate()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user