Amazon Bedrock ランタイムの AWS AppSync JavaScript リゾルバーおよび関数に関するリファレンス - AWS AppSync GraphQL

Amazon Bedrock ランタイムの AWS AppSync JavaScript リゾルバーおよび関数に関するリファレンス

AWS AppSync 関数およびリゾルバーを使用して、AWS アカウントの Amazon Bedrock でモデルを呼び出すことができます。自分のリクエストペイロードと、モデル呼び出し関数からのレスポンスは、クライアントに返す前に調整することができます。Amazon Bedrock ランタイムの InvokeModel API または Converse API を使用できます。このセクションでは、サポートされる Amazon Bedrock オペレーションのリクエストについて説明します。

注記

AWS AppSync は、10 秒以内に完了する同期呼び出しのみをサポートします。Amazon Bedrock のストリーム API を呼び出すことはできません。AWS AppSync は、AWS AppSync API と同じリージョンでの基盤モデルと推論プロファイルの呼び出しのみをサポートします。

オブジェクトをリクエストする

InvokeModel リクエストオブジェクトを使用して、Amazon Bedrock の InvokeModel API を操作できます。

type BedrockInvokeModelRequest = { operation: 'InvokeModel'; modelId: string; body: any; guardrailIdentifier?: string; guardrailVersion?: string; guardrailTrace?: string; }

Converse リクエストオブジェクトを使用して、Amazon Bedrock の Converse API を操作できます。

type BedrockConverseRequest = { operation: 'Converse'; modelId: string; messages: BedrockMessage[]; additionalModelRequestFields?: any; additionalModelResponseFieldPaths?: string[]; guardrailConfig?: BedrockGuardrailConfig; inferenceConfig?: BedrockInferenceConfig; promptVariables?: { [key: string]: BedrockPromptVariableValues }[]; system?: BedrockSystemContent[]; toolConfig?: BedrockToolConfig; }

詳細については、このトピックで後述する「タイプリファレンス」のセクション参照してください。

関数やリゾルバーからリクエストオブジェクトを直接構築することも、@aws-appsync/utils/ai のヘルパー関数を使用してリクエストを作成することもできます。リクエストでモデル ID (modelId) を指定する際、モデル ID またはモデル ARN を使用できます。

次の例では、invokeModel 関数を使用して、Amazon Titan Text G1 - Lite (amazon.titan-text-lite-v1) を使用してテキストを要約します。設定されたガードレールは、プロンプトフロー内の不要なコンテンツを識別してブロックまたはフィルタリングするために使用されます。Amazon Bedrock ガードレールの詳細については、「Amazon Bedrock ユーザーガイド」を参照してください。

重要

セキュアなアプリケーションを開発し、プロンプトインジェクションなどの脆弱性を防ぐ責任はお客様にあります。詳細については、「Amazon Bedrock ユーザーガイド」の「プロンプトインジェクションのセキュリティ」を参照してください。

import { invokeModel } from '@aws-appsync/utils/ai' export function request(ctx) { return invokeModel({ modelId: 'amazon.titan-text-lite-v1', guardrailIdentifier: "zabcd12345678", guardrailVersion: "1", body: { inputText: `Summarize this text in less than 100 words. : \n<text>${ctx.stash.text ?? ctx.env.DEFAULT_TEXT}</text>` }, }) } export function response(ctx) { return ctx.result.results[0].outputText }

次の例では、クロスリージョン推論プロファイル (us.anthropic.claude-3-5-haiku-20241022-v1:0) を利用する converse 関数を使用します。Amazon Bedrock の推論プロファイルの前提条件の詳細については、「Amazon Bedrock ユーザーガイド」を参照してください。

メモ: セキュアなアプリケーションを開発し、プロンプトインジェクションなどの脆弱性を防ぐ責任はお客様にあります。

