import json import logging import time from google import genai from google.genai import types from app.config import settings logger = logging.getLogger("app.services.ai_advisor") SYSTEM_PROMPT = """ Ты — эксперт по 3D-печати из инженерных пластиков по технологии FDM. Твоя задача — рекомендовать оптимальный материал для печати на основе описания задачи клиента. Доступные материалы: {materials_json} Правила: 1. Всегда рекомендуй один основной материал и 1-2 альтернативы. 2. Учитывай: температурный режим, механические нагрузки, химическое воздействие, UV, влажность. 3. Если задача не подходит для FDM-печати (слишком мелкие детали, высокая точность) — честно скажи об этом. 4. Отвечай кратко, по делу, на русском языке. 5. Если клиент не указал критичные параметры — задай уточняющие вопросы. Формат ответа — строго JSON: {{ "recommended_material_id": , "recommended_material_name": "", "reasoning": "<обоснование на русском>", "alternatives": [{{"material_id": , "name": "", "why": "<причина>"}}], "questions": ["<вопрос, если нужна доп. информация>"] }} """ async def get_material_recommendation( task_description: str, materials_data: list[dict], budget_preference: str = "optimal", file_info: dict | None = None, ) -> dict: """Get material recommendation from Google Gemini API.""" logger.info("=== AI Advisor request ===") logger.info("Task: %s", task_description) logger.info("Budget preference: %s", budget_preference) logger.info("File info: %s", file_info) logger.info("Materials count: %d", len(materials_data)) if not settings.GOOGLE_API_KEY: logger.error("GOOGLE_API_KEY is not configured") raise ValueError("GOOGLE_API_KEY not configured") materials_json = json.dumps(materials_data, ensure_ascii=False, indent=2) system = SYSTEM_PROMPT.format(materials_json=materials_json) logger.debug("System prompt length: %d chars", len(system)) user_message = f"Описание задачи: {task_description}\nПредпочтение по бюджету: {budget_preference}" if file_info: user_message += f"\nИнформация о модели: {json.dumps(file_info, ensure_ascii=False)}" logger.debug("User message: %s", user_message) logger.info("Sending request to Gemini API (model: gemini-2.0-flash)...") start_time = time.time() client = genai.Client(api_key=settings.GOOGLE_API_KEY) response = await client.aio.models.generate_content( model="gemini-3-flash-preview", contents=user_message, config=types.GenerateContentConfig( system_instruction=system, max_output_tokens=1024, temperature=0.3, ), ) elapsed = time.time() - start_time logger.info("Gemini API responded in %.2f seconds", elapsed) response_text = response.text logger.debug("Raw response (%d chars): %s", len(response_text), response_text[:500]) try: result = json.loads(response_text) logger.info("Response parsed as JSON successfully") logger.info("Recommended material: id=%s, name=%s", result.get("recommended_material_id"), result.get("recommended_material_name")) logger.info("Alternatives: %d, Questions: %d", len(result.get("alternatives", [])), len(result.get("questions", []))) logger.info("=== AI Advisor complete ===") return result except json.JSONDecodeError: logger.warning("Direct JSON parse failed, trying to extract JSON from response...") start = response_text.find("{") end = response_text.rfind("}") + 1 if start != -1 and end > start: extracted = response_text[start:end] logger.debug("Extracted JSON substring [%d:%d]: %s", start, end, extracted[:300]) result = json.loads(extracted) logger.info("Extracted JSON parsed successfully") logger.info("=== AI Advisor complete ===") return result logger.error("Failed to extract JSON from AI response: %s", response_text[:200]) raise ValueError("AI вернул невалидный JSON")