Cómo Usar Modelos de Lenguaje (LLMs) en Local con C# y Ollama
En el mundo del desarrollo de inteligencia artificial, trabajar con modelos de lenguaje en local es un reto. La mayoría de los ejemplos en internet están basados en APIs en la nube como OpenAI o Azure AI, pero ¿qué pasa si queremos independencia y privacidad? Ahí es donde entra Ollama, una plataforma que permite ejecutar modelos de IA localmente.
En este artículo te mostraré cómo logramos que modelos como Llama3, Mistral y Qwen2.5 funcionen correctamente en C#, con herramientas dinámicas, ejecución automática y una interfaz flexible. También comparto los errores en los que caímos y las soluciones que implementamos. ¡Porque aprender de los fallos es tan importante como de los éxitos!
💡 Objetivo del Proyecto
¿Qué queríamos lograr?
- Ejecutar modelos de lenguaje (LLMs) en local con Ollama.
- Integrarlos en una aplicación C# sin depender de APIs externas.
- Crear un sistema de herramientas personalizadas (
get_weather
,get_stock_price
...). - Permitir la selección dinámica de modelos y herramientas.
- Implementar un sistema de reintentos inteligentes cuando los modelos fallan en responder correctamente.
⚙️ Infraestructura y Configuración
📦 Modelos utilizados en Ollama
Estos son los modelos que instalamos y configuramos en local:
ollama pull llama3.2
ollama pull mistral
ollama pull qwen2.5
ollama pull gemma
Los modelos disponibles en nuestra instancia son:
- llama3.2
- mistral
- qwen2.5
- gemma
- llama3-groq-tool-use (versión especial de Llama3 optimizada para herramientas)
Cada uno tiene diferentes capacidades y responde de manera distinta a los prompts y herramientas.
🔧 Implementación en C#
Para hacer funcionar los modelos en C#, creamos varias clases especializadas que manejan la comunicación con Ollama y gestionan herramientas.
📜 Principales archivos y su función
Program.cs
→ Controla la ejecución del programa, menú interactivo y flujo de herramientas.OllamaModelBase.cs
→ Clase base para todos los modelos, define la estructura deHandleRequestAsync()
.MistralToolUse.cs
→ Adaptación de Mistral para que use herramientas de manera eficiente.Llama3ToolUse.cs
→ Implementación para Llama3 con herramientas personalizadas.QwenOllamaModel.cs
→ Especialización de Qwen2.5 para manejar herramientas de forma robusta.ConfigurationManager.cs
→ Crea el RequestBody dinámico para enviar a Ollama.ToolManager.cs
→ Gestiona herramientas comoget_weather
yget_stock_price
.
🛠️ Problemas y Soluciones
1️⃣ Error en la selección del modelo
Uno de los primeros errores fue que, al seleccionar un modelo en el menú, enviábamos un nombre incorrecto en la solicitud. Esto provocaba errores como:
"model 'QwenOllamaModel' not found, try pulling it first"
📌 Solución:
- Nos aseguramos de que el nombre del modelo en el RequestBody coincidiera con el nombre en Ollama.
- Ahora, en
Program.cs
, los modelos se referencian correctamente:
var modelHandlers = new Dictionary<string, OllamaModelBase>
{
{ "qwen2.5", new QwenOllamaModel() },
{ "mistral", new MistralToolUse() },
{ "gemma", new GenericOllamaModel() },
{ "llama3.2", new Llama3ToolUse() },
{ "llama3-groq-tool-use", new LlamaGroqToolUse() }
};
2️⃣ Mistral devolvía respuestas incorrectas o demasiado largas
Al principio, Mistral devolvía respuestas completas en lugar de llamar a las herramientas. En algunos casos, daba bloques de texto en lugar de usar get_weather
.
📌 Solución:
- Ajustamos los prompts en
PromptManager.cs
para que siempre usara herramientas:public static string GetSystemPrompt() { return "Eres un asistente con acceso a herramientas. Nunca respondas directamente si existe una herramienta que pueda proporcionar la información. Siempre usa las herramientas disponibles para responder."; }
- Implementamos reintentos inteligentes en
MistralToolUse.cs
para forzar el uso de herramientas si la primera respuesta no las incluía.
3️⃣ Qwen2.5 no ejecutaba herramientas
El modelo Qwen2.5 preguntaba por la ubicación antes de ejecutar get_weather
, lo que generaba bucles infinitos de reintentos.
📌 Solución:
- Incluimos la ubicación
Madrid
por defecto enMessageManager.cs
:public static string GetUserMessage(string toolName) { return toolName switch { "get_weather" => "Usa la herramienta 'get_weather' para decirme el clima en Madrid.", _ => "Usa la herramienta adecuada para responder mi pregunta." }; }
- Esto evitó que el modelo hiciera preguntas innecesarias antes de ejecutar la herramienta.
4️⃣ No se exportaba el código correctamente
Cuando intentamos implementar la opción de exportar código, CodeExporter.cs
no generaba code.txt
.
📌 Solución:
- Nos aseguramos de llamar correctamente a la función en
Program.cs
:static void ExportProjectCode() { CodeExporter.ExportCodeToTxt(Directory.GetCurrentDirectory()); Console.WriteLine("\n✅ Código exportado correctamente a 'code.txt'"); }
- Ahora el código se guarda correctamente sin incluir archivos innecesarios (
bin/
,obj/
).
🚀 Conclusión
Logramos implementar modelos de lenguaje locales en C# con Ollama de manera efectiva. Superamos errores clave y ahora podemos:
✅ Seleccionar modelos dinámicamente
✅ Ejecutar herramientas personalizadas (get_weather
, get_stock_price
)
✅ Evitar respuestas incorrectas de los modelos
✅ Exportar el código fuente automáticamente
Esto demuestra que es posible utilizar LLMs en local sin depender de la nube, mejorando privacidad, velocidad y control. 🔥
📌 Próximos pasos
🚀 Lo que viene en el proyecto:
- Hacer que funcione con
gemma
y mejorarqwen2.5
. - Crear un paquete NuGet para reutilizar la funcionalidad en otros proyectos.
- Implementar un servidor REST API, que reciba preguntas y haga las conexiones automáticamente.
📢 Si quieres seguir el desarrollo, revisa el repositorio en GitHub.
¿Te gustaría ver este proyecto evolucionar? Déjame tus comentarios. 🚀