Instala, configura y consume mediante una app en Python Flask tus LLMs en Local con Jan IA GRATIS - Guía Completa
Índice de contenido
- Qué es un LLM y por qué tenerlo en local
- Diferencia entre LLM online y LLM local
- Ventajas de ejecutar modelos de lenguaje en tu propio equipo
- Requisitos para instalar un LLM en tu PC (Windows, macOS o Linux)
- Compatibilidad de Jan IA, Ollama
- Instalación paso a paso de un LLM local con jan.ia
- Cómo descargar tu primer modelo (ejemplo: Gemma)
- Configuración inicial y prueba del asistente local
- Cómo elegir el modelo local adecuado para ti
- Factores clave: propósito, tamaño y rendimiento
- Consejos basados en mi experiencia
- Qué hacer si el modelo se congela o no responde
- Modelos 4B vs 8B vs 12B: ¿Cuál usar y comparación con el poder de cómputo?
- Qué significan realmente 4B, 8B y 12B en un LLM
- Modelos 4B: ligeros y rápidos
- Modelos 8B: equilibrio entre potencia y eficiencia
- Modelos 12B: salto de calidad visible
- Comparativa rápida
- Cómo elegir el LLM adecuado
- Asistentes
- Proyectos
- Conversar directamente dentro del proyecto
- En resumen
- Activar un Servidor Local (Localhost)
- Configuración básica
- Haciendo una petición manual (CURL)
- Problemas comunes
- Resultado
- FAQs prácticas
- Chat App: App Flask con Python para conectarse a un LLM mediante Jan.ia
- Selección del framework
- Creación del proyecto en VS Code + Ambiente Virtual
- Instalar Flask y requests
- Hola Mundo
- Primeros pasos con Flask
- Conecta un LLM Local con Jan IA a una app en Python con Flask
- Activar el servidor local
- Controlador base para conectarse al LLM
- Mediante un formulario GET POST
- Consume LLM Local con Python/Flask y peticiones fetch
- Analizar una imagen
- Refactorización
- LM Studio
- Preguntas frecuentes (FAQ)
- Conclusión: la libertad de tener tu IA sin conexión
- Conociendo e instalando nuestros propios LLMs (IAs)
Los modelos de lenguaje (LLM - Large Language Model (Modelo de Lenguaje Grande)) ya no son exclusivos de grandes empresas o servicios en la nube. Hoy puedes instalar y ejecutar un LLM directamente en tu computadora, sin depender de internet ni de servidores externos. En esta guía te explico cómo hacerlo empleando Ask Jan.IA que es una herramienta de código libre, qué necesitas, como configurarla y cuáles son las mejores opciones si buscas privacidad y control total sobre tus datos.
Qué es un LLM y por qué tenerlo en local
Un LLM (Large Language Model) es un modelo de inteligencia artificial entrenado para comprender y generar texto. ChatGPT o Gemini son ejemplos populares, pero ambos funcionan en servidores remotos.
Cuando hablamos de LLM en local, nos referimos a ejecutar ese mismo tipo de modelo directamente en tu PC.
Los motivos para ejecutar tu propio asistente son tres: privacidad, control y personalización.
- Privacidad: nada sale de tu ordenador. Perfecto si trabajas con datos sensibles o propiedad intelectual.
- Control total: tú defines las instrucciones, los límites y hasta el tono de voz de tu asistente.
- Personalización extrema: puedes afinarlo con prompts diseñados por ti, entrenarlo con tus documentos o adaptar su “personalidad”.
Diferencia entre LLM online y LLM local
Un modelo online depende de una conexión constante y de la infraestructura del proveedor. Un modelo local, en cambio, corre dentro de tu máquina: tú descargas los LLMs y los ejecutas y controlas todo el entorno. Esto elimina la dependencia de terceros y te permite usar IA sin conexión, además, te da privacidad y coste cero (sin contar con el coste del equipo y de mantener la IA local ejecutándose).
Ventajas de ejecutar modelos de lenguaje en tu propio equipo
Tener un LLM local ofrece dos beneficios principales:
- Privacidad absoluta: tus datos nunca salen de tu equipo.
- Independencia económica: no hay suscripciones ni límites de uso.
Además, puedes personalizar el modelo, ajustar su contexto y adaptarlo a tareas específicas. En mi caso, lo utilizo para analizar capítulos de libros y hacer preguntas-respuestas sobre ellos sin subir el contenido a ningún servidor.
Requisitos para instalar un LLM en tu PC (Windows, macOS o Linux)
Ejecutar un modelo local requiere cierta potencia de cómputo. Cuanto más grande el modelo, más memoria y procesamiento necesitarás.
- Hardware recomendado: CPU, GPU y RAM mínima
- RAM: al menos 8 GB para modelos ligeros (2B–4B).
- GPU: recomendable con soporte CUDA o nvidia o Apple Silicon.
- Almacenamiento: entre 1 y 20 GB por modelo descargado.
Si tu equipo es limitado, puedes optar por modelos cuantizados (GGUF o GPTQ), que reducen tamaño y consumo de memoria.
Compatibilidad de Jan IA, Ollama
En mi caso uso Jan IA, una herramienta de código abierto muy similar a Ollama. Ambos permiten instalar y ejecutar modelos localmente, y son compatibles con Windows, macOS y Linux. se usa más para integrar los modelos en aplicaciones de todo tipo mediante peticiones HTTP mediante ejecución local, pero, tambien se puede usar mediante la tipica caja de texto para hacer consultas.
Instalación paso a paso de un LLM local con jan.ia
jan.ia está disponible en su página oficial y se instala igual que cualquier otro programa. En mi caso, utilicé la versión de Windows, pero el proceso es equivalente en macOS o Linux.
Cómo descargar tu primer modelo (ejemplo: Gemma)
Dentro del apartado Host, jan.ia muestra una lista de modelos disponibles. Basta con escribir el nombre del modelo que deseas instalar. Uno de los más recomendados es Gemma, desarrollado por Google y disponible de forma gratuita para uso local:

