AWS Machine LearningPublicación de la fuente

Cree recuperación agéntica sobre una base de conocimiento administrada de Amazon Bedrock con CDK

Esta publicación crea recuperación agéntica empresarial sobre una base de conocimiento administrada de Amazon Bedrock con el AWS Cloud Development Kit (AWS CDK). Para entender por qué vale la pena construirla, ayuda comenzar por donde falla la Generación Aumentada por Recuperación (RAG) ordinaria.

Esta publicación crea recuperación agéntica empresarial sobre una base de conocimiento administrada de Amazon Bedrock con el AWS Cloud Development Kit (AWS CDK). Para entender por qué vale la pena construirla, ayuda comenzar por donde falla la Generación Aumentada por Recuperación (RAG) ordinaria. La mayoría de los sistemas RAG empiezan igual: incorporan la pregunta, obtienen los fragmentos más cercanos de un índice, los entregan a un modelo y devuelven la respuesta. Una recuperación, una generación. Para una gran clase de preguntas ese es el diseño correcto, y no hay razón para construir algo más complicado.

Falla de una manera reconocible. Haga una pregunta cuya respuesta abarque dos corpus, y una sola recuperación devuelve la mitad de lo que el modelo necesita, lo cual es peor que no devolver nada, porque la respuesta llega fluida e incompleta. Haga una pregunta donde la fuente correcta depende de la pregunta, y un solo índice no tiene mecanismo para elegirla. Haga una pregunta que requiera una segunda mirada al corpus después de ver el primer resultado, y no hay lugar donde esa segunda mirada pueda ocurrir.

La recuperación agéntica empresarial resuelve los tres problemas poniendo un agente de razonamiento en el bucle. El agente decide si recuperar, qué base de conocimiento consultar y si volver por más antes de componer una respuesta. Esta es la dirección en la que Amazon Bedrock Knowledge Bases ha evolucionado. Con el lanzamiento de la base de conocimiento administrada (Managed Knowledge Base), la recuperación ya no es una sola llamada de incorporación y obtención. Se ha convertido en una capacidad agéntica: planificación multi-turno, recuperación basada en herramientas y respuestas fundamentadas y con citas. La API AgenticRetrieveStream ofrece esto como una característica de servicio de primera clase en lugar de algo que usted ensambla. Eso funciona, y también introduce un problema operativo genuinamente más difícil. Un pipeline de una sola pasada es una función que puede razonar leyéndola. Un agente que razona y recupera en un bucle toma un camino diferente en cada pregunta. Por defecto, no puede ver ni el camino que siguió ni si la respuesta que produjo fue buena. La observabilidad deja de ser algo opcional y se convierte en la única forma de saber que el sistema funciona.

En agosto de 2024, Cree una solución RAG de extremo a extremo usando Knowledge Bases for Amazon Bedrock y el AWS CDK desplegó el diseño de una sola pasada como una aplicación de CDK: un corpus en Amazon Simple Storage Service (Amazon S3) , una colección e índice de Amazon OpenSearch Serverless , una base de conocimiento y una fuente de datos, aprovisionados como pilas de CDK cuyo orden usted secuenciaba a mano. Tres cosas han cambiado desde su publicación.

  1. Amazon Bedrock ahora ofrece una base de conocimiento administrada (Type: MANAGED), que se encarga de la ingesta, el almacenamiento, la indexación y la recuperación propiamente dichas. La colección e índice de OpenSearch Serverless que esa publicación aprovisiona ya no es algo que necesite crear, escalar o pagar con OpenSearch Compute Units (OCUs).
  2. Amazon Bedrock AgentCore proporciona la mitad agéntica, un Gateway que expone cada base de conocimiento como una herramienta de Model Context Protocol (MCP), un Runtime que aloja el agente de razonamiento y AgenticRetrieveStream, que reordena internamente y devuelve una respuesta sintetizada y con citas. La recuperación agéntica está disponible solo en la base de conocimiento administrada (Managed Knowledge Base).
  3. La historia de observabilidad y evaluación ahora es algo que puede aprovisionar, no algo que se añade después. Esta solución incluye dos Amazon CloudWatch dashboards que abarcan siete capas de telemetría, además de dos formas de evaluación, bajo demanda y continua, desde el mismo despliegue.

Esta publicación construye ese sistema: un agente que enruta entre dos bases de conocimiento, recupera a través del Gateway y devuelve una respuesta fundamentada y con citas, con cada capa de su comportamiento instrumentada, como una única AWS CDK aplicación en Python. Un solo comando despliega todo, y CDK deduce el orden.

Si leyó la entrada de 2024, la ruta desde un bucket de Amazon S3 hasta la base de conocimiento le resultará familiar, y todo lo que viene después es nuevo: el almacén vectorial desapareció, la recuperación es agéntica y aproximadamente la mitad de lo que la aplicación aprovisiona existe para decirle qué hizo el agente. Si no la leyó, esta entrada se sostiene por sí misma.

Los servicios involucrados y el recorrido de una pregunta a través de ellos: el agente decide si recuperar y a qué base de conocimiento consultar, el Gateway expone cada base de conocimiento como una herramienta que puede invocar, las Managed Knowledge Bases buscan y citan, y el bucle se repite tantas veces como la pregunta necesite. Todo lo que el agente hace en el camino queda registrado en Amazon CloudWatch.

Figura 1: Los servicios involucrados y el recorrido de una sola pregunta a través de ellos

Antecedentes

Antes del recorrido, ayuda establecer tres cosas: qué hace que la recuperación sea agéntica, por qué la Managed Knowledge Base es la base adecuada para ella, y por qué la observabilidad y la evaluación pertenecen al diseño en lugar de añadirse más tarde.

De RAG a la recuperación agéntica empresarial

