"""
OpenAI Provider für LLM Enrichment.
Verwendet gpt-5-nano (Level 1) oder gpt-5-mini (Level 2).
"""
import os
import json
from typing import Dict, Any
from .base import LLMProvider
try:
from openai import OpenAI
HAS_OPENAI = True
except ImportError:
HAS_OPENAI = False
class OpenAIProvider(LLMProvider):
"""OpenAI API Provider mit JSON-Response."""
def __init__(self, model: str = None):
if not HAS_OPENAI:
raise ImportError("openai nicht installiert. Bitte: pip install openai")
model = model or os.getenv('OPENAI_MODEL_LOW', 'gpt-4o-mini')
super().__init__(model)
self.client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
self.tokens_used = 0
def extract(self, prompt: str) -> Dict[str, Any]:
"""
Ruft OpenAI API auf und parsed JSON Response.
Args:
prompt: Der Enrichment-Prompt
Returns:
Dict mit extrahierten Daten
Raises:
ValueError: Bei API-Fehler oder JSON-Parse-Fehler
"""
try:
# gpt-5-* Modelle: Reasoning-Modelle, keine temperature, kein response_format
# gpt-4.1-* Modelle: Standard, temperature + response_format nutzbar
is_reasoning = self.model.startswith('gpt-5')
if is_reasoning:
response = self.client.chat.completions.create(
model=self.model,
messages=[{'role': 'user', 'content': prompt}],
max_completion_tokens=10000, # Reasoning braucht Platz
)
else:
response = self.client.chat.completions.create(
model=self.model,
messages=[{'role': 'user', 'content': prompt}],
max_tokens=2000,
temperature=0.2,
response_format={'type': 'json_object'},
)
# Token-Tracking
self.tokens_used = (
response.usage.prompt_tokens + response.usage.completion_tokens
)
# Response extrahieren und JSON parsen
raw_text = response.choices[0].message.content.strip()
data = json.loads(raw_text)
return data
except json.JSONDecodeError as e:
raise ValueError(f"JSON_PARSE_ERROR: {str(e)}")
except Exception as e:
raise ValueError(f"OPENAI_API_ERROR: {str(e)}")