# langgraph-agent-lab **Repository Path**: inner_boy/langgraph-agent-lab ## Basic Information - **Project Name**: langgraph-agent-lab - **Description**: agent 实验室 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-01 - **Last Updated**: 2026-09-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Agentic 设计模式实验室 基于 **LangGraph** 的本地学习平台,用来实操《Agentic Design Patterns》里的每一个设计模式。 每个模式一个页面,左边是讲解和**真实源码**,右边是实验台:填输入、拨对照开关、点运行, 然后看着图上的节点逐个点亮、state 一步步变化。 ``` make install && make dev # 然后打开 http://localhost:5173 ``` **不需要任何 API key 就能开始。** 默认的离线模拟供应商会用预设剧本把每个模式完整跑通—— 控制流、循环次数、分支走向、工具调用全都是真实执行的,只有模型说的话是预先写好的。 等你想看真实模型的表现时,在 `.env` 里配一个 key 切过去就行。 --- ## 这个平台想让你看见三件事 **一、看见图。** LangGraph 的本质是状态机。每个模式的拓扑都画在右侧, 实线是固定边,虚线是条件边(运行时才决定走向)。跑起来时节点会点亮,走过的边会高亮, 带环的图上还会显示某个节点被执行了几次。 **二、看见 state。** LangGraph 的心智模型是「节点不返回结果,而是往共享 state 上打补丁」。 执行轨迹里每一步都标出了这一步对 state 做了什么改动:`新增` / `追加` / `覆盖`, 以及 reducer 是怎么把增量合并进去的。 **三、看见差异。** 每个模式页都有**对照开关**,能把这个模式本身「关掉」: 提示链可以退回一个 prompt 直接要成品,路由可以退回一个万能客服, 反思可以把轮次调成 0,工具可以直接不给。 先跑开着的版本,再跑关掉的版本,对比产物——「为什么需要这个模式」就不用背了。 --- ## 快速开始 ```bash make install # uv sync + pnpm install,并生成 .env make dev # 后端 :8000 + 前端 :5173,Ctrl-C 一起退出 ``` 打开 。 **只想起后端**(调接口、写新模式时常用): ```bash ./backend/start.sh # 127.0.0.1:8000,开热重载 ./backend/start.sh -p 8080 # 换端口 ./backend/start.sh --host 0.0.0.0 # 让局域网里的其他设备也能访问 ./backend/start.sh --no-reload # 关掉热重载 ./backend/start.sh --help ``` 这个脚本不挑工作目录,从哪儿调用都行;首次运行会自己装依赖、生成 `.env`; 端口被占用时会直接告诉你是哪个进程占的,而不是甩一段栈。`make backend` 就是在调它。 ### 换模型 **推荐:在页面上配。** 右侧运行面板里点「模型设置」,可以为每个供应商填 API key、base_url、模型名,还能调采样温度,填完点「测试连接」立刻知道通不通。 配置存在浏览器 localStorage,刷新不丢,**不会写回 `.env`**。 填上 base_url 就能接任何 OpenAI 兼容服务——通义千问、Kimi、智谱、本地 vLLM 都行。 **也可以写进 `.env`**,适合长期固定使用的那一套: ```bash DEFAULT_PROVIDER=deepseek DEEPSEEK_API_KEY=sk-xxxxxxxx ``` 两层配置的关系: ``` 页面「模型设置」里填的 → 优先 ↓ 留空则回落 .env 里的默认值 ``` 支持 `deepseek` / `openai`(含任何 OpenAI 兼容网关)/ `anthropic` / `ollama` / `mock`。 在 `.env` 里没配 key 的供应商,只要在页面上填了 key,下拉框里就会点亮。 > API key 以明文存在浏览器 localStorage。本地学习用没问题; > 但如果用 `--host 0.0.0.0` 把后端暴露到局域网,同网段的人就能借你的 key 跑东西—— > 那种场景下把 key 放 `.env` 更合适。 其他命令: ```bash make check # 前端类型检查 + 后端冒烟测试(把每个模式的每个 knob 都跑一遍) make backend # 只起后端 make frontend # 只起前端 ``` --- ## 目录结构 ``` backend/ app/ config.py .env 配置 llm.py 统一模型层,模式代码只跟 LLMFactory 打交道 mock_model.py 可脚本化的离线模型(支持流式和工具调用) core/ spec.py PatternSpec —— 模式插件契约 registry.py 启动时自动扫描 patterns/ 注册 tracing.py LangGraph 事件流 → 归一化的 SSE 事件 graph_export.py 图拓扑 → 前端 JSON serialize.py state / 消息的安全序列化 + diff api/ 列表、详情、图预览、SSE 运行 patterns/ ★ 每个设计模式一个目录 smoke.py 冒烟测试 frontend/ src/ lib/ API 客户端、SSE 解析、运行状态管理 components/ 图、时间轴、state 面板、源码、讲解、练习 ``` --- ## 新增一个设计模式 **前后端都不用改。** 在 `backend/app/patterns/` 下建一个目录,放三个文件: ``` p06_planning/ __init__.py graph.py 真正的 LangGraph 实现(也是页面上展示给人读的源码) meta.py 元数据 + 离线剧本,导出名为 SPEC 的 PatternSpec doc.md 讲解正文 ``` `graph.py` 只需要导出一个 `build(llm, knobs)` 函数: ```python def build(llm: LLMFactory, knobs: dict[str, Any]): async def my_node(state: State) -> dict[str, Any]: model = llm("planner") # 角色名,决定 mock 查剧本里的哪一条 response = await model.ainvoke([...]) return {"plan": response.text} graph = StateGraph(State) graph.add_node("plan", my_node) graph.add_edge(START, "plan") graph.add_edge("plan", END) return graph.compile() ``` `meta.py` 里描述这个模式: ```python SPEC = PatternSpec( id="planning", chapter=6, name_zh="规划", name_en="Planning", summary="一句话说清它解决什么问题", build=build, mock_script={"planner": "离线模式下这个角色说的话"}, input_key="goal", knobs=[Knob(key="...", label="...", default=..., help="...")], samples=[Sample("示例名", "示例输入")], exercises=["动手题…"], ) ``` 存盘后刷新页面即可(后端 `--reload` 会自动重载)。跑一下 `make check` 确认没写错。 **几条经验:** - **knob 要能把模式本身关掉。** 学习平台最有价值的一步是对照实验, 所以每个模式至少留一个「退化成不用这个模式」的开关。 - **mock 剧本要写出差别。** 对照组的回答就该写得平庸——这不是作弊, 真实模型在没有这个模式时给出的就是那种质感。 - **列表型剧本演示循环**(`["第一轮", "第二轮", "PASS"]`,按调用次数推进), **函数型剧本演示分支**(`lambda messages: ...`,根据输入内容返回不同结果)。 - **doc.md 里少画 ASCII 图**,右侧就有真实的、会随 knob 变化的图。 讲解应该花在「为什么」和「什么时候不要用」上。 --- ## 模式进度 已实现 **15 / 21**。剩下 6 个待补齐。 | # | 模式 | 状态 | 图的形态 | |---|---|---|---| | 1 | Prompt Chaining 提示链 | ✅ | 线性 | | 2 | Routing 路由 | ✅ | 条件分支 | | 3 | Parallelization 并行化 | ✅ | 扇出扇入 | | 4 | Reflection 反思 | ✅ | 环 | | 5 | Tool Use 工具使用 | ✅ | ReAct 环 | | 6 | Planning 规划 | ✅ | 计划-执行环 | | 7 | Multi-Agent Collaboration 多智能体协作 | ✅ | 星形带回边 | | 8 | Memory Management 记忆管理 | ✅ | 线性 + 外部 store | | 9 | Learning and Adaptation 学习与适应 | ✅ | 线性 + 经验库 | | 10 | Model Context Protocol (MCP) | ✅ | 运行时装配工具 | | 11 | Goal Setting and Monitoring 目标设定与监控 | ✅ | 验收循环 | | 12 | Exception Handling and Recovery 异常处理与恢复 | ✅ | 重试/降级/兜底 | | 13 | Human-in-the-Loop 人在回路 | ✅ | interrupt 暂停 | | 14 | Knowledge Retrieval (RAG) 知识检索 | ✅ | 检索 + 生成 | | 15 | Inter-Agent Communication (A2A) 智能体间通信 | ✅ | 消息路由 | | 16 | Resource-Aware Optimization 资源感知优化 | ⬜ | | | 17 | Reasoning Techniques 推理技术 | ⬜ | | | 18 | Guardrails / Safety 护栏与安全 | ⬜ | | | 19 | Evaluation and Monitoring 评估与监控 | ⬜ | | | 20 | Prioritization 优先级排序 | ⬜ | | | 21 | Exploration and Discovery 探索与发现 | ⬜ | | > 这份章节清单尚未与书本目录逐条核对过。如果和你手上的版本有出入, > 改 `meta.py` 里的 `chapter` 和名字即可,列表会自动按章节排序。 --- ## 技术说明 - 后端 FastAPI + LangGraph 1.x,用 `astream_events(stream_mode="values")` 同时拿到 token 流和每个 super-step 后的完整 state 快照 - 执行过程用 SSE 推送,前端 `fetch` 流式读取(而不是 `EventSource`, 因为要 POST 一个带 knobs 的 body) - token 事件一次运行有好几百个,前端按 `requestAnimationFrame` 批量刷新 - 图用 dagre 算布局、React Flow 渲染 - 页面展示的源码由后端从磁盘直接读取,就是实际被执行的那份文件 - 模型配置分两层:`.env` 是默认值,页面「模型设置」是覆盖,随每次运行请求发给后端; 后端不落盘、不回写 `.env`,也从不把已配置的 key 返回给前端(`/api/providers` 只返回"有没有")