La Retrieval Augmented Generation (RAG) clásica realiza una recuperación y una generación. La recuperación agéntica empresarial pone un agente de razonamiento en el bucle: decide si y qué recuperar, puede recuperar varias veces para refinar, elige qué base de conocimiento es relevante (enrutamiento semántico), y solo entonces compone una respuesta fundamentada con citas. Con la Managed Knowledge Base, esta es una capacidad de servicio de primera clase; la API AgenticRetrieveStream realiza la planificación de múltiples turnos, ejecuta la recuperación y devuelve una respuesta con citas, en lugar de una capa de orquestación que usted construye y mantiene sobre una búsqueda vectorial básica. Eso produce mejores respuestas en preguntas complejas, pero también produce un sistema más complejo de operar, que es exactamente por lo que la observabilidad y la evaluación están integradas desde el principio.

Comparación entre gestionado y bases de conocimiento de bricolaje

Amazon Bedrock ahora ofrece una Managed Knowledge Base (Tipo: MANAGED): Amazon Bedrock gestiona la ingesta, el almacenamiento, la indexación y la recuperación por usted, incluyendo embedding y reranking con modelos gestionados por el servicio de forma predeterminada, por lo que no hay una base de datos vectorial que aprovisionar, escalar o parchear. Esto difiere de una base de conocimiento gestionada por el cliente (DIY), donde usted elige y opera el almacén de vectores (por ejemplo, Amazon OpenSearch Serverless) usted mismo.

Dos diferencias importan más para esta solución:

Capacidad Amazon Bedrock gestionado Gestionada por el cliente (DIY)
Recuperación agéntica (AgenticRetrieveStream) ✅ Compatible ❌ No compatible
Integración con AgentCore Gateway ✅ Compatible ❌ No compatible
Almacén de datos Escalado automático, totalmente gestionado por Amazon Bedrock Usted lo aprovisiona, escala y mantiene
Embedding + reranking Modelos gestionados integrados, sin coste adicional Usted los configura
Infraestructura que gestionar Ninguna Vector DB y más

Dado que la recuperación agéntica y el conector de AgentCore Gateway están disponibles solo en la base de conocimiento gestionada, esta es la base natural para la recuperación agéntica empresarial. También significa que Amazon Bedrock gestiona el almacenamiento y la indexación por usted, por lo que en este diseño no hay ninguna colección de OpenSearch Serverless ni capacidad de OCU que aprovisionar. La opción gestionada por el cliente sigue siendo la elección correcta cuando desea seleccionar y operar su propio almacén de vectores, por ejemplo para reutilizar una colección existente de OpenSearch Serverless o para cumplir requisitos específicos de residencia de datos, ajuste o cumplimiento. Para la recuperación agéntica empresarial, la base de conocimiento gestionada es lo que hace posible esta capacidad.

Por qué observabilidad y evaluación

Un sistema agéntico que devuelve una respuesta no es suficiente para producción. Necesita ver cómo se comporta (latencia, volumen de llamadas, uso de tokens), qué tan buenas son la recuperación y las respuestas, y necesita esas señales de forma continua. Esta solución incluye dos paneles de CloudWatch que abarcan siete capas de telemetría, además de dos formas de evaluación (bajo demanda y continua), todo aprovisionado por la misma aplicación de CDK. Las capas de grounding, citas y evaluación también respaldan el uso responsable. Las respuestas citadas se remontan a sus pasajes de origen para que las respuestas permanezcan auditables, y las puntuaciones de fidelidad y corrección le permiten detectar respuestas que se alejan de sus fuentes en lugar de descubrirlo en producción.

Por qué CDK para esta solución en particular

Cualquier herramienta de infraestructura como código puede crear estos recursos. CDK se justifica aquí por una razón específica de esta arquitectura: las cuatro pilas están densamente interreferenciadas. El Gateway necesita ambos identificadores de base de conocimiento. El agente necesita la URL y el ARN del Gateway. Los paneles necesitan los identificadores de la KB, el ARN del Gateway, y el identificador del runtime del agente: siete valores que cruzan los límites de las pilas, cada uno una dimensión en una métrica o un objetivo en un conector.

Escrito como plantillas en bruto, es decir, un conjunto de exportaciones de stacks y búsquedas entre stacks mantenidas a mano en coherencia, más un script que despliega en el orden correcto y encadena los outputs hacia adelante, y ambos se desincronizan en el momento en que se renombra cualquier cosa. En CDK pasas el construct, y la exportación y la arista de dependencia se derivan de ese único acto de pasarlo. La solución de 2024 tenía tres stacks y una cadena de dependencias mayormente lineal. Con cuatro stacks y siete valores cruzando entre ellos, la diferencia deja de ser estilística.

Descripción general de la solución

Esta es la ruta que sigue una sola pregunta a través del sistema, de extremo a extremo. Vale la pena mirarla con calma, porque el resto del post la recorre de izquierda a derecha.

El siguiente diagrama traza el flujo de trabajo de recuperación agéntica de extremo a extremo. La pregunta de un usuario entra al agente en el AgentCore Runtime, que la enruta a través del AgentCore Gateway hacia una de las dos herramientas AgenticRetrieveStream, una por base de conocimiento administrada, financiera y meteorológica, cada una ingestada desde Amazon S3. La herramienta seleccionada devuelve una respuesta fundamentada y con citas, y cada paso se transmite a Amazon CloudWatch y AWS X-Ray. Las insignias numeradas se corresponden con el siguiente recorrido.

Figura 2: Flujo de trabajo de recuperación agéntica de extremo a extremo para una sola pregunta

Los pasos numerados del diagrama se corresponden con el flujo de trabajo, que es el siguiente.

