フロントエンドを接続する
このガイドでは、会話の作成、更新、削除、およびメッセージの送信とアシスタント応答の購読方法について学びます。
会話とそれに関連するメッセージはAmazon DynamoDBに永続化されます。これは、会話の以前のメッセージがLLMに送信されたチェーンに自動的に含まれることを意味します。会話とメッセージへのアクセスは、所有者ベースの認可戦略を通じて個々のユーザーにスコープされます。
会話とメッセージの種類
会話
会話フロー内には、ConversationとMessageという2つのメインタイプがあります。
ConversationはアプリケーションユーザーとLLM間のチャットセッションのインスタンスです。会話と対話するためのデータとメソッドが含まれています。会話はそのメッセージとの1対多の関係があります。
ConversationタイプはSchema['myChat']['type']タイプ定義を通じてアクセス可能です。ここで'myChat'はデータスキーマ内の会話ルートの名前です。
| プロパティ/メソッド | 型 | 説明 |
|---|---|---|
id | string | 会話の一意の識別子 |
name | string | undefined | 会話の名前。 会話を作成または更新するときに名前を指定できます。 |
metadata | Record<string, string> | undefined | 会話に関連するメタデータ。 会話を作成または更新するときに任意のメタデータを指定できます。 |
createdAt | string | 会話が作成された日時 |
updatedAt | string | 最後のユーザーメッセージが送信された日時 |
sendMessage() | (content: MessageContent) => {data: Message;errors: Error[]} | AIアシスタントにメッセージを送信 |
listMessages() | () => {data: Message[];errors: Error[]} | 会話のすべてのメッセージをリスト表示 |
onStreamEvent() | (options: {next: (event: StreamEvent) => void;error: (error: Error) => void;}) => void | アシスタント応答を購読 |
メッセージ
MessageはアプリケーションユーザーとLLM間の単一のチャットメッセージです。各メッセージにはroleプロパティがあり、メッセージがユーザーからのものかアシスタントからのものかを示します。ユーザーとアシスタントのメッセージは1対1の関係があります。アシスタントメッセージには、アシスタント応答をトリガーしたユーザーメッセージのidを指すassociatedUserMessageIdプロパティが含まれています。
MessageタイプはSchema['myChat']['messageType']を通じてアクセス可能です。ここで'myChat'はデータスキーマ内の会話ルートの名前です。
| プロパティ | 型 | 説明 |
|---|---|---|
id | string | メッセージの一意の識別子 |
conversationId | string | このメッセージが属する会話のID |
associatedUserMessageId | string | undefined | アシスタントメッセージの場合、応答をトリガーしたユーザーメッセージのID |
content | MessageContent[] | メッセージの内容 |
role | 'user' | 'assistant' | メッセージがユーザーからのものかアシスタントからのものか |
createdAt | string | メッセージが作成された日時 |
リクエストレスポンスフロー
.create()で新しい会話を作成するか、.get()で既存の会話を取得します。.onStreamEvent()で会話のアシスタント応答を購読します。.sendMessage()で会話にメッセージを送信します。
import { generateClient } from 'aws-amplify/data';import { type Schema } from '../amplify/data/resource'
const client = generateClient<Schema>();
// 1. 会話を作成const { data: chat, errors } = await client.conversations.chat.create();
// 2. アシスタント応答を購読const subscription = chat.onStreamEvent({ next: (event) => { // アシスタント応答ストリームイベントを処理 console.log(event); }, error: (error) => { // エラーを処理 console.error(error); },});
// 3. 会話にメッセージを送信const { data: message, errors } = await chat.sendMessage('Hello, world!');会話の管理
会話を作成
会話ルートで.create()メソッドを呼び出して新しい会話を作成します。以下の例では、chatという名前の会話ルートを使用しています。
const { data: chat, errors } = await client.conversations.chat.create();
/**会話データの例{ id: '123e4567-e89b-12d3-a456-426614174000', createdAt: '2024-01-01T00:00:00.000Z', updatedAt: '2024-01-01T00:00:00.000Z',}*/.create()メソッドに引数としてnameとmetadataを渡すことで、会話に任意にnameとmetadataを付与することができます。会話のnameまたはmetadata値には一意性制約がありません。metadataを使用して、チャットを整理し、特定のトピックにグループ化することができます。
const { data: chat, errors } = await client.conversations.chat.create({ name: 'My conversation', metadata: { value: '1234567890', },});
/**会話データの例{ id: '123e4567-e89b-12d3-a456-426614174000', name: 'My conversation', metadata: { value: '1234567890', }, createdAt: '2024-01-01T00:00:00.000Z', updatedAt: '2024-01-01T00:00:00.000Z',}*/既存の会話を取得
会話ルートで.get()メソッドを呼び出して、会話のidを指定することで、既存の会話を取得できます。
const id = '123e4567-e89b-12d3-a456-426614174000';const { data: chat, errors } = await client.conversations.chat.get({ id });
/**会話データの例{ id: '123e4567-e89b-12d3-a456-426614174000', createdAt: '2024-01-01T00:00:00.000Z', updatedAt: '2024-01-01T00:00:00.000Z',}*/会話をリスト表示
.list()メソッドで、ユーザーのすべての会話をリスト表示できます。取得された会話はupdatedAtで降順にソートされます。これは、最近使用された会話が最初に返されることを意味します。
const { data: chat, errors } = await client.conversations.chat.list();
/**会話データの例{ items: [ { id: '123e4567-e89b-12d3-a456-426614174000', createdAt: '2024-01-01T00:00:00.000Z', updatedAt: '2024-01-01T00:00:00.000Z', }, ... ], nextToken: '...',}*/nextToken値を使用して会話をページネーションし、オプションでlimitを指定して返される会話の数を制限します。
const { data: chat, errors } = await client.conversations.chat.list({ limit: 10, nextToken: '...',});会話を更新
.update()メソッドで会話のnameとmetadataを更新できます。
これは、送信されたメッセージに基づいて会話名を更新したい場合や、後で任意のメタデータを添付したい場合に便利です。
const id = '123e4567-e89b-12d3-a456-426614174000';const { data: chat, errors } = await client.conversations.chat.update({ id, name: 'My updated conversation',});
/**会話データの例{ id: '123e4567-e89b-12d3-a456-426614174000', name: 'My updated conversation', createdAt: '2024-01-01T00:00:00.000Z', updatedAt: '2024-01-02T00:00:00.000Z',}*/会話を削除
const id = '123e4567-e89b-12d3-a456-426614174000';const { data: chat, errors } = await client.conversations.chat.delete({ id });会話インスタンスの使用
会話インスタンスを取得したら、インスタンスでメソッドを呼び出すことで対話できます。これらのメソッドは、会話とメッセージの種類セクションで説明しています。
メッセージを送信
会話インスタンスを取得したら、.sendMessage()メソッドを呼び出すことでAIアシスタントにメッセージを送信できます。最も単純な形式では、メッセージの内容をテキストとして渡すだけです。
const { data: message, errors } = await chat.sendMessage('Hello, world!');
/**メッセージデータの例{ id: '98765432-dcba-4321-9876-543210987654', conversationId: '123e4567-e89b-12d3-a456-426614174000', content: 'Hello, world!', role: 'user', createdAt: '2024-01-01T00:00:00.000Z',}*/.sendMessage()に渡すことができる他の引数があり、アプリケーションの必要に応じてメッセージをカスタマイズできます。
メッセージコンテンツのカスタマイズ
sendMessage()はcontentプロパティを持つオブジェクト型を受け入れ、AIアシスタントに異なるタイプのコンテンツを送信する柔軟な方法を提供します。
画像コンテンツ
imageを使用してAIアシスタントに画像を送信します。
サポートされている画像形式はpng、gif、jpeg、webpです。
const { data: message, errors } = await chat.sendMessage({ content: [ { image: { format: 'png', source: { bytes: new Uint8Array([1, 2, 3]), }, }, }, ],});単一のメッセージでtextとimageを混在させることができます。
const { data: message, errors } = await chat.sendMessage({ content: [ { text: 'describe the image in detail', }, { image: { format: 'png', source: { bytes: new Uint8Array([1, 2, 3]), }, }, }, ],});AIコンテキスト
aiContext引数を使用すると、任意にメッセージにデータを添付できます。これは、ユーザー情報やアプリケーションの現在の状態など、追加情報をユーザーメッセージでAIアシスタントに渡すのに便利です。
const { data: message, errors } = await chat.sendMessage({ content: [{ text: 'Hello, world!' }], aiContext: { user: { name: "Dan" } },});ツール構成
toolConfiguration引数を使用すると、クライアントツール構成をAIアシスタントにユーザーメッセージで渡すことができます。ツールの詳細については、ツールのコンセプトページとツールのガイドを参照してください。
jsonプロパティはツールの入力のJSON Schemaの定義です。AIアシスタントはこのスキーマを使用して、ツールに期待される入力を提供します。
const { data: message, errors } = await conversation.sendMessage({ content: [ { text: "I'd like to make a chocolate cake for my friend with a gluten intolerance. What ingredients do I need?", }, ], toolConfiguration: { tools: { generateRecipe: { description: "List ingredients needed for a recipe", inputSchema: { json: { type: "object", properties: { ingredients: { type: "array", items: { type: "string" }, }, }, }, }, }, }, },});AIアシスタントからの応答は、inputSchema定義に一致するJSONオブジェクトです。応答を処理する方法の詳細については、アシスタント応答を購読を参照してください。
アシスタント応答を購読
アシスタント応答は、生成されるにつれてクライアントにストリーミングされます。これにより、ユーザーはAIアシスタントからの完全な応答を待たずに進捗を確認し、応答の読み取りを開始することができる、より自然な会話フローが可能になります。アシスタント応答を購読するには、会話インスタンスで.onStreamEvent()メソッドを呼び出します。
const subscription = conversation.onStreamEvent({ next: (event) => { console.log(event); }, error: (error) => { console.error(error); },});
// 後で...subscription.unsubscribe();onStreamEvent()はnextとerrorという2つのコールバック関数を引数として受け取ります。nextコールバックは各アシスタント応答で呼び出されます。
errorコールバックはメッセージ処理中にエラーが発生した場合に呼び出されます。
nextコールバックはConversationStreamEventオブジェクトで呼び出されます。このタイプはSchema['myChat']['streamEventType']を通じてアクセス可能で、以下のタイプの共用体です:
ConversationStreamTextEvent
テキストがクライアントにストリーミングされるにつれて、nextコールバックはConversationStreamTextEventオブジェクトで呼び出されます。
| プロパティ | 型 | 説明 |
|---|---|---|
id | string | ストリームイベントの一意の識別子 |
conversationId | string | このイベントが属する会話のID |
associatedUserMessageId | string | この応答をトリガーしたユーザーメッセージのID |
contentBlockIndex | number | ストリーミングされているコンテンツブロックのインデックス |
contentBlockDeltaIndex | number | コンテンツブロック内のデルタのインデックス |
text | string | ストリーミングされているテキストコンテンツ |
ConversationStreamDoneAtIndexEvent
AIアシスタントがコンテンツブロックを完成させると、nextコールバックはConversationStreamDoneAtIndexEventオブジェクトで呼び出されます。
| プロパティ | 型 | 説明 |
|---|---|---|
id | string | ストリームイベントの一意の識別子 |
conversationId | string | このイベントが属する会話のID |
associatedUserMessageId | string | この応答をトリガーしたユーザーメッセージのID |
contentBlockIndex | number | 完了したコンテンツブロックのインデックス |
contentBlockDoneAtIndex | number | コンテンツブロックが完了するインデックス |
ConversationStreamTurnDoneEvent
AIアシスタントがターンを完了すると、nextコールバックはConversationStreamTurnDoneEventオブジェクトで呼び出されます。このイベントは、アシスタントがターンを完了し、次のユーザーメッセージを待っていることを示します。
| プロパティ | 型 | 説明 |
|---|---|---|
id | string | ストリームイベントの一意の識別子 |
conversationId | string | このイベントが属する会話のID |
associatedUserMessageId | string | この応答をトリガーしたユーザーメッセージのID |
contentBlockIndex | number | ターンの最後のコンテンツブロックのインデックス |
stopReason | string | アシスタントが応答の生成を停止した理由 |
ConversationStreamToolUseEvent
AIアシスタントがクライアントツールを使用すると、nextコールバックはConversationStreamToolUseEventオブジェクトで呼び出されます。ツール使用イベントはクラウドリソースに蓄積され、単一のイベントとしてクライアントに送信されます。
| プロパティ | 型 | 説明 |
|---|---|---|
id | string | ストリームイベントの一意の識別子 |
conversationId | string | このイベントが属する会話のID |
associatedUserMessageId | string | この応答をトリガーしたユーザーメッセージのID |
contentBlockIndex | number | ストリーミングされているコンテンツブロックのインデックス |
toolUse | ToolUseBlock | 関数呼び出し情報を含むツール使用ブロック |
会話のメッセージをリスト表示
会話インスタンスで.listMessages()メソッドを呼び出すことで、会話のすべてのメッセージを取得します。メッセージは自動的に永続化されるため、いつでも取得して会話履歴を表示できます。
const { data: messages, errors } = await conversation.listMessages();client.conversations.chat.list()メソッドと同様に、取得されたメッセージはページネーションされます。nextToken値を使用してメッセージをページネーションし、オプションでlimitを指定して返されるメッセージの数を制限します。
const { data: messages, errors } = await conversation.listMessages({ limit: 10, nextToken: '...',});