// 046Laboratorio propio · Agentes de IA

Analizador de Documentos Extensos
Doble RAG, Identidad Gestionada en Lugar de Claves y Observabilidad por Análisis

Microsoft FoundryAzure AI SearchAzure Container AppsManaged IdentityLog AnalyticsBicep
0 clavesen la aplicación: modelo, buscador, base de datos y secretos por identidad gestionada
2 índicesde recuperación: el documento y una base de conocimiento propia
1 línea JSONpor análisis con tokens, coste estimado y latencia, recogida por Log Analytics

Es un laboratorio propio, sin cliente y sin documentos reales. El servicio recibe un documento extenso (un pliego de requisitos, un contrato, una norma), extrae lo que importa y lo contrasta con una base de conocimiento propia para proponer un borrador de análisis con huecos y riesgos señalados. Los ejemplos que se usan para probarlo son sintéticos, y la salida del modelo es un borrador que exige revisión humana.

El interés del ejercicio no está en el análisis en sí, sino en tres cosas que casi siempre se descuidan al pasar de una demostración a algo que se pueda operar: cómo se maneja un documento más largo que la ventana del modelo, cómo se evita que haya claves por medio y cómo se sabe, análisis a análisis, cuánto cuesta y cuánto tarda. Y, sobre todo, qué ocurre cuando el primer despliegue no sale como en el tutorial.

Es la continuación práctica de dos ideas ya publicadas: operar agentes con telemetría (artículo 022) y conocer el coste de la IA cuando se produce (artículo 039).

  • Analizar documentos que no caben en el contexto del modelo sin perder las partes relevantes ni gastar tokens en el resto
  • Apoyar cada conclusión en evidencia recuperable, de dos fuentes distintas: el propio documento y una base de conocimiento propia, para que la cobertura declarada no sea una invención del modelo
  • Eliminar las claves de la aplicación: identidad gestionada para el modelo, el buscador, la base de datos y el almacén de secretos
  • Mantener el procesamiento de los datos dentro de la zona de datos de la UE sin renunciar a un modelo barato
  • Medir cada análisis (tokens, coste estimado, latencia) sin montar una plataforma de observabilidad aparte
  • Que el despliegue fuera reproducible con herramientas ordinarias, sin Docker local y sin depender de comandos «mágicos» que ocultan lo que hacen

La aplicación es un servicio web pequeño en Azure Container Apps que llama a un modelo de lenguaje y a un buscador, y guarda el histórico en una base de datos. Lo que importa es cómo se conectan las piezas.

// DOBLE RAG — Dos índices, dos preguntas distintas

  • RAG sobre el documento: se extrae el texto (PDF, DOCX, TXT o MD), se trocea en fragmentos de 1.200 palabras con solape de 150, se generan embeddings con text-embedding-3-large y se indexan en Azure AI Search con un campo vectorial y búsqueda de texto
  • Recuperación por dimensiones, no un volcado: en lugar de enviar el documento entero, el servicio hace una consulta híbrida por cada dimensión de análisis (objeto y alcance, requisitos técnicos, criterios de valoración, cumplimiento normativo, presupuesto y plazos) y se queda con los tres mejores fragmentos de cada una
  • RAG sobre la base de conocimiento propia: con el contexto ya recuperado como consulta, se buscan las capacidades relevantes en un segundo índice. Así la columna «cobertura» se apoya en evidencia real y, si el índice no estuviera disponible, el servicio lo dice en el prompt en lugar de inventarla
  • Un documento escaneado sin capa de texto se rechaza con un mensaje claro en vez de producir un análisis vacío

// IDENTIDAD — Sin claves en la aplicación

  • Una identidad gestionada de usuario con los roles mínimos: Cognitive Services OpenAI User sobre el modelo, Search Index Data Contributor y Search Service Contributor sobre el buscador y Key Vault Secrets User sobre el almacén de secretos; el acceso a los datos de la base de datos se concede con un rol de plano de datos
  • El buscador pasa de clave a RBAC: se habilita la autenticación por roles con aadOrApiKey, se concede a la identidad el rol de gestión de índices, la aplicación cambia a un modo de autenticación por identidad con una variable de configuración y el secreto de la clave se borra del almacén
  • Los modelos se despliegan en Data Zone Standard: el tipo Standard regional no estaba disponible para el modelo elegido en la región del laboratorio, y Data Zone mantiene el procesamiento dentro de la zona de datos de la UE, con los datos en reposo en la geografía del recurso

