不鸽工程队 —— 大模型评测作业
作业基本信息
| 项 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 202601福大-软件工程实践-W班 |
| 这个作业要求在哪里 | 软件工程实践——大模型评测作业 |
| 这个作业的目标 | 编写自动化测试程序,让两个大模型在 3 个购车场景、每个场景 3 次独立运行中完成 5 轮多轮对话任务,从约束命中、信息真实性、多轮一致性、指令遵循、稳定性、成本延迟六个维度量化评分并可视化;再从软件工程视角分析开发时间、同类产品、BUG 成因、市场与产品规划 |
| 其他参考文献 | 《构建之法》(第 8 章功能的定位和优先级、8.6 节对工作的估计、第 9 章项目经理、第 14 章软件的质量);IDC《中国 AI 软件市场半年度追踪,2026H1》;CNNIC《生成式人工智能应用发展报告(2026)》;工业和信息化部《2026 年 1—8 月份软件业运行情况》;两个平台的官方 API 文档 |
目录
- 作业基本信息
- 第一部分 调研,评测
- 1. 大模型一:GLM-4.5-Flash(智谱清言 / 智谱开放平台)
- 1.1 体验
- 1.1.1 介绍与使用
- 1.1.2 优缺点分析
- 1.1.3 用户对产品的改进意见
- 1.1.4 用户采访:要点与去向
- 1.2 自动化测试
- 1.2.1 任务中的表现
- 1.2.2 失败案例分析:标题写着"符合条件",表里却有三款车长超限的车
- 1.3 结论
- 2. 大模型二:Qwen3.8-Flash(千问 / 阿里云百炼)
- 2.1 体验
- 2.1.1 介绍与使用
- 2.1.2 优缺点分析
- 2.1.3 用户对产品的改进意见
- 2.1.4 用户采访:要点与去向
- 2.2 自动化测试
- 2.2.1 任务中的表现
- 2.2.2 失败案例分析:把"让我重新检查一下"写进了给用户的答复
- 2.3 结论
- 3. 两个大模型的对比与具体测试环境
- 3.1 测试环境与统一条件
- 3.2 三个测试场景与预期结果
- 3.3 评分维度与判定标准
- 3.4 自动化测试代码实现
- 3.5 六维得分对比
- 3.6 分场景表现对比
- 3.7 成本与延迟对比
- 3.8 选型结论
- 3.9 改进方案与备选方案比较
- 4. 对同学的采访
- 4.1 采访对象的背景、为什么选 TA、TA 的需求
- 4.2 TA 实际使用的产品栏目
- 4.2.1 使用路径小结
- 4.2.2 智谱清言(先使用)
- 4.2.3 千问(后使用)
- 4.3 使用过程中的问题与亮点
- 4.3.1 卡点
- 4.3.2 亮点
- 4.3.3 最重要的一个瞬间
- 4.3.4 观察与推测的分离
- 4.4 TA 觉得从用户体验角度需要改进的地方
- 4.5 TA 的推荐意愿
- 4.6 本次采访的局限
- 第二部分 分析
- 1. 开发时间估计
- 2. 同类产品对比排名
- 3. 软件工程方面的建议
- 3.1 我们用的平台与测试系统,分别体现在哪三个层次
- 3.2 四个角度的工程改进建议
- 4. BUG 存在的原因分析
- 5. 市场概况
- 6. 产品规划
- 7. 大模型对我们现实生活带来的影响
- 附:代码仓库与实验材料
- 附:团队分工与贡献度
第一部分 调研,评测
本次被测的两个产品:智谱开放平台的
glm-4.5-flash与阿里云百炼的qwen3.8-flash。前者对应的 C 端产品是智谱清言(chatglm.cn),后者对应千问(qianwen.com)。
1. 大模型一:GLM-4.5-Flash(智谱清言 / 智谱开放平台)
1.1 体验
1.1.1 介绍与使用
智谱清言(chatglm.cn)是智谱面向 C 端的对话产品,网页端与开放平台 BigModel 共用同一批模型,但入口不同、默认配置不同——这一点在后面的实测里成了关键差异。
我们使用 Chrome 真实浏览器、干净配置目录、未登录(游客模式)完成体验。
智谱清言无需注册也能使用,自动分配"访客_f5748a"身份,从打开首页到发出第一条消息,注册步数为 0。首页侧栏共 8 个功能入口(AI 画图、AI 生视频等),模型可下拉切换,默认为 GLM-5.3-Flash 极致;联网搜索默认开启且回答自带来源角标,首轮回答底部标注"30 个来源",每行表格都带可点的引用(autohome、zol 等);"深度思考"有独立开关,思考过程可折叠展开。
我们在网页端的测试中与 API 侧实测使用同一份提问稿(预算 20 万 / 城市通勤 / 有固定车位 / 车长 ≤ 4.7m,要求输出 3 款车的 5 列参数表),保证网页端与接口端可以横向对比。




它解决了用户的问题吗? 网页端解决了,而且解决得干净:两轮对话里硬约束全部守住,第二轮还**主动在备选池里标出"秦PLUS EV 4765mm ⚠️ 已超 4.7 米,仅作参考排除"**——这是用户没有要求它做的动作。
但接口端(闭卷、无联网)同一道题的表现相反:把 4765mm 的车写成了"完美符合 4.7 米限制"(详见 1.2.2 失败案例分析)。同一个厂商、同一道题,接了搜索引擎的版本把错误纠正了,闭卷的版本把错误说成了"完美符合"。 两个入口长得一模一样,用户不会知道哪一次回答背后有检索。
1.1.2 优缺点分析
| 维度 | 优点 | 缺点 |
|---|---|---|
| 数据量 | 网页端默认联网,回答带来源角标可回查;官方数据源占比高 | API 闭卷时车型参数记忆不可靠(4765mm 事件);新款车型受训练数据截止时间限制 |
| 界面 | 游客即用、零注册门槛;思考过程可折叠;流式输出 | 联网开关可发现性低(受访者找约 90 秒未找到,靠"30 个来源"反推);游客态未发现会话导出入口 |
| 功能 | 结构化表格输出稳定;文件上传、多模态入口齐全 | 分享、导出等部分功能需登录,游客态无法实测 |
| 准确度 | 网页端硬约束全部守住,且主动排除超标备选 | API 端约束命中率仅 47.6%(S1 场景),存在"凑数"倾向 |
| 速度 | 回答短、token 省(单次约 24.3k) | 单轮平均 30.5 秒,长表格任务要等一分多钟 |
1.1.3 用户对产品的改进意见
- 提速。 受访者原话:「智谱那个答题特别慢,一直显示'思考结束'然后才出字,我盯着屏幕等了一分多钟。」
- 把联网开关显式化。 联网与否直接决定答案质量(见上文网页端与接口端的对照),但开关藏在设置深处,用户只能靠"来源角标"反推当前状态。
- 主动追问缺失上下文。 受访者原话:「我希望它一开始就问我车位多长、家里几口人,别我给什么答什么。」
1.1.4 用户采访:要点与去向
本模型的用户采访不单独成节:两位被测模型共用同一位受访者、同一份任务卡,完整记录(背景、栏目、问题与亮点、改进意见、局限,含 14 张聊天截图)统一放在本文 「4. 对同学的采访」 一节,这里只留与本模型直接相关的三条结论:
- TA 用智谱清言完成了两轮对话,上报的推荐结果(海豹 06GT、元PLUS、ID.3)与我们的同日独立实测完全一致,可交叉核验。
- TA 明确肯定的动作是第二轮那张"带勾的核对表":模型主动标出"秦PLUS EV 4765mm 已超,直接排除",TA 评价"这个动作感觉挺专业的"。
- TA 提的两条改进意见(提速、主动追问上下文)已并入 1.1.3 用户对产品的改进意见。
1.2 自动化测试
测试环境与统一条件、三个场景的预期结果、六维评分标准、测试程序,全部写在本文 「3. 两个大模型的对比」3.1–3.4 节。本模型使用的场景、提示词、车型数据与参数与那套设置完全相同,本节只呈现本模型自己的结果。
1.2.1 任务中的表现
9 次任务成功,加权总分 86.7。三个场景拆解如下:
| 场景 | 约束命中率 | 幻觉次数 | 多轮一致性 | 平均单轮延迟 | 单次 token |
|---|---|---|---|---|---|
| S1 城市通勤 | 47.6% | 0 | 100 | 37.8 s | 25,549 |
| S2 家庭出行 | 61.1% | 0 | 100 | 34.1 s | 24,732 |
| S3 跨城通勤 | 100% | 0 | 100 | 19.5 s | 22,618 |
掉分集中在"硬约束"这一项,而且是稳定复现。 S1 要求车长 ≤ 4700 mm,三次运行的最终推荐集合里都出现了超长车型:秦PLUS DM-i(4765 mm)3/3 次、银河 L6(4782 mm)3/3 次、秦PLUS EV(4765 mm)2/3 次。S2 要求预算 25 万、7 座、五星,三次里汉兰达(26.98 万)出现 3/3 次——超预算 2 万元。也就是说,它在"选项不够"时倾向于放宽约束凑数,而不是明确告诉用户"符合的只有 2 款"。
S3 拿到满分,原因值得说明:不是它变强了,而是题变窄了。 第 3 轮需求变更后,符合"无充电桩 + 插混"的只剩秦PLUS DM-i、银河 L6、五菱星光 3 款,选择空间小到不需要权衡,三次运行的推荐集合完全相同。这恰好说明它的失败模式是多约束同时生效时的取舍能力,而不是记不住上下文——S3 的上下文保持它做得很好。
延迟倒挂也值得记一笔。 S1 平均单轮 37.8 秒,S3 只有 19.5 秒。差别不在算力,而在输出长度:S1 写了五款车的对比表和逐条理由,S3 只写三款。这也解释了为什么它单次 token 只有 25.5k——它靠"少说话"省下的成本,代价是约束执行不到位。
幻觉列写 0 的原因:评分脚本最初标记了 5 次"库外品牌:理想",人工复核后全部判定为误判——原句是"是您 15 万预算内最理想的选择""是二孩家庭三代同堂出行的理想选择",这里的"理想"是形容词,不是理想汽车。按规则回滚扣分后真实性实为 100 分:9 次任务中它没有编造过任何一款不存在的车型,也没有编造过库外参数。 这也是"启发式先扣分、人工再复核"这套机制存在的意义。
1.2.2 失败案例分析:标题写着"符合条件",表里却有三款车长超限的车
场景与轮次:S1 城市通勤,第 3 轮(用户要求"把符合条件的车型的动力、油耗、空间、安全配置做个对比表")
具体表现:GLM 输出的表格标题是 **
## 符合条件车型对比表**,表内 5 款车里 3 款的车长超过 4700 mm——而且车长就印在同一行的"车长(mm)"列里,它自己写下了矛盾:车型 价格(元) 车长(mm) 是否合规 丰田卡罗拉 122,800 4,635 ✅ 日产轩逸 119,000 4,641 ✅ 比亚迪秦PLUS DM-i 99,800 4,765 ❌ 超 65 mm 比亚迪秦PLUS EV 129,800 4,765 ❌ 超 65 mm 吉利银河L6 119,800 4,782 ❌ 超 82 mm 单轮(非多轮)直调 API 时同样复现:它甚至给秦PLUS DM-i 写了推荐理由"车长 4765mm,完美符合 4.7 米限制"(原始响应见仓库
study/trial_logs/glm_s1_raw.json)——超限 65 mm 的车被同一行文字盖章为"完美符合"。测试记录:
records/glm_s1_1.json第 6 条消息(第 3 轮回复)。同一现象在glm_s1_2、glm_s1_3中重复出现(秦PLUS DM-i 与银河 L6 均 3/3 次),S2 里对应的表现是把 26.98 万的汉兰达列入 25 万预算的候选(3/3 次)。三次复现 + 单轮复现,可排除随机性。
原始记录节选(records/glm_s1_1.json,未改写)
记录头字段:
{
"run_id": "glm_s1_1",
"model": "glm-4.5-flash",
"platform": "zhipu",
"scenario": "s1",
"repeat": 1,
"started_at": "2026-11-08T17:02:09.078720200+08:00",
"params": { "temperature": 0.3, "max_tokens": 1200, "stream": false },
"usage": { "prompt_tokens": 23690, "completion_tokens": 2706 },
"latency_ms": [45474, 48032, 42115, 24876, 14126],
"errors": []
}
turns[5].content(文件里第 6 条消息,模型第 3 轮回复)原文节选:
## 符合条件车型对比表
| 车型 | 品牌 | 价格(元) | 动力类型 | 油耗(L/百公里) | 车长(mm) | 轴距(mm) | 安全配置 | 保值率(3年) |
|------|------|----------|----------|----------------|----------|----------|----------|-------------|
| 丰田卡罗拉 | 丰田 | 122,800 | 汽油 | 5.6 | 4,635 | 2,700 | ESP, 6安全气囊, AEB, 全速域ACC, 车道保持 | 0.62 |
| 日产轩逸 | 日产 | 119,000 | 汽油 | 5.9 | 4,641 | 2,712 | ESP, 6安全气囊, AEB | 0.55 |
| 比亚迪秦PLUS DM-i | 比亚迪 | 99,800 | 插电混动 | 4.6 | 4,765 | 2,718 | ESP, 6安全气囊, AEB | 0.52 |
| 比亚迪秦PLUS EV | 比亚迪 | 129,800 | 纯电 | - | 4,765 | 2,718 | ESP, 6安全气囊, AEB | 0.48 |
| 吉利银河L6 | 吉利 | 119,800 | 插电混动 | 4.2 | 4,782 | 2,752 | ESP, 6安全气囊, AEB, 车道保持 | 0.48 |
**空间表现**:
- 轴距方面:银河L6(2,752mm) > 秦PLUS DM-i/秦PLUS EV(2,718mm) > 轩逸(2,712mm) > 卡罗拉(2,700mm)
- 所有车型车长均控制在4.8米以内,适合窄车位
(节选表格与"空间表现"两段,原文另含动力、油耗、安全配置、保值率四项逐条分析。)注意最后一行:用户给的硬约束是 4.7 米,模型自己在正文里把标准写成了"4.8 米以内"。
- 可能原因:
- 可观察到的事实:车长上限写在 system prompt 的"预算以外的硬约束"一行里,用户第 2 轮又原话重申过一次("车长必须控制在 4.7 米以内");但它输出的 5 款车全部只满足了"预算"这一条,说明它把预算当成了过滤条件,把车长当成了展示字段。
- 推测:模型在处理"预算 + 车长"这类混合约束时,倾向于把金额类条件当作硬过滤,把尺寸类条件当作"描述性信息";多约束并存时,后出现的数值约束权重被稀释。
1.3 结论
适合:约束少、或约束已被收窄到"选项本身就是答案"的任务——比如"在这 3 款里选一款""这个配置值不值得多花 2 万"。S3(需求变更后只剩 3 款插混)它拿到 97.5 的均分,三次运行的推荐集合完全相同,说明这类任务里它结论明确、前后一致、输出克制。
不适合:需要同时满足 3 条以上硬约束的筛选任务。S1(预算 20 万 + 车长 ≤ 4.7m)它只拿到 79.1 分,约束命中率 47.6%——而且失败不是"没看到约束":车长上限写在系统提示词里、用户第 2 轮又重申过一次,它照样把 4765 mm 的车放进标题为"符合条件车型对比表"的表格。它看懂了约束,只是没把约束当过滤器用。 这类任务必须外挂一层校验,不能让模型自己把关。
本模型的特征:稳、省、话少,但在多约束取舍上不可靠。
2. 大模型二:Qwen3.8-Flash(千问 / 阿里云百炼)
2.1 体验
2.1.1 介绍与使用
千问(qianwen.com)是阿里的 C 端对话产品,与开发者平台百炼(bailian.console.aliyun.com)是两个入口。体验方式沿用本次评测的统一方法:游客模式、同一份提问稿、用 Chrome 真实浏览器在干净配置目录下实测。
千问同样游客 0 步注册,匿名临时会话直接对话;界面是"日常/工作"双分区加输入框 6 个功能按钮,信息密度高于智谱清言;联网默认开启,回答头部显示"已完成分析,共参考 17 篇资料",正文带上标引用,底部有"22 篇来源"面板,其中包含吉利汽车官方数据等官方来源。




