【架构升级】LangGraph:用“图”的思维,重新定义多工具Agent的“智能编排”!

很多做 Agent 应用的朋友,都会遇到两个共性问题:

  1. 工具调用不收敛:LLM 一路狂点工具,次数、并发、总耗时都不可控。
  2. 运维不可观测:出了问题只能看一堆 log,完全没有「控制台」的感觉。

一、本次核心升级:工具编排护栏 + 预算管理

这次迭代的重点在于:给工具调用加「护栏」,避免 LLM 一直狂点 API、拖垮后端或把 AI 账单打爆。

1. ToolExecutionBudget & ToolBudgetManager

app/graph.py 中新增了两块核心结构(行号大约在 164–226):

@dataclass(frozen=True)
class ToolExecutionBudget:
    max_tasks: int = 6
    max_parallel: int = 3
    total_latency: float = 12.0
    def as_dict(self) -> Dict[str, Any]:
        return {
            "max_tasks": self.max_tasks,
            "max_parallel": self.max_parallel,
            "total_latency": self.total_latency,
        }
def _clamp_positive(value: int, *, floor: int = 1, ceil: Optional[int] = None) -> int:
    cap = ceil if ceil is not None else value
    return max(floor, min(cap, value))
class ToolBudgetManager:
    def __init__(self) -> None:
        self._lock = threading.Lock()
        self._settings = ToolExecutionBudget(
            max_tasks=_clamp_positive(int(os.getenv("TOOL_MAX_TASKS", "6")), floor=1),
            max_parallel=_clamp_positive(
                int(os.getenv("TOOL_MAX_PARALLEL", "3")), floor=1, ceil=MAX_PARALLEL_WORKERS
            ),
            total_latency=float(os.getenv("TOOL_MAX_LATENCY", "12")),
        )
    def get(self) -> ToolExecutionBudget:
        with self._lock:
            return replace(self._settings)
    def update(
        self,
        *,
        max_tasks: Optional[int] = None,
        max_parallel: Optional[int] = None,
        total_latency: Optional[float] = None,
    ) -> ToolExecutionBudget:
        with self._lock:
            settings = self._settings
            if max_tasks is not None:
                settings = replace(settings, max_tasks=_clamp_positive(max_tasks, floor=1))
            if max_parallel is not None:
                settings = replace(
                    settings,
                    max_parallel=_clamp_positive(
                        max_parallel, floor=1, ceil=MAX_PARALLEL_WORKERS
                    ),
                )
            if total_latency is not None:
                safe_latency = max(0.0, float(total_latency))
                settings = replace(settings, total_latency=safe_latency)
            self._settings = settings
            logger.info(
                "tool budget updated max_tasks=%s max_parallel=%s total_latency=%s",
                settings.max_tasks,
                settings.max_parallel,
                settings.total_latency,
            )
            return replace(self._settings)

  • ToolExecutionBudget:定义了一个「本轮对话 / 当前会话」的预算。
  • ToolBudgetManager:负责管理当前预算,提供 get()/update() 接口,供:
  • tool_orchestrator 使用
  • /config/tool-budget API 使用(后面讲)

2. tool_orchestrator:读取预算、裁剪任务、监控时延

原来的 tool_orchestrator 已经支持:

  • 自动补刀 _infer_required_tools:根据计划 & 中间结果推断还需要哪些工具。
  • 共用线程池:统一的 ThreadPoolExecutor,避免频繁创建线程。
  • Fallback 逻辑:工具失败后给 LLM 一个「工具挂了」的可解释信号。

这次在此基础上,主要做了三件事:

  1. 读取预算

    budget = tool_budget_manager.get()
    
    
  2. 裁剪任务 & 分批并发执行

  • 如果本轮计划生成了 30 个工具任务,而 max_tasks=20,就只取前 20 个。
  • 执行时以 max_parallel 为上限分批次提交到线程池。
  1. 累积时延 & 超限处理
  • 在 log 里写入一条 tool_latency_budget_exhausted

  • 给对话插入一条 ToolMessage,说明「因为预算限制,剩余工具被跳过」

  • 后续工具任务统一 skip,不再提交线程池

  • 每次工具执行完都记录耗时,累加到 total_latency_ms

  • 一旦超过预算,就:

这样做的好处是:LLM 能感知到「我已经被限流了」,下一轮规划时就会收敛一些,不再无限加工具。

3. Prometheus 指标:可观测的工具限流

