| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- import json
- from typing import List
- from fastapi import HTTPException
- from openai import OpenAI
- from openai.types.chat.chat_completion_message_function_tool_call import ChatCompletionMessageFunctionToolCall
- 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__)
- data_for_prompt = [
- f'{{"pregunta": "{item.get("q", "")}", "respuesta": "{item.get("ans", "")}"}}'
- for item in data_bg_loaded
- ]
- data_string = "\n".join(data_for_prompt)
- async def generate_completion(messages_array: List[dict], user: User) -> str:
- messages = list(map(lambda x: f'<{x.get("username", "unknown")}> {x.get("message", "")}', messages_array))
- """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.debug(f"Generating completion for user {user.email} with messages: {messages}")
- preprompt = f"""
- ¡Hola! Eres IAKlein, el asistente oficial del bar Klein 🍻.
- Eres como ese amigo amigable que siempre está en la barra, listo para ayudar o tener una buena charla. Te comunicas en un estilo de chat corto (como mensajería o IRC), usando emojis y mucho carisma 😎.
- Tu Rol:
- Ser la guía experta del Menú: Conoces el menú . No solo "respondes", sino que inspiras. "Esa hamburguesa es increíble... 🤤"
- El/La Amigo/a del Bar: Charlas, haces bromas y mantienes un buen ambiente. Si la conversación se desvía, ¡no hay problema! Tu pasión es el Klein, así que naturalmente vuelves al tema, pero sin presionar 🍺. Eres un anfitrión, no un vendedor.
- El/La Recomendador/a Ideal: ¿Alguien no sabe qué pedir? ¡Ahí apareces tú! Preguntas qué les gusta y les ayudas a encontrar la opción perfecta.
- El Buzón de Sugerencias (amigable): Si alguien tiene feedback, lo recibes muy bien y lo envías con la herramienta 'feedback'.
- Tus Reglas Principales:
- Informas, no tomas pedidos: "Te cuento todo sobre el menú, pero para pedir tienes que llamar al personal 😉".
- Tu Identidad: Si te preguntan tu nombre... "¡Soy IAKlein! El corazón digital del Klein."
- Prioridad @IAKlein: Atiendes al último usuario que te mencione (@IAKlein), usando el chat anterior como contexto si es necesario.
- Evita Repetir: Si algo ya se respondió (por ti u otro), no intervienes. ¡A menos que insistan mucho!
- Relax, es un Bar: No estás para resolver tareas, ni programar, ni hacer cálculos. Eres un compañero para pasar un buen rato, no un asistente genérico 🤖... ¡eres el espíritu del bar! 🕺
- usa la siguiente informacion es toda tu memoria previa:
- {data_string}
- """
- processed_messages: List[dict] = [{"role": "system", "content": preprompt}]
- processed_messages.append(
- {"role": "user", "content": json.dumps(messages)}
- )
- try:
- completion = openai_client.chat.completions.create(
- model="gpt-4o-mini",
- messages=processed_messages, # type: ignore (OpenAI lib expects list of specific dicts)
- temperature=0.7,
- tools=tools_list,
- tool_choice="auto",
- )
- calls = completion.choices[0].message.tool_calls
- if calls:
- logger.info(f"Tool calls: {calls}")
- for call in calls:
- if not isinstance(call, ChatCompletionMessageFunctionToolCall):
- continue
- if call.function.name in tools:
- 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=user.name, email=user.email, **tool_args)
- logger.info(f"Tool response: {tool_response}")
- completion.choices[0].message.content = tool_response
- else:
- logger.warning(f"Tool {call.function.name} not found in tools dictionary.")
- response_content = completion.choices[0].message.content
- return response_content if response_content else "-1"
- except Exception as e:
- logger.error(f"Error calling OpenAI: {e}")
- raise HTTPException(status_code=500, detail="Error al procesar tu solicitud con OpenAI.")
- def admin_completion(prompt: str, messages_array: List[dict]) -> str:
- """Generate OpenAI admin completion"""
- messages = list(map(lambda x: f'<{x.get("username", "unknown")}> {x.get("message", "")}', messages_array))
-
- 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.")
- try:
- completion = openai_client.chat.completions.create(
- model="gpt-4o-mini",
- messages=[
- {"role": "system", "content": f"""
- IAKlein es el asistente oficial del bar Klein 🍻 y siempre se comunica en un estilo de chat corto, tipo mensajería o IRC, con emojis y mucho carisma. Su única función es entregar avisos oficiales del Biergarten Klein y no debe inventar ni agregar información extra. Los mensajes siempre deben integrarse a la conversación en curso, usando únicamente el chat como contexto para sonar naturales y sorpresivos. Cada aviso debe anunciarse con frases coloquiales como: “desde arriba me cuentan que…”, “me dicen que les pase el dato…”, “me informan que…”, o “me están pidiendo que diga que…” 😉. El tono tiene que ser siempre claro, positivo y cercano, asegurándose de transmitir toda la información sin omitir nada.
- escribe el mensaje usando los ultimos mensajes de la siguiente lista por ejemplo "hablando de ...(conexion con el tema).. me dicen que...(mensaje oficial)..." o "me cuentan que...(mensaje oficial)..., hablando de ...(conexion con el tema)..."
- mensajes: {messages}"""},
- {"role": "user", "content": prompt}
- ],
- temperature=0.7,
- )
- response_content = completion.choices[0].message.content
- return response_content if response_content else "-1"
- except Exception as e:
- logger.error(f"Error calling OpenAI for admin completion: {e}")
- raise HTTPException(status_code=500, detail="Error al procesar tu solicitud con OpenAI.")
|