
Cómo crear un asistente virtual con Python y ChatGPT: Guía práctica
Crear tu propio asistente virtual con inteligencia artificial ya no es una tarea reservada a grandes empresas. Gracias a herramientas como Python y las APIs de ChatGPT, hoy es posible construir un asistente funcional, personalizado y conectado a internet con solo unos pocos bloques de código. Esta guía te muestra cómo hacerlo paso a paso, sin necesidad de arquitecturas complejas ni conocimientos avanzados de machine learning.
Vamos a crear un asistente que pueda mantener una conversación, responder preguntas, realizar tareas simples y conectarse a servicios externos si lo deseas. A lo largo de esta guía aprenderás a:
Configurar tu entorno de desarrollo.
Utilizar la API de OpenAI con Python.
Diseñar un bucle conversacional básico.
Añadir funcionalidades adicionales.
El objetivo es que termines con un asistente completamente funcional y extensible. Vamos allá.
Paso 1: Instalación del entorno y dependencias
Para comenzar, asegúrate de tener Python 3.8 o superior instalado en tu sistema. Puedes comprobarlo ejecutando:
python --version
Es recomendable crear un entorno virtual para aislar las dependencias del proyecto. Abre una terminal, crea y activa el entorno:
python -m venv asistente-env
source asistente-env/bin/activate # En Linux o macOS
# En Windows usa:
# asistente-env\Scripts\activate
A continuación, instala las librerías necesarias:
pip install openai python-dotenv
Por último, necesitarás una clave de API de OpenAI para interactuar con ChatGPT. Crea un archivo .env en la raíz del proyecto y guarda allí tu clave:
OPENAI_API_KEY=tu_clave_aqui
Paso 2: Preparar el entorno de trabajo
Para comenzar a desarrollar tu asistente virtual, necesitas un entorno limpio y controlado. En este paso vamos a crear una carpeta de proyecto, activar un entorno virtual de Python, instalar las bibliotecas necesarias y añadir un archivo .env para gestionar tu clave de API de forma segura.
Primero, crea la carpeta del proyecto y activa un entorno virtual:
mkdir asistente-chatgpt
cd asistente-chatgpt
python -m venv venv
source venv/bin/activate # En Windows: venv\Scripts\activate
A continuación, instala las dependencias principales (openai para acceder a la API y python-dotenv para manejar configuraciones):
pip install openai python-dotenv
Después, crea el archivo .env en la raíz del proyecto y añade tu clave de OpenAI (puedes obtenerla en https://platform.openai.com/account/api-keys):
OPENAI_API_KEY=tu_clave_aqui
Por último, recuerda excluir el archivo .env del repositorio si usas Git:
echo ".env" >> .gitignore
Paso 3: Crear el archivo base y cargar la clave de API
Con el entorno preparado y la clave de OpenAI almacenada de forma segura, el siguiente paso es construir la estructura base del asistente. Empezaremos creando el archivo principal de ejecución y escribiendo el código necesario para conectarnos con la API de ChatGPT.
Crea un archivo llamado asistente.py en la raíz del proyecto.
Importa las bibliotecas necesarias: openai, os y dotenv.
Carga la clave desde el archivo .env para inicializar la API.
import os
import openai
from dotenv import load_dotenv
# Cargar las variables de entorno
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
Paso 4: Crear la función principal del asistente
Ahora vamos a crear la función que se encargará de enviar el mensaje del usuario a la API de ChatGPT y devolver la respuesta. Esta será la base del funcionamiento del asistente virtual.
Define una función llamada consultar_chatgpt(mensaje) que reciba un mensaje como parámetro.
Utiliza el modelo gpt-3.5-turbo y configura la estructura del mensaje como una conversación.
Devuelve la respuesta generada por la IA como texto plano para mostrarla al usuario.
Este enfoque básico permite tener ya una interacción funcional con el modelo. Más adelante añadiremos mejoras como control de errores y gestión de contexto.
def consultar_chatgpt(mensaje):
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": mensaje}
]
)
return respuesta["choices"][0]["message"]["content"]
Paso 5: Ejecutar el asistente en bucle desde la terminal
Una vez definida la función principal, podemos crear un pequeño bucle que permita al usuario interactuar con el asistente desde la línea de comandos. Esto convierte tu script en una herramienta funcional, lista para probar desde consola.
Añade un bloque if __name__ == "__main__" para ejecutar el asistente cuando se llame el script directamente.
Dentro, crea un bucle while que reciba la entrada del usuario, llame a la función consultar_chatgpt() y muestre la respuesta.
Permite salir del programa escribiendo "salir", "exit" o "quit".
Este modo conversacional es la forma más sencilla de empezar a usar tu asistente. Más adelante podrás ampliar esta lógica para integrarla en interfaces gráficas o web.
if __name__ == "__main__":
print("Escribe tu mensaje o 'salir' para terminar.")
while True:
entrada = input("Tú: ")
if entrada.lower() in ["salir", "exit", "quit"]:
break
salida = consultar_chatgpt(entrada)
print("Asistente:", salida)
Paso 6: Personalizar el comportamiento del asistente
Puedes modificar la personalidad y el rol del asistente utilizando un mensaje de tipo system, que se envía al modelo antes de iniciar la conversación. Esto influye en cómo responde, su tono y su especialización.
Define una lista mensajes que incluya un mensaje inicial del tipo "system".
A partir de ahí, cada mensaje del usuario se añade con el rol "user" y cada respuesta del modelo se almacena con el rol "assistant".
Esta estructura permite mantener un historial conversacional y que el asistente recuerde lo que se ha dicho antes durante la sesión.
Por ejemplo, puedes hacer que el asistente actúe como un tutor especializado, un guía turístico o un agente de soporte técnico, según tus necesidades.
mensajes = [
{"role": "system", "content": "Eres un asistente útil especializado en Python. Responde de forma clara y concisa."}
]
def consultar_chatgpt(mensaje):
try:
mensajes.append({"role": "user", "content": mensaje})
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=mensajes
)
contenido = respuesta["choices"][0]["message"]["content"]
mensajes.append({"role": "assistant", "content": contenido})
return contenido.strip()
except Exception as e:
return f"Ocurrió un error: {str(e)}"
Paso 7: Añadir entrada de voz para interactuar por micrófono
Para que la interacción con tu asistente sea más natural, puedes permitir que el usuario hable en lugar de escribir. En este paso vamos a integrar reconocimiento de voz en tiempo real usando la biblioteca SpeechRecognition.
Este módulo permite capturar audio desde el micrófono y transcribirlo a texto con servicios como la API de Google Speech, que es gratuita y no requiere clave para usos básicos.
Antes de empezar, instala las siguientes dependencias desde la terminal:
pip install SpeechRecognition pyaudio
Luego, crea una función reconocer_voz() que escuche desde el micrófono y devuelva el texto reconocido. Podrás usar esta función como sustituto del input() en tu asistente.
import speech_recognition as sr
def reconocer_voz():
r = sr.Recognizer()
with sr.Microphone() as source:
print("Habla ahora...")
audio = r.listen(source)
try:
texto = r.recognize_google(audio, language="es-ES")
print("Has dicho:", texto)
return texto
except sr.UnknownValueError:
print("No se entendió el audio")
return None
except sr.RequestError as e:
print("Error al conectar con el servicio de reconocimiento:", e)
return None
Paso 8: Guardar el historial de conversación en un archivo
Para mejorar la experiencia del usuario y permitir seguimiento de las conversaciones, es útil guardar cada interacción en un archivo local. Así podrás revisar después lo que el usuario preguntó y cómo respondió el asistente.
Vamos a crear dos funciones: una para guardar cada mensaje en un archivo .txt y otra para recuperar el historial al inicio del programa, si lo deseas.
Primero definimos la función guardar_en_historial() para registrar cada mensaje en un archivo de texto:
def guardar_en_historial(usuario, asistente, archivo='chat_log.txt'):
with open(archivo, 'a', encoding='utf-8') as f:
f.write(f'Usuario: {usuario}\n')
f.write(f'Asistente: {asistente}\n\n')
Y a continuación, cargar_historial() que permite leer ese historial desde disco y usarlo si se quiere para continuar la conversación:
def cargar_historial(archivo='chat_log.txt'):
try:
with open(archivo, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return ""
Después, modifica ligeramente el bucle principal del asistente para que llame a estas funciones tras cada intercambio.
if __name__ == "__main__":
historial = cargar_historial()
print("Escribe tu mensaje o 'salir' para terminar.")
while True:
entrada = input("Tú: ")
if entrada.lower() in ["salir", "exit", "quit"]:
break
salida = consultar_chatgpt(entrada)
print("Asistente:", salida)
guardar_en_historial(entrada, salida)
Paso 9: Añadir instrucciones al sistema para personalizar el comportamiento
El modelo de ChatGPT permite definir un mensaje de sistema inicial para condicionar el comportamiento del asistente durante toda la sesión. Este mensaje se envía de forma oculta al modelo y sirve como directriz: puedes usarlo para darle una personalidad concreta, limitar su ámbito de respuesta o ajustar su estilo.
Vamos a modificar nuestro código para incluir un mensaje de sistema que indique, por ejemplo, que el asistente es experto en Python y debe responder de forma clara y concisa. Para ello, cambiaremos la forma en que se construyen los mensajes enviados al modelo.
Primero, crea una lista inicial de mensajes que incluya el mensaje de sistema:
mensajes = [
{"role": "system", "content": "Eres un asistente útil especializado en Python. Responde de forma clara y concisa."}
]
Luego modifica la función consultar_chatgpt() para que esta lista crezca con cada nuevo intercambio y se mantenga el historial conversacional:
def consultar_chatgpt(mensaje):
try:
mensajes.append({"role": "user", "content": mensaje})
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=mensajes
)
contenido = respuesta["choices"][0]["message"]["content"]
mensajes.append({"role": "assistant", "content": contenido})
return contenido.strip()
except Exception as e:
return f"Ocurrió un error: {str(e)}"
Con esto lograrás que el asistente mantenga una coherencia de estilo, tono y ámbito durante toda la conversación, lo que resulta especialmente útil en proyectos temáticos, educativos o especializados.
Paso 10: Añadir entrada por voz desde el micrófono
Una forma más natural de interactuar con tu asistente es mediante comandos por voz. En este paso vamos a integrar reconocimiento de voz en tiempo real, para que puedas hablar al asistente y recibir respuestas sin usar el teclado.
Para lograrlo, utilizaremos la biblioteca SpeechRecognition, que permite capturar audio del micrófono y transcribirlo a texto usando la API de Google. También usaremos PyAudio como motor de acceso al hardware de entrada.
Primero, instala las dependencias necesarias:
pip install SpeechRecognition pyaudio
Luego, crea una función reconocer_voz() que active el micrófono, escuche tu voz y devuelva la transcripción:
import speech_recognition as sr
def reconocer_voz():
r = sr.Recognizer()
with sr.Microphone() as source:
print("Habla ahora...")
audio = r.listen(source)
try:
texto = r.recognize_google(audio, language="es-ES")
print("Has dicho:", texto)
return texto
except sr.UnknownValueError:
print("No se entendió el audio")
except sr.RequestError as e:
print("Error al conectar con el servicio de reconocimiento:", e)
Puedes integrar esta función dentro del flujo principal del asistente para ofrecer la opción de hablar en lugar de escribir. Por ejemplo, puedes mostrar un menú al usuario para elegir entre texto o voz, y en función de la elección, llamar a input() o a reconocer_voz().
Este tipo de interacción es especialmente útil para asistentes personales en móviles, kioscos o interfaces accesibles para personas con limitaciones de escritura.
Paso 11: Añadir persistencia básica del historial con archivos
Para dotar al asistente de una mínima memoria de conversación, puedes guardar los mensajes en un archivo local. De este modo, el asistente podrá recuperar interacciones anteriores y generar respuestas con un poco más de contexto.
En este paso aprenderás a registrar cada mensaje del usuario y del asistente en un archivo de texto (historial.txt) y a cargar ese contenido cuando inicies el programa. Aunque no será una memoria estructurada como una base de datos, permite retener información entre sesiones.
Primero, define una función para guardar cada intercambio en el historial:
def guardar_historial(usuario, asistente, archivo='historial.txt'):
with open(archivo, 'a', encoding='utf-8') as f:
f.write(f"Tú: {usuario}\n")
f.write(f"Asistente: {asistente}\n\n")
Después, otra función para cargar el historial desde el archivo al iniciar el programa:
def cargar_historial(archivo='historial.txt'):
try:
with open(archivo, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return ""
Finalmente, modifica el flujo principal del asistente para recuperar el historial, usarlo como parte del contexto (si así lo deseas), y actualizar el archivo después de cada respuesta.
if __name__ == "__main__":
historial = cargar_historial()
print("Escribe tu mensaje o 'salir' para terminar.")
while True:
entrada = input("Tú: ")
if entrada.lower() in ["salir", "exit", "quit"]:
break
salida = consultar_chatgpt(entrada)
print("Asistente:", salida)
guardar_historial(entrada, salida)
Este enfoque te permite mantener un registro simple y persistente de las conversaciones sin complicaciones técnicas. Más adelante podrás evolucionarlo a JSON o una base de datos relacional si lo necesitas.
Paso 12: Añadir memoria conversacional a corto plazo
Aunque guardar las conversaciones en un archivo es útil, no mejora las respuestas del asistente en tiempo real. Para lograr un comportamiento más natural, puedes implementar una memoria de corto plazo dentro de la misma sesión.
En este paso, aprenderás a mantener en memoria los últimos mensajes intercambiados con el asistente, enviándolos como contexto junto a cada nueva consulta. Esto permite que ChatGPT entienda mejor el flujo conversacional sin necesidad de acceso a archivos externos o bases de datos.
Primero, crea una lista global que actuará como historial temporal durante la ejecución del programa:
historial_conversacion = [
{"role": "system", "content": "Eres un asistente útil especializado en programación y Python. Responde de forma clara y breve."}
]
Luego, ajusta la función consultar_chatgpt() para incluir esa lista de mensajes, con un límite de elementos para no saturar el contexto:
def consultar_chatgpt(mensaje):
try:
historial_conversacion.append({"role": "user", "content": mensaje})
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=historial_conversacion[-6:] # limitar a las últimas 6 interacciones
)
contenido = respuesta["choices"][0]["message"]["content"]
historial_conversacion.append({"role": "assistant", "content": contenido})
return contenido.strip()
except Exception as e:
return f"Ocurrió un error: {str(e)}"
Finalmente, actualiza el bloque principal para mantener el flujo conversacional y actualizar la memoria de sesión:
if __name__ == "__main__":
print("Escribe tu mensaje o 'salir' para terminar.")
while True:
entrada = input("Tú: ")
if entrada.lower() in ["salir", "exit", "quit"]:
break
salida = consultar_chatgpt(entrada)
print("Asistente:", salida)
Esta memoria se borra al cerrar el programa, pero mejora mucho la calidad de la conversación mientras esté activa.
Paso 13: Guardar el historial de conversación en un archivo local
Si quieres conservar las conversaciones entre sesiones, puedes guardar el historial en un archivo de texto. Esto te permitirá registrar lo que se ha dicho y usar esa información para análisis, depuración o entrenamiento posterior.
En este paso, añadiremos dos funciones: una para guardar cada turno de conversación en un archivo y otra para cargar el historial completo si se desea reutilizar.
Primero, define la función que guarda los mensajes en un archivo de texto plano llamado chat_log.txt:
def guardar_en_historial(usuario, asistente, archivo='chat_log.txt'):
with open(archivo, 'a', encoding='utf-8') as f:
f.write(f'Usuario: {usuario}\n')
f.write(f'Asistente: {asistente}\n\n')
A continuación, puedes definir una función opcional para cargar el contenido completo del historial si necesitas consultarlo o usarlo como contexto:
def cargar_historial(archivo='chat_log.txt'):
try:
with open(archivo, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return ""
Estas funciones son especialmente útiles si quieres analizar conversaciones largas, auditar interacciones o construir una memoria persistente.
Paso 14: Añadir una interfaz por voz usando SpeechRecognition
Una forma de hacer más natural la interacción con tu asistente es habilitar el reconocimiento de voz. Para ello, utilizaremos la librería SpeechRecognition, que permite capturar audio desde el micrófono y convertirlo a texto usando servicios como Google Speech API.
Primero, asegúrate de tener instaladas las dependencias necesarias:
pip install SpeechRecognition pyaudio
A continuación, define una función reconocer_voz() que escuche por el micrófono y devuelva el texto transcrito. Añadiremos control de errores para mejorar la robustez del asistente:
import speech_recognition as sr
def reconocer_voz():
r = sr.Recognizer()
with sr.Microphone() as source:
print("Habla ahora...")
audio = r.listen(source)
try:
texto = r.recognize_google(audio, language="es-ES")
print("Has dicho:", texto)
return texto
except sr.UnknownValueError:
print("No se entendió el audio")
return None
except sr.RequestError as e:
print("Error al conectar con el servicio de reconocimiento:", e)
return None
Puedes integrar esta función con tu bucle conversacional para que, en lugar de teclear, el usuario pueda hablarle al asistente directamente.
Paso 15: Añadir persistencia básica de conversación con archivo de texto
Si quieres que tu asistente recuerde los mensajes anteriores durante la sesión o incluso entre ejecuciones, puedes implementar una persistencia básica utilizando archivos de texto. Esto permite almacenar el historial de conversación localmente y simular una memoria del asistente.
Vamos a crear dos funciones:
guardar_en_historial(): guarda cada turno de conversación en un archivo.
cargar_historial(): lee el contenido completo del historial para recuperarlo al iniciar.
Estas funciones permiten guardar lo que dice el usuario y el asistente, lo cual es útil para mantener el contexto o revisar sesiones anteriores.
def guardar_en_historial(usuario, asistente, archivo='chat_log.txt'):
with open(archivo, 'a', encoding='utf-8') as f:
f.write(f'Usuario: {usuario}\n')
f.write(f'Asistente: {asistente}\n\n')
def cargar_historial(archivo='chat_log.txt'):
try:
with open(archivo, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return ""
Después, puedes usar este historial como base de entrada para ChatGPT. Por ejemplo, puedes leer el historial antes de enviar la nueva consulta:
def ejecutar_asistente():
historial = cargar_historial()
while True:
prompt = input("Tú: ")
if prompt.lower() in ['salir', 'exit']:
break
entrada = f"{historial}Usuario: {prompt}\nAsistente:"
respuesta = obtener_respuesta(entrada)
print("Asistente:", respuesta)
guardar_en_historial(prompt, respuesta)
historial += f"Usuario: {prompt}\nAsistente: {respuesta}\n\n"
Este sistema de persistencia es simple pero muy eficaz para proyectos personales, y puede evolucionar fácilmente hacia almacenamiento en JSON o bases de datos si lo necesitas más adelante.
Paso 16: Añadir persistencia con archivos JSON para conservar el historial estructurado
Aunque guardar el historial en un archivo de texto plano es funcional, usar un archivo JSON ofrece una forma más estructurada de conservar los mensajes. Esto facilita operaciones como filtrar, ordenar o migrar el historial a otros formatos (como bases de datos).
Vamos a usar un archivo historial.json que almacenará una lista de diccionarios con los turnos de conversación. Cada mensaje tendrá al menos dos claves: role (usuario o asistente) y content (contenido del mensaje).
Primero, definimos dos funciones:
guardar_historial_json(): guarda el historial completo en el archivo.
cargar_historial_json(): carga el historial desde el archivo si existe, o lo inicializa si no.
import json
import os
HISTORIAL_JSON = "historial.json"
def guardar_historial_json(historial, archivo=HISTORIAL_JSON):
with open(archivo, "w", encoding="utf-8") as f:
json.dump(historial, f, ensure_ascii=False, indent=2)
def cargar_historial_json(archivo=HISTORIAL_JSON):
if os.path.exists(archivo):
with open(archivo, "r", encoding="utf-8") as f:
return json.load(f)
return []
Luego, al ejecutar el asistente, actualizamos el historial en memoria y lo guardamos tras cada interacción. También enviamos los últimos mensajes a la API para mantener el contexto.
def ejecutar_asistente_json():
historial = cargar_historial_json()
while True:
prompt = input("Tú: ")
if prompt.lower() in ['salir', 'exit']:
break
historial.append({"role": "user", "content": prompt})
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=historial[-6:] # Solo enviamos las últimas 6 interacciones
)
content = respuesta['choices'][0]['message']['content']
historial.append({"role": "assistant", "content": content})
guardar_historial_json(historial)
print("Asistente:", content)
Este enfoque permite conservar el historial entre sesiones, mantener el formato compatible con la API de OpenAI y escalar fácilmente hacia una base de datos o un sistema más avanzado en el futuro.
Paso 17: Añadir interfaz web con Gradio para facilitar el uso
Para que cualquier persona pueda interactuar fácilmente con tu asistente, puedes añadir una interfaz web básica usando Gradio. Esta librería permite construir interfaces visuales en pocos pasos, sin necesidad de HTML o JavaScript.
Vamos a crear una interfaz sencilla que permita introducir texto, enviar la consulta al asistente y mostrar la respuesta. Para ello:
Instala Gradio con pip install gradio.
Define una función que reciba el input del usuario y devuelva la respuesta generada.
Lanza una interfaz con gr.Interface.
import gradio as gr
import openai
import os
from dotenv import load_dotenv
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
# Memoria simple de la conversación
historial = []
def responder_gradio(mensaje):
historial.append({"role": "user", "content": mensaje})
mensajes_recientes = historial[-6:]
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=mensajes_recientes
)
contenido = respuesta["choices"][0]["message"]["content"]
historial.append({"role": "assistant", "content": contenido})
return contenido
Si quieres que la conversación tenga algo de contexto, puedes almacenar los últimos turnos de diálogo en una lista compartida, que Gradio actualizará en cada llamada.
Este enfoque resulta ideal para demos, asistentes personales o herramientas internas, y se puede combinar con despliegue en local o en la nube.
Paso 18: Añadir entrada de voz con Gradio y reconocimiento de audio
Además de una interfaz escrita, puedes incorporar entrada de voz a tu asistente web usando Gradio junto con la librería SpeechRecognition. Esto permite hablarle directamente al asistente usando el micrófono, lo que mejora la accesibilidad y la naturalidad del uso.
Para implementarlo:
Asegúrate de tener instalada la librería SpeechRecognition y sus dependencias.
Configura una función que tome como entrada audio y lo transcriba a texto.
Usa ese texto como input para consultar al asistente.
Devuelve la respuesta generada y opcionalmente la transcripción.
Primero instala las dependencias necesarias:
pip install SpeechRecognition
pip install pydub
Luego crea una función de transcripción:
import speech_recognition as sr
def transcribir_audio(audio):
recognizer = sr.Recognizer()
with sr.AudioFile(audio) as source:
audio_data = recognizer.record(source)
try:
texto = recognizer.recognize_google(audio_data, language="es-ES")
return texto
except sr.UnknownValueError:
return "No se entendió el audio."
except sr.RequestError:
return "Error al conectar con el servicio de reconocimiento."
Crea una función que use esa transcripción como entrada al asistente:
def responder_desde_audio(audio):
texto = transcribir_audio(audio)
if texto.startswith("Error") or texto.startswith("No se"):
return texto
historial.append({"role": "user", "content": texto})
mensajes_recientes = historial[-6:]
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=mensajes_recientes
)
contenido = respuesta["choices"][0]["message"]["content"]
historial.append({"role": "assistant", "content": contenido})
return f"Tú dijiste: {texto}\n\nAsistente: {contenido}"
Y finalmente, genera la interfaz con Gradio para capturar audio desde el micrófono:
# Interfaz por voz en Gradio
gr.Interface(
fn=responder_desde_audio,
inputs=gr.Audio(source="microphone", type="filepath"),
outputs="text",
title="Asistente Virtual por Voz",
description="Habla al asistente y recibe una respuesta basada en ChatGPT."
).launch()
Este tipo de funcionalidad es útil en entornos educativos, asistentes accesibles o interfaces móviles. Puedes extenderlo aún más incorporando síntesis de voz para que el asistente también hable.
Paso 19: Añadir comandos personalizados al asistente
Una forma sencilla de extender las capacidades de tu asistente es incorporar comandos personalizados que reconozca y ejecute antes de enviar la petición al modelo de lenguaje. Esto permite crear atajos, ejecutar funciones específicas o integrar utilidades propias.
En este ejemplo, implementaremos un sistema que detecta si el usuario escribe un comando como /hora o /saludo, y responde directamente desde el código sin necesidad de consultar a ChatGPT. Solo si no se trata de un comando, se enviará el mensaje al modelo.
Añade un bloque de lógica previa que detecte estas órdenes especiales y genere una respuesta inmediata. Puedes adaptar este sistema a tus propias necesidades o incluir comandos más avanzados conectados a APIs externas, sensores u otros servicios.
import datetime
def procesar_comando(mensaje):
if mensaje.startswith("/hora"):
return f"La hora actual es {datetime.datetime.now().strftime('%H:%M:%S')}"
elif mensaje.startswith("/saludo"):
return "¡Hola! ¿En qué puedo ayudarte hoy?"
else:
return None
# Uso combinado dentro del bucle principal
entrada = input("Tú: ")
respuesta = procesar_comando(entrada)
if respuesta is None:
respuesta = consultar_chatgpt(entrada)
print("Asistente:", respuesta)
Este enfoque ofrece una forma eficaz de ampliar funcionalidades sin necesidad de sobrecargar el modelo con tareas que puedes resolver directamente desde el código. Además, mejora el tiempo de respuesta y aporta una experiencia más natural para el usuario.
Paso 20: Añadir soporte multilenguaje al asistente
Una funcionalidad muy útil en asistentes conversacionales es la capacidad de operar en varios idiomas. Esto permite que el mismo asistente sea útil para usuarios de diferentes regiones o que se adapte automáticamente al idioma detectado en cada mensaje de entrada.
En este paso, implementaremos una función sencilla que detecta el idioma del mensaje del usuario utilizando la biblioteca langdetect. A partir de ese resultado, modificaremos dinámicamente el mensaje del sistema para que el modelo responda en el mismo idioma, manteniendo la coherencia en la conversación.
Antes de nada, asegúrate de instalar la biblioteca necesaria con:
pip install langdetect
Una vez instalada, puedes incorporar al flujo del asistente una lógica que detecte el idioma del mensaje y construya la instrucción adecuada para cada interacción:
from langdetect import detect
def consultar_chatgpt_multilenguaje(mensaje):
idioma = detect(mensaje)
sistema = {
"role": "system",
"content": f"Eres un asistente útil. Responde en el mismo idioma detectado: {idioma}."
}
mensajes = [sistema, {"role": "user", "content": mensaje}]
try:
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=mensajes
)
contenido = respuesta["choices"][0]["message"]["content"]
return contenido.strip()
except Exception as e:
return f"Ocurrió un error: {str(e)}"
Esta funcionalidad es especialmente útil en proyectos con alcance internacional o en asistentes diseñados para atender a usuarios multilingües. También puede ser la base para añadir funciones de traducción o adaptación cultural en pasos posteriores.
Paso 21: Añadir logging para depuración y trazabilidad
A medida que tu asistente virtual crece en complejidad, resulta útil registrar eventos clave del sistema para depurar errores o analizar el uso del asistente. En este paso, vamos a implementar un sistema básico de logging en Python para capturar eventos como errores, mensajes enviados o respuestas generadas.
El módulo estándar logging de Python permite guardar registros con distintos niveles de severidad (info, warning, error) en consola o archivos. Esto es ideal para depurar en tiempo real durante el desarrollo o para revisar incidentes en producción.
Vamos a añadir un archivo de configuración de logs (asistente.log) donde quedarán registrados los eventos principales, como la interacción del usuario y posibles errores en la respuesta de la API.
Una vez configurado el logging, puedes sustituir los print() del sistema por llamadas al logger correspondiente. Así tendrás trazabilidad sin ensuciar la salida estándar del programa, y podrás consultar los registros en cualquier momento.
import logging
# Configurar el logger
logging.basicConfig(
filename='asistente.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# Ejemplo dentro del bucle principal o función de consulta
logging.info(f"Usuario: {entrada}")
logging.info(f"Asistente: {salida}")
Paso 22: Controlar límites de tokens para evitar errores en la API
Cuando usas la API de ChatGPT, cada mensaje enviado y recibido consume una cantidad de tokens. Si el historial de conversación crece demasiado, puedes alcanzar el límite permitido por la API, lo que provocará errores en las respuestas o interrupciones del servicio.
En este paso vamos a implementar un control simple para evitar enviar demasiados tokens. La idea es medir la longitud aproximada de los mensajes acumulados y recortar los más antiguos cuando se supere un umbral.
Esto permite mantener una memoria conversacional fluida sin comprometer la estabilidad del asistente. No es una medición exacta, pero es útil como protección básica para entornos ligeros.
def estimar_tokens(mensajes):
total = 0
for mensaje in mensajes:
total += len(mensaje['content'].split())
return total
MAX_TOKENS = 3500
def preparar_historial_seguro(mensajes):
while estimar_tokens(mensajes) > MAX_TOKENS and len(mensajes) > 1:
# Elimina el mensaje más antiguo (después del system prompt si lo hay)
mensajes.pop(1)
return mensajes
Paso 23: Añadir configuración externa con archivo config.json
Para mejorar la flexibilidad del asistente, es útil externalizar ciertos parámetros en un archivo de configuración. De esta forma, puedes cambiar valores como el modelo de lenguaje, el número máximo de tokens o el sistema prompt sin modificar el código fuente.
En este paso crearemos un archivo config.json que almacenará esa configuración básica. Luego, leeremos ese archivo desde el script y adaptaremos el comportamiento del asistente en función de los valores definidos.
Este enfoque facilita ajustes rápidos, pruebas de distintos modelos y una mayor escalabilidad del proyecto.
{
"modelo": "gpt-3.5-turbo",
"max_tokens": 1000,
"system_prompt": "Eres un asistente útil que responde de forma clara y precisa."
}
import json
def cargar_configuracion(ruta="config.json"):
with open(ruta, "r", encoding="utf-8") as f:
return json.load(f)
config = cargar_configuracion()
modelo = config.get("modelo", "gpt-3.5-turbo")
system_prompt = {"role": "system", "content": config.get("system_prompt", "")}
max_tokens = config.get("max_tokens", 1000)
Paso 24: Conectar el asistente con una API externa
Para ampliar las capacidades de tu asistente virtual, puedes permitirle consultar APIs externas y ofrecer respuestas dinámicas basadas en información en tiempo real. Por ejemplo, puedes integrarlo con una API meteorológica, financiera o de noticias.
En este ejemplo, haremos una integración simple con la API de api.agify.io, que estima la edad de una persona a partir de su nombre. Verás cómo conectar con el servicio, procesar la respuesta y devolver la información al usuario.
Añadir este tipo de conexiones hace que tu asistente sea más útil y adaptable a casos de uso reales.
pip install requests
import requests
def obtener_edad(nombre):
url = f"https://api.agify.io?name={nombre}"
try:
response = requests.get(url)
if response.status_code == 200:
datos = response.json()
return f"{datos['name'].capitalize()} tiene una edad estimada de {datos['age']} años."
else:
return "No se pudo obtener la edad estimada."
except Exception as e:
return f"Error al consultar la API: {str(e)}"
while True:
entrada = input("Tú: ")
if entrada.lower().startswith("edad de"):
nombre = entrada[8:].strip()
print("Asistente:", obtener_edad(nombre))
elif entrada.lower() in ["salir", "exit"]:
break
else:
print("Asistente:", consultar_chatgpt(entrada))
Paso 25: Añadir interfaz gráfica básica con Gradio
Para facilitar el uso del asistente sin depender de la terminal, puedes crear una interfaz gráfica sencilla utilizando Gradio, una librería en Python que permite generar interfaces web interactivas de forma rápida.
Con Gradio, tu asistente podrá recibir entradas desde una caja de texto y mostrar las respuestas directamente en el navegador, lo que resulta útil para compartirlo con otras personas o integrarlo en presentaciones y demos.
En este paso:
Instalaremos gradio.
Crearemos una función responder() que actúe como interfaz entre el usuario y el modelo.
Lanzaremos la aplicación web desde Python.
pip install gradio
import gradio as gr
def responder(mensaje):
return consultar_chatgpt(mensaje)
gr.Interface(fn=responder, inputs="text", outputs="text", title="Asistente Virtual").launch()
Paso 26: Añadir soporte multilenguaje con traducción automática
Para ampliar la utilidad del asistente a usuarios de distintos países, podemos incorporar soporte multilenguaje. Esto se puede lograr añadiendo una capa de traducción automática que convierta los mensajes del usuario al inglés (idioma nativo de los modelos de OpenAI) y luego traduzca la respuesta del asistente al idioma original del usuario.
En este ejemplo, utilizaremos la API gratuita de LibreTranslate para realizar las traducciones. Puedes usar su instancia pública o desplegar tu propia versión si deseas más estabilidad.
Primero definimos una función que traduzca un texto entre dos idiomas usando LibreTranslate:
import requests
def traducir(texto, origen, destino):
url = "https://libretranslate.de/translate"
payload = {
"q": texto,
"source": origen,
"target": destino,
"format": "text"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
return response.json()["translatedText"]
Luego necesitaremos una función para detectar automáticamente el idioma del mensaje del usuario, también con la misma API:
def detectar_idioma(texto):
url = "https://libretranslate.de/detect"
payload = {"q": texto}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
return response.json()[0]["language"]
Por último, adaptamos la función principal del asistente para que realice la traducción automática en ambos sentidos (entrada y salida) siempre que el idioma del usuario no sea inglés:
def consultar_chatgpt_multilenguaje(mensaje_usuario):
idioma_origen = detectar_idioma(mensaje_usuario)
mensaje_en_ingles = traducir(mensaje_usuario, idioma_origen, "en")
respuesta_en_ingles = consultar_chatgpt(mensaje_en_ingles)
if idioma_origen != "en":
respuesta_traducida = traducir(respuesta_en_ingles, "en", idioma_origen)
else:
respuesta_traducida = respuesta_en_ingles
return respuesta_traducida
Este enfoque mejora la accesibilidad y facilita la adopción de tu asistente en contextos multilingües sin necesidad de crear múltiples versiones.
Paso 27: Integrar comandos personalizados en el asistente
Una forma útil de ampliar la funcionalidad de tu asistente es añadir comandos específicos que el sistema pueda reconocer y ejecutar antes de enviar la consulta a la IA. Esto permite responder rápidamente a instrucciones como “/hora”, “/limpiar”, “/ayuda” o cualquier otra acción programada.
Para empezar, definimos una función procesar_comando() que detecte si el usuario ha introducido un comando (por ejemplo, empezando por “/”) y ejecute una acción concreta en ese caso:
import datetime
def procesar_comando(comando):
if comando == "/hora":
return datetime.datetime.now().strftime("La hora actual es %H:%M")
elif comando == "/limpiar":
global conversation_history
conversation_history = []
return "Historial de conversación limpiado."
elif comando == "/ayuda":
return "Comandos disponibles:\n/hora - Muestra la hora actual\n/limpiar - Limpia el historial\n/ayuda - Muestra este mensaje"
else:
return None
Luego, dentro del bucle principal del asistente, podemos interceptar la entrada del usuario y comprobar si es un comando antes de enviarla al modelo:
entrada = input("Tú: ")
if entrada.startswith("/"):
salida = procesar_comando(entrada)
if salida:
print("Asistente:", salida)
continue # Saltar llamada a la API
# Si no es comando, continuar con la conversación
respuesta = consultar_chatgpt(entrada)
print("Asistente:", respuesta)
Esto permite combinar capacidades automatizadas con la potencia conversacional del modelo, proporcionando una experiencia más versátil y controlada. Puedes ampliar fácilmente la lógica de comandos para interactuar con APIs, ejecutar scripts o modificar parámetros internos del asistente.
Paso 22: Implementar comandos personalizados y respuestas programadas
Además de responder a preguntas abiertas, un asistente puede ser mucho más útil si le permitimos ejecutar comandos específicos. Esto permite que, por ejemplo, puedas pedirle que abra una web, te diga la hora o incluso controle otras aplicaciones de tu sistema.
En este paso vamos a integrar una capa básica de comandos dentro del flujo conversacional. El asistente interpretará ciertas frases como comandos y responderá de forma personalizada sin llamar a la API.
La lógica es sencilla: antes de enviar el mensaje del usuario a ChatGPT, comprobamos si contiene alguno de los comandos predefinidos. Si es así, devolvemos una respuesta directa programada en el propio código. Esto permite añadir utilidades sin necesidad de entrenar o depender del modelo de lenguaje.
def procesar_comando(mensaje):
comandos = {
"hora": "Lo siento, no tengo reloj interno, pero puedes consultar la hora en tu sistema.",
"web": "Puedo ayudarte a abrir una página web. ¿Cuál necesitas?",
"ayuda": "Estos son algunos comandos que puedes usar: hora, web, ayuda."
}
for comando, respuesta in comandos.items():
if comando in mensaje.lower():
return respuesta
return None
Con esta estructura puedes seguir ampliando los comandos según tus necesidades. También puedes combinar esto con funciones del sistema (como abrir aplicaciones) o con conectores a APIs externas (como consultar el tiempo).
def ejecutar_asistente():
print("Escribe tu mensaje o 'salir' para terminar.")
while True:
entrada = input("Tú: ")
if entrada.lower() in ["salir", "exit", "quit"]:
break
respuesta_comando = procesar_comando(entrada)
if respuesta_comando:
print("Asistente:", respuesta_comando)
else:
salida = consultar_chatgpt(entrada)
print("Asistente:", salida)
Paso 23: Conectar el asistente a servicios externos
Una de las grandes ventajas de tener un asistente personalizado es que puedes integrarlo con servicios externos, como APIs de clima, tareas, correo, bases de datos, etc. Esto convierte al asistente en algo realmente útil y práctico para el día a día o para automatizaciones profesionales.
En este paso vamos a ver cómo conectar el asistente con una API externa. Usaremos un ejemplo simple: consultar el clima actual en una ciudad mediante la API de OpenWeatherMap. Necesitarás crear una cuenta gratuita en https://openweathermap.org/ y obtener una clave de API.
Crearemos una función consultar_clima(ciudad) que obtendrá los datos del tiempo actual usando requests y los formateará para que el asistente pueda responder con naturalidad.
import requests
def consultar_clima(ciudad):
api_key = os.getenv("OPENWEATHER_API_KEY")
url = f"http://api.openweathermap.org/data/2.5/weather?q={ciudad}&appid={api_key}&lang=es&units=metric"
try:
response = requests.get(url)
datos = response.json()
if datos.get("cod") != 200:
return f"No pude obtener el clima de {ciudad}. Verifica el nombre."
clima = datos["weather"][0]["description"]
temp = datos["main"]["temp"]
return f"El clima en {ciudad} es '{clima}' con una temperatura de {temp}°C."
except Exception as e:
return f"Error al consultar el clima: {str(e)}"
Luego, modificaremos el procesamiento de comandos para detectar cuándo el usuario pregunta por el clima y extraer el nombre de la ciudad de su mensaje:
def procesar_comando(mensaje):
comandos = {
"hora": "Lo siento, no tengo reloj interno, pero puedes consultar la hora en tu sistema.",
"web": "Puedo ayudarte a abrir una página web. ¿Cuál necesitas?",
"ayuda": "Estos son algunos comandos que puedes usar: hora, web, ayuda."
}
for comando, respuesta in comandos.items():
if comando in mensaje.lower():
return respuesta
if "clima" in mensaje.lower():
palabras = mensaje.lower().split()
ciudad = palabras[-1] if len(palabras) > 1 else ""
return consultar_clima(ciudad)
return None
Con esto, el asistente será capaz de reconocer peticiones del tipo “¿Qué tiempo hace en Sevilla?” y ofrecer la respuesta directamente, sin pasar por el modelo de OpenAI.
Consejo: Puedes aplicar el mismo patrón para conectar con cualquier otra API: de noticias, de eventos, de correo, etc.
Paso 24: Integrar el asistente con Telegram
Una forma habitual de utilizar asistentes virtuales es a través de mensajería instantánea. En este paso aprenderás a conectar tu asistente con Telegram, permitiendo que cualquier usuario interactúe con él desde su móvil.
Para ello, necesitas crear un bot en Telegram con el BotFather y obtener un token de bot. Después, utilizaremos la librería python-telegram-bot para gestionar los mensajes.
Instala la librería:
pip install python-telegram-bot
Después, crea un nuevo archivo telegram_bot.py e implementa el siguiente código base:
from telegram.ext import ApplicationBuilder, MessageHandler, filters
import openai
import os
from dotenv import load_dotenv
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
telegram_token = os.getenv("TELEGRAM_BOT_TOKEN")
async def responder(update, context):
user_message = update.message.text
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": user_message}]
)
reply = response["choices"][0]["message"]["content"]
await update.message.reply_text(reply)
app = ApplicationBuilder().token(telegram_token).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, responder))
app.run_polling()
Recuerda añadir el nuevo token al archivo .env:
TELEGRAM_BOT_TOKEN=tu_token_aqui
Con esto, tu asistente podrá responder en tiempo real a los mensajes que reciba desde Telegram.
Paso 25: Añadir reconocimiento de voz con Whisper
Para mejorar la accesibilidad y permitir comandos por voz de forma avanzada, puedes integrar Whisper, el modelo de transcripción de OpenAI. A diferencia de SpeechRecognition, Whisper es más preciso y soporta múltiples idiomas.
Primero instala el paquete:
pip install openai-whisper
Luego, puedes transcribir un archivo de audio (por ejemplo, grabado con un botón en tu app web o móvil):
import whisper
modelo = whisper.load_model("base")
resultado = modelo.transcribe("audio.wav")
print(resultado["text"])
Puedes integrar esta transcripción directamente al flujo de conversación del asistente, sustituyendo al input de texto tradicional.
Paso 26: Crear una interfaz web con Gradio
Para usuarios sin conocimientos técnicos, una interfaz gráfica simple puede marcar la diferencia. Gradio es una excelente herramienta para crear interfaces web ligeras sin complicaciones.
Instala Gradio:
pip install gradio
Y crea una interfaz sencilla en un archivo web_app.py:
import gradio as gr
import openai
import os
from dotenv import load_dotenv
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
def responder(mensaje):
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": mensaje}]
)
return respuesta["choices"][0]["message"]["content"]
iface = gr.Interface(fn=responder, inputs="text", outputs="text", title="Asistente ChatGPT")
iface.launch()
Al ejecutar este archivo, se abrirá automáticamente una interfaz web desde la que podrás interactuar con tu asistente de forma visual y sencilla.
Conclusiones
Crear un asistente virtual con Python y ChatGPT es un proyecto accesible, escalable y altamente personalizable. A lo largo de esta guía hemos recorrido paso a paso desde la instalación del entorno hasta la integración con herramientas como Telegram, Whisper o Gradio. Cada fase te ha permitido construir un asistente más completo, capaz de entender lenguaje natural, mantener memoria conversacional y ejecutarse tanto en local como en la nube.
Has aprendido a utilizar la API de OpenAI de forma segura con variables de entorno, a gestionar errores comunes, a implementar almacenamiento de historial con JSON y SQLite, y a desplegar tu solución en entornos como Render, Replit o un VPS con Docker. Además, exploraste opciones de interacción por voz y por chat, ampliando las posibilidades de tu asistente en múltiples canales.
Este proyecto es una excelente base para seguir aprendiendo sobre inteligencia artificial aplicada, y puede evolucionar hacia productos reales de soporte, automatización o atención personalizada. Con las herramientas y prácticas que ya dominas, estás preparado para crear un asistente potente y crear nuevas funcionalidades, explorando nuevas APIs, integraciones o incluso modelos personalizados.
Construir tu propio asistente no es solo un reto técnico: es una puerta abierta a la innovación y a la creación de soluciones útiles para personas reales. ¡Enhorabuena por llegar hasta aquí!
Artículos relacionados

Dominando Java: guía para principiantes
Si acabas de aterrizar en el mundo de la programación y quieres aprender a trabajar con Java, esta guía es para ti.

Flutter para principiantes: un lenguaje multiplataforma top
En la era digital, la innovación constante redefine nuestra manera de interactuar con el mundo. Las aplicaciones móviles,

Introducción a la ciberseguridad: guía básica
En la era digital, donde la mayoría de nuestras actividades se realizan de forma online, proteger nuestra información se ha convertido en una necesidad primordial.&n