格式被吞,补发: 如何优雅地约束LLM输出结构

文摘   2024-11-22 09:36   湖北  

在使用ChatGPT、Claude等大语言模型时,你是否遇到过这样的困扰:模型的输出格式不统一,难以直接用于后续处理?今天就来介绍一个优雅的解决方案 - 使用AI SDK来约束LLM的输出结构。

为什么需要结构化输出?

在实际应用中,我们经常需要LLM生成特定格式的内容,比如:

  • JSON数据
  • 标准化的配置文件
  • 数据库记录
  • API响应

如果没有proper的约束,LLM的输出可能:

  • 格式不一致
  • 缺少必要字段
  • 数据类型混乱
  • 难以进行类型检查

技术方案:AI SDK + Zod

AI SDK提供了一个强大的generateObject函数,配合Zod schema,可以优雅地解决这个问题。

1. 环境准备

首先需要安装必要的依赖:

import { generateObject } from 'ai';
import { createOpenAI as createGroq } from '@ai-sdk/openai';
import { z } from 'zod';

2. 配置LLM提供商

这里以Groq为例:

const groq = createGroq({
  baseURL: 'https://api.groq.com/openai/v1',
  apiKey: process.env.GROQ_API_KEY,
});

3. 定义输出模式

使用Zod定义你需要的数据结构:

const recipeSchema = z.object({
  recipe: z.object({
    name: z.string(),
    ingredients: z.array(z.object({ 
      name: z.string(), 
      amount: z.string() 
    })),
    steps: z.array(z.string()),
  }),
});

4. 生成结构化数据

最后,使用generateObject函数获取符合格式的输出:

const { object } = await generateObject({
  model: groq('llama-3.1-70b-versatile'),
  schema: recipeSchema,
  prompt: 'Generate a lasagna recipe.',
});

实战案例

让我们来看几个具体的实战案例。

案例1:新闻摘要生成器

const newsSchema = z.object({
  summary: z.object({
    title: z.string(),
    briefing: z.string().max(200),
    keyPoints: z.array(z.string()),
    sentiment: z.enum(['positive', 'negative', 'neutral'])
  })
});

const news = await generateObject({
  model: groq('llama-3.1-70b-versatile'),
  schema: newsSchema,
  prompt: `Summarize this news article: ${article}`,
});

案例2:商品信息提取

const productSchema = z.object({
  product: z.object({
    name: z.string(),
    category: z.string(),
    price: z.number(),
    features: z.array(z.string()),
    specs: z.record(z.string(), z.string())
  })
});

const productInfo = await generateObject({
  model: groq('llama-3.1-70b-versatile'), 
  schema: productSchema,
  prompt: `Extract product information from: ${description}`,
});

案例3:问答格式化

const qaSchema = z.object({
  qa: z.object({
    question: z.string(),
    answer: z.string(),
    confidence: z.number().min(0).max(1),
    references: z.array(z.string())
  })
});

const formattedQA = await generateObject({
  model: groq('llama-3.1-70b-versatile'),
  schema: qaSchema,
  prompt: `Answer this question: ${question}`,
});

这些案例展示了如何在不同场景下使用schema来约束输出。每个案例都包含:

  • 明确的数据结构定义
  • 类型和格式约束
  • 实际的业务场景应用

结语

通过以上案例,我们可以看到AI SDK + Zod的组合不仅能确保输出的结构化,还能大大提升开发效率。这种方案既保持了LLM的灵活性,又增加了必要的约束,是构建生产级AI应用的重要工具。


字节笔记本
专注于科技领域的分享,AIGC,全栈开发,产品运营
 最新文章