智能问数架构设计(八大原则)
本技能沉淀「自然语言智能问数」这一大类的架构最佳实践,面向基于华为 ModelEngine Nexent(ReAct 引擎 + MCP 工具)搭建问数平台。平台如何接入/调用 Nexent 接口、SSE 流式、MCP 注册等,见配套技能
nexent-integration(https://www.modelscope.cn/skills/dmkx01/nexent-integration);智能体 UI 设计与真机测试见配套技能agent-ui-design-and-testing(https://www.modelscope.cn/skills/dmkx01/agent-ui-design-and-testing);技能质量检查见配套技能skill-qc(https://www.modelscope.cn/skills/dmkx01/skill-qc)。本技能只讲业务应用架构怎么设计才经得起需求演进。
目录
- 核心心法(一句话)
- 八条设计原则总览
- 原则① 问数域区分
- 原则② 跨域联合分层
- 原则③ 宽表设计
- 原则④ 口径分层
- 原则⑤ 追问模式
- 原则⑥ 图表输出与多图处理
- 原则⑦ 后端智能体设计
- 原则⑧ 产品化引导
- 使用指南
核心心法(一句话)
AI 是执行者,不是架构师。 架构维护存在明确的人机分工:AI 擅长在既有结构内执行与增量优化,但不会主动发起重构、也洞察不了未来的业务需求——结构调整只能由懂业务的人判断并驱动。本技能把「人该在哪些点检查结构」显式化为八条原则,让平台从第一天就带着正确结构生长,而不是踩一遍坑再重构一遍。
八条设计原则总览
| # | 原则 | 一句话判据 | 详细参考 |
|---|---|---|---|
| ① | 问数域区分 | 数据源头不同 + 查询粒度不同 → 独立成域 | references/01-domain-split.md |
| ② | 跨域联合分层 | 可枚举→数据层;不可枚举→智能体编排 | references/02-cross-domain-join.md |
| ③ | 宽表设计 | 固定低基数→列;可变高基数→行 | references/03-wide-table.md |
| ④ | 口径分层 | schema 说「是什么」,metric 说「怎么算」 | references/04-metric-specs.md |
| ⑤ | 追问模式 | 会话续接 + 上下文外置 | references/05-followup.md |
| ⑥ | 图表输出与多图处理 | eChart 代码输出(强制),按语义 1~3 张、多图同主题 | references/06-multi-chart.md |
| ⑦ | 后端智能体设计 | 工具描述=说明书 + 可靠性分层(三层兜底 + 模型升级回退) | references/07-agent-backend.md |
| ⑧ | 产品化引导 | 应用能查 ≠ 用户会问:问得出、叫得准、找得回、进得来 | references/08-product-guides.md |
原则 ① 问数域区分:按「数据源头 + 查询粒度」分域
判据:两个问题若数据源头不同(明细表不同)且查询粒度不同(一个组织/月度级、一个行为/个体级),就该拆成两个独立的「问数域」,各自内部自洽;同源同粒度才合并。
为什么重要:域是后期陆续加进来的。早期只按第一个域设计,第二个域进来时若强行塞进同一套宽表/缓存,命名、口径、缓存结构会互相打架——这是最常见的「技术债」来源。
示意:一个平台先做了「订单问数」(订单宽表、月×店铺粒度),后来加「用户行为问数」(用户行为明细、用户级粒度)。两者数据源、粒度、缓存策略都不同,应拆成两个域,而不是把用户行为指标硬塞进订单宽表。
每个域内部的标准链路:原始明细 → 唯一真相源 → 宽表/缓存 → 指标;域间通过「联合层」打通(见原则②)。
原则 ② 跨域联合分层:守住「不膨胀单一宽表」的底线
判据:🚨 智能体是恒定入口,判据只判「联合口径在哪算」——联合指标可枚举(有限固定组合)→ 口径在数据层算好(SQL JOIN / 独立物化)、暴露成 API、智能体调用;不可枚举(开放任意组合)→ 数据层算不了、智能体调多域取数工具临时自拼。两条路最终都回到智能体调用(承载层三段:数据层算→API 层载→智能体层用),不要读成"可枚举就不需要智能体"。
🚨 不可枚举 ≠ 必须"总控+子域";聚合型 ≠ 必须编排:扁平单智能体本身就具备跨域语义合并能力(顺序调 A 域工具→调 B 域工具→自己比较下结论,LLM 内生能力)。实现形态由资源压力决定(工具规模 ~20 界 / 各域知识单上下文装得下 / 输出稳定性),三者界内时路由型与聚合型都用扁平单智能体(更优:少一跳);总控+子域只在资源压力真实超界时启用,它解决容量/稳定性问题、不是"要不要合并"。选形态 = 结构决策,必须让用户拍板(决策点见
references/02-cross-domain-join.md「实现形态选型」)。
三条硬底线:
- 绝不为了联合去改原宽表加列——新数据类别持续接入会导致列爆炸、丢明细维度。
- 物化是手段不是终点——物化表数量失控时,应回头评估「是否该升级为真正的跨域数据模型」,而非无限堆物化表。
- 口径固化在数据层——能由 SQL 算好的联合口径,绝不让智能体自己拼。
演进路线:短期「后端 JOIN」→ 中期「高频指标独立物化」→ 远期「开放式多智能体」,逐步放开而不失控。
主/子职责边界(走「开放式多智能体」时):域子智能体只取数、只回数据明细——不装载(import)并行执行工具/其它子智能体/MCP 工具、不绑图表工具、不出图也不返回可视化代码;跨域聚合语义与统一出图(总控拼参调 MCP 图表工具、输出 eChart 代码)全部收敛到总控。各子域各自出图只会产出无法合并的单域图(跨主题拼图稳定失败,见原则⑥);出图责任收敛后,图型路由与图表代码输出协议只在一处维护(详见 references/02-cross-domain-join.md)。
原则 ③ 宽表设计:固定低基数列化 + 列和自校验
判据:维度固定且小(枚举定死、不会再增)→ 横展成列进宽表;可变且大(实体数量不定)→ 只能行式下钻,绝不横展。
量化护栏:枚举值 ≤ 个位数(约 ≤ 8)且业务确定不再增 → 列化;两位数以上或会持续新增 → 行下钻。
关键的自校验机制:任何横展的列群,必须给出「列之和 = 总量」的校验式(如「5 类来源列之和 = 订单总量」「4 类×4 动作共 16 列之和 = 总合计」),作为口径正确性的自动守门——列和能对得上,说明拆分没漏、没重、没串。
归一分层是问数的第 0 层基础:宽表设计前,先让「用户/上游表叫的名字」命中「库内标准口径」——固定低基数枚举(来源/状态)走公共函数归类;可变高基数的实体名(门店/科室/产品)走名称映射表(标准名主表 + 别名映射行 + 未匹配登记待补),归一发生在入库源头而非查询层。两类归一与「固定低基数→列、可变高基数→行」正好对称,详见 references/03-wide-table.md §归一分层。
原则 ④ 口径分层:schema 与 metric 分离,单一出处 + 断言对齐
两层分离:
- 字段描述层(schema):只回答「字段是什么」(名称/类型/单位/枚举),承载不了跨字段口径。
- 统计口径层(metric):回答「指标怎么算」(公式、依赖字段、单位、端点),独立成层。
单一出处 + 结构化:所有口径收敛到一个字典(键名带域前缀,如「订单域.订单量」「订单域.环比增长率」),每个口径结构化声明 fields(依赖字段)+ formula(公式)+ check(校验式)+ endpoint(端点指向)。禁止把口径散写在字段描述的自由文本里。
断言对齐是纪律:口径字典里的 formula 必须与接口实际 SQL 公式级一致(可加单元测试断言)。这是最容易出错的地方——字典写「A/B」,接口算「A/C」,智能体读字典就会得到错误结论。
端点分流(高频/低频不是判据,计算方式才是):
- 口径要过滤原始明细(时间差、计数比,带「非空且≥0」等规则)→ 端点固化(后端算好,智能体用原始字段自算会错)。
- 口径是宽表列相加/比值/已物化值 → 声明 + 通用端点(查询/分组/趋势等少数通用端点覆盖),不为每个指标加端点。
原则 ⑤ 追问模式:会话续接 + 查询上下文外置
价值定位:问数不是「描述 + 出一张图」,而是 读数据 → 下结论 → 做决策 → 持续深挖——一图只是起点,价值在图之后的每一步。
两个实现要点:
- 会话续接:追问携带会话 ID 续接(「那 XX 呢」按追问处理),优先复用已取数据。
- 查询上下文外置:已确定的查询状态(月份/维度/指标)外置为结构化状态,而非只靠对话记忆——避免轮次一长、前文关键约束被截断导致追问「失忆」。
主动深挖:结论输出后主动给出可深挖的下一步(下钻 / 对比 / 归因),把「持续深挖」从被动等追问变主动引导。
原则 ⑥ 图表输出与多图处理:eChart 代码强制输出,禁止纯图片
强制铁律(本原则为硬约束,不可降级):问数应用的图表一律由后端智能体输出 eChart 可视化代码(工具查到的数据 + 图表配置代码),前端拿到代码渲染成可交互图表;禁止输出纯图片。若平台侧没有可用于出图的 eChart 工具,必须走下方「兜底接入」补齐工具,而不是退回图片输出。
强制 1|输出载体 = eChart 可视化代码(禁止纯图片)
- 后端智能体答图表类问题,返回「数据 + eChart 图表配置代码」交前端渲染;纯图片不可交互、数据无法复核、口径错了无从校验,一律禁止。
- 该约束写在后端智能体系统提示词层(属于业务输出协议),前端按「收到代码即渲染、收到图片视为违规」容错(UI 侧细则见配套
agent-ui-design-and-testing)。
强制 2|图表工具按业务诉求选约 13 个绑定(禁止全绑)
- eChart 能力常按图型拆成一组 MCP 工具暴露。全部绑定会拉长工具清单 → 稀释模型路由准确率、挤占上下文、选错工具概率上升。
- 从典型问答/验收问题反推需要表达的关系类型(对比/趋势/构成/分布/关联/流向…),每类取 1~2 个最常用图型工具,共约 13 个绑定到后端智能体;拿不准时把「图型覆盖」作为决策点询问用户(见使用指南决策点表)。选型方法与示范清单见
references/06-multi-chart.md。
强制 3|平台无 eChart MCP 工具时:提示 → 用户给地址 → 你接入并绑定(禁止图片兜底)
- 明确提示用户:图表输出需要 eChart 类 MCP 工具,可到魔搭社区免费获取一个;
- 请用户把该 MCP 的接入地址发给你——禁止自行猜测 server_url(符合
nexent-integration的 MCP 接入硬闸门); - 你负责按
nexent-integrationreferences/04-mcp.md原生 MCP 接入链路:添加到 Nexent(仓库注册 → 扫描工具)→ 按强制 2 选约 13 个绑定到后端智能体 → 发布版本; - 回到强制 1:在提示词层约束「必须输出 eChart 代码、禁止纯图片」。
输出组织(实测规律,规律表见 references/06-multi-chart.md):张数按语义 1~3 张、不默认一张(只需单视角给一张即可);多张必「同主题」视角组合;禁止跨主题拼图(提示词显式约束 + 前端对多图输出做容错降级);图表数据一律来自工具返回,禁止模型自造数值;大数据量图型设节点上限(如桑基节点 ≤ 20)防长 JSON 输出被截断。
原则 ⑦ 后端智能体设计:工具描述 = 说明书 + 三层兜底
核心洞察:后端对智能体的暴露,本质是「给一本取数说明书」——工具描述写得好不好,直接决定智能体调对调错、调几次。踩坑典型:漏写「支持多月」→ 智能体逐月查 6 次;漏写「不传维度返回全部」→ 智能体逐项循环调用上百次。
每个工具描述(docstring)必写清:
- 返回什么;
- 参数默认行为(不传 = 返回全部);
- 禁止行为(禁止逐项循环调用 / 禁止自算口径 / 禁止编造数值)。
三层兜底(可靠性分工):
- 工具描述约束「怎么调」(默认行为 + 禁止行为);
- 提示词约束「数值从哪来」(数字必须来自工具、图表入参由工具数值构造);
- 前端兜底约束「输出坏了怎么救」(截断修复 / 正则提取 / 容错降级)。
prompt 侧纪律(反向约束:别在提示词里重复工具内容):
- 提示词不写参数枚举/口径——工具参数与取值枚举(group_by 有哪些值、metric 有哪些)唯一来源 = 工具描述 docstring(平台自动提供给模型、最权威)。双份维护必然漂移(实证主源见
nexent-integration02 §5.5:docstring 枚举扩到 7 项、prompt 还写旧 5 项)。提示词只写「业务问题 → 工具」路由 + 组合策略,参数细节一律交给 docstring。 - 图型选择是业务路由,不是工具描述:图表工具(eChart 类)的「什么时候用哪种图型」按业务诉求在提示词层路由(见原则⑥强制 2),docstring 只管该工具返回结构与默认/禁止行为,不写死图型策略;「必须输出 eChart 代码、禁止纯图片」同样写在提示词层(原则⑥强制 1)。
- 组合策略显式化:同工具同参数只调一次(已取数据直接复用)、支持多月的工具一次取齐、返回全量的工具一次拿全(禁止逐项/逐科循环调用)。
- 改工具行为 = 只改 docstring:重连即生效、提示词无需动;提示词里的旧枚举就是脏数据,是漂移源。维护成本收敛到单一文件。
- 模型调错工具(该用专用图表工具却走通用出图工具)是概率事件:表象在前端(图型错 / 有轴无点)、根因在后端工具选择。三条认知:① chart option 99% 来自工具,prompt 的价值是引导模型选对工具、而非约束输出格式;② 调错代价≈2 倍耗时与流量;③ 前端归一兜底只减频、不根治(仍必须加)。排查先查
tools[].description措辞误导、再改 prompt 用「需求语义→专用工具」映射查表(枚举必漏项)。详见references/07-agent-backend.md;平台排障契约见nexent-integration01 + 02 §5.5。
只读暴露:智能体可见的工具只做查询,写操作一律不给,防误改数据。
import 分两类:内置基础库可用,平台扩展能力禁装(能力装载 = 发布配置,不是模型行为):import 本身不禁止——python 内置基础库(标准库,json/math/zipfile/xml 等)在智能体脚本/执行环境可用,属本地计算、不改变对外调用面(实证见配套 nexent-integration 03「纯标准库 0 依赖」)。禁止的只是借 import 装载平台扩展能力:内置并行执行工具 → 并发 fan-out、调用成倍放大;其它子智能体名称 → 运行期动态建立调用链、层级失控易串域;MCP 工具 → 绕过「按业务选绑」工具选型、清单失控调错概率上升。能力清单在发布配置里静态绑定(总控按原则⑥选绑图表工具,子智能体只绑本域取数工具),模型只使用已绑定能力;需要新工具/新子智能体 = 结构变更,归人决策后改配置重发布(呼应核心心法「AI 是执行者,不是架构师」)。判别线:import 目标是「运行环境自带的本地计算库」→ 允许;是「平台/外部扩展能力」→ 禁止(详见 references/07-agent-backend.md)。
可靠性分层第 4 层——模型升级与回退(三层兜底之上):三层兜底救「输出坏了」,模型升级救「模型能力不够」。重题(多工具+多图)失败重试仍不完整、且根因是主力轻量模型概率性「中途收尾/提前 stop」时,应升级到强推理模型再试:R1 默认(快速响应模型) → R2 升级(escalate,动态解析强推理候选+健康探测,不健康自动回退默认) → R3 回退默认保底,前端 3 轮封顶防无限循环,escalate 只在失败重试轮带。技能表述只认角色不认型号:快速响应模型 / 强推理模型的映射由部署决定(示例 DeepSeek-V4-Flash / V4-Pro)。四条纪律:强推理 id 不硬编码(管理 API 模型列表按部署命名约定动态解析,失败回退 env 手动指定);升级目标逐个健康探测(极短 query 真发;健康 = 有最终结果且无错误/配额信号——配额被拒时平台可能先吐"伪最终结果"再报错,只判"有结果"会误判健康;错误编码随部署/版本而异须实测,如 HTTP 402+code 30001,不作平台常量);"存在"≠"可用"(余额/配额、上下文预算只有实测才暴露);升级 = 对话请求体注入 model_id 每请求级覆盖,不改智能体绑定,配额恢复后健康探测自动转正常 = 零配置自动启用。⚠️ 动态解析易静默失败(加了真强推理却从不升级、审计日志只剩 env 兜底候选):按命中率排四坑——管理 base≠北向 base(拿北向调管理登录 404)、display 别名≠型号真名(别名如 test 漏判,须双字段任一命中)、探测超时太紧误杀健康模型(放宽到 30s 级,配额错即时返回)、管理凭据没真进进程(用无引号 EnvironmentFile 并核对进程 environ)——详见 references/07-agent-backend.md「模型升级与回退 · 落地实证」。
原则 ⑧ 产品化引导:应用能查 ≠ 用户会问(四大落地)
判据:架构让数据「查得到、查得对」只是前提——用户问得出吗、叫得准吗、找得回吗、数据进得来吗?四条产品化引导回答这四个问题(详细规范见 references/08-product-guides.md):
- 内置示例问题栏(默认 10 问)——让用户「问得出」:发送窗口(输入框 + 发送按钮)下方常驻「试试:」chip 区(小号胶囊、flow-wrap ≤2 行、不进空态居中,锚点 #2);每条 chip 双字段模型:按钮只显简短标签(
[难度] 主题概括,≤20 字一行内),完整自包含问句只存 data 属性(时间+指标/维度+图型+以便…)不铺上按钮;点击 = 把 data 完整问句填入输入框、可修改后手动发送,不是一点即发(交互细节与真机断言见配套 agent-ui-design-and-testing)。按问数域分组;10 问覆盖不同图型且含双图(双图=同主题双视角,守原则⑥),每条过三关——为决策而问 / 可查可答(命中口径字典)/ 难度分层;示例集 = 验收基线:答不上先修应用、不砍问题(详见 08 引导 A)。 - 行话/术语/别名映射表 = 前端配置项——让用户「叫得准」:术语/对照配置页=一张表格(🚨 表格化铁律:tbl 列模型
标准名【权威】 | 别名/映射 | 状态/说明,禁卡片流/标签云,锚点 #5),默认只读、点「✏️ 编辑」才进入编辑态(全局共享配置防误触;取消 = 丢弃未保存重载只读、保存才落库),编辑态增删改 + 未匹配叫法自动登记一键补录、只读态可导出;入口与问数并列、收「数据管理」一级视图多 tab 之一(锚点 #1);配置中心为唯一编辑入口,查询归一、入库归一、docstring 同源(守原则④);映射/对照 pane 无上传(操作集 = 编辑 + 导出,见 08 引导 B)。 - 问数历史面板(最近 10 次、可删、可追问、可放大)——让用户「找得回」:存本机会话快照(不传服务器:域 + 会话 ID + 追问链 + answer 原始 markdown(含表格)+ 图表配置/数据,按「域+会话 ID」合并更新、容量超限降级丢图表);点开 = 回放 + 可追问(🚨 回放 = 新开一个隔离会话 tab,与当前进行中的会话绝不揉合:禁止覆盖/插入/追加,无多 tab 时先「开启新会话」再回放;点整条记录即回放、无行内小按钮;回放 = 富内容重渲染——表格随 markdown 原文还原、图表用快照配置重建,禁止丢表格/丢图只回纯文本)——在回放会话里继续提问即续接(守原则⑤),切回原会话互不影响;会话被后端清除给「作为新问题」出口;弹窗可全屏/还原(详见 08 引导 C)。
- 数据接入与宽表呈现——让数据「进得来」:全部数据资产收归一处的「数据管理中心」一级入口(与问数并列,锚点 #1),页面全宽紧凑、pane = 次级页签 + 只一排工具栏 + ≈62vh 定高表格三段式(版面骨架见 agent-ui-design-and-testing
references/data-screen-ui.md§1-2,锚点 #4);上传按钮按资产类别配:只属于『外部文件定期送』的原始明细 pane(弹窗:业务期间必填 + 按表角色自动识别解析入库 + 联动重算),映射/对照/汇总宽表 pane 均无上传;对接已有系统数据库则无上传环节、ETL 物化即可;宽表在前端不叫「宽表」、按业务实质命名,核心列常驻、拆分列默认折叠「展开全表」可显隐、行可下钻(详见 08 引导 D)。
使用指南
- 从零设计问数平台:按 ① 分域 → ③ 宽表 → ④ 口径 → ⑥ 图表工具选型 → ⑦ 后端智能体 → ⑧ 产品化引导 的顺序走一遍,每步对照对应 reference 的判据自检。
- 给现有平台做重构/体检:逐条对照八原则,找出「判据未显式化」「口径散写」「工具描述缺失默认/禁止行为」「图表输出成图片」「图表工具全绑」「产品化引导缺位」的地方——这些就是技术债所在。
- 跨域 / 追问 / 图表输出与多图:遇到具体需求再查 ② ⑤ ⑥ 的专门参考。
决策点主动询问(人拍板的机制):八条原则给的是判据而非答案——判据往往需要业务输入才能落定。当以下情况出现时,必须用选项卡片向用户提问,不擅自假设:
| 决策点 | 提问示例 |
|---|---|
| 域边界模糊 | 新问题算第一域还是拆第二域?给出「拆域 / 并入」两个选项及各自代价 |
| 列化取舍 | 某维度要不要横展成列?给出「列化(查得快但加列要改表)/ 行下钻(灵活但每次聚合)」 |
| 口径归属 | 该口径放哪个域、归谁算?给出候选归属让用户选 |
| 联合方案 | 可枚举联合选「后端 JOIN / 物化表」?给出数据量与维护成本对比 |
| 跨域实现形态 | 先做数据分析判型再决策:①组合可枚举→数据层?②问题是否单域可答(路由型)还是须合并多域语义(聚合型)?AI 输出判型与推荐(扁平全量 MCP / 总控+子域 / 混合 + 代价),由用户拍板,AI 不默默认也不空手抛选择题(详见 references/02-cross-domain-join.md「实现形态选型」) |
| 端点分流 | 该指标是端点固化还是声明+通用端点?给出判据对照让用户确认 |
| 图表覆盖 | 业务需要覆盖哪些图型?给出按关系类型整理的候选(约 13 个)让用户确认后再绑定 |
| 数据接入 | 该域数据是「业务表格定期送」还是「对接已有系统库」?决定要不要做前端上传解析入库 |
平台接入细节(北向 API / SSE / MCP 注册 / 智能体管理 / 图表 MCP 工具接入与绑定)请转
nexent-integration技能;智能体 UI 设计与真机测试请转agent-ui-design-and-testing技能。
微信扫一扫