路由 对输入进行分类并将其定向到后续任务
路由 对输入进行分类并将其定向到专门的后续任务。此工作流允许分离关注点,并构建更专业的提示。如果没有此工作流程,针对一种输入进行优化可能会损害其他输入的性能。
何时使用此工作流程:路由非常适合复杂任务,其中有不同的类别可以更好地单独处理,并且可以通过 LLM 或更传统的分类模型/算法准确处理分类。
from typing import Literal
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
OPENAI_API_KEY= "lm-studio"
OPENAI_MODEL_NAME = "qwen2.5-3b-instruct"
OPENAI_BASE_URL="http://localhost:9999/v1"
llm = ChatOpenAI(
openai_api_key=OPENAI_API_KEY,
model_name=OPENAI_MODEL_NAME,
openai_api_base=OPENAI_BASE_URL,
temperature=5
)
# Graph state
# Schema for structured output to use as routing logic
class Route(BaseModel):
step: Literal["诗歌创作", "故事创作", "笑话创作"] = Field(
None, description="下一步路由选择"
)
rout = Route(step="故事创作")
# 序列化为字典
person_dict = rout.model_dump()
print(person_dict)
# Augment the LLM with schema for structured output
router = llm.with_structured_output(Route)
# State
class State(TypedDict):
input: str
decision: str
output: str
# Nodes
def llm_call_1(state: State):
"""Write a story"""
print("llm_call_1被调用,state->",state)
result = llm.invoke(state["input"])
return {"output": result.content}
def llm_call_2(state: State):
"""Write a joke"""
print("llm_call_2被调用,state->",state)
result = llm.invoke(state["input"])
return {"output": result.content}
def llm_call_3(state: State):
"""Write a poem"""
print("llm_call_3被调用,state->",state)
result = llm.invoke(state["input"])
return {"output": result.content}
def llm_call_router(state: State):
"""Route the input to the appropriate node"""
# Run the augmented LLM with structured output to serve as routing logic
decision = router.invoke(
[
SystemMessage(
content="基于用户的问题,自动选中路由到故事创作,笑话创作或者诗歌创作"
),
HumanMessage(content=state["input"]),
]
)
print("llm_call_router被调用,decision->",decision)
return {"decision": decision.step}
# Conditional edge function to route to the appropriate node
def route_decision(state: State):
# Return the node name you want to visit next
print("ruteState:",state)
if state["decision"] == "故事创作":
return "llm_call_1"
elif state["decision"] == "笑话创作":
return "llm_call_2"
elif state["decision"] == "诗歌创作":
return "llm_call_3"
# Build workflow
router_builder = StateGraph(State)
# Add nodes
router_builder.add_node("llm_call_1", llm_call_1)
router_builder.add_node("llm_call_2", llm_call_2)
router_builder.add_node("llm_call_3", llm_call_3)
router_builder.add_node("llm_call_router", llm_call_router)
# Add edges to connect nodes
router_builder.add_edge(START, "llm_call_router")
router_builder.add_conditional_edges(
"llm_call_router",
route_decision,
{ # Name returned by route_decision : Name of next node to visit
"llm_call_1": "llm_call_1",
"llm_call_2": "llm_call_2",
"llm_call_3": "llm_call_3",
},
)
router_builder.add_edge("llm_call_1", END)
router_builder.add_edge("llm_call_2", END)
router_builder.add_edge("llm_call_3", END)
# Compile workflow
router_workflow = router_builder.compile()
# Show the workflow
state = router_workflow.invoke({"input": "写一个关于曹操称象的歌词"})
print(state["output"])
输出:
{'step': '故事创作'}
llm_call_router被调用,decision-> step='故事创作'
ruteState: {'input': '写一个关于曹操称象的歌词', 'decision': '故事创作'}
llm_call_1被调用,state-> {'input': '写一个关于曹操称象的歌词', 'decision': '故事创作'}
当然,我可以根据这个经典故事改编成几句歌词:
【歌名】曹操与象
【副歌】
大象哪里去了呀,
众人纷纷眼发愣。
只有曹操静默不语啊,
智慧在他胸间升。
【第一节】
巨木沉水中,浮起来一片白。
人们围着瞧,心中无头绪乱,
“来人呀!谁有良策?能让这大象露!”
有人举秤测,却不敢贸然靠近它。
【副歌】
大象哪里去了呀,
众人纷纷眼发愣。
只有曹操静默不语啊,
智慧在他胸间升。
【第二节】
忽见桥旁立一人,
手中持布料。
“可将此布遮大象”,
曹丞相一笑赞:妙!
【副歌】
大象哪里去了呀,
众人纷纷眼发愣。
只有曹操静默不语啊,
智慧在他胸间升。
【第三节】
那桥上的人都惊异:
“如此绝招?
我们怎么也未想过!
好曹丞相智无双”。
【副歌】
大象哪里去了呀,
众人纷纷眼发愣。
只有曹操静默不语啊,
智慧在他胸间升。
这只是一个非常简略的尝试,由于歌曲歌词创作没有严格的标准限制,在编词时尽量融入原典故的思想内涵,希望能表达出《曹操称象》故事的趣味与智巧。