大语言模型下的JSON数据格式交互

插: AI时代,程序员或多或少要了解些人工智能,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家(前言 – 人工智能教程 )

坚持不懈,越努力越幸运,大家一起学习鸭~~~

随着大语言模型能力的增强,传统应用不可避免的需要调用LLM接口,提升应用的智能程度和用户体验,但是一般来说大语言模型的输出都是字符串,除了个别厂商支持JSON Mode,或者使用function call强制大语言模型输出json格式,大部分情况下,还是需要业务放自己去处理JSON格式,下面我来总结一下在解析JSON过程中遇到的一些问题和解决方案。

一、如何让大语言模型返回JSON格式?

其实LLM对Markdown和JSON格式还是比较友好的,在指令中指定返回JSON格式,基本都会遵循,

你是一个翻译大师,我给你一段中文,你翻译为英文、日文、韩文。
返回JSON格式,包含三个属性,分别为:english、japanese、korean。
现在开始翻译,中文内容是:
阿里巴巴是一家伟大的公司。

返回结果:

```json
{
  "english": "Alibaba is a great company.",
  "japanese": "アリババは素晴らしい会社です。",
  "korean": "알리바바는 위대한 회사입니다."
}
```

这个时候,我们可以使用正则表达式,提取出Markdown格式下的JSON内容:

const match = /```(json)?(.*)```/s.exec(s);
  if (!match) {
    return JSON.parse(s);
  } else {
    return JSON.parse(match[2]);
  }

但是返回一个稳定的JSON格式,也不是那么容易,如果模型能力不强,可以会返回以下内容:

Here is the translation in JSON format:


{
"english": "Alibaba is a great company.",
"japanese": "アルイババは偉大な企業です。",
"korean": "알리바바는 위대한 기업입니다."
}


Let me know if you need anything else! 😊

即使返回了正确的JSON格式,但是属性名和属性值对应的格式(可能嵌套数组、对象),也不定每次都正确,特别是在复杂场景下,目前有以下几种方案,可以确保返回的内容一定是遵循JSON格式。

1.1 JSON mode

在调用 Openai 的 gpt-4-turbo-preview 或 gpt-3.5-turbo-0125 模型时,可以将 response_format 设置为 { "type": "json_object" } 以启用 JSON 模式。启用后,模型仅限于生成解析为有效 JSON 对象的字符串。具体可查看:

​https://platform.openai.com/docs/guides/text-generation/json-mode​​。

示例代码:

import OpenAI from "openai";


const openai = new OpenAI();


async function main() {
  const completion = await openai.chat.completions.create({
    messages: [
      {
        role: "system",
        content: "You are a helpful assistant designed to output JSON.",
      },
      { role: "user", content: "Who won the world series in 2020?" },
    ],
    model: "gpt-3.5-turbo-0125",
    response_format: { type: "json_object" },
  });
  console.log(completion.choices[0].message.content);
}


main();

返回响应:

"content": "{\"winner\": \"Los Angeles Dodgers\"}"`

值得注意的是:除了Openai,其他厂商基本都不支持JSON mode 。

1.2 function call

function call 其实本身不是解决JSON格式的,主要是解决将大型语言模型连接到外部工具的问题。可以在对话时描述函数,并让模型智能地选择输出包含调用一个或多个函数的参数的 JSON 对象。聊天完成 API 不会调用该函数,模型会生成 JSON,然后使用它来调用代码中的函数。

const messages = [
      { role: 'system', content: 'You are a helpful assistant.' },
      {
        role: 'user',
        content: '给[email protected]发一封邮件,主题是祝福他生日快乐,内容是祝福语',
      },
    ];
const response = await openai.chat.completions.create({
  messages: messages,
  model: 'gpt-4-1106-preview',
  tools: [
    {
      type: 'function',
      function: {
        name: 'send_email',
        description: 'Send an email',
        parameters: {
          type: 'object',
          properties: {
            to: {
              type: 'string',
              description: 'Email address of the recipient',
            },
            subject: {
              type: 'string',
              description: 'Subject of the email',
            },
            body: {
              type: 'string',
              description: 'Body of the email',
            },
          },
          required: ['to', 'body'],
        }
      }
    }
  ],
});
const responseMessage = response.choices[0].message;
console.log(JSON.stringify(responseMessage));

返回:

{
    "content": null,
    "role": "assistant",
    "tool_calls": [
        {
            "function": {
                "arguments": "{\"to\":\"[email protected]\",\"subject\":\"祝你生日快乐\",\"body\":\"亲爱的无弃,祝你生日快乐!愿你新的一年里,幸福安康、梦想成真。\"}",
                "name": "send_email"
            },
            "id": "call_JqC8t3jlmg25uDJg7mwHvvOG",
            "type": "function"
        }
    ]
}

在这里我们就可以利用tools的function parameters来定义希望返回的JSON格式,parameters遵循了JSON chema的规范,​​https://json-schema.org/learn/getting-started-step-by-step​​。这个时候,返回的tool_calls的arguments就是一个标准的JSON字符串。

注意:也不是所有模型都支持function call的能力。

1.3 langchain结合Zod

Zod是一个TypeScript优先的模式声明和验证库。

​https://github.com/colinhacks/zod/blob/HEAD/README_ZH.md​​

import { z } from "zod";


const User = z.object({
  username: z.string(),
});


User.parseAsync({ username: "无弃" });  // => { username: "无弃" }
User.parseAsync({ name: "无弃" }); // => throws ZodError

在langchian.js中,Structured output parser就是使用Zod来声明和校验JSON格式。

1.3.1 声明返回JSON格式

import { z } from "zod";
import { StructuredOutputParser } from "langchain/output_parsers";


const parser = StructuredOutputParser.fromZodSchema(
  z.object({
    answer: z.string().describe("answer to the user's question"),
    sources: z
      .array(z.string())
      .describe("sources used to answer the question, should be websites."),
  })
);
console.log(parser.getFormatInstructions());
/*
Answer the users question as best as possible.
You must format your output as a JSON value that adheres to a given "JSON Schema" instance.


"JSON Schema" is a declarative language that allows you to annotate and validate JSON documents.


For example, the example "JSON Schema" instance {
  
  {"properties": {
  
  {"foo": {
  
  {"description": "a list of test words", "type": "array", "items": {
  
  {"type": "string"}}}}}}, "required": ["foo"]}}}}
would match an object with one required property, "foo". The "type" property specifies "foo" must be an "array", and the "description" property semantically describes it as "a list of test words". The items within "foo" must be strings
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值