GitHub Actions commited on
Commit
94dd7b2
·
1 Parent(s): e561008

Sync from GitHub · 2026-08-29 08:44 UTC

Browse files
Files changed (3) hide show
  1. routes/chat.py +2 -2
  2. routes/transcribe.py +2 -5
  3. utils/groq_client.py +46 -2
routes/chat.py CHANGED
@@ -69,8 +69,8 @@ def chat_message(
69
  ):
70
  """
71
  Accepts a user message and returns a streaming SSE response.
72
- For passive AI Chat: uses light model (llama-3.1-8b-instant).
73
- For AI Consultation: uses heavy model (llama-3.3-70b-versatile).
74
 
75
  Stream format (SSE):
76
  data: {"type": "thinking", "token": "..."} ← reasoning (heavy model only)
 
69
  ):
70
  """
71
  Accepts a user message and returns a streaming SSE response.
72
+ For passive AI Chat: uses light model (LIGHT_MODEL).
73
+ For AI Consultation: uses heavy model (HEAVY_MODEL).
74
 
75
  Stream format (SSE):
76
  data: {"type": "thinking", "token": "..."} ← reasoning (heavy model only)
routes/transcribe.py CHANGED
@@ -1,10 +1,8 @@
1
  from fastapi import APIRouter, UploadFile, File, Depends, HTTPException
2
  from auth import verify_firebase_token
3
- import os
4
- from groq import Groq
5
 
6
  router = APIRouter()
7
- groq_client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
8
 
9
  SUPPORTED_AUDIO_TYPES = {
10
  "audio/webm", "audio/mp4", "audio/mpeg", "audio/wav",
@@ -49,8 +47,7 @@ async def transcribe_audio(
49
  raise HTTPException(status_code=400, detail="Audio file is empty.")
50
 
51
  try:
52
- transcription = groq_client.audio.transcriptions.create(
53
- model="whisper-large-v3-turbo",
54
  file=(audio.filename or "recording.webm", audio_bytes, content_type),
55
  response_format="json",
56
  language="en",
 
1
  from fastapi import APIRouter, UploadFile, File, Depends, HTTPException
2
  from auth import verify_firebase_token
3
+ from utils.groq_client import call_groq_transcribe
 
4
 
5
  router = APIRouter()
 
6
 
7
  SUPPORTED_AUDIO_TYPES = {
8
  "audio/webm", "audio/mp4", "audio/mpeg", "audio/wav",
 
47
  raise HTTPException(status_code=400, detail="Audio file is empty.")
48
 
49
  try:
50
+ transcription = call_groq_transcribe(
 
51
  file=(audio.filename or "recording.webm", audio_bytes, content_type),
52
  response_format="json",
53
  language="en",
utils/groq_client.py CHANGED
@@ -39,8 +39,11 @@ if not _KEYS:
39
  print(f"[groq] {len(_KEYS)} API key(s) loaded for rotation")
40
 
41
  # ─── Model names ──────────────────────────────────────────────────────────────
42
- HEAVY_MODEL = "llama-3.3-70b-versatile" # reasoning, profile generation, consultation
43
- LIGHT_MODEL = "llama-3.1-8b-instant" # chat, quick responses
 
 
 
44
 
45
  # ─── Round-robin state ────────────────────────────────────────────────────────
46
  _idx = 0
@@ -121,6 +124,47 @@ def call_groq(
121
  raise last_error or RuntimeError("All Groq API keys are rate-limited")
122
 
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  def call_groq_json(
125
  system_prompt: str,
126
  user_prompt: str,
 
39
  print(f"[groq] {len(_KEYS)} API key(s) loaded for rotation")
40
 
41
  # ─── Model names ──────────────────────────────────────────────────────────────
42
+ # llama-3.3-70b-versatile / llama-3.1-8b-instant were retired by Groq — replaced
43
+ # with the current openai/gpt-oss lineup (see Groq's models page for the live list).
44
+ HEAVY_MODEL = "openai/gpt-oss-120b" # reasoning, profile generation, consultation
45
+ LIGHT_MODEL = "openai/gpt-oss-20b" # chat, quick responses
46
+ TRANSCRIBE_MODEL = "whisper-large-v3-turbo"
47
 
48
  # ─── Round-robin state ────────────────────────────────────────────────────────
49
  _idx = 0
 
124
  raise last_error or RuntimeError("All Groq API keys are rate-limited")
125
 
126
 
127
+ def call_groq_transcribe(
128
+ file: tuple,
129
+ model: str = TRANSCRIBE_MODEL,
130
+ response_format: str = "json",
131
+ language: str | None = None,
132
+ ):
133
+ """
134
+ Calls Groq's Whisper transcription endpoint with the same key-rotation
135
+ on 429 errors as the chat completion calls above.
136
+
137
+ `file` is the (filename, bytes, content_type) tuple the Groq SDK expects.
138
+ """
139
+ last_error: Exception | None = None
140
+
141
+ for attempt in range(len(_KEYS) + 1):
142
+ try:
143
+ client = Groq(api_key=_current_key())
144
+ kwargs: dict = dict(model=model, file=file, response_format=response_format)
145
+ if language:
146
+ kwargs["language"] = language
147
+ return client.audio.transcriptions.create(**kwargs)
148
+
149
+ except Exception as e:
150
+ last_error = e
151
+ err_str = str(e)
152
+ is_rate_limit = (
153
+ '429' in err_str
154
+ or 'rate_limit' in err_str.lower()
155
+ or 'rate limit' in err_str.lower()
156
+ )
157
+
158
+ if is_rate_limit and attempt < len(_KEYS):
159
+ _rotate()
160
+ time.sleep(1)
161
+ continue
162
+
163
+ raise
164
+
165
+ raise last_error or RuntimeError("All Groq API keys are rate-limited")
166
+
167
+
168
  def call_groq_json(
169
  system_prompt: str,
170
  user_prompt: str,