8. Responder en Base a Texto Propio - 1
8: Responder en Base a Texto Propio - 1
🎯 Tema: Construyendo Bases de Conocimiento Multiples para Chatbots Especializados
📚 Introducción: Del Archivo Único a la Biblioteca de Conocimiento
¡Hola muchachos! Hoy vamos a escalar nuestro proyecto: en lugar de tener un solo archivo de conocimiento, crearemos una biblioteca completa de información.
Analogía: Si antes teníamos un solo libro (info.txt), ahora tendremos una biblioteca con varios libros (info1.txt, info2.txt, etc.) que nuestro asistente puede consultar.
🔄 Parte 1: La Importancia de Usar Texto Plano (TXT)
¿Por qué TXT y no PDF?
Diagrama de Comparación:
┌─────────────────┐ ┌─────────────────┐
│ ARCHIVO PDF │ │ ARCHIVO TXT │
├─────────────────┤ ├─────────────────┤
│ Formato complejo│ │ Texto simple │
│ Necesita extraer│ │ Listo para usar │
│ │ │ │ │ │
│ PDF → Python │ │ TXT → Python │
│ │ (con librería)│ │ │ (directamente)│
│ ↓ │ │ ↓ │
│ Texto → Guardar│ │ Usar │
│ │ como TXT │ │ │
│ ↓ │ │ │
│ Leer TXT │ │ │
└─────────────────┘ └─────────────────┘
║ ║
║ ║
╚═══════════════════════════╝
│
▼
┌─────────────┐
│ OLLAMA │
│ (IA) │
└─────────────┘Problema con PDF:
# ❌ Más complejo, más pasos
import PyPDF2 # Necesitas instalar librería adicional
pdf = open("documento.pdf", "rb")
lector = PyPDF2.PdfReader(pdf)
texto = ""
for pagina in lector.pages:
texto += pagina.extract_text()
# Luego guardas como TXT o usas directamenteVentaja con TXT:
# ✅ Simple y directo
with open("documento.txt", "r", encoding="UTF-8") as archivo:
texto = archivo.read() # ¡Listo!Regla de oro para principiantes:
"Si puedes tener la información en TXT desde el principio, evita formatos complejos como PDF."
📚 Parte 2: Creando Nuestra Biblioteca de Archivos
Ejemplo de Estructura de Archivos:
Archivo 1: cursos.txt
CURSOS DE ANDERCODE:
Programación Web:
- API REST con Laravel: Aprende a crear APIs profesionales
- Laravel Blog Real: Desarrolla un blog completo desde cero
- JavaScript Moderno: Dominia ES6+, async/await, frameworks
Móviles:
- Flutter Completo: Apps iOS y Android con un solo código
- React Native: Desarrollo nativo con JavaScript
Base de Datos:
- Curso Básico de SQL: Desde cero hasta consultas avanzadas
- MongoDB para Principiantes: Bases de datos NoSQL
Bots y Automatización:
- Bots con WhatsApp: Automatiza mensajes y respuestas
- Bots con Python: Crea asistentes inteligentes
- Bots con Node.js: Backend para chatbots
Pagos y E-commerce:
- PayPal Integration: Integra pagos en tu aplicación
- Stripe API: Sistema de pagos profesionalArchivo 2: servicios.txt
SERVICIOS DE ANDERCODE:
Desarrollo a Medida:
- Aplicaciones Web Personalizadas
- Sistemas de Gestión Empresarial
- Plataformas E-learning
Consultoría:
- Arquitectura de Software
- Optimización de Bases de Datos
- Migración a la Nube
Mentoría:
- Sesiones 1:1 de Programación
- Revisión de Código
- Plan de Carrera en Tech
Precios:
- Desarrollo: $50/hora
- Consultoría: $80/hora
- Mentoría: $40/horaEstructura de carpetas:
mi_chatbot/
├── app.py
├── cursos.txt ← Archivo 1: Catálogo de cursos
├── servicios.txt ← Archivo 2: Servicios y precios
├── contacto.txt ← Archivo 3: Información de contacto
└── templates/
└── index.html🔧 Parte 3: Mejorando la Función de Carga
Versión Mejorada: Leer Múltiples Archivos
def cargar_contenido():
"""
Lee MÚLTIPLES archivos TXT y los combina en un solo texto
"""
archivos = ["cursos.txt", "servicios.txt", "contacto.txt"]
contenido_completo = ""
for nombre_archivo in archivos:
try:
with open(nombre_archivo, "r", encoding="UTF-8") as archivo:
contenido_completo += archivo.read() + "\n\n"
# \n\n añade espacio entre archivos
except FileNotFoundError:
print(f"⚠️ Advertencia: No se encontró {nombre_archivo}")
continue # Continúa con el siguiente archivo
return contenido_completoEsquema Visual de la Función:
┌─────────────────────────────────────┐ │ FUNCIÓN cargar_contenido() │ ├─────────────────────────────────────┤ │ 1. Lista de archivos a leer: │ │ ["cursos.txt", "servicios.txt"] │ │ │ │ 2. Para cada archivo en la lista: │ │ ├── Abrir archivo │ │ ├── Leer todo su contenido │ │ └── Añadir al total │ │ │ │ 3. Si un archivo no existe: │ │ └── Mostrar advertencia y │ │ continuar con los demás │ │ │ │ 4. Devolver todo el texto combinado│ └─────────────────────────────────────┘
Analogía:
Piensa en esta función como un bibliotecario que:
Sabe qué libros necesita (lista de archivos)
Toma cada libro de la estantería
Lee todas sus páginas
Junta todo en un gran informe
📏 Parte 4: ¡Cuidado con los Límites!
El Límite de Tokens/Contexto
¿Qué son los tokens?
1 token ≈ 0.75 palabras en español
100 tokens ≈ 75 palabras
Los modelos tienen límites (ej: 4096, 8192 tokens)
Ejemplo visual del límite:
┌─────────────────────────────────────────────────┐ │ LÍMITE DEL MODELO: 8000 CARACTERES │ ├─────────────────────────────────────────────────┤ │ │ │ cursos.txt │ servicios.txt │ contacto.txt │ │ (3000 chars) │ (2000 chars) │ (1000 chars) │ │ │ │ │ │ ─────────────────────────────────────────────── │ │ TOTAL: 6000 CARACTERES (DENTRO DEL LÍMITE) ✓ │ │ │ │ ─────────────────────────────────────────────── │ │ Si añadimos FAQ.txt (3000 chars): │ │ │ │ cursos.txt │ servicios.txt │ contacto.txt │ │ │ │ FAQ.txt │ │ ─────────────────────────────────────────────── │ │ TOTAL: 9000 CARACTERES (EXCEDE LÍMITE) ✗ │ └─────────────────────────────────────────────────┘
Consejo práctico:
# Verifica el tamaño aproximado
contenido = cargar_contenido()
print(f"Caracteres totales: {len(contenido)}")
print(f"Palabras aproximadas: {len(contenido.split())}")
# Si excede ~8000 caracteres, considera dividir
if len(contenido) > 8000:
print("⚠️ Advertencia: Podrías exceder el límite del modelo")💬 Parte 5: Pruebas con Múltiples Archivos
Tabla de Pruebas y Resultados:
| Pregunta | Archivos Consultados | Respuesta | ¿Correcto? |
|---|---|---|---|
| "Bríndame 5 cursos" | cursos.txt | Lista 5 cursos específicos | ✅ |
| "Cursos de Flutter" | cursos.txt | Menciona curso de Flutter | ✅ |
| "Precios de servicios" | servicios.txt | Muestra precios por hora | ✅ |
| "Cursos de PayPal" | cursos.txt | Menciona integración PayPal | ✅ |
| "¿Tienen mentoría?" | servicios.txt | Describe servicio de mentoría | ✅ |
Ejemplo de Conversación Completa:
Tú: ¿Qué cursos de programación web tienen?
IA: Ofrecemos: API REST con Laravel, Laravel Blog Real,
JavaScript Moderno. Todos incluyen proyectos prácticos.
Tú: ¿Cuánto cuesta la consultoría?
IA: El servicio de consultoría tiene un precio de $80/hora.
Incluye análisis de arquitectura y optimización.
Tú: ¿Y los bots con WhatsApp?
IA: Sí, tenemos el curso "Bots con WhatsApp" donde
aprendes a automatizar mensajes y respuestas.
Tú: ¿Qué es Python? (no está en los archivos)
IA: No está en el documento.🛠️ Parte 6: Mejoras en el Código
Versión Mejorada con Manejo de Errores:
def cargar_contenido_mejorada():
"""
Versión mejorada que maneja errores y verifica límites
"""
# Lista TODOS los archivos que quieres incluir
archivos_a_cargar = [
"cursos.txt",
"servicios.txt",
"contacto.txt",
# "faq.txt", # Puedes descomentar si añades más
# "testimonios.txt"
]
contenido_total = ""
archivos_cargados = []
for archivo in archivos_a_cargar:
try:
with open(archivo, "r", encoding="UTF-8") as f:
texto = f.read()
contenido_total += f"\n--- {archivo.upper()} ---\n"
contenido_total += texto + "\n"
archivos_cargados.append(archivo)
print(f"✓ Cargado: {archivo} ({len(texto)} caracteres)")
except FileNotFoundError:
print(f"✗ No encontrado: {archivo}")
except Exception as e:
print(f"⚠️ Error leyendo {archivo}: {str(e)}")
print(f"\n📊 RESUMEN: {len(archivos_cargados)}/{len(archivos_a_cargar)} archivos cargados")
print(f"📏 Total caracteres: {len(contenido_total)}")
if len(contenido_total) > 8000:
print("🔴 ADVERTENCIA: Podría exceder el límite del modelo")
return contenido_total💼 Parte 7: Aplicaciones Empresariales Reales
Ejemplos de Archivos para Diferentes Negocios:
# RESTAURANTE
menu.txt ← Platos, precios, ingredientes
horarios.txt ← Horas de atención, días especiales
ubicacion.txt ← Dirección, teléfono, mapa
# TIENDA ONLINE
productos.txt ← Catálogo con precios y descripciones
envios.txt ← Costos de envío, tiempos, zonas
garantias.txt ← Políticas de devolución y garantía
# CLÍNICA MÉDICA
servicios.txt ← Consultas, estudios, precios
doctores.txt ← Especialistas y horarios
seguros.txt ← Aseguradoras aceptadas
# ESCUELA
cursos.txt ← Materias, horarios, profesores
requisitos.txt ← Documentación necesaria
costos.txt ← Matrículas, mensualidadesBeneficios para Tu Negocio:
Respuestas consistentes: Todos reciben la misma información
Disponible 24/7: Atiende incluso fuera de horario
Escalable: Mismo esfuerzo para 10 o 10,000 consultas
Reducción de costos: Menos personal en atención al cliente
📝 Cuestionario de Repaso
Pregunta 1: ¿Por qué es mejor usar TXT que PDF para nuestra base de conocimiento?
a) Los PDF son más seguros
b) Los TXT se leen directamente sin conversión
c) Los PDF tienen mejores colores
Respuesta correcta: b
Pregunta 2: ¿Qué hace el \n\n al final de cada archivo leído?
a) Cierra el archivo
b) Añade espacio entre archivos (salto de línea doble)
c) Lo convierte a PDF
Respuesta correcta: b
Pregunta 3: Si tenemos 3 archivos de 3000 caracteres cada uno, ¿excedemos el límite de ~8000?
a) Sí (3000×3 = 9000)
b) No (3000×3 = 6000)
c) Depende del modelo
Respuesta correcta: a
Pregunta 4: ¿Qué significa "continue" en el bucle cuando un archivo no se encuentra?
a) Termina todo el programa
b) Salta ese archivo y continúa con los demás
c) Crea el archivo automáticamente
Respuesta correcta: b
Pregunta 5: ¿Para qué sirve el encoding="UTF-8" al abrir archivos?
a) Para leer archivos PDF
b) Para manejar correctamente tildes y caracteres especiales
c) Para hacerlos más rápidos
Respuesta correcta: b
💡 Consejos para Implementar en Tu Negocio:
Empieza pequeño: 1-2 archivos bien estructurados
Organiza por temas: Un archivo por categoría
Mantén actualizado: Revisa y actualiza periódicamente
Prueba con usuarios reales: Pide feedback de las respuestas
Monitorea el tamaño: No excedas los límites del modelo
🎉 ¡Tu Chatbot Ahora es un Experto en Varios Temas!
Logros de hoy:
✅ Aprendimos por qué TXT es mejor que PDF
✅ Creamos múltiples archivos de conocimiento
✅ Mejoramos la función de carga para varios archivos
✅ Entendimos los límites de tamaño
✅ Probamos con casos empresariales reales
Próximo paso: ¡Vamos a hacerlo aún más inteligente!
📂 Código Final Mejorado (app.py):
from flask import Flask, render_template, request
import requests
app = Flask(__name__)
conversation = []
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "gemma3:4b"
# --- FUNCIÓN MEJORADA para múltiples archivos ---
def cargar_contenido():
"""
Carga y combina MÚLTIPLES archivos TXT
"""
# Lista TODOS tus archivos de conocimiento aquí
lista_archivos = [
"cursos.txt", # Archivo 1: Catálogo de cursos
"servicios.txt", # Archivo 2: Servicios y precios
"contacto.txt" # Archivo 3: Información de contacto
]
contenido_combinado = ""
archivos_exitosos = 0
for archivo in lista_archivos:
try:
with open(archivo, "r", encoding="UTF-8") as f:
texto = f.read()
# Añade un separador con el nombre del archivo
contenido_combinado += f"\n\n[CONTENIDO DE {archivo.upper()}]:\n"
contenido_combinado += texto
archivos_exitosos += 1
print(f"✅ {archivo} cargado correctamente")
except FileNotFoundError:
print(f"⚠️ {archivo} no encontrado. Continuando...")
except Exception as e:
print(f"❌ Error leyendo {archivo}: {e}")
print(f"\n📊 Resumen: {archivos_exitosos}/{len(lista_archivos)} archivos cargados")
print(f"📏 Caracteres totales: {len(contenido_combinado)}")
# Advertencia si se acerca al límite
if len(contenido_combinado) > 7000:
print("🚨 ADVERTENCIA: Podrías acercarte al límite del modelo")
return contenido_combinado
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
user_input = request.form["user_input"]
conversation.append(("Tú", user_input))
try:
# Cargar TODOS los archivos
contexto = cargar_contenido()
# Crear prompt con todo el conocimiento
prompt_especializado = f"""
Eres un asistente especializado.
Responde SOLO basándote en la siguiente información.
Si la respuesta no está en la información, di "No está en el documento".
INFORMACIÓN DISPONIBLE:
{contexto}
PREGUNTA DEL USUARIO:
{user_input}
RESPUESTA:
"""
payload = {
"model": MODEL_NAME,
"prompt": prompt_especializado,
"stream": False
}
response = requests.post(OLLAMA_URL, json=payload, timeout=30)
if response.status_code == 200:
ai_response = response.json()["response"]
conversation.append(("IA", ai_response))
else:
conversation.append(("IA", "❌ Error al contactar con la IA"))
except Exception as e:
conversation.append(("IA", f"⚠️ Error del sistema: {str(e)}"))
return render_template("index.html", conversation=conversation)
if __name__ == "__main__":
app.run(debug=True, port=5000)🚀 ¡Ahora tienes un chatbot que conoce toda tu empresa! En la próxima clase exploraremos técnicas aún más avanzadas
Comentarios
Publicar un comentario