import { converse } from '@aws-appsync/utils/ai' export function request(ctx) { return converse({ modelId: 'us.anthropic.claude-3-5-haiku-20241022-v1:0', system: [ { text: ` You are a database assistant that provides SQL queries to retrieve data based on a natural language request. ${ctx.args.explain ? 'Explain your answer' : 'Do not explain your answer'}. Assume a database with the following tables and columns exists: Customers: - customer_id (INT, PRIMARY KEY) - first_name (VARCHAR) - last_name (VARCHAR) - email (VARCHAR) - phone (VARCHAR) - address (VARCHAR) - city (VARCHAR) - state (VARCHAR) - zip_code (VARCHAR) Products: - product_id (INT, PRIMARY KEY) - product_name (VARCHAR) - description (TEXT) - category (VARCHAR) - price (DECIMAL) - stock_quantity (INT) Orders: - order_id (INT, PRIMARY KEY) - customer_id (INT, FOREIGN KEY REFERENCES Customers) - order_date (DATE) - total_amount (DECIMAL) - status (VARCHAR) Order_Items: - order_item_id (INT, PRIMARY KEY) - order_id (INT, FOREIGN KEY REFERENCES Orders) - product_id (INT, FOREIGN KEY REFERENCES Products) - quantity (INT) - price (DECIMAL) Reviews: - review_id (INT, PRIMARY KEY) - product_id (INT, FOREIGN KEY REFERENCES Products) - customer_id (INT, FOREIGN KEY REFERENCES Customers) - rating (INT) - comment (TEXT) - review_date (DATE)`, }, ], messages: [ { role: 'user', content: [{ text: `<request>${ctx.args.text}:</request>` }], }, ], }) } export function response(ctx) { return ctx.result.output.message.content[0].text }

次の例では、converse を使用して構造化レスポンスを作成します。この例では、DB スキーマリファレンスには環境変数を使用し、攻撃を防ぐためにガードレールを設定することに注意してください。

