sistemas/ops/prompting-avanzado-manual

Manual de Prompting Avanzado: Arquitectura de Instrucción para LLMs

Guía exhaustiva de ingeniería de prompts orientada a sistemas productivos, no a conversación casual. Técnicas: chain-of-thought, few-shot estructurado, delimitadores de contexto, output formatting, y prevención de alucinaciones en dominios técnicos.

Publicado
Lectura~20 min
Formatomanual

La diferencia entre un usuario casual de ChatGPT y un operador de sistemas que integra LLMs en su arquitectura de producción está en la arquitectura de sus instrucciones, no en la calidad de sus preguntas. Un prompt de producción es un documento de especificación técnica: define rol, contexto, tarea, restricciones, formato de salida y ejemplos calibrados con la misma precisión con la que escribirías los requisitos de una API.

Este manual condensa las técnicas que uso a diario para operar modelos de lenguaje en contextos de producción real: generación de contenido técnico, análisis financiero automatizado, pipelines de código y agentes autónomos. Presenta una metodología de arquitectura de instrucción, no una colección de “trucos de prompting”.


1. Los Seis Componentes de un Prompt de Producción

Un prompt diseñado para ejecución repetible y determinista, no para conversación casual, debe contener exactamente seis secciones, idealmente delimitadas con etiquetas estructurales que el modelo pueda parsear sin ambigüedad:

Componente 1: Rol (System Prompt)

Define la identidad operativa que el modelo debe asumir. No es cosmético: el rol condiciona el espacio latente del que el modelo extrae patrones. Un modelo actuando como “analista financiero” accede a un subespacio de conocimiento distinto que si actúa como “redactor creativo”.

Eres un ingeniero de software senior especializado en auditoría de contratos
inteligentes en Solidity. Tu comunicación es precisa, técnica y sin ambigüedades.
No especulas: si no conoces un detalle, lo declaras explícitamente.

Componente 2: Contexto

Proporciona la información de fondo necesaria para que el modelo entienda el dominio del problema sin tener que inferirlo. Cuanto más específico sea el contexto, menos espacio hay para la interpretación creativa (que en contextos técnicos es error).

Contexto del proyecto:
- Protocolo DeFi de lending en Ethereum mainnet
- Contrato objetivo: LendingPool.sol (920 líneas, Solidity 0.8.20)
- Ya se ha completado una auditoría previa que identificó 3 vulnerabilidades críticas (ver adjunto)
- El foco de esta revisión es exclusivamente la gestión de liquidaciones (líneas 450-720)

Componente 3: Tarea

La instrucción concreta de lo que el modelo debe producir. Debe ser específica, medible y acotada. Instrucciones vagas producen outputs vagos.

Tarea: Revisa las líneas 450-720 del contrato LendingPool.sol y genera un informe
de vulnerabilidades que incluya:
1. Lista de todas las vulnerabilidades potenciales encontradas
2. Para cada una: severidad (Crítica/Alta/Media/Baja), línea exacta, descripción
3. Recomendación de mitigación con snippet de código corregido

Componente 4: Restricciones

Define explícitamente lo que el modelo no debe hacer. Esta sección es la que más se omite y la que más valor diferencial aporta en producción.

Restricciones:
- NO sugieras cambios fuera del alcance (líneas 450-720)
- NO especules sobre vulnerabilidades sin evidencia en el código
- NO uses markdown dentro de los snippets de código
- NO generes explicaciones para hallazgos de severidad Baja: solo enuméralos
- Si encuentras 0 vulnerabilidades, responde exactamente: "SIN_HALLAZGOS"

Componente 5: Formato de Salida

Especifica la estructura exacta del output. En producción, el output de un LLM suele ser el input de otro sistema (un parser, una base de datos, otro agente). La estructura debe ser parseable.

Formato de salida (JSON estricto, sin texto fuera del JSON):
{
  "total_vulnerabilidades": <número>,
  "hallazgos": [
    {
      "id": "VULN-001",
      "severidad": "Crítica|Alta|Media|Baja",
      "linea": <número>,
      "titulo": "<string>",
      "descripcion": "<string>",
      "codigo_vulnerable": "<snippet>",
      "codigo_corregido": "<snippet>"
    }
  ]
}

