Files
knightutils/test/langgraph/workflows-agents.ipynb

268 lines
28 KiB
Plaintext
Raw Normal View History

2025-10-25 21:14:41 +08:00
{
"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": "iVBORw0KGgoAAAANSUhEUgAAAMYAAAHgCAIAAABxe4WVAAAQAElEQVR4nOydB0ATyRrHZ5PQQm/SUUGwYcd6dtSz997refYC+k49u569nO3svSv2rufZux4edhEQBAEpUgOBZN+XrMYICe5qymYzv+fjNrOzk03y32+++aYJSJJEGIzmECAMRqNgSWE0DJYURsNgSWE0DJYURsNgSWE0DLsk9exe+tunOelp+ZI8sqBARXSDxyOk0sLpPAFBFqiIhRTNTPAI+EsWLYFuTkgsei0ys+BZOfBLlrOsWMcOGT0EG+JSt058ePEwU5QlJQgkMEEmpjy+KQ9JiKI5CR78zIUTeQIkLUB0MstS4POSRUrmIVQkJ0KFLyflmioEFAf/JAVkXo4st4UV37eKsGEnF2Ss6FlSV0ITXtzLIgiihLdp7VZO7qUtkCETH5Vz/0JqYlQeWLey1S2b9HBFxoc+JbVlxpt8MVm1kX2dVo6IWzy4lPzv5XSokYfM8UFGhn4klRCTc+TPeE9/s/bDvRB3Ob0tPvpJTruhrt7lrZDRoAdJ5Yokm6dGdRrj5uFjibhOaqJo78K4IXNLg4+FjANdS+p9dNaR1QmjlpVBxsTakIhWA1x8KlkjI4CHdEvoqoS+U7lc2ank1wWlz2xLRMaBTiW1adob3yoWto5myMjgm/DLBVpunPIGGQG6k9TF3QkQTmw1wAMZJc16uwlMiLM73iOuoztJvQrLqtuGa8ECRjTo5BT5OBtxHR1J6tL+BBMBqlzfHhkxftVsBKbEmW3xiNPoSFKR4Vme5YTI6PGtbPnulQhxGh1JSpyDmvfRdbdX8+bN4+LiEEPevHnTtm1bpB2a9XYV55J5ojzEXXQhqVunkvjQGWyi01jf+/fv09LSEHOePXuGtImJOXH7zEfEXXQhqfdReeZCbekJQrV79+7t3bv3Tz/91Ldv3zVr1kgkkgcPHrRr1w7OdujQITg4GMltz6JFi7p27VqvXj3IdvjwYeryiIiIwMDAGzdutGzZslevXuvXr589e3ZCQgIk7tmzB2kBC0veh1guWyldjJfKyZQIrbUlqf3792/dunX8+PEgqStXrqxdu9bS0nLQoEErV66ExOPHj3t4yMIWy5Yti4+PnzZtGkEQ0dHRIC83Nze4xMTEBM5u3ry5X79+VatWrVixolgsvnDhwqlTp5B2gK8iO0OCuIsuJFUgRtb22pLUo0ePKlSoQHk/nTp1qlmzZk5OTtFsCxYsyM7Odnd3h2OwQCdOnLh16xZIChQGKXXq1OnTpw/SCeaWgoyUAsRddDKqkyQJpC2qVKmyevXqOXPmVKtWrWHDhp6enkj1LZBgz27evPn27VsqhbJeFOXLl0e6gpTdDOIwupAUX0Dk5mjL1IMXBTXd1atXwQcSCATQyhs7dqyzs7NyHqlUOm7cOKjRRo8eDSbK2tp6yJAhyhnMzHTXR5SXI+EJtPeI6R9dSEpox8/J0Jap5/F4neRERkbeu3dv48aNWVlZK1asUM7z4sWLp0+frlu3rlatWlRKZmZmiRIlkD6Ar8JcqOveel2ii8/m5GqanS5F2gH8aGjNwYGPj0/Pnj2h1fby5ctCeT5+lDXaFRqKlIP0BBhsR3cTxF10Iak6bRwl+dpyH86dOzdp0qRr166lp6dDLODy5cvgXUF6qVKl4O/FixefPHkCaoM6cdeuXRkZGdDcW7JkCfjjELhSWaC3t3dycjI0HhVel2YRi1CNplzumNKFpMyFAr4A/XNIKwOGfv/9d1DMxIkTg4KC5s6d26hRI4gUQDr46RCagjgTOO+urq7z5s0LDw9v2rTphAkTRo0aBQEqkBr8LVpg/fr1IZoQEhJy/vx5pGmuH/+ACOToZtizNopHR6M6j/0VlxCd++siX2TcbJjyxtHVtOs4Lg9C1JGf2HGER4GYjIvIQUZM2gdxfi7JbT0hXc42dilldmZrwrA/VE9CAhdn4MCBKk9BNFKdKe3YsSOEyJF2gJLDwsJUnrK1tQXXTeWpyZMnt27dWuWpQytjnDy57JhT6HQ6w7qQiBrN7Gu3VDEQDzrmVEa9AZFIZGGh2vmA7hRzc3OkHeB+4K5UnsrPz6d6cooC96Py1L//pN48mTp6Offnceh0TYTOoz2OrIlTKSk+nw8RSJVXqUvXNkKhJgd43T6d2nqwUcxq12nMzbWURZWGtht+M4pR/cpsmBpRro6VT4BRTLrSw9TQmBdZJzcZ0VS+NRMjWg8ylkl8SF8T2G+fSn50+WPt1vaBzbg8wSHsesqtY2lla1sFdTei9Tb0tszGuzc5JzfEC234HUe4c29mX3a6OHR1XE6GpEV/FyOp7xToeTGgw6tiEt+KrWwF5WpZ1W7phAyfexeTn9/OzEqXOHuadp/gjYwPVixZdmRNbFKsWCohTc14FtY8S1uBiQmPEHzVdFCx/tznJcQIQj4CCf5PfBo08imlyIV8PlKEBRR55P8llHPKx+XJvxh5kiKD8oWKzKSUFIskOVkFYJPEeSSPh5w9ID5ujGKiYIWkKOIis8NvpqfEifNEUogySwstS0cUHrmmWJPuUyxU+qX9+pX+lF5ISAmf4Bcu8XMGRUwV/gtlKX0z6sqTwRMQAhPSzILv6G4aUM/Oy8/Y55axSFI6IDAw8MGDBwijTYxoReGCggIIqCKMljEuSQkEeFFurYMlhdEwRvQVF9PXi9Eg2EphNAyWFEbDYElhNAz2pTAaBlspjIbBksJoGCwpjIbBksJoGOyeYzQMtlIYDYMlhdEwWFIYDYMlhdEwWFIYDYMlhdEwWFIYDYMlhdEwONSJ0TDYSmE0jBF9xWCiLC0tEUbLGJGkJBJJZmYmwmgZI5IU1HpQ9yGMlsGSwmgYLCmMhsGSwmgYLCmMhsGSwmgYLCmMhsGSwmgYLCmMhsGSwmgYLCmMhsGSwmgYLCmMhsGSwmgYLCmMhsGSwmgY7u/OMHbs2OvXr/N4sg08AEKOubn5zZs3EUYL6HTXUL0wZswYNzc3kBGois/nU9ry9jbebYO0Dfcl5efnV7duXanSLkcWFhbdu3dHGO3AfUkBgwYN8vLyUrx0dXXt1KkTwmgHo5CUp6dngwYNKEMFFR/Wk1YxCkkB/fv3pwwVyKtz584IozW+p8V35XBCroiQSpR2PZRve0gqjlHh7Rg/7bQpy0ZAxkL7NRIy44EkUuXbkqn90w6MyluAFjlWtZuo0rafSkRGvol4/dK3TFlfX99C+XkEIovcM1K1r+Tn/IRUfkJxoDqz0s0p7R+JCu0dWfjb+PoljyDNrVCDjiUMZec3ZpI6sDw6Jb6Ab4p4JC8/X0lSYOykn7dzlf8+n4tV7BUreyM4Bf+RqvoS4ZSyRuEiAhWWFMGTqbGwpEB50sL3qU4iiCdFUlWGmScTceHHQF4Q3G5R1Sr0wYPbln6RlOzrlBbeslZxS9JPn0JW5tcf4UsKKiIpvgAKlBbkIwdXk16TSiLWw0BSp7fExUWKugeXxhsl6oX9SyNKeJp3GO6J2A1dSYWufpuekt9tQhmE0R+hKyOFNvzuE1htq+i654kx+Q26uCCMXgnq7/nhXT5iN7Qk9fxuGrgCrt7WCKNX7BxM+QL0+EYqYjG0uo1FIiSRIAwbAPc/O5XVnd+0JEVCK0mKMGwA2sWklNXNI7yEF0bD0JMUQUVpMPpHFrAjWD0eiZakZB+B46OqDAZZ7wO7n296vhTCsAbWP97Yl8JoGFqS4vPkvXgYFkCw3qmlJSmJVEXXLEYvsH+qAN2Kj8QtPnYgG83B7t+CrqTY3W41Ikgp2+c00XbPsZViBxyJS8nAVoodyAbPstsLwQ05ZoQe2R/UvFbxeSIjI5oEBf73379IG7C+uqAlKR5XOmSiot707N0W/QAVygf06zsU6RFutPikXOmQefnqGfoxypcPgH9If5Cs73DVVvRcKpX+uWrRjZtXTE1Mg4JaBlSsMmXa+NBD5x0cHOHsufMnT5wMjYqKKF26TNMmLbp07kW1jDt2bjZo4K/p6R937NxoYWFRM7Du6FEhjo5OSL712Zat6+7cvZGUlBAQULVTh+516tSn3qt
"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
}