- app.py +56 -114
- app2.py +114 -0
- entrenar.py +0 -0
app.py
CHANGED
|
@@ -1,114 +1,56 @@
|
|
| 1 |
-
import
|
| 2 |
-
import
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
#
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
Respuesta corta y precisa:
|
| 58 |
-
"""
|
| 59 |
-
|
| 60 |
-
# Tokenización con parámetros ajustados
|
| 61 |
-
inputs = tokenizer.encode_plus(
|
| 62 |
-
input_text,
|
| 63 |
-
return_tensors="pt",
|
| 64 |
-
max_length=1024,
|
| 65 |
-
truncation=True,
|
| 66 |
-
padding=True,
|
| 67 |
-
return_attention_mask=True
|
| 68 |
-
)
|
| 69 |
-
|
| 70 |
-
# Parámetros ajustados para generación de texto más coherente
|
| 71 |
-
response_ids = model.generate(
|
| 72 |
-
inputs["input_ids"],
|
| 73 |
-
attention_mask=inputs["attention_mask"],
|
| 74 |
-
max_new_tokens=150, # Aumentar el número de tokens generados
|
| 75 |
-
num_return_sequences=1,
|
| 76 |
-
no_repeat_ngram_size=2,
|
| 77 |
-
do_sample=True, # Cambiar a True para generar texto con variabilidad
|
| 78 |
-
top_p=0.9,
|
| 79 |
-
top_k=50,
|
| 80 |
-
temperature=0.8, # Aumento de la temperatura para una generación más flexible
|
| 81 |
-
pad_token_id=tokenizer.eos_token_id,
|
| 82 |
-
eos_token_id=tokenizer.eos_token_id,
|
| 83 |
-
early_stopping=True,
|
| 84 |
-
repetition_penalty=1.2 # Penalización de repetición
|
| 85 |
-
)
|
| 86 |
-
|
| 87 |
-
# Procesar la respuesta
|
| 88 |
-
response_text = tokenizer.decode(response_ids[0], skip_special_tokens=True).strip()
|
| 89 |
-
|
| 90 |
-
# Verificación básica
|
| 91 |
-
if len(response_text.strip()) < 10:
|
| 92 |
-
return {
|
| 93 |
-
"response": "Lo siento, necesito reformular la respuesta. ¿Podrías hacer la pregunta de otra manera?",
|
| 94 |
-
"contexto": input_text
|
| 95 |
-
}
|
| 96 |
-
|
| 97 |
-
return {"response": response_text, "contexto": input_text}
|
| 98 |
-
|
| 99 |
-
# ======== Función para ejecutar FastAPI en segundo plano =========
|
| 100 |
-
def run_api():
|
| 101 |
-
port = int(os.getenv("PORT", 7860))
|
| 102 |
-
uvicorn.run(app, host="0.0.0.0", port=port)
|
| 103 |
-
|
| 104 |
-
threading.Thread(target=run_api, daemon=True).start()
|
| 105 |
-
|
| 106 |
-
# ======== Interfaz con Streamlit =========
|
| 107 |
-
st.title("Mi Amigo Virtual 🤖")
|
| 108 |
-
st.write("Escríbeme algo y te responderé!")
|
| 109 |
-
|
| 110 |
-
contexto_defecto = "Historia de amor"
|
| 111 |
-
user_input = st.text_input("Tú:")
|
| 112 |
-
if user_input:
|
| 113 |
-
response = chat(Message(contexto=contexto_defecto, text=user_input))
|
| 114 |
-
st.write("🤖:", response["response"])
|
|
|
|
| 1 |
+
from datasets import Dataset
|
| 2 |
+
from transformers import GPT2Tokenizer, GPT2LMHeadModel, Trainer, TrainingArguments
|
| 3 |
+
|
| 4 |
+
# Formateamos las preguntas y respuestas en el formato adecuado
|
| 5 |
+
data = [
|
| 6 |
+
{
|
| 7 |
+
"input": "¿Cómo se conocieron Emmanuel y Rebeca?",
|
| 8 |
+
"output": "Rebeca y Emmanuel se conocieron en su primer día de trabajo cuando se estrecharon la mano..."
|
| 9 |
+
},
|
| 10 |
+
# Agrega más pares pregunta-respuesta aquí
|
| 11 |
+
]
|
| 12 |
+
|
| 13 |
+
# Crear el dataset
|
| 14 |
+
dataset = Dataset.from_dict({
|
| 15 |
+
'input': [entry['input'] for entry in data],
|
| 16 |
+
'output': [entry['output'] for entry in data]
|
| 17 |
+
})
|
| 18 |
+
|
| 19 |
+
# Cargar el tokenizer de GPT-2
|
| 20 |
+
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
|
| 21 |
+
|
| 22 |
+
# Tokenizar el dataset
|
| 23 |
+
def tokenize_function(examples):
|
| 24 |
+
return tokenizer(examples['input'], padding='max_length', truncation=True, max_length=512)
|
| 25 |
+
|
| 26 |
+
tokenized_datasets = dataset.map(tokenize_function, batched=True)
|
| 27 |
+
|
| 28 |
+
# Cargar el modelo GPT-2 Small
|
| 29 |
+
model = GPT2LMHeadModel.from_pretrained('gpt2')
|
| 30 |
+
|
| 31 |
+
# Configurar los parámetros de entrenamiento
|
| 32 |
+
training_args = TrainingArguments(
|
| 33 |
+
output_dir="./gpt2-small-finetuned", # Directorio para guardar el modelo
|
| 34 |
+
num_train_epochs=3, # Número de épocas (ajustable según el tamaño de tu dataset)
|
| 35 |
+
per_device_train_batch_size=2, # Tamaño del batch
|
| 36 |
+
per_device_eval_batch_size=2, # Tamaño del batch de evaluación
|
| 37 |
+
warmup_steps=500, # N��mero de pasos de calentamiento
|
| 38 |
+
weight_decay=0.01, # Decaimiento del peso
|
| 39 |
+
logging_dir='./logs', # Directorio para los logs
|
| 40 |
+
logging_steps=10,
|
| 41 |
+
save_steps=500, # Guardar el modelo cada 500 pasos
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Definir el trainer
|
| 45 |
+
trainer = Trainer(
|
| 46 |
+
model=model, # El modelo de GPT-2
|
| 47 |
+
args=training_args, # Los parámetros de entrenamiento
|
| 48 |
+
train_dataset=tokenized_datasets, # El dataset tokenizado
|
| 49 |
+
eval_dataset=tokenized_datasets, # El dataset de evaluación (puedes dividir tu dataset en entrenamiento y validación)
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
# Iniciar el entrenamiento
|
| 53 |
+
trainer.train()
|
| 54 |
+
|
| 55 |
+
# Guardar el modelo entrenado
|
| 56 |
+
trainer.save_model('./gpt2-small-finetuned')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app2.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import streamlit as st
|
| 3 |
+
from fastapi import FastAPI
|
| 4 |
+
from pydantic import BaseModel
|
| 5 |
+
from typing import List
|
| 6 |
+
import uvicorn
|
| 7 |
+
import threading
|
| 8 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 9 |
+
import torch
|
| 10 |
+
|
| 11 |
+
# ======== Cargar el modelo GPT-2 en español =========
|
| 12 |
+
tokenizer = AutoTokenizer.from_pretrained("PlanTL-GOB-ES/gpt2-large-bne")
|
| 13 |
+
model = AutoModelForCausalLM.from_pretrained("PlanTL-GOB-ES/gpt2-large-bne")
|
| 14 |
+
|
| 15 |
+
# Configurar el padding token y el modelo
|
| 16 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 17 |
+
model.config.pad_token_id = tokenizer.eos_token_id
|
| 18 |
+
|
| 19 |
+
# ======== Definir API con FastAPI =========
|
| 20 |
+
app = FastAPI()
|
| 21 |
+
|
| 22 |
+
class Pareja(BaseModel):
|
| 23 |
+
nombre_novio: str
|
| 24 |
+
nombre_novia: str
|
| 25 |
+
historia: str
|
| 26 |
+
frases: List[str]
|
| 27 |
+
anecdotas: List[str]
|
| 28 |
+
|
| 29 |
+
# Definir el modelo de solicitud que recibirá el JSON
|
| 30 |
+
class ChatRequest(BaseModel):
|
| 31 |
+
pareja: Pareja
|
| 32 |
+
pregunta: str
|
| 33 |
+
|
| 34 |
+
@app.post("/chat")
|
| 35 |
+
def chat(msg: ChatRequest):
|
| 36 |
+
nombre_novio = msg.pareja.nombre_novio
|
| 37 |
+
nombre_novia = msg.pareja.nombre_novia
|
| 38 |
+
historia = msg.pareja.historia
|
| 39 |
+
frases = ", ".join(msg.pareja.frases)
|
| 40 |
+
anecdotas = " ".join(msg.pareja.anecdotas)
|
| 41 |
+
pregunta = msg.pregunta
|
| 42 |
+
|
| 43 |
+
# Mejorar el formato del prompt con instrucciones claras
|
| 44 |
+
input_text = f"""
|
| 45 |
+
Eres un asistente virtual especializado en responder preguntas sobre la pareja {nombre_novio} y {nombre_novia}. Usa la siguiente información para responder de manera precisa y cercana:
|
| 46 |
+
|
| 47 |
+
Historia de la pareja:
|
| 48 |
+
{historia}
|
| 49 |
+
|
| 50 |
+
Frases memorables de la pareja:
|
| 51 |
+
{frases}
|
| 52 |
+
|
| 53 |
+
Momentos especiales juntos:
|
| 54 |
+
{anecdotas}
|
| 55 |
+
|
| 56 |
+
Pregunta: {pregunta}
|
| 57 |
+
Respuesta corta y precisa:
|
| 58 |
+
"""
|
| 59 |
+
|
| 60 |
+
# Tokenización con parámetros ajustados
|
| 61 |
+
inputs = tokenizer.encode_plus(
|
| 62 |
+
input_text,
|
| 63 |
+
return_tensors="pt",
|
| 64 |
+
max_length=1024,
|
| 65 |
+
truncation=True,
|
| 66 |
+
padding=True,
|
| 67 |
+
return_attention_mask=True
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
# Parámetros ajustados para generación de texto más coherente
|
| 71 |
+
response_ids = model.generate(
|
| 72 |
+
inputs["input_ids"],
|
| 73 |
+
attention_mask=inputs["attention_mask"],
|
| 74 |
+
max_new_tokens=150, # Aumentar el número de tokens generados
|
| 75 |
+
num_return_sequences=1,
|
| 76 |
+
no_repeat_ngram_size=2,
|
| 77 |
+
do_sample=True, # Cambiar a True para generar texto con variabilidad
|
| 78 |
+
top_p=0.9,
|
| 79 |
+
top_k=50,
|
| 80 |
+
temperature=0.8, # Aumento de la temperatura para una generación más flexible
|
| 81 |
+
pad_token_id=tokenizer.eos_token_id,
|
| 82 |
+
eos_token_id=tokenizer.eos_token_id,
|
| 83 |
+
early_stopping=True,
|
| 84 |
+
repetition_penalty=1.2 # Penalización de repetición
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
# Procesar la respuesta
|
| 88 |
+
response_text = tokenizer.decode(response_ids[0], skip_special_tokens=True).strip()
|
| 89 |
+
|
| 90 |
+
# Verificación básica
|
| 91 |
+
if len(response_text.strip()) < 10:
|
| 92 |
+
return {
|
| 93 |
+
"response": "Lo siento, necesito reformular la respuesta. ¿Podrías hacer la pregunta de otra manera?",
|
| 94 |
+
"contexto": input_text
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
return {"response": response_text, "contexto": input_text}
|
| 98 |
+
|
| 99 |
+
# ======== Función para ejecutar FastAPI en segundo plano =========
|
| 100 |
+
def run_api():
|
| 101 |
+
port = int(os.getenv("PORT", 7860))
|
| 102 |
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
| 103 |
+
|
| 104 |
+
threading.Thread(target=run_api, daemon=True).start()
|
| 105 |
+
|
| 106 |
+
# ======== Interfaz con Streamlit =========
|
| 107 |
+
st.title("Mi Amigo Virtual 🤖")
|
| 108 |
+
st.write("Escríbeme algo y te responderé!")
|
| 109 |
+
|
| 110 |
+
contexto_defecto = "Historia de amor"
|
| 111 |
+
user_input = st.text_input("Tú:")
|
| 112 |
+
if user_input:
|
| 113 |
+
response = chat(Message(contexto=contexto_defecto, text=user_input))
|
| 114 |
+
st.write("🤖:", response["response"])
|
entrenar.py
ADDED
|
File without changes
|