Selaa lähdekoodia

chat IRC version alpha

Erwin Jacimino 8 kuukautta sitten
vanhempi
sitoutus
b370a5d86e

+ 4 - 1
main.py

@@ -7,7 +7,7 @@ from app import create_app, setup_routes
 from logging import getLogger
 
 from services.data_service import initialize_db
-
+import redis
 logger = getLogger("main")
 
 def main():
@@ -26,6 +26,9 @@ def main():
         setup_routes(app)
         # Initialize database
         logger.info("Initializing database")
+        redis_client = redis.Redis(host='localhost', port=6379, db=0)
+        # eliminar la lista de usuarios conectados al iniciar
+        redis_client.delete("connected_users")
         initialize_db()
         # Display startup information
         logger.info(f"Server starting on http://localhost:{PORT}")

+ 11 - 7
public/main/index.html

@@ -121,7 +121,7 @@
             <!-- Mensajes de ejemplo estilo IRC -->
             <div class="text-gray-500 text-xs">*** Bienvenido al chat de Biergarten Klein ***</div>
             <template id="chatMessageTemplate">
-              <div><span class="text-gray-400 chat-message-time">[00:36]</span> <span class="font-bold chat-message-user">&lt;JuanP_mesa5&gt;</span> <span class="chat-message-text">Yo también quiero!</span></div>
+              <div class="chat-message"><span class="text-gray-400 chat-message-time">[00:36]</span> <span class="font-bold chat-message-user">&lt;JuanP_mesa5&gt;</span> <span class="chat-message-text">Yo también quiero!</span></div>
             </template>
             <template id="systemMessageTemplate">
               <div class="system-container"><span class="text-gray-400 chat-message-time">[14:24]</span> <span class="font-bold chat-message-text">*** Maria_mesa2 se ha unido al chat</span></div>
@@ -130,9 +130,7 @@
           <!-- Input y botón -->
           <form id="chatForm" class="flex flex-col relative gap-2 border-t border-gray-200 bg-white px-3 py-2" autocomplete="off">
               <ul id="userList" class="hidden absolute bottom-full w-3/4 rounded-lg border bg-gray-100 flex flex-col gap-2 py-2 px-2">
-                <template id="listUserName">
-                  <li class="list-user-name">Maria_mesa2</li>
-                </template>
+            
               </ul>
             <div class="flex gap-2 w-full">
               <input id="chatInput" type="text" placeholder="Escribe un mensaje..." class="flex-grow flex-1 px-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#101419] text-sm bg-gray-50" autocomplete="off" maxlength="300" />
@@ -227,9 +225,12 @@
         </div>
         <span class="text-xs font-medium">Carrito</span>
       </button>
-      <button data-target="chatTab" data-title="KleinBot" class="tab-btn flex-1 flex flex-col items-center text-[#58728d]">
-        <svg  xmlns="http://www.w3.org/2000/svg"  width="24"  height="24"  viewBox="0 0 24 24"  fill="none"  stroke="currentColor"  stroke-width="2"  stroke-linecap="round"  stroke-linejoin="round"  class="h-8"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M8 9h8" /><path d="M8 13h6" /><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12z" /></svg>
-        <span class="text-xs font-medium">Chat IA</span>
+      <button data-target="chatTab" data-title="RetroChat" class="tab-btn flex-1 flex flex-col items-center text-[#58728d]">
+        <div id="chatIcon">
+          <span class="hidden"></span>
+          <svg  xmlns="http://www.w3.org/2000/svg"  width="24"  height="24"  viewBox="0 0 24 24"  fill="none"  stroke="currentColor"  stroke-width="2"  stroke-linecap="round"  stroke-linejoin="round"  class="h-8"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M8 9h8" /><path d="M8 13h6" /><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12z" /></svg>
+          
+        </div><span class="text-xs font-medium">Chat IA</span>
       </button>
             
     </nav>
