V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lqw3030
V2EX  ›  问与答

大家是如何限制 LLM 输出格式为 JSON

  •  
  •   lqw3030 · 2024-06-02 10:34:48 +08:00 · 6844 次点击
    这是一个创建于 463 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 最近遇到一个问题,无论我用哪家(智谱、moonshot 、DeepSeek...等)都会存在有一定概率回复带引导词,或非完整的 json:
    {
        "usage": {
            "prompt_tokens": 185,
            "completion_tokens": 304,
            "total_tokens": 489
        },
        "created": 1717295221,
        "model": "GLM-4",
        "id": "123",
        "error": null,
        "choices": [
            {
                "finish_reason": "stop",
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": "根据您提供的信息,我为您做了以下规划:\n\n```json\n{\n  \"planDays\": [\n    {\n      \"dayPlanOrder\": 0,\n      \"dayStations\": [\n        {\n          \"stationName\": \"腾格里沙漠\",\n          \"stationOrder\": 0,\n          \"stationDescription\": \"中国第四大沙漠,体验沙漠探险和沙丘摩托\",\n          \"stationTag\": \"探险,自然景观\",\n          \"stationActivity\": \"沙漠徒步,骑骆驼,沙丘摩托\",\n          \"timeUsed\": 120\n        },\n        {\n          \"stationName\": \"贺兰山\",\n          \"stationOrder\": 1,\n          \"stationDescription\": \"阿拉善著名景点,参观贺兰山岩画\",\n          \"stationTag\": \"历史,文化,自然景观\",\n          \"stationActivity\": \"参观岩画,登山\",\n          \"timeUsed\": 90\n        },\n        {\n          \"stationName\": \"巴丹吉林沙漠\",\n          \"stationOrder\": 2,\n          \"stationDescription\": \"中国第三大沙漠,欣赏沙漠日落\",\n          \"stationTag\": \"自然景观\",\n          \"stationActivity\": \"欣赏日落\",\n          \"timeUsed\": 60\n        }\n      ]\n    }\n  ]\n}\n```\n\n 这个行程涵盖了阿拉善的主要景点,您可以根据个人兴趣选择参加的活动。如果选择自驾出行,可以在景点附近寻找停车场。祝您在阿拉善度过愉快的一天!",
                    "name": null,
                    "tool_call_id": null,
                    "tool_calls": null
                },
                "delta": null
            }
        ],
        "task_id": null,
        "request_id": null,
        "task_status": null
    }
    
    • 上述 content 字段中期望的理想的是只有纯粹的 json ,但实际字段中多出了“根据您提供的信息,我为您做了以下规划:\n\n```json\n”,并且是 markdown 格式的
    • 尽管我已经在 prompt 中加入了“参照以下格式输出,直接给出规划的结果,不需要添加任何引导性文本,输出的结果符合标准 json 格式{someKey:someValue}”。 想请教下各位是怎么解决的
    第 1 条附言  ·  91 天前

    以下是spring ai项目中使用的prompt实测能够达到比较高的约束力,给各位朋友提供个思路:

    Your response should be in JSON format.Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.Do not include markdown code blocks in your response.Remove the ```json markdown from the output.Here is the JSON Schema instance your output must adhere to: ```{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"someString":{"type":"string"}},"additionalProperties":false}```
    
    33 条回复    2024-06-05 23:02:36 +08:00
    mekingname
        1
    mekingname  
       2024-06-02 10:41:04 +08:00   ❤️ 3
    我使用 tool calling 来实现。

    定义一个函数,接受 n 个参数,这些参数就是你的 json 里面对应的各个字段。然后让大模型通过 tool calling 去调用这个函数就可以了。在函数里面拿到这些参数,就是你需要的已经格式化以后的数据。
    lqw3030
        2
    lqw3030  
    OP
       2024-06-02 10:44:55 +08:00
    @mekingname tool/funcation call 有碰到过非期望响应的情况不
    yinmin
        3
    yinmin  
       2024-06-02 10:45:55 +08:00 via iPhone   ❤️ 2
    调用 api 时,可以是多组对话,因此,你加几组“一问一答”到 message 里,给 gpt 做参考,而不是写在一条信息里
    maolon
        4
    maolon  
       2024-06-02 10:48:54 +08:00 via Android
    可能无关: gpt 可以指定 return as json object ,以及比较好奇楼上的 tool calling 能否解决嵌套字段问题?
    mumbler
        5
    mumbler  
       2024-06-02 11:32:44 +08:00
    指令跟随能力还是不够好,我用 gemini ,可以设置"response_mime_type": "application/json",几乎没遇到过加料的情况
    june4
        6
    june4  
       2024-06-02 11:36:00 +08:00
    就象楼上说的,给几个例子基本不可能出意外。
    yorhaha123
        7
    yorhaha123  
       2024-06-02 11:38:35 +08:00   ❤️ 1
    直接用正则表达式提取了
    yushi17
        8
    yushi17  
       2024-06-02 11:56:55 +08:00
    没有必要让大模型输出纯粹的 json 。你只要从里面找到 json 然后 parse 出来就行了。
    yushi17
        9
    yushi17  
       2024-06-02 11:58:09 +08:00
    可以参考 TypeChat: https://github.com/microsoft/TypeChat 就是我说的这个思路。
    izzy27
        10
    izzy27  
       2024-06-02 12:24:29 +08:00
    langchain 的 json parser
    m0unta1n886
        11
    m0unta1n886  
       2024-06-02 13:44:19 +08:00
    有个 github 项目专门处理这个问题的。
    codehz
        12
    codehz  
       2024-06-02 13:45:09 +08:00
    有些模型是自带这个的,不是我打广告,但是 minimax 那家是真的有,最关键是还能限制 json 格式,用一个类似 json schema 的语法
    (虽然实际用下来 bug 不少,尤其是和 array 类型配合,还是和模型本身的基础能力有关系。。。)
    akira
        13
    akira  
       2024-06-02 13:46:08 +08:00
    gpt 的话,有参数可以限制输出格式
    devliu1
        14
    devliu1  
       2024-06-02 14:22:07 +08:00 via Android
    gpt 可以直接指定
    lqw3030
        15
    lqw3030  
    OP
       2024-06-02 14:24:59 +08:00
    @m0unta1n886 https://github.com/RealAlexandreAI/json-repair 这个吗,我现在的做法是直接读取第一个{和最后一个},想说从语言模型本身出发解决这个问题
    lqw3030
        16
    lqw3030  
    OP
       2024-06-02 14:27:09 +08:00
    @yinmin 我去尝试下,先前的 prompt 模板都是参照 https://baoyu.io/translations/prompt-engineering/how-i-won-singapores-gpt-4-prompt-engineering-competition 里面建议的思路写的,我觉得你说的这个是个好主意👍
    lqw3030
        17
    lqw3030  
    OP
       2024-06-02 14:29:07 +08:00
    @maolon funcation 确实 function call 就是复杂的结构不好指定
    lqw3030
        18
    lqw3030  
    OP
       2024-06-02 14:35:27 +08:00
    @mumbler 我觉得可以这么指是最好得了,受限于调用环境,用的都是国内厂商的模型
    Cyron
        19
    Cyron  
       2024-06-02 14:47:48 +08:00 via iPhone   ❤️ 6
    之前做了几个试验性项目,用 dsl 约束+json_mode 效果稳定,写了个总结
    《 LLM 生成 Json 结构化数据的几种方案》 https://juejin.cn/post/7325429835387404307
    shampoo
        20
    shampoo  
       2024-06-02 16:43:35 +08:00
    题外话,做程序要讲究思维严谨、语义清晰:
    “限制输出格式为 JSON”这句话有歧义,应该改为“指定输出格式为 JSON 。”
    TheWalkingDead
        21
    TheWalkingDead  
       2024-06-02 19:48:57 +08:00
    @shampoo 你这真的是钻牛角尖,此地无银三百两。
    mekingname
        22
    mekingname  
       2024-06-02 20:14:45 +08:00
    @lqw3030 JSON 不能嵌套太深,否则可能拿到的结果跟预期不一致。
    wuyiccc
        23
    wuyiccc  
       2024-06-02 21:27:03 +08:00
    用的 langchain 的 output parser
    macaodoll
        24
    macaodoll  
       2024-06-02 21:57:18 +08:00 via Android
    国产的如果涉及到某些敏感词直接不按提示来的,用外面的没这个问题
    leehaoze98
        25
    leehaoze98  
       2024-06-02 23:48:30 +08:00
    模型本身支持限定输出为格式为 application/json 这种的效果最好,本身就是微调在模型内的。
    通过 Prompt 的方式约束,直接在 Prompt 内举出一个返回的示例效果是最好的,比如:

    ## 输出要求
    你的输出为 JSON 格式的字符串,压缩在一行内,包含两个字段,"KeyA"代表 XX ,"KeyB"代表 XX

    以下是一个输出示例
    leehaoze98
        26
    leehaoze98  
       2024-06-02 23:51:04 +08:00   ❤️ 1
    不小心发出去了,续楼上:

    以下是一个输出示例:
    {"KeyA":"ValA","KeyB":"ValB"}

    通过举例子的方法约束吼,只能保证返回的 JSON 大概率是你要求的格式,但是模型还是有概率在 JSON 后追加一些自然语言来进行解释,或者是加入 MarkDown 语法(有些模型就这么调的)。

    这个时候只能是对大模型的返回进行处理,已经有些现成的库,比如 LangChain 的 Parser ,Python 、TS 和 Go 都有一个 JSON Repair 库。

    只能是多种策略一起用,完全指望模型,代价高不稳定
    lqw3030
        27
    lqw3030  
    OP
       2024-06-02 23:59:33 +08:00
    @Cyron 晚些试了下,不知道是否是我调用的 API 问题,我参照文内编辑了 prompt ,整体输出质量是提高了,但是还是会出现类似```json 这样的 markdonw 头,好在简单的 substring 可以处理
    cheng6563
        28
    cheng6563  
       2024-06-03 09:07:21 +08:00
    问题是语言模型你不让他滔滔不绝说一堆的话,他的智力会有不少限制。
    yangyaofei
        29
    yangyaofei  
       2024-06-03 09:25:57 +08:00
    用 CFG 去控制, 比如 Guidance 和 OutLines 这种项目
    RRRoger
        30
    RRRoger  
       2024-06-03 09:39:24 +08:00
    https://mp.weixin.qq.com/s/gMdQBlTdvGbhzi_NL3HGXQ
    大语言模型下的 JSON 数据格式交互
    zhangwugui
        31
    zhangwugui  
       2024-06-03 15:40:36 +08:00
    那返回 json 的话,还能流式输出么
    Cyron
        32
    Cyron  
       2024-06-03 17:46:45 +08:00
    @lqw3030 #27 是的文本补全只能自己处理,如果想要 100%可用的 JSON 就用大模型的 JSON Mode ,参考 https://platform.openai.com/docs/guides/text-generation/json-mode
    Ironpan
        33
    Ironpan  
       2024-06-05 23:02:36 +08:00
    1. function_call/tools 能力
    2. 模型支持直接 mode 为 json 的, 例如 gpt-3.5 好像现在就行了?
    3. prompt: ReAct/Few shot(带几个例子进去)/langextract 里面有个提取结构化数据的核心 prompt 可以去找找, 然后改改
    4. 一些细节:
    4.1 prompt 使用 markdown 格式, 且添加标题, 如果返回的 json 里有注释, 你可以用 markdown 的格式添加注意事项叫它不要输出其他无关的内容, 或者不要加注释.
    4.2 上下文里不一定都是一个 human+ai 的成对消息. 可以是一个 system message + 一个/多个 ai 消息(补充说明) + user 消息. 然后自己看情况调整.
    4.3 我自己使用的时候返回的 json, 一般都是 markdown, 然后正则解析.

    希望有所帮助.
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5728 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 06:22 · PVG 14:22 · LAX 23:22 · JFK 02:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.