// DESPLIEGUE — Determinista y sin Docker local

  • La imagen se construye en Azure Container Registry con az acr build y una etiqueta por marca de tiempo, para que cada despliegue genere una revisión nueva
  • La identidad recibe el rol AcrPull y la aplicación descarga la imagen sin credenciales de registro
  • El cambio de imagen y el cambio de variables de entorno van en actualizaciones separadas: combinar ambos en una sola puede ignorar las variables

// AGENTOPS — Una línea JSON por análisis

  • Cada análisis imprime en consola una línea JSON con identificador, nombre del fichero, modelo, fragmentos indexados, latencia, tokens de entrada y de salida, tokens totales y coste estimado en euros
  • Log Analytics la recoge sola desde los registros de consola de la aplicación; no hace falta ningún agente ni librería de telemetría
  • Un libro de Azure Monitor desplegado con Bicep muestra análisis por día, tokens, coste diario, latencia p50 y p95 y una tabla de los últimos análisis
  • El coste es una estimación: tokens por tarifa configurable, no la factura
ContainerAppConsoleLogs_CL
| where Log_s startswith "AGENTOPS "
| extend j = parse_json(substring(Log_s, 9))
| summarize Analisis = count(),
            Tokens   = sum(tolong(j.tokens)),
            p50 = round(percentile(todouble(j.latency_s), 50), 1),
            p95 = round(percentile(todouble(j.latency_s), 95), 1)
  by bin(TimeGenerated, 1d)
Cero claves en la aplicaciónel modelo, la base de datos y el almacén de secretos se autentican por identidad, y el buscador, tras el cambio, también; el secreto de la clave se elimina. Con aadOrApiKey el servicio sigue aceptando claves hasta que se desactiva la autenticación local, paso que el laboratorio documenta como cierre opcional
Documentos largos sin volcarlos al modelocinco consultas híbridas por documento y tres fragmentos por consulta acotan el contexto que se envía, con independencia de la longitud del original
Medición por análisis sin infraestructura nuevauna línea de consola y una consulta basta para saber cuántos análisis se hacen, cuántos tokens consumen, cuánto cuestan de forma estimada y cuánto tardan
Despliegue reproducible tras los fallosla secuencia de construcción, permiso de descarga, cambio de imagen y variables funciona de forma repetible, y el script de reparación de un contenedor duplicado deja un único contenedor con la configuración mínima

Conviene ser claro sobre lo que no se ha medido: no hay una evaluación de la calidad del análisis frente a un revisor humano, ni un benchmark de latencia o coste con documentos reales. Las cifras de coste del laboratorio son estimaciones del propio diseño, no una factura analizada.

  • La orden «mágica» no sustituyó la imagen. En este montaje, la aplicación se creó con una imagen de ejemplo, y az containerapp up --source no la sustituyó: la aplicación siguió respondiendo con la de ejemplo. La documentación indica que, para redesplegar, hay que indicar el grupo de recursos y el entorno; no consta con qué opciones lo lancé, así que no puedo asegurar que fuera un defecto del comando y no de cómo lo usé, y pasé a la secuencia explícita: az acr build, rol AcrPull, containerapp registry set --identity y update --image --container-name. Lo importante no es quién tenía razón, sino que la secuencia explícita es la que se puede auditar
  • Había un contenedor duplicado dentro del mismo pod. Dos contenedores intentaban escuchar en el mismo puerto y el resultado era un bucle de reinicios con el error de dirección en uso y respuestas intermitentes entre una versión y otra. Se corrigió con un PATCH de ARM que envía una plantilla mínima, sin los campos de solo lectura que la API rechaza (almacenamiento efímero, periodo de enfriamiento, intervalo de sondeo), y después hubo que reafirmar las variables de entorno, que el PATCH había dejado sin valor
  • La reparación cambió el comportamiento de escalado. El script que deja un solo contenedor fija el mínimo y el máximo de réplicas en uno, de modo que la aplicación deja de escalar a cero. Es una decisión razonable para un servicio que se está depurando, pero contradice la premisa de coste cercano a cero en reposo y hay que acordarse de revertirla
  • Los roles tardan en propagarse. Tras habilitar RBAC en el buscador y asignar el rol, el script espera 60 segundos y el propio README habla de dos o tres minutos; la documentación de Microsoft menciona que las asignaciones pueden tardar entre cinco y diez minutos en hacer efecto. Un fallo de autorización justo después del cambio no implica que la configuración esté mal
  • La persistencia del histórico es de mejor esfuerzo. Si falla la escritura en la base de datos, el servicio lo registra como aviso y continúa. Es práctico para una demostración y peligroso en producción, porque un permiso mal concedido produce un histórico vacío sin romper nada