它解决了用户的问题吗? 网页端解决了。两轮全部守住硬约束,且第二轮**主动提醒"领克 20 大尾翼版车长 4520mm,虽未超但普通版 4495mm 更好停"**——这是超出提问范围的增值信息。
接口层实测(网页端看不到的部分):同一提问稿直调 API(qwen3.8-flash,max_tokens 1500)时出现三个网页端完全看不见的问题:① 输出 completion_tokens 恰为 1500、finish_reason = length,回答被硬截断,最后一款车的推荐理由没写完;② 关闭 enable_thinking 后响应体仍返回非空 reasoning_content;③ 同一 Key 下 qwen-flash 报 AllocationQuota.FreeTierOnly(免费额度耗尽)而 qwen3.8-flash 正常——免费额度按模型分别计算。另外它还出现了"过度自我否定":连续 4 款车自查超标、反复替换,最终因 token 耗尽没给出完整结论(原始响应见仓库 study/trial_logs/qwen_s1_raw.json)。
2.1.2 优缺点分析
| 维度 | 优点 | 缺点 |
|---|---|---|
| 数据量 | 联网检索引用官方来源(吉利官方数据),来源面板透明 | API 闭卷时的自查无终止条件,会陷入"替换-再查-再替换"循环 |
| 界面 | 首屏界面干净,视觉效果清爽 | 首屏指引少,第一次使用的人可能找不到功能在哪 |
| 功能 | 位置个性化、版本差异提醒等增值行为;游客态历史会话保留 | 未发现会话导出;API 层"关思考"参数行为与文档预期不完全一致 |
| 准确度 | 网页端硬约束全守住且主动提醒细分版本;API 端 S1 约束命中率 100%,剔除理由逐条可查 | 长表格任务会撞 max_tokens 被截断;存在"先排除后推荐"的输出反复 |
| 速度 | 单轮 14.9 秒(13.4–16.6),交互响应快,适合实时对话 | 单次约 34.4k token,长表格任务成本偏高 |
2.1.3 用户对产品的改进意见
- 给自我校验设终止条件。 连续替换 4 次仍未收敛、最后被 token 截断,不如在第三轮替换后明确告知"以下选项均不完美,差异点在 XX"。
- 截断要有兜底。
finish_reason = length时前端只看到一份"没写完的表格",应提示"回答因长度限制被截断"。
2.1.4 用户采访:要点与去向
本模型的用户采访不单独成节:两位被测模型共用同一位受访者 P1、同一份任务卡,完整记录见本文 「4. 对同学的采访」 一节。与本模型直接相关的观察有三条:
- TA 在千问侧完成两轮对话,上报的推荐(领克 20、深蓝 S05、银河 E5)与我们的独立实测完全一致。
- TA 注意到"共参考 17 篇资料"的来源面板,但没有专门评价;TA 更在意"核对过程有没有亮出来",而不是品牌。
- TA 没有对千问单独提出功能建议,这一点如实记录,不代为补写。
2.2 自动化测试
测试环境与统一条件、场景、评分标准与测试程序见本文 「3. 两个大模型的对比」3.1–3.4 节,与本模型完全一致,本节只呈现本模型自己的结果。
2.2.1 任务中的表现
9 次任务成功,加权总分 85.2:
| 场景 | 约束命中率 | 幻觉次数 | 多轮一致性 | 平均单轮延迟 | 单次 token |
|---|---|---|---|---|---|
| S1 城市通勤 | 100% | 0 | 70 | 13.4 s | 35,014 |
| S2 家庭出行 | 77.8% | 0 | 80 | 14.8 s | 34,320 |
| S3 跨城通勤 | 100% | 0 | 70 | 16.6 s | 34,002 |
约束执行是它的强项,而且强在"会说出来"。 S1 三次全部满分:它把 6 款超长车逐条剔掉,并在正文里写明理由——"比亚迪秦PLUS DM-i/EV、吉利银河L6……车长超过 4700mm(分别为 4765mm 和 4782mm),不符合您的 maxLengthMm = 4700 硬约束"。它把硬约束当过滤器用,而且把过滤的过程摊开给用户看,用户不需要自己去核对哪台被剔掉了。
S2 的 77.8 分是因"凑数"扣的。 符合"25 万内 + 7 座 + 五星"的其实只有唐DM-i 和传祺M8 两款,它 2/3 次把汉兰达(26.98 万)也列进了候选。这是"合规选项不够时放宽约束凑数"的典型形态。
一致性 70 分要拆开看,里面真问题和假问题都有。 规则是"前轮判不符合、后轮又推荐"扣 30 分(有上限),9 条记录里 8 条被扣分(唯一满分的 qwen_s2_3 恰好也是它约束全对的那次)。逐条复核:大部分是跨轮的回头推荐——例如 qwen_s3_1 里五菱星光在第 5 轮被判不符合,随后仍被列入推荐,qwen_s3_3 里同一款车在第 5 轮、第 7 轮各出现一次;qwen_s2_1 里传祺M8 与唐DM-i 也各有一次"先判不符合、后进候选"。另有一部分是同一轮内先排除、再自我修正(见下面案例二里的思域),严格说属于"输出反复",不是"跨轮遗忘"。这条口径偏严,我们在结论里按"输出质量"而非"记忆能力"来解读它。
真实性 92 分同样是误判。 脚本标记的 3 次"虚构车型"是"吉利高效""比亚迪扎实""比亚迪体系"——品牌名后接形容词被规则当成了"品牌+型号"。原句里没有任何虚构车型,回滚后真实性维度同样为 100 分。本模型在 9 次任务里没有编造过任何一款车型或库外参数。
延迟是它最强的指标:13.4–16.6 秒/轮,五次请求就能把一张对比表出完。 但这不完全是效率优势——它每次消耗约 34k token,因为提示词回显和输出都更长。它用更多的 token 换更快的首字和更啰嗦的论证。
2.2.2 失败案例分析:把"让我重新检查一下"写进了给用户的答复
场景与轮次:S1 城市通勤,第 1 轮(用户只说"预算 20 万、城市通勤、要空间舒适安全")
具体表现:Qwen 在同一段回复里先排除、再自我推翻、然后把结论改回来,全过程都留在了正文里。它先写下思域"因价格略超预算上限",紧接着在同一段里"让我重新检查数据",逐条复查后确认思域"价格 149,900(<200,000)、车长 4,674(<4,700)符合条件",最后把思域列进"修正后的推荐列表"第 4 位(原句见下方原始记录节选)。
也就是说,一句"价格略超预算"的错误判断(14.99 万 < 20 万)被它自己发现并纠正了,但错误判断和被纠正的过程一起交给了用户。 接口层单轮实测中还观察到更极端的形态:连续 4 款车自查超标、反复替换,最终因 token 耗尽没能给出结论(
study/trial_logs/qwen_s1_raw.json)。测试记录:
records/qwen_s1_1.json第 2 条消息(第 1 轮回复)。这类"先排除后推荐"在 9 条记录里造成 8 条一致性扣分;其中部分是同一轮内的自我修正(如本条),更多是跨轮的回头推荐(如qwen_s3_1里五菱星光两次被判不符合、仍被列入推荐)。
原始记录节选(records/qwen_s1_1.json,未改写)
记录头字段:
{
"run_id": "qwen_s1_1",
"model": "qwen3.8-flash",
"platform": "dashscope",
"scenario": "s1",
"repeat": 1,
"started_at": "2026-11-08T17:24:59.339151200+08:00",
"params": { "temperature": 0.3, "max_tokens": 1200, "stream": false },
"usage": { "prompt_tokens": 30536, "completion_tokens": 4458 },
"latency_ms": [17932, 19600, 10801, 11921, 10806],
"errors": []
}
turns[1].content(文件里第 2 条消息,模型第 1 轮回复)原文节选:
*注:比亚迪秦PLUS DM-i/EV、吉利银河L6等插混/纯电车型虽然性价比高,但因车长超过4700mm(分别为4765mm和4782mm),不符合您的"maxLengthMm = 4700"硬约束,故未列入首选推荐。本田思域因价格略超预算上限(14.99万虽在20万内,但通常作为运动取向,且对比之下卡罗拉/朗逸更符合"舒适+安全"的通勤定位,若考虑思域也可作为备选,但其车长4674mm符合长度要求,价格14.99万也在预算内,因此思域其实也符合硬约束。让我重新检查数据:*
* **本田思域**: 价格 149,900 (<200,000), 车长 4,674 (<4,700). **符合条件!**
* **大众速腾**: 价格 141,900 (<200,000), 车长 4,791 (>4,700). **不符合条件。**
* **比亚迪秦PLUS DM-i**: 车长 4,765 > 4,700. **不符合条件。**
* **比亚迪秦PLUS EV**: 车长 4,765 > 4,700. **不符合条件。**
* **广汽埃安 AION S**: 车长 4,810 > 4,700. **不符合条件。**
* **比亚迪元PLUS**: 车长 4,455 < 4,700, 价格 135,800 < 200,000. **符合条件!** (纯电SUV,空间可能不如轿车宽敞,但安全性好)
* **五菱星光PHEV**: 车长 4,835 > 4,700. **不符合条件。**
**修正后的推荐列表(严格符合硬约束):**
1. **丰田卡罗拉** (汽油)
2. **大众朗逸** (汽油)
3. **日产轩逸** (汽油)
4. **本田思域** (汽油)
5. **比亚迪元PLUS** (纯电)
(节选"注"、自查清单与修正后列表三部分,原文另含 5 款车的参数对比表与逐条推荐理由。)
可能原因:
- 可观察到的事实:该模型已按统一设置在请求里显式关闭思考模式(
enable_thinking = false),但输出中仍保留大量推演语句、自我质疑和"重新检查数据"的过程文本;接口层实测还发现关闭后reasoning_content字段仍可能非空。 - 推测:虽然关闭了思考模式但模型的推演被混入了完成内容里。
- 可观察到的事实:该模型已按统一设置在请求里显式关闭思考模式(
2.3 结论
适合:硬约束多、且用户需要知道"这台为什么不行"的筛选任务。S1(预算 20 万 + 车长 ≤ 4.7m)约束命中率 100%,三次全部满分——它把 6 款超长车逐条剔掉,并在正文写明"比亚迪秦PLUS DM-i/EV、吉利银河L6……车长超过 4700mm(分别为 4765mm 和 4782mm),不符合您的 maxLengthMm = 4700 硬约束"。把约束当过滤器用,还把过滤过程写出来给用户看。 给 4S 店销售做内部筛选、或做面向专业用户的比价工具,这种"逐条给理由"的能力是加分项。
不适合:对输出纪律与答案稳定性要求高的决策留痕场景。它的短处不在"算不出来",而在"说出来的过程":① 同一段回复里先排除、再自我推翻,把"让我重新检查数据"写进正文(案例二);② 推荐集合在三次运行之间漂移,9 条记录里 8 条出现"先判不符合、后又推荐"。用户会把结论截图给家人看,答案漂移就是产品缺陷。
本模型的特征:准、快、话多,但会把错误藏在文本里。
3. 两个大模型的对比与具体测试环境
本节放必须把两个模型放在一起才成立的内容。两个模型各自的表现与失败案例见前面两节,这里不再重复描述。
3.1 测试环境与统一条件
下表是被测对象与接入参数:
| 项目 | GLM-4.5-Flash | Qwen3.8-Flash |
|---|---|---|
| 平台 | 智谱开放平台 BigModel(open.bigmodel.cn) | 阿里云百炼(bailian.console.aliyun.com) |
| 精确模型标识 | glm-4.5-flash | qwen3.8-flash |
| 接入方式 | 官方 HTTP API,OpenAI 兼容端点 /api/paas/v4 | 官方 HTTP API,OpenAI 兼容端点 /compatible-mode/v1 |
| 测试日期 | 2026-11-07 预跑,2026-11-08 正式 18 次 | 同左 |
| 计费档位 | 免费模型 | 新用户免费额度内 |
为什么选这两个平台:三个条件同时成立才可选:有免费额度(本次不购买付费额度)、有可实际体验的 C 端产品(体验与采访需要截图)、接口为 OpenAI 兼容格式(调用层可统一,减少变量)。DeepSeek 一个 Key 能同时跑通用与推理两款模型、成本最低,但其网页端只有一个对话输入框,体验与采访写不出内容,因此放弃。
统一的参数与条件:
- 两个模型使用相同的测试场景、提示词、车型数据、输出要求
- 统一参数:
temperature = 0.3,max_tokens = 1200,stream = false,思考模式均显式关闭 - 车型数据:自建固定数据集共 16 款车,覆盖 9.98 万–28.99 万、5/6/7 座、汽油/插电混动/油电混动/纯电四种能源类型。属教学模拟数据,非真实市场行情,每款车标注了年款、配置、价格口径(厂商指导价,非落地价)、参数单位与来源日期,见仓库
data/cars.json - 联网条件:API 测试未启用联网检索。作业提醒"避免将数据获取差异直接解释为模型推理差异",因此本次让模型只在给定车型库内作答——这样"是否老实待在被给定范围内"本身成为可测项。网页端体验则使用两平台的默认联网模式,两者分开呈现、不混用结论
- 工具调用:本次未接入官方 Function Calling。原因是时间预算内优先保证 18 次任务可复现,工具调用会引入"是否触发、参数是否正确"这一层额外变量,与六维评分混在一起难以归因
无法统一的设置:
- 思考模式的开关语义相同但参数名不同。 智谱是
thinking: {type: "disabled"},百炼是enable_thinking: false。适配层按平台分别下发,行为上等价,但"等价"是我们判定的,平台内部实现未必一致——接口层实测发现,百炼关闭enable_thinking后响应体里仍可能返回非空reasoning_content。 - 限流策略不同,只能靠串行执行换取公平。 智谱免费池实测约 1 并发,超出即 429;百炼按模型独立计算配额,耗尽返回 403。为保证两个模型遇到的重试次数接近,程序全程串行、不并发。
- tokenizer 不同,token 数不可直接等值比较。 同样一段中文在两个平台切出的 token 数不同,因此成本维度只看两次实验之间的相对差距,不看绝对值。
- system prompt 在模型内部的权重不可知。 我们观察到格式要求在长对话后期会被稀释,但两家稀释程度无法测量,只能靠"每轮重申"缓解——这是工程折中,不是严格意义上的"已统一"。
3.2 三个测试场景与预期结果
| 场景 | 预算 | 用途 | 预算外硬约束 | 是否含需求变更 |
|---|---|---|---|---|
| S1 城市通勤 | 20 万 | 上下班通勤 | 车长 ≤ 4.7m | 否 |
| S2 家庭出行 | 25 万 | 二孩家庭 | 6/7 座 + C-NCAP 五星 | 否 |
| S3 跨城通勤 | 15 万 | 每周跨城 | 纯电续航 ≥ 500km | 是,第 3 轮改为"无充电桩,改看插混" |
每个场景在正式运行前就写明了预期结果,判据直接来自车型库字段,不依赖人工印象:
| 场景 | 合规车型(预期答案) | 刻意设置的陷阱 | 考察点 |
|---|---|---|---|
| S1 | 5 款:卡罗拉(12.28 万 / 4635 mm)、轩逸(11.90 万 / 4641 mm)、朗逸(12.09 万 / 4670 mm)、思域(14.99 万 / 4674 mm)、元PLUS(13.58 万 / 4455 mm) | 6 款车在预算内但超过 4700 mm:秦PLUS DM-i(4765)、秦PLUS EV(4765)、银河 L6(4782)、速腾(4791)、AION S(4810)、五菱星光 PHEV(4835);另有 5 款超预算 | 能否执行一条与"推荐好坏"无关的纯数值约束 |
| S2 | 仅 2 款:唐DM-i(20.98 万 / 7 座 / 五星)、传祺M8(23.98 万 / 7 座 / 五星) | 汉兰达 26.98 万、GL8 28.99 万(均 7 座五星但超预算);五菱星光为 4 星且 5 座(双重不符) | 合规选项极少时会不会"凑数"推荐不合规的车 |
| S3(变更前) | 3 款纯电:秦PLUS EV(12.98 万 / 510 km)、AION S(13.98 万 / 510 km)、元PLUS(13.58 万 / 510 km) | 插混车型在变更前全部不合规 | 第一阶段筛选是否严格 |
| S3(第 3 轮变更后) | 3 款插混:秦PLUS DM-i(9.98 万)、银河 L6(11.98 万)、五菱星光 PHEV(9.98 万) | 变更前的三款纯电此时全部不合规 | 上下文保持:能否用新约束覆盖旧约束 |
场景配置以 JSON 形式固化在仓库里,S3 的 mutationTurn 字段就是需求变更轮次的声明:
{
"id": "s3",
"name": "跨城通勤(含需求变更)",
"budgetCny": 150000,
"usage": "每周跨城往返一次,单程约 120 公里",
"hardConstraints": { "energy": "纯电", "minRangeKm": 500 },
"userTurns": [
"预算 15 万,每周要跨城通勤一次,主要考虑纯电车型,续航得 500 公里以上,推荐几款。",
"另外我比较在意充电便利性和电池质保政策。",
"补充一个重要变化:我们小区装不了充电桩,纯电不太现实了,改看插电混动。",
"把符合新条件的插混车型做个对比表。",
"综合下来你最终推荐哪一款?说明理由。"
],
"mutationTurn": 3
}
评分规则在同一时间点冻结:六维权重、容差(价格自报偏差 25%)、车型别名表、变更判定轮次全部写在 contract/weights.json 与 scoring/rules.json 中,实验开始后不再修改。这一点很重要——如果跑完再调权重,任何结论都可以被"调"出来。
运行规模与上下文管理:
- 2 模型 × 3 场景 × 3 次 = 18 次完整多轮任务,合计 90 次请求、180 条消息
- 每次任务固定 5 个用户轮:提出需求 → 补充约束 → 要求对比表 → 追问细节 → 要求最终结论,即一次 run 有 10 条消息
- 同一 run 内保留完整对话上下文(messages 逐轮追加,不截断);不同 run 之间重新初始化,不共享历史
temperature固定 0.3,但两家接口都不提供固定随机种子,因此同场景的 3 次运行不可能完全一致。这不是模型"不稳定"的证据,而是采样本身带随机性——也正因如此,稳定性维度采用"推荐集合的相似度"而非"是否完全相同"- 实测规模:单次任务 token 消耗 22.3k–35.9k,墙钟耗时 63–284 秒;18 次串行共 34 分钟,累计 528,706 token(GLM 218.7k + Qwen 310.0k)
- 样本量说明:每个场景、每个模型仅重复 3 次,样本量较小,稳定性分数波动较大。本文结论仅适用于本次数据、场景与实验设置,不代表行业整体排名
3.3 评分维度与判定标准
| 维度 | 权重 | 判定标准 | 计算方式 |
|---|---|---|---|
| 约束命中率 | 25% | 推荐车型是否满足预算与全部硬约束 | 合规车型数 ÷ 最终推荐车型数 × 100。合规 = 价格在预算容差内,且车长/座位数/能源类型/续航全部满足,数据取自车型库,不做模糊判断 |
| 信息真实性 | 20% | 是否编造不存在的车型或参数 | 100 − 12×库外品牌数 − 8×疑似编造型号数 − 15×自报价格偏差超 25% 的项数(各分项设扣分上限,最低 0 分) |
| 多轮一致性 | 20% | 是否忘记或违背已给出的约束 | 基线 100;变更后仍推荐旧约束下的车型 −50;前轮已判"不符合"、后轮又推荐 −30。用户主动改需求按新约束判定,不计矛盾 |
| 指令遵循 | 15% | 是否按要求输出表格并给出明确结论 | 对比轮给出符合要求的表格 +50;最终轮有明确推荐结论 +30;最终轮给出 ≥2 条理由 +20(仅 1 条 +10) |
| 稳定性 | 10% | 3 次运行结果是否一致 | 同场景 3 次最终推荐集合的两两 Jaccard 相似度取均值 |
| 成本与延迟 | 10% | 单次任务平均耗时与 token 消耗 | prompt_tokens + completion_tokens 与 latency_ms 均值,在 6 个(模型×场景)单元间做 min-max 归一化后各占一半 |
3.4 自动化测试代码实现
程序用 Java 17 + Maven 编写,用 JDK 内置的 java.net.http.HttpClient 加 Jackson;评分脚本用 Python。全部代码在仓库,下面贴的是关键部分。
1. 运行方式:一条命令跑完 18 次
# 仓库根目录,Key 从环境变量读取,不落代码
bash run.sh --models glm,qwen --scenarios s1,s2,s3 --repeat 3 --out records
# 跑完 records/index.csv 必须正好 18 行(不含表头)
run.sh 只做三件事:读 .env 到环境变量(只打印"已加载(长度 N)",不打印 Key 本身)、检查两个 Key 是否存在、把参数转交 jar。缺少 Key 时给出提示但不阻断单模型运行——这样只测一个模型时另一个 Key 不必配。
if [ -f .env ]; then
set -a
. ./.env
set +a
fi
missing=0
for v in ZHIPU_API_KEY DASHSCOPE_API_KEY; do
val="${!v:-}"
if [ -z "$val" ]; then
echo "[warn] $v 未设置"
missing=1
else
echo "[ok] $v 已加载(长度 ${#val})"
fi
done
exec java -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -jar "$JAR" "$@"
2. 主流程:模型配置与三重循环
模型接入参数集中在一张表里,用 tag 做 run_id 前缀,换模型只改这一处:
/** 各平台的接入参数。模型 tag 用于 run_id,模型标识可覆盖。 */
private record ModelSpec(String platform, String baseUrl, String keyEnv, String defaultModel) {
}
private static final Map<String, ModelSpec> SPECS = Map.of(
"glm", new ModelSpec("zhipu",
"https://open.bigmodel.cn/api/paas/v4",
"ZHIPU_API_KEY", "glm-4.5-flash"),
"qwen", new ModelSpec("dashscope",
"https://dashscope.aliyuncs.com/compatible-mode/v1",
"DASHSCOPE_API_KEY", "qwen3.8-flash"),
"deepseek", new ModelSpec("deepseek",
"https://api.deepseek.com/v1",
"DEEPSEEK_API_KEY", "deepseek-chat")
);
主循环就是"模型 × 场景 × 重复次数",每一条记录用 run_id(glm_s1_1)标识,已成功的直接跳过,因此中断后可以原命令重跑:
for (String modelToken : modelTokens) {
String tag = modelToken.contains(":") ? modelToken.split(":")[0] : modelToken;
String modelId = modelToken.contains(":")
? modelToken.split(":")[1]
: defaultModelId(tag, specs);
LlmClient client = buildClient(tag, modelId, mock, temperature, maxTokens, specs);
DialogRunner runner = new DialogRunner(client, tag.toLowerCase(), carsJson,
temperature, maxTokens);
for (String scenarioId : scenarioIds) {
Scenario scenario = loader.load(scenarioId);
for (int r = 1; r <= repeat; r++) {
String runId = tag.toLowerCase() + "_" + scenarioId + "_" + r;
if (writer.isSuccessful(runId)) { // 只跳过成功记录
skipped++;
System.out.printf("[skip] %s 已完成,跳过%n", runId);
continue;
}
System.out.printf("[run ] %s ...", runId);
RunRecord record = runner.run(scenario, r);
writer.write(record);
done++;
// ... 打印 token、耗时、失败原因
}
}
}
int indexed = writer.writeIndex(); // 扫描目录重建 index.csv
3. 请求构造:一个适配层吃掉两家的参数差异
两家都宣称"OpenAI 兼容",但思考模式的开关参数名完全不同。写错不会报错,只会静默返回被截断的内容——这是本次踩得最深的一个坑,所以适配层按平台分别下发:
private String buildBody(List<ChatMessage> messages) throws IOException {
ObjectNode root = Json.PLAIN.createObjectNode();
root.put("model", model);
root.put("temperature", temperature);
root.put("max_tokens", maxTokens);
root.put("stream", false);
if (thinkingDisabled) {
// 两个平台关闭思考模式的参数名不同,必须按平台分别下发,
// 否则参数被忽略、模型仍会输出 reasoning_content,正文可能为空。
if ("zhipu".equalsIgnoreCase(platform)) {
root.putObject("thinking").put("type", "disabled");
} else if ("dashscope".equalsIgnoreCase(platform)) {
root.put("enable_thinking", false);
}
}
ArrayNode arr = root.putArray("messages");
for (ChatMessage m : messages) {
ObjectNode node = arr.addObject();
node.put("role", m.role());
node.put("content", m.content());
}
return Json.PLAIN.writeValueAsString(root);
}
响应解析还要区分"思考占满 token"和"真的没返回"——两者状态码都是 200,但原因完全不同,不区分就会把接口问题记成模型问题:
String content = msg.path("content").asText("");
String finish = choices.get(0).path("finish_reason").asText("");
// content 为空时给出可诊断的信息:区分「思考占满 token」与「真的没返回」
if (content.isBlank()) {
boolean hasReasoning = !msg.path("reasoning_content").asText("").isBlank();
throw new IOException("返回空 content(finish_reason=" + finish
+ ", 含 reasoning_content=" + hasReasoning + ")");
}
4. 多轮对话状态机:同一次任务内累积上下文
作业要求"同一次任务内保留对话上下文,不同运行之间重新开始对话"。实现上就是一个 messages 列表逐轮追加,每次请求把完整历史重发;run 方法每次调用都新建列表,天然满足"不同 run 不共享历史":
public RunRecord run(Scenario scenario, int repeat) {
String runId = modelTag + "_" + scenario.id() + "_" + repeat;
List<ChatMessage> messages = new ArrayList<>();
messages.add(ChatMessage.system(systemPrompt(scenario)));
List<String> userTurns = scenario.userTurns();
for (int i = 0; i < userTurns.size(); i++) {
String userText = userTurns.get(i);
messages.add(ChatMessage.user(userText)); // 追加用户轮
turns.add(new RunRecord.Turn(turns.size(), "user", userText, elapsedMs(t0)));
ChatReply reply;
try {
reply = client.chat(messages); // 带全部历史请求
} catch (Exception e) {
errors.add("第 " + (i + 1) + " 轮调用失败:" + e.getMessage());
break; // 一轮失败即终止,保留已产生的部分
}
String content = reply.content() == null ? "" : reply.content();
if (content.isBlank()) {
errors.add("第 " + (i + 1) + " 轮返回空内容");
}
messages.add(ChatMessage.assistant(content)); // 累积模型回复
turns.add(new RunRecord.Turn(turns.size(), "assistant", content, elapsedMs(t0)));
latencies.add(reply.latencyMs());
}
// ... 组装 RunRecord 返回
}
系统提示词把车型库和硬约束一次性注入,保证两个模型拿到完全相同的信息:
return """
你是一名专业的汽车选购顾问,需要根据用户需求推荐车型。
【可用车型数据】
以下是本次可选的车型库(教学模拟数据,只能从中推荐,不得编造不存在的车型):
%s
【当前场景】
场景:%s
预算:%d 元
用途:%s
预算以外的硬约束:%s
【回答要求】
1. 只在上述车型库范围内推荐,不得虚构车型或参数。
2. 每轮回答先给结论,再给理由。
3. 用户要求表格时,必须用 markdown 表格输出,表头写清项目与车型。
4. 用户修改需求后,以最新需求为准。
""".formatted(carsJson, scenario.name(), scenario.budgetCny(),
scenario.usage(), scenario.hardConstraintText());
5. 记录落盘:失败记录隔离,索引每次重建
失败记录写进 records/_failed/,既不丢证据,也不占正式记录位。"是否已完成"只认成功记录,避免出现"18 个文件都在、其中 3 个是空壳"的假齐活:
public boolean isSuccessful(String runId) {
Path file = outDir.resolve(runId + ".json");
if (!Files.exists(file)) {
return false;
}
try {
RunRecord r = Json.RECORD.readValue(
Files.readString(file, StandardCharsets.UTF_8), RunRecord.class);
boolean noErrors = r.errors() == null || r.errors().isEmpty();
boolean hasTurns = r.turns() != null && r.turns().size() >= 2;
return noErrors && hasTurns;
} catch (Exception e) {
return false;
}
}
index.csv 采用"扫描目录重建"而不是"逐条追加",这样断点续跑或重跑之后索引依然准确:
rows.add("run_id,model,scenario,repeat,status,turns,prompt_tokens,completion_tokens,"
+ "avg_latency_ms,started_at");
// ... 遍历 outDir 下所有 *.json,解析后拼一行
Files.write(outDir.resolve("index.csv"), rows, StandardCharsets.UTF_8);
6. 评分脚本:把"合规"变成可复现的判定
评分不靠人看,靠字段比较。violations() 拿一款车的参数去逐条比对当前生效的约束,返回空列表才算合规:
def violations(car: dict, constraints: dict, budget: int, budget_pct: float):
"""返回违反项的中文说明列表,空列表代表完全满足。"""
v = []
limit = budget * (1 + budget_pct / 100.0)
if budget and car.get("priceCny") and car["priceCny"] > limit:
v.append(f"价格 {car['priceCny'] / 10000:.2f} 万 > 预算 {budget / 10000:.0f} 万"
f"(允许上浮 {budget_pct:.0f}%)")
for key, want in (constraints or {}).items():
if key == "maxLengthMm":
got = car.get("lengthMm")
if got is None or got > want:
v.append(f"车长 {got} mm > {want} mm")
elif key == "minSeats":
got = car.get("seats")
if got is None or got < want:
v.append(f"座位 {got} < {want}")
elif key == "minRangeKm":
got = car.get("rangeKm")
if got is None:
v.append(f"无纯电续航数据(要求 ≥ {want} km)")
elif got < want:
v.append(f"续航 {got} km < {want} km")
elif key == "minSafetyStars":
got = car.get("cncapStars")
if got is None or got < want:
v.append(f"C-NCAP {got} 星 < {want} 星")
elif key == "energy":
allow = want if isinstance(want, list) else [want]
if car.get("energy") not in allow:
v.append(f"能源类型 {car.get('energy')} 不在 {'/'.join(allow)}")
return v
约束命中率的分母是"结论行点名的车型 ∪ 对比表里的车型"。只算结论会漏掉"把违规车型放进候选表"这种最典型的错误——GLM 的失败案例正是这一类:
# 候选集 = 对比表里的车型;结论集 = 结论行里点名的车型。两者取并。
# 只算结论会漏判“把违规车型放进候选表”这种典型错误。
table_text = ats[expect_idx].get("content", "") if 0 <= expect_idx < len(ats) else ""
cand_ids = cars_in_tables(table_text, matcher)
if not cand_ids:
for t in ats:
cand_ids = cars_in_tables(t.get("content") or "", matcher)
if cand_ids:
break
final_ids, basis = final_recommended(final_text, matcher, rules, exclusion_re)
scored_ids = list(dict.fromkeys(final_ids + cand_ids))
valid_ids = [cid for cid, c in cars.items()
if not violations(c, active, budget, budget_pct)]
good = [cid for cid in scored_ids if cid in valid_ids]
ch = 100.0 * len(good) / len(scored_ids)
评分脚本自身也有回归测试(scoring/selftest.py,14 条用例)。理由很简单:评测程序如果不被评测,它自己的错误会伪装成被测对象的错误,而且伪装得非常像——因为它输出的也是"分数"。
3.5 六维得分对比

指标:六维得分(分,0–100,外圈越大越好)|样本:每模型 9 次任务(3 场景 × 3 次)取均值|来源:scoring/out/summary.csv
| 维度(权重) | GLM-4.5-Flash | Qwen3.8-Flash | 领先方 |
|---|---|---|---|
| 约束命中率(25%) | 69.6 | 92.6 | Qwen +23.0 |
| 信息真实性(20%) | 93.3 | 97.3 | 复核后均为 100,实际打平 |
| 多轮一致性(20%) | 100 | 73.3 | GLM +26.7 |
| 指令遵循(15%) | 100 | 100 | 打平(都做到了表格 + 明确结论) |
| 稳定性(10%) | 84.4 | 76.3 | GLM +8.1 |
| 成本与延迟(10%) | 72.5 | 52.8 | GLM +19.7 |
| 加权总分 | 86.7 | 85.2 | GLM +1.5 |
总结:GLM 赢在"稳和省",Qwen 赢在"准"。 总分差 1.5 分,每个模型只有 9 条记录,这个差距不足以证明谁整体更强。有信息量的是六维的形状:GLM 的领先几乎全部来自一致性(+26.7)和成本(+19.7);Qwen 唯一的强项恰好是权重最高的约束命中率(25%),但它在一致性上丢的 20% 权重又把优势吐了回去。总分接近,本质上是因为两者把分丢在了不同的地方。
3.6 分场景表现对比

指标:各场景加权总分(分,0–100,纵轴自 0 起未截断)|样本:每模型每场景 3 次运行取均值,共 6 个柱|来源:scoring/out/scores.csv 的 total 列按 model × scenario 聚合
| 场景 | GLM 均分 | Qwen 均分 | 分差 | 谁赢 |
|---|---|---|---|---|
| S1 城市通勤(车长硬约束) | 79.1 | 86.6 | 7.5 | Qwen |
| S2 家庭出行(预算 + 座位 + 星级) | 83.7 | 83.6 | 0.1 | 打平 |
| S3 跨城通勤(含需求变更) | 97.5 | 85.4 | 12.1 | GLM |
总结:约束越"硬"、越依赖数值判断,Qwen 优势越大;选项越少、越接近"从 3 个里挑 1 个",GLM 优势越大。 S2 打平的原因也一致,两个模型都在"只有 2 款合规"的情况下凑了第 3 款(汉兰达),一起被扣分。S3 是 GLM 唯一大幅领先的场景,而它领先的方式不是"更强",是在选项收窄后不再犯错:三次运行推荐集合完全相同,而 Qwen 在同一场景里两次回头推荐了自己刚排除的五菱星光。
3.7 成本与延迟对比

指标:横轴为单次任务 token 消耗(千 token,prompt + completion),纵轴为平均单轮延迟(秒);圆点 = GLM,方点 = Qwen,左下角为"又快又省"|样本:6 个「模型 × 场景」单元,各 3 次取均值|来源:records/index.csv
| 指标 | GLM-4.5-Flash | Qwen3.8-Flash | 倍数关系 |
|---|---|---|---|
| 平均单轮延迟 | 30.5 s(19.5–37.8) | 14.9 s(13.4–16.6) | Qwen 快 2.0 倍 |
| 单次任务 token | 24,300 | 34,445 | GLM 省 29% |
| 18 次累计 token | 218,697 | 310,009 | 合计 528,706 |
| 18 次墙钟时间 | 约 23 分钟 | 约 11 分钟 | 串行合计 34 分钟 |
Qwen 单轮快一倍,代价是 token 多 42%(它把提示词和推演都复述了一遍);GLM 慢一倍,但回答短、token 省。
本次 18 次任务实测消耗 52.9 万 token,若按已公开的轻量模型定价区间粗估,把同一套评测扩到 10 个场景 × 5 次重复(100 次任务),Qwen 会比 GLM 多花约 42% 的费用。反过来,如果是面向用户的在线产品,Qwen 快 2 倍的单轮延迟意味着"用户等 15 秒"和"用户等 30 秒"的差别——这个差别在转化率上的价值,通常远高于那 42% 的 token 费。
3.8 选型结论
选 GLM-4.5-Flash,但必须在它外面包一层约束校验器。 理由三条,每条对应一个数据:
- 它的失败是可修的,对手的失败是难修的。 GLM 丢分在"没把车长当过滤器"——这个问题可以用一个 30 行的后置校验(拿最终推荐车型去
cars.json比对硬约束,不合规就退回重问)兜住,代价极低。而 Qwen 丢分在"把内心独白写进正文"和"回头推荐自己刚排除的车"——这属于对话状态管理与输出纪律问题,只能靠重写提示词或换整套对话框架,成本高且不确定。在工程上,选一个"错误可被外部规则拦截"的模型,比选一个"错误藏在文本里"的模型更安全。 - 它的稳定性更适合做可复现的产品。 S3 三次运行推荐集合完全相同(Jaccard 1.0),S1/S2 的差异也只在"凑数那第 3 款"上;Qwen 三次里换过推荐组合,同场景同参数下用户看到的答案不一致。对购车这类决策留痕场景(用户会截图给家人看),答案漂移是产品缺陷。
- 成本低 29%,而本次它并不慢到不可用。 单轮 30.5 秒确实比 Qwen 的 14.9 秒差一倍,但购车决策是低频、高客单价、用户愿意等的场景——没有人为省 15 秒而接受一辆车长超出车位 65 mm 的车。
反面场景同样明确: 如果做的是"约束极多、且每条都要向用户解释"的筛选工具(比如给 4S 店销售用的内部工具,需要逐条说明"这台为什么不行"),Qwen 更好——约束命中率 92.6% vs 69.6%,而且愿意为每条剔除写理由。换句话说:给消费者用的决策产品选 GLM + 校验层,给专业销售用的辅助工具选 Qwen。
3.9 改进方案与备选方案比较
问题(工程现象,非模型能力判断):多轮任务里上下文是累积的。第 5 轮的 prompt 包含 system(含整份 16 款车型的车型库)+ 前 4 轮问答,prompt token 随轮次近似线性增长——实测单次任务总消耗 22.3k–35.9k token,远高于"5 次独立问答"的直觉估计。在免费档的 TPM 限额下,这直接表现为:越到后面的轮次越容易触发 429,单任务耗时被拉长(本次实测最长单次 284 秒)。
方案 A(选定):车型库压缩 + 历史轮次摘要。 车型库以紧凑 JSON(无缩进无换行)注入 system;第 5 轮起把前 4 轮压缩成一条"已知约束 + 已排除车型"的摘要替换掉原始多轮历史,只保留最近 1 轮原文。
选它的理由:改动局限在提示词构造层,不影响记录结构、不影响评分脚本;而且它衡量的是"约束能否被保持"——摘要恰好是检验这一点的更强形式,模型必须在摘要丢信息时表现出来。
方案 B(备选,否决):缩短车型库 / 减少候选数量。 只给 5–8 款车,token 立刻下降,实现成本最低。
为什么不用:它改变了任务难度本身。车型库越小,"找到合规车型"越容易,两个模型的差距会被抹平,测出的差异不再能归因于多轮约束保持能力——不能为了让指标好看而降低任务难度。
方案 C(备选,否决):历史全保留,改用支持超长上下文的付费模型。
为什么不用:成本上升且掩盖问题。免费档的 TPM 限制本来就是真实工程约束,在约束下把方案做稳比换环境更有说服力;而且换模型会让"两个模型对比"变成"两种额度档位对比"。
验证方法(不需要真实实现即可执行):同一批场景用方案 A 与原策略各跑 3 次,比较 records/index.csv 里的 prompt_tokens 与 avg_latency_ms。关键不是 token 降了多少,而是约束命中率是否下降:若 token 显著下降但 S3 第 5 轮(需求变更后复核)的合规率保持,则方案成立;若合规率下降,说明摘要丢了关键约束,应调整摘要字段而不是放弃方案。
4. 对同学的采访
本节记录一位计算机相关专业同学(下称 P1)在 20:08–20:35 之间自行操作两个被测产品 C 端入口的全过程。两位被测模型共用这一位受访者、同一份任务卡,因此按时间顺序统一记录,不按模型拆成两段;两个模型各自的体验章节只引用与本模型相关的结论。
4.1 采访对象的背景、为什么选 TA、TA 的需求
基本信息:P1,计算机相关专业在读本科生。有软件开发经验(自述"之前用过智谱的 API 做过课设")。无购车经验。
为什么选 TA:选择有 API 使用经验但对汽车零先验的学生:一方面 TA 能独立完成双平台操作、不会卡在工具层,另一方面 TA 对车型参数没有先验知识,可以观察产品在"零领域经验"条件下能否支撑一次真实决策——这正是本次评测的核心场景(任务卡设定"你不懂车,看不懂参数")。
TA 的需求(TA 自己说的):TA 对任务的第一反应不是提问,而是核对约束的可理解性——「等一下,4.7 米是长还是短?一般的车位好像就 5 米多」。说明对普通消费者而言,"车长 ≤ 4.7 米"这类硬约束本身就需要被翻译成生活参照物,产品若能在输入端主动做这个换算,体验会完全不同。
4.2 TA 实际使用的产品栏目
采访方式:2026-11-08 20:08–20:35,QQ 文字采访,约 27 分钟。受访者自行操作两个平台并回传文字描述与截图,我们提供同一份任务卡(预算 20 万、城市通勤、家里有固定车位、车长不超过 4.7 米、要求 3 款车的参数表)。完整聊天记录 14 张按时间顺序列在下方,未做删改,仅对头像与昵称打码。














上述 14 张截图对应的时间线:20:08 开场与匿名约定 → 20:09 交付任务卡与统一提问稿 → 20:17 报告"两个都问了" → 20:18 上报两平台推荐结果 → 20:21 起追问信任度 → 20:29 评价"带勾的核对表"与响应速度 → 20:35 推荐意愿与收尾确认。
4.2.1 使用路径小结
| 项 | 记录 |
|---|---|
| 形式 | QQ 文字采访,受访者自行操作两个平台,回传文字描述与截图 |
| 时间线 | 20:08 开场 → 20:09 交付任务卡 → 20:17 报告"两个都问了" → 20:18 上报两平台推荐结果 → 20:18–20:35 追问 → 20:35 收尾确认 |
| 先用平台 | 智谱清言(理由见 4.2.2) |
| 是否使用联网 / 深度思考 | 未找到开关;从回答附带的来源数推断默认联网 |
| 是否上传文件 | 未使用(本轮未追问原因) |
| 总耗时 | 约 8 分钟完成任务 + 18 分钟追问 |
4.2.2 智谱清言(先使用)
TA 上报的结果:推荐海豹 06GT、元PLUS、ID.3。
(交叉核验:与 study/screenshots/01_体验记录.md 中我们同日实测的网页端结果一致,说明 TA 确实完成了真实操作。)
观察到的关键行为:
- 先用智谱的理由是工具熟悉度而非产品判断——「智谱。因为我之前用过智谱的 API 做过课设,有印象,千问没用过」。
- 被问及"联网搜索 / 深度思考"开关时,先答「没注意……我看看」,约 90 秒后回复「没找到开关。但是它回答上面写了'30 个来源',应该默认就是联网的吧」——通过回答的结果特征反推功能状态,而不是通过界面控件。说明该开关在界面上的可发现性低。
4.2.3 千问(后使用)
TA 上报的结果:推荐领克 20、深蓝 S05、银河 E5。
(与实测一致。)
观察到的关键行为:
- TA 主动对两个平台做了隐式对比(上报时并列陈述),但未展开差异,追问环节才给出态度(见 4.3.2)。
4.3 使用过程中的问题与亮点
4.3.1 卡点
| 卡在哪 | 具体表现 | TA 的原话 |
|---|---|---|
| 约束不可理解 | 拿到任务后先反问单位换算 | 「等一下,4.7 米是长还是短?一般的车位好像就 5 米多」 |
| 功能开关难发现 | 被提示后翻找约 90 秒仍未找到,靠来源角标反推 | 「没找到开关。但是它回答上面写了'30 个来源',应该默认就是联网的吧」 |
| 响应速度 | 等待生成约 1 分钟以上 | 「智谱那个答题特别慢,一直显示'思考结束'然后才出字,我盯着屏幕等了一分多钟」 |
4.3.2 亮点
| 亮点 | 具体表现 | TA 的原话 |
|---|---|---|
| 约束自查 | 第二轮追问后逐条核对并主动剔除超标备选 | 「我问它车长有没有超的,它回了一个带勾的表,一条一条列出来说符合,还说备选里秦PLUS EV 4765 已超,直接排除。这个动作感觉挺专业的」 |
| 无需人工复核的过滤 | TA 主动补了一句,把这次剔除理解成产品的稳定行为,而不是一次偶然 | 「它自己会把不合格的剔掉,不用我再问」 |
4.3.3 最重要的一个瞬间
对可信度的追问中,P1 给出了一个分层答案:「7 成吧,主要是价格我不信,车长我信」。追问原因,TA 的解释是:「车长是个固定数字吧,写错了很容易被查出来。价格每个地方优惠都不一样,它给的肯定是指导价」。
这段话说明普通用户并非无条件信任模型,而是按"错误可被发现度"给不同字段分配信任:可验证、有客观基准的字段(车长)获得高信任,随行情波动的字段(价格)获得低信任。TA 还主动给出了自己的核验渠道——「我会去懂车帝看一下实际落地多少」。
更有价值的是随后的自我修正。被问"如果它推荐错了你怪谁",TA 先给标准答案「怪我自己吧。它又没逼我买」,几秒后补了一句:「……不过要是它写得那么肯定,我可能真就不查了。那算谁的?」
这半句自我反问,恰好命中了本次评测的核心发现:模型输出的确定性语气与实际正确率无关(接口端 GLM 曾把 4765mm 写成"完美符合 4.7 米限制",见 1.2.2),而用户核实与否,取决于语气给不给留怀疑空间。
4.3.4 观察与推测的分离
| # | 实际观察(有记录可查) | 原因推测(未经 TA 确认) |
|---|---|---|
| 1 | TA 收到任务后先反问 4.7 米的长短参照,未直接开始操作 | 可能是 TA 在评估任务可行性,也可能是真实的生活经验联想(车位 5 米多)被即时触发 |
| 2 | TA 用约 90 秒寻找联网开关未果,改由"30 个来源"推断 | 可能该开关入口位置不符合 TA 的预期路径;也可能移动端 / 桌面端布局差异导致 |
| 3 | TA 对车长字段逐一做了 mm→m 换算 | 可能因为任务卡强调"务必让它满足",TA 把它当成了必须亲自验收的条件 |
| 4 | TA 对没听过的车型(海豹 06GT、领克 20)未做任何查证,并自知 | 「不过我没去查这两个是不是真车……应该不会编吧」——可能是查证成本高于其决策利益 |
| 5 | TA 先答"怪我自己",随后自行反问"那算谁的" | 可能是 TA 意识到标准答案与真实感受不一致;其真实态度是摇摆的,无法从单次回答判断 |
| 6 | TA 全程未使用文件上传 | 本轮未追问原因,无法归因 |
说明:右栏全部是访谈者的解读,不能由单次观察推广到"用户普遍如此"。
4.4 TA 觉得从用户体验角度需要改进的地方
按 TA 提出顺序,未改写:
- 「改速度。」——响应等待超过一分钟是最直接的负面体验。
- 「还有我希望它一开始就问我车位多长、家里几口人,别我给什么答什么」——希望产品主动追问缺失上下文,而不是被动应答。
TA 没有对千问单独提出功能建议,这一点如实记录,不代为补写。
4.5 TA 的推荐意愿
TA 的整体推荐意愿:会,但有条件——「会,但我会说别全信。它整理信息是真的快,我原来完全不知道 20 万这个价位该看什么,现在至少知道要看车长、续航、有没有激光雷达」。
值得注意:TA 把产品价值定义为"教会我该看什么参数",而非"给我答案"——与第二部分"把模型当提出好问题的人"的结论相互印证。
4.6 本次采访的局限
- 样本 1 人;TA 有 API 使用经验,不代表零 AI 经验用户的表现。
- 文字采访无法记录界面操作过程(点击、滚动、停留),行为数据弱于面对面观察,"回复间隔"只能作为辅助信号。
- 任务卡中的约束是我们设定的,非 TA 真实需求;TA 对结果的投入度低于真实购车决策。
- 未交叉平衡两平台使用顺序,先用智谱可能产生锚定效应。
- 未追问文件上传未使用的原因,该维度缺数据。
知情同意:开场已明确匿名(P1)、聊天记录截图将用于作业、可随时要求删除部分内容;收尾确认原话「都可以,别写我名字就行」;已承诺整理稿回传给 TA 核对。
第二部分 分析
1. 开发时间估计
四个人、五天,按人时计。下表"实际"一栏以仓库提交时间戳与实验日志推算,含等待与调试时间。
| 模块 | 预估工时 | 实际工时 | 偏差原因 |
|---|---|---|---|
| 车型数据集整理(16 款 × 16 字段) | 3 h | 约 3.5 h | 参数要统一到"厂商指导价 + mm + km"口径,逐款核对年款与配置 |
| 场景与提示词设计(3 个场景) | 3 h | 约 4 h | 硬约束反复改了三轮,才做到"合规车型可穷举、陷阱可量化" |
| 评测程序开发(Java,含 mock 模式) | 12 h | 约 14 h | 骨架 4 h、真实调用联调 6 h、平台适配与重试 4 h |
| 18 次实验执行 | 1 h | 0.5 h | 高估。机器时间 34 分钟,人工只占"检查 18 行齐不齐"的几分钟 |
| 评分脚本(六维自动打分) | 6 h | 约 8 h | 低估了规则调试,见下 |
| 可视化(3 张 PNG + 图注) | 3 h | 约 1.5 h | 数据现成,脚本出图;图注文字与结论一并写成 |
| 博客撰写 | 8 h | 约 14 h | 跨三天多次重写,主要是把"预跑结论"逐条核对成"18 次实测结论" |
估计偏差主要出现在计划里根本没预料到的一项。
我们按"数据集 / 提示词 / 程序 / 实验 / 评分 / 图表 / 写作"七项估时,唯独漏了"确认这两个模型到底能不能用"。实际这一步花掉将近一个晚上:glm-4.7-flash 反复返回 429(免费池拥挤)、glm-4.6-flash 返回 403 无权限、qwq-32b 返回 404 模型不存在、qwen-plus 等旧模型免费额度已耗尽(403 Free quota exhausted);换到可用模型后,又发现两个新模型默认开启思考模式,思考过程把 max_tokens 吃光,正文返回空字符串,而接口仍然是 200。计划里这一项是 0 小时,实际约 4 小时。
第二处低估在评分脚本。原以为"抽出车型名、比一下价格"是几个正则的事,写下来才发现真正的困难在边界:模型会把参照车型写成"油耗远低于卡罗拉、轩逸",会把用户预算"15 万"当成车价,品牌名后面紧跟数字("丰田 122,800 元")会被误认成车型。代码 2 小时写完,规则调了 6 小时。
第三处是高估了实验执行。我们按"人需要守着"来估,实际是挂机等待,人工介入只有核对行数。
2. 同类产品对比排名
引用第一部分的评测结果,不重复贴图表、不做重复排名。排名仅适用于本次数据、场景与实验设置。
不同使用需求下的选型建议(依据均为本次 18 次实测):
| 使用需求 | 更合适的模型 | 依据(本次实测数据) |
|---|---|---|
| 硬约束多、依赖数值判断的筛选(预算+尺寸+座位+星级) | qwen3.8-flash | 约束命中率 92.6% vs 69.6%;S1 场景 100% vs 47.6% |
| 多轮追问、需要上下文与结论前后一致 | glm-4.5-flash | 多轮一致性 100 vs 73.3;Qwen 在 9 条记录里 8 条出现"先排除后推荐" |
| 结果需要可复现、可留痕 | glm-4.5-flash | 稳定性 84.4 vs 76.3;S3 三次运行推荐集合完全相同(Jaccard 1.0) |
| 成本敏感、批量调用 | glm-4.5-flash | 单次 token 24.3k vs 34.4k,省 29% |
| 低延迟的实时交互 | qwen3.8-flash | 平均单轮 14.9 s vs 30.5 s,快 2.0 倍 |
为什么这样选,而不是简单说"谁更好": 两个模型的差距不在"能不能答对"——两者都零失败、零幻觉——而在丢分的位置。购车、选型这类任务里,用户给出的硬约束(车长上限、座位数、预算)往往比推荐理由更重要:推荐一辆好车但超出预算,等于没有完成任务。所以任务包含硬约束时 Qwen 的优势被放大;任务是开放式咨询、需要多轮保持同一口径时,GLM 更稳;成本与延迟则取决于产品形态——面向开发者的批量调用选省 token 的,面向用户的在线产品选低延迟的。
需要说明的是,两者在"信息真实性"维度人工复核后均为满分,没有编造库外车型,因此差异不是"谁更可靠",而是"谁更守规矩、谁更稳"。
3. 软件工程方面的建议
3.1 我们用的平台与测试系统,分别体现在哪三个层次
程序层面(算法 / 数据结构):模型侧是 Transformer 自回归生成与注意力机制(内部细节不可观察,只能从接口行为推断);上下文管理在我们的工具里是一个线性追加的 messages 数组——同一次任务的全部历史逐轮拼接重发,这正是 token 随轮次线性增长的直接原因;工具调用参数解析本次未启用,取而代之的是结构化输出解析:Jackson 把响应反序列化到 record,评分脚本用集合运算(Jaccard 相似度)与白名单比对量化表现。
软件工程层面(服务 / 文档 / 协作机制):两家开放平台提供 API 网关、按 token 计费与限流、模型版本管理(API 的 glm-4.5-flash 与网页端的 GLM-5.3-Flash 并存,就是同一厂商的多版本迭代)、文档与错误码体系(429 的错误码 1305、403 的 Free quota exhausted 都是可编程处理的语义错误)。我们自己的评测工具链则包括:mock 先行(不烧额度跑通全流程)、断点续跑(只跳过成功记录)、配置外置(换 base_url 不改代码)、14 条回归用例的评分自检,以及 Git 版本化协作与"契约冻结"(schema 与评分规则实验前定死)。
商业层面(商业模式 / 竞争优势):智谱用完全免费的 glm-4.5-flash 获客,用高价位模型盈利——本次实测正好撞上它的分层:API 闭卷免费模型犯错,网页端联网的新一代模型全对,免费档本身就是产品漏斗的顶层。阿里百炼的免费额度按模型分别计算(qwen-flash 耗尽而 qwen3.8-flash 可用),这是典型的导流设计:把新用户推向指定模型。两家都采用"开源权重 + 云服务"双轨:开源扩大生态与基准话语权,云上按 token 计费变现。行业整体价格两年降幅超 90%,单纯卖通用底座接口的模式正在失效(详见市场概况一节)。
3.2 四个角度的工程改进建议
测试覆盖:最先暴露问题的不是被测模型,而是我们自己的评分程序。第一版报告里,
glm的"信息真实性"远低于直觉,核查后发现是解析器把"比亚迪保值率最高"这句话里的品牌名误识别成了虚构车型;另一处是把用户说的"15 万预算"当成了某款车的报价,判了三款车"自报价格偏差 50%"。这两处都不是模型的错。为此我们补了一套 14 条用例的回归自检(scoring/selftest.py),并定了一条规矩:改动车型库或抽取规则后必须先跑自检,再跑真实数据。本次正式跑批后,评分脚本的 8 个"疑似虚构"标记经人工复核全部是误报,全部回滚——这套机制第二次证明了自己的价值。接口适配:两家平台都宣称"OpenAI 兼容",但兼容的只是最外层结构,差异全在参数和配额上。① 思考模式的开关参数名不同:智谱是
thinking: {type: "disabled"},百炼是enable_thinking: false,写错不会报错,只会静默返回被截断的内容;② 限流策略不同:智谱免费池实际约 1 并发,超出直接返回 429,百炼按模型独立计算配额,耗尽返回 403;③ 模型可用性不同:同一个 Key 下有些模型返回 404(不存在)、有些返回 403(无权限),而控制台的模型列表里它们看起来都在。所以适配层不能做成"统一一份请求体",要做成"平台 → 参数映射表",把差异显式列出来——我们把它外置到harness/config/providers.properties,换 base_url 或换模型不用重新打包。上下文管理:两个具体问题。① 车型库(16 款车、十几个字段)每轮随上下文重发,实测单次任务总 token 22.3k–35.9k,其中车型库与历史消息占大头,成本随轮次线性增长——"增加候选车型数量"和"降低单次成本"直接冲突,改进方案见第一部分「3.9 改进方案与备选方案比较」;② 需求变更轮需要显式声明"以最新需求为准",否则评分无法区分"用户改需求"和"模型自相矛盾",我们在评分规则里用
mutationTurn单独做了处理。异常处理:四类必须显式处理。① 空响应:思考过程占满
max_tokens时,接口返回 200 但content为空字符串,若不判空就会静默写入一条空记录,后续评分全部失真;② 限流:429 需指数退避,我们做了最多 5 次重试(2 s 起步、翻倍、上限 20 s),超过则记录失败而不是无限重试;③ 断点续跑:只能跳过成功的记录,失败记录必须重跑并覆盖——我们最初写成"文件存在就跳过",结果是记录文件看着齐了,其中混着失败的空壳;④ 截断与格式错乱:finish_reason = length说明"答错"和"没答完"必须能区分,否则截断会被算成能力问题;解析失败时保留原始响应体,不要让异常吞掉证据。
4. BUG 存在的原因分析
引用第一部分的失败案例,不重复描述案例本身。区分"可观察"与"假设"。
| 可能的来源 | 判断依据(本次实测) | 确定性 |
|---|---|---|
| 模型本身 | S1 的车长约束写在 system prompt 里、用户第 2 轮又重申一次,glm 仍把 4765/4782 mm 的车放进标题为"符合条件车型对比表"的表格(3/3 复现),还写出"完美符合 4.7 米限制";qwen 在 9 条记录里 8 条出现"先判不符合、后又推荐" | 现象可观察;"为什么没执行"属假设 |
| 数据 | 车型库为教学模拟数据,参数与真实行情存在偏差;模型若引用库外真实车型(如凯美瑞),会被白名单判为"疑似虚构" | 可观察(库内 / 库外) |
| 提示词 | 约束以自然语言嵌在 system prompt,未结构化;输出格式要求集中在开头,长对话后期未重申 | 注入方式可观察;"后期稀释"机制属假设 |
| 解析程序 | 评分脚本共修出 5 处错误,"归一化坐标错位"与"预算被当成车价"两处直接造成误判;正式跑批的 8 个幻觉标记经复核全部是误报 | 已确认(有回归用例可复现) |
| 接口服务 | 思考模式参数不同导致空响应;免费池 429;模型 ID 不可用返回 404/403;Qwen 长表格撞 max_tokens 被截断 | 已确认(有响应码与错误码记录) |
本次最值得记的一条:分数异常时,先怀疑工具,再怀疑模型。
第一版报告里 glm 的真实性得分远低于直觉,我们的第一反应是"模型在编造车型"。核查后发现是解析器的问题——它以归一化后的文本位置去切原始文本,而归一化删掉了空格与顿号,位置整体偏移,于是从相邻段落里抓到了数字。类似地,"用户预算被当成车价"也是我们的错,与模型无关。这两处在修正后,glm 的真实性回到 100 分。正式跑批后评分脚本报出的 8 个"虚构车型"待复核项,人工逐条核对后也全部是误报(形容词与品牌名粘连),按规则回滚。
因此归因要分成两类来看:
- "约束没执行"这类失败,能确定的只有输出文本呈现的现象(硬约束没有落到候选集合上),不能确定的是内部原因。可能是长对话中早期指令权重下降,也可能是模型把"给出好推荐"的倾向排在了"遵守筛选条件"之前——这些都标为假设,本次实验没有做消融验证,不作定论。
- "分数异常"这类失败,主因首先在自己的解析程序和数据映射上。可观察的证据是:同一批原始记录,只改解析规则、不动模型,分数就会大幅变化。这本身就说明问题出在工具侧。
此外,"接口服务"这一层的问题(空响应、429、截断、模型不可用)不属于模型能力问题,但在实际工程中它们造成的失败次数并不比模型错误少,且更容易被误记为"模型不行"。
5. 市场概况
市场规模与增速
中国大模型 API(MaaS)市场在 2025–2026 年处于爆发期,且增速远高于整体软件行业:
- 营收规模:2026 年上半年中国 MaaS 市场规模 106.3 亿元,同比增长 **889.4%**,首次跨过百亿元;IDC 预计 2026 全年约 186 亿元。(IDC《中国 AI 软件市场半年度追踪,2026H1》)
- 调用量:2025 年全年 token 消耗 1,944 万亿,较 2024 年的 114 万亿增长约 16 倍;2026 年上半年已达 2,857.9 万亿(同比 +432.5%),全年预计约 40,000 万亿。(同上)
- 智能体(Agent)市场:2026 年预计 135.3 亿元,是 MaaS 之外增长最快的一层。(IDC)
- 渗透率:2025 年部署大模型的企业超过 8 万家,2026 年预计突破 10 万家;金融、政务、制造三个行业的渗透率预计分别达 68%、61%、53%。(IDC)
- 对照系:同期全国软件业务收入 2026 年前 8 个月为 10.28 万亿元、同比增长 8.8%(工信部《2026 年 1—8 月份软件业运行情况》)。也就是说,MaaS 是在一个个位数增长的行业里以三位数增长的细分市场。
直接用户与潜在用户
| 类型 | 规模 | 特征 |
|---|---|---|
| 直接用户:开发者 | 智谱 MaaS 平台企业及开发者用户超 740 万(2026 年 8 月末),覆盖 233 个国家和地区 | 以 API 调用为主,对价格、限流、文档质量极敏感;一次接入后迁移成本较高 |
| 直接用户:企业客户 | 部署大模型的企业 2025 年超 8 万家,2026 年预计超 10 万家 | 采购决策看合规、SLA 与私有化能力,不看榜单排名 |
| 潜在用户:C 端 | 生成式 AI 用户 7 亿人,普及率超 **50%**(CNNIC,2026 年上半年) | 其中 76% 用于问答,47.8% 用于图片/视频生成——需求集中在"帮我把事做完",而非"陪我聊" |
三个值得注意的结构性事实
- 高度集中。 按 token 调用份额,火山引擎 49.5%、阿里云 28%、百度智能云 10%,前三家合计约 87.5%(IDC,2025 年)。这意味着模型选型的现实选项其实只有三四个,而不是宣传中的"百花齐放"。
- 价格已降到底。 近两年国产主流大模型 API 价格整体降幅超过 90%,单纯售卖通用底座接口的商业模式正在失效。与此同时,智谱 2026 年上半年 API 平均售价反而**同比提高 101%**——说明行业已经分层:通用能力在打价格战,高价值任务(长程、工具调用、工程级交付)在提价。
- 增长拐点已到。 普及率超过 50% 之后,新增用户增速会放缓,行业重心从"抢新用户"转向"抢深度使用"。这一条直接决定了产品规划的方向:不再做新入口,而是做"任务完成度"。
6. 产品规划
主线:实测发现模型在长对话里会丢掉用户设过的硬约束,而决策类任务恰恰是"约束优先"的。所以规划不做新入口,做"约束可验证"。
N(需求):用户要的不是"更多推荐",是"推荐满足我全部条件,并且我能自己验证"。市场概况的数据支持这个判断——7 亿生成式 AI 用户里 76% 是用来问答的,普及率已过半,增长只能来自"把事真正办成",而不是"再多一个聊天框"。如果用户不懂车、不会自己查参数表,大模型推荐产生的错误是很难被发现的——推荐的"像不像"和"对不对"之间存在一条用户无法自查的缝,这就是需求所在。
A(做法):在模型之外加一层"约束编译器 + 校验器"。把用户的自然语言需求编译成结构化约束(预算区间、车长上限、座位数、能源类型),模型每给出一批候选,就用这组结构化规则做一次硬校验,不合规的车型自动剔除并要求模型重答。
为什么是这个方案,而不是其他三个:
| 备选方案 | 为什么不选 |
|---|---|
| 换一个更强的模型 | 只能降低出错概率,不能消除;换模型的成本是持续的(每次升级都要重测),校验层的成本是一次性的 |
| 重写 prompt,把约束写得更显眼 | 我们的 prompt 里约束已经写在 system prompt 里、用户又重申过一次,问题出在长对话中的执行,不是"没看到" |
| 人工复核 | 不解决问题,只把成本转移给用户 |
关键在于校验是确定性的:给定车型参数表和约束,结果是可复现的,不需要再调一次模型,成本几乎为零。
B(好处):把"约束命中率"从实测的 47.6%(glm,S1 场景)补到接近 100%,并且补的过程不依赖模型是否听话。对用户,等于把"自己对着参数表逐项核对"变成一次自动检查;对开发者,等于把一次人工复核变成一个本地函数调用,可以批量跑。副作用是成本下降——不合规的答案在本地就被拦掉了,不需要再多轮追问。
C(竞争):现有平台方(例如火山、阿里、智谱)卖的是模型能力本身,不会为某一个垂直场景去做约束编译。现有做法的共同点是把约束当成 prompt 的一部分,没有独立于模型的校验层,而这正好是独立服务商和垂直应用的生态位。这项差异化在于校验层本身,校验层对任何模型都成立,用户换模型不用换校验规则,这在模型能力快速迭代、价格频繁变动的当下,比"绑一个最强模型"更耐久。
D(推广):先打购车这一个场景——它天然适合结构化校验(参数表明确、约束可量化、决策周期短、试错成本低),做成一套可复用的"约束模板"。第一步面向开发者,把模板库开源,配免费档模型(如本次实测的 glm-4.5-flash)降低试用门槛;第二步横向复制到选房、选电脑、招标参数比对等同类"多约束筛选"任务。获客不靠投放,靠"约束模板"本身被搜索到——搜"20 万车长 4.7 米以内怎么选"的人,正是目标用户。
7. 大模型对我们现实生活带来的影响
在大模型推广度如此高的当下,责任被悄悄转移了。 就像采访里我们问过 P1:如果它推荐错了,你会怪谁?TA 先给了一个标准答案:「怪我自己吧。它又没逼我买。」几秒后,TA 自己补了一句:
「……不过要是它写得那么肯定,我可能真就不查了。那算谁的?」
这个问题在真实的消费场景里正在变得具体。假设有人照着一份错误推荐买了车,回家发现车位停不进去,他能找谁?厂商的免责条款写着"生成内容仅供参考",平台说"这是模型输出",模型没有主体资格。责任在链条上被逐层稀释,最后落回最没有信息优势的那一方——消费者本人。
这不是要否定这项技术。恰恰相反,我们组的判断是:这类工具在信息整理和权衡呈现上是真实有效的,它能把一个不懂车的人从"完全不知道从哪问起"带到"知道该比哪几个参数"。它的问题不在于会不会犯错,而在于它犯错的方式让人无从察觉。
所以,普通人该怎么办。 基于这次评测和访谈,我们给出三条可操作的建议,都不需要技术背景:
- 把模型当"提出好问题的人",不当"给答案的人"。 它最擅长的是告诉你"买这个价位该关注车长、亏电油耗、后排头部空间",这部分几乎不会错;它给的每一个具体数字,都当成待核对的线索。
- 凡是能查到权威源的硬指标,一律回查。 车长、价格、续航、碰撞成绩——去工信部或厂商官网,三十秒的事。判断标准很简单:这个数字错了会不会让你花错钱,会,就去查。
- 让它自己复述约束。 我们发现一个有效的小技巧:在下结论之后追问一句"你推荐的车里有没有违反我条件的?"——模型往往能自己揪出前一轮的错误。这不是因为它变聪明了,是因为第二次它被迫逐个核对。
对做产品的人,这三条建议反过来读就是需求:约束要能结构化校验,事实要能溯源,错误要被主动暴露而不是等用户发现。 这也是我们提出"约束校验层"这个产品方向的依据。
附:代码仓库与实验材料
- 代码仓库(含全部代码、数据、记录、评分结果):https://devcloud.cn-north-4.huaweicloud.com/codehub/project/489b94eae18e4d3eb188872dc49d6c5a/codehub/3115262/repo
- 车型数据与场景配置(教学模拟数据,含年款、价格口径、参数单位与来源日期):仓库
data/cars.json、data/scenarios/s1~s3.json - 提示词:用户轮次见
data/scenarios/*.json的userTurns字段;系统提示词(含车型库注入与硬约束声明)见harness/src/main/java/eval/DialogRunner.java的systemPrompt方法 - 完整代码:
harness/src/main/java/eval/(Main、HttpLlmClient、DialogRunner、RecordWriter、ScenarioLoader、MockClient、model/*)、scoring/score.py、scoring/selftest.py、run.sh、harness/pom.xml - 脱敏原始记录:
records/*.json(18 条完整多轮对话记录,不含任何密钥与个人信息)、records/index.csv(汇总索引) - 评分结果:
scoring/out/scores.csv(逐条六维得分)、scoring/out/summary.md(模型汇总)、scoring/out/details.json(逐条判定依据,含人工复核记录) - 体验与采访材料(均已脱敏):
study/screenshots/(两平台游客模式实测截图与体验记录)、study/interview/(采访记录与 14 张聊天截图)、study/feature_matrix.md(功能矩阵)、study/trial_logs/(接口层原始响应与复现脚本) - 图表:
figures/(六维雷达图、分场景柱状图、token-延迟散点图)
密钥保护说明:两个平台的 API Key 均通过环境变量(
ZHIPU_API_KEY、DASHSCOPE_API_KEY)与本地.env文件读取,.env已被.gitignore排除,未出现在代码、博客与任何附件中;复现脚本从环境变量读 Key,脚本内不含密钥。
附:团队分工与贡献度
| 姓名 | 学号 | 角色 | 主要交付物 | 贡献度 |
|---|---|---|---|---|
| 李佳 | 102400403 | 组长 / 模块D:写作与合规 | 需求拆解与分工、仓库骨架与数据契约、18 次跑批执行、评分程序与六维口径、全文撰写与排版发布、三张评测图表的出图脚本与成图 | 30% |
| 王嘉萍 | 102400206 | 模块C:用户调研与体验评测 | 双平台游客模式实测与 8 张截图、14 页 QQ 采访记录、功能矩阵、接口层原始响应、第二部分第 7 节初稿 | 25% |
| 林严泽 | 102400120 | 模块A:评测框架 | Java 多轮对话框架(HttpLlmClient / DialogRunner / RecordWriter)、成品 jar、平台配置外置、稳定性改进(失败隔离、断点续跑、限速)、改进方案稿 | 25% |
| 施乐山 | 102300324 | 模块B:数据与可视化 | 图表的指标 / 单位 / 样本数 / 来源规范(figures/captions.md)、评测结论摘要与评分口径核对(scoring/conclusion.md) | 20% |
相关推荐
YOLO26算法心电图十二导联目标检测+训练好的模型+368张数据集+pyqt可视化界面.zip
附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[导联I(I), 导联II(II), 导联III(III), 胸导联V1(V1), 胸导联V2(V2), 胸导联V3(V3), 胸导联V4(V4), 胸导联V5(V5), 胸导联V6(V6), 加压肢体导联aVF(aVF), 加压肢体导联aVL(aVL), 加压肢体导联aVR(aVR)] · 训练集:313 张 · 验证集:37 张 · 测试集:18 张 · 总计:368 张 该数据集聚焦于临床心电图信号的精准识别与定位,其核心检测目标为标准12导联心电图中的各个独立导联波形区域,涵盖肢体导联(I、II、III)与加压肢体导联(aVR、aVL、aVF),以及胸前导联(V1至V6),适用于心电图自动分析系统中对各导联位置的快速准确标注与分类。数据采集场景真实还原了医院心电图室或急诊监护环境下的标准心电图记录纸,波形清晰、基线稳定,具有高度临床参考价值。... 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 57 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.9708** mAP50-95 | 0.6344 Precision | 0.8990 Recall | 0.9191 train/box_loss | 1.2231 train/cls_loss | 0.9703 val/box_loss | 1.2779 val/cls_loss | 0.... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。
企业级AI助手平台 开箱即用的全栈AI平台,支持多智能体协同、Supervisor模式编排、多种决策模式、RAG技术和流程编排能力 支持多厂商大模型统一接入与管理,安全可控的企业知识库与高精度检索优化
企业级AI应用开发框架,支持多厂商大模型统一接入与管理,安全可控的企业知识库与高精度检索优化能力,提供可视化流程编排、自主决策智能体与多智能体协同调度,兼容主流 Agent Skill 协议,帮助企业与开发者零门槛快速构建安全、高效、可落地的AI智能体应用与行业解决方案。
VLOOKUP_fixed.py
VLOOKUP_fixed.py
基于动态窗口法DWA的机器人路径规划研究(Matlab代码实现)
内容概要:本文系统研究了基于动态窗口法(DWA)的机器人局部路径规划算法,深入剖析其在动态环境中实现自主避障与实时轨迹优化的核心机制。文章详细阐述了DWA算法的速度空间采样策略、轨迹预测模型、动力学约束处理及多目标代价函数的设计原理,并通过构建完整的Matlab仿真框架验证算法有效性。结合典型场景的仿真实验,展示了机器人在复杂障碍物环境下如何实时生成安全、平滑且符合运动学约束的最优路径,充分体现了DWA在移动机器人导航中的实用性与鲁棒性。; 适合人群:具备机器人运动规划基础知识和Matlab编程能力,从事智能移动机器人、自动驾驶或服务机器人研发的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入理解DWA算法的理论基础与实现细节;②掌握机器人局部路径规划的仿真实现方法;③为实际机器人系统的导航模块开发提供可复用的算法原型与代码参考;④作为进一步研究高级导航算法(如TEB、MPC)的技术基础。; 阅读建议:建议结合提供的Matlab代码逐模块分析与调试,重点关注速度采样、轨迹积分、障碍物距离计算及代价评估等关键环节,通过调整参数在不同地图环境中进行对比实验,以深刻把握算法性能与参数之间的关系,进而提升对实时路径规划系统设计的理解与应用能力。
【轴承故障诊断】用于轴承故障诊断的集中时频分析研究(Matlab代码实现)
内容概要:本文系统研究了用于轴承故障诊断的集中时频分析技术,重点解决了传统时频分析方法在处理非平稳信号时存在的能量分散与分辨率不足等问题。通过引入集中时频分析方法,能够有效聚焦信号能量,精确提取轴承故障特征频率,提升故障识别的准确性与时效性。文章详细阐述了该方法的理论基础,并结合仿真信号与实际实验数据验证其优越性能,同时提供了完整的Matlab代码实现流程,涵盖信号预处理、时频变换、参数优化及结果可视化等环节,便于读者复现与拓展应用。; 适合人群:具备一定信号处理理论基础和Matlab编程能力的研究生、科研人员,以及从事机械设备状态监测、故障诊断与预测性维护工作的工程技术人员。; 使用场景及目标:①应用于电机、风机、齿轮箱等旋转机械的早期轴承故障检测,实现故障预警;②提升工业设备运维系统的智能化水平,支撑预测性维护体系构建;③作为高校或研究机构在信号处理、机械故障诊断等课程中的教学案例与实践素材。; 阅读建议:建议读者结合文中提供的Matlab代码逐段运行与调试,深入理解集中时频分布的生成机制及其关键参数(如核函数选择、平滑窗口大小)对诊断效果的影响,并尝试将其应用于其他类型的机械故障信号分析中,开展对比研究以深化对该方法适用性的认识。


