Initial commit: Robot ökoszisztéma v2.0 - Stabilizált jármű és szerviz robotok

This commit is contained in:
Kincses
2026-03-04 02:03:03 +01:00
commit 250f4f4b8f
7942 changed files with 449625 additions and 0 deletions

View 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])