Files
iot-device-management-service/app/services/agent/graph.py
16337 8156f54004 重构 Agent:引入 LangGraph StateGraph 替代手写 FC 循环
架构变更:
- 新增 app/services/agent/ 模块(state/prompts/graph/tools)
- 7 个工具从 _tool_xxx 方法提取为 @tool 装饰器函数
- 构建 assistant + ToolNode 的 ReAct 图
- agent_dispatcher.py 改为薄壳入口,支持 USE_LANGGRAPH 开关
- MemorySaver checkpoint 持久化对话(thread_id=wechat-{user_id})
- 新增依赖:langchain-core, langchain-openai, langgraph

向后兼容:
- USE_LANGGRAPH=false 可切回旧版 FC 循环
- LangGraph 初始化失败自动降级到 Legacy 模式
- 企微图片处理/VLM分析逻辑不变
2026-03-25 13:52:55 +08:00

71 lines
2.1 KiB
Python
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.

"""
LangGraph StateGraph 构建
构建 assistant + ToolNode 的 ReAct 图,接入 Dashscope Qwen。
"""
from typing import Optional
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.checkpoint.memory import MemorySaver
from langchain_openai import ChatOpenAI
from app.config import settings
from app.utils.logger import logger
from .state import AgentState
from .tools import all_tools
from .prompts import SYSTEM_PROMPT
def _create_llm():
"""创建 LLM 客户端(通过 Dashscope OpenAI 兼容接口对接 Qwen"""
return ChatOpenAI(
model=settings.agent.model,
base_url=settings.agent.vlm_base_url,
api_key=settings.agent.vlm_api_key,
timeout=settings.agent.timeout,
)
def build_agent_graph(checkpointer=None):
"""构建并编译 Agent 图
Args:
checkpointer: LangGraph checkpointer 实例None=不持久化)
Returns:
编译后的 CompiledGraph
"""
llm = _create_llm()
llm_with_tools = llm.bind_tools(all_tools)
def assistant(state: AgentState):
"""LLM 推理节点:接收消息 + 系统提示,返回回复或工具调用"""
system_msg = {"role": "system", "content": SYSTEM_PROMPT}
response = llm_with_tools.invoke([system_msg] + state["messages"])
return {"messages": [response]}
# 构建图
builder = StateGraph(AgentState)
# 两个核心节点
builder.add_node("assistant", assistant)
builder.add_node("tools", ToolNode(all_tools))
# 边START → assistant → (条件) → tools 或 END
builder.add_edge(START, "assistant")
builder.add_conditional_edges("assistant", tools_condition)
builder.add_edge("tools", "assistant")
# 编译
graph = builder.compile(checkpointer=checkpointer)
logger.info("LangGraph Agent 图已编译")
return graph
def create_default_graph():
"""创建带内存 checkpoint 的默认图(开发用)"""
checkpointer = MemorySaver()
return build_agent_graph(checkpointer=checkpointer)