Configuración inicial y prueba del asistente local
Tras descargar el modelo, lo encontrarás en la sección Ya, donde puedes crear un asistente y asignarle el modelo que instalaste. Desde ese momento puedes interactuar con él igual que con ChatGPT, pero sin conexión. También puedes subir archivos y obtener respuestas contextuales:

Cómo elegir el modelo local adecuado para ti
Factores clave: propósito, tamaño y rendimiento
La elección depende de lo que necesites. Si buscas velocidad, elige un modelo pequeño (2B o 4B). Si priorizas calidad de respuestas, opta por modelos más grandes (7B o 13B), siempre que tu hardware lo permita.
- Modelos populares: Gemma, Llama, Mistral, Granite
- Gemma (Google): eficiente y fácil de instalar.
- Llama (Meta): excelente en comprensión y generación.
- Mistral: ligero y rápido, ideal para laptops.
- Granite (IBM): especializado en análisis de datos.
Recomendaciones para equipos con poca potencia
Usa modelos pequeños (Gemma 2B, Phi-3 Mini).
Cierra otras aplicaciones mientras ejecutas el LLM.
Consejos basados en mi experiencia
He probado varios modelos: Quyen, Llama, Granite y Gemma. Algunos funcionan muy bien, otros se ralentizan dependiendo del tamaño y de la memoria disponible. Si tu equipo no tiene demasiada potencia, evita modelos pesados; pueden congelarse o consumir todos los recursos.
Ajustes, rendimiento y solución de problemas comunes
Cómo optimizar el consumo de recursos
Desde el menú de Configuraciones → Settings, puedes limitar el contexto máximo y ajustar el número de hilos de CPU o el uso de GPU. Reducir el contexto mejora la velocidad sin afectar demasiado la coherencia de las respuestas.
Qué hacer si el modelo se congela o no responde
A veces el programa puede quedarse bloqueado. En esos casos, basta con cerrarlo y reiniciarlo. No siempre se trata de un error de hardware; a veces el modelo simplemente excede la memoria asignada.
Modelos 4B vs 8B vs 12B: ¿Cuál usar y comparación con el poder de cómputo?
Qué significan realmente 4B, 8B y 12B en un LLM
Si te has topado con nombres como LLama, Granite 4B o Gemma 12B y te preguntas qué significa ese numerito con la “B”, estás en el lugar correcto.
La “B” representa billones de parámetros: pequeñas conexiones neuronales que el modelo usa para razonar.
En términos simples: más B = mayor capacidad de comprensión y coherencia, pero también más consumo de VRAM y CPU.
Como siempre recomiendo, si tienes dudas sobre parámetros sobre temperatura, redactar las instrucciones sobre que LLM local emplear… en resumen… dudas de IA, el que mejor te puede ayudar es OTRA IA, pregúntale a una inteligencia artificial. ¿Quién mejor que una IA para resolver tus dudas sobre inteligencia artificial? Así de simple.
Modelos 4B: ligeros y rápidos
Perfectos si tienes 8–12 GB de VRAM o una GPU modesta.
En mis pruebas generando preguntas desde un capítulo de mi libro Coding Nader 4, el 4B respondía, pero con errores frecuentes: repeticiones, falta de contexto y preguntas superficiales.
Ideal para tareas simples: resúmenes breves, comandos o generación de texto básico.
Ventajas:
- Instalan rápido y consumen poco.
- Funcionan sin hardware de gama alta.
- Útiles para pruebas iniciales.
Limitaciones:
- Pérdida de coherencia en textos largos.
- Contexto limitado (se “pierde” en hilos complejos).
Modelos 8B: equilibrio entre potencia y eficiencia
Los 8B son el punto medio; mantienen velocidad aceptable con mejoras notables en gramática y razonamiento.
Aun sin llegar a la fluidez de 12B, ofrecen mejor comprensión semántica y menos repeticiones.
Si trabajas en proyectos educativos o de automatización ligera, un 8B puede darte el balance ideal: precisión razonable sin sobrecargar tu GPU.
Modelos 12B: salto de calidad visible
Cuando usé el 12B para entrenar mi asistente local, las preguntas y respuestas eran más coherentes, estructuradas y explicativas, en la de modelos anteriores como de 3B o 4B, al analizar mis libros o se quedaba pegado, o las preguntas y respuestas generadas no estaban bien estructuradas, no respetaba la estructura en las instrucciones y vale contar.
Ventajas:
Textos fluidos y con lógica extendida.
Ideal para creación de contenido y análisis complejos.
Mayor contexto: entiende referencias entre párrafos.
Desventajas:
Requiere ≥ 12 GB VRAM.
Tiempo de inferencia mayor.
Comparativa rápida
Modelo Parámetros VRAM mín. recomendada Ideal para Limitaciones
4B 4 mil M 6-8 GB Tareas simples, bots básicos Falta de contexto
8B 8 mil M 10-12 GB Equilibrio entre rapidez y calidad Aún limitado en razonamiento largo
12B 12 mil M 12-16 GB Generación avanzada, IA creativa
Cómo elegir el LLM adecuado
Define tu objetivo: ¿quieres generar texto, analizar datos o enseñar a tu IA a escribir?
Evalúa tu hardware: sin GPU potente, 4B o 8B serán más prácticos.
Mide resultados: genera el mismo prompt en 4B y 12B para comparar coherencia.
Prueba, ajusta y escala: empieza pequeño y sube cuando notes límites reales.
En mi caso, comencé con 4B para aprender y migré a 12B cuando necesitaba coherencia y análisis más profundos en mis asistentes de contenido.
No existe un ganador absoluto entre LLM 4B, 8B y 12B; todo depende de tu hardware y de lo que quieras lograr.
Si buscas velocidad, el 4B te basta; si buscas equilibrio, el 8B es perfecto y si deseas resultados que parezcan escritos por un experto, el 12B es tu aliado.
Mi consejo: empieza pequeño, mide resultados y escala.
Así aprovechas al máximo la inteligencia artificial sin desperdiciar recursos.
Asistentes
Los asistentes en Jan son el equivalente a las Gemas en Gemini o los GTP personalizados en Chat GTP, que en resumidas cuentas simplemente es una IA que entrenamos, dando instrucciones sobre que queremos que haga; por ejemplo, en mi caso, entrené una IA en la cual, le dije lo siguiente:
Generame las intrucciones para entrenar a una IA en la cual,
1 le voy a compartir cada uno de los capitulos de un libro, como fuente de entrada. luego, cuando le de la orden, le voy a pedir que me genere una lista de preguntas y respuesta en formato json con el siguiente formato de ejemplo:
{
"text": "¿Cuál es la capital de Francia?",
"question_type": "multiple_choice",
"options": [
"Madrid",
"Berlín",
"París",
"Roma"
],
"correct_answer_index": 2,
"book_section_id": 42,
"language": "es",
"tutorial_section_id": null
}
2 Finalmente, el propósito de este asistente es que me genere Genere una cantidad especificada de preguntas de selección simple, verdadero y falso, selección multiples (hasta 4) del contenido compartido anteriormente.
En resumen, le dije que le iba a dar un capitulo de uno de mis libros y que me generara preguntas y respuestas en base a un formato en leguaje natural; ahora, esto lo podemos mejorar, para que este optimizado, le pedio a una IA como Gemini o ChatGTP (dudas o formatos para IAs, pideselas a la IA) que me redactar las instrucciones para Jan.ia y me lo hizo perfectamente:
# Rol y Misión
Eres un Asistente Experto en Creación de Contenido Educativo. Tu misión es transformar el texto de un libro en un banco de preguntas y respuestas estructurado en formato JSON.
# FASE 1: Recepción de Contenido (Modo Contexto)
1. **Instrucción:** Recibirás el contenido del libro en fragmentos (capítulos).
2. **Acción:** Debes leer y almacenar **todo** el contenido recibido en tu memoria de contexto. No generes preguntas en esta fase.
3. **Respuesta al Usuario:** Tras cada fragmento, responde únicamente: "**Capítulo [Número/Título] almacenado. Listo para continuar o para FASE 2.**"# FASE 2: Generación de Preguntas (Modo Ejecución)
1. **Activación:** El usuario activará la generación con la orden explícita: **"COMENZAR GENERACIÓN JSON"**.
2. **Requerimiento:** El usuario especificará la **cantidad total de preguntas** y la **distribución de los tipos**.
3. **Fuente:** Las preguntas deben basarse **estrictamente** en el contenido cargado en la FASE 1.
4. **Formato de Salida OBLIGATORIO:**
* La respuesta completa debe ser un **único objeto JSON válido**.
* Todas las preguntas deben estar contenidas en un *array* JSON llamado `"banco_de_preguntas"`.### Tipos de Pregunta y Formato JSON Estricto
Cada objeto de pregunta debe seguir el siguiente esquema:
| Clave | Tipo de Dato | Reglas y Contenido |
| :--- | :--- | :--- |
| `"text"` | String | La pregunta generada. |
| `"question_type"` | String | Usar: **"multiple_choice"** (para 2 o 4 opciones) o **"true_false"**. |
| `"options"` | Array de Strings | Contiene las opciones. Para 'true\_false', siempre debe ser **`["Verdadero", "Falso"]`**. |
| `"correct_answer_index"` | Entero | El índice (empezando en **0**) de la respuesta correcta en `"options"`. |
| `"book_section_id"` | Entero/Null | El número del capítulo/sección de origen. Si no se especifica, usar **`null`**. |
| `"language"` | String | Siempre debe ser **`"es"`**. |
| `"tutorial_section_id"` | Null | Siempre debe ser **`null`**. |### Ejemplo de Output (Selección Múltiple)
```json
{
"banco_de_preguntas": [
{
"text": "¿Cuál es la capital de Francia?",
"question_type": "multiple_choice",
"options": [
"Madrid",
"Berlín",
"París",
"Roma"
],
"correct_answer_index": 2,
"book_section_id": 42,
"language": "es",
"tutorial_section_id": null
}
]
}
Listo para copiar y pegar pero, lo más interesante son las instrucciones. Esto es lo bonito de la IA: si redactamos unas instrucciones, por ejemplo utilizando Gemini, ChatGTP o cualquier otra, en principio, aunque puede que tengas que hacer algunas modificaciones, puedes copiarlas y pegarlas directamente. que claro esta que puedes editar a gusto.
Ya con esto, simplemente click en asistentes en la barra lateral y creo un asistente personalizado dando click en Add Assistant:

En el cuadro marcado con rojo, es donde coloca las intrucciones de tu IA personalizada, tu asistente a gusto.
Por lo demás, ya esta listo para emplear y para ello, al seleccionar una nueva conversación (New Chat, de la imagen anterior) en la parte superior podrás seleccionar cual asistente quieres emplear ya que, por defecto, ya existe un asistente llamado Jan.
Proyectos
Los proyectos. Otra característica muy interesante que tenemos aquí en Jan IA el uso de los proyectos, con los cuales podemos organizar nuestras conversaciones.
Por ejemplo, en mi caso que tengo una conversación por capítulos de mis libros, crear un proyecto para cada libro y tengo tantas conversaciones en ese proyecto como capítulos.
Creo que la utilidad de esto es bastante obvia —ya te acabo de mostrar un posible ejemplo— y básicamente es para eso. Simplemente vienes aquí a:
Projects

Y lo creas como siempre.
Es muy sencillo, al igual que ocurría cuando creábamos un nuevo asistente: hay un botoncito en la parte de gestión, en el apartado de asistentes. La interfaz es prácticamente la misma; lo único que cambia es el modelo con el que estamos trabajando: allí eran asistentes, aquí son proyectos.
Conversar directamente dentro del proyecto
Una vez seleccionado un proyecto, tienes igual una caja de texto, así que podrías preguntarle directamente desde allí, por ejemplo: hola. Al hacerlo, la conversación se crea directamente dentro del proyecto. Si vuelves a entrar, ya la ves organizada allí.
En resumen
Ahora puedes organizar tus conversaciones de manera muy cómoda, lo cual creo que es bastante útil precisamente por el tipo de uso que solemos darle a estos LLMs locales, donde queremos mantener todo más privado y tener la posibilidad de seguir conversaciones previas sin perderlas. Con esta funcionalidad, las puedes tener claramente organizadas.
Activar un Servidor Local (Localhost)
Una característica brutal que tenemos en Jan es la posibilidad de crear un servidor local completamente privado, ya sea en tu red personal o configurado como tú prefieras. Esto es, literalmente, lo que estás viendo por acá: en resumen, levanta un localhost.
Por más que aquí estemos interactuando desde el cliente, por detrás siempre está corriendo ese servidor, el cual podemos exponer para hacer lo que queramos, tal como veremos en este minicurso. Por ejemplo, vamos a crear una aplicación en Python (con Flask) que envíe una petición a nuestro servidor local para ejecutar una acción. Esa es la idea general.

Configuración básica
Básicamente, debes ir a Settings → Local API Server. Allí, antes de activarlo, puedes revisar lo siguiente:
- IP por defecto (puedes cambiarla si lo vas a exponer en una intranet, por ejemplo).
- Puerto, que también puedes modificar (por defecto es el 1337).
- Versión de la API.
- Clave secreta, que por defecto aparece vacía. Aquí debes colocar una clave para acceder.
Fíjate que en el ejemplo del cURL, se envía un Authorization: Bearer, así que ese secret es exactamente el que coloques aquí. Usa una clave seria si vas a usarlo en entornos profesionales o compartidos.
Una vez definido, simplemente presionamos Start Server... y listo.
Haciendo una petición manual (CURL)
En Windows, te recomiendo usar Git Bash. Te dejaré el comando para copiar y pegar:
curl http://127.0.0.1:1337/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer 12345" -d '{ "model": "gemma-3-12b-it-IQ4_XS", "messages": [{"role": "user", "content": "Tell me a joke."}] }'El formato de la petición es algo como:
- curl -X POST a la ruta /v1/chat/completions
- Content-Type: application/json
- Authorization: Bearer <tu_secret>
- El modelo que quieres usar, en mi ejemplo el de gemma-3-12b-it-IQ4_XS
- El mensaje que le quieres enviar
La parte más delicada puede ser el ID del modelo, que debe coincidir exactamente con el que aparece en la lista de modelos instalados. Actualmente, no hay un botón para copiar el nombre (al menos en esta versión), así que hay que copiarlo manualmente.
Problemas comunes
- Si el servidor no está levantado, te dará inmediatamente un error de conexión.
- En Windows, Git Bash funciona mejor que la terminal normal o PowerShell.
- Si tienes ocupado el puerto 1337, puedes cambiarlo sin problema.
Resultado
La respuesta será un JSON, que luego procesaremos. Pero lo importante es entender que, a partir de este punto, podemos conectar cualquier aplicación externa (PHP, Python, JavaScript, etc.) con nuestro servidor local.
Y justo eso será lo que haremos en la siguiente clase, creando nuestra primera aplicación conectada a Jan.
FAQs prácticas
¿Qué hardware necesito?
Cualquier PC moderno con al menos 8 GB de RAM puede correr modelos de 7 B cuantizados.
¿Puedo usar modelos en español?
Sí, hay modelos multilingües (Mistral, OpenHermes, Llama 3 Instruct).
¿Qué pasa si la IA no responde bien?
Ajusta las instrucciones. Como digo siempre:
“Si la IA no responde como quieres, simplemente ajusta las instrucciones. Todo depende de cómo quieras manejarlo.”
¿Y si quiero que ejecute acciones locales?
Puedes hacerlo mediante scripts Python o Node, pero recuerda aplicar whitelisting y logs de seguridad
Crear asistentes LLM locales es más fácil de lo que parece. Con un modelo ligero, un backend sencillo y prompts bien diseñados, puedes tener tu propio sistema de IA 100 % privado y personalizable.
Chat App: App Flask con Python para conectarse a un LLM mediante Jan.ia
Selección del framework
Lo siguiente que debemos decidir es qué framework utilizar. Los más conocidos son Django, Flask y FastAPI. Recordemos que el objetivo aquí es simplemente crear una aplicación que consuma o envíe una petición a cualquiera de las IA (LLMs) que tenemos instaladas localmente, y que devuelva algo; por ejemplo, un chat conversacional, como los que ya tenemos por acá.
- Django me parece demasiado grande para lo que queremos. Solo necesitamos una caja de chat, un controlador que haga la petición, reciba la respuesta, la analice y la muestre.
- FastAPI sería una excelente opción. Funciona como microframework, similar a Flask, pero lo considero un poco más complejo, con documentación más cambiante, y quiero mantener esto como una primera prueba.
- Flask, en cambio, no tiene la complejidad de Django y mantiene una sintaxis más estable que FastAPI, que sigue en fuerte desarrollo. Por ser un microframework, permite crear una aplicación mínima con solo lo necesario.
Por todo esto, usaré Flask.
Primer paso: crear un ambiente virtual
¿Qué es lo primero que hacemos al crear cualquier proyecto en Python? Crear un ambiente virtual. Esto permite que el proyecto esté aislado del resto del sistema operativo. Así podrás tener, por ejemplo, un proyecto con Django y otro con Flask, cada uno con sus propias dependencias.
Esto es fundamental.
Creación del proyecto en VS Code + Ambiente Virtual
Voy a abrir VS Code. Asumiré que ya tienes Python instalado, junto con el soporte para ambientes virtuales y crearemos el ambiente virtual en flask mediante VSC.
Creamos una carpeta vacía. En mi caso usaré:
jam/
└─ chat_01
Arrastro esa carpeta a VS Code antes de crear el entorno para evitar errores.
Presionamos Ctrl + Shift + P (o Command + Shift + P en Mac) en VSC y buscamos:
Create EnvironmentSelecciono Python como intérprete, y se empezará a crear el ambiente virtual automáticamente dentro de .venv.
Instalar Flask y requests
El siguiente paso es instalar Flask y un paquete que nos permitirá realizar peticiones HTTP que es la clave para poder conectarse al LLM en local:
$ pip install flask requestsHola Mundo
Crearemos una sencilla app tipo Hola Mundo en Flask:
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", port=5050)Primeros pasos con Flask
Recuerda que tengo formaciones totalmente gratuitas para ti: tanto el libro comunitario de Flask, como la versión gratuita del curso. Puedes acceder desde:
https://academia.desarrollolibre.net → apartado Cursos → busca Flask.
Incluso puedes ver los primeros módulos sin registrarte. Allí cubro:
- ¿Qué es Flask?
- Software necesario
- Hola Mundo en Python
- Repaso de Python
- Introducción a bases de datos
Este es el repositorio:
https://github.com/libredesarrollo/01-jan-chat
Conecta un LLM Local con Jan IA a una app en Python con Flask
En este apartado, vamos a conectarnos al LLM en Local.
Activar el servidor local
Antes de conectar, debemos activar el servidor Jan.IA:
Settings → Local App Server → establecer tu clave → Start
Controlador base para conectarse al LLM
En cuanto a lo principal, el controlador que se va a conectar al LLM, tenemos:
- URL y cabeceras
Definimos la URL del endpoint al que le haremos la petición:
http://localhost:port/v1/chat/completions
Y las cabeceras que Jam necesita:
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer 12345"
}Modelo → el que tengas seleccionado en Jam (debes escribirlo idéntico, ejemplo: yema-3-12b)
Mensaje → array JSON con el rol user y el contenido.
En este ejemplo: “cuéntame una broma”.
data = {
"model": "gemma-3-12b-it-IQ4_XS",
"messages": [
# {"role": "user", "content": request.form.get("prompt", "Tell me a joke.")}
{"role": "user", "content": prompt}
]
}Haciendo la petición
Como esto puede fallar, lo envolvemos en un try.
Realizamos un requests.post(...) enviando:
- URL
- headers
- json=data (no body, porque es JSON explícitamente)
Luego validamos la respuesta: si response.status_code == 200, todo perfecto.
- 404 sería ruta no encontrada.
- 500 = algo explotó en el servidor o mandaste algo inválido.
try:
# URL del servidor local de Jan.AI
url = "http://127.0.0.1:1337/v1/chat/completions"
# Hacemos la petición POST
response = requests.post(url, headers=headers, json=data, stream=False) # stream=False para respuestas completas
# Si responde con éxito
if response.status_code == 200:
return jsonify(response.json())
else:
return jsonify({
"error": f"Server responded with {response.status_code}",
"body": response.text
}), response.status_code
except Exception as e:
return jsonify({"error": str(e)}), 500Quedando como:
app.py
@app.route("/ask", methods=['GET', 'POST'])
def ask_model():
if request.method == 'GET':
return "Por favor, usa el formulario en la página de inicio para hacer una pregunta."
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer 12345"
}
# Obtenemos el prompt del cuerpo JSON de la petición
prompt = request.json.get("prompt", "Tell me a joke.")
# Cuerpo de la petición
data = {
"model": "gemma-3-12b-it-IQ4_XS",
"messages": [
{"role": "user", "content": request.form.get("prompt", "Tell me a joke.")}
{"role": "user", "content": prompt}
]
}
try:
# URL del servidor local de Jan.AI
url = "http://127.0.0.1:1337/v1/chat/completions"
# Hacemos la petición POST
response = requests.post(url, headers=headers, json=data, stream=False) # stream=False para respuestas completas
# Si responde con éxito
if response.status_code == 200:
return jsonify(response.json())
else:
return jsonify({
"error": f"Server responded with {response.status_code}",
"body": response.text
}), response.status_code
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", port=5050)Mediante un formulario GET POST
Para que sea interesante, vamos a generar un formulario para poder hacer la consulta y NO quede fija como la tenemos ahora:
"Tell me a joke."Le pedimos a la IA, por ejemplo a Gemini CLI como asistente de programación, que nos genera un formulario para consumir el LLM:
Genérame un formulario y controlador que permita conectarse al LLM que configuramos en la función de ask_model,
El formulario:
templates\form.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ask the LLM</title>
</head>
<body>
<h1>Pregúntale al LLM</h1>
<form action="/ask" method="post">
<textarea name="prompt" rows="4" cols="50" placeholder="Escribe tu pregunta aquí..."></textarea>
<br>
<button type="submit">Enviar</button>
</form>
</body>
</html>
Inicialmente Gemini lo definió el template dentro del contenedor y le solicite que lo genere en un archivo aparte:
Define el HTML_FORM en un archivo template aparte
El controlador anterior, queda exactamente igual ya que, desde el mismo, se verifica la respuesta:
request.form.get("prompt", "Tell me a joke.")}Consume LLM Local con Python/Flask y peticiones fetch
Para hacerlo mas interesante y poder almacenar los datos de las peticiones, vamos a hacer peticiones por fetch.
Le pedimos a Gemini CLI o el asistente que emplees:
Haz la petición mediante fetch en el form.html y NO uses un formulario
Cabíamos que ahora debemos de leer una petición JSON y no por FORM en el controlador, quedando como:
@app.route("/ask", methods=['GET', 'POST'])
def ask_model():
***
# Obtenemos el prompt del cuerpo JSON de la petición
prompt = request.json.get("prompt", "Tell me a joke.")
# Cuerpo de la petición
data = {
"model": "gemma-3-12b-it-IQ4_XS",
"messages": [
# {"role": "user", "content": request.form.get("prompt", "Tell me a joke.")}
{"role": "user", "content": prompt}
]
}
***Simplemente vario como recibe los datos, la variable llamada prompt.
Y en la vista:
templates\form.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ask the LLM (Fetch)</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: auto; padding: 20px; }
textarea { width: 100%; box-sizing: border-box; }
button { margin-top: 10px; padding: 8px 15px; }
#response-output {
margin-top: 20px;
padding: 15px;
background-color: #f4f4f4;
border-radius: 5px;
white-space: pre-wrap; /* Para respetar saltos de línea */
}
</style>
</head>
<body>
<h1>Pregúntale al LLM</h1>
<textarea id="prompt-input" rows="4" placeholder="Escribe tu pregunta aquí..."></textarea>
<br>
<button id="submit-btn">Enviar</button>
<h2>Respuesta:</h2>
<pre id="response-output">La respuesta del modelo aparecerá aquí...</pre>
<script>
document.getElementById('submit-btn').addEventListener('click', async () => {
const promptInput = document.getElementById('prompt-input');
const responseOutput = document.getElementById('response-output');
const prompt = promptInput.value;
if (!prompt.trim()) {
responseOutput.textContent = 'Por favor, escribe una pregunta.';
return;
}
responseOutput.textContent = 'Pensando...';
try {
const response = await fetch('/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: prompt })
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `Error del servidor: ${response.status}`);
}
const messageContent = data.choices[0].message.content;
responseOutput.textContent = messageContent;
} catch (error) {
responseOutput.textContent = `Error al contactar al servidor: ${error.message}`;
}
});
</script>
</body>
</html>Analizar una imagen
También, podemos analizar la imagen, para ello, debemos de proveer una URL de la imagen a analizar y la instrucción de lo que queremos hacer con ella:
@app.route("/analyze", methods=["GET"])
def analyze_image():
# image_path = request.json.get("path")
# image_url = "https://cdn.pixabay.com/photo/2025/09/12/15/10/small-copper-9830647_1280.jpg"
# # image_url = "https://www.desarrollolibre.net/public/images/course/laravel/laravel.webp"
# # Descargamos la imagen
# img_data = requests.get(image_url).content
# img_b64 = base64.b64encode(img_data).decode("utf-8")
# data_uri = f"data:image/webp;base64,{img_b64}"
# # Leer imagen local y convertir a base64
# # with open(image_path, "rb") as f:
# # image_b64 = base64.b64encode(f.read()).decode("utf-8")
# data = {
# "model": "gemma-3-4b-it-IQ4_XS", # solo texto
# "messages": [
# {
# "role": "user",
# "content": [
# {"type": "text", "text": "Describe this image."},
# # {"type": "image_url", "image_url": f"data:image/png;base64,{image_b64}"}
# # {"type": "image_url", "image_url": "https://www.desarrollolibre.net/public/images/course/laravel/laravel.webp"}
# {"type": "image_url", "image_url": data_uri}
# ]
# }
# ]
# }
data = {
"model": "gemma-3-4b-it-IQ4_XS",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image."},
{
"type": "image_url",
"image_url": {
"url": "https://cdn.pixabay.com/photo/2025/09/12/15/10/small-copper-9830647_1280.jpg"
}
}
]
}
]
}
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer 12345"
}
response = requests.post(
"http://127.0.0.1:1337/v1/chat/completions",
headers=headers,
json=data
)
return jsonify({
"error": f"Server responded with {response.status_code}",
"body": response.text
})Es el mismo código de antes, pero, ahora tiene una opción adicional para la imagen:
"image_url": {
"url": "https://cdn.pixabay.com/photo/2025/09/12/15/10/small-copper-9830647_1280.jpg"
}Refactorización
Le pedimos a Gemini CLI que nos ayudara con 3 puntos:
- Modularizando la aplicación: para guardar todas las rutas en un archivo aparte llamado chat_routes.py y que la conexión a la API lo hiciera mediante un método reutilizable llamado llm_service.py; de esta forma, todas las conexiones se hacen en un solo lugar.
- Estilo Chat: Tambien, le pedimos que el chat tuviera un estilo más acorde con los asistentes modernos, donde la información aparece arriba y la caja de texto se mantiene fija abajo con desplazamiento automático.
- Guardando mensajes en Local Storage: para los mensajes, que es un sistema de almacenamiento integrado en los navegadores.
LM Studio
LM Studio al igual que Jan.IA es otra excelente opción que tenemos a nuestra disposición para instalar IAs en local y también cuenta con un servidor local al igual que Jan.IA, por lo tanto, podemos utilizarlo también para nuestro proyecto en Flask SIN PRACTICAMENTE CAMBIOS, pero, a diferencia de Jan, LM Studio NO emplea un token BEARER de protección y por defecto su puerto es el 1234 (que puedes cambiar); en la siguiente tabla, te resumo lo comentado:
Diferencia Jan.AI LM Studio
URL por defecto http://localhost:1337 http://localhost:1234
API Key Necesaria si la activas No usa API Key
Compatibilidad Estilo OpenAI 100% OpenAI-compatible
Headers Content-Type + Authorization
Puedes descargar LM Studio desde:
Su funcionamiento es muy similar al de Jan IA, así que no te perderás, por lo demás, LM Studio al igual que Jan, también puedes conectarte exactamente igual, porque LM Studio expone una API 100% compatible con OpenAI en los cuales, tenemos algunos endpoints interesantes que podemos emplear:
- v1/chat/completions
- /v1/models
2. LM Studio no usa API KEY
Esto significa que debes quitar el header Authorization, porque si lo mandas, LM Studio lo ignora o te lanza 401 en algunos casos.
Preguntas frecuentes (FAQ)
- ¿Qué significa ejecutar un LLM en local?
Significa instalar y usar un modelo de lenguaje directamente en tu computadora, sin depender de servidores externos. - ¿Qué necesito para instalar un modelo de lenguaje en mi PC?
Un equipo con al menos 8 GB de RAM, espacio libre (5–20 GB) y preferiblemente una GPU compatible con CUDA o Metal. - ¿Cuál es el mejor LLM local para PC con poca RAM?
Modelos ligeros como Gemma 2B o Phi-3 Mini ofrecen buena calidad con bajo consumo. - ¿Puedo usar un LLM local sin conexión a internet?
Sí, una vez descargado el modelo, funciona totalmente offline. - ¿Qué ventajas tiene un LLM local frente a ChatGPT o Gemini?
Mayor privacidad, independencia económica y personalización del entorno. - ¿Cómo integrar un LLM local con Python o Jan IA?
Mediante APIs locales o librerías específicas que permiten conectarlo a tus propias aplicaciones.
Conclusión: la libertad de tener tu IA sin conexión
Ejecutar un LLM en local es una forma de recuperar control sobre la inteligencia artificial. Permite experimentar, proteger tus datos y adaptar la IA a tus propios proyectos.
No necesitas depender de grandes servicios: basta con un poco de curiosidad técnica y una herramienta como jan.ia, FM Studio u Ollama. Con ellas, tu computadora puede convertirse en un laboratorio privado de IA.
Acepto recibir anuncios de interes sobre este Blog.
Re voy a mostrar la guía definitiva para instalar y ejecutar tus propios Modelos de Lenguaje Grandes (LLMs) directamente en tu computadora (PC o Mac), crear asistentes, tips para emplear el LLM correcto y finalmente, un script en Python para crear un programa que envíe peticiones a tu LLM local.
Algunas recomendaciones:
Benjamin Huizar Barajas
Laravel Legacy - Ya había tomado este curso pero era cuando estaba la versión 7 u 8. Ahora con la ac...
Andrés Rolán Torres
Laravel Legacy - Cumple de sobras con su propósito. Se nota el grandísimo esfuerzo puesto en este cu...
Cristian Semeria Cortes
Laravel Legacy - El curso la verdad esta muy bueno, por error compre este cuando ya estaba la versi...
Bryan Montes
Laravel Legacy - Hasta el momento el profesor es muy claro en cuanto al proceso de enseñanza y se pu...
José Nephtali Frías Cortés
Fllask 3 - Hasta el momento, están muy claras las expectativas del curso
| 👤 Andrés Cruz
Por aquí tienes el listado completo de clases que vamos a cubrir en el libro y curso:
Conociendo e instalando nuestros propios LLMs (IAs)
-
1 ¡Adiós a la Nube! Instala y configura tus LLMs en Local con Jan IA GRATIS - Guía Completa
¿Cansado de depender de internet o de pagar suscripciones para usar una Inteligencia Artificial potente? ¡Es hora de tomar el control!
-
2 Modelos 4B vs 8B vs 12B: ¿Cuál usar y comparación con el poder de cómputo?
Exploramos qué significan realmente los números detrás de los modelos de inteligencia artificial: 4B, 8B y 12B. Te muestro cómo afectan la capacidad de razonamiento, la precisión de las respuestas y por qué algunos modelos requieren más poder de cómputo que otros.
-
3 Cómo Crear un Asistente Local de IA Paso a Paso | con Jan IA
Cómo generar asistentes como Gemini Gemas pero con los LLMs locales, paso a paso, para automatizar tareas como generar preguntas y respuestas de tus libros, mantener tu información privada y trabajar con modelos de propósito general.
-
4 Jan.ia, LLM locales, Agrupa chats en un PROYECTO para un flujo de trabajo más limpio
Mostramos la característica de Proyectos, con los cuales, podremos agrupar chats en un mismo lugar.
-
5 Jan.ia, LLM locales, Crea TU PROPIO Servidor Local - BRUTAL
Hablamos sobre como podemos crear nuestro proprio servidor local y hacer una petición mediante CURL.
-
6 Crear Proyecto en Flask para consumir el LLM en local
Hablamos sobre como podemos crear nuestro proprio servidor local y hacer una petición mediante CURL.
-
7 Hola Mundo en Flask - Conecta tus LLM locales #Python
Creamos el Hola mundo en Flask.
-
8 Conecta un LLM Local con Jan IA a una app en Python con Flask
Iniciamos el servidor local en Jan IA y creamos un controlador en Flask que realize una petición a la IA Local
-
9 Consume LLM Local con Python/Flask Mediante Formulario y peticiones fetch
Iniciamos el servidor local en Jan IA y creamos un controlador en Flask que realize una petición a la IA Local
-
10 Usar un LLM Local para Analizar una Imagen mediante IA y una app en Flask con Python
Creamos un controlador en Flask para analizar una imagen mediante una URL.
-
11 Refactorizar app Flask (LLM Local) con Gemini CLI 3 Prompt! - 11
Vamos a usar Gemini CLI para refactorizar la aplicación que consume un LLM local con Jan.IA: 1 prompt - Modularizar rutas app 2 prompt - UI como chat 3 prompt - Guardar en el local Storage
-
12 Usar Servidor Local LM Studio En Python/Flask para conectar LLM
Vamos a usar KM Studio en Lugar de Jan IA para conectarse mediante la app en Flask a OTRO