はじめに
この記事では、LLM では、モデルから構造化データを取得できます。この記事では、LangChain でモデルから構造化データを返す方法について説明します。具体的には以下の記事を参考に記述します。
https://js.langchain.com/v0.2/docs/how_to/structured_output/
TypeScript / JavaScript での GitHub リポジトリーを公開している実装例はすくないので記事化しました。作業リポジトリはこちらです。
https://github.com/hayato94087/langchain-extract-structured-data-demo
LangChain x TypeScript での実装例を以下の記事で紹介しています。
- LangChain で 簡易LLMアプリを構築(Node.js)
- LangChain でチャットボットを構築(Node.js)
- LangChain で構造化データを取得(Node.js)
- LangChain で Tools 呼び出す(Node.js)
- LangChain で Runnable をシクエンシャルに結合(Node.js)
- LangChain で Runnable を並列実行(Node.js)
- LangChain で 外部からデータを参照 前編(Node.js)
- LangChain で 外部からデータを参照 後編(Node.js)
- LangChain で Fallbacks(Node.js)
LangChain とは
LangChain は、大規模言語モデル(LLM)を活用したアプリケーションの開発を支援するフレームワークです。
https://js.langchain.com/v0.2/docs/introduction/
構造化データを取得する方法
LangChain でモデルから構造化データを返す方法について説明します。Zod で型を定義し、.withStructuredOutput を使うことで構造化データを取得できます。
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import 'dotenv/config'
// model
const model = new ChatOpenAI({
model: "gpt-3.5-turbo",
temperature: 0
});
// schema
const joke = z.object({
setup: z.string().describe("ジョークの前置き"),
punchline: z.string().describe("ジョークのオチ"),
rating: z.number().optional().describe("ジョークの面白さを1から10で評価"),
});
// structured output
const llm = model.withStructuredOutput(joke);
// invoke
const result = await llm.invoke("猫についてジョークを言ってください");
console.log(result)
作業プロジェクトの準備
TypeScript の簡易プロジェクトを作成します。
LangChain をインストール
LangChain をインストールします。
$ pnpm add langchain @langchain/core
言語モデルの選択
LangChain は、多くの異なる言語モデルをサポートしており、それらを自由に選んで使用できます。
例えば、以下のような言語モデルを選択できます。
- OpenAI
- Anthropic
- FireworksAI
- MistralAI
- Groq
- VertexAI
ここでは OpenAI を利用します。OpenAI を LangChain で利用するためのパッケージをインストールします。
$ pnpm add @langchain/openai
OpenAI API キーを取得
OpenAI API キーの取得方法はこちらを参照してください。
https://zenn.dev/hayato94087/articles/85378e1f7bc0e5#openai-の-apiキーの取得
環境変数の設定
環境変数に OpenAI キーを追加します。<your-api-key> に自身の API キーを設定してください。
$ touch .env
# OPENAI_API_KEY は OpenAI の API キーです。
OPENAI_API_KEY='<your-api-key>'
Node.js で環境変数を利用するために dotenv をインストールします。
$ pnpm i -D dotenv
基礎編
まず、シンプルに LLM を使ってみます。
コードを作成
コードを作成します。
$ touch demo01.ts
import { ChatOpenAI } from "@langchain/openai";
import 'dotenv/config'
const model = new ChatOpenAI({
model: "gpt-3.5-turbo",
temperature: 0
});
const result = await model.invoke("猫についてジョークを言ってください");
console.log(result)
ローカルで実行します。
$ pnpm vite-node demo01.ts
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: 'Q: 猫がパーティーで何を飲む?\nA: ミャウハイボール!',
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ 'langchain_core', 'messages' ],
content: 'Q: 猫がパーティーで何を飲む?\nA: ミャウハイボール!',
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 32, promptTokens: 22, totalTokens: 54 },
finish_reason: 'stop'
},
tool_calls: [],
invalid_tool_calls: []
}
コードの解説
OpenAI を利用します。
import { ChatOpenAI } from "@langchain/openai";
gpt-3.5-turbo のモデルを選択します。temperature は 0 に設定します。temperature が低いほど、モデルの出力はより予測可能になります。
const model = new ChatOpenAI({
model: "gpt-3.5-turbo",
temperature: 0
});
.invoke() を利用して、モデルにテキストを送信します。
const result = await model.invoke("猫についてジョークを言ってください");
Zod を使う方法
OpenAI を利用の場合、.withStructuredOutput() メソッドを利用することで構造化データを取得できます。どのような構造化データが欲しいかは Zod のスキーマを定義します。
インストール
Zod をインストールします。
$ pnpm add zod
コードを作成
コードを作成します。
$ touch demo02.ts
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import 'dotenv/config'
// model
const model = new ChatOpenAI({
model: "gpt-3.5-turbo",
temperature: 0
});
// schema
const joke = z.object({
setup: z.string().describe("ジョークの前置き"),
punchline: z.string().describe("ジョークのオチ"),
rating: z.number().optional().describe("ジョークの面白さを1から10で評価"),
});
// structured output
const llm = model.withStructuredOutput(joke);
// invoke
const result = await llm.invoke("猫についてジョークを言ってください");
console.log(result)
ローカルで実行します。
$ pnpm vite-node demo02.ts
{ setup: 'なぜ猫はコンピューターが好きなのか?', punchline: 'マウスがいるから!', rating: 8 }
コードを解説
構造化データのスキーマを Zod で定義します。
// schema
const joke = z.object({
setup: z.string().describe("ジョークの前置き"),
punchline: z.string().describe("ジョークのオチ"),
rating: z.number().optional().describe("ジョークの面白さを1から10で評価"),
});
.withStructuredOutput() メソッドを利用することで、構造化データを取得できるようになります。
// structured output
const llm = model.withStructuredOutput(joke);
Zod を使わない方法
Zod を使わずに、.withStructuredOutput() メソッドを利用して構造化データを取得する方法もあります。
コードを作成
コードを作成します。
$ touch demo03.ts
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import 'dotenv/config'
// model
const model = new ChatOpenAI({
model: "gpt-3.5-turbo",
temperature: 0
});
// schema
const parameters = {
title: "Joke",
type: "object",
properties: {
setup: { type: "string", description: "ジョークの前置き" },
punchline: { type: "string", description: "ジョークのオチ" },
},
required: ["setup", "punchline"],
}
// structured output
const llm = model.withStructuredOutput({
name: "joke",
description: "ユーザーに伝えるジョーク",
parameters
});
// invoke
const result = await llm.invoke("猫についてジョークを言ってください");
console.log(result)
ローカルで実行します。
$ pnpm vite-node demo03.ts
{ setup: 'なぜ猫はコンピューターが好きなのか?', punchline: 'マウスがいるから!' }
コードを解説
構造化データのスキーマを Zod で定義します。
// schema
const parameters = {
title: "Joke",
type: "object",
properties: {
setup: { type: "string", description: "ジョークの前置き" },
punchline: { type: "string", description: "ジョークのオチ" },
},
required: ["setup", "punchline"],
}
.withStructuredOutput() メソッドを利用することで、構造化データを取得できるようになります。
// structured output
const llm = model.withStructuredOutput({
name: "joke",
description: "ユーザーに伝えるジョーク",
parameters
});
Zod を利用したほうが記述は直感的です。
さいごに
LangChain でモデルから構造化データを返す方法について説明しました。LangChain を使って、モデルから構造化データを取得する方法を理解しました。Zod を利用することで、構造化データのスキーマを定義できます。Zod を使わずに構造化データを取得する方法もありますが、Zod を使ったほうが記述は直感的です。
作業リポジトリ
作業リポジトリはこちらです。
https://github.com/hayato94087/langchain-extract-structured-data-demo
