Skip to Content
メモリAI SDK useChat フック

例: AI SDK useChat フック

Vercel AI SDKのuseChatフックを使用して、ReactのようなフロントエンドフレームワークとMastraのメモリを統合するには、メッセージ履歴を重複しないように注意深く扱う必要があります。この例では、推奨されるパターンを示しています。

useChatを使用したメッセージ重複の防止

useChatのデフォルトの動作は、各リクエストでチャット履歴全体を送信します。MastraのメモリはthreadIdに基づいて履歴を自動的に取得するため、クライアントから完全な履歴を送信すると、コンテキストウィンドウとストレージに重複したメッセージが発生します。

解決策: useChatを設定して、threadIdresourceIdと共に最新のメッセージのみを送信します。

// components/Chat.tsx (React Example) import { useChat } from "ai/react"; export function Chat({ threadId, resourceId }) { const { messages, input, handleInputChange, handleSubmit } = useChat({ api: "/api/chat", // Your backend endpoint // Pass only the latest message and custom IDs experimental_prepareRequestBody: (request) => { // Ensure messages array is not empty and get the last message const lastMessage = request.messages.length > 0 ? request.messages[request.messages.length - 1] : null; // Return the structured body for your API route return { message: lastMessage, // Send only the most recent message content/role threadId, resourceId, }; }, // Optional: Initial messages if loading history from backend // initialMessages: loadedMessages, }); // ... rest of your chat UI component return ( <div> {/* Render messages */} <form onSubmit={handleSubmit}> <input value={input} onChange={handleInputChange} placeholder="Send a message..." /> <button type="submit">Send</button> </form> </div> ); } // app/api/chat/route.ts (Next.js Example) import { Agent } from "@mastra/core/agent"; import { Memory } from "@mastra/memory"; import { openai } from "@ai-sdk/openai"; import { CoreMessage } from "@mastra/core"; // Import CoreMessage const agent = new Agent({ name: "ChatAgent", instructions: "You are a helpful assistant.", model: openai("gpt-4o"), memory: new Memory(), // Assumes default memory setup }); export async function POST(request: Request) { // Get data structured by experimental_prepareRequestBody const { message, threadId, resourceId }: { message: CoreMessage | null; threadId: string; resourceId: string } = await request.json(); // Handle cases where message might be null (e.g., initial load or error) if (!message || !message.content) { // Return an appropriate response or error return new Response("Missing message content", { status: 400 }); } // Process with memory using the single message content const stream = await agent.stream(message.content, { threadId, resourceId, // Pass other message properties if needed, e.g., role // messageOptions: { role: message.role } }); // Return the streaming response return stream.toDataStreamResponse(); }

メッセージの永続性に関する詳細は、AI SDKのドキュメントを参照してください。

基本スレッド管理UI

このページは useChat に焦点を当てていますが、スレッドを管理するためのUI(リスト、作成、選択)を構築することもできます。これは通常、memory.getThreadsByResourceId()memory.createThread() のようなMastraのメモリ機能とやり取りするバックエンドAPIエンドポイントを含みます。

// スレッドリストの概念的なReactコンポーネント import React, { useState, useEffect } from 'react'; // API関数が存在すると仮定: fetchThreads, createNewThread async function fetchThreads(userId: string): Promise<{ id: string; title: string }[]> { /* ... */ } async function createNewThread(userId: string): Promise<{ id: string; title: string }> { /* ... */ } function ThreadList({ userId, currentThreadId, onSelectThread }) { const [threads, setThreads] = useState([]); // ... ローディングとエラーステート ... useEffect(() => { // userIdのスレッドを取得 }, [userId]); const handleCreateThread = async () => { // createNewThread APIを呼び出し、状態を更新し、新しいスレッドを選択 }; // ... スレッドのリストと新しい会話ボタンでUIをレンダリング ... return ( <div> <h2>会話</h2> <button onClick={handleCreateThread}>新しい会話</button> <ul> {threads.map(thread => ( <li key={thread.id}> <button onClick={() => onSelectThread(thread.id)} disabled={thread.id === currentThreadId}> {thread.title || `チャット ${thread.id.substring(0, 8)}...`} </button> </li> ))} </ul> </div> ); } // 親チャットコンポーネントでの使用例 function ChatApp() { const userId = "user_123"; const [currentThreadId, setCurrentThreadId] = useState<string | null>(null); return ( <div style={{ display: 'flex' }}> <ThreadList userId={userId} currentThreadId={currentThreadId} onSelectThread={setCurrentThreadId} /> <div style={{ flexGrow: 1 }}> {currentThreadId ? ( <Chat threadId={currentThreadId} resourceId={userId} /> // あなたのuseChatコンポーネント ) : ( <div>会話を選択または開始してください。</div> )} </div> </div> ); }

関連