Yassine Mhirsi commited on
Commit
16153ee
·
1 Parent(s): 2c1862b

feat: Introduce individual GROQ API keys for Topic, STT, TTS, and Chat services, enhancing configuration flexibility and service initialization checks across the application.

Browse files
config.py CHANGED
@@ -28,6 +28,12 @@ GENERATE_MODEL_ID = HUGGINGFACE_GENERATE_MODEL_ID
28
  # ============ GROQ MODELS ============
29
  GROQ_API_KEY = os.getenv("GROQ_API_KEY", "")
30
 
 
 
 
 
 
 
31
  # ============ GOOGLE MODELS ============
32
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY", "")
33
 
 
28
  # ============ GROQ MODELS ============
29
  GROQ_API_KEY = os.getenv("GROQ_API_KEY", "")
30
 
31
+ # Individual API keys for different services (fallback to GROQ_API_KEY if not set)
32
+ GROQ_TOPIC_API_KEY = os.getenv("GROQ_TOPIC_API_KEY", GROQ_API_KEY)
33
+ GROQ_TTS_API_KEY = os.getenv("GROQ_TTS_API_KEY", GROQ_API_KEY)
34
+ GROQ_STT_API_KEY = os.getenv("GROQ_STT_API_KEY", GROQ_API_KEY)
35
+ GROQ_CHAT_API_KEY = os.getenv("GROQ_CHAT_API_KEY", GROQ_API_KEY)
36
+
37
  # ============ GOOGLE MODELS ============
38
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY", "")
39
 
main.py CHANGED
@@ -23,7 +23,8 @@ from config import (
23
  HOST, PORT, RELOAD,
24
  CORS_ORIGINS, CORS_METHODS, CORS_HEADERS, CORS_CREDENTIALS,
25
  PRELOAD_MODELS_ON_STARTUP, LOAD_STANCE_MODEL, LOAD_KPA_MODEL,
26
- GROQ_API_KEY, GROQ_STT_MODEL, GROQ_TTS_MODEL, GROQ_CHAT_MODEL
 
27
  )
28
 
29
  # --- Fonction de nettoyage ---
@@ -106,7 +107,7 @@ async def lifespan(app: FastAPI):
106
  logger.error("⚠️ Generation endpoints will not work!")
107
 
108
  # Initialize Topic Extraction service (uses Groq LLM)
109
- if topic_similarity_service and GROQ_API_KEY:
110
  try:
111
  logger.info("Initializing Topic Extraction service (Groq LLM)...")
112
  topic_similarity_service.initialize()
@@ -114,17 +115,28 @@ async def lifespan(app: FastAPI):
114
  except Exception as e:
115
  logger.error(f"✗ Failed to initialize Topic Extraction service: {str(e)}")
116
  logger.error("⚠️ Topic extraction endpoints will not work!")
117
- elif not GROQ_API_KEY:
118
- logger.warning("⚠ GROQ_API_KEY not configured. Topic extraction service will not be available.")
119
 
120
  logger.info("✓ API startup complete")
121
  logger.info("https://nlp-debater-project-fastapi-backend-models.hf.space/docs")
122
 
123
  # Vérifier les clés API
124
- if not GROQ_API_KEY:
125
- logger.warning("⚠ GROQ_API_KEY non configurée. Fonctions STT/TTS désactivées.")
 
 
 
 
 
 
 
126
  else:
127
- logger.info("✓ GROQ_API_KEY configurée")
 
 
 
 
128
 
129
  if not HUGGINGFACE_API_KEY:
130
  logger.warning("⚠ HUGGINGFACE_API_KEY non configurée. Modèles locaux désactivés.")
@@ -164,7 +176,7 @@ async def lifespan(app: FastAPI):
164
  logger.info(f" TTS Model: {GROQ_TTS_MODEL}")
165
  logger.info(f" Chat Model: {GROQ_CHAT_MODEL}")
166
  logger.info(f" Topic Extraction: {'Initialized' if (topic_similarity_service and topic_similarity_service.initialized) else 'Not initialized'}")
167
- logger.info(f" Voice Chat: {'Available' if GROQ_API_KEY else 'Disabled (no GROQ_API_KEY)'}")
168
  logger.info(f" MCP: {'Activé' if MCP_ENABLED else 'Désactivé'}")
169
  if MCP_ENABLED:
170
  logger.info(f" - Tools: detect_stance, match_keypoint_argument, transcribe_audio, generate_speech, generate_argument, extract_topic, voice_chat, health_check")
@@ -277,11 +289,11 @@ async def health():
277
  "service": "NLP Debater + Groq Voice",
278
  "version": API_VERSION,
279
  "features": {
280
- "stt": GROQ_STT_MODEL if GROQ_API_KEY else "disabled",
281
- "tts": GROQ_TTS_MODEL if GROQ_API_KEY else "disabled",
282
- "chat": GROQ_CHAT_MODEL if GROQ_API_KEY else "disabled",
283
  "topic_extraction": "initialized" if (topic_similarity_service and hasattr(topic_similarity_service, 'initialized') and topic_similarity_service.initialized) else "not initialized",
284
- "voice_chat": "available" if GROQ_API_KEY else "disabled",
285
  "stance_model": "loaded" if (stance_model_manager and hasattr(stance_model_manager, 'model_loaded') and stance_model_manager.model_loaded) else "not loaded",
286
  "kpa_model": "loaded" if (kpa_model_manager and hasattr(kpa_model_manager, 'model_loaded') and kpa_model_manager.model_loaded) else "not loaded",
287
  "generate_model": "loaded" if (generate_model_manager and hasattr(generate_model_manager, 'model_loaded') and generate_model_manager.model_loaded) else "not loaded",
 
23
  HOST, PORT, RELOAD,
24
  CORS_ORIGINS, CORS_METHODS, CORS_HEADERS, CORS_CREDENTIALS,
25
  PRELOAD_MODELS_ON_STARTUP, LOAD_STANCE_MODEL, LOAD_KPA_MODEL,
26
+ GROQ_TOPIC_API_KEY, GROQ_STT_API_KEY, GROQ_TTS_API_KEY, GROQ_CHAT_API_KEY,
27
+ GROQ_STT_MODEL, GROQ_TTS_MODEL, GROQ_CHAT_MODEL
28
  )
29
 
30
  # --- Fonction de nettoyage ---
 
107
  logger.error("⚠️ Generation endpoints will not work!")
108
 
109
  # Initialize Topic Extraction service (uses Groq LLM)
110
+ if topic_similarity_service and GROQ_TOPIC_API_KEY:
111
  try:
112
  logger.info("Initializing Topic Extraction service (Groq LLM)...")
113
  topic_similarity_service.initialize()
 
115
  except Exception as e:
116
  logger.error(f"✗ Failed to initialize Topic Extraction service: {str(e)}")
117
  logger.error("⚠️ Topic extraction endpoints will not work!")
118
+ elif not GROQ_TOPIC_API_KEY:
119
+ logger.warning("⚠ GROQ_TOPIC_API_KEY not configured. Topic extraction service will not be available.")
120
 
121
  logger.info("✓ API startup complete")
122
  logger.info("https://nlp-debater-project-fastapi-backend-models.hf.space/docs")
123
 
124
  # Vérifier les clés API
125
+ groq_services_configured = any([
126
+ GROQ_TOPIC_API_KEY,
127
+ GROQ_STT_API_KEY,
128
+ GROQ_TTS_API_KEY,
129
+ GROQ_CHAT_API_KEY
130
+ ])
131
+
132
+ if not groq_services_configured:
133
+ logger.warning("⚠ Aucune clé GROQ API configurée. Fonctions STT/TTS/Chat/Topic désactivées.")
134
  else:
135
+ logger.info("✓ Clés GROQ API configurées:")
136
+ if GROQ_TOPIC_API_KEY: logger.info(" - Topic Extraction: ✓")
137
+ if GROQ_STT_API_KEY: logger.info(" - Speech-to-Text: ✓")
138
+ if GROQ_TTS_API_KEY: logger.info(" - Text-to-Speech: ✓")
139
+ if GROQ_CHAT_API_KEY: logger.info(" - Chat/Voice Chat: ✓")
140
 
141
  if not HUGGINGFACE_API_KEY:
142
  logger.warning("⚠ HUGGINGFACE_API_KEY non configurée. Modèles locaux désactivés.")
 
176
  logger.info(f" TTS Model: {GROQ_TTS_MODEL}")
177
  logger.info(f" Chat Model: {GROQ_CHAT_MODEL}")
178
  logger.info(f" Topic Extraction: {'Initialized' if (topic_similarity_service and topic_similarity_service.initialized) else 'Not initialized'}")