Componente 6: Ejemplos Calibrados

Proporciona al menos un ejemplo de input → output correcto. Los ejemplos anclan al modelo en el nivel de detalle, tono y formato exacto que esperas. Esto se trata en profundidad en la Sección 3.


2. Chain-of-Thought y Tree-of-Thought: Técnicas de Razonamiento Estructurado

Chain-of-Thought (CoT)

La técnica de cadena de pensamiento fuerza al modelo a externalizar su razonamiento paso a paso antes de emitir una conclusión. Esto es particularmente efectivo para tareas que requieren razonamiento multi-paso: matemáticas, análisis de código, planificación financiera, diagnóstico técnico.

Antes de responder, sigue este proceso de razonamiento:
Paso 1: Identifica todas las variables relevantes en el problema
Paso 2: Determina las relaciones entre variables
Paso 3: Aplica las fórmulas o reglas pertinentes
Paso 4: Verifica cada paso intermedio
Paso 5: Solo entonces, emite tu respuesta final

Problema: [describir problema]

Para tareas de análisis, utilizo una variante más agresiva que fuerza la autoverificación:

Para cada afirmación que hagas:
1. Enúnciala
2. Proporciona la evidencia en la que se basa (cita la fuente o línea de código)
3. Evalúa tu grado de confianza en una escala 1-5
4. Identifica explícitamente cualquier suposición no verificada

Tree-of-Thought (ToT)

Cuando el problema admite múltiples caminos de razonamiento, Tree-of-Thought explora varias ramas en paralelo y selecciona la más prometedora:

Para resolver este problema, genera 3 enfoques distintos:

Enfoque A: [descripción breve]
Enfoque B: [descripción breve]
Enfoque C: [descripción breve]

Para cada enfoque, evalúa:
- Viabilidad (1-5)
- Riesgos
- Tiempo estimado de implementación

Después de evaluar los 3, selecciona el enfoque óptimo y desarróllalo completamente.

3. Few-Shot Estructurado: Ejemplos Que Enseñan, No Que Decoran

El few-shot prompting no consiste en pegar ejemplos aleatorios. Consiste en seleccionar ejemplos que deliberadamente muestren al modelo los casos extremos, los errores comunes y el nivel de detalle esperado.

Principios de un Few-Shot Efectivo

  1. Diversidad de casos: Incluye el caso más simple, el más complejo, y al menos un caso límite (edge case). Esto enseña al modelo el rango completo de comportamiento esperado.

  2. Mostrar errores y correcciones: Si hay errores comunes que quieres evitar, incluye un ejemplo de output incorrecto junto con su corrección. El aprendizaje por contraste es más potente que el aprendizaje por instrucción.

  3. Auto-consistencia: El formato de todos los ejemplos debe ser idéntico. Cualquier variación de formato entre ejemplos introduce ruido que el modelo puede interpretar como señal.

Ejemplo 1 (Caso simple):
Input: "Analiza el riesgo de este activo: BTC, asignación 5%, volatilidad anual 60%"
Output:
{
  "activo": "BTC",
  "asignacion": "5%",
  "volatilidad": "60%",
  "nivel_riesgo": "Alto",
  "razonamiento": "Volatilidad > 50% con asignación < 10%: riesgo controlado por tamaño de posición pero alta incertidumbre de precio."
}

Ejemplo 2 (Caso complejo - múltiples activos correlacionados):
Input: "Analiza el riesgo del portfolio: BTC (40%), ETH (35%), SOL (25%)"
Output:
{
  "activos": ["BTC", "ETH", "SOL"],
  "asignaciones": {"BTC": "40%", "ETH": "35%", "SOL": "25%"},
  "correlacion_media": "0.78 (alta)",
  "nivel_riesgo": "Muy Alto",
  "razonamiento": "Tres criptoactivos con correlación > 0.7 entre sí: la diversificación aparente es ilusoria. El portfolio se comporta como un solo activo de alta volatilidad."
}