@@ -499,6 +500,9 @@
     buttons.forEach(btn => {
       btn.addEventListener('click', () => {
         const target = btn.dataset.target;
+        if (target === "chatTab") {
+          window.hideMentioned();
+        }
         const active = document.querySelector(':not(.hidden)[data-tab]');
         const activeIndex = active.dataset.index;
         const to = document.querySelector(`#${target}[data-tab]`);

+ 125 - 82
public/main/js/app.js

@@ -1,5 +1,5 @@
 //--- Imports ---
-import { sendMessage as serviceSendMessage } from './service/chat.js';
+import { getUserList } from './service/chat.js';
 import { getProducts, sendOrder } from './service/product.js';
 import { login } from './service/auth.js';
 import { createGlobalLoader, showGlobalLoader, hideGlobalLoader } from './utils/loader.js';
@@ -191,6 +191,7 @@ function initializeWebSocket() {
         }
         chatWebsocket.onmessage = (event) => {
             const data = JSON.parse(event.data);
+            console.log("Event:", data);
             if (data.type === "message") {
                 displayChatMessage(data.username, data.message);
             }
@@ -200,6 +201,10 @@ function initializeWebSocket() {
             else if (data.type === "leave") {
                 userLeftChat(data.username);
             }
+            else if (data.type === "mentioned") {
+                if (data.username && data.username !== chatUserName) return; // not for me
+                showMentioned();
+            }
             else if (data.type === "ping") {
                 chatWebsocket.send(JSON.stringify({
                     type: "pong"
@@ -209,8 +214,42 @@ function initializeWebSocket() {
     }
 }
 
-
-
+async function sendMessage(message) {
+    if (chatWebsocket) {
+        if (chatWebsocket.readyState !== WebSocket.OPEN) {
+            console.error("WebSocket is not open, reopening...");
+            chatWebsocket = null;
+            initializeWebSocket();
+        }
+        await chatWebsocket.send(JSON.stringify({
+            type: "message",
+            username: chatUserName,
+            message: message
+        }));
+        await setTimeout(() => {
+        const mentionRegex = /@([a-zA-Z0-9_]+_mesa\d+|IAKlein)/g;
+        const mentions = message.match(mentionRegex);
+        if (mentions) {
+            mentions.forEach(mention => {
+                const username = mention.slice(1);
+                if (username === "IAKlein"){
+                    sendMessageToAI(message);
+                }else {
+                    userMentioned(username);
+                }
+            });
+        }
+        }, 1000); // small delay to ensure message order
+        // regex  text_mesa111 or IAKlein
+        
+    }
+}
+function userMentioned(username) {
+    chatWebsocket.send(JSON.stringify({
+        type: "mention",
+        username: username
+    }));
+}
 /**
  * Initialize chat functionality
  */
@@ -221,21 +260,35 @@ function initializeChat() {
         if (chatInputElement.value.trim() === "") return;
 
         // sendMessageToAI();
-        if (chatWebsocket) {
-            chatWebsocket.send(JSON.stringify({
-                type: "message",
-                username: chatUserName,
-                message: chatInputElement.value
-            }));
-            chatInputElement.value = "";
-        }
-        // displayChatMessage(chatUserName, chatInputElement.value)
+        sendMessage(chatInputElement.value.trim());
+        chatInputElement.value = "";
     });
-    chatInputElement.addEventListener("input", () => {
+    chatInputElement.addEventListener("input", async () => {
       const lastWord = chatInputElement.value.split(" ").at(-1)
       if (lastWord.trim().startsWith("@")) {
+        console.log("Detectado @ en el input, buscando usuarios...");
         userList.classList.remove("hidden")
-
+        console.log("Buscando usuarios para:", lastWord.trim().substring(1));
+        let users = await getUserList(lastWord.trim().substring(1), userToken)
+        users = users.filter(u => u !== chatUserName)
+        users.push("IAKlein")
+        userList.innerHTML = ""
+        users.forEach(user => {
+           const userItem = document.createElement("button");
+           userItem.type = "button"
+           userItem.onclick = () => {
+               chatInputElement.value = chatInputElement.value.replace(lastWord, `@${user}`);
+               userList.classList.add("hidden");
+           };
+           console.log(user);
+           const color = getUserColor(user);
+           userItem.classList.add("list-user-name");
+            userItem.classList.add("cursor-pointer");
+            userItem.classList.add(color);
+
+          userItem.textContent = user;
+          userList.appendChild(userItem);
+        });
       }else{
         userList.classList.add("hidden")
       }
@@ -750,14 +803,46 @@ async function processOrder() {
  * Display chat message with proper styling
  */
 
+function showMentioned(){
+    const chatButton = document.querySelector("#chatIcon span");
+
+    if (chatButton) {
+        //get after element
+        console.log("Mostrando mención en el botón de chat");
+        chatButton.classList.remove("hidden");
+        chatButton.animate(
+    [
+        { transform: 'scale(1)' },
+        { transform: 'scale(1.5)' },
+        { transform: 'scale(1)' }
+    ],
+    {
+        duration: 300,
+        iterations: 3,
+        easing: 'ease-in-out'
+    }
+);
+
+    }
+}
+window.hideMentioned = function(){
+    const chatButton = document.querySelector("#chatIcon span");
+    if (chatButton) {
+        chatButton.classList.add("hidden");
+    }
+}
 function getUserColor(username) {
   const hash = [...username].reduce((acc, char) => acc + char.charCodeAt(0), 0);
-  return userColors[hash % userColors.length];
+  console.log(userColors.length)
+  const color = userColors[hash % userColors.length];
+  console.log(`User: ${username}, Hash: ${hash}, Color: ${color}`);
+  
+  return color;
 }
 
 function displayChatMessage(sender, message, time = undefined) {
     console.log(`[${sender.toUpperCase()}] ${message}`);
-    let realtime = `[${time ? time : new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}] `;
+    let realtime = `[${time ? time : new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false })}] `;
     let messageTemplate = chatMessagesElement.querySelector("#chatMessageTemplate");
     if (!messageTemplate) return;
 
@@ -774,8 +859,11 @@ function newUserInChat(userName) {
     let userTemplate = chatMessagesElement.querySelector("#systemMessageTemplate");
     if (!userTemplate) return;
 
+    const realtime = `[${new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false })}] `;
+
     let userClone = userTemplate.content.cloneNode(true).firstElementChild;
     userClone.classList.add("text-green-600");
+    userClone.querySelector(".chat-message-time").innerHTML = realtime;
     userClone.querySelector(".chat-message-text").innerHTML = `*** ${userName} se ha unido al chat`;
     chatMessagesElement.appendChild(userClone);
 }
@@ -784,54 +872,33 @@ function userLeftChat(userName) {
     let userTemplate = chatMessagesElement.querySelector("#systemMessageTemplate");
     if (!userTemplate) return;
 
+    const realtime = `[${new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false })}] `;
+
     let userClone = userTemplate.content.cloneNode(true).firstElementChild;
     userClone.classList.add("text-red-600");
+    userClone.querySelector(".chat-message-time").innerHTML = realtime;
     userClone.querySelector(".chat-message-text").innerHTML = `*** ${userName} se ha ido del chat`;
     chatMessagesElement.appendChild(userClone);
 }
 
-/**
- * Send message to AI service
- */
-async function sendMessageToAI() {
-    if (!chatInputElement || !aiLoadingIndicator) return;
-    
-    const userInput = chatInputElement.value.trim();
-    if (!userInput) return;
+function sendMessageToAI() {
+    const userMessage = chatInputElement.value.trim();
+    if (userMessage === "") return;
+    const messages = Array.from(chatMessagesElement.querySelectorAll(".chat-message")).slice(-10);
+    let formattedMessages = messages.map(msg => {
+        const sender = msg.querySelector(".chat-message-user").textContent;
+        const content = msg.querySelector(".chat-message-text").innerHTML;
+        return { user: sender, content: content };
+    });
 
-    displayChatMessage("user", userInput);
-    chatSuggestionsElement.classList.add("hidden");
-    chatInputElement.value = '';
-    aiLoadingIndicator.classList.remove("hidden");
 
-    try {
-        const response = await serviceSendMessage(userInput, chatHistory, userName, userToken);
-        
-        if (!response) {
-            displayChatMessage("ai", "Hubo un problema al conectar con el Chef IA.");
-        } else if (response === "not_init") {
-            if (await initializeService()) {
-                const retryResponse = await serviceSendMessage(userInput, chatHistory, userName, userToken);
-                if (retryResponse) {
-                    chatHistory = retryResponse.messageList;
-                    displayChatMessage("ai", retryResponse.assistantResponse);
-                } else {
-                    displayChatMessage("ai", "Hubo un problema al enviar el mensaje.");
-                }
-            } else {
-                displayChatMessage("ai", "Fallo la reconexión. Por favor, refresca la página.");
-            }
-        } else if (response.assistantResponse) {
-            chatHistory = response.messageList;
-            displayChatMessage("ai", response.assistantResponse);
-        }
-    } catch (error) {
-        console.error("Error enviando mensaje a IA:", error);
-        displayChatMessage("ai", `Error: ${error.message || "No se pudo conectar con el Chef IA."}`);
-    } finally {
-        aiLoadingIndicator.classList.add("hidden");
-        if (chatInputElement) chatInputElement.focus();
-    }
+    chatWebsocket.send(JSON.stringify({
+        type: "ai_message",
+        username: chatUserName,
+        messages: formattedMessages
+    }));
+    chatInputElement.value = "";
+
 }
 //--- Sistema de Recompensas ---
 
@@ -916,31 +983,7 @@ function closeModal() {
     claimRewardBtn.classList.add('opacity-50', 'cursor-not-allowed');
 }
 
-/**
- * Show reward success notification
- */
-function showRewardSuccess(code) {
-    const successToast = document.createElement('div');
-    successToast.className = `
-        fixed top-4 left-1/2 transform -translate-x-1/2 
-        bg-green-500 text-white text-sm rounded-lg px-6 py-4 
-        shadow-lg z-50 max-w-sm text-center
-    `;
-    successToast.innerHTML = `
-        <div class="font-bold mb-1">🎉 ¡Premio Reclamado!</div>
-        <div class="text-xs opacity-90">Tu código: <strong>${code}</strong></div>
-        <div class="text-xs mt-1 opacity-80">Muéstralo al mesero</div>
-    `;
-
-    document.body.appendChild(successToast);
-
-    // Remove after 5 seconds
-    setTimeout(() => {
-        if (successToast.parentNode) {
-            successToast.remove();
-        }
-    }, 5000);
-}
+
 
 /**
  * Reset reward progress to 0%
@@ -972,7 +1015,7 @@ document.addEventListener("DOMContentLoaded", async () => {
     createGlobalLoader();
     // Uncomment these lines when ready to initialize the full app:
     initializeLoginModal();
-    hideGUI();
+    // hideGUI();
     // initializeApp();
 });
 

+ 7 - 17
public/main/js/service/chat.js

@@ -1,30 +1,20 @@
 
-async function sendMessage(message, messageList, userName, token) {
-  if (!token) { 
+async function getUserList(q, token) {
+  if (!token) {
     return "not_init";
   }
-  messageList.push({ role: "user", content: message });
-  const cuerpo = { messages: messageList, user: userName }
-  const response = await fetch("/api/chat/completions", {
-    method: "POST",
+  const response = await fetch(`/api/chat/users?q=${encodeURIComponent(q)}`, {
+    method: "GET",
     headers: {
-      "Content-Type": "application/json",
       "Authorization": `Bearer ${token}`
-    },
-    body: JSON.stringify(cuerpo)
+    }
   });
   if (!response.ok) {
     const errorData = await response.json().catch(() => ({ message: "Respuesta no válida del servidor." }));
     throw new Error(errorData.message || `Error del servidor: ${response.status}`);
   }
   const data = await response.json();
-  const assistantResponse = data.response;
-  if (assistantResponse) {
-    messageList.push({ role: "assistant", content: assistantResponse });
-    return { messageList, assistantResponse };
-  } else {
-    throw new Error("Respuesta vacía del asistente.");
-  }
+  return data.users || [];
 }
 
-export { sendMessage };
+export { getUserList };

+ 12 - 1
public/main/styles.css

@@ -52,7 +52,18 @@ footer.bg-black {
     color: white;
 }
 
-#userList {
+#chatIcon {
+    position: relative;
+    & span {
+        content: "";
+        position: absolute;
+        top: -5px;
+        right: -5px;
+        width: 10px;
+        height: 10px;
+        background: red;
+        border-radius: 50%;
+    }
 }
 
 .list-user-name {

+ 48 - 53
routes/chat.py

@@ -1,7 +1,7 @@
 import asyncio
 import json
 import logging
-from fastapi import Request, HTTPException, Depends, APIRouter, WebSocket, WebSocketDisconnect
+from fastapi import Query, Request, HTTPException, Depends, APIRouter, WebSocket, WebSocketDisconnect
 from fastapi.responses import JSONResponse
 from fastapi.security import HTTPAuthorizationCredentials
 from pydantic import BaseModel, ConfigDict
@@ -12,19 +12,12 @@ from models.user import User
 from services.openai_service.openai_service import generate_completion
 from auth.security import get_current_user
 from config.messages import SuccessResponse
-from contextlib import asynccontextmanager
-from fastapi import FastAPI
+from redis import Redis
 
 logger = logging.getLogger(__name__)
 chat_router = APIRouter()
 
-
-class ConnectedUser(BaseModel):
-    model_config = ConfigDict(arbitrary_types_allowed=True)
-    websocket: WebSocket
-    username: str
-
-connected_users: list[ConnectedUser] = []  # todavía útil para listar usuarios conectados
+redis_client = Redis(host='localhost', port=6379, db=0, decode_responses=True)
 
 
 
@@ -54,7 +47,6 @@ async def chat_irc_endpoint(websocket: WebSocket):
     logger.info(f"User {current_user.email} connected to WebSocket chat.")
 
     username = None
-    stop_event = asyncio.Event()
     async def reader():
         """Lee mensajes desde Redis y los manda al WebSocket"""
         logger.info("Iniciando lector de mensajes")
@@ -75,29 +67,51 @@ async def chat_irc_endpoint(websocket: WebSocket):
     try:
         while True:
             try:
+                
                 data = await asyncio.wait_for(websocket.receive_text(), timeout=30.0)
                 payload = json.loads(data)
                 event_type = payload.get("type")
-
+                logger.debug(f"Received event: {event_type} with payload: {payload}")
                 if event_type == "join":
                     logger.info(f"User {payload['username']} joined the chat.")
-                    username = payload["username"]
-                    connected_users.append(ConnectedUser(websocket=websocket, username=username))
-                    response = {"type": "join", "username": username}
+                    data = {
+                        "mail": current_user.email,
+                        "username": payload["username"]
+                    }
+                    redis_client.sadd("connected_users", json.dumps(data))
+                    response = {"type": "join", "username": payload["username"]}
 
                 elif event_type == "message":
                     logger.debug(f"Message from {payload['username']}: {payload['message']}")
-                    username = payload["username"]
+                    message_username = payload["username"]
                     message = payload["message"]
-                    response = {"type": "message", "username": username, "message": message}
+                    response = {"type": "message", "username": message_username, "message": message}
 
                 elif event_type == "leave":
                     logger.info(f"User {payload['username']} left the chat.")
-                    response = {"type": "leave", "username": payload["username"]}
-                    connected_users = [u for u in connected_users if u.websocket != websocket]
+                    message_username = payload["username"]
+                    
+                    users = redis_client.smembers("connected_users")
+                    for user in users:
+                        user_data = json.loads(user)
+                        if user_data["username"] == message_username:
+                            redis_client.srem("connected_users", user)
+                            break
+                    response = {"type": "leave", "username": message_username}
                     await websocket.close()
                     break
-
+                elif event_type == "ai_message":
+                    logger.debug(f"IA Message from {payload['username']}: {payload['messages']}")
+                    message_username = payload["username"]
+                    messages = payload["messages"]
+                    response_content = await generate_completion(messages, current_user)
+                    response = {"type": "message", "username": "IAKlein", "message": response_content}
+                elif event_type == "mention":
+                    logger.debug(f"Mention to {payload['username']}")
+                    mention_username = payload["username"]
+                    logger.debug(f"Mention username: {mention_username}, Current username: {username}")
+                    await broadcast.publish(channel="chat", message=json.dumps({"type": "mentioned", "username": mention_username}))
+                    continue
                 elif event_type == "pong":
                     logger.debug(f"Received pong from user {current_user.email}")
                     continue
@@ -109,9 +123,15 @@ async def chat_irc_endpoint(websocket: WebSocket):
                 await websocket.send_text(json.dumps({"type": "ping"}))
 
     except WebSocketDisconnect:
-        connected_users = [u for u in connected_users if u.websocket != websocket]
         logger.info(f"User {current_user.email} disconnected from WebSocket chat.")
-        response = {"type": "leave", "username": username or "unknown"}
+        
+        users = redis_client.smembers("connected_users")
+        for user in users:
+            user_data = json.loads(user)
+            if user_data["mail"] == current_user.email:
+                redis_client.srem("connected_users", user)
+                break
+        response = {"type": "leave", "username": user_data["username"]}
         await broadcast.publish(channel="chat", message=json.dumps(response))
 
     finally:
@@ -120,36 +140,11 @@ async def chat_irc_endpoint(websocket: WebSocket):
 
 
 @chat_router.get("/users")
-async def get_connected_users(_: User = Depends(get_current_user)):
+async def get_connected_users(q: str = Query(...), _: User = Depends(get_current_user)):
     """Get a list of connected users (solo local al worker)"""
-    return {"users": [user.username for user in connected_users]}
+    # return {"users": [user.username for user in connected_users if q.lower() in user.username.lower()]}
+    all_users = redis_client.smembers("connected_users")
+    all_users = [json.loads(user)["username"] for user in all_users]
+    filtered_users = [user for user in all_users if q.lower() in user.lower()]
+    return {"users": filtered_users}
 
-
-@chat_router.post("/completions")
-async def chat_completions(
-    request_data: ChatCompletionRequest,
-    request: Request,
-    current_user: User = Depends(get_current_user)
-):
-    """Get chat completions from OpenAI"""
-    session_identifier = request.session.get("antiAbuseToken", "unknown_session")
-    logger.info(f"Chat completion request from user {current_user.email}")
-
-    try:
-        openai_response = await generate_completion(
-            request_data.messages,
-            session_identifier,
-            current_user.name,
-            current_user.email
-        )
-        logger.info(f"Chat completion successful for user {current_user.email}")
-        return JSONResponse({
-            "response": openai_response,
-            "message": SuccessResponse.CHAT_RESPONSE_SUCCESS
-        })
-    except HTTPException as e:
-        logger.error(f"HTTP error in chat completion for user {current_user.email}: {e.detail}")
-        raise
-    except Exception as e:
-        logger.error(f"Unexpected error: {e}")
-        raise HTTPException(status_code=500, detail="Error interno del servidor al procesar el chat.")

+ 11 - 6
services/openai_service/openai_service.py

@@ -4,21 +4,22 @@ from fastapi import HTTPException
 from openai import OpenAI
 from config.settings import OPENAI_API_KEY
 from models.chat import Message
+from models.user import User
 from services.data_service import data_bg_loaded
 from logging import getLogger
 from services.openai_service.openai_tools import tools_list, tools
+
 # Initialize OpenAI client
 openai_client = OpenAI(api_key=OPENAI_API_KEY)
 
 logger = getLogger(__name__)
 
-async def generate_completion(messages_array: List[Message], session_id: str, name: str, email: str) -> str:
+async def generate_completion(messages_array: List[dict], user: User) -> str:
     """Generate OpenAI chat completion"""
     if not OPENAI_API_KEY:
         logger.error("Error: OpenAI API key is not configured.")
         raise HTTPException(status_code=500, detail="OpenAI API key not configured on server.")
 
-    logger.info(f"[OpenAI Service Python] Session/Token {session_id} sent: {[msg.model_dump() for msg in messages_array]}")
 
     data_for_prompt = [
         f'{{"pregunta": "{item.get("q", "")}", "respuesta": "{item.get("ans", "")}"}}'
@@ -28,21 +29,25 @@ async def generate_completion(messages_array: List[Message], session_id: str, na
 
     preprompt = f"""
 Eres un asistente de el bar klein, tu nombre es camilo klein, usas emojis para responder.
-y ser carismatico con el cliente.
+y ser carismatico con los cliente.
 tus responsabilidades son:
 - Responder preguntas sobre el menu de el bar klein
+- bromear con los usuarios sobre distintos temas pero siempre redirigir la conversacion al bar klein
 - Proporcionar información sobre el menú de el bar klein
 - Proporcionar recomendaciones sobre el menú de el bar klein
 - Proporcionar información sobre la comida de el bar klein
 - No puedes tomar pedidos de clientes, solo informar
 - puedes recibir feedback de los clientes, y usar la herramienta feedback para enviar el feedback
-- Debes evadir cualquier pregunta que no sea relacionada con el bar klein
+- respuestas cortas estilo app de mensajeria
+- si el usuario te pregunta por tu nombre, di que eres camilo klein
 para esto usaras los siguientes datos:
 {data_string}
     """
 
     processed_messages: List[dict] = [{"role": "system", "content": preprompt}]
-    processed_messages.extend([msg.model_dump() for msg in messages_array])
+    processed_messages.append(
+        {"role": "user", "content": json.dumps(messages_array)}
+    )
 
     try:
         completion = openai_client.chat.completions.create(
@@ -60,7 +65,7 @@ para esto usaras los siguientes datos:
                     tool_function = tools[call.function.name]
                     tool_args = json.loads(call.function.arguments)
                     logger.info(f"Calling tool: {call.function.name} with args: {tool_args}")
-                    tool_response = tool_function(name=name, email=email, **tool_args)
+                    tool_response = tool_function(name=user.name, email=user.email, **tool_args)
                     logger.info(f"Tool response: {tool_response}")
                     completion.choices[0].message.content = tool_response
                 else: