Skip to content

智能问数 · 项目复盘 ​

关键取舍 ​

为什么不让模型直接写 SQL 去执行? ​

  • 原因:模型写的 SQL 一旦能直接跑,写库、拖库和把引擎拖垮都只隔一次生成;出了错也无法区分是理解错了还是写错了。
  • 处理:主链上模型只产出查询意图,服务端编译成 SQL 后再执行;run_sql 登记在工具表里但对模型不可见。回退回路里模型只看到 get_schema、sample_data、plot、export、run_python 五个闭集工具,单轮最多 10 步。
  • 取舍:意图能表达的查询范围比裸 SQL 窄,解析不出时退回工具回路而不是放开 SQL。

为什么查询进子进程、计算留在进程内、Python 才进容器? ​

  • 查询:要挡的是写库和引擎失控,只读连接加独立子进程够用,不需要容器开销。
  • 计算:输入已经是接受过的结果,运算限制在加减乘除、比率、增速、求和、平均、排名和 top-N 这个闭集里,不执行模型生成的代码,所以留在进程内。
  • Python:要挡的是写宿主机、出网和危险模块,静态检查挡第一层,--network none、只读根文件系统、非 root 和资源限制挡第二层。没有固定摘要的镜像就返回 SANDBOX_UNAVAILABLE,不改到进程内执行。

为什么把问、查、算、整理、回答拆成五段? ​

  • 原因:一次模型调用同时做拆解、查数、计算和措辞,失败时看不出停在哪一段,回答里的数字也指不回来源。
  • 处理:每段有自己的状态和编号——plan_revision、task_id、result_id、fact_id。回答只读整理好的素材,对不上的数字标为未验证;评估台按同样五段回看。
  • 取舍:一轮多两次模型调用(拆解轮、回答轮),换来每个数字可追溯。

为什么等待和确认不能交给模型自己结束? ​

  • 问题:口径没定、或导出这类副作用还挂着时,如果模型还能自己继续查、自己点确认,用户的决定就形同虚设。
  • 处理:所有需要用户决定的情况停在同一种等待态,依赖该决定的任务执行数为 0。confirm 不在模型可见列表里,只有用户经 POST /v1/confirm 批准后才执行一次;模型若发出确认调用,按未登记工具处理。

为什么对抗评测不用模型当裁判? ​

  • 原因:裁判模型本身可以被注入影响。
  • 处理:攻击是否拦住、合法请求是否误杀,都用规则判定;逃逸率和误杀率写在同一份报告里,只报拦截率会掩盖把合法请求一起拒掉的情况。

遇到的问题与处理 ​

必需任务失败时为什么直接结束本轮? ​

  • 原因:必需结果缺失时继续整理回答,容易把未完成标成成功。
  • 处理:必需任务失败就结束本轮并返回错误,不再整理部分回答。

模型选了不存在的工具,或规划失败怎么办? ​

  • 方法不在表里:按 UNKNOWN_TOOL 拒绝,不执行;注入用例里的 os.system、eval、run_sql_admin 都走这条。
  • 拆解超时、限流或空回复:返回对应错误码,不伪装成「没有查到数据」;每次模型调用用小轮 60 秒,整轮用 20 分钟墙钟;断连后取消后续处理。

目前的边界 ​

五阶段什么时候才进? ​

意图能解析、且表结构来自 SQLite 文件时才进入;否则走回退工具回路。PostgreSQL 来源目前只在回退回路里可用。

身份是怎么处理的? ​

本地和演示用会话登录与 Cookie;护栏只接收调用方已构造好的 Principal,自己不解析令牌。这不等于已接上主产品的鉴权。

导出回执是真的吗? ​

确认后的导出回执按规格是模拟的,用来把确认契约走通;真实导出目标不在范围内。

数据从哪来? ​

合成数据,seed 固定可重现;不使用公司客户数据和内部表结构。

经验总结 ​

  • 先收窄能力,再谈规划:模型能调的工具、能写的查询形态、能用的 Python 模块都放进服务端可校验的清单里,规划再灵活也出不了这个圈。
  • 阶段分开之后,执行隔离才有地方落:查询、计算和模型生成的 Python 各有边界,不互相冒充;每段都有编号,评估台才能按段定位。
  • 低信任内容先标记:工具返回、表注释和工具描述可以进上下文,不能直接当成下一轮要执行的指令。
  • 两个比例一起看:拦截率和误杀率并排,准确率和失败原因分布并排;只报一个数会把问题藏起来。
  • 终态先汇合再展示:完成、部分完成、失败、取消和过期走同一个出口,未完成的任务不标成成功,用户才知道下一步能做什么。