基于双层 RAG(Agentic + Modular)与多 Agent 编排的对话式 3C 电子产品 AI 导购系统,强调评测驱动优化与全链路可观测。
A conversational AI shopping-guide agent for consumer electronics — built on two-layer RAG (Agentic + Modular), multi-agent orchestration, eval-driven optimization, and end-to-end observability.
raguide 打通「意图理解 → 证据检索 → 决策辅助」核心路径:用双层 RAG(Agentic 外层多 Agent 编排 + Modular 内层 6 阶段可组合检索)做检索,用评测驱动做优化(5 维加权分 0.712 → 0.838),用全链路可观测保证能上线。后端 FastAPI / LangGraph,前端 Next.js 15 全栈,端到端 SSE 流式返回。
- 🧠 双层 RAG 架构 — 外层 Agentic RAG(Orchestrator + 3 个 sub-agent 自主决策「要不要检索 / 检索什么 / 够不够」,规避 Tool-call RAG 反模式);内层 Modular RAG 6 阶段管道(查询改写 → BM25 + 稠密向量 + 跨模态图像三路并发召回 → RRF 融合 → 重排 + 压缩 → Self-Eval 自评循环 → CRAG 联网兜底),覆盖 RAG 四种编排范式。
- 📊 评测驱动优化 — 自研 5 维度加权评测(任务完成 / 输出质量 / 过程质量 / 效率 / 安全)+ 75 例 gold-set(happy 18 / edge 14 / error 13 / adversarial 16 / regression 14,含 prompt injection 对抗),以「评测信号 → 改动 → 实测前后分」闭环迭代,加权总分 0.712 → 0.838、安全维度达 1.000;CI 设无回归门禁。
- 🔭 全链路可观测 / 可上线 — 每个 trace span 强制 9 字段(输入 / 输出 / 模型 / token / 延迟 / 错误 / 状态…),Langfuse + Prometheus + Grafana 12 面板 + 9 条告警规则 + 月成本熔断 + runbook;75 例 gold-set 镜像成 Langfuse Dataset + dataset-run 闭环(5 维分按 run 挂回数据项、跨 run 可比)+ 业主端评测看板(baseline / 历史报告 / 逐案 judge 理由 / fixtures,免 Langfuse 只读);17 项上线 DoD 验收满足 16。
- 🔌 自研 LLM 网关 — Ports & Adapters(Adapter / Template Method / Strategy / Chain of Responsibility 四设计模式协同),多 provider(Claude / GPT / DeepSeek)× 多角色运行时路由 + FallbackChain 故障降级;密钥只走
.env、DB 仅存变量名(零硬编码、零入库)。 - 🖼️ 多模态 + 结构化检索 — 图文输入(MinIO 临时存 + JinaCLIP-v2 跨模态检索 + Claude vision VLM)、商品 / 对比卡片结构化出库;规格大表「双列存储 +
spec_query_sql」让「电池 ≥ 5000mAh ∧ 价格 ≤ 6000」走参数化 SQL 精确过滤。 - ✅ 工程严谨 — 889 后端单测(含 prompt injection / SQL / 路径遍历对抗用例;另含认证 22 测)+ 自建「工程验证账本」机制:每个里程碑独立验证、留痕、闭环,专治「声称完成 ≠ 真完成」。
📐 架构详解(mermaid 图) · 🎯 技术答辩 30 题 · ✅ 17 项 DoD 验收 · 🛠️ 运维 runbook
raguide 是一个面向 3C 电子产品(手机 / 笔记本 / 耳机)的 AI 导购 Agent。消费者用自然语言提问("5000 以内拍照好的手机"、"游戏本推荐"),Agent 基于内部商品知识库(PDF 解析 + 向量检索 + 结构化规格库)完成意图识别、证据检索、推荐生成的全链路,以 SSE 流方式实时返回。
为什么这么设计?
- Agentic RAG 外层:Orchestrator + 3 sub-agents 决定是否检索、用什么 Query 检索、结果是否足够——而不是让 LLM 直接调
kb_search工具(Tool-call RAG 的常见反模式)。 - Modular RAG 内层(M2c 已交付):Retrieval Agent 内部是 6 阶段可组合模块流水线(Pre-Retrieval 分支 / Retrieval 3 路并发 / RRF Fusion / Post-Retrieval 线性 / Self-Eval 循环 / CRAG 条件兜底),覆盖 Gao et al. (2023) 全部 4 种编排模式(Linear / Conditional / Branching / Looping)。
- Ports & Adapters LLM 抽象:不用 LiteLLM,自研 Protocol-based 适配层,支持 FallbackChain、多角色路由、指数退避重试——面试可深挖 4 个设计模式。
- 求职作品集定位:每个技术决策都要扛得住 AI 全栈岗位面试技术官的深度追问。
| 里程碑 | 状态 | 说明 |
|---|---|---|
| M0 脚手架 | ✅ 完成 + ✅ 工程验证 | repo、uv 环境、Docker Compose(Qdrant + Postgres + Redis + Langfuse + SearXNG + Grafana)、CI 骨架、docs/requirements.md。工程验证 2026-05-25:26 条 checklist 全 ✓,7 个 finding 全闭环(5 修复固化 + 2 显式 defer),live smoke eng-m0.yml 在 main 上 green。完整账本:docs/engineering-verification/m0-scaffold.md |
| M1 Hello RAG | ✅ 完成 + ✅ 工程验证 | KB Pipeline v0(5 份 PDF → bge-m3 → Qdrant)、单 Agent SSE、4 事件协议。工程验证 2026-05-25:19/19 checklist 全 ✓(CI 结构层 + 本地真 LLM 层),4 个 finding 全闭环。CI eng-m1.yml 在 main green。完整账本:docs/engineering-verification/m1-hello-rag.md |
| M2a LLM Ports & Adapters | ✅ 完成 + ✅ 工程验证 | LLMProvider Protocol、AnthropicAdapter、OpenAICompatibleAdapter、DeepSeekAdapter 注册、FallbackChain、5 类 LLMError、YAML 角色路由。工程验证 2026-05-25:15/15 checklist 全 ✓,finding-007 当场修死(_validate_routed_keys 聚合 lifespan 失败 + 2 个回归测试),CI eng-m2a.yml 在 main green。完整账本:docs/engineering-verification/m2a-llm-adapter.md |
| M2b Multi-Agent + Tools + json_schema | ✅ 完成 + ✅ 工程验证 | LangGraph 5 节点、4 工具、8 事件 SSE、IntentSlots json_schema 双重校验、Working-Memory Anchor。工程验证 2026-05-25:合并到 M2b-Obs session 一并验完 |
| M2b-Obs Langfuse + Ragas + AgentEvaluator + Grafana | ✅ 完成 + ✅ 工程验证 | 22/22 task;Langfuse 3 trace(9 字段 span)+ Ragas 4 指标 + 5 维度 AgentEvaluator + 53 条 gold-set + 8 面板 Grafana + CI eval gate(finding-014 accepted)。工程验证 2026-05-25:27 项 checklist 全过(含 F4 18/53 partial + G2 4/8 + H1 accepted-fail per finding-011);CI eng-m2b.yml 在 main green。完整账本:docs/engineering-verification/m2b-obs-eval.md |
| M2c Modular RAG 内层(hybrid retrieval + Self-Eval + CRAG) | ✅ 完成 + ✅ 工程验证 | 28/28 task;6 stages 全交付:Pre-Retrieval(HyDE/Multi-Query/Decompose intent-conditional 路由)+ 3 路 Retrieval(BM25 Tantivy / Dense bge-m3 / Image JinaCLIP-v2 并发 fan-out)+ RRF Fusion(k=60)+ Post-Retrieval(bge-reranker-v2-m3 TEI + Sonnet 4.6 Contextual Compression)+ Self-Eval Looping(rule 快门 + LLM 仲裁,max 2 轮)+ CRAG SearXNG 兜底。13 个新 SpanHook step + 7 个新 Prom 指标 + 4 个 Grafana 面板。工程验证 2026-05-25:24 项 checklist 全过;finding-013 终结(compression + crag schema double wrap 修死 + 3 层防线:I3 5-param regression test + I4 CI grep guard + unit tests);138/138 retrieval tests;CI eng-m2c.yml 在 main green。3 个新 finding(016-018 Tantivy 422 / TEI 5s timeout / Self-Eval iter cap)全 deferred:M4。完整账本:docs/engineering-verification/m2c-modular-rag.md |
| M3 Multimodal + Working Memory(图文输入 + 卡片) | ✅ 完成 + ✅ 工程验证(2026-05-29,聚焦跨模态 live;eng-m3.yml 本地全绿,GitHub 自动跑待账单恢复) | 图片上传 API(minio + 6 行错误矩阵)、JinaCLIP-v2 跨模态检索激活、Claude Sonnet vision VLM 工具、商品卡片 / 对比卡片 JSON 出库(emit_cards)、Working-Memory 4→6 slots。前端上传 UI 为设计基线,落地见 M5 |
| M4 评测闭环 v2(增量优化) | ✅ 完成 + ✅ 工程验证(billing-adapted) | 工程验证揭示并修复 12 个 finding(010/016-026),其中 finding-024 为核心:agent 工具调用循环因 async-generator state 传播缺陷自 M2b 起从未真正执行(commit b3d0118 修复)。修复后跑出首个有意义的 v1 baseline:weighted_score 0.712(5 维度:task_completion 0.701 / output_quality 0.713 / process_quality 0.885 / efficiency 0.291 / safety 0.819),71 case,judge schema_failures 0,case_errors 2。Phase C(3 轮 prompt 优化)deferred。完整账本:docs/engineering-verification/m4-eval-loop.md |
| M5 Web UI(对话展厅) | ✅ 完成 + ✅ 工程验证(2026-06-02,本地 demo;前端无 GitHub 自动跑,待账单恢复) | Next.js 15 + React 19 + Tailwind 4 + shadcn/ui + Vercel AI SDK 6.x(useChat + 自研 ChatTransport 桥接真实 9 事件 SSE)+ Zustand + TanStack Query。双栏 Chat + 检索透明化 Inspector(意图→三路召回→工具调用[含 latency_ms]→生成→usage/trace_id 实时时间线)、ProductCard(SSE 形状 + GET /v1/products/{id} 图片富化)/ CompareCard(dim×product 矩阵)、图片输入(上传按钮 / 拖拽 / 粘贴 三种方式 → minio → JinaCLIP 跨模态检索)、👍👎 反馈(POST /v1/agent/feedback)。设计经 ui-ux-pro-max(AI-Native UI / Trust-Blue / Plus Jakarta Sans + JetBrains Mono / Lucide)。后端 additive:CORS + feedback + products 读端点 + history 接入 agent。live 验证:真 newapi 全栈 → 推荐/对比/多轮查询全 9 事件 + 工具真执行 + 卡片真出 + 多轮 history 解析「它」;finding-027(首查询冷加载阻塞→SSE 取消)修死(embedder 启动预热)。完整账本:docs/engineering-verification/m5-web-ui.md |
| M5.1 左侧功能栏 + 多会话 | ✅ 完成 + ✅ 工程验证(2026-06-02,本地 demo;浏览器 QA 见账本) | claude.ai 式左侧栏(shadcn sidebar,自适应折叠:≥1280 展开 / 1024–1280 图标条 / <1024 抽屉)+ 多会话管理(新建/切换/删除/重命名/搜索)。后端 additive conversations CRUD(Postgres,匿名 device_id 经 X-Owner-Id,messages JSONB);前端 TanStack Query + Zustand activeConversationId;切换 useChat.setMessages 全量还原;首条消息懒建会话、每轮 ready 后 PUT 存。三列 侧栏|对话|Inspector(Inspector 固定 360,去 resizable)。侧栏附加面:能做什么 dialog / 可观测看板(Langfuse:3001·Grafana:3002)/ 设置(主题·清空·owner_id)。/v1/agent/run 不变。live 验证:conversations CRUD 全过 + 跨 owner 隔离(B 见空+404)+ 缺头 422;前端集成 SSR 出侧栏。完整账本:docs/engineering-verification/m5.1-sidebar-conversations.md |
| M6 KB 在线管理 | ✅ 完成 + ✅ 工程验证(2026-06-13,18/20 checklist,35 passed,2 Minor finding 非阻断) | 业主在应用内增删 3C 商品进运行中 KB(owner-gated):PDF / 表单摄入 → dense Qdrant + BM25 Tantivy + Postgres(+ 可选图像);独立 /kb 管理页(列表 / 详情 / 编辑 / 重摄入 / 删除 + 真实 chunk_count + 源 PDF 查看)。完整账本:docs/engineering-verification/m6-kb-admin.md |
| M7 LLM 模型配置 | ✅ 完成 + ✅ 工程验证(2026-06-13,17/18 checklist,102 passed,凭据红线守住) | 业主经 admin「模型设置」面板在线配置多 provider(Claude / GPT / DeepSeek)端点 + 角色绑定(密钥只写 .env,DB 仅存 env 变量名);DB 角色映射热重载 + FallbackChain;连通性检测(throwaway adapter 探活,分 6 类状态,密钥零泄漏)。完整账本:docs/engineering-verification/m7-llm-config.md |
| M8 用户画像持久化 | ✅ 完成 + ✅ 工程验证(2026-06-13,16/17 checklist,19 passed,防自强化机制亲验) | 跨会话、时间衰减的用户偏好画像(按匿名 owner_id):done_hook 异步更新、intent 空缺槽补全、working_memory 注入;参数全 admin 在线可配(热加载);GET/DELETE /v1/me/profile 自助查看 / 清除。详见 §多轮对话记忆。完整账本:docs/engineering-verification/m8-user-profile.md |
| Pre-M9 细节补全 | ✅ 完成 | 4 文档审计后补齐「设计≠代码」细节:spec_query_sql 接真 Postgres、chitchat 跳检索、coverage_score + 评测 rule_based 打分器、retrieval_step 实时 SSE、记忆 L0 候选池门禁 / L1 类目大纲 / L4 对话摘要、在线 spec 抽取、Anthropic prompt caching、大表行级 chunk(最小版)。spec/plan:docs/superpowers/{specs,plans}/2026-06-09-pre-m9-detail-completion*。 |
| M9 故事化 + 作品集文档 + 上线 Checklist | ✅ 完成(DoD 16/17 ✅,1 🔶——第 16 项 CI 自动触发因账单 defer) | 优化:P1 空输入鲁棒性(三层防御,error 类 0.708→0.858)、P3 efficiency+grounding(weighted 0.789→0.838,GATE PASSED,baseline v3)、P4 运维就绪(Prometheus 9 条告警规则 + Alertmanager → 后端 webhook、月成本上限「软告警 80% + 硬熔断 100%」/v1/admin/budget-config、runbook(SLO + 8 故障场景 + 演练)、eval baseline 仅 GATE PASSED 可写 + --force-baseline 逃生口——launch checklist 第 4/5/8/9 项落地)。作品集文档(commit 6771eda):interview-qa.md(30 题技术答辩底稿)+ architecture.md(3 个 mermaid:系统全景 / LangGraph 流程 / Modular RAG pipeline)+ dod-verification.md(17 项 DoD 验收)+ M6/M7/M8 工程验证账本补齐。优化全记录见 §评测驱动优化日志 |
| M10 iOS 原生客户端(课题:原生移动端) | ✅ 真机跑通(近 Web 平价) | SwiftUI 原生 App(apps/ios/RaguideMobile),复用现成 FastAPI/SSE 后端(后端零改动,仅 additive 修复),已在真机 ⌘R 跑通;含 App 图标(Trust-Blue 对话气泡 + 绿火花)。功能:① 多会话历史(本地持久化 + 新建/切换/重命名/删除/搜索/时间分组/生成中指示)② 透明度 Inspector(9 个 SSE 事件实时入 trace → 意图槽位 / 检索步骤+耗时 / 证据 / 工具调用 / 用量;「检索过程」全屏面板)③ 消息操作(长按 复制/编辑重发/撤回)+ 流式停止 + 出错重试 ④ 反馈闭环(👍/👎 + 原因码 + 自由文本 → /v1/agent/feedback)⑤ 流式逐字 + 块级 Markdown ⑥ 商品/对比卡(对比卡 维度×产品 矩阵)⑦ 图片输入(PhotosPicker → JinaCLIP 跨模态)+ 完整展示 + 全屏预览。导航/外观:自定义平铺顶栏(去 iOS 26 按钮白底)+ 跟手左侧抽屉(功能选择框)+ 全屏历史;选项图标全黑 + 深色模式;经 ui-ux-pro-max。签名:DEVELOPMENT_TEAM 走 gitignored Config.xcconfig(不入库)。可观测:Langfuse 已重新启用(端口与主栈去冲突);iOS 反馈经 user_feedback score(含 comment + metadata 原因码)进对应 trace。踩坑实录:URLSession.AsyncBytes.lines 对本后端 SSE 不产出行(→手动逐字节切行)/ 键盘弹出整页下沉(.ignoresSafeArea(.keyboard) 误用)/ 删除会话「点删一瞬消失又出现」(swipe 去掉 role:.destructive)/ 带图查询被分类 chitchat 跳过检索丢图(路由强制带图走检索)/ 对比卡 rows LLM 用中文名作 key 致全 —(后端按位归一化)。构建/运行见 apps/ios/ios-setup.md。真机跑通后续增强(均经 ui-ux-pro-max):① 豆包化视觉改版(信任蓝·柔和版,commit a520864)—— 灰画布 #F5F6F8 + 白卡柔阴影、用户气泡淡薰衣草 #E8ECFF、全局 .fontDesign(.rounded)、主渐变 #2E6BFF→#6366F1、豆包式首屏 2×2 建议卡;② 抽屉补全 Tier1+2 消费者功能(commit b1c94e8,对齐 web 侧栏)—— 我的偏好 / 能做什么 / 外观 / 帮助·关于 / 意见反馈 / 设置;③ 历史删除改两段式 inline 确认(commit 8e7e9dd,去弹窗;原生 .swipeActions 做不到就地撑大 → 自定义 SwipeConversationRow);④ 管理·业主段(commit 44516b8)—— 画像参数(GET/PUT /v1/admin/profile-config)+ 评测候选(approve / reject);⑤ Gold-set 浏览器(commit f75db75)—— GoldSetView 只读浏览 + 类别 chip 筛选;⑥ 抽屉改整页 push 导航(已实现+验证,未提交,用户要求)—— 从「底部弹出 sheet」改为「整页 push + 左缘右滑返回」,关键架构决策是把 NavigationStack 放最外层包住 SideMenuContainer{chatScreen}(而非抽屉内层),让抽屉「左缘起手」手势只在 root、push 页交系统导航控制器接管以隔离手势;enum MenuRoute + NavigationPath + pushAfterDrawer 错峰 + pushPageChrome modifier,9 个功能页删自定义 SheetHeader 改系统返回,clean build SUCCEEDED;⑦ 数字键盘加「完成」(commit 92b953e,numberPad 无 return 键 → 键盘工具栏)。剩余:多轮长场景回归 + 可选录屏。 |
| 评测可观测化增强(Langfuse Dataset 闭环 + 业主评测看板) | ✅ 已实现 + 本地验证(本会话,尚未提交) | 把「评测信号只在 CLI / 本地文件可见」这条缺口补上,分三块。A · Langfuse gold-set Dataset:新模块 packages/eval/src/raguide_eval/langfuse_dataset.py 把 75 例 gold-set 全量镜像成名为 raguide-gold-set 的 Langfuse Dataset(input=query,expected_output={expected_slots, expected_safety},metadata=case_id / category / source / human_verified / cohort / notes / fixture_image),item id=case_id 幂等;make eval-langfuse-dataset 运行,YAML 仍是唯一真值 + L0 门禁;live 验证 75 items 在册。B · dataset-run 闭环:make eval-dataset-run(tests/eval/run_gold_set.py --dataset-run)逐例用 SDK item.run() 上下文把 trace 注册为 dataset run,5 维 + 加权分作为 goldset.* score 挂回数据项,跨 run 在 Langfuse UI 可比;live 端到端验证(run 建成、item 关联、6 个 score 与 run 输出一致;冒烟 run 跑后删除)。run_gold_set --write-report 现额外落 tests/eval/_reports/report-<stamp>.json(含逐案完整 judge 理由 + 维度,弥补 .md 只有 worst-5 截断理由)。C · Ragas 现状(诚实记录):离线 Ragas 已全部接线但未启用——根因 ragas 0.2.15 依赖 langchain-core 0.3.x,与后端 langgraph 1.2.x 所需 langchain-core 1.x 无法共存(强降 langchain 会把 langgraph 1.2.1→1.0.1 触碰锁定的 agent 编排,拒绝)→ ragas 返回全 NaN → NaN 守卫返 None → 本环境从未真正产出 Ragas 数据;eval-dataset-run 因此不传 --ragas,4 指标(Faithfulness / Answer Relevancy 生成侧、Context Precision / Context Recall 检索侧)仍属设计未运行;解法见 §提升清单。D · 业主评测看板(web,只读、免 Langfuse):admin 专属 EvalDashboardDialog(侧栏「评测看板」)4 标签——基线(加权 + 5 维纯 CSS 横条按阈值着色 + 按类别 / cohort + git_sha / judge_model / case_count / 时间戳)/ 报告(master-detail + Markdown)/ 案例理由(逐案完整 judge 理由表,读 .json sidecar)/ Fixtures(跨模态 fixture 图廊);后端 5 个只读端点 /v1/admin/eval/{baseline,reports,reports/{name},reports/{name}/cases,fixtures}(全 require_admin + 严格 report-<stamp> 正则防路径遍历),fixture 图字节经新增 公开 /static/eval-fixtures StaticFiles 提供(<img> 带不了 JWT 头;均为已入库的良性测试 fixture)。测试本会话新增 backend +8(admin_eval 共 29 passed)、web +15(admin-eval.test.ts + EvalDashboardDialog.test.tsx,web 套件共 270 passed,tsc 0 err,biome clean);UI 经 ui-ux-pro-max(Data-Dense Dashboard / 复用现有 shadcn token / 颜色不单独承载语义)。评测分数不变(本批纯可观测化,baseline 仍 v3=0.838)。 |
| 用户认证 + RBAC + 统一身份(三端) | ✅ 已交付(后端 5acf363 / web 4efa9ca / iOS e8659df) |
用户授权的架构新增(超原 §4 锁定架构,经确认)。锁定设计:统一身份 / 允许游客 / 首位注册者 = admin / 用户名 + 密码。后端(api/auth.py):users 表(id=u_acct_<hex> / username unique / password_hash / role / created_at);POST /v1/auth/register|login → HS256 JWT(claim sub/username/role);GET /v1/auth/me。密码 bcrypt(72 字节一致截断、永不明文 / 不入日志);login 统一 401 防用户名枚举;register 事务内 count+insert → 首位注册者 = admin(防并发双 admin)。统一身份:effective_owner_id(agent,游客返回 "")/ require_owner_id(profile / conversations,缺身份 422)—— 有效 JWT → owner_id=claim.sub,否则回退 X-Owner-Id 头;游客路径零回归。RBAC:require_admin = Bearer admin JWT 优先、X-Admin-Token 后备(迁移期不破);config 加 jwt_secret(env JWT_SECRET,空 → register/login 返回 503 AUTH_DISABLED)+ jwt_expire_days;新依赖 pyjwt + bcrypt。坑:infra/postgres/init.sql 只在 Postgres 数据卷首次初始化跑 → main.py lifespan 加幂等 CREATE TABLE IF NOT EXISTS users(非致命 try/except)兼容现有库。web(lib/auth.ts):zustand store 只持久化 token(localStorage key raguide-auth),user 靠 /me hydrate 重取、密码不入 state;AppSidebar 6 个管理入口包 {isAdmin && ...}(可观测 / KB / 模型设置 / 画像参数 / 评测候选 / 评测集),非 admin 隐藏;AuthDialog 过 ui-ux-pro-max。iOS(Auth.swift):AuthTokenStore(JWT 存 Keychain,service raguide.auth)+ @MainActor AuthStore 单例;SideMenu 账户区 + 管理段 if auth.isAdmin(注:iOS 会话本地存储,故「会话跨端同步」在 iOS 不适用,画像 / Langfuse 才跨端归一)。配套:会话按用户隔离(web owner-scoped React Query key ["conversations", ownerKey] + 身份切换 reset;iOS ConversationStore.switchOwner 按 owner 分文件存,commit 2193b0f);Langfuse user_id 重设计(acct:<username> / guest:<device>,与 data-scoping owner_id 分离,commit 4daae9a);Google 式字母头像(确定性底色 + 白色首字母,web+iOS 跨端同色,对比 ≥4.5:1,commit 0038d9e);Gold-set 浏览器后端只读端点(GET /v1/admin/eval/gold-set,加载 5 类别 YAML 扁平化、admin-gated,commit f75db75)。 |
| 用户账户自管理(头像 / 昵称 / 改密)+ 密码强度 | ✅ 已交付(后端 bc66559 / web b366703 / iOS b0867a8;已测 + 后端 live 重启) |
在原「仅登录 / 注册」之上补齐三端自助账户管理。后端(api/auth.py + config.py + main.py + init.sql):users 表新增 display_name(昵称,nullable)+ avatar_url(nullable),经 lifespan 幂等 ALTER TABLE ... ADD COLUMN IF NOT EXISTS + init.sql(新卷)加列,/me 与 login 均返回二者;新增 Bearer 鉴权端点 PATCH /v1/auth/me(改昵称,trim、空→null、≤40 字)、POST /v1/auth/change-password(先校验当前密码,错则 403;新密码过强度校验,弱则 422;bcrypt 重哈希)、POST /v1/auth/avatar(multipart file,仅 PNG/JPEG/WebP、≤2 MB)。头像存储:用一个持久化的后端 static 目录经新公开挂载 /static/avatars 提供(非 minio——minio bucket 1 天自动过期,而 <img> 标签带不了 JWT 故字节须公开,与 seed-images / eval-fixtures 同模式);avatar_url 带 ?v=<ts> 缓存击穿。密码策略强化:register + change-password 共享 _validate_password_strength,要求长度 ≥ 8 且至少一字母一数字;register + change 须二次确认(client-side 强制),login 保持宽松不锁既有账号。web(apps/web):新 components/sidebar/AccountDialog.tsx(点侧栏头像打开)—— 头像上传(client 端 2MB/类型预检 + 字母头像兜底)/ 昵称编辑 / 只读用户名 / 角色徽章 / 改密(当前 + 新 + 确认、明暗切换、行内强度提示、不一致阻断提交)/ 登出;lib/auth.ts 加 display_name/avatar_url、isStrongPassword、updateProfile/changePassword/uploadAvatar(成功刷新 store);注册表单加确认密码 + 强度门禁;过 ui-ux-pro-max。iOS(apps/ios/RaguideMobile):新 AccountView.swift(从抽屉账户行 push)—— 头像(AsyncImage + 字母头像兜底 + PhotosPicker 上传,降采样 ~256px JPEG)/ 昵称 / 只读用户名 / 角色 / 改密(当前 + 新 + 确认、明暗切换、强度、不一致)/ 登出(两段式 inline 确认);Models.swift AuthUser 加 display_name/avatar_url,Backend.swift 加 avatarURL + updateProfile/changePassword/uploadAvatar(multipart);注册加确认 + 强度。验证:后端 tests/api/test_auth.py 31 passed(+9:强度字母/数字、PATCH 昵称设置/清空/超长、改密成功/当前密码错 403/弱 422/鉴权、头像成功/非图片 422/鉴权);web tsc 0 错、biome clean、vitest 291 passed;iOS xcodebuild ** BUILD SUCCEEDED **。诚实说明:早先创建的账号 display_name/avatar 为 null(UI 兜底用户名 + 字母头像);login 密码策略保持宽松(仅 register/change 强制新强度),既有弱密码仍可登录;头像持久化在后端宿主 static 目录(dev / 作品集语境)。 |
本项目的所有优化由 75 例 gold-set(happy 18 / edge 14 / error 13 / adversarial 16 / regression 14,5 类别)的 5 维度加权评测(task_completion 30% + output_quality 30% + process_quality 20% + efficiency 10% + safety 10%)驱动:每次优化记录「触发信号 → 改动 → 实测前后分数」,baseline 只在干净全量验收后更新。设计文档见
docs/superpowers/specs/。
| # | 日期 | 优化 | 触发(评测信号) | 关键改动 | 实测结果 |
|---|---|---|---|---|---|
| 1 | 2026-06-01 | M4 finding-024 工具循环修复 | 评测暴露 agent 工具调用自 M2b 起从未真正执行(async-generator 原地 mutate 不进 LangGraph channel,旧分数全部虚高作废) | 全部节点改为 RETURN state delta(commit b3d0118) |
首个有意义 baseline v1:weighted 0.712(efficiency 0.291 / safety 0.819),71 例 |
| 2 | 2026-06-10 | Pre-M9 细节补全批次 | v1 baseline 暴露 efficiency / safety 短板;4 文档审计发现 11 项「设计≠代码」缺口 | spec_query_sql 接真 Postgres、chitchat 跳检索、F3 覆盖度 + F5 规则打分、Anthropic prompt caching、记忆 L0/L1/L4、大表行级 chunk 等 |
baseline v2:weighted 0.712 → 0.789(efficiency 0.291→0.535,safety 0.819→0.972) |
| 3 | 2026-06-11 | 评测方法论修正(睡眠污染) | 全量评测 GATE FAILED(0.717),但 6 个 0 分案例中 4 个 ReadTimeout 由机器睡眠掐断连接制造 | 评测 SOP:caffeinate 防睡眠 + 污染数据不更新 baseline;数学拆解证明非错误 65 例持平 |
干净重跑确证 4 个超时为假象——评测基础设施与被评系统同样需要工程化 |
| 4 | 2026-06-11 | P1 空输入鲁棒性 | error_005("")/ error_103(" ")把空 content 发给 LLM → provider 400,整例 0 分 |
三层防御:graph 入口短路 clarify_node(零 LLM)+ adapter LLMContentError 出站守卫 + UserInput 422(merge a2f6a22) |
2026-06-12 干净验收:GATE PASSED,weighted 0.795,error 类 0.708→0.858,safety 1.000 |
| 5 | 2026-06-13 | P3 efficiency + grounding | efficiency 0.514 最弱维度;judge 点名「编造商品」——运行时 emit_cards 白名单(evidence ∪ 工具输入)宽于评测 F5(仅 evidence),模型钻政策裂缝 | 证据增广(工具验证产品写回 evidence channel)统一三方 grounding 口径 + emit_cards 仅-evidence + prompt 工具预算纪律(5 轮迭代见下表)+ budget schema 解钳(le 100k→1M)+ --cases 评测子集闭环 |
全量验收 GATE PASSED:weighted 0.789 → 0.838(+0.050);process_quality 0.876→0.966、output_quality 0.701→0.750、task_completion 0.842→0.885、safety 1.000、efficiency 0.535→0.544;最差案例 0.375→0.635;「编造」类负面评语 71 例剩 3 例(零编造目标未完全达成,如实记录):edge_002 经终态 dump 证伪(pid 确在 evidence,judge 看不到工具输出内的规格数字)、happy_100 / regression_105 属同一 judge 可见性盲区——候选修复(backlog):tool-evidence snippet 嵌入关键规格摘要。baseline v3 = 0.838(git c98987f) |
迭代集 = 最差 5 例(edge_002/003/004、regression_004/005)+ 3 对照(happy_001、error_003、adversarial_009);每轮 --cases 子集跑分后按 judge 评语微调 prompt,单独 commit 可回滚。
| 轮次 | 日期 | 改动 | 子集结果 |
|---|---|---|---|
| 1 | 2026-06-12 | 行为验证基线(T1–T6 代码改动后首跑,prompt 未再调) | regression_004 0.478→0.851、regression_005 0.399→0.814、edge_004 0.403→0.609(grounding 增广 + 抽样纪律生效:「工具调用仅 3 次未出现循环」「cards 仅含已验证两款」);edge_002 0.375→0.443 / edge_003 0.384→0.422(仍撞 iter≥5 与 same_tool≥3 规则罚分——prompt「至多 3 款」恰好踩 _SAME_TOOL_CAP=3 触发线);adversarial_009 回归至 0.33(budget 解钳副作用:注入语境的 9999999 预算被照单提取,违反 must_not_inflate);happy_001 0.800 持平,error_003 0.520 为先前已存在的「单词 query 应追问」缺口(非本批引入) |
| 2 | 2026-06-12 | 工具预算规则收紧(总数 ≤4 / details ≤2 / 证据已覆盖不重复验证 / 卡片交付优先)+ intent 注入语境槽位清零 + 预算异常首行 584c3fc;依据 = 轮 1 + edge_002 终态 dump:5 次迭代把 emit_cards 挤出上限致 cards 为空、3 次 details 中 2 次冗余) |
子集加权 0.599 → 0.795;process_quality 0.44→0.975;edge_002 0.443→0.807、edge_003 0.422→0.722、edge_004 0.609→0.849、adversarial_009 0.330→0.759(注入预算修复);对照组持稳(happy_001 0.831 / regression_004 0.853 / regression_005 0.811)。新副作用:预算 |
| 3 | 2026-06-12 | 候选全覆盖 + 预算提示唯一 + 价格存疑标注 + 拒绝指定模型(commit 5f13a1b) |
子集 0.795 → 0.750 回落——过度调参实证:「每款必须覆盖」反噬(edge_004 0.849→0.680,模型为未深查款编规格触发「编造风险」评语);emit_cards 义务被新增规则稀释(edge_003 / regression_004 cards 为空); |
| 4 | 2026-06-13 | 外科手术修正轮 3 副作用:候选覆盖弱化为一句话点名 + 预算 7345d67) |
子集 0.750 → 0.766:edge_003 0.646→0.837( |
| 5 | 2026-06-13 | 最小回退收官:覆盖句恢复轮 2 原文(评语收敛判停,保留轮 3/4 验证有效项:价格存疑标注 / 模型调度说明 / c98987f) |
全量 71 例验收 GATE PASSED,weighted 0.838。迭代集回查(06-12 基线 → 验收):edge_002 0.375→0.669、edge_003 0.384→0.844、edge_004 0.403→0.856、regression_004 0.478→0.812、regression_005 0.399→0.712;对照组 happy_001 0.878 / adversarial_009 0.834 / error_003 0.635(descope 项)。详见上表 #5 行 |
┌──────────────────────────────────────────────────────────────────┐
│ Web Client (Next.js 15) [M5 ✅] │
│ 流式聊天 UI + 商品卡片 + 对比卡片 + 图文输入 │
└────────────────────────────┬─────────────────────────────────────┘
│ HTTPS + SSE
▼
┌──────────────────────────────────────────────────────────────────┐
│ FastAPI Backend (Port 8000) │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ LangGraph StateGraph (Orchestrator) │ │
│ │ │ │
│ │ START → orchestrator → intent → retrieval → advisor │ │
│ │ ↑ ↓ │ │
│ │ └─ tool_dispatch ←──┘ │ │
│ │ ↓ │ │
│ │ END │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────┼──────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌────────────────────┐ ┌──────────────────┐ │
│ │ LLM Gateway │ │ Retrieval │ │ Tools Layer │ │
│ │ Ports & │ │ (M2c Modular RAG │ │ 4 tools wired │ │
│ │ Adapters │ │ 6-stage pipeline) │ │ (see §工具) │ │
│ └──────┬──────┘ └──────┬─────────────┘ └──────────────────┘ │
└─────────┼────────────────┼──────────────────────────────────────┘
│ │
┌───────┴───────┐ ▼
▼ ▼ ┌─────────────────────────────────┐
newapi proxy DeepSeek│ Qdrant 1.13 │
(sonnet/opus) (扩展点)│ ├─ products_text (bge-m3 1024d)│
│ └─ products_image (JinaCLIP │
│ 1024d, 跨模态) │
│ Tantivy svc :7700 (BM25) │
│ TEI svc :7997 (bge-reranker) │
│ SearXNG :8080 (CRAG fallback) │
│ PostgreSQL 16 / Redis 7 │
└─────────────────────────────────┘
↑
┌──────────────────────┐
│ KB Ingestion (离线) │
│ M2c demo seed_kb + │
│ M3 真 Docling 管道 │
└──────────────────────┘
* M2b 已交付:5 LangGraph nodes, 4 tools, 8 SSE events
* M2b-Obs 已交付:Langfuse 3 trace + 5 维度 AgentEvaluator + Ragas + 50 gold-set + CI eval gate + 8 面板 Grafana
* M2c 已交付:Modular RAG 6 阶段(Pre-Retrieval / 3-way Retrieval / RRF / Reranker+Compression / Self-Eval Loop / CRAG),+13 SpanHook steps,+7 Prom metrics,+4 Grafana panels
* 当前 **后端 889 passed(含认证 22 测;CI 默认 = 不含 integration/e2e);eval 包 51 + kb-ingestion 包 45;前端 web 254 vitest**(M2c close 396 → M6-M10 + 认证增量)
* M6 KB 在线管理 / M7 LLM 模型配置 / M8 用户画像持久化 / Pre-M9 细节补全 / M10 iOS 客户端 / 用户认证 + RBAC + 统一身份 均已交付(见 Roadmap)
| 层 | 选型 | 版本 / 说明 |
|---|---|---|
| 后端语言 | Python 3.12 + uv | uv 包管理,比 pip/poetry 快 10-100× |
| Web 框架 | FastAPI | 0.115+,异步原生,原生 SSE 支持 |
| Agent 编排 | LangGraph | 0.2+,StateGraph + 条件边;当前未启用 Checkpointer——多轮记忆走「客户端持有历史 + Working-Memory 锚点」,详见 §多轮对话记忆 |
| LLM(Advisor / Intent) | Claude Sonnet 4.6 | via newapi proxy(SONNET_API_KEY) |
| LLM(Judge) | Claude Sonnet 4.6 | via newapi proxy(SONNET_API_KEY);T17.5 起从 Opus 4.7 切换 — newapi 对 Opus 4-系列强制 temperature=1.0 破坏判定稳定性,详见 llm.yaml。anthropic_opus provider 仍注册可未来切回 |
| LLM 抽象 | 自研 Ports & Adapters | 非 LiteLLM;Protocol-based + Adapter + FallbackChain |
| 向量库 | Qdrant 1.13+ | 自托管 Docker;双 collection — products_text (bge-m3 1024d) + products_image (JinaCLIP 1024d);M2c 后均已激活 |
| 关系库 | PostgreSQL 16 + asyncpg | 商品元数据 + 结构化规格双列 |
| Embedding | bge-m3 | 自托管,1024d,多语言,稠密+稀疏+ColBERT 三合一 |
| Reranker | bge-reranker-v2-m3 | M2c 已交付;HF Text Embeddings Inference (TEI) Docker 服务(host port 7997);top-20 → top-5 cross-encoder |
| BM25 | Tantivy | M2c 已交付 docker 服务(host port 7700);FastAPI+tantivy-py wrap;jieba 中文分词(client side) |
| 跨模态 Embedding | JinaCLIP-v2 | M2c 已交付;865M 模型 in-process 单例(双 check lock);文本/图像共享 1024d 空间 |
| 缓存 | Redis 7 | LLM 响应缓存 |
| Web 搜索 | SearXNG | 自托管;M2c 已激活作为 CRAG fallback(rewrite → /search → top-3 → Evidence(source="web")) |
| 可观测 | Langfuse 3.x 自托管 + Prometheus + Grafana | M2b-Obs 已交付;9 字段 SpanFields;prometheus-fastapi-instrumentator |
| 评估 | Ragas 0.2+ + 自研 AgentEvaluator 5 维度 | M2b-Obs 已交付;CI eval gate + 50 case gold-set |
| 前端(M5 已交付) | Next.js 15 / React 19 / Vercel AI SDK 6.x / shadcn-style(base-ui) / Tailwind 4 | TypeScript 5.5+ |
raguide 在 macOS / Linux / Windows 上都能跑。所有路径用 pathlib、配置只读 .env(不依赖 .zshrc / .bash_profile / PowerShell $PROFILE)。
Windows 提示:推荐使用 WSL2,所有命令和 Mac/Linux 完全一致。如果坚持原生 PowerShell,下面各节给出对应命令。
| 工具 | 用途 | macOS | Linux | Windows |
|---|---|---|---|---|
| Python ≥ 3.12 | 后端 + 摄入 CLI | brew install python@3.12 |
apt install python3.12 |
https://python.org/downloads |
| uv | Python 包管理 | curl -LsSf https://astral.sh/uv/install.sh | sh |
同 macOS | powershell -c "irm https://astral.sh/uv/install.ps1 | iex" |
| Docker Desktop | 容器编排 | https://docker.com/products/docker-desktop | https://docs.docker.com/engine/install/ | https://docker.com/products/docker-desktop |
| Node.js ≥ 20 | Web 前端(M5) | brew install node@20 |
nvm install 20 |
https://nodejs.org/en/download |
| Git | 版本控制 | brew install git |
apt install git |
https://git-scm.com/download/win |
git clone git@github.com:JavaLyHn/raguide.git
cd raguide# macOS / Linux / WSL
cp .env.example .env
# Windows PowerShell
Copy-Item .env.example .env然后编辑 .env 填入 LLM 凭据。详见下面「LLM 配置」小节。
docker compose -f infra/docker-compose.yml up -d第一次会拉镜像(~6 GB),耐心等。
# macOS / Linux / WSL
cd apps/backend
uv run uvicorn raguide_backend.main:app --reload --port 8000
# Windows PowerShell
cd apps\backend
uv run uvicorn raguide_backend.main:app --reload --port 8000如果
.env缺少必要的 API key,uvicorn 会在启动时立刻抛RuntimeError(含可点击的.env路径),不会等到请求时才报错——这是设计意图。
cd apps/web
npm install
npm run dev浏览器打开 http://localhost:3000
raguide 使用 Anthropic SDK,通过 config/llm.yaml 做角色路由。当前默认走 newapi 代理,使用两个独立 API key(newapi 按 key 做模型隔离)。
编辑 .env:
SONNET_API_KEY=<newapi 给的 sonnet key>
OPUS_API_KEY=<newapi 给的 opus key>
ANTHROPIC_BASE_URL=https://newapi.elevatesphere.com
ANTHROPIC_BASE_URL不要带/v1后缀。Anthropic SDK 自己会追加/v1/messages。如果写成.../v1,SDK 会拼成/v1/v1/messages→ 404。raguide 启动时会自动检测并剥掉错误的/v1,但建议写对。
如果用官方 API(无代理),.env 改为:
ANTHROPIC_API_KEY=sk-ant-api03-...
ANTHROPIC_BASE_URL=同时修改 apps/backend/config/llm.yaml,将 anthropic_sonnet 和 anthropic_opus 两个 provider 都改用 api_key_env: ANTHROPIC_API_KEY。
pydantic-settings 优先级:OS env > .env > 默认值。
# macOS / Linux / WSL
export SONNET_API_KEY=...
export OPUS_API_KEY=...
export ANTHROPIC_BASE_URL=https://newapi.elevatesphere.com
# Windows PowerShell(当前 session)
$env:SONNET_API_KEY = "..."
$env:OPUS_API_KEY = "..."
# Windows PowerShell(持久化)
[Environment]::SetEnvironmentVariable("SONNET_API_KEY", "...", "User")M1 已完成,演示 RAG 全链路:PDF 摄入 → 向量检索 → 流式生成。
# 1. 确保 Qdrant + Postgres 在跑
docker compose -f infra/docker-compose.yml up -d qdrant postgres
# 2. 摄入 5 份 3C 商品 PDF(首次会下载 bge-m3 约 2GB,5-10 分钟)
uv run raguide-ingest --src data/m1/
# 3. 起后端
cd apps/backend
uv run uvicorn raguide_backend.main:app --port 8000 &
# 4. 发送问题
curl -N -X POST http://localhost:8000/v1/agent/run \
-H "Content-Type: application/json" \
-d '{"session_id":"demo","user_input":{"text":"小米 17 Pro Max 电池多大"}}'# 1. 起 Docker
docker compose -f infra\docker-compose.yml up -d qdrant postgres
# 2. 摄入
uv run raguide-ingest --src data\m1\
# 3. 起后端
cd apps\backend
Start-Process -NoNewWindow uv -ArgumentList "run", "uvicorn", "raguide_backend.main:app", "--port", "8000"
cd ..\..
# 4. 发送(PowerShell 内建,SSE 流不显示;建议用 curl)
Invoke-RestMethod -Method Post -Uri "http://localhost:8000/v1/agent/run" `
-ContentType "application/json" `
-Body '{"session_id":"demo","user_input":{"text":"小米 17 Pro Max 电池多大"}}'Windows + SSE:
Invoke-RestMethod不支持 SSE 流式显示。推荐安装 curl:winget install curl,然后使用 macOS 命令。
event: intent_done
data: {"slots":{"category":"phone","budget":null,"preferences":["battery"],"mentioned_products":["小米 17 Pro Max"],"intent_type":"spec_lookup","complexity":"simple"}}
event: retrieval_done
data: {"evidence":[{"product_id":"xiaomi-17-pro-max","score":0.747,"snippet":"...7500mAh..."},...]}
event: token
data: {"delta":"小米 17 Pro Max 搭载 **7500mAh** 大"}
event: token
data: {"delta":"电池,支持 **100W 有线快充 + 50W 无线快充**,是该系列容量最大的版本。\n\n—— 来自 xiaomi-17-pro-max.pdf p.1"}
event: done
data: {"usage":{"tokens_in":2551,"tokens_out":90,"cost_cny":0.063},"trace_id":"trc_..."}
M2b 完成后,完整的 5 节点 LangGraph 流水线已上线。
curl -N -X POST http://localhost:8000/v1/agent/run \
-H "Content-Type: application/json" \
-d '{"session_id":"demo","user_input":{"text":"5000 以内拍照好的手机"}}'最简路径(Advisor 认为检索结果已足够,无工具调用):
event: intent_done
data: {"slots":{"category":"phone","budget":5000,"preferences":["camera"],"mentioned_products":[],"intent_type":"recommend","complexity":"deep"}}
event: retrieval_done
data: {"evidence":[{"product_id":"vivo-x300-ultra","score":0.62,...},{"product_id":"xiaomi-17-pro-max","score":0.60,...},...]}
event: token
data: {"delta":"根据您的预算和拍照需求,为您推荐以下几款..."}
...(更多 token)...
event: done
data: {"usage":{...},"trace_id":"trc_..."}
含工具调用路径(Advisor 主动查详情或对比):
event: intent_done
data: {...}
event: retrieval_done
data: {...}
event: tool_call_started
data: {"tool_name":"compare_products","args":{"product_ids":["vivo-x300-ultra","xiaomi-17-pro-max"]}}
event: tool_call_done
data: {"tool_name":"compare_products","result":{...}}
event: card
data: {"kind":"compare","products":[...],"dimensions":[...]}
event: token
data: {"delta":"综合以上对比..."}
event: done
data: {...}
所有 4 个工具均已接入:get_product_details(Postgres + Qdrant 真实数据)、compare_products(真实,组合调用 get_product_details)、spec_query_sql(真实,Pre-M9 起查 Postgres product_specs 双列做数值硬约束过滤)、read_sop(真实,读取 docs/sops/*.md)。
| 事件名 | Payload 结构 | 何时发出 | 起始里程碑 |
|---|---|---|---|
intent_done |
{"slots": IntentSlots} |
IntentAgent 完成 json_schema 解析 | M2b |
retrieval_done |
{"evidence": [Evidence, ...]} |
RetrievalAgent 完成检索 | M1 |
tool_call_started |
{"tool_name": str, "args": dict} |
AdvisorAgent 发起工具调用 | M2b |
tool_call_done |
{"tool_name": str, "result": Any} |
工具执行返回 | M2b |
card |
{"kind": "product"|"compare", ...} |
compare_products 或 Advisor 生成卡片 | M2b |
token |
{"delta": str} |
AdvisorAgent 流式吐字(每个 token chunk) | M1 |
done |
{"usage": {...}, "trace_id": str} |
单轮对话结束 | M1 |
error |
{"code": str, "message": str, "recoverable": bool} |
任意节点异常 | M1 |
IntentSlots 结构:
{
"category": "phone|laptop|earphone|null",
"budget": 5000,
"preferences": ["camera", "battery"],
"mentioned_products": ["iPhone 16"],
"intent_type": "recommend|compare|spec_lookup|faq|unknown",
"complexity": "simple|deep"
}| 节点 | 职责 | 读取 State 字段 | 写入 State 字段 |
|---|---|---|---|
orchestrator |
路由入口,初始化 trace_id,校验输入 | user_query |
trace_id, started_at |
intent |
用 Claude Sonnet json_schema 解析用户意图,提取 6 维 IntentSlots;双重校验(Anthropic server + Pydantic client) | user_query, history |
slots |
retrieval |
M2c Modular RAG 6 阶段管道(详见 §Modular RAG 内层管道);签名保持 async def retrieval_node(state) -> state 不变;body 委托给 modular_pipeline.run();emit retrieval_done SSE |
slots, user_image_url? |
evidence, compressed_evidence, web_results, self_eval_*, crag_triggered, ... |
advisor |
Claude Sonnet 生成推荐,可在 tool-use loop 内多次调用工具(max 5 轮,同一工具 max 3 次);流式 emit token + card |
slots, evidence, history |
response, tool_calls, cards |
tool_dispatch |
执行单次工具调用,刷新 Working-Memory Anchor;根据结果决定回到 advisor 还是结束 | tool_calls[-1] |
tool_calls[-1].result, working_memory |
| 工具 | 类型 | Trigger 条件 | Exclusion 条件 |
|---|---|---|---|
get_product_details |
真实(Postgres + Qdrant) | 已知 product_id,需完整规格 | product_id 未知时 |
compare_products |
真实(组合调用) | 用户要求对比 2-3 款 | 仅 1 个候选时 |
spec_query_sql |
真实(Postgres product_specs 双列) |
硬约束过滤(电池≥5000mAh、价格≤6000 等数值约束,参数化 SQL 取交集) | 语义模糊查询 |
read_sop |
真实(读 docs/sops/) | 需要领域 SOP(话术/口径/对比规则) | 常识性回答 |
<working_memory>
当前用户意图: recommend / phone
对比中商品: vivo-x300-ultra | xiaomi-17-pro-max
已收集证据: 8 段检索 + 2 次工具
用户上传图摘要: (未上传)
图像证据命中数: 0
用户偏好痕迹: camera · 预算 ≤5000元
</working_memory>设计意图:多轮对话中 LLM 容易忘记早期偏好。Working-Memory Anchor 不依赖完整 history,通过每次工具返回末尾(注入到最后一条 tool_result)刷新焦点状态来缓解遗忘(借鉴 GenericAgent 设计 ②)。这 6 块固定字段由 agent/working_memory.py 组装,完整机制见 §多轮对话记忆。
- MAX_TOOL_ITERATIONS = 5:防止 Advisor 无限工具调用循环
- SAME_TOOL_CAP = 3:同一工具最多调用 3 次(防重复)
- json_schema 双重校验:Anthropic server 强制 schema + Pydantic client 二次校验,prompt injection 在 IntentAgent 层直接被过滤为
null字段 - 业务异常 vs 基础设施异常分离:
ToolError(可重试)vsInfraError(直接 error 事件)
raguide 当前采用 「客户端持有历史 + 无状态后端 + Working-Memory 锚点」 的记忆架构,未启用 LangGraph Checkpointer。分三层:
- 前端
useChat(Vercel AI SDK 6.x)维护messages数组(apps/web/app/page.tsx)。 - 自研
RaguideChatTransport每轮把「最新 user 文本 + 完整历史history[]」一起 POST 到/v1/agent/run(apps/web/lib/transport.ts)。 - 后端 Advisor 每轮重建消息列表,最多取最近 20 轮,无摘要(
agent/advisor.py的history[-20:])。 session_id(前端 UUID)仅用于日志 / 反馈追踪,不用于状态恢复。- → 后端完全无状态;"记忆"实体在前端,逐轮整体重发。
工具循环(Self-Eval loop,最多 2 轮)中,每次工具返回后把 <working_memory> 块注入到最后一条 tool_result 消息(agent/working_memory.py + agent/advisor.py)。固定 6 块:当前意图 / 对比中商品 / 已收集证据 / 用户上传图摘要 / 图像命中数 / 偏好痕迹·预算。让 LLM 在每次工具返回后重读累积焦点,缓解长上下文遗忘。格式见上文 §Working-Memory Anchor。
-
conversations表(PostgreSQL,messagesJSONB,匿名owner_id)保存 / 恢复整段对话(api/conversations.py,M5.1 交付)。 -
切换会话时
GET /v1/conversations/{id}→setMessages全量还原。 -
用户画像(跨会话偏好学习,已实现):按
owner_id持久化时间衰减的偏好画像(user_profiles表 +agent/user_profile.py)。done_hook每轮异步把slots合并进画像(指数半衰期计数);intent_node用画像补全空缺槽位(本轮明说优先),working_memory注入「历史画像」块。参数(半衰期 / Top-N / 守卫阈值 / 品牌白名单)经 admin「画像参数」面板在线可调(profile_config表 + 热加载)。用户可在「设置」查看 / 清除自己的画像(GET/DELETE /v1/me/profile)。设计见docs/superpowers/specs/2026-06-09-user-profile-persistence-design.md。 -
5 层记忆(L0–L4)已基本落地(Pre-M9 批次):L0 失败 case 候选池 + 人工确认门禁(
done_hook低分入池 → admin「评测候选」面板 approve → 写human_verifiedgold-set);L1 商品类目大纲常驻注入(kb/catalog_outline.py,热加载);L2 Working-Memory 锚点 + 用户画像;L3 Modular RAG 向量召回;L4 对话摘要压缩(超 12 轮即时摘要,替代硬截断)。
| 设计(CLAUDE.md §5 / umbrella spec) | 现状 |
|---|---|
| 统一「5 层」记忆抽象 | L0–L4 各层均已落地(见上),但仍是离散实现,无单一 MemoryManager 抽象层(YAGNI,可不做) |
| LangGraph Checkpointer(thread_id 恢复) | 不采用(有意做无状态后端) |
| 完整大表父子检索(MultiVectorRetriever) | 仅最小版(表格行级 chunk + 模板前缀 capability 已建+测);MultiVectorRetriever + LLM Contextual 前缀 + 摄入路径接线待续 |
设计取舍:无状态后端便于水平扩展(无 session 亲和性要求),历史真值在前端、跨会话持久化交给
conversations表 +user_profiles画像表。L0–L4 五层记忆已落地(L4 用即时摘要替代了原 20 轮硬截断);仅「统一抽象层」与 checkpointer 是有意未做的取舍——面试时主动说清这条"现状 vs 设计"边界。
RetrievalAgent 内部 6 阶段流水线 — Pre-Retrieval → 3-way Retrieval → RRF Fusion → Post-Retrieval → Self-Eval Loop → CRAG fallback:
用户问题
↓
┌─ 1. Pre-Retrieval (Branching, intent-conditional) ──────────┐
│ IntentSlots → router → 选一支: │
│ • HyDE (短/模糊 query, Sonnet 4.6 → 假设性回答) │
│ • Multi-Query (长 query 多面, Sonnet 4.6 → 3 个变体) │
│ • Decompose (compare ≥2 产品, 纯 Python 拆分) │
│ • passthrough (chitchat / unknown) │
└────────────────────────────────────────────────────────────┘
↓ asyncio.gather (per-path 2s timeout, 失败不阻塞)
┌─ 2. Retrieval (Branching, 3-way concurrent) ────────────────┐
│ • BM25 :7700 (Tantivy + jieba 中文分词) │
│ • Dense Qdrant (bge-m3 1024d, products_text) │
│ • Image Qdrant (JinaCLIP-v2 1024d, products_image, │
│ activate when state.user_image_url ≠ "")│
└────────────────────────────────────────────────────────────┘
↓
3. Fusion (RRF k=60) — chunk_id dedup, max-score keep, top-20
↓
┌─ 4. Post-Retrieval (Linear) ───────────────────────────────┐
│ 4.1 Reranker (TEI :7997, bge-reranker-v2-m3) → top-5 │
│ 4.2 Compression (Sonnet 4.6 json_schema, ≤200 字符/chunk, │
│ reject hallucinated chunk_id) │
└────────────────────────────────────────────────────────────┘
↓
┌─ 5. Self-Eval Loop (Looping, max 2 轮) ─────────────────────┐
│ 5.1 rule (top≥0.7 ∧ count≥3 → 1.0) │
│ 5.2 llm (rule 没过 → Sonnet 4.6 仲裁 │
│ {enough, has_clues, missing_aspects}) │
│ verdict 路由: │
│ • enough=True → finish (score=1.0) │
│ • !enough, has_clues, iter<2 → retry_with_focus (0.0) │
│ • !enough, has_clues, iter=2 → finish_degraded (0.4) │
│ • !enough, !has_clues → CRAG ↓ │
└────────────────────────────────────────────────────────────┘
↓
┌─ 6. CRAG Fallback (Conditional) ───────────────────────────┐
│ Sonnet 4.6 rewrite (json_schema, ≤100 char web query) │
│ → SearXNG :8080 /search → top-3 │
│ → Evidence(source="web", chunk_id="web_0..2") │
│ Advisor system prompt 末追加 §7 网络检索补充规则 │
│ (强制 "经查询 [年月]" 引用前缀) │
└────────────────────────────────────────────────────────────┘
↓
state["evidence"] = state["compressed_evidence"] (或 web_results 若 CRAG)
→ AdvisorAgent
| # | 决策 | 选择 |
|---|---|---|
| Q1 | scope | 一锅端 28 task / 单 milestone |
| Q2 | KB 数据 | M2c 内嵌 demo seed(5 产品 × 6-10 chunk + 5 图),M3 真 Docling 替换 |
| Q3 | BM25 实现 | Tantivy 独立 docker service(非 Qdrant 原生 sparse),严格按 spec |
| Q4 | JinaCLIP | 进 scope + 5 CC0 placeholder 图 |
| Q5 | Self-Eval | Hybrid 规则粗筛 + LLM 细筛(非纯 LLM 也非纯规则) |
| Q6 | Pre-Retrieval | 3 个分支全上 + intent-conditional 路由(非并跑所有) |
| Q7 | CRAG | 最小可行闭环(rewrite → SearXNG → 3 results;无 full-page scrape;无 DuckDuckGo Plan B) |
| Q8 | Reranker 部署 | TEI Docker(非 in-process) |
- Panel 9 Retrieval pipeline latency p95 by step(13 个 step 标签:pre_retrieval.hyde / retrieval.bm25 / fusion.rrf / post.rerank / self_eval.llm / crag.search …)
- Panel 10 Self-Eval verdict distribution(finish / finish_degraded / retry_with_focus / crag stacked)
- Panel 11 CRAG fallback frequency(rate stat, 阈值 green/yellow/red @ 0.01/0.05)
- Panel 12 Recall@5 trend(gold-set 跑 eval 写入的 gauge)
新加 7 个 Prom 指标:raguide_retrieval_latency_seconds(Histogram by step+status)、raguide_retrieval_recall_at_5(Gauge)、raguide_self_eval_decisions_total(Counter by verdict)、raguide_self_eval_iterations_total(Counter by iter)、raguide_crag_fallback_total(Counter)、raguide_fusion_dedup_ratio(Gauge)、raguide_rerank_score_delta(Histogram, buckets 0/1/2/3/5/10/20)。
agent.self_eval — done_hook 在 state.self_eval_score 非空时通过 langfuse_client.create_score() 推送。不进 5 维 AgentEvaluator 加权(CLAUDE.md Rule #3 LOCKED:task_completion 30% + output_quality 30% + process_quality 20% + efficiency 10% + safety 10% 不变)。
LLMProvider (Protocol, PEP 544)
├── stream_chat(messages, tools, system_prompt, ...) -> AsyncIterator[StreamEvent]
├── supports(feature: str) -> bool
└── estimate_cost(tokens_in, tokens_out) -> float
↓ implements
AnthropicAdapter ← v1 唯一路由(via SONNET/OPUS key + newapi proxy)
OpenAICompatibleAdapter ← Template Method base(骨架:build_payload + parse_stream)
└── DeepSeekAdapter ← 已注册(ProviderRegistry),不路由(扩展点演示)
ProviderRegistry (Factory) ← 从 llm.yaml 加载,启动时验证所有 role→provider 映射
FallbackChain (CoR) ← [anthropic_sonnet → anthropic_opus],指数退避 1s/2s/4s
4 个设计模式协同:
| 模式 | 体现 |
|---|---|
| Adapter | 各家 SDK → 统一 LLMProvider Protocol 接口 |
| Template Method | OpenAICompatibleAdapter 定义流式归一化骨架;子类只填 base_url / model_id |
| Strategy | YAML 配置 roles.advisor.provider: anthropic_sonnet 做运行时路由 |
| Chain of Responsibility | FallbackChain(primary, *fallbacks) 主路失败自动降级,无需调用方感知 |
5 类 LLMError 树:
LLMError (base)
├── TransientLLMError ← 网络抖动,FallbackChain 自动重试
├── RateLimitLLMError ← 429,指数退避后重试
├── AuthLLMError ← 401/403,启动时 fail-fast,不重试
├── SchemaValidationError ← json_schema 不合 schema,记 trace span error
└── UpstreamLLMError ← 500/502,对外 error 事件
# 单元测试(CI 默认 = 不含 integration/e2e,889 个后端单测;前端另有 254 web vitest)
uv run pytest -m "not integration and not e2e"
# 集成测试(需要 Docker 起 Postgres + Qdrant,约 10 秒)
uv run pytest -m integration
# E2E 测试(需要 .env 真实 API key,约 40 秒,消耗约 ¥0.05)
uv run pytest -m e2e测试覆盖分布(下表为 M2c 收尾时的 396 单测分布;M6-M10 + 认证增量后后端共 889 单测(含认证 22 测)、前端 254 web vitest、eval 包 51 + kb-ingestion 包 45):
| 层 | 来源里程碑 | 测试数 | 说明 |
|---|---|---|---|
| LLM + Agent 单元 | M1/M2a/M2b | ~191 | json_schema 校验、Tool dispatch cap、Working-Memory、Adversarial (prompt injection / SQL / 路径遍历) |
| Observability 单元 | M2b-Obs + M2c | ~35 | LangfuseSpanHook 18 step 注册(5 M2b + 13 M2c)、tokens_capture per-trace counter、Prom metrics 13 个指标 |
| Eval pipeline 单元 | M2b-Obs | ~30 | AgentEvaluator 5 维度、Judge JSON schema、Ragas runner、ci_gate 双门禁、gold-set GoldCase schema |
| Modular RAG 单元 | M2c | ~125 | Pre-Retrieval(HyDE/Multi-Query/Decompose/router 24)+ 3 路 Retrieval(Tantivy/dense/image/fanout 16)+ RRF(7)+ Post(reranker/compression 11)+ Self-Eval(rule/llm/loop 19)+ CRAG(fallback/searxng 9)+ Integration(pipeline 5)+ Obs(m2c_obs 5)+ Seed(kb/images 9) |
| Workflow YAML lint | M2b-Obs | 2 | .github/workflows/*.yml 顶层 key 防漂移 |
| 集成 | M1/M2b | 3 | KB fetchers + lifespan boot |
| E2E | M1/M2b | 3 | M2b recommend + M2b compare + M1 regression(真 API) |
**M2c 新增的 Modular RAG 测试(~125 个)**包括:HyDE/Multi-Query json_schema + 6 元素 prompt + 拒幻觉 chunk_id(compression Q3)+ 3 路 retrieval graceful degradation + RRF k=60 + dedup 比 + reranker rank-delta + Self-Eval rule fast-path + LLM verdict 矩阵 + CRAG rewrite/<script> 过滤 + 4 verdict 路由(finish/retry/finish_degraded/crag)+ retrieval_node 签名保持。3 类新 adversarial:Pre-Retrieval 注入 / 图片隐藏文本 / CRAG web 污染。
| 命令 | 来源里程碑 | 用途 |
|---|---|---|
make langfuse-up |
M2b-Obs | 启动 Langfuse 自托管 docker-compose(ClickHouse + Postgres + MinIO + Worker + Web,6 容器,Web UI 默认 http://localhost:3001) |
make langfuse-down |
M2b-Obs | 停止 Langfuse 全部容器 |
make langfuse-logs |
M2b-Obs | 跟踪 Langfuse Web/Worker 日志 |
make langfuse-status |
M2b-Obs | Langfuse 各容器健康状态 |
make eval-gold |
M2b-Obs | 跑 50 条 gold-set → Ragas 4 指标 + 5 维度 AgentEvaluator + 双门禁;本地需先 make eval-infra 起 pg/qdrant/redis |
make eval-baseline |
M2b-Obs | 重置 tests/gold_set/_baseline.json(intentional 行为变更后用) |
make eval-infra |
M2b-Obs | 起本地 eval 三件套(pg + qdrant + redis) |
make eval-infra-down |
M2b-Obs | 关本地 eval 服务 |
make ci-check |
M2b-Obs | 本地复现 CI sweep(ruff + pytest) |
make m2c-infra-up |
M2c | 起 Modular RAG 全栈(qdrant + postgres + redis + searxng + tantivy-server :7700 + tei-reranker :7997) |
make m2c-infra-down |
M2c | 仅停 M2c 新增的 tantivy + tei(共享 infra 不动) |
make m2c-seed |
M2c | 跑 scripts/seed_kb_demo.py:5 产品 × 6-10 chunk + 5 图 → Qdrant text/image + Tantivy + Postgres |
make eval-langfuse-dataset |
评测可观测化 | 把 75 例 gold-set YAML 镜像成 Langfuse Dataset raguide-gold-set(仅 items,item id=case_id 幂等;YAML 仍是唯一真值) |
make eval-dataset-run |
评测可观测化 | 跑 gold-set 并用 item.run() 把每例结果注册为 Langfuse dataset run + 挂回 5 维 / 加权 goldset.* score(跨 run 可比;不传 --ragas,Ragas 因依赖冲突 deferred) |
CI Eval Gate(.github/workflows/eval.yml)当前为 manual workflow_dispatch trigger(per Run #8 secret-config issue resolved by switching trigger)— 想跑就到 Actions 页面手动点 Run workflow。
依据 spec:
| Variable | Required for | Default | Notes |
|---|---|---|---|
LANGFUSE_HOST |
trace | http://localhost:3001 |
UI host port from infra/docker-compose.langfuse.yml |
LANGFUSE_PUBLIC_KEY |
trace | unset → no-op | Created in Langfuse UI; pk-lf-... |
LANGFUSE_SECRET_KEY |
trace | unset → no-op | Created in Langfuse UI; sk-lf-... |
EVAL_ENABLED |
prod async eval | true |
Set false in CI/e2e to avoid duplicate judge spend |
EVAL_SAMPLE_RATE |
prod async eval | 1.0 |
Float 0..1; production sampling |
When the Langfuse keys are absent the LangfuseClient.get() returns None
and all hooks no-op — backend stays fully functional without observability.
.github/workflows/eval.yml runs all 50 gold-set cases on every PR (gate
enforcement) and on every push to main (baseline auto-update on PASS).
It requires the following repo secrets:
SONNET_API_KEY— required (judge LLM is Sonnet 4.6 since T17.5; see CLAUDE.md §4)OPUS_API_KEY— required only for Ragas runner (LangchainLLMWrapper currently points at Opus)ANTHROPIC_API_KEY— fallback / unified key when not using the newapi proxyANTHROPIC_BASE_URL— required when proxying through newapi
PR runs evaluate against the current main baseline. Main pushes update the baseline on PASS (auto-commit by github-actions[bot]).
Each run executes 50 cases × 1 judge call = ~50 Sonnet 4.6 invocations. Typical cost: $0.10–$0.30/run. Set
EVAL_SAMPLE_RATEto throttle in dev.
(EVAL_SAMPLE_RATE is the production-eval sampling knob in the backend;
it does not affect CI eval, which always runs all 50. The note is informational only.)
.env 还是占位符(或缺少 SONNET_API_KEY)。打开错误消息里的绝对路径,填入真实 key。详见「LLM 配置」。
ANTHROPIC_BASE_URL 带了 /v1 后缀。改为不带 /v1 的根 URL(如 https://newapi.elevatesphere.com)。
sentence-transformers 缓存目录权限或网络问题。
- macOS / Linux:检查
~/.cache/huggingface/hub/可写 - Windows:检查
%USERPROFILE%\.cache\huggingface\hub\可写 - 中国大陆:可设
HF_ENDPOINT=https://hf-mirror.com走镜像
Docker Desktop 必须在前台启动(鲸鱼图标 menubar 显示绿色)。首次在 WSL2 下需手动启用 integration。
Start-Process 后用 Get-Process uv | Stop-Process,或直接关 PowerShell 窗口。
已知问题:ClickHouse healthcheck 用 localhost 会解析到 IPv6。raguide M0 的 docker-compose.yml 已修复(用 127.0.0.1)。更新到 main 最新即可。
这是正确的。newapi 代理当前只暴露 sonnet-4-6 和 opus-4-7,haiku-4-5 不可用。因此 intent 和 advisor 两个角色都路由到 claude-sonnet-4-6(见 config/llm.yaml)。当 newapi 暴露 haiku 或切换到官方 Anthropic key 时,intent 角色可降级到 haiku 以节省约 10× 成本——只需改 llm.yaml,代码零改动。
M2b-Obs 已交付。 起本地 Langfuse 即可:
make langfuse-up
# 等 60 秒让 ClickHouse + Postgres 初始化
open http://localhost:3001 # 创建 org/project + 拿 pk-lf-... / sk-lf-... key
# 把两个 key 写进 .env 后重启后端X-Trace-ID HTTP 响应头会带 32 char OTel hex trace_id,直接到 Langfuse UI 搜该 id 看完整 span 树(含 9 字段 metadata + LLM-as-Judge 5 维度 score + Ragas 4 指标 score)。
raguide/
├── apps/
│ ├── backend/ # FastAPI + LangGraph
│ │ ├── src/raguide_backend/
│ │ │ ├── agent/ # 5 LangGraph nodes + tools + prompts
│ │ │ │ ├── orchestrator.py # 路由入口,trace_id 初始化
│ │ │ │ ├── intent.py # IntentAgent + json_schema 双重校验
│ │ │ │ ├── retrieval.py # RetrievalAgent(M1 dense;M2c 扩展)
│ │ │ │ ├── advisor.py # AdvisorAgent + tool-use loop
│ │ │ │ ├── tool_dispatch.py # 执行工具 + Working-Memory 刷新 + 安全 cap
│ │ │ │ ├── working_memory.py # Working-Memory Anchor 构建
│ │ │ │ ├── graph.py # StateGraph 组装 + 条件边
│ │ │ │ ├── state.py # AgentState 10 字段 TypedDict
│ │ │ │ ├── prompts/ # intent.md, advisor.md(6 要素框架)
│ │ │ │ └── tools/ # 4 工具实现(含 trigger/exclusion 元数据)
│ │ │ │ ├── base.py # Tool ABC + ToolRegistry
│ │ │ │ ├── get_product_details.py
│ │ │ │ ├── compare_products.py
│ │ │ │ ├── spec_query_sql.py
│ │ │ │ └── read_sop.py
│ │ │ ├── llm/ # Ports & Adapters
│ │ │ │ ├── ports.py # LLMProvider Protocol + 5 类 LLMError
│ │ │ │ ├── registry.py # ProviderRegistry + YAML loader + 启动校验
│ │ │ │ ├── fallback.py # FallbackChain(Chain of Responsibility)
│ │ │ │ ├── retry.py # 指数退避(1s/2s/4s)
│ │ │ │ └── adapters/
│ │ │ │ ├── anthropic.py # AnthropicAdapter(v1 唯一路由)
│ │ │ │ ├── openai_compat.py # OpenAICompatibleAdapter(Template Method)
│ │ │ │ └── deepseek.py # DeepSeekAdapter(已注册,不路由)
│ │ │ ├── kb/
│ │ │ │ └── products.py # asyncpg pool + Postgres/Qdrant fetchers
│ │ │ ├── retrieval/ # M1 dense retrieval(M2c 将扩展)
│ │ │ ├── api/ # FastAPI routes + 8-event SSE handler
│ │ │ └── main.py # Lifespan: settings + registry + pool + tools
│ │ ├── config/
│ │ │ └── llm.yaml # Role → provider + model 路由配置
│ │ └── tests/ # 889 unit(CI 默认,含认证 22)+ integration/e2e(需 Docker)
│ └── web/ # Next.js 15(M5 — 已脚手架,功能 minimal)
├── packages/
│ └── kb-ingestion/ # KB 摄入 CLI(Python,离线 job)
├── docs/
│ ├── requirements.md # M0 交付物(Step 1 七问)
│ ├── architecture.md # 高层架构概览
│ ├── archive/ # 历史版本文档存档
│ ├── superpowers/
│ │ ├── specs/ # Umbrella spec + 各 milestone spec
│ │ └── plans/ # 实施计划 + 完成报告
│ └── sops/ # 5 份领域 SOP(read_sop 工具读取)
│ ├── phone_recommendation.md
│ ├── comparison_protocol.md
│ ├── budget_constraints.md
│ ├── camera_advice.md
│ └── gaming_recommendation.md
├── infra/
│ └── docker-compose.yml # Qdrant + Postgres + Redis + Langfuse + SearXNG + Grafana
├── data/
│ └── m1/ # 5 份 3C 商品 PDF(M1 demo 数据)
├── tests/
│ └── gold_set.yaml # 评测金标集(M4 扩展至 50 条 5 类别)
├── 07-Phase7-实战篇-从零到生产.md # 强制标准 #1(10 步工作流 + 10 项 launch checklist)
├── 08-可观测与可评估Agent深度设计.md # 强制标准 #2(17 项 DoD)
├── CLAUDE.md # AI 工作规则(所有 AI 工具自动加载)
├── pyproject.toml # uv 项目配置
├── .env.example # 凭据模板(无真实 key,可进 git)
└── .gitignore # 屏蔽 .env / __pycache__ / .venv / *.pyc
| 文件 | 用途 |
|---|---|
| CLAUDE.md | AI 工作规则(所有 AI 工具自动加载) |
| docs/requirements.md | 需求文档(M0 Step 1 交付物) |
| docs/architecture.md | 架构概览 — 3 个 mermaid(系统全景 / LangGraph 流程 / Modular RAG pipeline) |
| docs/interview-qa.md | 30 题技术答辩底稿(架构决策 / 工程深度 / 实战教训 / 安全与对抗 + 电梯陈述) |
| docs/dod-verification.md | 17 项 DoD 验收(16 ✅ / 1 🔶 CI 自动触发因账单 defer) |
| docs/runbook.md | 运维手册 — SLO + 9 告警速查 + 8 故障场景 + 演练命令 |
| docs/engineering-verification/ | 逐里程碑工程验证账本(M0–M8,每本:checklist + finding + 闭环 + 亲跑测试结果) |
| docs/PROJECT_CHECKLIST.md | M0-M6 完整验收清单(注:勾选状态偏旧,以工程验证账本为准) |
| docs/superpowers/specs/ | Umbrella spec + 各 milestone 设计 spec(M2b-Obs ✅ / M2c ✅ 完成报告) |
| docs/superpowers/plans/ | 实施计划 + 完成报告(M2b-Obs 22 task ✅ + M2c 28 task ✅;DoD 验收见 dod-verification.md 16/17 ✅) |
| docs/sops/ | 5 份领域 SOP(由 read_sop 工具按需加载) |
| docs/standards/INDEX.md | 强制开发标准索引 |
| 07-Phase7-实战篇-从零到生产.md | 强制标准 #1 — 10 步工作流 |
| 08-可观测与可评估Agent深度设计.md | 强制标准 #2 — 17 项 DoD |
完整 commit 流可看 git log --oneline。已交付里程碑(最新在前):
- ✅ 评测可观测化增强(本会话已实现 + 本地验证,尚未提交):75 例 gold-set 镜像成 Langfuse Dataset
raguide-gold-set(make eval-langfuse-dataset,新模块packages/eval/src/raguide_eval/langfuse_dataset.py,live 验 75 items)+ dataset-run 闭环(make eval-dataset-run,每例item.run()挂回 5 维 / 加权goldset.*score,跨 run 可比,live 端到端验过冒烟 run)+run_gold_set --write-report额外落report-<stamp>.json逐案完整 judge 理由;业主端只读评测看板(EvalDashboardDialog+ 5 个 admin-gated 只读端点/v1/admin/eval/{baseline,reports,…,fixtures}+ 公开/static/eval-fixtures服 fixture 图,免 Langfuse 看 baseline / 历史报告 / 逐案理由 / fixtures);UI 经ui-ux-pro-max。诚实更正:离线 Ragas 已全部接线但未启用——ragas 0.2.15 与后端 langgraph 1.2.x 的 langchain-core 版本冲突无法共存,本环境从未真正产出 Ragas 数据(4 指标设计未运行,解法见提升.md)。测试:backend +8(admin_eval 29 passed)/ web +15(共 270 passed);eval 套件 163 passed;评测分数不变(纯可观测化,baseline 仍 0.838)。 - ✅ 用户认证 + RBAC + 统一身份(三端)(后端
5acf363/ web4efa9ca/ iOSe8659df):用户名 + 密码注册登录(HS256 JWT / bcrypt / 首位注册者 = admin)、effective_owner_id统一身份(有效 JWT →owner_id=sub,否则回退X-Owner-Id,游客零回归)、RBAC(Bearer admin JWT 优先 +X-Admin-Token后备)。配套:会话按用户隔离(2193b0f)、Langfuseuser_id重设计(acct:/guest:,4daae9a)、Google 式字母头像(0038d9e)、Gold-set 浏览器(后端只读GET /v1/admin/eval/gold-set+ web/iOS 业主视图,f75db75)。 - ✅ M10 iOS 后续增强:豆包化视觉改版(信任蓝·柔和版,
a520864)、抽屉补全 Tier1+2 消费者功能(b1c94e8)、历史删除两段式 inline 确认(8e7e9dd,自定义SwipeConversationRow)、管理·业主段(画像参数 + 评测候选 approve/reject,44516b8)、数字键盘加「完成」(92b953e);未提交但已实现+验证:评测候选「查看完整内容」详情视图(web master-detail / iOS 整页,修「卡片只截断 2 行、整卡不可点」bug,+2 web vitest)、抽屉改整页 push 导航(NavigationStack移至最外层隔离手势,clean build SUCCEEDED)、Gold-set L0 富化(贯通 4 层修复采纳入库候选数据稀疏:eval_candidate_cases加signalsJSONB → done_hook 存 signals → admin approve 构建expected_slots+ 富 notes →append_failed_case写入;旧候选signals=NULL优雅降级,+1 backend 测试)。 - ✅ M9 作品集文档 + 工程验证账本补齐(commit
6771eda):interview-qa.md(30 题技术答辩)+ architecture.md(3 mermaid)+ dod-verification.md(17 项 DoD,16✅1🔶)+ M6/M7/M8 工程验证账本(35 / 102 / 19 passed 亲跑复核)。此前 M9 优化(P1 空输入鲁棒 / P3 grounding 0.789→0.838 / P4 运维就绪)见上方 Roadmap 与评测日志。 - ✅ M8 用户画像持久化:跨会话时间衰减偏好画像(
owner_idkeyed)+ admin 在线可配参数(热加载)+ 自助查看 / 清除。14 任务 Subagent-Driven + opus 最终评审(修复「偏好自强化循环」)。 - ✅ M7 LLM 模型配置:业主在线配置多 provider 端点 + 角色绑定(密钥只进
.env)+ 热重载 + 连通性检测。 - ✅ M6 KB 在线管理:业主应用内增删商品进运行中 KB + 独立
/kb管理页(详情 / 编辑 / 重摄入 / 源 PDF)。 - ✅ M5 / M5.1 Web UI:对话展厅(AI SDK 6.x,双栏 Chat + Inspector)+ claude.ai 式左侧栏多会话。
- ✅ M2b-Obs / M2c:Langfuse + Ragas + 5 维 AgentEvaluator + Grafana;Modular RAG 6 阶段检索 pipeline。
- ✅ Pre-M9 细节补全:4 文档审计 → 补齐 11 项「设计≠代码」细节(spec_query_sql 真查 / chitchat 跳检索 / coverage_score + 评测 rule_based 打分 / retrieval_step 实时 SSE / 记忆 L0 候选池门禁 / L1 类目大纲 / L4 对话摘要 / 在线 spec 抽取 / prompt caching / 大表行级 chunk 最小版)。Subagent-Driven 15 任务 + 安全评审(T1 spec_query_sql、T10 L0 gate)。
- 测试:后端 889 passed(含认证 22 测;CI 默认 = 不含 integration/e2e),eval 包 51 + kb-ingestion 包 45,前端 web 254 vitest。CI:
ci.yml(backend + web jobs)绿;eval.yml为 manualworkflow_dispatch。 - ⏳ Pre-M9 遗留(已记 spec):eval baseline 需
make eval-baseline重置(F5 改了打分);大表行级 chunk 的摄入路径接线(capability 已建未接 live);descope 项见 spec。
(WIP — 项目作品集用途,未正式发布)