Paso 0 — único, en el despliegue. Antes de que se haga cualquier pregunta, cada corpus en Amazon S3 se ingesta en su propia Managed Knowledge Base: Amazon Bedrock lo analiza, lo divide en fragmentos, genera embeddings y lo indexa automáticamente. Esto ocurre una sola vez cuando se despliegan los stacks, no forma parte de la ruta por pregunta, por lo que se dibuja como una flecha discontinua y se marca como paso 0. Después, cada pregunta sigue los pasos 1–6:

  1. Un usuario envía una pregunta al agente alojado en el Amazon Bedrock AgentCore Runtime. El Runtime instrumenta automáticamente todo el bucle de razonar-y-actuar con spans de OpenTelemetry (OTEL), por lo que el sistema es observable desde la primera llamada.
  2. El modelo de razonamiento del agente planifica y enruta entre las bases de conocimiento. Como cada base de conocimiento se expone como su propia herramienta de recuperación, el agente selecciona la herramienta cuyo tema coincide con la pregunta, financiera o meteorológica, en lugar de buscar en un índice mezclado.
  3. La llamada a la herramienta seleccionada es intermediada por el AgentCore Gateway sobre MCP, autorizada por el rol de tarea IAM del agente y firmada con SigV4, que invoca la API AgenticRetrieveStream de esa base de conocimiento en la Managed Knowledge Base.
  4. AgenticRetrieveStream realiza el trabajo dentro de la base de conocimiento: descompone la pregunta en subconsultas, recupera iterativamente del almacén de datos que administra Amazon Bedrock (ingestado de los corpora en Amazon S3) y sintetiza una respuesta fundamentada y con citas que se transmite de vuelta a través del Gateway.
  5. El agente comprueba si el contexto devuelto es suficiente. Si no lo es, itera, enrutando y recuperando de nuevo, antes de componer su respuesta final. Si lo es, devuelve la respuesta con citas al usuario.
  6. Durante todo el proceso, el Runtime emite spans, recuentos de tokens y métricas a Amazon CloudWatch y AWS X-Ray, poblando las siete capas de observabilidad y alimentando tanto las puntuaciones de evaluación bajo demanda como continuas.

Internamente, ese flujo de trabajo es una sola app de CDK, app.py, que declara cuatro stacks. Tú no eliges el orden, CDK lo deriva de las referencias a constructs que pasas:

kb_stack = KnowledgeBasesStack(app, f"{project}-kb", env=env)

gateway_stack = AgenticGatewayStack(
    app, f"{project}-gateway", env=env,
    financial_kb=kb_stack.financial_kb,  # ← the reference creates the dependency
    weather_kb=kb_stack.weather_kb,
)

agent_stack = AgentRuntimeStack(
    app, f"{project}-agent", env=env,
    gateway=gateway_stack.gateway,
)

DashboardsStack(
    app, f"{project}-dashboards", env=env,
    financial_kb=kb_stack.financial_kb,
    weather_kb=kb_stack.weather_kb,
    gateway=gateway_stack.gateway,
    agent_runtime=agent_stack.agent_runtime,
)

Ese es todo el cableado. Esas cuatro llamadas al constructor son lo que reemplaza la contabilidad de export/import y el script de despliegue.

# Stack Lo que crea Nota
1 -kb Bucket de S3, carga de corpora, dos KBs Type: MANAGED, fuentes de datos, IAM, ingesta Las KBs llegan a ACTIVE, corpora ingestados
2 -gateway Gateway (AWS_IAM / MCP), destinos AgenticRetrieveStream por KB no se necesita Cognito
3 -agent ECR, CodeBuild, agente Strands instrumentado en Runtime, logs/trazas vendidos, evaluación en línea ~8–10 min (construcción de la imagen)
4 -dashboards dashboards de agentic-observability y kb-observability vacíos hasta que generes tráfico

El agente ejecuta un ciclo de razonar-y-actuar: piensa (una llamada a un modelo de lenguaje de gran escala (LLM)), decide qué herramienta del KB llamar, lee lo que regresó a través del Gateway y, a menudo, recupera de nuevo antes de componer su respuesta final con citas. Cada paso es auto-instrumentado por el Runtime, de modo que las siete capas de observabilidad se llenan con tráfico real.

Las siete capas. L1 métricas nativas del KB, L2 ingesta, L3 calidad de recuperación agéntica, L4 métricas de Gateway/MCP, L5 árbol de spans OTEL, L6 uso de tokens y L7 puntajes de evaluación. Las capas 1, 4 y 5 se emiten automáticamente. Las capas 3, 6 y 7 se publican como métricas personalizadas por el notebook del driver.

Todo lo ajustable se encuentra en un solo archivo, config.py:

Opción Significado Predeterminado
EnvSettings.PROJECT_NAME Prefijo de nombre para cada stack y recurso bmkb-obs-cdk
EnvSettings.ACCOUNT_REGION Región de AWS donde desplegar us-west-2 (o la de tu perfil)
KbConfig.EMBEDDING_MODEL_TYPE MANAGED (incluido) o CUSTOM (trae tu propio ARN) MANAGED
AgentConfig.MODEL_ID El modelo de razonamiento del agente, el gasto de la Layer 6 Claude Haiku 4.5
EvalConfig.SAMPLING_PERCENTAGE Tasa de muestreo de la evaluación en línea, ve el aviso 100

Cambiar PROJECT_NAME te da una copia con nombre independiente de toda la solución, de modo que dos despliegues pueden coexistir en una misma cuenta. El notebook del controlador lee la misma constante, por lo que sigue el cambio de nombre automáticamente; no hay nombres de stack que mantener sincronizados a mano.

Describe el conjunto de datos

La solución incluye dos pequeños corpus, incluidos en el repositorio bajo data/:

  • Financiero — Un 10-K sintético de Octank Financial (octank_financial_10K.pdf, ~198 KB).
  • Meteorológico — Un informe real, disponible públicamente del Servicio de Investigación del Congreso de EE. UU. sobre tornados (IF12695, tornadoes_report.pdf, ~560 KB).

⚠️ Sobre los datos: El corpus financiero es sintético. Octank es una empresa ficticia y el 10-K son datos de muestra generados por un modelo (con licencia CC0). Esno datos financieros reales. El corpus meteorológico es una obra del Gobierno de los Estados Unidos de dominio público y es un informe del Congressional Research Service, disponible públicamente en sgp.fas.org/crs/misc/IF12695.pdf (las obras del Gobierno de los EE. UU. no están sujetas a derechos de autor). Para usar sus propios datos, coloque archivos bajo data/ y ajuste los prefijos en config.py, no se requiere ningún otro cambio.

