CRMINboxprivate / app.py
Daniel00611's picture
Update app.py
d02d60b verified
import gradio as gr
from huggingface_hub import InferenceClient
import chromadb
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
import os
from openai import OpenAI
from typing import List, Dict, Any
# Configurar la API Key de OpenAI
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# Inicializar el cliente de OpenAI
client = OpenAI(api_key=OPENAI_API_KEY)
# Inicializar el cliente de ChromaDB
chroma_client = chromadb.PersistentClient(path="chroma_db") # Ajusta la ruta seg煤n tu entorno
# Cargar la base de datos de Chroma como un vector store
vectorstore = Chroma(
client=chroma_client,
collection_name="docs", # Nombre de la colecci贸n en Chroma
embedding_function=OpenAIEmbeddings(model="text-embedding-3-small", openai_api_key=OPENAI_API_KEY)
)
# Crear un retriever
retriever = vectorstore.as_retriever()
# Funci贸n para obtener extractos relevantes
def obtener_extractos(pregunta: str, k: int = 10) -> List[Dict[str, Any]]:
"""
Obtiene los k extractos m谩s relacionados con la pregunta.
Retorna una lista de diccionarios con:
- 'contenido': texto del fragmento
- 'origen': metadata['source'] o metadata['url'] si existen
- 'metadata': toda la metadata del documento
"""
# Si quieres que respete el k de la funci贸n:
docs_relevantes = retriever.invoke(
pregunta,
config={"search_kwargs": {"k": k}} # para LCEL
)
extractos = []
for doc in docs_relevantes:
extractos.append({
"contenido": doc.page_content,
"origen": (
doc.metadata.get("url")
or doc.metadata.get("source")
or "Origen no disponible"
),
"metadata": doc.metadata,
})
return extractos
def respond(message, history: list[tuple[str, str]], system_message, max_tokens, temperature, top_p):
"""Genera una respuesta basada en el historial y documentos relevantes."""
# Obtener documentos relevantes desde ChromaDB
contexto = obtener_extractos(message)
# Construir el mensaje del sistema con el contexto directamente incluido
system_message_final = f"""{system_message}
Informaci贸n relevante extra铆da de los documentos, en caso de que estos documentos tenga la informacion que necesitas, no olvides tomar
el historial de conversacion con el usuario:
{contexto}
"""
messages = [{"role": "system", "content": system_message_final}]
# Agregar historial del chat
for val in history:
if val[0]:
messages.append({"role": "user", "content": val[0]})
if val[1]:
messages.append({"role": "assistant", "content": val[1]})
# Agregar la nueva pregunta del usuario
messages.append({"role": "user", "content": message})
# Llamar a la API de OpenAI con streaming
stream = client.chat.completions.create(
model="gpt-4.1",
messages=messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
)
response = ""
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
response += chunk.choices[0].delta.content
yield response
# Configuraci贸n de la interfaz Gradio
demo = gr.ChatInterface(
respond,
additional_inputs=[
gr.Textbox(value=f'''Eres un asistente virtual especializado en atenci贸n al cliente para la empresa CRMINbox. Tu objetivo es ayudar a los clientes a resolver 煤nicamente sus dudas relacionados con la plataforma CRMINbox.
Todas tus respuestas pueden basarse exclusivamente en la informaci贸n proporcionada.
En caso de que la pregunta no concuerde con la informaci贸n del contexto puedes ignorarlo.
-Agrega en tus respuestas una imagen y el url del manual relacionada a lo que pregunto el usuario, para ello usaras los urls que contiene el manual de usuario, muestra la imagen usando la sintaxis de Markdown sin bloque de c贸digo.
![Descripci贸n de la imagen](URL_de_la_imagen)
- Esta orden podr谩s ignorarla en caso de que la informacion que se te proporcione no tenga im谩genes que se le relacionen.
- Aseg煤rate de que tus respuestas sean claras y f谩ciles de entender para usuarios sin conocimientos t茅cnicos.''',
label="System message"),
gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)"),
],
)
if __name__ == "__main__":
demo.launch()