Referencia a la función y solucionador de JavaScript de AWS AppSync para Amazon Bedrock Runtime - AWS AppSync GraphQL

Referencia a la función y solucionador de JavaScript de AWS AppSync para Amazon Bedrock Runtime

Puede usar las funciones y solucionadores de AWS AppSync para invocar modelos de Amazon Bedrock en su Cuenta de AWS. Puede configurar las cargas útiles de sus solicitudes y la respuesta de sus invocaciones de modelo antes de devolverlas a los clientes. Puede utilizar la API de InvokeModel o la API de Converse de Amazon Bedrock Runtine. En esta sección se describen las solicitudes para las operaciones de Amazon Bedrock admitidas.

nota

AWS AppSync solo admite invocaciones sincrónicas que se completen en 10 segundos. No es posible llamar a las API de transmisión de Amazon Bedrock. AWS AppSync solo admite la invocación de modelos fundacionales y perfiles de inferencia en la misma región que la API de AWS AppSync.

Objeto de solicitud

El objeto de solicitud de InvokeModel le permite interactuar con la API de InvokeModel de Amazon Bedrock.

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

El objeto de solicitud de Converse le permite interactuar con la API de Converse de Amazon Bedrock.

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

Para obtener más información, consulte la sección Referencia de tipos más adelante en este tema.

A partir de las funciones y solucionadores, puede crear los objetos de solicitud directamente o bien utilizar las funciones auxiliares de @aws-appsync/utils/ai para crear la solicitud. Al especificar el ID del modelo (modelId) en las solicitudes, puede usar el ID del modelo o el ARN del modelo.

En el siguiente ejemplo, se utiliza la función de invokeModel para resumir texto con Amazon Titan Text G1 - Lite (amazon.titan-text-lite-v1). Se utiliza una barrera de protección configurada para identificar y bloquear o filtrar el contenido no deseado en el flujo de peticiones. Obtenga más información sobre las barreras de protección de Amazon Bedrock en la Guía del usuario de Amazon Bedrock.

importante

Usted es responsable del desarrollo seguro de las aplicaciones y de la prevención de vulnerabilidades, como las inyecciones de peticiones. Para obtener más información, consulte Seguridad de la inyección de peticiones en la Guía del usuario de 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 }

En el siguiente ejemplo se usa la función converse con un perfil de inferencia entre regiones (us.anthropic.claude-3-5-haiku-20241022-v 1:0). Obtenga más información sobre los requisitos previos de Amazon Bedrock para los perfiles de inferencia en la Guía del usuario de Amazon Bedrock

Recordatorio: Usted es responsable del desarrollo seguro de las aplicaciones y de la prevención de vulnerabilidades, como las inyecciones de peticiones.

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 }

En el siguiente ejemplo se utiliza converse para crear una respuesta estructurada. Tenga en cuenta que utilizamos variables de entorno como referencia para nuestro esquema de base de datos y configuramos una barrera de protección para ayudar a prevenir los ataques.

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 }

Dado el esquema:

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

y la consulta:

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

Con los siguientes parámetros:

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

Se devuelve la siguiente respuesta:

{ "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 } } }

Sin embargo, con esta solicitud:

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

Se devuelve la siguiente respuesta:

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

Para obtener más información sobre la configuración de barreras de protección de Amazon Bedrock, consulte Detención del contenido dañino en los modelos que utilizan barreras de protección de Amazon Bedrock en la Guía del usuario de Amazon Bedrock.

Objeto de respuesta

La respuesta de la invocación en tiempo de ejecución de Amazon Bedrock se incluye en la propiedad de resultado del contexto (context.result). La respuesta coincide con la forma especificada por las API de Amazon Bedrock. Consulte la Guía del usuario de Amazon Bedrock para obtener más información sobre la forma esperada de los resultados de la invocación.

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

No hay campos obligatorios ni restricciones de forma aplicables al objeto de respuesta. Sin embargo, dado que los tipos de GraphQL son estrictos, la respuesta resuelta debe coincidir con el tipo de GraphQL previsto.

Invocaciones de larga duración

Actualmente, muchas organizaciones utilizan AWS AppSync como puerta de enlace de IA para crear aplicaciones de IA generativas que se basan en modelos fundacionales en Amazon Bedrock. Los clientes utilizan las suscripciones de AWS AppSync, basadas en WebSockets, para devolver actualizaciones progresivas a partir de invocaciones de modelos de larga duración. Esto les permite implementar patrones asíncronos.

En el siguiente diagrama se muestra cómo se puede implementar este patrón. En el diagrama se muestran los siguientes pasos:

  1. Su cliente inicia una suscripción, que configura un WebSocket, y hace una solicitud a AWS AppSync para que active una invocación de IA generativa.

  2. AWS AppSync llama a la función de AWS Lambda en modo Evento e inmediatamente devuelve una respuesta al cliente.

  3. La función de Lambda invoca el modelo en Amazon Bedrock. La función de Lambda puede usar una API sincrónica, por ejemplo InvokeModel, o una API de transmisión, por ejemplo InvokeModelWithResponseStream, para obtener actualizaciones progresivas.

  4. A medida que se reciben las actualizaciones o cuando se completa la invocación, la función de Lambda envía actualizaciones mediante mutaciones a la API de AWS AppSync, lo que activa las suscripciones.

  5. Los eventos de suscripción se envían en tiempo real y su cliente los recibe a través del WebSocket.

Un diagrama que muestra el flujo de trabajo para usar una suscripción de AWS AppSync para devolver actualizaciones de un modelo de Amazon Bedrock.

Referencia de tipos

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