import asyncio import logging from sqlalchemy import select, update, func, and_, case # JAVÍTVA: and_ és case importálva from app.db.session import SessionLocal from app.models.vehicle_definitions import VehicleModelDefinition from app.services.ai_service import AIService # Logolás finomhangolása logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s') logger = logging.getLogger("Robot-Alchemist-v2.2") class AlchemistBot: def __init__(self): self.batch_size = 5 # GPU VRAM kímélése (Ollama párhuzamosítás mellett) self.delay_between_records = 12 # Quadro P4000 hűtési idő/késleltetés async def synthesize_vehicle(self, vehicle_id: int): """AI dúsítás végrehajtása a begyűjtött kontextusból.""" async with SessionLocal() as db: res = await db.execute(select(VehicleModelDefinition).where(VehicleModelDefinition.id == vehicle_id)) v = res.scalar_one_or_none() if not v or not v.raw_search_context: logger.warning(f"⚠️ Nincs kontextus az ID:{vehicle_id} rekordhoz, átugrás.") return make, model = v.make, v.marketing_name logger.info(f"🧪 Arany dúsítás indul (AI Synthesis): {make} {model}") # Státusz zárolása a feldolgozás idejére await db.execute( update(VehicleModelDefinition) .where(VehicleModelDefinition.id == vehicle_id) .values(status='ai_synthesis_in_progress') ) await db.commit() # AI hívás: Gold-Data kinyerése a "szemetesládából" gold_data = await AIService.get_gold_data_from_research(make, model, v.raw_search_context) async with SessionLocal() as db: if gold_data: # Értékek kinyerése és normalizálása ccm = gold_data.get("ccm") kw = gold_data.get("kw") m_name = gold_data.get("marketing_name", model)[:50] t_code = gold_data.get("technical_code") await db.execute( update(VehicleModelDefinition) .where(VehicleModelDefinition.id == vehicle_id) .values( marketing_name=m_name, technical_code=t_code or v.technical_code, engine_capacity=ccm, power_kw=kw, features_json=gold_data, # A teljes technikai JSON (olaj, gumi, stb.) status='gold_enriched', updated_at=func.now() ) ) logger.info(f"✨ GOLD ENRICHED: {make} {m_name} ({ccm} ccm, {kw} kW)") else: # Hiba esetén visszatesszük a sorba, növelve a kísérletek számát await db.execute( update(VehicleModelDefinition) .where(VehicleModelDefinition.id == vehicle_id) .values( status='awaiting_ai_synthesis', attempts=v.attempts + 1, last_error="AI extraction failed or returned empty" ) ) logger.warning(f"⚠️ Sikertelen dúsítás: {make} {model}") await db.commit() async def run(self): logger.info("🚀 Robot 2.2 (Alchemist) ONLINE - Prioritásos feldolgozás") while True: async with SessionLocal() as db: # --- PRIORITÁSI LOGIKA (Megegyezik a Researcher botéval) --- priorities = case( (and_(VehicleModelDefinition.vehicle_type == 'car', VehicleModelDefinition.make.in_(['SUZUKI', 'TOYOTA', 'SKODA', 'VOLKSWAGEN', 'OPEL'])), 1), (VehicleModelDefinition.vehicle_type == 'car', 2), (and_(VehicleModelDefinition.vehicle_type == 'motorcycle', VehicleModelDefinition.make.in_(['HONDA', 'YAMAHA', 'SUZUKI', 'KAWASAKI'])), 3), else_=4 ) # Lekérdezés prioritás szerint, majd a legrégebben frissített rekordok szerint stmt = select(VehicleModelDefinition.id).where( VehicleModelDefinition.status == 'awaiting_ai_synthesis' ).order_by(priorities, VehicleModelDefinition.updated_at.asc()).limit(self.batch_size) res = await db.execute(stmt) ids = [r[0] for r in res.fetchall()] if not ids: # Ha üres a tartály, pihenünk és várunk a porszívóra await asyncio.sleep(20) continue for vid in ids: await self.synthesize_vehicle(vid) # Quadro P4000 hűtés és Ollama API tehermentesítés await asyncio.sleep(self.delay_between_records) if __name__ == "__main__": asyncio.run(AlchemistBot().run())