- 1. Introducción a Semantic Kernel con C#: Construyendo tu Primera Aplicación de IA
- 2.Creando Plugins Personalizados en Semantic Kernel
- 3. Clasificación de Intenciones con LLMs en .NET
- 4. Servicios de Chat Completion con Azure OpenAI y Semantic Kernel
- 5. Vector Embeddings y Búsqueda Semántica con .NET
- 6. Prompt Engineering: Mejores Prácticas para LLMs
- 7. Integración de Azure OpenAI en Aplicaciones .NET
- 8. Configuración de Temperatura y Tokens en Modelos LLM
- 9. Estrategias de Caché para Servicios de IA
- 10. Manejo de Errores en Aplicaciones de IA con .NET
- 11. Salida JSON Estructurada con LLMs
- 12. Testing de Servicios de IA en .NET
- 13. Inyección de Dependencias con Semantic Kernel
- 14. Comprensión de Consultas con Lenguaje Natural
- 15. Sistemas de Búsqueda Semántica en Producción
- 16. Configuración de HttpClient para Servicios de IA
- 17. Guardrails y Validación en Sistemas de IA
- 18. Workflows Multi-Paso con IA
- 19. Optimización de Costos en Aplicaciones de IA
- 20. Monitoreo y Observabilidad de Servicios de IA
- 21. Arquitectura de Microservicios con IA
- 22. Seguridad en Aplicaciones de IA
- 23. Implementación de Routers Conversacionales Inteligentes
- 24. Filtrado por Relevancia Semántica en Búsquedas
- 25. Normalización y Preprocesamiento de Datos para IA
Introducción
El prompt engineering es el arte de diseñar instrucciones efectivas para modelos de lenguaje. Un buen prompt puede ser la diferencia entre resultados mediocres y excepcionales. En este tutorial aprenderás técnicas probadas para crear prompts efectivos.
Principios Fundamentales
1. Claridad y Especificidad
❌ Prompt vago:
Escribe sobre perros
✅ Prompt específico:
Escribe un artículo de 500 palabras sobre los beneficios de tener un perro como mascota,
enfocándote en aspectos de salud mental, ejercicio físico y compañía.
2. Estructura Clara
var promptTemplate = """
CONTEXTO: Eres un experto en {{$dominio}}.
TAREA: {{$tarea}}
RESTRICCIONES:
- Máximo {{$maxPalabras}} palabras
- Usa ejemplos concretos
- Formato {{$formato}}
EJEMPLO:
{{$ejemplo}}
""";
3. Ejemplos (Few-Shot Learning)
var promptConEjemplos = """
Clasifica el sentimiento de estos mensajes como positivo, negativo o neutral.
Ejemplos:
- "Me encanta este producto" → positivo
- "No funciona bien" → negativo
- "Es de color azul" → neutral
Ahora clasifica: "{{$mensaje}}"
""";
Técnicas de Prompt Engineering
Chain-of-Thought (Cadena de Pensamiento)
Pedir al modelo que “piense paso a paso”:
var chainOfThoughtPrompt = """
Resuelve este problema paso a paso:
Problema: {{$problema}}
Piensa en voz alta y muestra tu razonamiento:
1. ¿Qué información tengo?
2. ¿Qué necesito calcular?
3. ¿Cómo lo resuelvo?
4. ¿Cuál es la respuesta final?
""";
Zero-Shot vs Few-Shot vs Many-Shot
// Zero-Shot: Sin ejemplos
var zeroShot = "Traduce al inglés: {{$texto}}";
// Few-Shot: Pocos ejemplos (2-5)
var fewShot = """
Traduce al inglés:
- "Hola" → "Hello"
- "Adiós" → "Goodbye"
- "{{$texto}}" →
""";
// Many-Shot: Muchos ejemplos (10+)
var manyShot = """
Traduce al inglés:
- "Buenos días" → "Good morning"
- "Buenas tardes" → "Good afternoon"
- "Buenas noches" → "Good night"
- "Por favor" → "Please"
- "Gracias" → "Thank you"
- "De nada" → "You're welcome"
[... más ejemplos ...]
- "{{$texto}}" →
""";
Role Prompting
Asignar un rol específico al modelo:
var rolePrompt = """
Eres un {{$rol}} con {{$experiencia}} años de experiencia.
Tu estilo de comunicación es:
- {{$estilo1}}
- {{$estilo2}}
- {{$estilo3}}
Responde a: {{$pregunta}}
""";
// Ejemplo concreto
var expertPrompt = """
Eres un arquitecto de software senior con 15 años de experiencia en sistemas distribuidos.
Tu estilo de comunicación es:
- Técnico pero accesible
- Usa ejemplos concretos
- Menciona trade-offs y consideraciones importantes
Responde a: ¿Cómo diseñarías un sistema de caché distribuido?
""";
Structured Output
Solicitar formato específico:
var structuredPrompt = """
Analiza el siguiente texto y responde en formato JSON:
{
"resumen": "string (máximo 100 palabras)",
"temas_principales": ["string"],
"sentimiento": "positivo|negativo|neutral",
"entidades": [{"nombre": "string", "tipo": "string"}],
"palabras_clave": ["string"]
}
Texto: {{$texto}}
""";
Patrones Avanzados
Template Method Pattern
public abstract class PromptTemplate
{
public string Build(Dictionary<string, string> variables)
{
var prompt = GetSystemMessage();
prompt += "\n\n" + GetTaskDescription(variables);
prompt += "\n\n" + GetConstraints();
prompt += "\n\n" + GetExamples();
prompt += "\n\n" + GetUserInput(variables);
return prompt;
}
protected abstract string GetSystemMessage();
protected abstract string GetTaskDescription(Dictionary<string, string> variables);
protected abstract string GetConstraints();
protected abstract string GetExamples();
protected abstract string GetUserInput(Dictionary<string, string> variables);
}
public class ClassificationPromptTemplate : PromptTemplate
{
protected override string GetSystemMessage()
{
return "Eres un clasificador experto que analiza texto y lo categoriza con precisión.";
}
protected override string GetTaskDescription(Dictionary<string, string> variables)
{
return $"Clasifica el siguiente texto en una de estas categorías: {variables["categories"]}";
}
protected override string GetConstraints()
{
return """
REGLAS:
- Selecciona solo UNA categoría
- Justifica tu decisión brevemente
- Si no estás seguro, indica tu nivel de confianza
""";
}
protected override string GetExamples()
{
return """
EJEMPLOS:
Texto: "Necesito un fontanero urgente"
Categoría: servicios_hogar
Confianza: 95%
Texto: "¿Dónde puedo comprar pan?"
Categoría: alimentación
Confianza: 90%
""";
}
protected override string GetUserInput(Dictionary<string, string> variables)
{
return $"Texto a clasificar: {variables["text"]}";
}
}
Prompt Chaining
Encadenar múltiples prompts para tareas complejas:
public class PromptChainService
{
private readonly Kernel _kernel;
public async Task<string> AnalyzeArticleAsync(string article)
{
// Paso 1: Extraer temas principales
var topicsPrompt = $"""
Extrae los 3 temas principales de este artículo.
Responde solo con la lista de temas, uno por línea.
Artículo: {article}
""";
var topics = await InvokePromptAsync(topicsPrompt);
// Paso 2: Resumir cada tema
var summaries = new List<string>();
foreach (var topic in topics.Split('\n'))
{
var summaryPrompt = $"""
Resume cómo se trata el tema "{topic}" en el siguiente artículo.
Usa máximo 50 palabras.
Artículo: {article}
""";
var summary = await InvokePromptAsync(summaryPrompt);
summaries.Add($"{topic}: {summary}");
}
// Paso 3: Crear resumen ejecutivo
var executiveSummaryPrompt = $"""
Basándote en estos resúmenes por tema, crea un resumen ejecutivo del artículo.
{string.Join("\n\n", summaries)}
""";
return await InvokePromptAsync(executiveSummaryPrompt);
}
private async Task<string> InvokePromptAsync(string prompt)
{
var function = _kernel.CreateFunctionFromPrompt(prompt);
var result = await _kernel.InvokeAsync(function);
return result.GetValue<string>() ?? "";
}
}
Self-Consistency
Generar múltiples respuestas y tomar la más común:
public class SelfConsistentService
{
private readonly Kernel _kernel;
public async Task<string> GetConsistentAnswerAsync(
string question,
int iterations = 5)
{
var answers = new List<string>();
var prompt = $"""
Responde la siguiente pregunta:
{question}
Piensa paso a paso y proporciona tu respuesta final.
""";
// Generar múltiples respuestas con temperatura alta
for (int i = 0; i < iterations; i++)
{
var settings = new OpenAIPromptExecutionSettings
{
Temperature = 0.8
};
var function = _kernel.CreateFunctionFromPrompt(prompt, settings);
var result = await _kernel.InvokeAsync(function);
answers.Add(result.GetValue<string>() ?? "");
}
// Encontrar respuesta más común o consenso
return FindConsensus(answers);
}
private string FindConsensus(List<string> answers)
{
// Implementación simplificada: retornar la más frecuente
return answers
.GroupBy(a => a)
.OrderByDescending(g => g.Count())
.First()
.Key;
}
}
Anti-Patrones (Qué Evitar)
❌ Prompts Ambiguos
// MAL
var malPrompt = "Háblame de eso";
// BIEN
var buenPrompt = """
Proporciona una explicación detallada sobre {{$tema}}, incluyendo:
1. Definición
2. Casos de uso principales
3. Ventajas y desventajas
4. Ejemplo práctico
""";
❌ Instrucciones Contradictorias
// MAL: Instrucciones que se contradicen
var contradictorio = """
Sé muy breve pero incluye todos los detalles posibles.
""";
// BIEN: Instrucciones claras y coherentes
var claro = """
Proporciona un resumen ejecutivo de 200 palabras que destaque
los 3 puntos más importantes.
""";
❌ Formato Inconsistente
// MAL
var inconsistente = """
dame info sobre:
Tema: {{$tema}}
quiero saber todo
formato: lista
""";
// BIEN
var consistente = """
TEMA: {{$tema}}
FORMATO REQUERIDO:
- Lista con viñetas
- Máximo 5 puntos
- Cada punto: 1-2 oraciones
PROFUNDIDAD:
Proporciona información intermedia, adecuada para alguien con
conocimientos básicos del tema.
""";
Prompts para Casos de Uso Comunes
Clasificación
var classificationPrompt = """
Clasifica el siguiente mensaje según su intención.
CATEGORÍAS POSIBLES:
- pregunta: El usuario hace una pregunta
- queja: El usuario expresa insatisfacción
- elogio: El usuario expresa satisfacción
- solicitud: El usuario pide algo específico
- otro: No encaja en las categorías anteriores
REGLAS:
1. Responde con UNA sola palabra (el nombre de la categoría)
2. Si hay duda entre dos, elige la más específica
MENSAJE: {{$mensaje}}
CATEGORÍA:
""";
Extracción de Información
var extractionPrompt = """
Extrae información estructurada del siguiente texto.
INFORMACIÓN A EXTRAER:
- Nombre de persona(s)
- Fechas
- Ubicaciones
- Organizaciones
- Números de contacto
FORMATO DE SALIDA:
{
"personas": ["string"],
"fechas": ["string"],
"ubicaciones": ["string"],
"organizaciones": ["string"],
"contactos": ["string"]
}
Si no encuentras información de algún tipo, usa un array vacío [].
TEXTO: {{$texto}}
JSON:
""";
Generación Creativa
var creativePrompt = """
Genera {{$tipo}} con las siguientes características:
ESTILO: {{$estilo}}
TONO: {{$tono}}
LONGITUD: {{$longitud}} palabras
AUDIENCIA: {{$audiencia}}
REQUISITOS:
- Original y creativo
- Apropiado para la audiencia
- Mantén el tono consistente
{{#if incluir_ejemplos}}
- Incluye ejemplos concretos
{{/if}}
TEMA: {{$tema}}
{{$tipo}}:
""";
Análisis y Resumen
var analysisPrompt = """
Analiza el siguiente contenido y proporciona:
1. RESUMEN (100 palabras máximo)
- Idea principal
- Puntos clave
2. ANÁLISIS
- Fortalezas del contenido
- Debilidades o áreas de mejora
- Público objetivo
3. RECOMENDACIONES
- 3 sugerencias específicas de mejora
CONTENIDO:
{{$contenido}}
---
ANÁLISIS:
""";
Testing de Prompts
public class PromptTester
{
private readonly Kernel _kernel;
public async Task<PromptTestResult> TestPromptAsync(
string promptTemplate,
Dictionary<string, string> testCases)
{
var results = new List<TestCase>();
foreach (var testCase in testCases)
{
var prompt = promptTemplate.Replace("{{$input}}", testCase.Value);
var function = _kernel.CreateFunctionFromPrompt(prompt);
var result = await _kernel.InvokeAsync(function);
var output = result.GetValue<string>() ?? "";
results.Add(new TestCase
{
Input = testCase.Value,
Output = output,
Expected = testCase.Key
});
}
return new PromptTestResult
{
TestCases = results,
SuccessRate = CalculateSuccessRate(results)
};
}
private double CalculateSuccessRate(List<TestCase> results)
{
// Implementar lógica de evaluación
return 0.0;
}
}
public class TestCase
{
public required string Input { get; init; }
public required string Output { get; init; }
public required string Expected { get; init; }
}
public class PromptTestResult
{
public required List<TestCase> TestCases { get; init; }
public double SuccessRate { get; init; }
}
Optimización de Prompts
A/B Testing
public class PromptOptimizer
{
private readonly Kernel _kernel;
public async Task<string> FindBestPromptAsync(
List<string> promptVariants,
List<string> testInputs)
{
var scores = new Dictionary<string, double>();
foreach (var prompt in promptVariants)
{
var totalScore = 0.0;
foreach (var input in testInputs)
{
var result = await TestPromptWithInputAsync(prompt, input);
totalScore += result.Quality;
}
scores[prompt] = totalScore / testInputs.Count;
}
return scores.OrderByDescending(kvp => kvp.Value).First().Key;
}
private async Task<(string Output, double Quality)> TestPromptWithInputAsync(
string prompt,
string input)
{
// Implementar testing y scoring
return ("", 0.0);
}
}
Iteración Basada en Feedback
public class PromptIterator
{
public string ImprovePrompt(
string originalPrompt,
List<PromptFeedback> feedbacks)
{
var improvements = new List<string>();
// Analizar feedback común
var commonIssues = feedbacks
.SelectMany(f => f.Issues)
.GroupBy(i => i)
.OrderByDescending(g => g.Count())
.Take(3)
.Select(g => g.Key);
foreach (var issue in commonIssues)
{
improvements.Add(GetImprovementForIssue(issue));
}
return ApplyImprovements(originalPrompt, improvements);
}
private string GetImprovementForIssue(string issue)
{
return issue switch
{
"too_vague" => "Agregar más especificidad y ejemplos",
"inconsistent" => "Estandarizar formato y estructura",
"too_long" => "Simplificar y reducir instrucciones",
_ => "Revisar claridad general"
};
}
private string ApplyImprovements(string prompt, List<string> improvements)
{
// Implementar lógica de mejora
return prompt;
}
}
public class PromptFeedback
{
public required string PromptVersion { get; init; }
public required List<string> Issues { get; init; }
public int Rating { get; init; }
}
Mejores Prácticas Resumidas
1. Estructura
- Usa secciones claramente delimitadas
- Instrucciones antes de datos
- Formato consistente
2. Claridad
- Sé específico sobre lo que quieres
- Proporciona ejemplos cuando sea útil
- Define el formato de salida esperado
3. Contexto
- Da contexto relevante al modelo
- Define el rol o perspectiva
- Establece restricciones claras
4. Testing
- Prueba con múltiples entradas
- Itera basándote en resultados
- Mantén registro de versiones
5. Temperatura
- Baja (0.0-0.3) para tareas determinísticas
- Media (0.4-0.7) para balance
- Alta (0.8-1.0) para creatividad
Conclusión
El prompt engineering es una habilidad esencial para trabajar efectivamente con LLMs. Buenos prompts son claros, estructurados y específicos. La práctica y la iteración basada en resultados te ayudarán a crear prompts cada vez más efectivos. Recuerda que no existe un “prompt perfecto” universal – cada caso de uso requiere adaptación y optimización.
Palabras clave: prompt engineering, LLM, GPT, Azure OpenAI, few-shot learning, chain-of-thought, structured output
Share this content: