import httpx import logging from typing import List, Dict, Any, Optional from core.config import settings from services.oauth_service import OAuthService # Assurez-vous que ce service existe logger = logging.getLogger(__name__) class RomeoService: def __init__(self): self.base_url = settings.FRANCE_TRAVAIL_ROMEO_API_URL # URL de base de l'API Romeo self.scope = "api_romeov2" # Scope spécifique pour Romeo self.oauth_service = OAuthService(settings.FRANCE_TRAVAIL_OAUTH_URL, settings.FRANCE_TRAVAIL_CLIENT_ID, settings.FRANCE_TRAVAIL_CLIENT_SECRET) self.client = httpx.AsyncClient() logger.info(f"RomeoService initialized with base_url: {self.base_url}") async def _get_access_token(self) -> str: """Récupère le token d'accès spécifique à l'API Romeo.""" try: token_response = await self.oauth_service.get_access_token(self.scope) return token_response.access_token except Exception as e: logger.error(f"Erreur lors de la récupération du token d'accès pour Romeo: {e}") raise RuntimeError(f"Impossible de récupérer le token d'accès pour Romeo: {e}") async def _call_api(self, endpoint: str, text: str) -> Optional[Dict[str, Any]]: """ Appelle un endpoint de l'API Romeo avec le texte donné. Gère l'authentification et les erreurs de base. """ token = await self._get_access_token() headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json; charset=utf-8" } # Les APIs Romeo attendent le texte dans un champ 'texte' de l'objet JSON data = {"texte": text} url = f"{self.base_url}{endpoint}" logger.info(f"Calling Romeo API: {url} with text length {len(text)}") try: response = await self.client.post(url, headers=headers, json=data, timeout=30.0) response.raise_for_status() # Lève une exception pour les codes d'erreur HTTP (4xx ou 5xx) return response.json() except httpx.HTTPStatusError as e: logger.error(f"Erreur HTTP lors de l'appel à Romeo {endpoint}: {e.response.status_code} - {e.response.text}") raise RuntimeError(f"Erreur de l'API Romeo: {e.response.text}") except httpx.RequestError as e: logger.error(f"Erreur réseau ou de requête lors de l'appel à Romeo {endpoint}: {e}") raise RuntimeError(f"Erreur de communication avec l'API Romeo: {e}") except Exception as e: logger.error(f"Une erreur inattendue est survenue lors de l'appel à Romeo {endpoint}: {e}") raise RuntimeError(f"Erreur inattendue avec l'API Romeo: {e}") async def predict_metiers(self, text: str) -> List[Dict[str, Any]]: """ Prédit les métiers ROME à partir d'un texte donné. Retourne une liste de dictionnaires avec les détails des prédictions métiers. """ if not text: return [] # Retourne une liste vide si le texte est vide response_data = await self._call_api("/predictionMetiers", text) # Romeo renvoie souvent une liste directe de prédictions si successful return response_data if response_data is not None else [] async def predict_competences(self, text: str) -> List[Dict[str, Any]]: """ Prédit les compétences ROME à partir d'un texte donné. Retourne une liste de dictionnaires avec les détails des prédictions de compétences. """ if not text: return [] # Retourne une liste vide si le texte est vide response_data = await self._call_api("/predictionCompetences", text) # Romeo renvoie souvent une liste directe de prédictions si successful return response_data if response_data is not None else [] # Instanciation unique du service Romeo romeo_service = RomeoService()