import json from typing import Any from uuid import UUID from banortegpt.database.mongo_memory import crud from langfuse.decorators import langfuse_context, observe from pydantic import BaseModel import api.context as ctx from api.agent import agent class Response(BaseModel): content: str urls: list[str] @observe(capture_input=False, capture_output=False) async def generate( prompt: str, conversation_id: UUID, ) -> Response: conversation = await crud.get_conversation(conversation_id) if conversation is None: raise ValueError(f"Conversation with ID {conversation_id} not found") conversation.add(role="user", content=prompt) response = await agent.generate(conversation.to_openai_format(agent.message_limit)) reference_urls, image_urls = [], [] if call := response.tool_calls: if id := call[0].id: ctx.tool_id.set(id) if name := call[0].function.name: ctx.tool_name.set(name) ctx.tool_buffer.set(call[0].function.arguments) else: assert response.content is not None ctx.buffer.set(response.content) buffer = ctx.buffer.get() tool_buffer = ctx.tool_buffer.get() tool_id = ctx.tool_id.get() tool_name = ctx.tool_name.get() if tool_id is not None: # Si tool_buffer es un string JSON, lo convertimos a diccionario if isinstance(tool_buffer, str): try: tool_args = json.loads(tool_buffer) except json.JSONDecodeError: tool_args = {"question": tool_buffer} else: tool_args = tool_buffer response, payloads = await agent.tool_map[tool_name](**tool_args) # type: ignore assert tool_name is not None tool_call: dict[str, Any] = agent.llm.build_tool_call( tool_id, tool_name, tool_buffer ) tool_call_id: dict[str, Any] = agent.llm.build_tool_call_id(tool_id) conversation.add("assistant", **tool_call) conversation.add("tool", content=response, **tool_call_id) response = await agent.generate( conversation.to_openai_format(agent.message_limit), {"tools": None} ) assert response.content is not None ctx.buffer.set(response.content) reference_urls, image_urls = await agent.get_shareable_urls(payloads) # type: ignore buffer = ctx.buffer.get() if buffer is None: raise ValueError("No buffer found") conversation.add(role="assistant", content=buffer) langfuse_context.update_current_trace( name=agent.__class__.__name__, session_id=str(conversation_id), input=prompt, output=buffer, ) return Response(content=buffer, urls=reference_urls + image_urls)