Ejemplo 3 (Caso límite - incluye stablecoin):
Input: "Analiza el riesgo del portfolio: BTC (50%), USDC (50%)"
Output:
{
  "activos": ["BTC", "USDC"],
  "asignaciones": {"BTC": "50%", "USDC": "50%"},
  "nivel_riesgo": "Moderado",
  "razonamiento": "USDC introduce riesgo de contraparte (emisor) y riesgo de desvinculación (depeg) que no equivale a efectivo libre de riesgo. El portfolio 50/50 no es conservador en términos absolutos."
}

4. Gestión de la Ventana de Contexto: Estrategia de Delimitadores

La ventana de contexto de un LLM es su memoria de trabajo. Gestionarla bien es la diferencia entre un modelo que recuerda tus instrucciones y uno que las “olvida” a mitad del procesamiento.

Jerarquía de Delimitadores (XML Tags)

Utilizo etiquetas XML como delimitadores estructurales porque los modelos modernos (Claude, GPT-4, Gemini) están entrenados con cantidades masivas de datos estructurados en XML/HTML y parsean estas etiquetas con alta precisión:

<system>
Eres un analista financiero. Responde solo con datos, sin opiniones.
</system>

<context>
Se adjuntan los siguientes documentos:
<documento id="balance_2025">
[contenido del balance]
</documento>
<documento id="forecast_2026">
[contenido de las proyecciones]
</documento>
</context>

<task>
Compara los datos del balance 2025 con las proyecciones 2026 y extrae discrepancias mayores al 5%.
</task>

<output_format>
JSON con el esquema especificado en <schema>.
</output_format>

Principios de Gestión de Contexto

  1. Orden de prioridad: La información más importante debe ir al final del prompt (efecto recency bias). Las instrucciones de sistema van al principio, los ejemplos en el medio, y los datos concretos a procesar al final.

  2. Compresión progresiva: Si procesas documentos largos (>10K tokens), no los pegues completos. Extrae primero un resumen estructural con un prompt inicial y luego procesa secciones específicas en prompts subsiguientes.

  3. Instrucciones autocontenidas: Cada bloque de instrucciones debe ser comprensible sin depender de bloques anteriores. Esto reduce el riesgo de que el modelo pierda el hilo si el contexto es extenso.


5. Enforcement del Esquema de Salida: JSON Mode y Restricciones de Regex

En producción, el output de un LLM debe ser parseable por máquina. Si tienes que leer el output manualmente para extraer datos, estás ante una interfaz de chat glorificada, no ante un sistema automatizado.

Técnica 1: JSON Mode Nativo

La mayoría de APIs modernas ofrecen un modo JSON que garantiza output sintácticamente válido:

# OpenAI API - JSON mode
response = client.chat.completions.create(
    model="gpt-4o",
    response_format={"type": "json_object"},
    messages=[...]
)

# Anthropic API - Structured outputs con tool use
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    tools=[{
        "name": "output",
        "input_schema": {
            "type": "object",
            "properties": {
                "hallazgos": {"type": "array", ...}
            }
        }
    }],
    ...
)

Técnica 2: Restricciones por Prompt (fallback)

Cuando no tienes acceso a JSON mode, la restricción debe ser redundante y explícita:

Tu respuesta debe ser EXCLUSIVAMENTE un objeto JSON válido. No incluyas:
- Texto antes del JSON (ni "aquí está el resultado", ni explicaciones)
- Texto después del JSON
- Comentarios dentro del JSON
- Markdown code blocks (ni ```json ni ```)

Si no puedes generar una respuesta válida, devuelve:
{"error": "no_se_puede_completar", "razon": "<explicación breve>"}

Técnica 3: Post-Procesamiento Defensivo

Incluso con JSON mode, implementa siempre un parser defensivo:

import json
import re

def parse_llm_output(raw_output: str) -> dict:
    """Extrae JSON de un output de LLM con tolerancia a fallos."""
    # Intenta parseo directo
    try:
        return json.loads(raw_output)
    except json.JSONDecodeError:
        pass

    # Intenta extraer de bloques de código markdown
    match = re.search(r'```(?:json)?\s*\n?(.*?)\n?```', raw_output, re.DOTALL)
    if match:
        try:
            return json.loads(match.group(1))
        except json.JSONDecodeError:
            pass

    # Intenta encontrar el primer { y último }
    start = raw_output.find('{')
    end = raw_output.rfind('}')
    if start != -1 and end != -1:
        try:
            return json.loads(raw_output[start:end+1])
        except json.JSONDecodeError:
            pass

    raise ValueError("No se pudo extraer JSON válido del output")