Los dos corpora son intencionalmente distintos, de modo que el agente debe dirigir cada pregunta a la base de conocimiento correcta: la historia del enrutamiento semántico. Como estas son Managed Knowledge Bases, no configuramos el chunking, los embeddings ni un índice: durante la ingesta, Amazon Bedrock analiza cada PDF, lo divide en fragmentos, lo convierte en embeddings con su modelo administrado y lo indexa automáticamente.

Usamos dos bases de conocimiento separadas, cada una expuesta a través del Gateway como su propia herramienta de recuperación, en lugar de una sola base de conocimiento que contenga ambos corpora, y esa elección es deliberada. Dar al agente dos herramientas con nombre hace que el enrutamiento sea un acto explícito de razonamiento que se puede observar: el árbol de spans muestra qué herramienta eligió para una pregunta dada, y las métricas de calidad de recuperación en la Layer 3 permanecen separables por base de conocimiento, de modo que la precisión financiera y meteorológica nunca se difuminan en un solo número. Una sola herramienta que abarque ambos corpora colapsaría esa distinción: la decisión de enrutamiento se movería dentro del ranking de un único índice, fuera de la vista, y cada señal de calidad sería un promedio entre dos dominios no relacionados. Mantener los corpora y sus herramientas separados es lo que hace legible el comportamiento del agente, que es el objetivo principal del ejercicio.

En CDK, llevar los corpora a S3 es un BucketDeployment:

s3deploy.BucketDeployment(
    self, "FinancialCorpus",
    sources=[s3deploy.Source.asset(str(ROOT / "data" / "financial"))],
    destination_bucket=self.source_bucket,
    destination_key_prefix=KbConfig.FINANCIAL_PREFIX,
)

BucketDeployment vale la pena conocerlo precisamente porque la alternativa es tan tentadora: sin él, el recurso personalizado que activa la ingesta tiende a desarrollar un paso de carga, y ahora un recurso tendría dos trabajos no relacionados. Aquí solo tiene que ingest.

La ingesta administrada escanea, divide, convierte en embeddings e indexa cada documento automáticamente: un documento indexado por base de conocimiento, cero fallos.

Figura 3: Resultados de la ingesta administrada, un documento indexado por base de conocimiento con cero fallos

Despliegue de la solución

Esta sección explica cómo desplegar toda la solución con un solo comando. Una vez cumplidos los requisitos previos, cdk deploy --all aprovisiona las cuatro stacks en el orden de dependencias derivado de CDK y conecta automáticamente todos los valores entre stacks.

Requisitos previos

  • Una cuenta de AWS con permisos para Amazon Bedrock, AgentCore (Runtime + Gateway), AWS Identity and Access Management (IAM), CloudWatch, AWS X-Ray, Amazon Elastic Container Registry (Amazon ECR), AWS CodeBuild, Amazon S3, AWS Lambday AWS CloudFormation.
  • El modelo del agente disponible en la cuenta (predeterminado us.anthropic.claude-haiku-4-5-20251001-v1:0).
  • CloudWatch Transaction Search habilitado, para que los spans de OTEL lleguen a aws/spans para las Capas 5–7.
  • Node.js 18+ y la CLI de CDK (npm install -g aws-cdk), además de Python 3.13+.
  • La cuenta y la región preparadas (bootstrapped) para CDK (cdk bootstrap), una vez por cuenta/región.
  • No se necesita Docker local: la imagen del agente se compila con CodeBuild (ARM64).

Un solo comando

Para desplegar la solución, clone el repositorio, cree un entorno virtual, instale las dependencias y ejecute cdk deploy --all. Ejecute los siguientes comandos desde su terminal:

git clone https://github.com/aws-samples/amazon-bedrock-samples.git
cd rag/managed-knowledge-bases/07-IaaC/managed-kb-observability-cdk/
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cdk bootstrap  # once per account/region
cdk deploy --all

Los dos primeros comandos clonan el ejemplo y se mueven al directorio del proyecto. Los dos siguientes crean y activan un entorno virtual de Python e instalan las dependencias de la aplicación CDK. cdk bootstrap prepara la cuenta y la región para CDK (solo lo necesita una vez por cuenta/región), y cdk deploy --all aprovisiona las cuatro pilas.

La cuenta y la región provienen de su perfil de AWS (CDK_DEFAULT_ACCOUNT / CDK_DEFAULT_REGION), por lo que la aplicación se despliega sin necesidad de ediciones.

Disponibilidad por región: la base de conocimiento administrada, la recuperación agéntica (AgenticRetrieveStream) y Amazon Bedrock AgentCore (Runtime y Gateway) no están disponibles en todas las regiones de AWS. Antes de desplegar, confirme que todas estas funcionalidades se ofrecen en su región de destino y configure ACCOUNT_REGION en config.py en consecuencia. El valor predeterminado es us-west-2. Para consultar la disponibilidad actual, vea la documentación de Amazon Bedrock y Amazon Bedrock AgentCore y la AWS Regional Services List.

No hay script de despliegue en esta versión, y ese es justo el punto: cdk deploy --all recorre el grafo de dependencias que derivó de app.py, despliega las cuatro pilas en orden y pasa automáticamente cada valor entre pilas. La terminal informa de cada pila a medida que se completa, bmkb-obs-cdk-kb [1/4] (el PROJECT_NAME predeterminado), luego gateway [2/4], luego agent [3/4], luego dashboards [4/4], y ese orden se deriva, no se declara: surge de las referencias de construct entre las pilas, de modo que añadir una quinta pila que consuma una salida existente reordena el despliegue por sí solo.

La pila -agent construye el contenedor del agente con CodeBuild, así que reserva entre 8 y 10 minutos para esa etapa. Las otras tres son rápidas. Cada pila imprime sus salidas al completarse, que es donde obtienes los ids de las bases de conocimiento, la URL del Gateway, el ARN del runtime y ambas URLs de los dashboards. Cuando el despliegue termina, las cuatro pilas están completas. La siguiente captura de pantalla muestra la consola de AWS CloudFormation tras un cdk deploy --all.

