我们的文本转查询 Agent 从使用前沿模型时的 45 秒,降到了使用 GLM 5.3 Flash 时的 2 秒,在保持相同准确率的同时,成本仅为原来的 1/20。
我们在 Conversion 近期的大部分 AI 工作都集中在通用营销智能上。
营销自动化团队跨系统执行着广泛的工作:研究客户、构建受众群体、规划营销活动、撰写内容,以及根据绩效数据采取行动。我们一直在构建能够跨这些工作流进行推理,并使用熟练营销人员会使用的相同工具的 Agent。
这些系统受益于功能强大的通用模型。工作本身是开放式的,良好的判断力往往比快速完成任务更重要。
但我们也有一个积压的、更小、更聚焦的 AI 功能需求。其中之一是自然语言筛选器:让用户用日常英语描述一个受众群体,然后将该描述转化为一个他们可以在 Conversion 现有语句构建器中查看和编辑的筛选器。(在 Conversion 中,筛选器被称为语句。)
起初,这看起来像是一个直接的结构化生成任务。给模型提供可用的字段,描述输出格式,然后让它生成 JSON。结果发现,这比想象中要困难得多。

使用 GLM 5.3 Flash 在 5 秒内生成的复合语句。
以下面这个例子为例:
查找在过去 30 天内至少提交过一次演示表单,并且在一家拥有价值超过 50,000 美元开放商机的软件公司工作的联系人。
这要求系统能够:
- 找到用户所说的“演示表单”具体指哪个表单
- 确定哪个字段代表公司的行业
- 了解该工作区如何表示“软件”,这意味着要查看该字段中实际存储的值,而不是猜测
- 从联系人遍历到其公司,再到该公司的商机
- 确保“开放”和“超过 50,000 美元”应用于同一个商机
- 应用相对事件窗口
同时,它还需要足够快地完成所有这些操作,以提供筛选器界面的体验,而不是研究型 Agent。
这个看似简单的提示工程任务,变成了一个受限的文本转查询问题。解决它需要一个使用工具的 Agent、一个中间表示、一个确定性编译器以及一个语义基准测试。
我们通过最终生成的基准测试 Statement Bench,对八个模型进行了评估,包括 Claude Opus 5、Kimi K3、GLM 5.3 Flash 以及今天早上发布的 Gemini 3.8 Flash。结果如下。
为 Agent 提供工具
回答上述请求所需的大部分信息都特定于客户的环境。单个工作区可能包含数亿个历史字段值,以及其资产和对象。出于显而易见的原因,我们无法将所有信息都放入一个提示中。
我们第一个有用的架构决策是,不再将这个问题视为普通的结构化生成。相反,模型会收到一小套工具。它可以搜索字段、检查历史值,并解析特定于业务的资产,如表单、营销活动、电子邮件和受众群体。它仅在请求需要时才使用这些工具。
这个搜索基础设施的很大一部分来自我们最近的全局搜索工作,该工作提供了对 Conversion 中所有记录进行文本和语义搜索的能力。我们计划很快分享更多相关信息!
基本流程如下所示:
1自然语言请求2 |3 v4 使用工具的 Agent <-----------------+5 / | \ |6字段 资产 关系 | 带原因的拒绝7 \ | / |8 v |9 受限的中间表示 |10 | |11 v |12 验证器和编译器 ---------------+13 |14 v15 生产环境语句
这保持了初始上下文的精简。它也使失败更容易理解。如果一条语句是错误的,我们可以确定是 Agent 找到了错误的资产、选择了错误的字段、误解了关系、错误地表示了正确的意图,还是编译器存在 bug。这个区分后来对我们的评估循环变得非常重要。
创建一种更小的语言
使用工具解决了上下文问题,但没有解决延迟问题。
从早期反馈中得到的一个教训是:用户对专用界面中的延迟容忍度远低于聊天界面。
这指向了一个更广泛的悖论。我们设定延迟期望是基于任务给我们的感觉有多难,而不是对系统来说有多难。撰写内容感觉困难,因为我们能看到工作本身。描述一个筛选器感觉简单,因为我们的思维会默默地解析上下文、实体、关系和意图。对于模型来说,重建这些隐藏的假设就是任务本身。用户感知到的工作越少,他们留给系统完成工作的时间就越少。
根据早期反馈,我们设定了两个目标:对于常见查询,准确率超过 95%,响应时间约为 5 秒。
Conversion 拥有一种表达力丰富的内部查询语言。在我们早期的测试中,直接使用生产环境格式,只有像 Claude Opus 这样最大的模型才能可靠地生成它。即使是简单的语句也需要大约 45 秒。
可视化语句构建器只暴露了完整语言的一个子集。我们为这个子集创建了一个更小、对 Agent 更友好的中间表示。较小的模型可以使用更少的 token 来生成它,而一个确定性编译器则负责处理完整的生产环境格式。
考虑以下语句:
职位名称包含“总监”。
原始的生产环境语句如下所示:
1{2 "type": "LOGICAL",3 "version": 1,4 "logical": {5 "operator": "OR",6 "operands": [7 {8 "type": "LOGICAL",9 "version": 1,10 "logical": {11 "operator": "AND",12 "operands": [13 {14 "type": "VARIABLE",15 "version": 1,16 "variable": {17 "variableSchemaId": "550e8400-e29b-41d4-a716-446655440000",18 "where": {19 "type": "LOGICAL",20 "version": 1,21 "logical": {22 "operator": "AND",23 "operands": [24 {25 "type": "LOGICAL",26 "version": 1,27 "logical": {28 "operator": "CONTAINS",29 "operands": [30 {31 "type": "ATTRIBUTE",32 "version": 1,33 "attribute": {34 "name": "value"35 }36 },37 {38 "type": "CONSTANT",39 "version": 1,40 "constant": {41 "value": "Director"42 }43 }44 ]45 }46 }47 ]48 }49 }50 }51 }52 ]53 }54 }55 ]56 }57}
同一筛选器面向模型的表示是:
1{2 "field": "550e8400-e29b-41d4-a716-446655440000",3 "op": "contains",4 "value": "Director"5}
这个中间表示已经经历了多次迭代,最新版本是通过观察小模型在早期版本上失败而塑造的。一个重大的改进是引入了更好的同记录语义(这是模式验证无法捕捉到的):
1{2 "related": "OPPORTUNITY",3 "all": [4 { "field": "<stage uuid>", "op": "equals", "value": "Closed Won" },5 { "field": "<amount uuid>", "op": "gt", "value": 100000 }6 ]7}
这种模型与代码的分离为我们带来了一些有用的特性:
- 难以表达不支持的语句
- 同记录关系语义是可见的
- 字段和关系引用可以被验证
- 编译器可以独立于模型进行测试
- 生成的语句在现有 UI 中仍然可编辑
中间表示最终简化了模型的工作:Agent 解析用户的意图并生成一个受限的计划;代码则处理生产环境格式。
构建一个语义基准测试
一个输出可能完全有效,但仍然可能是错误的。以这个请求为例:
在拥有价值超过 100,000 美元已赢单商机的公司工作的联系人。
联系人属于一家公司,而一家公司可以拥有多个商机。匹配这个筛选器意味着遍历关系(联系人到公司,公司到商机),并沿途检查两个条件:交易已赢单,且交易价值超过 100,000 美元。
难点在于这些条件必须对同一个商机成立。如果它们被独立检查,一家拥有一个已赢单的 20,000 美元交易和一个开放的 150,000 美元交易的公司,可以同时满足这两个条件:每个条件匹配一个不同的交易。模式验证永远无法捕捉到这一点。
一旦有几个这样的例子通过了,编辑提示就有可能使它们退化。我们需要一种方法来检查含义,而不仅仅是有效性,并且在每次有变化时都进行检查。
我们围绕产品的行为构建了 Statement Bench,这些行为源自我们客户之前构建的匿名受众模式。该测试套件现在包含 15 个类别的 100 个案例,例如纯字段条件、事件、相对和日历时间窗口、关系以及复合查询。
每个案例都在一个逼真的工作区沙盒中运行。Agent 接收与生产环境中相同的数据和工具。
评估器检查多个层面:
- Agent 是否返回了一条语句?
- 中间表示是否满足其模式?
- 引用的字段和关系是否存在?
- 语句能否编译并通过生产环境验证?
- 它是否代表了请求的含义?
- 它需要多少模型步骤、工具调用、token 和被拒绝的提交?
第五点是最有趣的,因为有效性并不能保证语义等价。
语义检查会读取编译后的语句,断言诸如“一个商机条件同时携带了阶段和金额”、“一个电子邮件事件,其类型是点击,而不是打开”,或者“一个网络研讨会条件,而不是自定义营销活动条件”之类的事情。
运行一个评估驱动的优化循环
这个基准测试改变了我们继续开发该功能的方式。我们不再要求编码 Agent“改进提示”或“实现一个新的中间表示”,而是可以给它一个可执行的改进定义。
循环如下所示:
- 运行基准测试
- 根据根本原因对失败进行分组
- 检查 Agent 的工具轨迹和提交的中间表示
- 更改提示、工具、验证器或编译器
- 再次运行完整的基准测试
- 仅当更改在不引入回归的情况下改进了系统时才保留它
编码 Agent 可以使用基准测试来比较模型、试验中间表示、改进工具描述,并自主优化提示。每次更改后运行完整测试套件也防止了我们过度拟合于个别失败,我们还保留了另外 50 个案例来确认这一点。
一些更改带来了最大的改进:
- 将路径、类型和结构移入编译器。 我们的第一个中间表示让模型显式写出所有关系:联系人到公司,公司到商机。字段的元数据已经隐含了该路径,因此编译器现在可以推断它。我们对日期、类型转换、否定放置和分组嵌套也做了同样的处理。将规则移入编译器简化了中间表示并减少了模式失败。
- 附带解释和修复方案进行拒绝。 每次模式和编译器的拒绝都会说明应该写什么(如果可用的话):“gt 不能在此字段上取反;请使用 lte”、“从 campaign_list 复制 id”。小模型在一两次重试后就能收敛,生产环境模型每百个请求中只有几个被拒绝。
- 为小模型结构化提示。 重新组织提示并没有改变准确率,但它将重试次数减半,这直接改善了延迟。这受到了 Anthropic 的 提示最佳实践 的启发。
- 使用示例而非散文。 在我们的格式参考中增加两个额外的示例,解决了一类用大段解释未能解决的遗漏问题,将拒绝提交的数量大致减半。
- 提供完整的上下文,或者不提供。 模型在调用工具之前会优先使用上下文中的内容。当上下文包含一组部分或不带标签的字段时,模型会使用最近的字段而不是进行搜索,从而产生语义不正确的语句。通过减少部分上下文并鼓励工具调用,我们提高了构建率并将输入 token 减少了五分之一。
最终的生产环境配置,GLM 5.3 Flash,完成了所有 100 个基准测试案例,中位延迟为 2.3 秒,第 95 百分位延迟为 7.1 秒。并且,100 个中有 97 个在语义上是正确的。与最初的生产环境格式方法相比,简单筛选器从大约 45 秒缩短到略高于 1 秒,成本仅为原来的 1/20。
在 Statement Bench 上比较模型
这个基准测试也为我们提供了一种在实际任务上比较模型的方法。
在 2026 年 9 月 2 日,我们在八个模型上运行了相同的 100 个案例。每个模型都收到了相同的提示、工具、中间表示、编译器和 30 秒的请求超时时间。
提供商路由、提示缓存和临时推理负载都会影响延迟。
模型
有效构建
语义正确
P50 延迟
P95 延迟
缓存读取
工具调用
被拒绝的提交
每 1,000 次请求预估成本
Claude Opus 5
100/100 (100%)
100/100 (100%)
3.16s
8.53s
91.1%
162
0
$27.51
GLM 5.2
100/100 (100%)
100/100 (100%)
4.38s
13.02s
93.5%
201
5
$14.94
Kimi K3
100/100 (100%)
100/100 (100%)
5.17s
11.84s
34.3%
157
0
$48.51
GLM 5.3 Flash
100/100 (100%)
97/100 (97%)
2.34s
7.07s
92.8%
163
2
$1.33
DeepSeek V4 Pro
96/100 (96%)
96/96 (100%)
5.53s
24.31s
47.8%
172
1
$12.00
Gemini 3.7 Flash
77/100 (77%)
77/77 (100%)
15.14s
30.01s
26.5%
228
1
$18.24
Gemini 3.8 Flash
76/100 (76%)
76/76 (100%)
14.29s
30.01s
35.4%
266
1
$27.44
DeepSeek V4 Flash
56/100 (56%)
55/56 (98%)
6.79s
30.00s
41.5%
100
1
$0.56
预估成本基于 2026 年 9 月 2 日各提供商列出的非促销费率,使用观察到的输入、缓存输入和输出 token 计算每 1,000 次尝试请求的成本。缓存输入按提供商公布的缓存读取费率计费(如果提供商公布了该费率),否则按完整输入费率计费。

