ストリーミング作業メモリ(上級)
この例では、最小限のコンテキストでも作業メモリを使用してToDoリストを維持するエージェントを作成する方法を示しています。作業メモリに関するより簡単な入門については、基本的な作業メモリの例を参照してください。
セットアップ
ワーキングメモリ機能を持つエージェントの作成方法を詳しく見ていきましょう。最小限のコンテキストでもタスクを記憶するTodoリストマネージャーを構築します。
1. メモリのセットアップ
まず、状態を維持するためにワーキングメモリを使用するので、短いコンテキストウィンドウでメモリシステムを設定します。メモリはデフォルトでLibSQLストレージを使用しますが、必要に応じて他のストレージプロバイダーを使用することもできます:
import { Memory } from "@mastra/memory";
const memory = new Memory({
options: {
lastMessages: 1, // ワーキングメモリを使用することで、短いコンテキストウィンドウでも会話の一貫性を維持できます
workingMemory: {
enabled: true,
},
},
});
2. ワーキングメモリテンプレートの定義
次に、エージェントがTodoリストデータをどのように構造化するかを示すテンプレートを定義します。このテンプレートはMarkdownを使用してデータ構造を表現します。これにより、エージェントは各Todoアイテムについて追跡すべき情報を理解できるようになります。
const memory = new Memory({
options: {
lastMessages: 1,
workingMemory: {
enabled: true,
template: `
# Todo List
## Item Status
- Active items:
- Example (Due: Feb 7 3028, Started: Feb 7 2025)
- Description: This is an example task
## Completed
- None yet
`,
},
},
});
3. Todoリストエージェントの作成
最後に、このメモリシステムを使用するエージェントを作成します。エージェントの指示は、ユーザーとどのように対話し、Todoリストを管理するかを定義します。
import { openai } from "@ai-sdk/openai";
const todoAgent = new Agent({
name: "TODO Agent",
instructions:
"You are a helpful todolist AI agent. Help the user manage their todolist. If there is no list yet ask them what to add! If there is a list always print it out when the chat starts. For each item add emojis, dates, titles (with an index number starting at 1), descriptions, and statuses. For each piece of info add an emoji to the left of it. Also support subtask lists with bullet points inside a box. Help the user timebox each task by asking them how long it will take.",
model: openai("gpt-4o-mini"),
memory,
});
注意: テンプレートと指示は任意です - workingMemory.enabled
がtrue
に設定されている場合、エージェントがワーキングメモリの使用方法を理解するのに役立つデフォルトのシステムメッセージが自動的に挿入されます。
使用例
エージェントの応答には、Mastraが自動的にワーキングメモリを更新するために使用する <working_memory>$data</working_memory>
のようなXMLタグが含まれています。これを処理する2つの方法を見てみましょう:
基本的な使用方法
シンプルなケースでは、maskStreamTags
を使用してワーキングメモリの更新をユーザーから隠すことができます:
import { randomUUID } from "crypto";
import { maskStreamTags } from "@mastra/core/utils";
// 会話を開始する
const threadId = randomUUID();
const resourceId = "SOME_USER_ID";
// 新しいTodoアイテムを追加する
const response = await todoAgent.stream(
"タスクを追加してください:アプリに新機能を構築する。約2時間かかり、来週の金曜日までに完了する必要があります。",
{
threadId,
resourceId,
},
);
// ワーキングメモリの更新を隠しながらストリームを処理する
for await (const chunk of maskStreamTags(
response.textStream,
"working_memory",
)) {
process.stdout.write(chunk);
}
UIフィードバック付きの高度な使用方法
より良いユーザー体験のために、ワーキングメモリが更新されている間にローディング状態を表示することができます:
// 上記と同じインポートとセットアップ...
// UIフィードバックを提供するライフサイクルフックを追加
const maskedStream = maskStreamTags(response.textStream, "working_memory", {
// working_memoryタグが始まるときに呼び出される
onStart: () => showLoadingSpinner("Todoリストを更新中..."),
// working_memoryタグが終了するときに呼び出される
onEnd: () => hideLoadingSpinner(),
// マスクされたコンテンツで呼び出される
onMask: (chunk) => console.debug("更新されたTodoリスト:", chunk),
});
// マスクされたストリームを処理する
for await (const chunk of maskedStream) {
process.stdout.write(chunk);
}
この例では以下を示しています:
- ワーキングメモリを有効にしたメモリシステムのセットアップ
- 構造化XMLを持つTodoリストテンプレートの作成
maskStreamTags
を使用してメモリ更新をユーザーから隠す- ライフサイクルフックを使用してメモリ更新中にUIローディング状態を提供する
コンテキスト内に1つのメッセージしかない場合でも(lastMessages: 1
)、エージェントはワーキングメモリに完全なTodoリストを維持します。エージェントが応答するたびに、Todoリストの現在の状態でワーキングメモリを更新し、対話間の永続性を確保します。
エージェントメモリについて、他のメモリタイプやストレージオプションを含めて詳しく知るには、メモリのドキュメントページをご覧ください。