Skip to main content
Glama
Bdata0
by Bdata0
llm_client.py4.81 kB
# app/llm_client/llm_client.py import logging from mistralai import Mistral # Используем актуальный класс клиента from mistralai.models import SystemMessage, UserMessage # Импортируем нужные типы сообщений # ChatMessage как отдельный публичный класс для создания сообщений не используется в mistralai >= 1.0.0 from app.config import settings import json logger = logging.getLogger(__name__) if not settings.MISTRAL_API_KEY or settings.MISTRAL_API_KEY == "ВАШ_КЛЮЧ_MISTRAL_API": logger.critical("MISTRAL_API_KEY is not set or is a placeholder in .env. LLM calls will fail.") # exit("MISTRAL_API_KEY is not configured.") # Раскомментировать, если это критично mistral_client = Mistral(api_key=settings.MISTRAL_API_KEY) async def get_llm_response(system_prompt: str, user_prompt: str, model_name: str | None = None) -> dict | None: """ Sends a request to the Mistral API and returns the structured JSON response. """ if not settings.MISTRAL_API_KEY or settings.MISTRAL_API_KEY == "ВАШ_КЛЮЧ_MISTRAL_API": logger.error("MISTRAL_API_KEY is not configured. Cannot make LLM call.") return {"error": "LLM API key not configured."} current_model = model_name or settings.LLM_MODEL_NAME logger.debug(f"Sending request to Mistral API. Model: {current_model}") if settings.DEBUG_MODE: logger.debug(f"System Prompt for LLM: \n{system_prompt}") logger.debug(f"User Prompt for LLM: \n{user_prompt}") # Используем рекомендованные классы или словари для сообщений # Для mistralai >= 1.0.0 messages_to_send = [ SystemMessage(content=system_prompt), UserMessage(content=user_prompt) ] # Альтернативно, можно использовать словари: # messages_to_send = [ # {"role": "system", "content": system_prompt}, # {"role": "user", "content": user_prompt} # ] try: # Pydantic v2 может жаловаться на Union (List[Union[SystemMessage, UserMessage...]]), # но API Mistral должен принять это. Если нет, передавайте как List[Dict[str, str]]. chat_response = await mistral_client.chat.complete_async( model=current_model, messages=messages_to_send, # type: ignore response_format={"type": "json_object"} ) response_content = chat_response.choices[0].message.content logger.debug(f"Raw LLM response content: {response_content}") if response_content: try: # Иногда LLM может обернуть JSON в markdown code block if response_content.strip().startswith("```json"): response_content = response_content.strip()[7:-3].strip() elif response_content.strip().startswith("```"): # Общий случай для ``` response_content = response_content.strip()[3:-3].strip() parsed_response = json.loads(response_content) logger.info("Successfully parsed LLM JSON response.") return parsed_response except json.JSONDecodeError as e: logger.error(f"Failed to parse JSON from LLM response: {e}. Response: {response_content}") return {"error": "LLM returned invalid JSON.", "raw_response": response_content} logger.warning("LLM response content was empty.") return {"error": "LLM response content was empty."} except Exception as e: logger.error(f"Error calling Mistral API: {e}", exc_info=True) api_error_details = "" # Попытка извлечь детали из ошибки API, если возможно # У Mistral SDK ошибки обычно содержат response атрибут if hasattr(e, 'response') and e.response is not None and hasattr(e.response, 'text'): try: error_data = json.loads(e.response.text) api_error_details = error_data.get("message", e.response.text) except json.JSONDecodeError: api_error_details = e.response.text[:500] # Первые 500 символов elif hasattr(e, 'message'): # Некоторые ошибки могут иметь просто message api_error_details = str(getattr(e, 'message', str(e))) # getattr для безопасности else: api_error_details = str(e) return {"error": f"LLM API call failed: {str(e)}", "details": api_error_details}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Bdata0/Exely_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server