Figura 4: consola de AWS CloudFormation tras un despliegue exitoso, con las cuatro pilas en CREATE_COMPLETE

En la consola, las cuatro pilas, kb, gateway, agent y dashboards, muestran CREATE_COMPLETE, cada una con su posición [n/4] en el orden de dependencias derivado que se muestra en su descripción.

Una nota sobre los recursos de larga ejecución

Dos cosas en esta solución toman mucho más tiempo de lo que permite el límite de 15 minutos de una función de AWS Lambda para un sondeo ingenuo: la sincronización de ingesta de la KB y la construcción de la imagen con CodeBuild. El framework de proveedores de AWS CDK lo gestiona con una on_event / is_complete división, en la que un controlador inicia el trabajo y un segundo se consulta hasta que informa de que ha terminado.

cr.Provider(
    self, "IngestSyncProvider",
    on_event_handler=on_event,        # StartIngestionJob, return the job id
    is_complete_handler=is_complete,  # GetIngestionJob, report IsComplete
    query_interval=Duration.seconds(30),
    total_timeout=Duration.minutes(30),
)

Nada se bloquea, el protocolo de respuesta de vuelta a CloudFormation es propiedad del framework en lugar de escribirse a mano en cada controlador, y el presupuesto de 30 minutos es una propiedad en lugar de algo que haya que ingeniar para sortear.

Lanzamiento y prueba

Abre notebooks/01-drive-and-observe.ipynb y ejecútalo de principio a fin (pip install -r requirements-notebook.txt primero). Lee las salidas de las pilas y luego envía prompts específicos por tema al agente desplegado, una sesión por KB, para que puedas ver tanto las respuestas como el enrutamiento semántico en un solo lugar: las preguntas financieras se responden a partir del 10-K de Octank y las preguntas meteorológicas a partir del informe de tornados, cada una enrutada automáticamente a la herramienta AgenticRetrieveStream correspondiente.

El notebook descubre todo a partir de las salidas de las pilas, así que no hay nada que pegar a mano:

# Stack names are derived from the same PROJECT_NAME the CDK app uses, so renaming the
# project in config.py cannot leave this notebook pointing at stale stacks.
from config import EnvSettings

PROJECT = EnvSettings.PROJECT_NAME
STACKS = {suffix: f'{PROJECT}-{suffix}'
          for suffix in ('kb', 'gateway', 'agent', 'dashboards')}

def outputs(stack_name):
    s = cfn.describe_stacks(StackName=stack_name)['Stacks'][0]
    return {o['OutputKey']: o['OutputValue'] for o in s.get('Outputs', [])}

El notebook importa el mismo config.py que la aplicación, de modo que ambos nunca pueden discrepar sobre cómo se llaman las pilas.

El driver envía prompts por KB a través del agente desplegado. Las preguntas financieras se enrutan a la KB financiera y las meteorológicas a la KB meteorológica, cada una con una respuesta fundamentada y con citas.

Figura 5: prompts por KB enrutados a la base de conocimiento correspondiente, cada uno devolviendo una respuesta fundamentada y con citas

El notebook también calcula las señales de calidad de recuperación de la Capa 3 sin referencia a partir de lo que el agente recuperó y citó realmente, sin ground truth, sin juez adicional, y las publica en CloudWatch.

Figura 6: señales de calidad de recuperación de la Capa 3 sin referencia por base de conocimiento

Observe: Los paneles de las siete capas

Los dos paneles son donde las siete capas se hacen visibles. El stack crea ambos paneles, y el tráfico los va llenando. La siguiente captura de pantalla muestra los dos paneles tal como aparecen en la consola de CloudWatch.

Figura 7: Los dos paneles en la consola de CloudWatch, observabilidad agéntica de extremo a extremo y observabilidad por KB

Ambos paneles aparecen en la consola de CloudWatch: uno para la observabilidad agéntica de extremo a extremo y otro para la observabilidad por KB (BMKB, Bedrock Managed Knowledge Base). El resto de esta sección recorre lo que muestra cada capa.

En esta versión, los paneles se construyen a partir de objetos tipados en lugar de una cadena JSON. Una métrica es un Metric, un widget es un GraphWidget, y la disposición es una lista de Rows:

cw.GraphWidget(
    title="L4 — Gateway metrics (MCP)",
    width=12, height=6, period=PERIOD, statistic="Sum",
    left=[
        self._gateway_metric("Invocations", gateway_arn, "tools/call Invocations"),
        self._gateway_metric("SystemErrors", gateway_arn, "SystemErrors"),
        self._gateway_metric("UserErrors", gateway_arn, "UserErrors"),
        self._gateway_metric("Throttles", gateway_arn, "Throttles"),
    ],
)

El beneficio práctico no son menos líneas, dashboards_stack.py llega a 400 líneas, más que el JSON equivalente de DashboardBody. Es que una propiedad mal escrita o una combinación de widgets inválida falla en cdk synth, en tu computadora portátil, en aproximadamente un segundo. El mismo error dentro de una cadena DashboardBody se despliega con éxito y se muestra como un widget roto en la AWS Management Console, donde lo descubres mirándolo.

Como un Row acepta cualquier widget, la documentación forma parte de la disposición en lugar de ser una página wiki que se desactualiza. Cada panel intercala TextWidgets con los gráficos:

[cw.TextWidget(width=24, height=7, markdown=self._l3_explainer())],
[
    self._quality_widget("L3 · Financial KB — agentic quality (reference-free, 0–1)", fin_id),
    self._quality_widget("L3 · Weather KB — agentic quality (reference-free, 0–1)", wx_id),
],

_l3_explainer() devuelve una tabla markdown que define cada ratio y cómo leerlo, de modo que el widget que explica grounded_coverage se entrega en el mismo commit que el widget que lo grafica, y un lector que abre el panel sin contexto no necesita adivinar qué es una métrica sin referencias.

