Spaces:
Sleeping
Sleeping
File size: 2,889 Bytes
ee838b2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | """Adaptateur LLM — OpenAI (GPT-4o, GPT-4o-mini)."""
from __future__ import annotations
import logging
import os
from typing import Optional
from picarones.adapters.llm.base import (
BaseLLMAdapter,
log_http_error,
normalize_llm_content,
)
logger = logging.getLogger(__name__)
class OpenAIAdapter(BaseLLMAdapter):
"""Adaptateur pour les modèles OpenAI (GPT-4o, GPT-4o-mini).
Clé API via la variable d'environnement ``OPENAI_API_KEY``.
Modes supportés : text_only, text_and_image, zero_shot.
"""
api_key_env_var = "OPENAI_API_KEY"
@property
def name(self) -> str:
return "openai"
@property
def default_model(self) -> str:
return "gpt-4o"
def __init__(
self,
model: Optional[str] = None,
config: Optional[dict] = None,
) -> None:
super().__init__(model, config)
self._api_key = os.environ.get("OPENAI_API_KEY")
def _call(self, prompt: str, image_b64: Optional[str] = None) -> str:
if not self._api_key:
raise RuntimeError(
"Clé API OpenAI manquante — définissez la variable d'environnement OPENAI_API_KEY"
)
try:
from openai import OpenAI
except ImportError as exc:
raise RuntimeError(
"Le package 'openai' n'est pas installé. Lancez : pip install openai"
) from exc
client = OpenAI(api_key=self._api_key)
temperature = float(self.config.get("temperature", 0.0))
max_tokens = int(self.config.get("max_tokens", 4096))
if image_b64:
content = [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_b64}"},
},
]
else:
content = prompt # type: ignore[assignment]
try:
response = client.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": content}],
temperature=temperature,
max_tokens=max_tokens,
)
except Exception as exc:
log_http_error(
"OpenAIAdapter", self.model, exc,
env_var=self.api_key_env_var,
)
raise
if not response.choices:
logger.warning(
"[OpenAIAdapter] response.choices vide (modèle=%s).", self.model,
)
return ""
# Chantier 4 — propagation du fix Sprint 15 : le SDK OpenAI
# peut retourner une ``list[ContentBlock]`` selon l'API
# (Responses, structured outputs). ``normalize_llm_content``
# gère les deux cas (str et list).
return normalize_llm_content(response.choices[0].message.content)
|