Saltar al contenido principal

Conjuntos de prompts

Definición

Los conjuntos de prompts son una técnica de prompting que genera múltiples formulaciones estructuralmente diferentes de la misma pregunta o tarea, las envía todas a un modelo de lenguaje y luego combina los resultados en una sola respuesta final. La intuición central se toma prestada de los conjuntos de aprendizaje automático clásico (bagging, boosting, stacking): ningún predictor individual es perfecto, pero un comité diverso de predictores imperfectos tiende a ser más fiable que cualquier miembro individual, porque sus errores son parcialmente no correlacionados y por tanto se cancelan en la agregación.

La distinción crítica entre los conjuntos de prompts y la autoconsistencia es la fuente de diversidad. En la autoconsistencia, ejecutas el mismo prompt N veces con temperatura > 0 y confías en el muestreo estocástico para producir caminos de razonamiento diversos. En los conjuntos de prompts, deliberadamente elaboras diferentes prompts —variando el encuadre, la asignación de rol, la formulación de la instrucción, los ejemplos de pocos disparos, o el formato de salida— y ejecutas cada uno (típicamente con temperatura 0 o baja) para producir resultados diversos pero deterministas. La autoconsistencia explota la varianza introducida por el muestreo; los conjuntos de prompts explotan la varianza introducida por el diseño del prompt. En la práctica, los dos enfoques son complementarios y pueden combinarse.

Los conjuntos de prompts son especialmente valiosos en dos escenarios. Primero, cuando no estás seguro de qué formulación de prompt es óptima para una tarea y no puedes evaluar alternativas a escala —ejecutar múltiples candidatos y votar sobre sus resultados te da el beneficio del mejor prompt sin tener que identificarlo de antemano. Segundo, cuando una tarea es de alto riesgo y el modo de falla de un solo prompt es inaceptable —un conjunto proporciona un rastro de auditoría suave, porque la distribución de votos entre diferentes respuestas es una señal directa de la incertidumbre del modelo. El costo principal es la latencia y los tokens: K variantes de prompts requieren K llamadas de inferencia, que pueden paralelizarse pero no eliminarse.

Cómo funciona

Estrategias de variación de prompts

La calidad de un conjunto depende en gran medida de la diversidad de las variantes del prompt. Si todas las variantes son superficialmente diferentes pero estructuralmente idénticas, el conjunto degenera hacia el muestreo repetido. Las estrategias de variación efectivas incluyen:

Variación de rol y persona. Asignar diferentes personas expertas (p. ej., "Eres un médico cauteloso", "Eres un científico de datos", "Eres un ingeniero pragmático") desplaza el conocimiento previo del modelo sobre respuestas plausibles y activa diferentes registros de conocimiento. La variación de roles es especialmente efectiva para tareas con múltiples encuadres válidos.

Variación en la formulación de la instrucción. La misma tarea puede formularse como una pregunta ("¿Cuál es el nivel de riesgo de...?"), un comando ("Evalúa el nivel de riesgo de..."), o una completación ("El nivel de riesgo de ... es"), y estas diferencias superficiales cambian mensurablemente la distribución de salida del modelo. Parafrasear la instrucción central es la forma de variación de menor esfuerzo.

Variación de ejemplos de pocos disparos. Usar diferentes conjuntos de ejemplos en contexto cambia qué parte del conocimiento del modelo activa el contexto de pocos disparos. Rotar a través de conjuntos de ejemplos extraídos de diferentes subdominios de la distribución de entrenamiento aumenta sustancialmente la diversidad del conjunto, especialmente para tareas de clasificación.

Variación de cadena de pensamiento vs. respuesta directa. Incluir una o más variantes de CoT junto con variantes de respuesta directa combina los beneficios de calidad de razonamiento de CoT con los beneficios de velocidad del prompting directo. Las variantes de CoT típicamente reciben más peso en la agregación porque son más fiables, pero las variantes directas pueden anular en casos donde CoT lleva al modelo a sobre-pensar preguntas simples.

