95 lines
3.4 KiB
Python
95 lines
3.4 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
|
|
from app.db.session import SessionLocal
|
|
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:
|
|
async with SessionLocal() 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) |