🧠

AI SDKでLLMの出力を構造化する

に公開

この記事ではVercelのAI SDKを利用して,LLMの出力を制御する方法を紹介します[1]

AI SDKとは

AI SDKはVercelが提供しているツールキットで,TypeScriptでAIを活用したアプリケーションを作成するための様々な機能を含んでいます.
その特徴として,例えば,

  • OpenAIやAnthropic,Grokなど様々なLLMモデルについて統一的な取り扱いを可能にしている
  • 型安全で構造化された出力管理を可能にする
  • マルチモーダルに対応している
  • 外部APIや関数をLLMから呼び出すことが可能になっている

などの点が挙げられます.

ここでは特に,型安全な出力が得られるという特徴を取り上げて,具体的な使用例とともに紹介します.

背景と目的

近年,ChatGPTなどの生成AIが目覚ましい進展を見せています.
OpenAI APIなどを利用することにより,TypeScriptやPythonのコードの中でもLLMを呼び出すことが可能になっています.

しかし,LLMの出力は

  • 自然言語によるものであり
  • 実行のたびに異なる

という観点からプログラムの中で使うには扱いづらい部分があります.

例えば,"1+1は?"と聞くと"1+1の答えは2です"などという答えが帰ってきます.
しかし,これではその計算結果を次の計算に使うこともままなりません.

AI SDKの提供している機能を活用することで,LLMの出力を制御し,指定した型で結果を得ることが可能になります.

generateObject()

型安全で構造化された出力を得るための機能はgenerateObject()という関数として提供されています.
この関数ではZodを使って定義されたスキーマを指定することで,指定されたスキーマの形で出力を得ることができます.

それでは,具体例で使い方を見ていきましょう[2]
今回は,人名の入力に対して,LLMに人名(string),誕生年(number),出身国(string)を答えさせる簡単なコードを作成します.

まず,プロジェクトの準備を行います.
ここでは,OpenAI APIを使用するので,APIキーを.envファイルに書き込んでおきます.
APIキーはOpenAIのサイトにアクセスしてCreate new secret keyから発行します[3]

mkdir AiSdk_sample

cd AiSdk_sample

touch generateObject.ts

pnpm add @ai-sdk/openai ai dotenv zod tsx

echo OPENAI_API_KEY="[Your OpenAI API Key]" > .env

続いて,上で作成したgenerateObject.tsファイルの中身を編集していきましょう.
まず必要なツールと環境変数の読み込みを行います.

generateObject.ts
import { z } from "zod";
import { openai } from "@ai-sdk/openai";
import { generateObject } from "ai";
import * as dotenv from "dotenv";

dotenv.config();

次に,人名(string),誕生年(number),出身国(string)の3つからなるスキーマpersonSchemaを定義します.

generateObject.ts
const personSchema = z.object({
  name: z.string().describe("名前"),
  year: z.number().describe("誕生年"),
  country: z.string().describe("出身国"),
});

generateObject関数にpersonSchemaを与え,promptにLLMに実行させる命令文を与えることで,指定した形での出力が得られます.
具体的には以下のように使用します.

generateObject.ts
const generatePersonInfo = async (personName: string) => {
  const result = await generateObject({
    model: openai("gpt-4.1-mini"),
    schema: personSchema,
    prompt: `以下の人物に関して,人名,誕生年,出身国を出力してください:
    ${personName}`,
  });
  return result;
};

簡単なテストを実行するために,main関数に具体例とその出力をまとめましょう.

generateObject.ts
async function main() {
  const personName = "福沢諭吉";
  const result = await generatePersonInfo(personName);

  console.log("Result:\n", result.object, "\n");
  console.log("Name:\n", result.object.name, "\n", typeof result.object.name);
  console.log("Year:\n", result.object.year, "\n", typeof result.object.year);
  console.log("Country:\n", result.object.country, "\n", typeof result.object.country);
}

main().catch(console.error);

以下をターミナルに入力することでコードを実行できます.

pnpm tsx generateObject.ts

以下のような結果が得られれば成功です.

Result:
 { name: '福沢諭吉', year: 1835, country: '日本' } 

Name:
 福沢諭吉 
 string
Year:
 1835 
 number
Country:
 日本 
 string

求めていたとおり,stringnumberstringの出力が得られていることが分かります.

おわりに

今回の記事では,AI SDKを利用して,LLMの出力を制御する方法を紹介しました.
LLMの出力を単なるテキストではなく,型付きのオブジェクトとして扱えることで,より安全で使いやすいアプリケーションを開発することができます.
このような手法は,LLMを利用したアプリケーションの開発において,重要な設計パターンの一つとなっていくでしょう.

この記事がプログラミングの中での生成AI活用の一助となれば幸いです.

脚注
  1. pnpmでTypeScriptが実行可能であれば,記事の通りに進めていただくことで動作するように書かれています. ↩︎

  2. 以下ではpnpmを使ってパッケージ管理や実行を行っていきます. ↩︎

  3. Githubなどでコードを管理する場合は,.gitignoreファイルを作成して,.envファイルを公開してしまわないように注意してください. ↩︎

Discussion