diff --git a/README.md b/README.md index 61ef6c4a..2bb46f40 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ## 目录 - [快速开始](#快速开始) · [生产部署](#生产部署) · [核心能力](#核心能力) · [受限动态编排](#受限动态编排模板定骨架agent-填关节) -- [可点击证据](#可点击证据报告里的每个数都点得开出处) · [工作流形态](#工作流形态) · [节点类型](#节点类型) · [架构](#架构) +- [可点击证据](#可点击证据报告里的每个数都点得开出处) · [数据目录](#数据目录让助手和-agent-看懂业务数据) · [工作流形态](#工作流形态) · [节点类型](#节点类型) · [架构](#架构) - [关键设计决策](#关键设计决策) · [运行环境](#运行环境) · [常见问题](#常见问题) · [开发与验证](#开发与验证) --- @@ -83,7 +83,7 @@ http://127.0.0.1:8000 。前端产物不存在或比源码旧时才重新构建 | 领域 | 能力 | |---|---| -| **可视化编排** | 17 种节点拖拽连线;运行时节点实时高亮、边上光点流动画、卡片内直接呈现流式 token;底部航迹把各节点的起止和并行度排在一条时间轴上,实时和回放共用;多 agent 节点在卡片里展开协作矩阵(谁在跑、几个人并行、省下多少) | +| **可视化编排** | 18 种节点拖拽连线;运行时节点实时高亮、边上光点流动画、卡片内直接呈现流式 token;底部航迹把各节点的起止和并行度排在一条时间轴上,实时和回放共用;多 agent 节点在卡片里展开协作矩阵(谁在跑、几个人并行、省下多少) | | **对话式取数** | 「问数据」页:自然语言提问,系统自行接入数据源、生成工作流、执行并给出结论;答案里有数字时经报告撰写节点输出、逐段点得开;对话持久化、可分享链接 | | **多模型接入** | Anthropic / OpenAI / 任意 OpenAI 兼容服务(DeepSeek、Kimi、通义、智谱、硅基流动、Ollama 等)+ Mock | | **工具链** | 15 个内置工具 + 自定义工具(HTTP 模板 / 沙箱 Python)+ MCP server 接入;MCP 与自定义工具默认每次等审批,可逐个改成门控模型把关或始终允许 | @@ -93,9 +93,12 @@ http://127.0.0.1:8000 。前端产物不存在或比源码旧时才重新构建 | **断点续跑** | 失败的运行可从失败节点继续,已完成的节点不重复执行;允许修改节点配置,但拓扑必须一致 | | **知识库** | 向量 + BM25 混合检索、倒排索引、可选模型重排;PDF / Word / PowerPoint / HTML / Markdown 解析;向量模型可接本地端点 | | **表格入库** | Excel / CSV 上传后转为可用 SQL 查询的表,自动生成 `db_query__` 工具——数字由 SQL 计算得出,而非模型读取 | +| **数据目录** | 给数据源的每张表记下粒度、业务主键、业务日期、有效记录条件,每个字段的含义、单位、度量类型和码值,以及表与表的关联;由外键、命名推断、数据剖析和模型起草,逐项确认后生效;助手建图、agent 查结构、SQL 检查都读它 | +| **SQL 检查** | 按数据目录检查一对多关联后重复计算、存量跨时间相加、比率被相加等七类问题;助手自查时交回修正,受管模板发布时挡住,运行时标在查询结果上、契约指标降档 | +| **跨库合并** | 合并查询节点:各库先聚合到同一个键,再在库外按键合并;截断的输入拒收,证据一路追到两边的原始查询 | | **长期记忆** | 跨运行的记忆读写与自动去重;Copilot 建图时主动记录应当记住的事实 | | **Skill 管理** | 将方法论抽象为可复用单元,挂载到节点上注入 system prompt | -| **自然语言编排** | Copilot:一句话生成或改写整张图,自动排版;交付前按运行时同一套规则自查,查出会跑挂的问题先交回去改,改不好就不自动运行 | +| **自然语言编排** | Copilot:一句话生成或改写整张图,自动排版;表多的库先按需求挑表、沿关联补上中间表,只给相关表的全部字段和数据目录;交付前按运行时同一套规则自查,查出会跑挂的问题先交回去改,改不好就不自动运行 | | **结构化成果** | JSON Schema 校验,不合格时将错误回传模型自动返工 | | **产出复核** | 运行结束后规则扫描事件流,发现异常才调用模型复核;复核可重组答案但**不得引入原答案中不存在的数字** | | **追踪与成本** | 全量事件落库可回放;逐节点耗时、token 用量、按目录价折算的成本 | @@ -245,6 +248,38 @@ flowchart LR --- +## 数据目录:让助手和 agent 看懂业务数据 + +表名和字段名说不清业务:一行代表一张门票还是一次检票,`visitor_count` 能不能按天相加,两张表按哪一列连、 +连上之后会不会一对多。助手(Copilot)建图、agent 写 SQL 时只能猜,猜错了查询照样能跑,数却是错的。 +数据目录把这些事实记下来,交给三处读: + +- **助手建图**:表多的库先按需求挑表,再沿关联关系补上连接路径上的中间表,只给这些表的全部字段、目录和 + 可以照抄的连接条件,其余表只列名字。挑不出时退回只列表名,不阻断生成;只探查了一部分表时如实说明。 +- **运行时查结构**:`db_schema` 返回表结构时附上目录,问数据页里现场写 SQL 的 agent 也用得上。 +- **SQL 检查**:按目录检查七类问题——一对多关联后重复计算、存量跨时间相加、比率被相加或平均、漏了有效记录条件、 + 码值不存在、没用约定的业务日期、关联条件对不上已知关系。助手自查时交回修正,受管模板发布时挡住,运行时标在 + 查询快照上,契约指标的来源查询有错误时出具降档。解析不了的写法一律跳过:宁可漏报,不误报。 + +目录里每一项都带来源和状态。来源是数据库注释、外键、命名推断、数据剖析、模型起草或人工;状态是推断、已验证、 +已确认或已驳回。推断的项只作提示,已验证、已确认的才进入错误级检查;驳回的项保留编号,不会被下一次起草或 +推断带回来。 + +| 环节 | 做法 | +|---|---| +| 起草 | 探查时读外键和唯一约束;按 `xxx_id`、`xxxId` 推断关联,表名带业务前缀的也认;可选让模型起草中文名、粒度、度量类型。导入表格的源已有系统按核对结果生成的说明,目录不重复、不改写它 | +| 数据剖析 | 默认关闭,按数据源开启。只读、经过守卫,单条查询和整次剖析都有上限,大表用统计信息估算行数,遮罩的列不取样。抽样核实推断出的关联,补上覆盖率和基数,站得住的升为已验证;状态列给出码值候选,含义等人填写 | +| 对话里纠正 | 用户说「status=9 表示作废」,助手给出一条目录修改提案,列出改前、改后和理由,人确认后才保存;公式不收,留给口径卡 | +| 版本与提醒 | 目录随表结构快照冻结进证据,每次运行用的是哪一版查得到。发布时记下模板引用的表的目录版本,正式运行时目录有变化就提醒;agent 运行时才写 SQL 的,按「可能涉及」单独提醒。只提醒,不拦运行 | + +目录只记数据事实,不记计算公式:「在园人数是存量,不能跨天相加」进目录,「环比 =(本月 − 上月)÷ 上月」进口径卡。 +这也是不另做一层指标编译式语义层的原因——口径已经由口径卡和版本固定在管,再造一层就会出现两份口径。 + +跨库的问题不做联邦查询:各库先聚合到同一个键,再用**合并查询**节点在库外按键合并(内存 SQLite,同一套只读守卫)。 +被截断的输入拒收,键类型不一致、合并后行数变多都会提醒,报告里的数能一路追到两边的原始查询。 + +--- + ## 工作流形态 **人工介入与分支**——执行在 `human` 节点暂停并落盘,人工决策后沿对应出口继续: @@ -294,7 +329,7 @@ flowchart LR |---|---|---| | 起止 | `input` `output` | 声明输入字段 / 收集结构化成果 | | 模型 | `llm` `agent` `supervisor` `report` | 单次调用 / 带工具循环 / 多 agent 协作 / 报告撰写(只写引用标记,数字由系统填) | -| 执行 | `tool` `code` | 直接调用工具 / 沙箱内执行代码 | +| 执行 | `tool` `code` `merge` | 直接调用工具 / 沙箱内执行代码 / 合并几次查询的结果(跨库按键对齐) | | 控制 | `branch` `loop` `subgraph` | 条件或语义分支 / 遍历与条件循环 / 嵌套工作流 | | 上下文 | `memory` `retrieve` `transform` | 长期记忆读写 / 知识检索 / 数据整形 | | 把关 | `human` `validate` `metrics` | 人工介入 / Schema 校验与自动返工 / 口径卡 | @@ -637,16 +672,16 @@ loop 节点给它定轮数上限的环:用 loop 节点包住它。确实需要 ## 开发与验证 ```bash -# 后端:约 2860 个测试,-n auto 并行约 16 秒 +# 后端:约 6600 个测试,-n auto 并行约 40 秒 cd backend && env -u ANTHROPIC_API_KEY -u ANTHROPIC_BASE_URL -u ANTHROPIC_AUTH_TOKEN -u OPENAI_API_KEY \ python -m pytest -n auto # 前端类型检查 cd frontend && npx tsc -b -# 前端检查:17 项,默认 8 道并行,约 3.5 分钟。连 5273 / 8000,先起 ./scripts/dev.sh +# 前端检查:20 项,默认 8 道并行,约 8 分钟。连 5273 / 8000,先起 ./scripts/dev.sh node scripts/check-all.mjs -# 另起 2 套只给检查用的「后端 + vite」,各用一份数据拷贝,约 3 分钟;边改代码边跑也不被打断 +# 另起 2 套只给检查用的「后端 + vite」,各用一份数据拷贝,约 6.5 分钟;边改代码边跑也不被打断 CHECK_DATA_SRC=<数据目录> node scripts/check-all.mjs --stacks 2 --lanes 12 # 只跑某几项(名字去掉 check- 前缀) node scripts/check-all.mjs evidence publish @@ -655,14 +690,14 @@ node scripts/check-all.mjs evidence publish pytest 前面的 `env -u` 不能省:没配 Key 的 provider 会退回环境变量里的密钥,启动时的 seed 也会拿它种一个 provider——环境里留着真密钥,测试就可能真的去调接口。 -`check-all` 的 17 项按 `scripts/check-all.mjs` 里 `ORDER` 的顺序排: +`check-all` 的 20 项按 `scripts/check-all.mjs` 里 `ORDER` 的顺序排: | 类别 | 检查 | |---|---| -| 不开浏览器 | `tokens`(令牌静态扫描)`trace`(运行态内核的纯函数)`decode`(事件翻译层) | +| 不开浏览器 | `tokens`(令牌静态扫描)`copy`(界面文案)`trace`(运行态内核的纯函数)`decode`(事件翻译层) | | 走线、组件与护栏 | `canvas-layout` `ui-kit` `guards` | | 外壳、回答流与运行态 | `shell` `stream` `evidence`(可点击证据)`run-states`(节点卡)`canvas-fx`(画布表层) | -| 各页面 | `studio` `publish`(发布前检查与自动修复)`chat` `runs` `manage` `ui`(端到端,连真数据) | +| 各页面 | `studio` `publish`(发布前检查与自动修复)`chat` `runs` `manage` `versions`(上传表格的版本)`catalog`(数据目录)`ui`(端到端,连真数据) | 完整输出写进 `/tmp/agentlab-checks/<时间>/`,终端只给汇总;并行时没过的最后单独重跑一遍,重跑才过的单列成「偶发」。 `--stacks` 每套拷一份数据、端口自动挑空闲的,后端不热重载、vite 不监听文件,跑完、出错或被中断都收干净。