跳到正文

LLM 输出格式如何强校验?

大模型输出格式校验与后处理方案,正则+JSON Schema 实践

原题:在使用大语言模型时,如何设计有效的输出过滤机制来确保模型返回的结果符合预期的格式要求?请分享你的技术方案和实践经验。

Prompt工程 · 字节真题

30 秒回答

  1. 区分Prompt层、模型层、后处理层三层防护策略
  2. 掌握JSON Schema/Function Calling等结构化输出技术
  3. 设计解析失败时的降级和重试机制
  4. 结合实际业务场景说明方案选型依据

回答与解析

答案要点

  • 区分Prompt层、模型层、后处理层三层防护策略
  • 掌握JSON Schema/Function Calling等结构化输出技术
  • 设计解析失败时的降级和重试机制
  • 结合实际业务场景说明方案选型依据

我通常从三层防护来设计输出过滤机制:

第一层:Prompt工程(预防)

  • Few-shot示例:在Prompt中给2-3个符合格式的输出样例
  • 明确格式指令:用代码块包裹格式模板,强调"必须严格遵循以下JSON格式"
  • 角色设定:指定模型扮演"严格的JSON生成器"角色

第二层:结构化输出(约束)

优先使用模型原生能力:

  • Function Calling:OpenAI/Claude的tools参数,强制输出匹配schema
  • JSON Moderesponse_format={"type": "json_object"},约束输出为合法JSON
  • Guidance/Outlines:复杂场景用约束解码库,如微软Guidance

第三层:后处理校验(兜底)

def validate_output(text, schema):
    try:
        data = json.loads(text)
        jsonschema.validate(data, schema)  # 结构校验
        business_validate(data)            # 业务规则校验
        return data
    except:
        return retry_with_stricter_prompt() # 或返回降级结果

实践经验

场景 方案 原因
高确定性任务(如API调用) Function Calling + 强校验 失败即重试,不接受脏数据
开放性生成(如创意写作) Prompt引导 + 宽松后处理 保留创造性,人工兜底
流式输出 增量解析 + 状态机校验 实时发现格式错误,提前截断

关键权衡:格式严格性 vs 任务完成率。对Agent工具调用必须严格,对内容生成可适当宽松。

口语版讲法(约4分钟)

  • 开场:这道题在问输出可控性与业务风险的平衡
  • 三层防护:Prompt层做预防,结构化输出做硬约束,后处理做兜底
  • 方案边界:高确定性任务用Function Calling,开放生成用宽松Prompt
  • 业务案例:客服退款场景的严格校验与降级机制
  • 风险与取舍:格式严格性 vs 任务完成率,工程师的判断

这道题其实是在问,当大模型输出不可控时,你怎么在保证格式合规的同时,不把业务的灵活性和成功率丢掉。我一般会从三层防护来设计,从预防到硬约束再到兜底,每一层解决不同的问题。

先说第一层,Prompt工程。这层是预防性的,成本最低。我会在Prompt里给两三个格式样例,明确说必须严格遵循某个JSON格式,甚至让它扮演一个严格的JSON生成器角色。但这层只能提高概率,不能保证100%听话,所以不能只靠它。

第二层是结构化输出,这才是真正的硬约束。能用模型原生能力就用,比如OpenAI的Function Calling或者JSON Mode,直接告诉模型输出必须匹配某个schema,它会在解码层就做约束。如果模型本身不支持,或者场景更复杂,我会用Guidance这类约束解码库,在生成过程中实时卡住非法token。说白了,这层是从模型内部把输出框死,比Prompt可靠得多。

第三层是后处理校验,做兜底。不管前面两层多强,总会有意外,比如模型输出了合法JSON但业务逻辑不对。我会写一个validate函数,先用json.loads解析,再用jsonschema校验结构,最后跑业务规则。如果校验失败,就触发重试,用更严格的Prompt再问一次,或者直接返回一个降级结果。

这三层怎么选,得看场景。我举个例子,客服退款场景,模型需要调用API修改订单状态,这时候输出格式必须绝对正确,一个字段都不能错。我会用Function Calling加严格校验,失败就重试,不接受脏数据。但如果是创意写作,比如给用户生成一段文案,格式要求就宽松很多,用Prompt引导加一个简单的后处理就够了,太严格反而扼杀创造性。真正落地时,常常是X加Y一起上,没有银弹。

这里有个坑:后处理校验不能太死板。比如流式输出场景,模型在生成过程中可能先输出一个不完整的JSON片段,你不能等它全吐完了再校验,那延迟就太大了。我会用增量解析加状态机,实时发现格式错误,提前截断或者修正。

还有一个点值得注意:Function Calling虽然好,但它的schema设计其实有讲究,嵌套太深或者可选字段太多,模型反而容易出错。所以我会把schema尽量扁平化,只留必填字段,复杂逻辑放到后处理里做。

总的来说,我更倾向于把输出过滤看成一种风险控制,而不是追求完美的格式。前提是你要清楚业务对格式的容忍度有多高,如果容忍度低,就多上几层约束;如果容忍度高,就放宽一点,把成功率拉上去。上线后我会特别关注重试率和降级比例,如果某个场景频繁触发降级,说明前面的约束太严了,需要调整。

关键一句:Function Calling的schema设计对模型输出质量有显著影响,需要平衡扁平化与表达能力。

面试官还可能这样问

  1. 问法 1 · 场景切入

    假设我们做一个订单查询的Agent,用户说‘查一下我的订单’,模型可能输出一段话也可能输出JSON。你怎么保证它一定返回一个结构化的订单对象,而不是自由文本?

  2. 问法 2 · 层层追问

    你平时怎么保证模型输出是你要的格式?……那如果Prompt里写了要求,它还是偶尔输出乱的呢?……再比如API调用场景,格式错了整个流程就断了,你会怎么兜底?

  3. 问法 3 · 直球架构

    聊聊大模型输出的格式过滤机制。从Prompt、模型层到后处理,你一般怎么设计?有哪些关键技术和权衡?

同模块相关题目