Panel A — observabilidad agéntica (de extremo a extremo). El panel abre con una explicación de cómo cada capa cuenta algo distinto (para N consultas verás ~N invocaciones del agente, ~2N recuperaciones, ~3N llamadas LLM, y ~5N operaciones MCP del Gateway, el bucle agéntico hecho visible), luego muestra las métricas del KB (L1), las métricas y la latencia del Gateway (L4), el uso de tokens (L6) y, como el agente usa AgenticRetrieveStream, que devuelve una respuesta sintetizada y con citas en lugar de puntuaciones por fragmento, las señales de calidad sin referencias de la Layer 3, definidas en línea y graficadas por KB.

En el Panel A, las señales de calidad sin referencias de la Layer 3 se grafican por base de conocimiento. Primero, el KB financiero. El siguiente gráfico muestra su retrieval_utilization, grounded_coverage y duplicate_rate.

Figura 8: Calidad de la Layer 3 del KB financiero, graficando la utilización de recuperación, la cobertura fundamentada y la tasa de duplicados

El KB del clima muestra las mismas tres señales, rastreadas por separado para que los dos dominios nunca se difuminen en un solo número.

Figura 9: Calidad de la Layer 3 del KB del clima, rastreada por separado del KB financiero

Los dos gráficos muestran retrieval_utilization, grounded_coverage y duplicate_rate para el KB financiero (izquierda) y el KB del clima (derecha), de modo que la calidad de recuperación de cada base de conocimiento permanezca separable en lugar de promediarse en un solo número.

Panel B — observabilidad por KB (BMKB). Las señales operativas que también determinan el gasto, por KB: tamaño del índice (a partir de los bytes de origen de S3), volumen de retrieve, llamadas a herramientas agénticas, uso de tokens de sesión y uso de tokens de generación por modelo, cada una con una explicación en línea.

Las siguientes capturas de pantalla muestran los cuatro widgets de métricas del Panel B, llenados después de una ejecución. El primer widget informa el tamaño del índice, derivado de los bytes de origen de S3, por base de conocimiento.

Figura 10: Tamaño del índice del Panel B por base de conocimiento, derivado de los bytes de origen de Amazon S3

El segundo widget cuenta las llamadas retrieve por base de conocimiento.

Figura 11: Dashboard B, número de llamadas retrieve por base de conocimiento

El tercer widget cuenta las llamadas a herramientas agénticas a través del Gateway. Este se comparte entre ambas bases de conocimiento en lugar de dividirse.

Figura 12: Dashboard B, número de llamadas a herramientas agénticas a través de AgentCore Gateway, compartido entre ambas bases de conocimiento

El cuarto widget informa del uso de tokens de sesión por base de conocimiento.

Figura 13: Dashboard B, uso de tokens de sesión por base de conocimiento

Los cuatro widgets muestran el tamaño del índice (a partir de los bytes de origen en S3), el volumen de llamadas retrieve, las llamadas a herramientas agénticas a través del Gateway y el uso de tokens de sesión. Cada uno se desglosa por base de conocimiento excepto el recuento de llamadas a herramientas del Gateway, que se comparte entre ambas.

