Files
knightutils/test/langgraph/workflows-agents.ipynb
2025-10-25 21:14:41 +08:00

268 lines
28 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"id": "initial_id",
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2025-09-14T00:07:57.910209Z",
"start_time": "2025-09-14T00:07:56.596730Z"
}
},
"source": [
"import os\n",
"\n",
"os.environ['DASHSCOPE_API_KEY'] = 'sk-e2a05bbcfac84e53b73f98acef15a009'\n",
"\n",
"# Step 0: Define tools and model\n",
"\n",
"from langchain_core.tools import tool\n",
"from langchain_community.chat_models.tongyi import ChatTongyi\n",
"\n",
"llm = ChatTongyi(\n",
" model=\"qwen-max\", # 此处以qwen-max为例您可按需更换模型名称。模型列表https://help.aliyun.com/zh/model-studio/getting-started/models\n",
" streaming=True,\n",
" # other params...\n",
")"
],
"outputs": [],
"execution_count": 1
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-09-14T00:08:02.725584Z",
"start_time": "2025-09-14T00:07:59.739323Z"
}
},
"cell_type": "code",
"source": [
"# Schema for structured output\n",
"from pydantic import BaseModel, Field\n",
"\n",
"class SearchQuery(BaseModel):\n",
" search_query: str = Field(None, description=\"Query that is optimized web search.\")\n",
" justification: str = Field(\n",
" None, description=\"Why this query is relevant to the user's request.\"\n",
" )\n",
"\n",
"\n",
"# Augment the LLM with schema for structured output\n",
"structured_llm = llm.with_structured_output(SearchQuery)\n",
"\n",
"# Invoke the augmented LLM\n",
"output = structured_llm.invoke(\"How does Calcium CT score relate to high cholesterol?\")\n",
"\n",
"# Define a tool\n",
"def multiply(a: int, b: int) -> int:\n",
" return a * b\n",
"\n",
"# Augment the LLM with tools\n",
"llm_with_tools = llm.bind_tools([multiply])\n",
"\n",
"# Invoke the LLM with input that triggers the tool call\n",
"msg = llm_with_tools.invoke(\"What is 2 times 3?\")\n",
"\n",
"# Get the tool call\n",
"msg.tool_calls"
],
"id": "ffc3ae3a2187bb05",
"outputs": [
{
"data": {
"text/plain": [
"[{'name': 'multiply',\n",
" 'args': {'a': 2, 'b': 3},\n",
" 'id': 'call_a59e5004790d42dc827469',\n",
" 'type': 'tool_call'}]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 2
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-09-14T00:08:05.086490Z",
"start_time": "2025-09-14T00:08:04.747991Z"
}
},
"cell_type": "code",
"source": [
"# Graph API\n",
"from typing_extensions import TypedDict\n",
"from langgraph.graph import StateGraph, START, END\n",
"from IPython.display import Image, display\n",
"\n",
"\n",
"# Graph state\n",
"class State(TypedDict):\n",
" topic: str\n",
" joke: str\n",
" improved_joke: str\n",
" final_joke: str\n",
"\n",
"\n",
"# Nodes\n",
"def generate_joke(state: State):\n",
" \"\"\"First LLM call to generate initial joke\"\"\"\n",
"\n",
" msg = llm.invoke(f\"Write a short joke about {state['topic']}\")\n",
" return {\"joke\": msg.content}\n",
"\n",
"\n",
"def check_punchline(state: State):\n",
" \"\"\"Gate function to check if the joke has a punchline\"\"\"\n",
"\n",
" # Simple check - does the joke contain \"?\" or \"!\"\n",
" if \"?\" in state[\"joke\"] or \"!\" in state[\"joke\"]:\n",
" return \"Pass\"\n",
" return \"Fail\"\n",
"\n",
"\n",
"def improve_joke(state: State):\n",
" \"\"\"Second LLM call to improve the joke\"\"\"\n",
"\n",
" msg = llm.invoke(f\"Make this joke funnier by adding wordplay: {state['joke']}\")\n",
" return {\"improved_joke\": msg.content}\n",
"\n",
"\n",
"def polish_joke(state: State):\n",
" \"\"\"Third LLM call for final polish\"\"\"\n",
" msg = llm.invoke(f\"Add a surprising twist to this joke: {state['improved_joke']}\")\n",
" return {\"final_joke\": msg.content}\n",
"\n",
"\n",
"# Build workflow\n",
"workflow = StateGraph(State)\n",
"\n",
"# Add nodes\n",
"workflow.add_node(\"generate_joke\", generate_joke)\n",
"workflow.add_node(\"improve_joke\", improve_joke)\n",
"workflow.add_node(\"polish_joke\", polish_joke)\n",
"\n",
"# Add edges to connect nodes\n",
"workflow.add_edge(START, \"generate_joke\")\n",
"workflow.add_conditional_edges(\n",
" \"generate_joke\", check_punchline, {\"Fail\": \"improve_joke\", \"Pass\": END}\n",
")\n",
"workflow.add_edge(\"improve_joke\", \"polish_joke\")\n",
"workflow.add_edge(\"polish_joke\", END)\n",
"\n",
"# Compile\n",
"chain = workflow.compile()"
],
"id": "a4c40dfac5828bfc",
"outputs": [],
"execution_count": 3
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-09-14T00:08:07.323059Z",
"start_time": "2025-09-14T00:08:06.397007Z"
}
},
"cell_type": "code",
"source": [
"\n",
"# Show workflow\n",
"display(Image(chain.get_graph().draw_mermaid_png()))"
],
"id": "52d1e4c5b839e17f",
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"metadata": {},
"output_type": "display_data",
"jetTransient": {
"display_id": null
}
}
],
"execution_count": 4
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-09-14T00:08:10.237014Z",
"start_time": "2025-09-14T00:08:09.399345Z"
}
},
"cell_type": "code",
"source": [
"\n",
"# Invoke\n",
"state = chain.invoke({\"topic\": \"cats\"})\n",
"print(\"Initial joke:\")\n",
"print(state[\"joke\"])\n",
"print(\"\\n--- --- ---\\n\")\n",
"if \"improved_joke\" in state:\n",
" print(\"Improved joke:\")\n",
" print(state[\"improved_joke\"])\n",
" print(\"\\n--- --- ---\\n\")\n",
"\n",
" print(\"Final joke:\")\n",
" print(state[\"final_joke\"])\n",
"else:\n",
" print(\"Joke failed quality gate - no punchline detected!\")"
],
"id": "aef7038dd23aea84",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Initial joke:\n",
"Why did the cat join the gym? Because it wanted to improve its mew-scles!\n",
"\n",
"--- --- ---\n",
"\n",
"Joke failed quality gate - no punchline detected!\n"
]
}
],
"execution_count": 5
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"source": "",
"id": "5667aff79b939054"
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}