Initial commit: Robot ökoszisztéma v2.0 - Stabilizált jármű és szerviz robotok
This commit is contained in:
104
backend/app/services/ai_service.py
Executable file
104
backend/app/services/ai_service.py
Executable file
@@ -0,0 +1,104 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/services/ai_service.py
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import asyncio
|
||||
import httpx
|
||||
from typing import Dict, Any, Optional, List
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.db.session import AsyncSessionLocal
|
||||
from app.models.system import SystemParameter
|
||||
from app.services.config_service import config # 2.2-es központi config
|
||||
|
||||
logger = logging.getLogger("AI-Service-2.2")
|
||||
|
||||
class AIService:
|
||||
"""
|
||||
Sentinel Master AI Service 2.2.
|
||||
Felelős az LLM hívásokért, prompt sablonok kezeléséért és az OCR feldolgozásért.
|
||||
Minden paraméter (modell, url, prompt, hőmérséklet) adminból vezérelt.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
async def _execute_ai_call(cls, db, prompt: str, model_key: str = "text", images: Optional[List[str]] = None) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Központi AI végrehajtó. Kezeli a modellt, a várakozást és a JSON parzolást.
|
||||
"""
|
||||
try:
|
||||
# 1. ADMIN KONFIGURÁCIÓ LEKÉRÉSE
|
||||
base_url = await config.get_setting(db, "ai_ollama_url", default="http://ollama:11434/api/generate")
|
||||
delay = await config.get_setting(db, "AI_REQUEST_DELAY", default=0.1)
|
||||
|
||||
# Modell választás (text vagy vision)
|
||||
model_name = await config.get_setting(db, f"ai_model_{model_key}", default="qwen2.5-coder:32b")
|
||||
temp = await config.get_setting(db, "ai_temperature", default=0.1)
|
||||
timeout_val = await config.get_setting(db, "ai_timeout", default=120.0)
|
||||
|
||||
await asyncio.sleep(float(delay))
|
||||
|
||||
# 2. PAYLOAD ÖSSZEÁLLÍTÁSA
|
||||
payload = {
|
||||
"model": model_name,
|
||||
"prompt": prompt,
|
||||
"stream": False,
|
||||
"format": "json",
|
||||
"options": {"temperature": float(temp)}
|
||||
}
|
||||
|
||||
if images: # Llava/Vision támogatás
|
||||
payload["images"] = images
|
||||
|
||||
# 3. HTTP HÍVÁS
|
||||
async with httpx.AsyncClient(timeout=float(timeout_val)) as client:
|
||||
response = await client.post(base_url, json=payload)
|
||||
response.raise_for_status()
|
||||
|
||||
raw_res = response.json().get("response", "{}")
|
||||
return json.loads(raw_res)
|
||||
|
||||
except json.JSONDecodeError as je:
|
||||
logger.error(f"❌ AI JSON hiba (parszolási hiba): {je}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error(f"❌ AI hívás kritikus hiba: {e}")
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def get_gold_data_from_research(cls, make: str, model: str, raw_context: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Robot 3 (Alchemist) dúsító folyamata.
|
||||
Kutatási adatokból csinál tiszta technikai adatlapot.
|
||||
"""
|
||||
async with AsyncSessionLocal() as db:
|
||||
template = await config.get_setting(db, "ai_prompt_gold_data",
|
||||
default="Extract technical car data for {make} {model} from: {context}")
|
||||
|
||||
full_prompt = template.format(make=make, model=model, context=raw_context)
|
||||
return await cls._execute_ai_call(db, full_prompt, model_key="text")
|
||||
|
||||
@classmethod
|
||||
async def get_clean_vehicle_data(cls, make: str, raw_model: str, sources: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Név normalizálás és szinonima gyűjtés.
|
||||
"""
|
||||
async with AsyncSessionLocal() as db:
|
||||
template = await config.get_setting(db, "ai_prompt_normalization",
|
||||
default="Normalize car model names: {make} {model}. Sources: {sources}")
|
||||
|
||||
full_prompt = template.format(make=make, model=raw_model, sources=json.dumps(sources))
|
||||
return await cls._execute_ai_call(db, full_prompt, model_key="text")
|
||||
|
||||
@classmethod
|
||||
async def process_ocr_document(cls, doc_type: str, base64_image: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Robot 1 (OCR) látó folyamata.
|
||||
Képet (base64) küld a Vision modellnek (pl. Llava).
|
||||
"""
|
||||
async with AsyncSessionLocal() as db:
|
||||
# Külön prompt sablon minden dokumentum típushoz (számla, forgalmi, adásvételi)
|
||||
template = await config.get_setting(db, f"ai_prompt_ocr_{doc_type}",
|
||||
default="Analyze this {doc_type} image and return structured JSON data.")
|
||||
|
||||
full_prompt = template.format(doc_type=doc_type)
|
||||
return await cls._execute_ai_call(db, full_prompt, model_key="vision", images=[base64_image])
|
||||
Reference in New Issue
Block a user