V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
chouqiu
V2EX  ›  程序员

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

  •  
  •   chouqiu · 9 天前 · 3004 次点击

    需求是:提取 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 条回复    2025-05-29 11:26:53 +08:00
    miracleyin
        1
    miracleyin  
       9 天前
    取决于模型,有 json 模式的模型输出会稳定不少。
    其次,使用 langfun
    Latin
        2
    Latin  
       9 天前
    matrix1010
        3
    matrix1010  
       9 天前
    现在的闭源模型或者 ollama/vllm 这些基本都支持 structed output 了吧,你直接动态构建一个 schema 传过去不就行了。数组数量不一致你可以转换为 object: {"1": "hello", "2": "what is it", ...}, 强制 structed output 符合这个结构
    qieqie
        4
    qieqie  
       9 天前
    现在 vllm, sglang 这些推理端点的结构化输出可以直接用 cfg 状态机制导,屏蔽掉不符合语法规则的 token 输出。
    mbeoliero123
        5
    mbeoliero123  
       9 天前
    插楼问下,怎么处理乱码情况,我的 api 好像比较频繁出现乱码
    liudewa
        6
    liudewa  
       9 天前
    我司搞的 结构化 就稳定输出 json 结构 就用的 提示词让返回 包含 json 格式的字符串 然后根据关键词 截取需要的 json
    mercurylanded
        7
    mercurylanded  
       9 天前
    用 function call ,json 格式作为 input
    ruoxie
        8
    ruoxie  
       9 天前
    你是一个根据以下 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
        9
    ruoxie  
       9 天前
    https://github.com/microsoft/TypeChat 配合这个对返回的结果进行校验,把错误内容发过去再问一次,不过我用了这么久基本很少出错
    yexiaoqiu358
        10
    yexiaoqiu358  
       9 天前
    https://juejin.cn/post/7491240940126158900 试了一下这个,用 zod 去验证 josn 挺好的
    mumbler
        11
    mumbler  
       9 天前
    模型不听话,换更大更贵的模型
    rogerer
        12
    rogerer  
       9 天前
    1. prompt ,现在 LLM 在对齐阶段一般做过格式的对齐,所以直接让输出 JSON 效果就会不错,如果还是不行把温度系数调一下;
    2. 受限解码,大致思想是要求 LLM 的 output 必须符合某个语法结构,如果不行就重新采样。好处是可以保证一定不会出现格式错误,但是这样做的问题是会影响本身的性能,不推荐;
    visper
        13
    visper  
       9 天前
    发现有时候模型还是喜欢输出 json 的时候加上```json ```这样的 markdown 格式,即使已经不再输出其他解释文字了。所以后来我直接叫它输出这样的格式,自己再去截取出来了。
    darkengine
        14
    darkengine  
       9 天前
    不是提示语的问题,调用 API 的时候需要指定用 Structured Outputs ,并且定义好输出需要的字段。
    ningxing
        15
    ningxing  
       8 天前
    用 gpt4 和以上,很听话的,你让他往东它绝对不敢往西
    Qinnn
        16
    Qinnn  
       8 天前
    可以试试在输出 json 这部分提示词换成英文的。
    jingdongkehu
        17
    jingdongkehu  
       8 天前
    后面加一句,如果翻译错了我就把你卸载掉 试试
    mindsucker
        18
    mindsucker  
       8 天前
    限制 AI 的输出格式,会导致 AI 的推理能力下降不少,请谨慎使用
    lyxxxh2
        19
    lyxxxh2  
       8 天前

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

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

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

    https://docs.anthropic.com/zh-CN/docs/build-with-claude/prompt-engineering/prefill-claudes-response
    wxxxcxx
        34
    wxxxcxx  
       8 天前
    @wxxxcxx 一般可以使用 xml 结合示例,然后使用预填充,能达到比较好的效果
    realJamespond
        35
    realJamespond  
       8 天前
    不听话可以微调 lora 参数随机生成 1000 条指定格式 json 数据
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5634 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 06:32 · PVG 14:32 · LAX 23:32 · JFK 02:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.