当前位置: 首页 > article >正文

AI - 使用LangChain请求LLM结构化生成内容

AI - 使用LangChain请求LLM结构化生成内容

ai-langchain

基于深度学习的大型语言模型(LLM)不仅可以生成文本,还可以帮助我们完成许多复杂任务,如自动化客服、内容创作和数据分析。然而,如何从这些模型中结构化地获取输出,仍然是一个关键问题。在这篇文章中,我们将探索如何使用 JavaScript 和 LangChain 构建一个简单的 LLM结构化输出的应用程序。

场景

在构建 LLM 应用程序时,许多时候我们不仅仅需要模型生成文本,还需要它按照我们指定的格式输出结果。这样的需求在以下场景中非常常见:

  • 数据处理和分析:当我们需要对生成的数据进一步处理和分析时,结构化数据会更加便于处理。
  • 系统集成:在复杂系统中,各个组件的协作往往需要标准化的数据格式,以确保不同模块之间的兼容性和数据流的顺畅。
  • 用户界面展示:结构化的数据更容易在用户界面中展示,让用户可以直观地理解内容。

好处

一致性

结构化输出可以确保返回的数据格式一致。这对于解析和处理数据非常重要,尤其是在需要进一步操作或存储数据的情况下。

易于调试

标准化的数据格式使得调试过程更加容易。通过固定的结构,我们可以迅速识别并修复可能存在的格式或内容问题。

自动化

结构化数据更便于自动化处理。无论是将数据存储到数据库中,还是进行进一步的分析和可视化,结构化数据都能大大简化这些过程。

实现结构化内容生成的方式

在利用大型语言模型(LLM)生成结构化内容时,我们可以通过直接设置提示(prompting)或使用withStructuredOutput方法来达到目的。这两种方法都有其独特的优点和适用场合。以下是对这两种方法的比较:

通过提示(Prompting)

通过提示法实现结构化内容生成,主要依赖于构建一个明确的文本提示,指导模型生成所需格式的输出。

优点

  • 简单易行:不需要额外的工具或库,只需精心设计提示即可。
  • 灵活性高:可以自由地设计和修改提示内容,适应不同的需求。
  • 模型无关:适用于不同类型的语言模型(如GPT-3、BERT等),无论其内部细节如何。

缺点

  • 依赖人工设计质量:提示的设计质量直接影响输出的准确性和格式一致性。
  • 不易维护和扩展:复杂的提示容易变得冗长和难以管理,修改提示可能导致意料之外的问题。
  • 高变异性:模型可能因细微的提示变化生成不同的格式,缺乏一致性和稳定性。

使用withStructuredOutput

withStructuredOutput方法是LangChain库提供的一种方法,通过定义结构化输出的模式来指导模型生成特定格式的内容。

优点

  • 强一致性:通过预定义的数据模式确保输出的格式和内容一致。
  • 易于维护和扩展:更改结构化输出模式比更改提示更为简单和直观,不需要修改大量提示文本。
  • 自动化:减少了手动调试和格式化的麻烦,通过明确的模式定义确保输出的准确性。

缺点

  • 依赖工具库:需要学习和使用LangChain或类似工具库提供的API。
  • 灵活性较低:输出格式固定,适应特定需求相对简单,但面对复杂和变动频繁的需求时可能不灵活。

示例代码

示例代码来主体源于LangChain官网,有兴趣的小伙伴可以去官网查看。下面将通过多种方式提示 LLM 讲一个笑话,并要求返回包括笑话的开头(setup),笑点(punchline),笑话的搞笑程度(rating)以及为什么它很搞笑(reason)的结构化输出。

第一步:设置开发环境

首先,创建一个新目录并进入该目录:

mkdir langchain-structure-output-app
cd langchain-structure-output-app

初始化一个新的Node.js项目:

npm init -y

安装必要的依赖:

# 安装langchain
npm install langchain @langchain/core --save

# 安装groq的langchain开发包
npm install @langchain/groq  --save

# 安装环境变量配置库
npm install dotenv --save

# 安装JSONSchema生成库
npm install zod --save

