ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

我给查数 AI 的「话痨」装了个音量旋钮:50 行太少 200 行太多?那就让用户自己拧

我给查数 AI 的「话痨」装了个音量旋钮:50 行太少 200 行太多?那就让用户自己拧 我给查数 AI 的「话痨」装了个音量旋钮50 行太少 200 行太多那就让用户自己拧这两天 AI 圈还在卷 Agent 的聪明程度更大的上下文窗口、更长的记忆、一次能吞下整库。但有个反直觉的现实没人爱提——查数 Agent 最大的敌人不是看不见而是看太多。一次查询吐回 5000 行上下文当场撑爆token 烧得哗哗的模型还被淹没在数字里找不着北。我没跟着卷窗口长度。我干了另一件事——去翻了一个开源数据智能体工作台daw「寒鸦数据工作台」的代码看它怎么给查询工具限流。它的解法跟模型半毛钱关系没有一个行数上限从硬编码 50进化成用户手里的旋钮。看完我可以负责任地告诉你三件事。第一截断多少行不是技术问题是产品判断——daw 的作者在 2026 年 9 月 7 日那天拍板50 改成 200理由只有一句明细下钻常需超 50 行。第二一个数字在代码里出现四次改漏一次 AI 就瞎猜——所以它先被提成常量再被测试钉死最后升级成设置项。第三最漂亮的设计是把度交给用户把界留给自己用户可以在 10~1000 之间随便拧但手改配置文件想拧到 5000门都没有代码会把它钳回来。1. 先看病为什么查数工具必须截断先给大家科普一个概念「上下文是按行烧钱的」Agent 查一次数数据库返回的每一行都会变成 token塞进模型的上下文窗口。一张明细表动不动几千行全塞进去的后果有三个——窗口撑爆直接报错、token 费用原地起飞、模型在数字海洋里注意力涣散该看的聚合数反而看不见。翻译成人话查数工具不截断等于让 AI 用吸管喝水库——要么呛死要么淹死。daw 的工具描述里把纪律写得很直白结果超过 N 行自动截断全量先拿聚合函数算总数明细再按需下钻。注意这个顺序——聚合先行下钻按需。这不是截断这是查数的方法论。但这里有个魔鬼细节工具描述里写着超过 50 行自动截断代码里真的是 50 吗这就是下面要讲的故事。2. 第一步先拍板一个数——50→200故事的起点是一个用户拍板。2026 年 9 月 7 日daw 把查询行数上限从 50 改成 200commit 信息里写的原因朴素到只有一句话明细下钻常需超 50 行。翻译成人话真实用下来发现50 行根本不够看明细——用户问上个月退货最多的 10 个 SKU 是哪些聚合算完总得下钻看看明细长什么样吧50 行卡在那儿刚看到点意思就没了。所以拍板改成 200。这一步是地基截断数不是算出来的是用出来的。没有理论最优行数只有在真实会话里够不够用。先定一个当前最合理的数让它跑起来——先有判断再有机制反过来先做配置界面的默认值往往是个拍脑袋的数字。学完这一步你能带走的第一个方法给 Agent 工具定输出上限时先从真实使用场景里找一个够用的数写死它跑两周再说。过早的可配置化配置的是你的不确定不是用户的需求。3. 第二步一个数字四处引用——提成常量50 改 200 的时候daw 的作者发现一个要命的问题这个50在代码里出现了四次——实际落库的查询包装wrap_query(sql, Some(50))SQL 层面加 LIMIT执行层的查询调用run_query(guard, sql, Some(50))工具描述告诉模型的“结果超过 50 行自动截断”截断文案告诉用户的“(结果已截断仅返回前 50 行”翻译成人话第 1、2 处是实际发生的事第 3 处是告诉 AI 的事第 4 处是告诉用户的事。改漏第 3 处代码截 200 行模型却以为只截 50 行——它会基于错误假设瞎推理。对 Agent 来说描述与实现不一致就是说明书和机器对不上不报错只犯浑。所以第二个 commit 干了一件很笨的事定义const ROW_LIMIT: usize 200;四处统一引用它。注释里写得斩钉截铁包装查询、执行、工具描述与截断文案四处统一引用本常量防止漂移。同时系统提示preamble里原来写死的数字也同步掉。学完这一步你能带走的第二个方法凡是会同时出现在给模型的描述和给机器的代码里的数字必须是同一个常量。这是 Agent 开发独有的纪律——传统软件里描述和实现漂移只是文档 bug在 Agent 系统里描述就是模型世界观的一部分漂移了模型就活在虚假的世界里。4. 第三步写个测试把描述和常量钉死常量统一了但人性是靠不住的——下次有人改了常量忘了改描述或者改了描述的措辞把数字写错了漂移又回来了。daw 的解法是写一个测试专门盯着这件事。#[test]fnrow_limit_matches_tool_description(){forlimitin[DEFAULT_ROW_LIMIT,10,1000]{assert!(tool_description(limit).contains(format!(超过 {limit} 行自动截断)),...);}}翻译成人话拿默认 200、下限 10、上限 1000 三个值分别渲染描述断言里面的数字和传入值对得上。以后谁改描述模板漏了数字测试直接变红。这个测试的名字就叫防漂移。我认为是全篇最值得抄的一行代码它把文档与实现一致从一种期望变成了一道门禁。很多团队的 Agent 工具描述都是手写文案改代码时顺手改不改全看良心——daw 选择不赌良心赌测试。学完这一步你能带走的第三个方法给你的每个 Agent 工具写一个描述一致性测试——描述里承诺的每一个数字、每一个行为都要有测试断言它和实现对得上。改实现不改描述应该和改坏逻辑一样被测试拦下来。5. 第四步从硬编码到用户自己拧——设置项 queryRowLimit常量测试跑稳之后daw 才做了最后一步把行数上限升级成用户可配的设置项queryRowLimit。注意这个时机——不是一上来就做配置而是在默认值经过验证、一致性有测试兜底之后才开放。顺序反了配置项就会变成我也不知道多少合适你自己试的甩锅。这个设置项的设计有五个细节每个都值得抄第一缺省 200。不配置就是 200——那个经过真实会话验证的数。配置项的默认值不是随便填是大多数人不用改也好用。第二钳位 10~1000。代码注释写得直白行数直接进 LLM 上下文过大的单查即可撑爆窗口前端 UI 限范围这里防手改文件。翻译成人话设置页输入框能限范围但用户可以直接改settings.json——手改个 100000 进去下次查询就把上下文撑爆了。所以读取时钳位小于 10 按 10大于 1000 按 1000。把度交给用户把界留给自己。第三读取容错一律回落默认。文件缺失、JSON 损坏、键缺失、值不是数字——一律回落 200不报错不崩溃。翻译成人话用户把配置文件改坏了程序默默用默认值继续工作而不是崩给用户看。第四改完下一查即生效无需重启。实现很糙快猛每次执行查询重读一次设置文件。tiny JSON 读一次开销忽略不计换来改完下一查即生效——没有缓存就没有缓存失效问题。第五工具描述动态注入当前值。工具描述不再写死超过 200 行自动截断而是按当前设置值动态渲染——用户改成 500模型看到的就是超过 500 行自动截断。描述必须说真话实现会变描述就得跟着动。截断文案也升级了“(结果已截断仅返回前 N 行。可在设置中调整行数上限”——限制用户之前先告诉用户门在哪。6. 为什么这样设计藏在四步背后的三条纪律回头看这四步——拍板数、常量统一、防漂移测试、可配化——其实是三条纪律的展开纪律一描述即世界观。在 Agent 系统里工具描述不是文档是模型理解世界的窗口。描述里的每一个数字都必须为真且必须持续为真。这就是为什么 daw 愿意为描述里的数字专门写一个测试——它保护的不是文档质量是模型的世界观不崩塌。纪律二先判断后机制。50→200 是判断从真实场景来常量统一是工程可配化是产品。很多团队的顺序是反的先做个配置项默认值拍脑袋描述手写不管一致性。daw 的顺序是数字先在真实会话里被验证再用工程手段保证不漂移最后才交到用户手里——交出去时上下界和容错都已想好。纪律三双通道输出。还有个藏在代码里的细节返回给 LLM 的是紧凑文本列名前 N 行纯文本避免灌满上下文而完整结构化结果通过 payload 发给前端 UI。翻译成人话模型和人看到的不是同一份结果——模型拿够推理用的就行前端展示用人要看时有全量数据。一份数据两种包装各取所需截的不是数据是进模型的那条通道。给开发者的建议先定一个用出来的数再谈可配置。从真实会话里找截断点写死跑两周。过早的配置项配置的是你的不确定。描述与实现共享同一个常量。凡是同时出现在工具描述和代码里的数字必须是同一个常量的两次引用。这是 Agent 开发的专属纪律。给工具描述写一致性测试。描述里承诺的数字和行为用测试钉死。改实现不改描述应该被测试拦下来和改坏逻辑同等对待。开放配置时同时给出界缺省、钳位、容错三件套。缺省是不用改也好用钳位防手改文件作死容错保证配置文件坏了程序不崩。配置变更要热生效描述要动态注入。读一次 tiny JSON 的开销换来改完即生效描述里的数字必须跟着当前值变——描述说真话模型才不瞎猜。截断时告诉用户门在哪。“(结果已截断仅返回前 N 行。可在设置中调整行数上限”——限制之前先给出口这是产品的基本礼貌。说到底daw 的行数上限回答了一个 Agent 开发者都要回答的问题模型一次该看多少答案是先看够用的再保证看到的是真的最后把遥控器交到用户手里——但遥控器两头永远有钳子守着。不替用户做决定但替用户守住底线。
返回列表