248 lines
22 KiB
Plaintext
248 lines
22 KiB
Plaintext
|
|
{
|
|||
|
|
"cells": [
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"id": "initial_id",
|
|||
|
|
"metadata": {
|
|||
|
|
"collapsed": true,
|
|||
|
|
"ExecuteTime": {
|
|||
|
|
"end_time": "2025-09-14T07:07:20.035830Z",
|
|||
|
|
"start_time": "2025-09-14T07:07:18.952675Z"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"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-14T07:08:19.248026Z",
|
|||
|
|
"start_time": "2025-09-14T07:08:19.242281Z"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"from typing import Annotated, List\n",
|
|||
|
|
"import operator\n",
|
|||
|
|
"from pydantic import BaseModel, Field\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Schema for structured output to use in planning\n",
|
|||
|
|
"class Section(BaseModel):\n",
|
|||
|
|
" name: str = Field(\n",
|
|||
|
|
" description=\"Name for this section of the report.\",\n",
|
|||
|
|
" )\n",
|
|||
|
|
" description: str = Field(\n",
|
|||
|
|
" description=\"Brief overview of the main topics and concepts to be covered in this section.\",\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"class Sections(BaseModel):\n",
|
|||
|
|
" sections: List[Section] = Field(\n",
|
|||
|
|
" description=\"Sections of the report.\",\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Augment the LLM with schema for structured output\n",
|
|||
|
|
"planner = llm.with_structured_output(Sections)"
|
|||
|
|
],
|
|||
|
|
"id": "b9c22b9f90a9810b",
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": 2
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"metadata": {
|
|||
|
|
"ExecuteTime": {
|
|||
|
|
"end_time": "2025-09-14T07:10:47.458182Z",
|
|||
|
|
"start_time": "2025-09-14T07:10:47.448495Z"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"from typing import TypedDict\n",
|
|||
|
|
"from IPython.core.display import Image\n",
|
|||
|
|
"from langgraph.constants import START, END\n",
|
|||
|
|
"from langgraph.graph import StateGraph\n",
|
|||
|
|
"from langchain_core.messages import SystemMessage, HumanMessage\n",
|
|||
|
|
"from langgraph.types import Send\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Graph state\n",
|
|||
|
|
"class State(TypedDict):\n",
|
|||
|
|
" topic: str # Report topic\n",
|
|||
|
|
" sections: list[Section] # List of report sections\n",
|
|||
|
|
" completed_sections: Annotated[\n",
|
|||
|
|
" list, operator.add\n",
|
|||
|
|
" ] # All workers write to this key in parallel\n",
|
|||
|
|
" final_report: str # Final report\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Worker state\n",
|
|||
|
|
"class WorkerState(TypedDict):\n",
|
|||
|
|
" section: Section\n",
|
|||
|
|
" completed_sections: Annotated[list, operator.add]\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Nodes\n",
|
|||
|
|
"def orchestrator(state: State):\n",
|
|||
|
|
" \"\"\"Orchestrator that generates a plan for the report\"\"\"\n",
|
|||
|
|
"\n",
|
|||
|
|
" # Generate queries\n",
|
|||
|
|
" report_sections = planner.invoke(\n",
|
|||
|
|
" [\n",
|
|||
|
|
" SystemMessage(content=\"Generate a plan for the report.\"),\n",
|
|||
|
|
" HumanMessage(content=f\"Here is the report topic: {state['topic']}\"),\n",
|
|||
|
|
" ]\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" return {\"sections\": report_sections.sections}\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"def llm_call(state: WorkerState):\n",
|
|||
|
|
" \"\"\"Worker writes a section of the report\"\"\"\n",
|
|||
|
|
"\n",
|
|||
|
|
" # Generate section\n",
|
|||
|
|
" section = llm.invoke(\n",
|
|||
|
|
" [\n",
|
|||
|
|
" SystemMessage(\n",
|
|||
|
|
" content=\"Write a report section following the provided name and description. Include no preamble for each section. Use markdown formatting.\"\n",
|
|||
|
|
" ),\n",
|
|||
|
|
" HumanMessage(\n",
|
|||
|
|
" content=f\"Here is the section name: {state['section'].name} and description: {state['section'].description}\"\n",
|
|||
|
|
" ),\n",
|
|||
|
|
" ]\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" # Write the updated section to completed sections\n",
|
|||
|
|
" return {\"completed_sections\": [section.content]}\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"def synthesizer(state: State):\n",
|
|||
|
|
" \"\"\"Synthesize full report from sections\"\"\"\n",
|
|||
|
|
"\n",
|
|||
|
|
" # List of completed sections\n",
|
|||
|
|
" completed_sections = state[\"completed_sections\"]\n",
|
|||
|
|
"\n",
|
|||
|
|
" # Format completed section to str to use as context for final sections\n",
|
|||
|
|
" completed_report_sections = \"\\n\\n---\\n\\n\".join(completed_sections)\n",
|
|||
|
|
"\n",
|
|||
|
|
" return {\"final_report\": completed_report_sections}\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Conditional edge function to create llm_call workers that each write a section of the report\n",
|
|||
|
|
"def assign_workers(state: State):\n",
|
|||
|
|
" \"\"\"Assign a worker to each section in the plan\"\"\"\n",
|
|||
|
|
"\n",
|
|||
|
|
" # Kick off section writing in parallel via Send() API\n",
|
|||
|
|
" return [Send(\"llm_call\", {\"section\": s}) for s in state[\"sections\"]]\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Build workflow\n",
|
|||
|
|
"orchestrator_worker_builder = StateGraph(State)\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Add the nodes\n",
|
|||
|
|
"orchestrator_worker_builder.add_node(\"orchestrator\", orchestrator)\n",
|
|||
|
|
"orchestrator_worker_builder.add_node(\"llm_call\", llm_call)\n",
|
|||
|
|
"orchestrator_worker_builder.add_node(\"synthesizer\", synthesizer)\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Add edges to connect nodes\n",
|
|||
|
|
"orchestrator_worker_builder.add_edge(START, \"orchestrator\")\n",
|
|||
|
|
"orchestrator_worker_builder.add_conditional_edges(\n",
|
|||
|
|
" \"orchestrator\", assign_workers, [\"llm_call\"]\n",
|
|||
|
|
")\n",
|
|||
|
|
"orchestrator_worker_builder.add_edge(\"llm_call\", \"synthesizer\")\n",
|
|||
|
|
"orchestrator_worker_builder.add_edge(\"synthesizer\", END)\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Compile the workflow\n",
|
|||
|
|
"orchestrator_worker = orchestrator_worker_builder.compile()"
|
|||
|
|
],
|
|||
|
|
"id": "afcc65ff28c2e69b",
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": 4
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"metadata": {
|
|||
|
|
"ExecuteTime": {
|
|||
|
|
"end_time": "2025-09-14T07:10:50.990699Z",
|
|||
|
|
"start_time": "2025-09-14T07:10:50.153622Z"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"\n",
|
|||
|
|
"# Show the workflow\n",
|
|||
|
|
"display(Image(orchestrator_worker.get_graph().draw_mermaid_png()))"
|
|||
|
|
],
|
|||
|
|
"id": "8b97064947c2cb7a",
|
|||
|
|
"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": 5
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"metadata": {},
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"outputs": [],
|
|||
|
|
"execution_count": null,
|
|||
|
|
"source": [
|
|||
|
|
"\n",
|
|||
|
|
"# Invoke\n",
|
|||
|
|
"state = orchestrator_worker.invoke({\"topic\": \"Create a report on LLM scaling laws\"})\n",
|
|||
|
|
"\n",
|
|||
|
|
"from IPython.display import Markdown\n",
|
|||
|
|
"Markdown(state[\"final_report\"])"
|
|||
|
|
],
|
|||
|
|
"id": "c0de9dd437183722"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"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
|
|||
|
|
}
|