Vale la pena destacar un detalle de dimensión, porque la API tipada no lo detectará por ti: el AWS/Bedrock/KnowledgeBases namespace espera un id con prefijo, knowledge-base/<id>, mientras que los propios BMKB/* namespaces de la solución usan el id sin prefijo. Para CDK, ambos son solo cadenas.

# L1 — AWS/Bedrock/KnowledgeBases wants the prefixed form.
dimensions_map={"Operation": "Retrieve", "KnowledgeBaseId": f"knowledge-base/{kb_id}"}

# BMKB/* — our own namespaces use the bare id.
dimensions_map={"KnowledgeBaseId": kb_id}

Capa 5: El árbol de spans

La capa 5 es el árbol de spans OTEL sin procesar en aws/spans, y es la capa que te muestra directamente el bucle agéntico. Vale la pena leerlo con cuidado, porque el anidamiento no es obvio: una llamada LLM produce tres spans. El span de Strands invoke_agent envuelve el turno, un span interno chat envuelve la llamada al modelo, y un span chat <model> de kind CLIENT es la llamada real, y los tres repiten los mismos atributos de tokens gen_ai.usage.* .

La siguiente captura de pantalla muestra el árbol de spans en aws/spans, con el anidamiento de tres spans visible en las filas superiores.

Figura 14: Árbol de spans de la capa 5 en aws/spans, mostrando el anidamiento de tres spans de una sola llamada LLM

Leyendo las tres filas superiores: un agregado invoke_agent de Strands Agents, luego un span interno chat, luego un span chat de tipo CLIENT, todos reportando idénticos 7,299 tokens de entrada y 268 de salida. Es la misma llamada LLM apareciendo en tres niveles del árbol, por eso la agregación requiere cuidado.

Esa estructura importa en el momento en que agregas. Para contar cada llamada LLM una sola vez, filtra por la CLIENT hoja:

fields attributes.gen_ai.request.model as model,
       attributes.gen_ai.usage.input_tokens as in_tok,
       attributes.gen_ai.usage.output_tokens as out_tok
| filter ispresent(in_tok) and kind = 'CLIENT' and name like /^chat /
| stats sum(in_tok) as input_tokens, sum(out_tok) as output_tokens,
        count(*) as llm_calls by model

Sin ese filtro, la misma consulta reporta el triple de tokens y el triple de llamadas.

Aplicando ese filtro de CLIENT-leaf, la siguiente captura de pantalla muestra el uso de tokens de generación por modelo, contando cada llamada LLM una sola vez.

Figura 15: Uso de tokens de generación por modelo, contando cada llamada LLM una sola vez

Con el filtro aplicado, la ejecución muestra 14 llamadas LLM con un total de 60,472 tokens de entrada y 2,709 de salida. Sin él, la misma consulta reportaría el triple de llamadas y el triple de tokens.

Evaluar: bajo demanda y continua

La calidad se mide de dos maneras, y ambas son aprovisionadas por la aplicación.

Bajo demanda: El notebook del controlador llama a AgentCore No hay script de despliegue en esta versión, y ese es el punto: (LLM-as-judge) sobre los spans de cada sesión para los evaluadores integrados, Correctness, Faithfulness, Tool-Selection Accuracy, y publica las puntuaciones en CloudWatch, donde aparecen como la Capa 7 en el Dashboard A.

La siguiente captura de pantalla muestra la Capa 7 en el Dashboard A: puntuaciones de evaluación bajo demanda por base de conocimiento, con la tabla de spans OTEL de la Capa 5 en el mismo dashboard.

Figura 16: Puntuaciones de evaluación bajo demanda de la Capa 7 por base de conocimiento, junto a la tabla de spans de la Capa 5

La Capa 7 muestra las puntuaciones de evaluación bajo demanda por base de conocimiento, con la tabla de spans OTEL de la Capa 5 al lado, de modo que las puntuaciones y los spans que las produjeron se leen juntos en un solo tablero.

Continua (en línea): La pila del agente también aprovisiona un AWS::BedrockAgentCore::OnlineEvaluationConfig que muestrea sesiones en vivo y las puntúa automáticamente, sin necesidad de ejecutar el notebook. La configuración en sí es visible en la consola de Bedrock AgentCore bajo Assess → Evaluations → Evaluation configurations. Los resultados llegan al grupo de registros /aws/bedrock-agentcore/evaluations/results/<config-id>, y cada puntuación también se publica como una métrica de CloudWatch en el Bedrock-AgentCore/Evaluations namespace, indexada por nombre de evaluador y id de configuración, de modo que puedes graficar las puntuaciones o crear alarmas sobre ellas sin analizar registros.

La siguiente captura de pantalla muestra la configuración de evaluación en línea en la consola de AgentCore, bajo Assess, luego Evaluations, luego Evaluation configurations.

Figura 17: La configuración de evaluación en línea en la consola de AgentCore, con cuatro evaluadores integrados al 100 percent de muestreo

La configuración enumera cuatro evaluadores integrados, Tool-Selection Accuracy, Faithfulness, Correctness y Response Relevance, configurados al 100 percent de muestreo y mostrados como ACTIVE y habilitados.

Como las puntuaciones son métricas ordinarias de CloudWatch, se grafican como cualquier otra cosa, sin análisis de registros, y el mismo widget podría llevar una alarma. La siguiente captura de pantalla muestra esas cuatro puntuaciones de evaluadores graficadas como métricas ordinarias de CloudWatch.

Figura 18: Las cuatro puntuaciones de evaluadores continuas graficadas como métricas ordinarias de CloudWatch

Las cuatro puntuaciones de los evaluadores aparecen como métricas en el Bedrock-AgentCore/Evaluations namespace, cada una indexada al id de la configuración de evaluación y al nombre del servicio del agente, de modo que puedes graficarlas o crear alarmas sobre ellas sin analizar registros.

Los resultados en línea solo llegan después de que una sesión se cierra. La puntuación se ejecuta sobre la sesión completada, por lo que el grupo de registros de resultados permanece vacío durante aproximadamente el tiempo de espera por inactividad de la sesión (~30 minutos) después de generar tráfico. Un grupo vacío justo después de una ejecución es lo esperado, no un error de configuración. Cada evento de resultado lleva session.id, por lo que se une a todas las demás capas. La ruta bajo demanda en el notebook no tiene esa espera, razón por la cual ambas están aquí.

En los cuatro evaluadores integrados de esta ejecución, la ruta continua puntuó 1.00 en Correctness, Faithfulness, Response Relevance y Tool-Selection Accuracy, cinco trazas puntuadas por evaluador, cada resultado con una explicación escrita.

⚠️ Muestreo y coste. Esta aplicación establece SAMPLING_PERCENTAGE = 100 puramente para el experimento del blog, de modo que cada sesión se puntúa y los resultados son visibles de inmediato. Esto no es una recomendación para producción. La evaluación en línea invoca un LLM-as-judge por cada sesión muestreada, por lo que el costo escala con la tasa de muestreo y el volumen de tráfico. Para un despliegue real, elija un porcentaje de muestreo que se ajuste a sus necesidades de monitoreo de calidad y a su presupuesto, y alinee la configuración con las políticas y los requisitos de gobernanza de costos de su organización antes de habilitarlo. La tasa es una única constante, EvalConfig.SAMPLING_PERCENTAGE, en config.py.

Limpieza

Cuando haya terminado, elimine la solución para que deje de generar cargos, ya que los datos de KB almacenados, la imagen del agente en ECR y la evaluación en línea aún activa cuestan dinero mientras los stacks permanecen inactivos. Un solo comando elimina todo:

cdk destroy --all

CDK elimina los stacks por su cuenta en orden inverso de dependencias: primero los dashboards, luego el agente, luego el gateway, luego kb: el mismo grafo que derivó para el despliegue, recorrido hacia atrás. No hay un script de desmontaje que mantener en coherencia con el script de despliegue, lo cual es una de las propiedades silenciosamente más valiosas de modelar las dependencias una sola vez.

Vale la pena conocer dos comportamientos de eliminación, porque ambos reemplazan código de limpieza escrito a mano:

self.source_bucket = s3.Bucket(
    self, "SourceBucket",
    removal_policy=RemovalPolicy.DESTROY,
    auto_delete_objects=True,  # replaces a list_object_versions delete loop
)

self.repository = ecr.Repository(
    self, "AgentImageRepo",
    removal_policy=RemovalPolicy.DESTROY,
    empty_on_delete=True,  # replaces an image-delete loop
)

Ambos están configurados por higiene del ejemplo; para cualquier cosa que le importe, cambie el bucket a RemovalPolicy.RETAIN.

El stack de bootstrap de CDK (CDKToolkit) y su bucket de staging no se eliminan. Son infraestructura compartida a nivel de cuenta de la que otras aplicaciones de CDK pueden depender.

Qué cambió desde la solución de una sola ejecución

Tanto esta publicación como la solución de 2024 son aplicaciones de CDK en Python, desplegadas con cdk deploy. La herramienta de autoría es la constante aquí; lo que cambió es la arquitectura debajo de ella, y la mayor parte del cambio es sustracción:

Aspecto 2024: RAG de una sola ejecución Esta solución
Almacén de vectores Una colección e índice de OpenSearch Serverless que usted aprovisiona, escala y paga por OCU Ninguno. Tipo: MANAGED, Amazon Bedrock es propietario del almacenamiento y la indexación
Ciclo de vida del índice Un recurso personalizado crea el índice y espera a que sea buscable Nada que crear
Modelo de embedding Lo selecciona usted y concede acceso al modelo Gestionado por el servicio de forma predeterminada
Stacks 3: rol de KB → infraestructura de OpenSearch → KB + fuente de datos 4: kb → gateway → agent → dashboards
Recuperación Un solo Retrieve, fragmentos top-k por similitud vectorial AgenticRetrieveStream, reranked internamente, devuelve una respuesta sintetizada con citas
Elección de una base de conocimiento No aplica, hay un solo índice El agente enruta semánticamente entre dos
Segunda mirada al corpus No es posible de una sola vez El agente recupera de nuevo antes de responder
Telemetría Ninguna aprovisionada Siete capas, dos dashboards
Evaluación Manual: sincronizar, elegir un modelo, hacer preguntas Bajo demanda y continua, ambas aprovisionadas
Costo mínimo en reposo Los cargos por OCU se acumulen o no las consultas Solo almacenamiento

El intercambio es real en ambas direcciones. Un único índice que responde preguntas de un solo disparo es más barato por consulta, más simple de razonar y completamente suficiente cuando un solo corpus contiene la respuesta. Recurra a este diseño cuando no sea así.

Los constructos de CDK que hacen el trabajo

Cuatro constructos cargan con la mayor parte del peso en esta aplicación, y vale la pena nombrarlos porque cada uno reemplaza algo que la gente de otro modo escribiría a mano:

  • Provider – Para recursos personalizados que sobreviven al límite de 15 minutos de una función de AWS Lambda. El on_event / is_complete split significa que nada duerme en un bucle de sondeo, y el protocolo de respuesta hacia CloudFormation es tarea del framework en lugar de un callback empaquetado urllib en cada handler.
  • BucketDeployment – Sube los corpora, de modo que el recurso personalizado de ingesta solo ingiere.
  • auto_delete_objects=True y empty_on_delete=True, reemplazan los bucles escritos a mano list_object_versions y de eliminación de imágenes que, de lo contrario, una pila necesitaría para poder destruirse siquiera.
  • repository.grant_pull_push(project) – Una línea para las ocho ecr:* acciones que CodeBuild necesita, escritas correctamente por construcción.

Y dashboards tipados, de la sección Observe: objetos Metric / GraphWidget / Row en lugar de una cadena JSON de DashboardBody, lo que convierte una combinación de widgets no válida de «se ve rota en la consola» a «falla en cdk synth.”

Dos cosas que CDK no cambia, y ambas vale la pena saber antes de empezar:

  • El JSON de forma libre sigue en camelCase. connector_parameters y parameter_values se pasan tal cual, de modo que la conversión de snake_case a PascalCase de AWS CDK no se aplica dentro de ellos. Claves como bucketName y inclusionPrefixes deben escribirse exactamente como la API espera, y nada te dirá lo contrario hasta que el recurso falle.
  • Los valores de tipo cadena siguen siendo cadenas. La knowledge-base/<id> frente a la diferencia de dimensión de <id> sin comillas de la sección Observe es invisible para el sistema de tipos. Los constructos tipados verifican la estructura, no la semántica.

Ninguna de las dos es una razón para preferir una herramienta sobre la otra. Son el límite de lo que te aporta «tipado», y saber dónde está ese límite es la mayor parte de lo que hace que CDK sea agradable en lugar de sorprendente.

Conclusión

Construimos una solución empresarial completa de recuperación agéntica sobre un Managed Amazon Bedrock Knowledge Base y AgentCore: enrutamiento semántico multi-KB, un agente de razonamiento, siete capas de observabilidad, y tanto evaluación bajo demanda como continua, y desplegamos todo ello como una única aplicación de AWS CDK.

Dos cosas vale la pena destacar. La base de conocimiento gestionada eliminó infraestructura en lugar de añadirla: no hay almacén de vectores que aprovisionar, no hay índice que crear y esperar, no hay una partida de OCU acumulándose mientras el sistema está inactivo. También es el tipo de base de conocimiento que admite la recuperación agéntica y el conector de AgentCore Gateway, como se describe en la documentación de Amazon Bedrock. Y una vez que la recuperación se volvió agéntica, la observabilidad dejó de ser opcional. Aproximadamente la mitad de lo que esta aplicación aprovisiona existe para responder qué hizo realmente el agente y si la respuesta fue buena, lo cual no es una sobrecarga en un sistema agéntico. Es la parte que lo hace operable.

El modelo de autoría de CDK demostró su valor en las uniones. Siete valores cruzan los límites de las pilas en esta arquitectura, y cada uno de ellos es una referencia de constructo en lugar de un par de exportación/importación, razón por la cual tampoco hay script de despliegue, ni script de desmantelamiento, ni un orden fijo que recordar.

Desde aquí puedes apuntar las fuentes de datos a tus propios corpora, colocar el agente en una nube privada virtual (VPC), ajustar la tasa de muestreo de la evaluación en línea según tu presupuesto y políticas, o añadir más bases de conocimiento al enrutador. Para saber más, consulta la Amazon Bedrock página de detalles y la documentación de Amazon Bedrock. La aplicación, el notebook del controlador y las utilidades autónomas se encuentran todos en el repositorio de GitHub adjunto, por lo que puede clonarlo y desplegar su propia copia con un solo comando.

 


Sobre los autores

Fuente original

AWS Machine Learning

Notas sobre el contenido

La publicación original y los derechos pertenecen a la fuente.

Traducción automática · Consulte el original