第二步:创建项目结构

创建项目所需的文件和目录结构:

langchain-structure-output-app
├── index.js
├── .env
└── package.json

第三步:配置环境变量

在项目目录中创建一个 .env 文件,并添加Groq API密钥:

GROQ_API_KEY=your_groq_api_key_here

第四步:编写主应用程序

index.js 中编写应用程序代码,配置LangChain并创建翻译功能。

// 引入LangChain开发包,ChatGroq是用于与Groq语言模型交互的类
import { ChatGroq } from "@langchain/groq";

// 导入 dotenv,它是一个零依赖模块,能够从.env文件中加载环境变量到process.env中
import dotenv from "dotenv";

// 导入zod用于TypeScript优先的模式验证,并带有静态类型推断功能
import { z } from "zod";

// 加载 .env 文件中的环境变量GROQ_API_KEY
dotenv.config();

// 配置Groq LLM(语言模型),设置模型名称和温度参数
const model = new ChatGroq({
  model: "mixtral-8x7b-32768", // 使用的模型名称
  temperature: 0, // 温度参数,决定输出的随机性
});

第五步:JsonSchema结构化输出

/**
 * 通过JsonSchema实现结构化输出
 * 
 * @param {string} model LLM实例
 * @param {boolean} includeRaw 是否包含原始内容,默认不包含
 */
async function tellJoke(model, includeRaw = false) {
  // 定义结构化的笑话对象模式
  const joke = z.object({
    setup: z.string().describe("The setup of the joke"), // 笑话的开场部分,为字符串类型
    rating: z.number().describe("How funny the joke is, from 1 to 10"), // 笑话的搞笑程度评分,1到10的数字类型
    punchline: z.string().describe("The punchline to the joke"), // 笑点部分,为字符串类型
    reason: z.string().describe("The reason why it is funny"), // 可笑的原因,为字符串类型
  });

  // 使用withStructuredOutput方法,将输出格式化为定义好的笑话模式
  // 设置输出格式名为“joke”
  const structuredLlm = model.withStructuredOutput(joke, {
    includeRaw: includeRaw,
    name: "joke",
  });

  // 通过invoke方法向模型询问一个关于狗的笑话并获取结构化的输出
  const answer = await structuredLlm.invoke("Tell me a joke about dogs");

  // 打印输出的笑话结果
  console.log(answer);
}
await tellJoke(model);

用以下命令或者npm start运行应用程序:

node index.js

输出结果是一个标准的JSON格式,如下所示:

bash-3.2$ npm start

> langchain-structure-output-app@1.0.0 start
> node index

{
  setup: 'Why did the scarecrow adopt a dog?',
  rating: 5,
  punchline: 'Because he needed a bark-ing buddy!',
  reason: "It's a play on words between 'bark' and 'scarecrow's job'"
}

然后并非所有的LLM都支持结构化内容输出,对于不支持的情况,可以考虑将tellJoke(model, includeRaw = false)的第二个参数includeRaw置成true,这样可以返回原始内容,如下所示,然后开发者可以进行自定义解析。

{
  raw: AIMessage {
    "content": "",
    "additional_kwargs": {
      "tool_calls": [
        {
          "id": "call_sxtk",
          "type": "function",
          "function": "[Object]"
        }
      ]
    },
    "response_metadata": {
      "tokenUsage": {
        "completionTokens": 158,
        "promptTokens": 1280,
        "totalTokens": 1438
      },
      "finish_reason": "tool_calls"
    },
    "tool_calls": [
      {
        "name": "joke",
        "args": {
          "setup": "Why did the scarecrow adopt a dog?",
          "rating": 5,
          "punchline": "Because he needed a bark-ing buddy!",
          "reason": "It's a play on words between 'bark' and 'scarecrow's job'"
        },
        "type": "tool_call",
        "id": "call_sxtk"
      }
    ],
    "invalid_tool_calls": [],
    "usage_metadata": {
      "input_tokens": 1280,
      "output_tokens": 158,
      "total_tokens": 1438
    }
  },
  parsed: {
    setup: 'Why did the scarecrow adopt a dog?',
    rating: 5,
    punchline: 'Because he needed a bark-ing buddy!',
    reason: "It's a play on words between 'bark' and 'scarecrow's job'"
  }
}

