|
|
import gradio as gr |
|
|
from transformers import AutoModelForCausalLM, AutoTokenizer |
|
|
from collections import defaultdict, OrderedDict |
|
|
import re |
|
|
import torch |
|
|
from threading import Lock |
|
|
|
|
|
|
|
|
model_name = "microsoft/DialoGPT-small" |
|
|
device = "cuda" if torch.cuda.is_available() else "cpu" |
|
|
tokenizer = AutoTokenizer.from_pretrained(model_name) |
|
|
model = AutoModelForCausalLM.from_pretrained(model_name).to(device) |
|
|
model.eval() |
|
|
|
|
|
|
|
|
def cargar_alojamientos(): |
|
|
with open("alojamientos.txt", "r", encoding="utf-8") as file: |
|
|
alojamientos = file.read().split("\n\n") |
|
|
return {idx: alojamiento for idx, alojamiento in enumerate(alojamientos)} |
|
|
|
|
|
alojamientos_info = cargar_alojamientos() |
|
|
|
|
|
|
|
|
indice_palabras = defaultdict(set) |
|
|
for idx, alojamiento in alojamientos_info.items(): |
|
|
for palabra in re.split(r'\W+', alojamiento.lower()): |
|
|
if len(palabra) > 2: |
|
|
indice_palabras[palabra].add(idx) |
|
|
|
|
|
|
|
|
class LRUCache: |
|
|
def __init__(self, capacity=100): |
|
|
self.cache = OrderedDict() |
|
|
self.capacity = capacity |
|
|
self.lock = Lock() |
|
|
|
|
|
def get(self, key): |
|
|
with self.lock: |
|
|
if key not in self.cache: |
|
|
return None |
|
|
self.cache.move_to_end(key) |
|
|
return self.cache[key] |
|
|
|
|
|
def put(self, key, value): |
|
|
with self.lock: |
|
|
if key in self.cache: |
|
|
self.cache.move_to_end(key) |
|
|
self.cache[key] = value |
|
|
if len(self.cache) > self.capacity: |
|
|
self.cache.popitem(last=False) |
|
|
|
|
|
cache_respuestas = LRUCache() |
|
|
cache_paginas = LRUCache() |
|
|
|
|
|
|
|
|
sinonimos = ["alojamiento", "alquiler", "hospedaje", "residencia", "vivienda"] |
|
|
|
|
|
|
|
|
def buscar_alojamiento(consulta): |
|
|
consulta = consulta.lower() |
|
|
cached = cache_respuestas.get(consulta) |
|
|
if cached is not None: |
|
|
return cached |
|
|
|
|
|
palabras = set(re.split(r'\W+', consulta)) |
|
|
indices = set() |
|
|
for palabra in palabras: |
|
|
if palabra in indice_palabras or palabra in sinonimos: |
|
|
indices.update(indice_palabras[palabra]) |
|
|
|
|
|
resultados = [alojamientos_info[idx] for idx in indices] |
|
|
resultados.sort() |
|
|
cache_respuestas.put(consulta, resultados) |
|
|
cache_paginas.put(consulta, 0) |
|
|
return resultados |
|
|
|
|
|
|
|
|
def formatear_alojamiento(texto): |
|
|
bloques = texto.split("\n\n") |
|
|
resultado = [] |
|
|
nombre_alojamiento = "" |
|
|
datos_contacto = [] |
|
|
tipos_alojamiento = [] |
|
|
|
|
|
for bloque in bloques: |
|
|
lineas = bloque.split("\n") |
|
|
for linea in lineas: |
|
|
if "Alojamiento:" in linea or "Alquiler:" in linea: |
|
|
nombre_alojamiento = linea |
|
|
elif any(tag in linea for tag in ["Direcci贸n:", "Tel茅fono:", "Email:", "Mascotas:", "Wifi:", "Directv:", "Ropa blanca:", "Habilitaci贸n provincial:"]): |
|
|
datos_contacto.append(linea) |
|
|
elif "Plazas:" in linea or any(tag in linea for tag in ["Descripci贸n:", "Servicios:"]): |
|
|
tipos_alojamiento.append(linea) |
|
|
|
|
|
if nombre_alojamiento: |
|
|
resultado.append(nombre_alojamiento) |
|
|
if datos_contacto: |
|
|
resultado.append("\n".join(datos_contacto)) |
|
|
if tipos_alojamiento: |
|
|
resultado.append("Tipos de alojamiento:\n" + "\n".join(tipos_alojamiento)) |
|
|
|
|
|
return "\n\n".join(resultado) |
|
|
|
|
|
|
|
|
def mostrar_resultados(consulta): |
|
|
resultados = buscar_alojamiento(consulta) |
|
|
if not resultados: |
|
|
return "Lo siento, no encontr茅 informaci贸n exacta. Intenta preguntar de otra manera.", "" |
|
|
|
|
|
pagina = cache_paginas.get(consulta) or 0 |
|
|
inicio, fin = pagina * 3, (pagina + 1) * 3 |
|
|
resultados_pagina = resultados[inicio:fin] |
|
|
|
|
|
respuesta = "\n\n".join(formatear_alojamiento(r) for r in resultados_pagina) |
|
|
pregunta_mas = "" |
|
|
if fin < len(resultados): |
|
|
cache_paginas.put(consulta, pagina + 1) |
|
|
pregunta_mas = "驴Quieres ver m谩s resultados? Escribe 's铆' para continuar." |
|
|
elif pagina > 0: |
|
|
pregunta_mas = "驴Quieres ver resultados anteriores? Escribe 'atr谩s' para volver." |
|
|
|
|
|
return respuesta, pregunta_mas |
|
|
|
|
|
|
|
|
with gr.Blocks(title="Chat de Turismo") as iface: |
|
|
gr.Markdown("### Asistente de Turismo - Alojamientos") |
|
|
output_box = gr.Textbox(label="Historial", lines=15, interactive=False) |
|
|
input_box = gr.Textbox(label="Consulta", placeholder="Escribe aqu铆 y presiona Enter...") |
|
|
extra_box = gr.Textbox(label="Opciones", interactive=False) |
|
|
send_button = gr.Button("Enviar") |
|
|
|
|
|
send_button.click(mostrar_resultados, inputs=input_box, outputs=[output_box, extra_box]) |
|
|
input_box.submit(mostrar_resultados, inputs=input_box, outputs=[output_box, extra_box]) |
|
|
|
|
|
iface.launch(share=True, inbrowser=True) |
|
|
|