配合上面的逻辑,在 app/graph.py / app/main.py 中增加了几个 Prometheus 计数器 / 直方图,例如:

  • tool_throttle_events_total{reason="max_tasks"}
    —— 超过 max_tasks 时 +1
  • tool_latency_seconds_total{tool="kb"}
    —— 分工具的累计耗时
  • tool_latency_budget_exhausted_total
    —— 本轮对话第一次把预算打爆时 +1

app/main.py 新增的 /metrics 接口会把这些指标以文本格式暴露出来,Prometheus 抓取后就可以在 Grafana 里画图、告警。


二、运行时配置与观测:/config/tool-budget + /metrics

有了预算体系,下一步就是:让它可以在生产环境动态调参

1. Pydantic 模型 + /config/tool-budget API

app/main.py 新增:

class ToolBudgetConfig(BaseModel):
max_tasks: int
max_parallel: int
total_latency: float
class ToolBudgetUpdate(BaseModel):
max_tasks: Optional[int] = None
max_parallel: Optional[int] = None
total_latency: Optional[float] = None

并提供两个接口:

  • GET /config/tool-budget
  • 返回当前的预算配置(从 ToolBudgetManager 读)。
  • PATCH /config/tool-budget
  • 允许部分字段更新,操作时会写 log,类似:

    [tool-budget] update max_tasks: 20 → 50 by user=admin

这两个接口就是前端 Ops Console 的数据源。

2. /metrics:Prometheus 采集入口

app/main.py 加上:

from prometheus_client import CONTENT_TYPE_LATEST, generate_latest
@app.get("/metrics")
def metrics():
payload = generate_latest()
return Response(content=payload, media_type=CONTENT_TYPE_LATEST)

然后在 Prometheus 配置中新增:

scrape_configs:
- job_name: "langgraph-agent"
static_configs:
- targets: ["localhost:8000"]  # 根据部署环境调整
metrics_path: /metrics
到这里,工具编排的限流行为就有了「肉眼可见」的曲线:哪些工具最耗时、哪天 budget 被打爆了几次,一目了然。

三、前端更新:浅色主题 + Ops 控制台

1. 浅色主题:更清爽的 UI

frontend/src/App.jsxfrontend/src/Chat.jsx 中,这次做了一次比较大的 UI 换肤:

  • 全局改成 浅色主题
  • 顶栏用蓝色渐变 / 纯蓝背景。
  • 内容区使用白色卡片 + 阴影。
  • 聊天气泡:
  • 用户消息、Agent 消息采用不同的浅色卡片、圆角、徽章色。
  • Plan banner、工具结果面板、文档列表等统一改为浅色块,更易阅读。
  • 表单 & 标签:
  • 提问输入框采用「白底 + 淡灰边框」风格。
  • Tag / Badge 用柔和的蓝绿点缀,用来标记「RAG 命中」「工具执行」「预算触发」等状态。

2. Ops Console Tab:可视化调参入口

在主界面的 Tabs 中新增了一个 "Ops Console" 页签,大致功能:

  1. 读取预算配置

    通过 GET /config/tool-budget 获取当前max_tasks、max_parallel、total_latency_ms在表单中展示。

  2. 在线更新预算

    用户修改表单值后,点击「保存」,前端调用:PATCH /config/tool-budget提交更新,更新成功后,前端给出提醒,并刷新展示值。

  3. 快速跳转监控

    提供一个按钮「打开 /metrics」,直接在新标签页打开原始指标页面,方便排查问题或在 Grafana 调试 query。

对应的前端 API 封装在 frontend/src/api.js 中,新增了两个函数:

export async function fetchToolBudgetConfig() {
const resp = await fetch(`${API_BASE}/config/tool-budget`);
if (!resp.ok) {
throw new Error(`Failed to load tool budget: ${resp.status}`);
}
return resp.json();
}
export async function updateToolBudgetConfig(payload) {
const resp = await fetch(`${API_BASE}/config/tool-budget`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!resp.ok) {
throw new Error(`Failed to update tool budget: ${resp.status}`);
}
return resp.json();
}

这样一来,「运维配置」从手改 .env 升级成了「控制台一键调整」。

四、运行效果

五、总结

通过本次迭代我们实现了:

  • ToolExecutionBudget + ToolBudgetManager 让工具调用「有预算、有护栏」;
  • Prometheus + Grafana 提供可观测性;
  • 前端 Ops Console 把调参这件事从 VSCode 搬到了浏览器。

想要本次修改后的完整代码 github下载:

git clone -b six --single-branch git@github.com:xywang279/langgraph.git

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值