Spaces:
Running
on
Zero
Running
on
Zero
File size: 4,194 Bytes
cfad8ea 43786a1 9e45e2f 7977dd9 9e45e2f 43786a1 c3ec6b8 bc04226 cfad8ea c3ec6b8 cfad8ea c3ec6b8 a56b6e1 cfad8ea 7977dd9 c3ec6b8 43786a1 5b798a1 c3c5a7d c3ec6b8 43786a1 cfad8ea 0a63192 43786a1 9e45e2f c3ec6b8 fa62c74 43786a1 cfad8ea 0a63192 fa62c74 e077d41 6f87108 e077d41 6f87108 092620d 75062ee 93053b0 e077d41 408c937 e077d41 7baae85 e077d41 75062ee e077d41 75062ee e077d41 75062ee c3ec6b8 2404c70 c3ec6b8 0869270 c3ec6b8 43786a1 c3ec6b8 43786a1 9e45e2f 43786a1 9e45e2f 43786a1 c3ec6b8 43786a1 cfad8ea c3ec6b8 fa62c74 |
1 2 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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
import gradio as gr
import pickle
import os
import json
from transformers import AutoTokenizer, AutoModel, pipeline
import torch
import faiss
import numpy as np
from spaces import GPU # IMPORTANTE para ZeroGPU
hf_token = os.getenv("HF_KEY")
# Cargar índice FAISS y los chunks
if os.path.exists("index.pkl"):
with open("index.pkl", "rb") as f:
index, chunks = pickle.load(f)
else:
raise FileNotFoundError("No se encontró el archivo 'index.pkl'.")
# Cargar diccionario de sinónimos
with open("sinonimos.json", "r", encoding="utf-8") as f:
diccionario_sinonimos = json.load(f)
# Función para expandir palabras clave con sinónimos
def expandir_con_sinonimos(palabras, diccionario):
resultado = set(palabras)
for palabra in palabras:
for clave, sinonimos in diccionario.items():
if palabra == clave or palabra in sinonimos:
resultado.update([clave] + sinonimos)
return list(resultado)
# Modelo de embeddings
model_id = "jinaai/jina-embeddings-v2-base-es"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModel.from_pretrained(model_id)
def generar_embedding(texto):
inputs = tokenizer(texto, return_tensors="pt", padding=True, truncation=True)
with torch.no_grad():
outputs = model(**inputs)
last_hidden = outputs.last_hidden_state
mask = inputs["attention_mask"].unsqueeze(-1).expand(last_hidden.size()).float()
summed = torch.sum(last_hidden * mask, 1)
counted = torch.clamp(mask.sum(1), min=1e-9)
mean_pooled = summed / counted
return mean_pooled.numpy()
# LLM para generar respuesta final
llm = pipeline(
"text-generation",
model="meta-llama/Llama-3.2-3B-Instruct",
token=hf_token,
trust_remote_code=True
)
@GPU
def responder(pregunta):
if not pregunta:
return "Por favor ingresa una pregunta."
pregunta_embedding = generar_embedding(pregunta)
distances, indices = index.search(pregunta_embedding.reshape(1, -1), k=10)
result_chunks = [chunks[i] for i in indices[0]]
palabras_clave = pregunta.lower().split()
palabras_expandidas = expandir_con_sinonimos(palabras_clave, diccionario_sinonimos)
def contar_coincidencias(chunk, palabras):
return sum(1 for p in palabras if p in chunk.lower())
filtrados = sorted(
result_chunks,
key=lambda c: contar_coincidencias(c, palabras_expandidas),
reverse=True
)
contexto_final = "\n\n".join(filtrados[:5]) if filtrados else "\n\n".join(result_chunks[:5])
prompt = f"""
Eres un asistente legal especializado en la legislación colombiana, con conocimientos en el Código de Tránsito, el Código Nacional de Policía y el Código Penal. Tu tarea es responder de forma clara, breve y profesional la siguiente pregunta, utilizando únicamente el contexto legal que se te proporciona. Puedes interpretar el significado de los artículos si su relación con la pregunta es evidente, pero no debes inventar leyes, sanciones ni artículos que no estén presentes en el texto.
No utilices conocimiento externo, no cites fuentes adicionales, ni incluyas enlaces o advertencias innecesarias. Si el contexto no ofrece información suficiente para responder, dilo de forma directa y concluye. Siempre que sea posible, sintetiza tu respuesta para que sea comprensible incluso para personas sin formación jurídica.
CONTEXTO LEGAL:
{contexto_final}
PREGUNTA:
{pregunta}
RESPUESTA:
"""
resultado = llm(
prompt,
max_new_tokens=350,
temperature=0.4,
top_p=0.9,
repetition_penalty=1.2
)[0]["generated_text"]
if "RESPUESTA:" in resultado:
solo_respuesta = resultado.split("RESPUESTA:")[-1].strip()
else:
solo_respuesta = resultado.strip()
return solo_respuesta
# Interfaz de usuario con Gradio
demo = gr.Interface(
fn=responder,
inputs=gr.Textbox(label="Escribe tu pregunta"),
outputs=gr.Textbox(label="Respuesta generada"),
title="Asistente Legal Colombiano",
description="Consulta el Código de Tránsito, Código de Policía y Código Penal colombiano."
)
if __name__ == "__main__":
demo.launch() |