6. Mitigación de Alucinaciones en Dominios Técnicos

La alucinación, el modelo genera información plausible pero falsa, es el mayor riesgo operativo al usar LLMs en producción. Estas son las técnicas que aplico, ordenadas por efectividad:

Técnica 1: Exigir Citación de Fuentes

Obliga al modelo a vincular cada afirmación con una fuente verificable:

Para cada afirmación que hagas, indica:
- Fuente: [cita el documento, línea de código, o sección específica]
- Si la afirmación se basa en conocimiento general sin fuente en el contexto proporcionado,
  márcala explícitamente como [CONOCIMIENTO_GENERAL - verificar]

Técnica 2: Niveles de Confianza Explícitos

Fuerza al modelo a calibrar su propia incertidumbre:

Al final de tu respuesta, incluye una sección "Evaluación de Confianza":

1. Afirmaciones de alta confianza (evidencia directa en el contexto): [lista]
2. Afirmaciones de confianza media (inferencias razonables): [lista]
3. Afirmaciones de baja confianza (especulación o conocimiento general no verificado): [lista]

Técnica 3: Verificación Cruzada Forzada

Para tareas críticas, ejecuta el mismo análisis dos veces con redacción diferente del prompt y compara resultados. Si hay divergencia, ambas respuestas son sospechosas:

# Prompt A (original)
Analiza este contrato y encuentra vulnerabilidades de reentrancy.

# Prompt B (reformulado)
Revisa este código y determina si es seguro contra ataques que involucren
llamadas externas recursivas antes de actualizar el estado interno.

Técnica 4: Zero-Knowledge Gate

Incluye una instrucción de “no sé” explícita que da permiso al modelo para declarar ignorancia:

Si encuentras una pregunta para la que no tienes información suficiente en el
contexto proporcionado, responde exactamente: "INFORMACIÓN_INSUFICIENTE: [describe qué falta]"
No intentes adivinar ni completar con conocimiento general.

7. Calibración de Temperature y Top-P por Caso de Uso

La temperature controla la entropía del muestreo del modelo: de ella depende la diferencia entre un output determinista (útil) y uno creativo (impredecible).

Caso de UsoTemperatureTop-PRazonamiento
Generación de código0.01.0Quieres el token más probable siempre. Cero creatividad.
Extracción de datos / Parsing0.0 - 0.11.0Mismo principio: determinismo absoluto.
Análisis técnico / Respuestas factuales0.1 - 0.30.95Mínima variación para evitar repeticiones literales.
Generación de texto profesional0.3 - 0.50.9Balance entre coherencia y naturalidad.
Brainstorming / Ideación0.7 - 0.90.9Diversidad de ideas. Puede requerir filtrado posterior.
Escritura creativa0.8 - 1.00.95Máxima variación estilística.

La regla práctica: si el output alimenta otro sistema, temperature = 0. Si es para consumo humano, temperature ≤ 0.5.


8. Protocolo de Iteración: A/B Testing de Prompts

Un prompt de producción no se escribe una vez. Se itera como cualquier otro componente de software. El protocolo:

Paso 1: Versiona tus Prompts

prompts/analisis_financiero/v1_prompt.txtv2_prompt.txtv3_prompt.txt (actual)generacion_contenido/v1.txtv2.txtresultados/test_analisis_financiero_v1_v2.mdtest_generacion_v1_v2.md

Paso 2: Define Métricas de Evaluación

Para cada prompt, define al menos 3 métricas cuantificables:

Prompt: generacion_informes_financieros
Métricas:
1. Precisión numérica: % de cifras que coinciden con los datos fuente
2. Formato válido: % de outputs parseables como JSON sin errores
3. Completitud: % de secciones requeridas presentes en el output

Paso 3: Test A/B con Mismo Input

Ejecuta ambas versiones con 10-20 inputs de prueba variados. Compara outputs lado a lado:

