适用于 Amazon Bedrock 运行时的 AWS AppSync JavaScript 解析器和函数参考 - AWS AppSync GraphQL

适用于 Amazon Bedrock 运行时的 AWS AppSync JavaScript 解析器和函数参考

您可以在您的 AWS 账户中的 Amazon Bedrock 上使用 AWS AppSync 函数和解析器来调用模型。您可以在将请求有效载荷和模型调用函数响应返回给客户端之前对其进行调整。您可以使用 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 Guardrails 的更多信息,请参阅《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 }

以下示例使用了 converse 函数,并指定了一个跨区域推理配置文件(us.anthropic.claude-3-5-haiku-20241022-v1:0)。有关 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 来创建结构化响应。请注意,我们使用环境变量作为数据库架构引用,并配置了护栏来帮助防止攻击。

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 Guardrails 的更多信息,请参阅《Amazon Bedrock 用户指南》中的使用 Amazon Bedrock Guardrails 阻止模型中的有害内容

响应对象

上下文的结果属性(context.result)中包含来自 Amazon Bedrock 运行时调用的响应。响应的结构符合 Amazon Bedrock 的 API 规范。有关调用结果预期结构的更多信息,请参阅 Amazon Bedrock 用户指南

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

没有适用于响应对象的必填字段或形状限制。不过,由于 GraphQL 是强类型的,因此,解析的响应必须与预期的 GraphQL 类型匹配。

长时间运行的调用

目前,许多组织都使用 AWS AppSync 作为人工智能网关,用于构建由 Amazon Bedrock 上的基础模型提供支持的生成式人工智能应用程序。客户使用基于 WebSocket 的 AWS AppSync 订阅,从长时间运行的模型调用中获取渐进式更新。这使他们能够实施异步模式。

下图说明了如何实施此模式。图中包含以下步骤。

  1. 您的客户端启动订阅,该订阅会设置 WebSocket,然后向 AWS AppSync 发出请求来触发生成式人工智能调用。

  2. AWS AppSync 在事件模式下调用您的 AWS Lambda 函数并立即向客户端返回响应。

  3. Lambda 函数调用 Amazon Bedrock 上的模型。Lambda 函数可以使用同步 API(例如 InvokeModel)或流 API(例如 InvokeModelWithResponseStream)来获取渐进式更新。

  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; };