179
+ logger.info(f" Voice Chat: {'Available' if GROQ_CHAT_API_KEY else 'Disabled (no GROQ_CHAT_API_KEY)'}")
180
  logger.info(f" MCP: {'Activé' if MCP_ENABLED else 'Désactivé'}")
181
  if MCP_ENABLED:
182
  logger.info(f" - Tools: detect_stance, match_keypoint_argument, transcribe_audio, generate_speech, generate_argument, extract_topic, voice_chat, health_check")
 
289
  "service": "NLP Debater + Groq Voice",
290
  "version": API_VERSION,
291
  "features": {
292
+ "stt": GROQ_STT_MODEL if GROQ_STT_API_KEY else "disabled",
293
+ "tts": GROQ_TTS_MODEL if GROQ_TTS_API_KEY else "disabled",
294
+ "chat": GROQ_CHAT_MODEL if GROQ_CHAT_API_KEY else "disabled",
295
  "topic_extraction": "initialized" if (topic_similarity_service and hasattr(topic_similarity_service, 'initialized') and topic_similarity_service.initialized) else "not initialized",
296
+ "voice_chat": "available" if GROQ_CHAT_API_KEY else "disabled",
297
  "stance_model": "loaded" if (stance_model_manager and hasattr(stance_model_manager, 'model_loaded') and stance_model_manager.model_loaded) else "not loaded",
298
  "kpa_model": "loaded" if (kpa_model_manager and hasattr(kpa_model_manager, 'model_loaded') and kpa_model_manager.model_loaded) else "not loaded",
299
  "generate_model": "loaded" if (generate_model_manager and hasattr(generate_model_manager, 'model_loaded') and generate_model_manager.model_loaded) else "not loaded",
services/chat_service.py CHANGED
@@ -4,7 +4,7 @@ from datetime import datetime
4
  import requests
5
  import json
6
 
7
- from config import GROQ_API_KEY, GROQ_CHAT_MODEL
8
 
9
  # In-memory conversation storage
10
  conversation_store: Dict[str, List[Dict]] = {}
@@ -56,7 +56,7 @@ def generate_chat_response(
56
  messages.append({"role": msg["role"], "content": msg["content"]})
57
 
58
  # 6. Call Groq Chat API
59
- if not GROQ_API_KEY:
60
  # Fallback if no API key
61
  response_text = f"Hello! You said: '{user_input}'. I'm a voice assistant configured to respond in English."
62
  else:
@@ -87,13 +87,13 @@ def call_groq_chat_api(messages: List[Dict]) -> str:
87
  """
88
  Call Groq Chat API
89
  """
90
- if not GROQ_API_KEY:
91
- raise RuntimeError("GROQ_API_KEY is not configured")
92
 
93
  url = "https://api.groq.com/openai/v1/chat/completions"
94
 
95
  headers = {
96
- "Authorization": f"Bearer {GROQ_API_KEY}",
97
  "Content-Type": "application/json"
98
  }
99
 
 
4
  import requests
5
  import json
6
 
7
+ from config import GROQ_CHAT_API_KEY, GROQ_CHAT_MODEL
8
 
9
  # In-memory conversation storage
10
  conversation_store: Dict[str, List[Dict]] = {}
 
56
  messages.append({"role": msg["role"], "content": msg["content"]})
57
 
58
  # 6. Call Groq Chat API
59
+ if not GROQ_CHAT_API_KEY:
60
  # Fallback if no API key
61
  response_text = f"Hello! You said: '{user_input}'. I'm a voice assistant configured to respond in English."
62
  else:
 
87
  """
88
  Call Groq Chat API
89
  """
90
+ if not GROQ_CHAT_API_KEY:
91
+ raise RuntimeError("GROQ_CHAT_API_KEY is not configured")
92
 
93
  url = "https://api.groq.com/openai/v1/chat/completions"
94
 
95
  headers = {
96
+ "Authorization": f"Bearer {GROQ_CHAT_API_KEY}",
97
  "Content-Type": "application/json"
98
  }
99
 
services/stt_service.py CHANGED
@@ -1,17 +1,17 @@
1
  import requests
2
- from config import GROQ_API_KEY, GROQ_STT_MODEL
3
 
4
  def speech_to_text(audio_file: str) -> str:
5
  """
6
  Convert audio file to text using Groq's Whisper API (English only)
7
  """
8
- if not GROQ_API_KEY:
9
- raise RuntimeError("GROQ_API_KEY is not set in config")
10
 
11
  url = "https://api.groq.com/openai/v1/audio/transcriptions"
12
 
13
  headers = {
14
- "Authorization": f"Bearer {GROQ_API_KEY}"
15
  }
16
 
17
  with open(audio_file, "rb") as audio_data:
 
1
  import requests
2
+ from config import GROQ_STT_API_KEY, GROQ_STT_MODEL
3
 
4
  def speech_to_text(audio_file: str) -> str:
5
  """
6
  Convert audio file to text using Groq's Whisper API (English only)
7
  """
8
+ if not GROQ_STT_API_KEY:
9
+ raise RuntimeError("GROQ_STT_API_KEY is not set in config")
10
 
11
  url = "https://api.groq.com/openai/v1/audio/transcriptions"
12
 
13
  headers = {
14
+ "Authorization": f"Bearer {GROQ_STT_API_KEY}"
15
  }
16
 
17
  with open(audio_file, "rb") as audio_data:
services/topic_service.py CHANGED
@@ -7,7 +7,7 @@ from langchain_groq import ChatGroq
7
  from pydantic import BaseModel, Field
8
  from langsmith import traceable
9
 
10
- from config import GROQ_API_KEY
11
 
12
  logger = logging.getLogger(__name__)
13
 
@@ -31,8 +31,8 @@ class TopicService:
31
  logger.info("Topic service already initialized")
32
  return
33
 
34
- if not GROQ_API_KEY:
35
- raise ValueError("GROQ_API_KEY not found in environment variables")
36
 
37
  if model_name:
38
  self.model_name = model_name
@@ -42,7 +42,7 @@ class TopicService:
42
 
43
  llm = ChatGroq(
44
  model=self.model_name,
45
- api_key=GROQ_API_KEY,
46
  temperature=0.0,
47
  max_tokens=512,
48
  )
 
7
  from pydantic import BaseModel, Field
8
  from langsmith import traceable
9
 
10
+ from config import GROQ_TOPIC_API_KEY
11
 
12
  logger = logging.getLogger(__name__)
13
 
 
31
  logger.info("Topic service already initialized")
32
  return
33
 
34
+ if not GROQ_TOPIC_API_KEY:
35
+ raise ValueError("GROQ_TOPIC_API_KEY not found in environment variables")
36
 
37
  if model_name:
38
  self.model_name = model_name
 
42
 
43
  llm = ChatGroq(
44
  model=self.model_name,
45
+ api_key=GROQ_TOPIC_API_KEY,
46
  temperature=0.0,
47
  max_tokens=512,
48
  )
services/tts_service.py CHANGED
@@ -2,7 +2,7 @@ import requests
2
  import uuid
3
  import os
4
  from pathlib import Path
5
- from config import GROQ_API_KEY, GROQ_TTS_MODEL
6
 
7
  def text_to_speech(
8
  text: str,
@@ -12,8 +12,8 @@ def text_to_speech(
12
  """
13
  Convert text to speech using Groq's TTS API (English only)
14
  """
15
- if not GROQ_API_KEY:
16
- raise RuntimeError("GROQ_API_KEY is not set in config")
17
 
18
  if not text or not text.strip():
19
  raise ValueError("Text cannot be empty")
@@ -21,7 +21,7 @@ def text_to_speech(
21
  url = "https://api.groq.com/openai/v1/audio/speech"
22
 
23
  headers = {
24
- "Authorization": f"Bearer {GROQ_API_KEY}",
25
  "Content-Type": "application/json"
26
  }
27
 
 
2
  import uuid
3
  import os
4
  from pathlib import Path
5
+ from config import GROQ_TTS_API_KEY, GROQ_TTS_MODEL
6
 
7
  def text_to_speech(
8
  text: str,
 
12
  """
13
  Convert text to speech using Groq's TTS API (English only)
14
  """
15
+ if not GROQ_TTS_API_KEY:
16
+ raise RuntimeError("GROQ_TTS_API_KEY is not set in config")
17
 
18
  if not text or not text.strip():
19
  raise ValueError("Text cannot be empty")
 
21
  url = "https://api.groq.com/openai/v1/audio/speech"
22
 
23
  headers = {
24
+ "Authorization": f"Bearer {GROQ_TTS_API_KEY}",
25
  "Content-Type": "application/json"
26
  }
27