图 1. 正确性与成本对比。GLM 5.3 Flash 达到了 97% 的正确率,成本约为 Claude Opus 5 的二十分之一。

图 2. 延迟分布,中位数和第 95 百分位,按 P95 排序。
一些发现值得注意。
模型大小和价格都不能预测延迟。 最快的模型是最小和最便宜的。第二快的模型是最大和最贵的。
失败已从错误答案转变为缓慢答案。 八个模型中有六个在它们完成的每条语句上都是语义正确的;它们之间的差异几乎完全在于有多少请求在超时时间内完成。在中间表示和提示的早期迭代中,大多数较小的模型在构建步骤就未能通过基准测试,语义准确率低于 50%。
推理 token 的消耗超过了工具调用。 Gemini 3.8 Flash 在其 192,000 个输出 token 中花费了 180,000 个用于推理,并进行了 266 次工具调用;Claude Opus 5 花费了 813 个 token 用于推理,进行了 162 次调用,并完成了所有案例。我们的全局搜索工作将每次工具查找时间降低到了毫秒级,因此剩余的成本在于模型在两次调用之间的周转。
要点
模型擅长解决歧义,代码擅长强制执行精确性,而我们早期的大部分失败都源于要求模型同时做这两件事。构建这个 Agent 的工作,就是决定这两者各自应负责哪一部分。我们相信,对于文本转 SQL 和大多数其他自然语言界面来说,情况也是如此。
如果你对这些问题的任何一个感兴趣,请联系我们!我们正在招聘。





