Files
service-finder/backend/app/services/ai_service.py
2026-02-26 08:19:25 +01:00

97 lines
3.5 KiB
Python

import os
import json
import logging
import asyncio
import re
import base64
import httpx
from typing import Dict, Any, Optional, List
from sqlalchemy import select
# JAVÍTVA: AsyncSessionLocal használata
from app.db.session import AsyncSessionLocal
from app.models.system import SystemParameter
logger = logging.getLogger("AI-Service")
class AIService:
OLLAMA_BASE_URL = "http://ollama:11434/api/generate"
TEXT_MODEL = "qwen2.5-coder:32b"
VISION_MODEL = "llava:7b"
DVLA_API_KEY = os.getenv("DVLA_API_KEY")
@classmethod
async def get_config_delay(cls) -> float:
try:
# JAVÍTVA: Aszinkron session kezelés
async with AsyncSessionLocal() as db:
stmt = select(SystemParameter).where(SystemParameter.key == "AI_REQUEST_DELAY")
res = await db.execute(stmt)
param = res.scalar_one_or_none()
return float(param.value) if param else 0.1
except Exception:
return 0.1
@classmethod
async def get_gold_data_from_research(cls, make: str, model: str, raw_context: str) -> Optional[Dict[str, Any]]:
await asyncio.sleep(await cls.get_config_delay())
prompt = f"""
FELADAT: A mellékelt kutatási adatokból állíts össze egy hiteles technikai adatlapot.
JÁRMŰ: {make} {model}
KUTATÁSI ADATOK (Szemetesláda tartalom):
{raw_context}
SZIGORÚ SZABÁLYOK:
1. Csak a megerősített adatokat töltsd ki.
2. Ha lóerőt (hp/bhp) találsz, váltsd át kW-ra (hp * 0.745).
3. A 'marketing_name' maradjon 50 karakter alatt.
VÁLASZ FORMÁTUM (Tiszta JSON):
{{
"marketing_name": "string",
"technical_code": "string",
"ccm": int,
"kw": int,
"maintenance": {{
"oil_type": "string",
"oil_qty_liters": float,
"spark_plug": "string",
"final_drive": "string"
}},
"tires": {{
"front": "string",
"rear": "string"
}},
"is_duplicate_potential": bool
}}
"""
return await cls._execute_ai_call(prompt, make, model)
@classmethod
async def _execute_ai_call(cls, prompt: str, make: str, model: str) -> Optional[Dict[str, Any]]:
payload = {
"model": cls.TEXT_MODEL,
"prompt": prompt,
"stream": False,
"format": "json",
"options": {"temperature": 0.1}
}
try:
async with httpx.AsyncClient(timeout=120.0) as client:
response = await client.post(cls.OLLAMA_BASE_URL, json=payload)
response.raise_for_status()
res_json = response.json()
return json.loads(res_json.get("response", "{}"))
except Exception as e:
logger.error(f"❌ AI hiba ({make} {model}): {e}")
return None
@classmethod
async def get_clean_vehicle_data(cls, make: str, raw_model: str, v_type: str, sources: Dict[str, Any]) -> Optional[Dict[str, Any]]:
await asyncio.sleep(await cls.get_config_delay())
prompt = f"""
FELADAT: Normalizáld a jármű adatait.
GYÁRTÓ: {make} | MODELL: {raw_model}
ADATOK: {json.dumps(sources)}
(JSON válasz marketing_name, synonyms, technical_code, ccm, kw, year_from, year_to)
"""
return await cls._execute_ai_call(prompt, make, raw_model)