• 请不要在回答技术问题时复制粘贴 AI 生成的内容
chouqiu
V2EX  ›  程序员

如何让 AI 稳定的输出指定 json 结构

  •  
  •   chouqiu · May 28, 2025 · 5757 views
    This topic created in 525 days ago, the information mentioned may be changed or developed.

    需求是:提取 word 文档内容,翻译成多个语种

    目前的实现方式是把 word 文档里的 xml 内容提取出来,整理成一个 list ,结构如下:

    ["待翻译的文本一", "待翻译的文本二"]
    

    使用的 prompt 如下:

    system prompt

    你是一个{industry}行业的{language}翻译专家,请将用户输入的文字翻译成{language},翻译结果需要严格按照用户输入的 JSON 内容进行翻译,翻译后返回的 JSON 结构与用户输入的 JSON 结构需要完全一致。请参考用户输入的术语库翻译 JSON 数组内容,翻译结果输出 JSON 格式。
    
    下面是一个用户输入内容示例:
    术语库:
    {"你好": "hello", "什么": "what"}
    需翻译的 JSON 内容:
    {"filename": "这是文件名", "items": ["你好", "这是什么", "你好"]}
    
    请严格按照下面的要求输出翻译结果:
    1. 翻译结果为合法的标准的 JSON 对象字符串(不要输出 markdown 格式),不要过度转义,输出稳定的合法的标准的 JSON 对象字符串
    2. 翻译结果 JSON 包含 filename 和 items 两个 key ,并保证 items 数组元素数量和待翻译的 items 数组元素数量一致
    3. 翻译结果需要严格按照用户输入的 JSON 内容进行翻译,翻译后返回的 JSON 结构与用户输入的 JSON 结构需要完全一致,并保证 items 数组元素数量和待翻译的 items 数组元素数量严格保持一致。
    4. 输出示例:{"filename": "this is filename", "items": ["hello", "what is it", "hello"]}
    

    user prompt

    术语库:
    xxxxxxxxxx
    需翻译的 JSON 内容:
    xxxxxxxxxx
    
    

    但是 AI 的响应结果,有时是 json 格式,有时是 markdown 格式,有时返回的 json 里面,items 的数量和待翻译的数量又不一致

    35 replies  •  2025-05-29 11:26:53 +08:00
    miracleyin
    miracleyin
    May 28, 2025
    1
    取决于模型,有 json 模式的模型输出会稳定不少。
    其次,使用 langfun
    Latin
    Latin
    May 28, 2025
    2
    matrix1010
    matrix1010
    May 28, 2025
    3
    现在的闭源模型或者 ollama/vllm 这些基本都支持 structed output 了吧,你直接动态构建一个 schema 传过去不就行了。数组数量不一致你可以转换为 object: {"1": "hello", "2": "what is it", ...}, 强制 structed output 符合这个结构
    qieqie
    qieqie
    May 28, 2025
    4
    现在 vllm, sglang 这些推理端点的结构化输出可以直接用 cfg 状态机制导,屏蔽掉不符合语法规则的 token 输出。
    sesshomaru0
    sesshomaru0
    May 28, 2025
    5
    插楼问下,怎么处理乱码情况,我的 api 好像比较频繁出现乱码
    liudewa
    liudewa
    May 28, 2025
    6
    我司搞的 结构化 就稳定输出 json 结构 就用的 提示词让返回 包含 json 格式的字符串 然后根据关键词 截取需要的 json
    mercurylanded
    mercurylanded
    May 28, 2025
    7
    用 function call ,json 格式作为 input
    ruoxie
    ruoxie
    May 28, 2025
    8
    你是一个根据以下 TypeScript 类型定义将用户请求转换为 "PageConfig" 类型的 JSON 对象的服务,并且按照字段的注释进行处理:
    ```
    export type PageConfig = {
    filters: {
    component: string;
    /**
    * @description 翻译成英文,驼峰格式
    * @type {string}
    */
    key: string;
    /**
    * @description 保持原始内容,不要翻译
    * @type {string}
    */
    label: string;
    /**
    * @description 保持原始内容,不要翻译
    * @type {string}
    */
    placeholder: string;
    }[];
    columns: {
    slot: boolean;
    /**
    * @description 保持原始内容,不要翻译
    * @type {string}
    */
    title: string;
    /**
    * @description 翻译成英文,驼峰格式
    * @type {string}
    */
    dataIndex: string;
    /**
    * @description 翻译成英文,驼峰格式
    * @type {string}
    */
    key: string;
    }[];
    pagination: {
    show: boolean;
    page: string;
    size: string;
    total: string;
    };
    includeModifyModal: boolean;
    fetchName: string;
    result: string;
    serviceName: string;
    };
    ```
    以下是用户请求:
    """
    {"filters":[{"component":"range-picker","key":"transactionTime","label":"成交时间"},{"component":"input","key":"planName","label":"提成方案名称","placeholder":"提成方案名称(个人/店组/片区)"}],"columns":[{"slot":false,"title":"成交时间","dataIndex":"成交时间","key":"成交时间"},{"slot":false,"title":"申佣时间","dataIndex":"申佣时间","key":"申佣时间"},{"slot":false,"title":"业绩来源","dataIndex":"业绩来源","key":"业绩来源"},{"slot":false,"title":"所属片区","dataIndex":"所属片区","key":"所属片区"},{"slot":false,"title":"当前组织","dataIndex":"当前组织","key":"当前组织"},{"slot":false,"title":"提成类型","dataIndex":"提成类型","key":"提成类型"},{"slot":false,"title":"员工姓名","dataIndex":"员工姓名","key":"员工姓名"},{"slot":false,"title":"成交编号","dataIndex":"成交编号","key":"成交编号"},{"slot":false,"title":"分成角色","dataIndex":"分成角色","key":"分成角色"},{"slot":false,"title":"本次申佣业绩","dataIndex":"本次申佣业绩","key":"本次申佣业绩"},{"slot":false,"title":"提成","dataIndex":"提成","key":"提成"},{"slot":false,"title":"已算提成业绩","dataIndex":"已算提成业绩","key":"已算提成业绩"},{"slot":false,"title":"当月总提成业绩","dataIndex":"当月总提成业绩","key":"当月总提成业绩"},{"slot":false,"title":"提成方案名称","dataIndex":"提成方案名称","key":"提成方案名称"},{"slot":false,"title":"方案计算类型","dataIndex":"方案计算类型","key":"方案计算类型"}],"pagination":{"show":true,"page":"page","size":"size","total":"result.total"},"includeModifyModal":false,"fetchName":"fetchTableList","result":"[\"result\"][\"records\"]","serviceName":"getTableList"}
    """
    The following is the user request translated into a JSON object with 2 spaces of indentation and no properties with the value undefined:
    ruoxie
    ruoxie
    May 28, 2025
    9
    https://github.com/microsoft/TypeChat 配合这个对返回的结果进行校验,把错误内容发过去再问一次,不过我用了这么久基本很少出错
    yexiaoqiu358
    yexiaoqiu358
    May 28, 2025
    10
    https://juejin.cn/post/7491240940126158900 试了一下这个,用 zod 去验证 josn 挺好的
    mumbler
    mumbler
    May 28, 2025
    11
    模型不听话,换更大更贵的模型
    rogerer
    rogerer
    May 28, 2025
    12
    1. prompt ,现在 LLM 在对齐阶段一般做过格式的对齐,所以直接让输出 JSON 效果就会不错,如果还是不行把温度系数调一下;
    2. 受限解码,大致思想是要求 LLM 的 output 必须符合某个语法结构,如果不行就重新采样。好处是可以保证一定不会出现格式错误,但是这样做的问题是会影响本身的性能,不推荐;
    visper
    visper
    May 28, 2025
    13
    发现有时候模型还是喜欢输出 json 的时候加上```json ```这样的 markdown 格式,即使已经不再输出其他解释文字了。所以后来我直接叫它输出这样的格式,自己再去截取出来了。
    darkengine
    darkengine
    May 28, 2025
    14
    不是提示语的问题,调用 API 的时候需要指定用 Structured Outputs ,并且定义好输出需要的字段。
    ningxing
    ningxing
    May 28, 2025
    15
    用 gpt4 和以上,很听话的,你让他往东它绝对不敢往西
    Qinnn
    Qinnn
    May 28, 2025
    16
    可以试试在输出 json 这部分提示词换成英文的。
    jingdongkehu
    jingdongkehu
    May 28, 2025
    17
    后面加一句,如果翻译错了我就把你卸载掉 试试
    mindsucker
    mindsucker
    May 28, 2025
    18
    限制 AI 的输出格式,会导致 AI 的推理能力下降不少,请谨慎使用
    lyxxxh2
    lyxxxh2
    May 28, 2025
    19

    看文档,应该有说怎么指定的。
    yplam
    yplam
    May 28, 2025
    20
    openai 的 api 很久之前就可以,一直在用很稳定
    eycfsjd
    eycfsjd
    May 28, 2025
    21
    通过 function_calling(or tools)实现 Structured Output
    chouqiu
    chouqiu
    OP
    May 28, 2025
    22
    收到,谢谢各位,我研究下 response_format ,都不知道这个
    BeautifulSoap
    BeautifulSoap
    May 28, 2025
    24
    模型支持 json mode 或者 structured outputs 的话时最简单的
    如果不支持但支持 function call ,那就用 function call
    如果不支持 function call ,那么这里有个很全的整理

    https://www.boundaryml.com/blog/structured-output-from-llms
    freemoon
    freemoon
    May 28, 2025
    25
    langchain 支持 结构化输出
    findstrx
    findstrx
    May 28, 2025
    26
    如果是调用 API 的话,有一个参数,可以强行指定 json 返回,这比在提示词里强调效果要好的多
    mkroen
    mkroen
    May 28, 2025
    27
    怎么没人提 pydantic-ai ,可以将 BaseModel 派生出的类作为参数传入,工具会自行校验返回结果
    Hundredwz
    Hundredwz
    May 28, 2025
    28
    自己部署的话,可以看看 sglang ,支持[结构化输出]( https://docs.sglang.ai/backend/structured_outputs.html),vllm 应该也一样。
    如果使用 api ,openai 是支持的,其他的没调研过,不了解了。
    conn457567
    conn457567
    May 28, 2025 via Android
    30
    可以试试 json-repair 这个库,一些小的格式错误它能修复
    macaodoll
    macaodoll
    May 28, 2025
    31
    结构化输出,这个开关打开,不过也得看你用的模型支持不支持,
    m319
    m319
    May 29, 2025
    32
    除了 api 中指定结构化输出以外,还有一个提示词层面的小技巧,由于 llm 会模仿输入的格式,所以只要输入格式也用 json 就行,不过也看模型指令遵循情况

    如何让大语言模型输出 JSON 格式? - HowardZhangdqs 的回答 - 知乎
    https://www.zhihu.com/question/656512469/answer/3515553778
    wxxxcxx
    wxxxcxx
    May 29, 2025
    33
    可以学习下 anthropic 的提示工程文档,里面很多技巧是通用的。

    https://docs.anthropic.com/zh-CN/docs/build-with-claude/prompt-engineering/prefill-claudes-response
    wxxxcxx
    wxxxcxx
    May 29, 2025
    34
    @wxxxcxx 一般可以使用 xml 结合示例,然后使用预填充,能达到比较好的效果
    realJamespond
    realJamespond
    May 29, 2025
    35
    不听话可以微调 lora 参数随机生成 1000 条指定格式 json 数据
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3004 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 69ms · UTC 11:03 · PVG 19:03 · LAX 03:03 · JFK 06:03
    ♥ Do have faith in what you're doing.