Variación del formato de salida. Pedir la respuesta como un objeto JSON, como una lista numerada, o como una oración de texto libre puede generar diferentes niveles de precisión. Las variantes de salida estructurada son más fáciles de analizar y agregar programáticamente.

Métodos de agregación

Una vez que tienes K resultados, necesitas reducirlos a una sola respuesta. La elección del método de agregación debe coincidir con el tipo de salida:

El voto por mayoría funciona mejor para salidas discretas (etiquetas de clasificación, respuestas factuales cortas, selecciones de opción múltiple). Es robusto ante variantes adversariales o confusas, no requiere llamadas adicionales al modelo, y refleja directamente cómo opera la autoconsistencia. Los empates pueden romperse por log-probabilidad o deferiendo a una variante "de confianza" designada.

El promedio de puntuaciones es apropiado cuando cada variante devuelve una puntuación numérica o probabilidad en lugar de una etiqueta. El promedio es sensible a los valores atípicos; la agregación por mediana es más robusta cuando las variantes individuales pueden producir valores extremos.

La agregación por meta-prompt (LLM como juez) envía todos los K resultados a una segunda llamada al LLM que recibe instrucciones para sintetizar o seleccionar la mejor respuesta. Este es el método más poderoso pero más costoso, e introduce un segundo punto de falla del LLM. Es más útil cuando la tarea requiere generación de extremo abierto (resúmenes, código, ensayos) donde el voto por mayoría no es aplicable.

El voto ponderado asigna diferentes pesos a diferentes variantes basándose en su precisión histórica en un conjunto de validación reservado. Si tienes datos etiquetados y puedes medir qué variantes se desempeñan mejor, la ponderación supera significativamente al voto uniforme —pero requiere esfuerzo de calibración por adelantado.

Cuándo usar / Cuándo NO usar

Usar cuandoEvitar cuando
No estás seguro de qué formulación de prompt funciona mejor y no puedes evaluarlas individualmente a escalaLa latencia es una restricción estricta — K llamadas paralelas aún tienen la latencia de la llamada más lenta
La tarea es de alto riesgo y el modo de falla de un solo prompt es inaceptableEl presupuesto de tokens está severamente limitado y no puedes permitirte K completaciones
Los resultados de diferentes encuadres de prompts proporcionan perspectivas complementarias (p. ej., diagnóstico médico desde múltiples ángulos especializados)El modelo ya alcanza la precisión máxima con un solo prompt bien ajustado — rendimientos decrecientes
Quieres una señal de incertidumbre incorporada (distribución de votos = desacuerdo del modelo)El espacio de salida es continuo o de extremo abierto de una manera que hace que votar o promediar no tenga sentido
Estás construyendo un pipeline de producción donde la sensibilidad al prompt debe amortiguarseCareces de la infraestructura de ingeniería para ejecutar y agregar llamadas LLM paralelas

Comparaciones

CriterioConjuntos de promptsAutoconsistenciaPrompt único
Fuente de diversidadDiferentes diseños de promptsMuestreo estocástico de un promptNinguna
Número de llamadas al LLMK (número de variantes, típicamente 3–10)N (típicamente 10–40)1
TemperaturaBaja (0–0.3) por varianteAlta (0.5–0.8)Dependiente de la tarea
Mejora de precisiónAlta para tareas sensibles a la formulación del promptAlta para razonamiento de múltiples pasosLínea base
Requiere esfuerzo de ingeniería de promptsSí — diseñar variantes diversasNo — solo se necesita un promptModerado
Maneja salida de extremo abiertoSí, mediante agregación de meta-promptNo — el voto por mayoría requiere respuestas discretas
Mejor caso de usoTareas con sensibilidad al prompt o múltiples encuadres válidosMatemáticas, razonamiento simbólico, QA factualTareas simples y bien definidas con un buen prompt conocido

Ejemplos de código

Conjuntos de prompts con múltiples plantillas usando OpenAI

# Prompt ensembling: run K prompt variants and aggregate by majority vote
# pip install openai

import os
from collections import Counter
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

