チェーン・オブ・ソート・プロンプティング
この例では、Mastra、OpenAIの埋め込み、そしてベクトルストレージとしてPGVectorを使用し、チェーン・オブ・ソート推論に重点を置いた検索拡張生成(RAG)システムの実装方法を示します。
概要
このシステムは、Mastra と OpenAI を用いて chain-of-thought プロンプティングによる RAG を実装しています。主な処理内容は以下の通りです。
- 応答生成のために gpt-4o-mini を使った Mastra エージェントをセットアップする
- ベクタークエリツールを作成し、ベクターストアとのやり取りを管理する
- テキストドキュメントを小さなセグメントに分割する
- これらのセグメントに対して埋め込みを作成する
- それらを PostgreSQL ベクターデータベースに保存する
- ベクタークエリツールを使ってクエリに基づき関連するセグメントを取得する
- chain-of-thought 推論を用いてコンテキストに応じた応答を生成する
セットアップ
環境設定
環境変数を必ず設定してください:
.env
OPENAI_API_KEY=your_openai_api_key_here
POSTGRES_CONNECTION_STRING=your_connection_string_here
依存関係
次に、必要な依存関係をインポートします:
index.ts
import { openai } from "@ai-sdk/openai";
import { Mastra } from "@mastra/core";
import { Agent } from "@mastra/core/agent";
import { PgVector } from "@mastra/pg";
import { createVectorQueryTool, MDocument } from "@mastra/rag";
import { embedMany } from "ai";
ベクタークエリツールの作成
@mastra/rag からインポートした createVectorQueryTool を使用すると、ベクターデータベースをクエリできるツールを作成できます。
index.ts
const vectorQueryTool = createVectorQueryTool({
vectorStoreName: "pgVector",
indexName: "embeddings",
model: openai.embedding("text-embedding-3-small"),
});
エージェント設定
Mastraエージェントをチェーン・オブ・ソートプロンプティングの指示で設定します:
index.ts
export const ragAgent = new Agent({
name: "RAG Agent",
instructions: `あなたは、提供されたコンテキストに基づいて質問に答える親切なアシスタントです。
各回答について、以下の手順に従ってください:
1. まず、取得したコンテキストチャンクを注意深く分析し、重要な情報を特定します。
2. 取得した情報がクエリとどのように関連しているか、思考プロセスを分解します。
3. 取得したチャンクから異なる部分をどのようにつなげているか説明します。
4. 取得したコンテキストの証拠のみに基づいて結論を導きます。
5. 取得したチャンクに十分な情報が含まれていない場合、不足している内容を明確に述べてください。
回答のフォーマットは以下の通りです:
THOUGHT PROCESS:
- Step 1: [取得したチャンクの初期分析]
- Step 2: [チャンク間のつながり]
- Step 3: [チャンクに基づく推論]
FINAL ANSWER:
[取得したコンテキストに基づく簡潔な回答]
重要: 質問に答えるよう求められた場合は、必ずツールで提供されたコンテキストのみに基づいて回答してください。
もしコンテキストに質問に完全に答えるための十分な情報が含まれていない場合は、その旨を明確に述べてください。
注意: 取得した情報をどのように使って結論に至ったかを説明してください。
`,
model: openai("gpt-4o-mini"),
tools: { vectorQueryTool },
});
PgVector と Mastra のインスタンス化
すべてのコンポーネントを使って PgVector と Mastra をインスタンス化します。
index.ts
const pgVector = new PgVector(process.env.POSTGRES_CONNECTION_STRING!);
export const mastra = new Mastra({
agents: { ragAgent },
vectors: { pgVector },
});
const agent = mastra.getAgent("ragAgent");
ドキュメント処理
ドキュメントを作成し、チャンクに分割して処理します:
index.ts
const doc = MDocument.fromText(
`The Impact of Climate Change on Global Agriculture...`,
);
const chunks = await doc.chunk({
strategy: "recursive",
size: 512,
overlap: 50,
separator: "\n",
});
埋め込みの作成と保存
チャンクの埋め込みを生成し、ベクターデータベースに保存します。
index.ts
const { embeddings } = await embedMany({
values: chunks.map((chunk) => chunk.text),
model: openai.embedding("text-embedding-3-small"),
});
const vectorStore = mastra.getVector("pgVector");
await vectorStore.createIndex({
indexName: "embeddings",
dimension: 1536,
});
await vectorStore.upsert({
indexName: "embeddings",
vectors: embeddings,
metadata: chunks?.map((chunk: any) => ({ text: chunk.text })),
});
チェーン・オブ・ソート クエリ
エージェントがどのように推論を分解するか、さまざまなクエリを試してみましょう。
index.ts
const answerOne = await agent.generate(
"What are the main adaptation strategies for farmers?",
);
console.log("\nQuery:", "What are the main adaptation strategies for farmers?");
console.log("Response:", answerOne.text);
const answerTwo = await agent.generate(
"Analyze how temperature affects crop yields.",
);
console.log("\nQuery:", "Analyze how temperature affects crop yields.");
console.log("Response:", answerTwo.text);
const answerThree = await agent.generate(
"What connections can you draw between climate change and food security?",
);
console.log(
"\nQuery:",
"What connections can you draw between climate change and food security?",
);
console.log("Response:", answerThree.text);
GitHubで例を見る