test_cases = load_test_cases("test_analisis_financiero.json")
results = {"v1": [], "v2": []}

for case in test_cases:
    for version in ["v1", "v2"]:
        prompt = load_prompt(f"analisis_financiero/{version}.txt")
        output = llm.generate(prompt.format(**case))
        metrics = evaluate(output, case["expected"])
        results[version].append(metrics)

compare_and_report(results)

Paso 4: Documenta la Decisión

Cada cambio de versión debe documentar qué cambió y por qué:

# v2 → v3: Análisis Financiero
Cambio: Añadida restricción de "NO especules sobre tendencias futuras"
Razón: v2 producía proyecciones no solicitadas en el 30% de los casos
Impacto: Precisión numérica subió de 92% a 97%. Formato válido: 100%.

9. Plantillas de Prompts de Referencia

Prompt de Análisis de Código

<system>
Eres un revisor de código senior. Tu función es encontrar bugs, vulnerabilidades
de seguridad y problemas de rendimiento. Sé específico: señala la línea exacta,
explica el problema, y proporciona la corrección.
</system>

<context>
Lenguaje: {lenguaje}
Framework: {framework}
Archivo: {nombre_archivo}
</context>

<code>
{codigo_a_revisar}
</code>

<task>
Revisa el código proporcionado y genera un informe estructurado.
</task>

<constraints>
- Solo informa de problemas reales, no de preferencias estilísticas
- Si no encuentras problemas, responde: {"hallazgos": [], "status": "limpio"}
- Para cada hallazgo, incluye la línea exacta y código de corrección
</constraints>

<output_format>
{
  "hallazgos": [
    {
      "severidad": "crítica|alta|media|baja",
      "linea": <número>,
      "categoria": "seguridad|bug|rendimiento|mantenibilidad",
      "descripcion": "<explicación concisa>",
      "codigo_actual": "<línea problemática>",
      "codigo_corregido": "<línea corregida>"
    }
  ]
}
</output_format>

Prompt de Síntesis de Documentos

<role>
Eres un analista de investigación especializado en sintetizar documentos
técnicos densos en resúmenes accionables para tomadores de decisiones.
</role>

<documents>
{documentos}
</documents>

<instructions>
1. Lee todos los documentos completamente
2. Identifica los 5 puntos clave más relevantes para {objetivo}
3. Para cada punto clave, indica en qué documento(s) aparece y la página exacta
4. Identifica contradicciones entre documentos (si las hay)
5. Genera 3 recomendaciones accionables basadas exclusivamente en la evidencia de los documentos
</instructions>

<output_format>
# Resumen Ejecutivo: {tema}

## 5 Puntos Clave
1. **{titulo punto 1}** — [Fuente: {documento}, p.{pagina}]
   {explicación de 2-3 líneas}

## Contradicciones Detectadas
- {si_no_hay: "No se detectaron contradicciones entre los documentos analizados."}

## 3 Recomendaciones Accionables
1. **{recomendación}** — Evidencia: {cita de documento}
</output_format>

<confidence>
Al final, indica tu nivel de confianza general (Alta/Media/Baja) y cualquier
limitación de tu análisis (documentos incompletos, temas fuera de tu conocimiento, etc.)
</confidence>

La Trampa del “Prompt Engineer”

Un apunte final: dominar el prompting avanzado es necesario pero no suficiente. El mercado está lleno de “prompt engineers” que saben escribir instrucciones elaboradas pero no saben integrar un LLM en un pipeline de producción, manejar rate limits, implementar retry logic, o diseñar una arquitectura de agentes.

Este manual es el Nivel 1 del framework de dominio de IA. Es la base sobre la que se construyen las capacidades de automatización (agentes-automatizacion.mdx) y los sistemas de delegación autónoma. Domínalo, pero no te quedes aquí. El valor real no está en prompts mejores; está en sistemas que ejecutan prompts sin ti.

“Saber prompting avanzado en 2026 es como saber HTML en 2005: necesario para existir en el ecosistema digital, insuficiente para liderarlo. La ventaja competitiva está en quien construye los sistemas, no en quien los opera manualmente.”

¿Te sirvió este artículo?
Compártelo con alguien que también lo necesite.