Arquitectura de Integración
LegalFlowAI → AWS Bedrock (eu-west-1)
Flujo de datos — dentro de AWS eu-west-1
LegalFlowAI
App Python/FastAPI
→
IAM Role
Permisos mínimos
→
Bedrock
Claude 3.5 Sonnet
→
Guardrails
PII + Off-topic
→
CloudWatch
Logs + métricas
Cumplimiento RGPD
Toda la inferencia ocurre en eu-west-1 (Irlanda). Los datos de los contratos nunca salen de la región AWS. AWS firma el DPA (Data Processing Addendum) requerido bajo RGPD.
1. Setup y Credenciales IAM
Instalación, configuración y política IAM mínima para LegalFlowAI
Paso obligatorio previo
Habilitar modelos en la consola AWS: Bedrock → Model Access → Habilitar "Claude 3.5 Sonnet v2" en eu-west-1 antes de ejecutar cualquier código.
# Instalar dependencias pip install boto3 # Configurar credenciales AWS (dev local) aws configure # AWS Access Key ID: AKIAIOSFODNN7LEGALAI # AWS Secret Access Key: xxxxxxxxxxxxxxxx # Default region: eu-west-1 # Output format: json # En producción (EC2/ECS): usar IAM Role adjunto, NO credenciales estáticas # Variables de entorno para CI/CD: export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7LEGALAI" export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxx" export AWS_DEFAULT_REGION="eu-west-1"
{
"Version": "2012-10-17",
"Statement": [
{
// Permisos mínimos: solo modelos aprobados en eu-west-1
"Effect": "Allow",
"Action": [
"bedrock:Converse",
"bedrock:ConverseStream"
],
"Resource": [
"arn:aws:bedrock:eu-west-1::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0"
]
},
{
// Permiso para Knowledge Bases de jurisprudencia
"Effect": "Allow",
"Action": [
"bedrock:RetrieveAndGenerate",
"bedrock:Retrieve"
],
"Resource": [
"arn:aws:bedrock:eu-west-1:123456789012:knowledge-base/KBJURISPRUDENCIA"
]
}
]
}
2. Modelos Disponibles en Bedrock
Selección recomendada para casos de uso legal
| Model ID | Proveedor | Mejor para | Estado |
|---|---|---|---|
| anthropic.claude-3-5-sonnet-20241022-v2:0 | Anthropic | Análisis contratos, drafting, RAG | ✓ En uso |
| anthropic.claude-3-5-haiku-20241022-v1:0 | Anthropic | Clasificación rápida, resúmenes simples | Alternativa rápida |
| anthropic.claude-3-opus-20240229-v1:0 | Anthropic | Análisis legal complejo, razonamiento | Máxima calidad |
| cohere.command-r-plus-v1:0 | Cohere | RAG alternativo, multilingüe | RAG |
| meta.llama3-70b-instruct-v1:0 | Meta | Procesamiento en volumen (open-weight) | Open-weight |
Nota región
En eu-west-1 no todos los modelos están disponibles. Verificar disponibilidad en la consola AWS antes de habilitarlos. Claude 3.5 Sonnet v2 está disponible en eu-west-1.
3. Converse API — Análisis de Contratos
Caso de uso real: extraer cláusulas clave de contratos de arrendamiento
import boto3 from typing import Optional # Cliente Bedrock en eu-west-1 (cumplimiento RGPD) bedrock = boto3.client("bedrock-runtime", region_name="eu-west-1") SYSTEM_PROMPT = """Eres un asistente legal especializado en derecho español. Analiza contratos y extrae información clave en formato JSON estructurado. IMPORTANTE: No reveles datos personales identificables fuera del análisis solicitado. Responde siempre en español.""" def analizar_contrato(texto_contrato: str, tipo: str = "arrendamiento") -> dict: """Extrae cláusulas clave de un contrato usando Claude 3.5 Sonnet.""" response = bedrock.converse( modelId="anthropic.claude-3-5-sonnet-20241022-v2:0", messages=[ { "role": "user", "content": [{"text": f"""Analiza este contrato de {tipo}: --- {texto_contrato} --- Extrae en JSON: - partes (arrendador, arrendatario) - duracion (inicio, fin, prorrogas) - renta (importe, actualizacion_IPC) - fianza (meses, deposito_comunidad) - clausulas_especiales (lista) - riesgos_detectados (lista con descripcion y severidad)"""}] } ], system=[{"text": SYSTEM_PROMPT}], inferenceConfig={ "maxTokens": 2048, "temperature": 0.1, # Baja temp para mayor precisión }, # Guardrail para bloquear PII y contenido fuera de dominio guardrailConfig={ "guardrailIdentifier": "legalflowai-rgpd-guard", "guardrailVersion": "1", "trace": "enabled", }, ) texto = response["output"]["message"]["content"][0]["text"] # Log de tokens consumidos (para control de costes) usage = response["usage"] print(ff"Tokens — input: {usage['inputTokens']} | output: {usage['outputTokens']}") # Coste aprox: (input * 3€/M) + (output * 15€/M) — Claude 3.5 Sonnet return {"analisis": texto, "tokens": usage} # Ejemplo de uso resultado = analizar_contrato(contrato_pdf_texto, tipo="arrendamiento comercial") print(resultado["analisis"])
4. Streaming — Drafting en Tiempo Real
UX fluida para el asistente de redacción de cláusulas legales
import boto3 from collections.abc import Generator bedrock = boto3.client("bedrock-runtime", region_name="eu-west-1") def draft_clausula_stream( tipo_clausula: str, contexto: str, jurisdiccion: str = "España" ) -> Generator[str, None, None]: """ Genera una cláusula legal en streaming. Uso en FastAPI con StreamingResponse para UX en tiempo real. """ response = bedrock.converse_stream( modelId="anthropic.claude-3-5-sonnet-20241022-v2:0", messages=[{ "role": "user", "content": [{"text": f"""Redacta una cláusula de {tipo_clausula} para un contrato bajo legislación de {jurisdiccion}. Contexto del contrato: {contexto} Formato: texto legal formal, párrafos numerados, sin ambigüedades."""}] }], system=[{"text": "Eres abogado especialista en derecho mercantil español."}], inferenceConfig={"maxTokens": 1500, "temperature": 0.2}, ) # Iterar sobre chunks del stream for event in response["stream"]: if "contentBlockDelta" in event: delta = event["contentBlockDelta"]["delta"] if "text" in delta: yield delta["text"] # Ejemplo: integración con FastAPI from fastapi import FastAPI from fastapi.responses import StreamingResponse app = FastAPI() @app.post("/draft/clausula") async def draft_endpoint(tipo: str, contexto: str): return StreamingResponse( draft_clausula_stream(tipo, contexto), media_type="text/event-stream" )
5. RAG — Base de Jurisprudencia
Knowledge Base Bedrock con jurisprudencia española (OpenSearch Serverless)
Setup Knowledge Base
Crear la KB en la consola AWS: Bedrock → Knowledge Bases → Create. Fuente de datos: bucket S3
s3://legalflowai-jurisprudencia-eu/. Embeddings: Amazon Titan Embeddings v2. Vector store: OpenSearch Serverless (gestionado por Bedrock).
import boto3 bedrock_agent = boto3.client( "bedrock-agent-runtime", region_name="eu-west-1" ) KB_ID = "KBJURISPRUDENCIA" # Obtenido al crear la Knowledge Base MODEL_ARN = ( "arn:aws:bedrock:eu-west-1::foundation-model/" "anthropic.claude-3-5-sonnet-20241022-v2:0" ) def consultar_jurisprudencia(pregunta: str) -> dict: """ RAG sobre la base de jurisprudencia española. Devuelve respuesta fundamentada + fuentes citadas. """ # Opción 1: Retrieve & Generate (respuesta completa) response = bedrock_agent.retrieve_and_generate( input={"text": pregunta}, retrieveAndGenerateConfiguration={ "type": "KNOWLEDGE_BASE", "knowledgeBaseConfiguration": { "knowledgeBaseId": KB_ID, "modelArn": MODEL_ARN, "retrievalConfiguration": { "vectorSearchConfiguration": { "numberOfResults": 5 # Top 5 sentencias relevantes } }, "generationConfiguration": { "promptTemplate": { "textPromptTemplate": """Eres un asistente legal experto. Responde basándote SOLO en la jurisprudencia proporcionada. Si no encuentras respuesta en los documentos, indícalo explícitamente. Cita siempre el número de sentencia y tribunal. Documentos: $search_results$ Pregunta: $query$""" } } }, }, ) respuesta = response["output"]["text"] # Extraer fuentes citadas citations = response.get("citations", []) fuentes = [ c["retrievedReferences"][0]["location"]["s3Location"]["uri"] for c in citations if c.get("retrievedReferences") ] return {"respuesta": respuesta, "fuentes": fuentes} # Uso resultado = consultar_jurisprudencia( "¿Cuál es el plazo de preaviso en arrendamientos comerciales en España?" ) print(resultado["respuesta"]) print("Fuentes:", resultado["fuentes"])
6. Guardrails — Cumplimiento RGPD
Guardrail configurado para bloquear PII y consultas fuera del dominio legal
Crear Guardrail en consola AWS
Bedrock → Guardrails → Create → Configurar los filtros de contenido, PII y denied topics (ver código de configuración abajo).
import boto3 bedrock_mgmt = boto3.client("bedrock", region_name="eu-west-1") # Crear guardrail para LegalFlowAI guardrail = bedrock_mgmt.create_guardrail( name="legalflowai-rgpd-guard", description="Guardrail RGPD para LegalFlowAI — bloquea PII y off-topic", # Bloquear temas NO relacionados con derecho topicPolicyConfig={ "topicsConfig": [ { "name": "off-topic-no-legal", "definition": "Consultas no relacionadas con derecho, contratos, o legislación", "examples": ["¿Cuál es la capital de Francia?", "Escribe un poema"], "type": "DENY", } ] }, # Detectar y enmascarar PII (RGPD) sensitiveInformationPolicyConfig={ "piiEntitiesConfig": [ {"type": "SPAIN_NIE", "action": "ANONYMIZE"}, {"type": "SPAIN_NIF", "action": "ANONYMIZE"}, {"type": "EMAIL", "action": "ANONYMIZE"}, {"type": "PHONE", "action": "ANONYMIZE"}, {"type": "NAME", "action": "ANONYMIZE"}, ] }, # Mensajes de bloqueo en español blockedInputMessaging="Consulta no permitida. LegalFlowAI responde solo a preguntas sobre derecho y contratos.", blockedOutputsMessaging="La respuesta contenía información sensible y ha sido bloqueada por cumplimiento RGPD.", ) guardrail_id = guardrail["guardrailId"] print(ff"Guardrail creado: {guardrail_id}") # Publicar versión estable bedrock_mgmt.create_guardrail_version(guardrailIdentifier=guardrail_id) print("Guardrail v1 publicado.")
7. Best Practices para LegalFlowAI
Recomendaciones operacionales y de costes
Residencia de datos
Usar siempre
eu-west-1 (Irlanda). AWS garantiza que los datos no salen de la región. Nunca usar regiones US para datos de clientes europeos.
Streaming siempre en UI
Usar
converse_stream para todas las interfaces de usuario. Reduce la latencia percibida de 8s a ~1s primer token. Clave para el asistente de drafting.
Control de costes
Loguear
inputTokens y outputTokens en CloudWatch. Usar Haiku para clasificación inicial (10x más barato) y Sonnet solo para análisis profundo.
IAM mínimo
Nunca usar credenciales de usuario root. IAM Role con permisos solo para los modelos específicos y la KB de jurisprudencia. Rotar claves trimestralmente.
Monitorización
Habilitar CloudWatch Logs para todas las llamadas a Bedrock. Configurar alarmas en: latencia P95 > 5s, tasa de bloqueo guardrail > 5%, coste diario > 20€.
Fallback cross-region
Usar inference profiles para fallback automático a
eu-central-1 (Frankfurt) si eu-west-1 no tiene capacidad. Transparente para la aplicación.
Temperatura baja para legal
Usar
temperature: 0.1 para análisis y extracción de datos. Solo subir a 0.3-0.4 para drafting creativo de cláusulas donde se busca variedad.
Tags para auditoría
Etiquetar todas las llamadas con
{"Application": "LegalFlowAI", "CostCenter": "AI-Inference"} para desglose de costes por cliente en AWS Cost Explorer.