# Five structurally different prompt variants for the same classification task
PROMPT_VARIANTS = [
# 1. Direct instruction
"Is the following customer review positive, negative, or neutral? "
"Reply with exactly one word.\n\nReview: {review}",

# 2. Role-play framing
"You are a sentiment analysis expert. Classify the sentiment of the "
"review below as positive, negative, or neutral. Output only the label.\n\nReview: {review}",

# 3. Few-shot examples
"Review: 'The product broke in two days.' → negative\n"
"Review: 'Decent quality for the price.' → neutral\n"
"Review: 'Absolutely love it, will buy again!' → positive\n"
"Review: '{review}' →",

# 4. Chain-of-thought variant
"Analyze the sentiment of this review step by step, then state the "
"final label (positive / negative / neutral) on the last line.\n\nReview: {review}",

# 5. Completion framing
"The overall sentiment expressed in the review '{review}' is",
]


def call_variant(prompt: str, model: str = "gpt-4o-mini") -> str:
"""Call the LLM with a single prompt variant and return the raw response."""
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=0.0,
max_tokens=80,
)
return resp.choices[0].message.content.strip()


def extract_label(text: str) -> str | None:
"""Extract a sentiment label from raw model output."""
text_lower = text.lower()
for label in ("positive", "negative", "neutral"):
if label in text_lower:
return label
return None


def ensemble_sentiment(review: str) -> dict:
"""Run all prompt variants and aggregate by majority vote."""
raw_outputs, labels = [], []

for i, template in enumerate(PROMPT_VARIANTS):
prompt = template.format(review=review)
raw = call_variant(prompt)
label = extract_label(raw)
raw_outputs.append(raw)
if label:
labels.append(label)
print(f" Variant {i + 1}: {label!r} (raw: {raw[:60]!r})")

if not labels:
return {"answer": None, "votes": {}}

counts = Counter(labels)
winner, top_votes = counts.most_common(1)[0]
return {
"answer": winner,
"confidence": top_votes / len(labels),
"votes": dict(counts),
"raw_outputs": raw_outputs,
}


if __name__ == "__main__":
review = (
"The delivery was fast but the item looks nothing like the photos. "
"I'm disappointed and won't order again."
)
result = ensemble_sentiment(review)
print(f"\nFinal answer : {result['answer']}")
print(f"Confidence : {result['confidence']:.0%}")
print(f"Vote counts : {result['votes']}")

Conjunto ponderado con un conjunto de validación reservado

# Weighted prompt ensembling: calibrate variant weights from a validation set
# pip install openai scikit-learn

import os
from collections import defaultdict
from openai import OpenAI
from sklearn.metrics import accuracy_score

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])


def evaluate_variant(template: str, examples: list[dict]) -> float:
"""Return accuracy of a single prompt variant on a labeled dataset."""
preds = []
for ex in examples:
prompt = template.format(review=ex["text"])
raw = call_variant(prompt) # reuse function from above
preds.append(extract_label(raw) or "neutral")
return accuracy_score([ex["label"] for ex in examples], preds)


def weighted_ensemble(review: str, templates: list[str], weights: list[float]) -> str:
"""Aggregate variant outputs with per-variant weights."""
scores: dict[str, float] = defaultdict(float)
for template, weight in zip(templates, weights):
raw = call_variant(template.format(review=review))
label = extract_label(raw)
if label:
scores[label] += weight
return max(scores, key=scores.__getitem__) if scores else "neutral"


if __name__ == "__main__":
# Dummy validation set — replace with real labeled examples
val_set = [
{"text": "Great product!", "label": "positive"},
{"text": "Terrible quality.", "label": "negative"},
{"text": "It's okay I guess.", "label": "neutral"},
]
# Calibrate weights (accuracy on val set)
weights = [evaluate_variant(t, val_set) for t in PROMPT_VARIANTS]
print("Variant weights:", [f"{w:.2f}" for w in weights])

review = "Arrived on time but packaging was damaged."
answer = weighted_ensemble(review, PROMPT_VARIANTS, weights)
print("Weighted ensemble answer:", answer)

Recursos prácticos

Ver también