AI 测试开发面试高频题:"大模型接口常见的边界问题有哪些?"
边界值分析是测试的老手艺,但大模型的边界换了形态:输入有上下文窗口,输出有 max_tokens,计费有 token 统计——三个边界,三种翻车方式。这篇用两起 400 错误讲透。
一、真实事故:两个 400,两种边界
某招聘平台的 AI 面试助手,支持多轮深挖对话。上线一个月后客服反馈:用户聊到 30 轮左右,界面突然弹"服务不可用,请稍后再试",之后这个会话永远打不开——重试也报错,用户积累了几十轮的面试记录直接废掉。
排查:多轮历史全量拼接进上下文,30 轮后总 token 数突破 128K 窗口,API 返回 400(context_length_exceeded)。前端把 400 翻译成了"服务不可用",而且每次重试都带上同样的超长历史,永远 400。输入边界没测,截断策略没做,错误提示没说人话,三个坑叠成一个死局。
同周另一起:报告生成接口把 max_tokens 设成 512,一份结构化报告输出到一半被截断,JSON 少了半边括号,下游解析服务抛异常,重试三次后任务标"失败"——输出边界没测,截断既没有兜底也没有提示。
二、核心代码:三类边界的用例设计
第 1 步:输入边界——窗口 -1 / = / +1
WIN = 128_000
def build_history(tokens):
"""按目标 token 数构造多轮历史(用分词器精确计数,别按字符估)"""
rounds = []
while count_tokens(rounds) < tokens:
rounds.append({
"role": "user", "content": "请继续详细展开上一段内容。"})
rounds.append({
"role": "assistant", "content": PAD_SENTENCE * 40})
return trim_to(rounds, tokens)
@pytest.mark.parametrize("delta", [-1, 0, +1, +5000])
def test_context_window_boundary(delta):
r = client.chat(build_history(WIN + delta))
if delta <= 0:
assert r.ok
else:
# 溢出必须优雅:自动截断或友好提示,绝不允许 400/500 裸奔给用户
assert r.graceful, f"溢出 {delta} tokens 时行为不优雅:{r.status}"
边界值分析的老三样(刚好、差一、超一)原封不动适用,只是"值"从长度字段换成了 token 数——必须用分词器精确计数,按字符数估会在中文场景差出 2~3 倍。
第 2 步:截断策略测试——丢了旧话,不能丢关键信息
溢出时常见的策略是滑窗丢弃早期轮次或做摘要。测试要验证:截断之后,最新问题和关键实体还在不在:
def test_truncation_keeps_key_info():
history = build_history(WIN + 5000)
history[-1]["content"] = "结合我第 3 轮给的订单 A1002,继续分析。"
r = client.chat(history)
assert "A1002" in r.answer, "截断把关键实体丢了,回答必然答非所问"
第 3 步:输出边界——max_tokens 截断必须可感知
def test_output_truncation_detectable():
r = client.chat(REPORT_PROMPT, max_tokens=512)
if r.finish_reason == "length": # 被截断
assert r.has_truncated_flag or r.retry_with_larger_budget, \
"截断既没标记也没续写,下游必炸"
else:
json.loads(r.text) # 未截断则 JSON 必须完整
第三类边界是计费对账:用 API 返回的 usage 与本地分词器计数做比对,偏差超 5% 告警——计费边界翻车不报错,只烧钱。
三、沉淀成方法:大模型边界测试清单
| 边界 | 翻车形态 | 测试动作 |
|---|---|---|
| 输入上下文窗口 | 400 裸奔、会话永久废掉 | 窗口 -1/=/+1 用例 + 截断策略关键信息保留率 |
| 输出 max_tokens | JSON 半截、下游崩溃 | finish_reason 断言 + 截断标记/续写验证 |
| 计费 token 统计 | 隐性超支 | usage 与本地计数对账,偏差告警 |
三条工程纪律:一是边界用例进回归,窗口大小和 max_tokens 是配置项,配置一改用例就要重跑;二是错误提示要进用例——"服务不可用"和"对话太长,已为你保留最近 10 轮"是两种产品,溢出时的用户文案必须是断言对象;三是长会话要有记忆评测:截断/摘要策略上线前,跑"第 N 轮关键信息召回率",策略好坏用数据说话。
四、面试追问,你答得上来吗
- 大模型接口常见的边界问题有哪些?——答:三类。输入侧上下文窗口溢出(400 或静默截断)、输出侧 max_tokens 截断(半截 JSON/半句话)、计费侧 token 统计偏差(隐性超支)。再往细了说还有单条消息超长、图片/文件转 token 超限、并发下的配额边界。
- 截断策略的质量怎么测?——答:构造"关键信息埋在早期轮次"的用例集,跑截断后回答的关键实体召回率;对比滑窗、摘要、重要性保留三种策略的召回率与成本,给架构选型提供数据。截断不是"不报错就行",丢什么、留什么是产品决策,测试要量化它。
- 为什么 token 计数不能按字符估算?——答:分词器对中文大约 1 字 1~2 token,对英文约 4 字符 1 token,混排、代码、标点差异更大。边界用例差一个 token 就是过与不过的区别,必须用与服务端一致的分词器精确计数——计数器不一致本身就是要对账的 bug。
(本系列十篇正文完结。回顾:01 可靠断言 → 02 RAG 评测 → 03 Prompt 回归 → 04 Function Calling → 05 Agent 熔断 → 06 SSE 流式 → 07 幻觉监控 → 08 注入安全 → 09 性能压测 → 10 边界测试)