第六步:OpenAI风格结构化输出

// 通过OpenAI-style JSON schema 实现结构化输出
async function tellJoke2(model) {
  // 定义结构化的笑话对象模式
  const structuredLlm = model.withStructuredOutput({
    name: "joke",
    description: "Joke to tell user.",
    parameters: {
      title: "Joke",
      type: "object",
      properties: {
        setup: { type: "string", description: "The setup for the joke" },
        rating: { type: "number", description: "How funny the joke is, from 1 to 10" },
        punchline: { type: "string", description: "The punchline to the joke" },
        reason: { type: "string", description: "The reason why it is funny" }
      },
      required: ["setup", "punchline", "rating", "reason"],
    },
  });
  
  // 通过invoke方法向模型询问一个关于老鼠的笑话并获取结构化的输出
  // 设置输出格式名为“joke”
  const answer = await structuredLlm.invoke("Tell me a joke about mouse", { name: "joke" });

  // 打印输出的笑话结果
  console.log(answer);
}
await tellJoke2(model);

用以下命令或者npm start运行应用程序:

node index.js

输出结果是一个标准的JSON格式,如下所示:

bash-3.2$ npm start

> langchain-structure-output-app@1.0.0 start
> node index

{
  setup: "Why don't mice use spell check?",
  punchline: "Because they're afraid of making a misspell-mouse!",
  rating: 5,
  reason: "It's a play on words related to the question."
}

总结

ai-quotes-1

在本文中,我们使用LangChain和JavaScript创建了一个简单的格式化输出应用程序,通过配置Groq API并使用LangChain框架,在利用大型语言模型(LLM)生成结构化内容时,我们可以通过直接设置提示(prompting)或使用withStructuredOutput方法来达到目的。在这个基础上,您可以扩展该应用程序,以支持更多的功能和更复杂的应用场景。希望本教程对您有所帮助!


http://www.kler.cn/a/383504.html

相关文章:

  • ubuntu 22.04 server 安装 xtrabackup 2.4 qpress LTS
  • java的体系结构
  • 【青牛科技】GC8549替代LV8549/ONSEMI在摇头机、舞台灯、打印机和白色家电等产品上的应用分析
  • 大数据新视界 -- 大数据大厂之 Impala 性能优化:解锁大数据分析的速度密码(上)(1/30)
  • 全文检索ElasticSearch到底是什么?
  • Docker 基础命令简介
  • Unet++改进3:添加NAMAttention注意力机制
  • 重新回顾反向传播与梯度下降:训练神经网络的基石
  • Redis安装配置及基本使用(保姆级安装教程非常耐用)
  • 【云原生开发】K8S多集群资源管理平台架构设计
  • 【静态页面】尚品汇 1、设计稿分析及资源准备
  • Nginx 在中小企业的初级应用实操指南
  • 【HCIP园区网综合拓扑实验】配置步骤与详解(未施工完,持续更新中)
  • git撤销commit和add
  • 【YOLO学习】YOLOv8改进举例
  • 深入理解Java虚拟机(JVM):从基础到实战
  • 【p2p、分布式,区块链笔记 Torrent】WebTorrent bittorrent-dht DHT的构造+lookup+announce
  • 领克双十一营销设计:视觉与策略的完美融合
  • Flutter 鸿蒙next中的 Stack 和 Positioned 用法详解
  • 算法练习:1004. 最大连续1的个数 III
  • 基于SSM+VUE守护萌宠宠物网站JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解
  • ORACLE 19C 安装数据库补丁的详细过程
  • 利用全排列解决LeetCode第3343题“统计平衡排列的数目”问题
  • 【Java SE语法】抽象类(abstract class)和接口(interface)有什么异同?
  • 一个国产 API 开源项目,在 ProductHunt 杀疯了...
  • 【HarmonyOS】引导用户跳转APP设置详情页开启权限