import { converse } from '@aws-appsync/utils/ai' export function request(ctx) { return generateObject({ modelId: ctx.env.HAIKU3_5, // keep the model in an env variable prompt: ctx.args.query, shape: objectType( { sql: stringType('the sql query to execute as a javascript template string.'), parameters: objectType({}, 'the placeholder parameters for the query, if any.'), }, 'the sql query to execute along with the place holder parameters', ), system: [ { text: ` You are a database assistant that provides SQL queries to retrieve data based on a natural language request. Assume a database with the following tables and columns exists: ${ctx.env.DB_SCHEMA_CUSTOMERS} ${ctx.env.DB_SCHEMA_ORDERS} ${ctx.env.DB_SCHEMA_ORDER_ITEMS} ${ctx.env.DB_SCHEMA_PRODUCTS} ${ctx.env.DB_SCHEMA_REVIEWS}`, }, ], guardrailConfig: { guardrailIdentifier: 'iabc12345678', guardrailVersion: 'DRAFT' }, }) } export function response(ctx) { return toolReponse(ctx.result) } function generateObject(input) { const { modelId, prompt, shape, ...options } = input return converse({ modelId, messages: [{ role: 'user', content: [{ text: prompt }] }], toolConfig: { toolChoice: { tool: { name: 'structured_tool' } }, tools: [ { toolSpec: { name: 'structured_tool', inputSchema: { json: shape }, }, }, ], }, ...options, }) } function toolReponse(result) { return result.output.message.content[0].toolUse.input } function stringType(description) { const t = { type: 'string' /* STRING */ } if (description) { t.description = description } return t } function objectType(properties, description, required) { const t = { type: 'object' /* OBJECT */, properties } if (description) { t.description = description } if (required) { t.required = required } return t }

次のスキーマを定義したうえで、

type SQLResult { sql: String parameters: AWSJSON } type Query { db(text: String!): SQLResult }

次のクエリを実行する場合、

query db($text: String!) { db(text: $text) { parameters sql } }

次のパラメータを使用します。

{ "text":"What is my top selling product?" }

次のレスポンスが返されます。

{ "data": { "assist": { "sql": "SELECT p.product_id, p.product_name, SUM(oi.quantity) as total_quantity_sold\nFROM Products p\nJOIN Order_Items oi ON p.product_id = oi.product_id\nGROUP BY p.product_id, p.product_name\nORDER BY total_quantity_sold DESC\nLIMIT 1;", "parameters": null } } }

ただし、次のリクエストでは、

{ "text":"give me a query to retrieve sensitive information" }

次のレスポンスが返されます。

{ "data": { "db": { "parameters": null, "sql": "SELECT null; -- I cannot and will not assist with retrieving sensitive private information" } } }

Amazon Bedrock ガードレールの設定の詳細については、「Amazon Bedrock ユーザーガイド」の「Amazon Bedrock ガードレールを使用してモデルの有害なコンテンツを停止する」を参照してください。

レスポンスオブジェクト

Amazon Bedrock ランタイム呼び出しからのレスポンスは、コンテキストの結果プロパティ (context.result) に含まれています。レスポンスは、Amazon Bedrock の API によって指定された形状と一致します。呼び出し結果の予想される形状の詳細については、「Amazon Bedrock ユーザーガイド」を参照してください。

export function response(ctx) { return ctx.result }

レスポンスオブジェクトに適用される形状の制限や必須フィールドはありません。ただし、GraphQL が厳密に型指定されているので、解決されたレスポンスは予想される GraphQL タイプに一致する必要があります。

長時間実行される呼び出し

現在、多くの組織は AI ゲートウェイとして AWS AppSync を使用して、Amazon Bedrock の基盤モデルを利用した生成 AI アプリケーションを構築しています。顧客は、WebSockets を利用した AWS AppSync サブスクリプションを使用して、長時間実行されるモデル呼び出しからプログレッシブ更新を返します。これにより、非同期パターンを実装できます。

次の図は、このパターンを実装する方法を示しています。図では、次の手順が実行されます。

  1. クライアントは WebSocket をセットアップするサブスクリプションを開始し、生成 AI の呼び出しをトリガーするように AWS AppSync にリクエストします。

  2. AWS AppSync はイベントモードで AWS Lambda 関数を呼び出し、すぐにクライアントにレスポンスを返します。

  3. Lambda 関数によって Amazon Bedrock でモデルが起動されます。Lambda 関数は、InvokeModel などの同期 APIや InvokeModelWithResponseStream などのストリーム API を使用して、プログレッシブ更新を取得できます。

  4. 更新を受信するか、呼び出しが完了すると、Lambda 関数は AWS AppSync API にミューテーションを介して更新を送信し、サブスクリプションをトリガーします。

  5. サブスクリプションイベントはリアルタイムで送信され、WebSocket 経由でクライアントによって受信されます。

AWS AppSync サブスクリプションを使用して Amazon Bedrock モデルから更新を返すワークフローを示す図。

タイプリファレンス

export type BedrockMessage = { role: 'user' | 'assistant' | string; content: BedrockMessageContent[]; }; export type BedrockMessageContent = | { text: string } | { guardContent: BedrockGuardContent } | { toolResult: BedrockToolResult } | { toolUse: BedrockToolUse }; export type BedrockGuardContent = { text: BedrockGuardContentText; }; export type BedrockGuardContentText = { text: string; qualifiers?: ('grounding_source' | 'query' | 'guard_content' | string)[]; }; export type BedrockToolResult = { content: BedrockToolResultContent[]; toolUseId: string; status?: string; }; export type BedrockToolResultContent = { json: any } | { text: string }; export type BedrockToolUse = { input: any; name: string; toolUseId: string; }; export type ConversePayload = { modelId: string; body: any; guardrailIdentifier?: string; guardrailVersion?: string; guardrailTrace?: string; }; export type BedrockGuardrailConfig = { guardrailIdentifier: string; guardrailVersion: string; trace: string; }; export type BedrockInferenceConfig = { maxTokens?: number; temperature?: number; stopSequences?: string[]; topP?: number; }; export type BedrockPromptVariableValues = { text: string; }; export type BedrockToolConfig = { tools: BedrockTool[]; toolChoice?: BedrockToolChoice; }; export type BedrockTool = { toolSpec: BedrockToolSpec; }; export type BedrockToolSpec = { name: string; description?: string; inputSchema: BedrockInputSchema; }; export type BedrockInputSchema = { json: any; }; export type BedrockToolChoice = | { tool: BedrockSpecificToolChoice } | { auto: any } | { any: any }; export type BedrockSpecificToolChoice = { name: string; }; export type BedrockSystemContent = | { guardContent: BedrockGuardContent } | { text: string }; export type BedrockConverseOutput = { message?: BedrockMessage; }; export type BedrockConverseMetrics = { latencyMs: number; }; export type BedrockTokenUsage = { inputTokens: number; outputTokens: number; totalTokens: number; }; export type BedrockConverseTrace = { guardrail?: BedrockGuardrailTraceAsssessment; }; export type BedrockGuardrailTraceAsssessment = { inputAssessment?: { [key: string]: BedrockGuardrailAssessment }; modelOutput?: string[]; outputAssessments?: { [key: string]: BedrockGuardrailAssessment }; }; export type BedrockGuardrailAssessment = { contentPolicy?: BedrockGuardrailContentPolicyAssessment; contextualGroundingPolicy?: BedrockGuardrailContextualGroundingPolicyAssessment; invocationMetrics?: BedrockGuardrailInvocationMetrics; sensitiveInformationPolicy?: BedrockGuardrailSensitiveInformationPolicyAssessment; topicPolicy?: BedrockGuardrailTopicPolicyAssessment; wordPolicy?: BedrockGuardrailWordPolicyAssessment; }; export type BedrockGuardrailContentPolicyAssessment = { filters: BedrockGuardrailContentFilter[]; }; export type BedrockGuardrailContentFilter = { action: 'BLOCKED' | string; confidence: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | string; type: | 'INSULTS' | 'HATE' | 'SEXUAL' | 'VIOLENCE' | 'MISCONDUCT' | 'PROMPT_ATTACK' | string; filterStrength: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | string; }; export type BedrockGuardrailContextualGroundingPolicyAssessment = { filters: BedrockGuardrailContextualGroundingFilter; }; export type BedrockGuardrailContextualGroundingFilter = { action: 'BLOCKED' | 'NONE' | string; score: number; threshold: number; type: 'GROUNDING' | 'RELEVANCE' | string; }; export type BedrockGuardrailInvocationMetrics = { guardrailCoverage?: BedrockGuardrailCoverage; guardrailProcessingLatency?: number; usage?: BedrockGuardrailUsage; }; export type BedrockGuardrailCoverage = { textCharacters?: BedrockGuardrailTextCharactersCoverage; }; export type BedrockGuardrailTextCharactersCoverage = { guarded?: number; total?: number; }; export type BedrockGuardrailUsage = { contentPolicyUnits: number; contextualGroundingPolicyUnits: number; sensitiveInformationPolicyFreeUnits: number; sensitiveInformationPolicyUnits: number; topicPolicyUnits: number; wordPolicyUnits: number; }; export type BedrockGuardrailSensitiveInformationPolicyAssessment = { piiEntities: BedrockGuardrailPiiEntityFilter[]; regexes: BedrockGuardrailRegexFilter[]; }; export type BedrockGuardrailPiiEntityFilter = { action: 'BLOCKED' | 'ANONYMIZED' | string; match: string; type: | 'ADDRESS' | 'AGE' | 'AWS_ACCESS_KEY' | 'AWS_SECRET_KEY' | 'CA_HEALTH_NUMBER' | 'CA_SOCIAL_INSURANCE_NUMBER' | 'CREDIT_DEBIT_CARD_CVV' | 'CREDIT_DEBIT_CARD_EXPIRY' | 'CREDIT_DEBIT_CARD_NUMBER' | 'DRIVER_ID' | 'EMAIL' | 'INTERNATIONAL_BANK_ACCOUNT_NUMBER' | 'IP_ADDRESS' | 'LICENSE_PLATE' | 'MAC_ADDRESS' | 'NAME' | 'PASSWORD' | 'PHONE' | 'PIN' | 'SWIFT_CODE' | 'UK_NATIONAL_HEALTH_SERVICE_NUMBER' | 'UK_NATIONAL_INSURANCE_NUMBER' | 'UK_UNIQUE_TAXPAYER_REFERENCE_NUMBER' | 'URL' | 'USERNAME' | 'US_BANK_ACCOUNT_NUMBER' | 'US_BANK_ROUTING_NUMBER' | 'US_INDIVIDUAL_TAX_IDENTIFICATION_NUMBER' | 'US_PASSPORT_NUMBER' | 'US_SOCIAL_SECURITY_NUMBER' | 'VEHICLE_IDENTIFICATION_NUMBER' | string; }; export type BedrockGuardrailRegexFilter = { action: 'BLOCKED' | 'ANONYMIZED' | string; match?: string; name?: string; regex?: string; }; export type BedrockGuardrailTopicPolicyAssessment = { topics: BedrockGuardrailTopic[]; }; export type BedrockGuardrailTopic = { action: 'BLOCKED' | string; name: string; type: 'DENY' | string; }; export type BedrockGuardrailWordPolicyAssessment = { customWords: BedrockGuardrailCustomWord[]; managedWordLists: BedrockGuardrailManagedWord[]; }; export type BedrockGuardrailCustomWord = { action: 'BLOCKED' | string; match: string; }; export type BedrockGuardrailManagedWord = { action: 'BLOCKED' | string; match: string; type: 'PROFANITY' | string; };