Es un entorno de laboratorio y se comporta como tal:

  • Un solo servicio de IA y de búsqueda, sin redundancia ni zonas de disponibilidad, en una región y con el nivel gratuito del buscador, que solo admite uno por suscripción
  • Red pública en los servicios del plano de datos y de seguridad, aceptable en un entorno efímero y no en uno que maneje documentos reales
  • La salida es un borrador: exige revisión humana y no sustituye a un análisis experto
  • Sin evaluación de calidad ni pruebas de carga, y sin reconocimiento óptico de caracteres: los documentos escaneados se rechazan

El laboratorio ya está destruido, por lo que no se enlaza a ninguna URL y no se publican identificadores de suscripción, de identidad ni nombres de recurso.

// ARCH 46 · Agente de documentos · Doble RAG · Identidad gestionada
Analizador de Documentos Extensos — Doble RAG, Sin Claves y con Observabilidad por Análisis
  Usuario ──► servicio web (Container Apps, una identidad gestionada)
                 │
                 ├─ extraer + trocear + embeddings ──► Foundry (text-embedding-3-large, Data Zone)
                 ├─ índice del documento  ◄── 5 consultas híbridas × 3 fragmentos
                 ├─ índice de conocimiento propio ◄── contexto recuperado como consulta
                 ├─ análisis ──► Foundry (modelo de chat, Data Zone Standard)
                 ├─ histórico ──► base de datos serverless (rol de plano de datos)
                 └─ línea JSON por análisis ──► consola ──► Log Analytics ──► libro de Monitor

Un servicio en Azure Container Apps recupera, por dimensiones, los fragmentos relevantes de un documento largo y los contrasta con una base de conocimiento propia antes de pedir un borrador de análisis al modelo. La aplicación se autentica por identidad y cada análisis deja una línea JSON que Log Analytics recoge sin agentes.

Azure Container AppsMicrosoft FoundryAzure AI SearchAzure Cosmos DBAzure Container RegistryLog AnalyticsManaged IdentityBicep
// Consideraciones de arquitectura · Agentes de documentos WAF
  1. Recupera por dimensiones, no por volumen — acotar lo que se envía al modelo controla el coste y la calidad a la vez, y funciona con cualquier longitud de documento.
  2. Separa la evidencia del documento de la evidencia propia — dos índices con dos preguntas distintas evitan que el modelo invente la cobertura.
  3. «Sin claves» es una propiedad de la aplicación y del servicio, no solo del código — mientras el servicio acepte claves, un secreto olvidado sigue siendo un acceso válido; cierra el ciclo desactivando la autenticación local cuando hayas verificado el acceso por roles.
  4. Los roles tardan: espera antes de diagnosticar — una denegación justo después de asignar un rol no demuestra un error de configuración.
  5. Prefiere la secuencia explícita al comando único — construir, conceder permiso, cambiar imagen y cambiar variables por separado deja cada paso auditable y repetible.
  6. Mide en el momento de inferir — una línea estructurada por llamada da latencia, tokens y coste estimado sin infraestructura nueva; la factura se usa para conciliar, no para operar.
SeguridadExcelencia OperacionalOptimización de costesFiabilidad

Artículo relacionado

Lo que falló en el primer despliegue y cómo se arregló, contado con detalle. Un agente de documentos sin claves en Container Apps →