# Guia para Llama en Amazon Bedrock

## Acceso escalable, seguro y sin gestión de infraestructura

> Para MiPyMEs que necesitan IA en producción sin complejidad técnica

***

## Introducción

Amazon Bedrock ofrece acceso simplificado a modelos Llama (y otros) a través de una API completamente administrada. En lugar de gestionar servidores, actualizaciones y escalabilidad, Bedrock se encarga de todo —permitiéndote enfocarte en construir aplicaciones de IA. Este enfoque es ideal para:

* **MiPyMEs sin equipo DevOps** → Deploy en minutos, no semanas
* **Startups que escalan rápido** → Autoescalado automático
* **Empresas reguladas** → Cumplimiento LFPDPPP y encriptación nativa
* **Proyectos con datos sensibles** → Datos NO se usan para entrenar modelos de Bedrock
* **Equipos que prefieren APIs** → Sin gestión de contenedores, GPUs ni dependencias complejas

Diferencia clave con Local:

* ✅ **Bedrock:** Paga por uso, escalabilidad infinita, cero mantenimiento, compliance built-in
* ❌ **Local:** Compra GPU cara, gestiona actualizaciones, recursos limitados a tu máquina

***

## Requisitos Previos

### Cuenta AWS Activa

Necesitas:

* Cuenta AWS (si no tienes, crea en <https://aws.amazon.com>)
* Acceso a consola AWS Management
* Tarjeta de crédito para billing (aunque Bedrock tiene tier gratuito limitado)

Costo estimado (Llama 2 70B):

* Entrada: $0.00195 por 1K tokens
* Salida: $0.00256 por 1K tokens
* Ejemplo: 10,000 requests de 500 tokens cada uno ≈ $15-20/mes

### Permisos IAM

Tu usuario AWS necesita permisos Bedrock. Opción recomendada: adjunta política `AmazonBedrockFullAccess` a tu usuario.

```json
// Política mínima recomendada
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock:*"
      ],
      "Resource": "*"
    }
  ]
}
```

### Habilitar Modelo Llama en Bedrock

{% stepper %}
{% step %}

### Habilitar modelos Llama en Bedrock

Pasos:

* Ve a AWS Console → Bedrock → Model Access
* Busca "Llama"
* Click "Enable" en los modelos Llama que necesites:
  * `Llama 2 Chat 7B` (rápido, económico)
  * `Llama 2 Chat 13B` (balanceado)
  * `Llama 2 Chat 70B` (más potente)
* Espera 1-2 minutos a habilitación
  {% endstep %}
  {% endstepper %}

### Instalar AWS SDK Python

```bash
pip install boto3
pip install aws-cli-v2  # Opcional, para CLI
```

### Configurar Credenciales AWS

Opción A (Recomendado para desarrollo):

```bash
aws configure

# Ingresa:

# AWS Access Key ID: [Tu key]

# AWS Secret Access Key: [Tu secret]

# Default region: us-east-1 (donde está Bedrock disponible)

# Default output: json
```

Opción B (Variables de entorno):

```bash
export AWS_ACCESS_KEY_ID="tu-access-key"
export AWS_SECRET_ACCESS_KEY="tu-secret-key"
export AWS_DEFAULT_REGION="us-east-1"
```

Opción C (En código):

```python
import boto3

client = boto3.client(
    'bedrock-runtime',
    region_name='us-east-1',
    aws_access_key_id='tu-key',
    aws_secret_access_key='tu-secret'
)
```

***

## Paso 1: Invocación Básica de Llama en Bedrock

### Script Simple: Tu Primer Request

{% code title="bedrock\_llama\_basic.py" %}

```python
import boto3
import json

# Crear cliente Bedrock Runtime
client = boto3.client('bedrock-runtime', region_name='us-east-1')

# Parámetros del modelo
model_id = "meta.llama2-70b-chat-v1"  # Puedes cambiar a 7b o 13b

# Tu prompt
prompt = "Explica en 50 palabras qué es Amazon Bedrock"

# Formatear input según especificaciones Llama
body = {
    "prompt": f"[INST] {prompt} [/INST]",
    "max_gen_len": 512,
    "temperature": 0.7,
    "top_p": 0.9
}

# Invocar modelo
response = client.invoke_model(
    modelId=model_id,
    body=json.dumps(body),
    contentType='application/json',
    accept='application/json'
)

# Procesar respuesta
response_body = json.loads(response['body'].read())
print("Respuesta Llama:")
print(response_body['generation'])
print("\nTokens utilizados:")
print(f"  Entrada: {response_body['prompt_token_count']}")
print(f"  Salida: {response_body['generation_token_count']}")
```

{% endcode %}

Ejecución:

```bash
python bedrock_llama_basic.py
```

Output esperado:

```
Respuesta Llama:
Amazon Bedrock es un servicio administrado que proporciona acceso a modelos de lenguaje de gran escala a través de una API. Permite a desarrolladores crear aplicaciones de IA sin gestionar infraestructura, con escalabilidad automática y seguridad nativa.

Tokens utilizados:
  Entrada: 14
  Salida: 48
```

***

## Paso 2: Conversación Multi-Turno (Chatbot)

### Script: Mantener Contexto Conversacional

{% code title="bedrock\_chatbot.py" %}

```python
import boto3
import json

class LlamaBedrocktChatbot:
    def __init__(self, model_id="meta.llama2-70b-chat-v1"):
        self.client = boto3.client('bedrock-runtime', region_name='us-east-1')
        self.model_id = model_id
        self.conversation_history = []
        self.total_input_tokens = 0
        self.total_output_tokens = 0
    
    def chat(self, user_message):
        """
        Envía mensaje y mantiene contexto conversacional
        """
        # Agregar mensaje usuario al historial
        self.conversation_history.append({
            "role": "user",
            "content": user_message
        })
        
        # Construir prompt con historial completo
        prompt = self._build_prompt()
        
        # Preparar body para Bedrock
        body = {
            "prompt": prompt,
            "max_gen_len": 1024,
            "temperature": 0.7,
            "top_p": 0.9
        }
        
        # Invocar
        response = self.client.invoke_model(
            modelId=self.model_id,
            body=json.dumps(body),
            contentType='application/json',
            accept='application/json'
        )
        
        # Parsear respuesta
        response_body = json.loads(response['body'].read())
        assistant_message = response_body['generation'].strip()
        
        # Actualizar historial
        self.conversation_history.append({
            "role": "assistant",
            "content": assistant_message
        })
        
        # Tracking de tokens
        self.total_input_tokens += response_body['prompt_token_count']
        self.total_output_tokens += response_body['generation_token_count']
        
        return assistant_message
    
    def _build_prompt(self):
        """
        Construir prompt con historial conversacional
        Formato Llama 2: [INST] ... [/INST]
        """
        prompt_parts = []
        
        for message in self.conversation_history:
            if message['role'] == 'user':
                prompt_parts.append(f"[INST] {message['content']} [/INST]")
            else:
                prompt_parts.append(f"{message['content']}")
        
        return "\n".join(prompt_parts)
    
    def get_token_usage(self):
        """Retorna estadísticas de tokens utilizados"""
        return {
            "input_tokens": self.total_input_tokens,
            "output_tokens": self.total_output_tokens,
            "total_tokens": self.total_input_tokens + self.total_output_tokens
        }
    
    def reset_conversation(self):
        """Limpiar historial para nueva conversación"""
        self.conversation_history = []

# Uso
if __name__ == "__main__":
    chatbot = LlamaBedrocktChatbot()
    
    # Turno 1
    print("Usuario: ¿Qué es una MiPyME?")
    response1 = chatbot.chat("¿Qué es una MiPyME?")
    print(f"Llama: {response1}\n")
    
    # Turno 2 (mantiene contexto)
    print("Usuario: ¿Cómo pueden usar IA?")
    response2 = chatbot.chat("¿Cómo pueden usar IA?")
    print(f"Llama: {response2}\n")
    
    # Turno 3
    print("Usuario: Dame un ejemplo práctico")
    response3 = chatbot.chat("Dame un ejemplo práctico")
    print(f"Llama: {response3}\n")
    
    # Estadísticas
    print("=== Estadísticas de Uso ===")
    stats = chatbot.get_token_usage()
    print(f"Tokens entrada: {stats['input_tokens']}")
    print(f"Tokens salida: {stats['output_tokens']}")
    print(f"Total: {stats['total_tokens']}")
    print(f"Costo estimado: ${(stats['input_tokens'] * 0.00195 + stats['output_tokens'] * 0.00256) / 1000:.4f}")
```

{% endcode %}

Ejecución:

```bash
python bedrock_chatbot.py
```

***

## Paso 3: Personalización Avanzada (RAG con Bedrock)

### Caso de Uso: Chatbot que Responde Preguntas Sobre Tu Base Conocimiento

{% code title="bedrock\_rag.py" %}

```python
import boto3
import json
from typing import List, Dict

class LlamaBedrockRAG:
    """
    Implementa RAG (Retrieval-Augmented Generation):
    1. Busca documento relevante
    2. Lo pasa a Llama para respuesta contextualizada
    """
    
    def __init__(self, model_id="meta.llama2-70b-chat-v1"):
        self.client = boto3.client('bedrock-runtime', region_name='us-east-1')
        self.model_id = model_id
        
        # Base de conocimiento simulada (en producción: BD vectorial, Elasticsearch, etc)
        self.knowledge_base = {
            "normativa_ia": """
            LFPDPPP 2025: Toda MiPyME debe obtener consentimiento explícito antes 
            de procesar datos personales con IA. Encriptación AES-256 obligatoria en tránsito.
            """,
            "derechos_empleados": """
            Los empleados tienen derecho a saber cuándo IA participa en decisiones sobre ellos.
            Prohibido monitoreo biométrico 24/7 sin consentimiento.
            """,
            "implementacion": """
            Plan 30-60-90: Semana 1 (7 quick wins), Semana 2 (8-point audit),
            Semana 3 (5 políticas), Semana 4 (capacitación + go-live).
            """
        }
    
    def retrieve_context(self, query: str, top_k: int = 1) -> str:
        """
        Busca documentos relevantes en base de conocimiento
        En producción: usar embedding + vector search
        """
        # Búsqueda simple por keywords (simplificada para ejemplo)
        keywords = query.lower().split()
        scores = {}
        
        for doc_id, content in self.knowledge_base.items():
            score = sum(1 for kw in keywords if kw in content.lower())
            scores[doc_id] = score
        
        best_doc_id = max(scores, key=scores.get)
        return self.knowledge_base[best_doc_id]
    
    def generate_with_context(self, query: str) -> Dict:
        """
        RAG Pipeline:
        1. Retrieve contexto
        2. Pass a Llama
        3. Generar respuesta
        """
        # Step 1: Retrieve
        context = self.retrieve_context(query)
        
        # Step 2: Build prompt con contexto
        system_prompt = """Eres experto en normativa de IA para MiPyMEs mexicanas.
Responde basándote SOLO en el contexto proporcionado.
Si no sabes, di "No tengo información sobre esto"."""
        
        prompt = f"""[INST] {system_prompt}

Contexto:
{context}

Pregunta: {query}
[/INST]"""
        
        # Step 3: Invoke Llama
        body = {
            "prompt": prompt,
            "max_gen_len": 1024,
            "temperature": 0.5,  # Más bajo para respuestas más precisas
            "top_p": 0.9
        }
        
        response = self.client.invoke_model(
            modelId=self.model_id,
            body=json.dumps(body),
            contentType='application/json',
            accept='application/json'
        )
        
        response_body = json.loads(response['body'].read())
        
        return {
            "question": query,
            "context_retrieved": context[:200] + "...",
            "answer": response_body['generation'].strip(),
            "tokens": {
                "input": response_body['prompt_token_count'],
                "output": response_body['generation_token_count']
            }
        }

# Uso
if __name__ == "__main__":
    rag = LlamaBedrockRAG()
    
    questions = [
        "¿Cuál es la obligación LFPDPPP?",
        "¿Qué derechos tienen los empleados?",
        "¿Cómo implemento compliance IA?"
    ]
    
    for q in questions:
        print(f"\n📋 Pregunta: {q}")
        result = rag.generate_with_context(q)
        print(f"📌 Contexto: {result['context_retrieved']}")
        print(f"✅ Respuesta: {result['answer']}")
        print(f"📊 Tokens: {result['tokens']}")
```

{% endcode %}

***

## Paso 4: Integración en Aplicaciones (API REST)

### FastAPI + Bedrock = API de IA en 30 minutos

{% code title="bedrock\_api.py" %}

```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import boto3
import json
import logging

# Setup
app = FastAPI(
    title="Llama API con Bedrock",
    description="API REST para acceder a Llama vía Amazon Bedrock"
)

bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')
logger = logging.getLogger(__name__)

# Modelos Pydantic
class LlamaRequest(BaseModel):
    prompt: str
    max_tokens: int = 512
    temperature: float = 0.7
    top_p: float = 0.9

class LlamaResponse(BaseModel):
    prompt: str
    response: str
    tokens_input: int
    tokens_output: int
    cost_usd: float

# Endpoints
@app.post("/invoke", response_model=LlamaResponse)
async def invoke_llama(request: LlamaRequest):
    """
    Invocar Llama directamente
    """
    try:
        body = {
            "prompt": f"[INST] {request.prompt} [/INST]",
            "max_gen_len": request.max_tokens,
            "temperature": request.temperature,
            "top_p": request.top_p
        }
        
        response = bedrock.invoke_model(
            modelId="meta.llama2-70b-chat-v1",
            body=json.dumps(body),
            contentType='application/json',
            accept='application/json'
        )
        
        result = json.loads(response['body'].read())
        
        # Calcular costo
        cost = (result['prompt_token_count'] * 0.00195 + 
                result['generation_token_count'] * 0.00256) / 1000
        
        return LlamaResponse(
            prompt=request.prompt,
            response=result['generation'].strip(),
            tokens_input=result['prompt_token_count'],
            tokens_output=result['generation_token_count'],
            cost_usd=cost
        )
        
    except Exception as e:
        logger.error(f"Error invoking Bedrock: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/models")
async def list_available_models():
    """
    Listar modelos disponibles
    """
    return {
        "models": [
            "meta.llama2-70b-chat-v1",
            "meta.llama2-13b-chat-v1",
            "meta.llama2-7b-chat-v1"
        ],
        "default": "meta.llama2-70b-chat-v1"
    }

@app.get("/health")
async def health_check():
    """Health check"""
    return {"status": "ok", "service": "Llama-Bedrock API"}

# Ejecutar
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
```

{% endcode %}

Uso:

```bash
# Instalar
pip install fastapi uvicorn

# Ejecutar
python bedrock_api.py

# Test en otra terminal
curl -X POST "http://localhost:8000/invoke" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "¿Qué es IA?", "max_tokens": 256}'
```

***

## Paso 5: Monitoreo y Optimización de Costos

### Script: Dashboard de Uso Bedrock

{% code title="bedrock\_monitor.py" %}

```python
import boto3
import json
from datetime import datetime, timedelta

class BedrockMonitor:
    """
    Monitor de uso y costos en Bedrock
    """
    
    def __init__(self):
        self.cloudwatch = boto3.client('cloudwatch', region_name='us-east-1')
        self.pricing = {
            "input": 0.00195,   # $ por 1K tokens entrada
            "output": 0.00256   # $ por 1K tokens salida
        }
    
    def get_usage_last_7_days(self):
        """Obtener estadísticas últimos 7 días"""
        end_time = datetime.utcnow()
        start_time = end_time - timedelta(days=7)
        
        try:
            response = self.cloudwatch.get_metric_statistics(
                Namespace='AWS/Bedrock',
                MetricName='InvocationTokens',
                StartTime=start_time,
                EndTime=end_time,
                Period=86400,  # 1 día
                Statistics=['Sum']
            )
            
            total_tokens = sum(dp['Sum'] for dp in response['Datapoints'])
            estimated_cost = total_tokens * self.pricing['input'] / 1000
            
            return {
                "period": "Last 7 days",
                "total_tokens": total_tokens,
                "estimated_cost": f"${estimated_cost:.2f}",
                "daily_avg": f"{total_tokens/7:.0f} tokens/day"
            }
        except Exception as e:
            return {"error": str(e)}
    
    def optimize_recommendations(self):
        """Recomendaciones de optimización"""
        return {
            "recommendations": [
                "1. Usar Llama 2 7B para tareas simples (25% más barato)",
                "2. Cachear prompts comunes para evitar re-processing",
                "3. Implementar RAG: búsqueda precisa reduce tokens innecesarios",
                "4. Batch processing: agrupar requests para mejor throughput",
                "5. Usar temperature=0.5 para tareas determinísticas (menos varianza)"
            ]
        }

# Uso
monitor = BedrockMonitor()
print("📊 Uso Últimos 7 Días:")
print(monitor.get_usage_last_7_days())
print("\n💡 Optimizaciones:")
print(monitor.optimize_recommendations())
```

{% endcode %}

***

## Paso 6: Seguridad y Compliance para MiPyMEs

### Checklist: Protegiendo Datos en Bedrock

{% code title="security\_checklist.py" %}

```python
"""
SEGURIDAD Y COMPLIANCE EN BEDROCK PARA MIPYMES MEXICANAS
"""

security_checklist = {
    "LFPDPPP": [
        "✅ Bedrock encripta datos en tránsito (TLS 1.2+)",
        "✅ Datos en reposo: encriptación con AWS KMS",
        "✅ NO utiliza datos para entrenar sus modelos base",
        "⚠️  Responsabilidad: Obtener consentimiento cliente antes pasar datos"
    ],
    
    "Acceso": [
        "✅ IAM roles: Restricción por usuario/aplicación",
        "✅ Logging completo en CloudTrail",
        "⚠️  Auditar quién accede qué",
        "⚠️  Rotación de AWS Access Keys cada 90 días"
    ],
    
    "Datos Sensibles": [
        "✅ Usar VPC endpoints (no exponer en internet)",
        "✅ Implementar data masking para PII",
        "⚠️  NO pasar información médica sin encriptar",
        "⚠️  NO pasar números de tarjeta sin hashing"
    ],
    
    "Monitoreo": [
        "✅ CloudWatch alertas por uso anómalo",
        "✅ Billing alerts si costo supera threshold",
        "⚠️  Revisar CloudTrail logs semanalmente",
        "⚠️  Audit trail completo para compliance"
    ]
}

print("=" * 60)
print("SEGURIDAD Y COMPLIANCE: Bedrock para MiPyMEs")
print("=" * 60)

for categoria, items in security_checklist.items():
    print(f"\n📋 {categoria.upper()}")
    for item in items:
        print(f"  {item}")
```

{% endcode %}

***

## Comparativa: Local vs Bedrock

| Aspecto          |                           Llama Local |                            Llama en Bedrock |
| ---------------- | ------------------------------------: | ------------------------------------------: |
| Setup Inicial    |                             2-3 horas |                                  10 minutos |
| Costo Hardware   |                    $1,000-3,000 (GPU) |                           $0 (paga por uso) |
| Escalabilidad    |                 Limitada a tu máquina |                        Infinita, automática |
| Mantenimiento    |        Actualizaciones, parches, CUDA |                         Cero (AWS gestiona) |
| Latencia         |                          Bajo (local) |                       Bajo (AWS optimizado) |
| Privacidad Datos |                         Control total |                    AWS gestiona, no entrena |
| Compliance       |                                Manual |           Built-in (LFPDPPP, PCI-DSS, SOC2) |
| Mejor para       | Prototipo, offline, máxima privacidad | Producción, escalabilidad, equipos pequeños |

***

## Próximos Pasos Recomendados

{% stepper %}
{% step %}

### Semana 1: Setup Bedrock

* Crear cuenta AWS.
* Habilitar modelos Llama.
* Ejecutar script básico.
* Entender precios.
  {% endstep %}

{% step %}

### Semana 2: Chatbot Simple

* Implementar conversación multi-turno.
* Integrar en web/app.
* Pruebas con usuarios reales.
  {% endstep %}

{% step %}

### Semana 3: RAG

* Conectar a base de conocimiento.
* Fine-tuning de prompts.
* Optimizar costos.
  {% endstep %}

{% step %}

### Semana 4: Producción

* Implementar FastAPI/similar.
* Monitoreo con CloudWatch.
* Auditoría LFPDPPP.
  {% endstep %}
  {% endstepper %}

***

## Solución de Problemas Comunes

<details>

<summary>Error: "Access Denied"</summary>

Causa: Usuario IAM sin permisos Bedrock\
Solución: Adjuntar política AmazonBedrockFullAccess

</details>

<details>

<summary>Error: "Model not found"</summary>

Causa: Modelo no habilitado en Model Access\
Solución: Console AWS → Bedrock → Enable modelo

</details>

<details>

<summary>Error: "Rate limit exceeded"</summary>

Causa: Demasiados requests simultáneos\
Solución: Implementar backoff exponencial, usar batch APIs

</details>

<details>

<summary>Costo Muy Alto</summary>

Causa: Prompts muy largos, muchas iteraciones\
Solución: Implementar caching, usar Llama 7B, optimizar prompts

</details>

***

## Conclusión

Amazon Bedrock elimina la complejidad de ejecutar Llama en producción. Para MiPyMEs mexicanas, representa:

* ✅ Acceso inmediato a modelos SOTA sin inversión hardware
* ✅ Escalabilidad automática para crecer sin límite
* ✅ Compliance nativo para LFPDPPP y regulaciones
* ✅ Costo predecible (paga solo lo que usas)
* ✅ Equipos pequeños pueden construir grandes cosas

Comienza hoy: Sigue el Script Básico → Chatbot → RAG → Producción. En 4 semanas, tendrás sistema IA robusto y listo para escalar.

***

**Referencias:**

* **AWS Bedrock Docs:** <https://docs.aws.amazon.com/bedrock/>
* **Llama 2 Model Card:** <https://llama.meta.com/>
* **Pricing Calculator:** <https://calculator.aws/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://incmty.gitbook.io/llama/sesion-2/guia-para-llama-en-amazon-bedrock.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
