precison9 commited on
Commit
c8576d9
·
verified ·
1 Parent(s): e701855

Update app/rag/routes.py

Browse files
Files changed (1) hide show
  1. app/rag/routes.py +59 -24
app/rag/routes.py CHANGED
@@ -4,6 +4,7 @@ from fastapi.responses import StreamingResponse
4
  from motor.motor_asyncio import AsyncIOMotorDatabase
5
  from bson import ObjectId
6
  from groq import AsyncGroq
 
7
  import json
8
  import logging
9
  from datetime import datetime
@@ -34,6 +35,32 @@ WEB_SEARCH_TOOL = {
34
  },
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  @router.post("/conversations", status_code=status.HTTP_201_CREATED)
39
  async def create_conversation(
@@ -46,9 +73,6 @@ async def create_conversation(
46
  return {"conversation_id": conv.id}
47
 
48
 
49
- # NEW — this was the missing endpoint causing conversations to
50
- # "disappear" on refresh. They were never gone from Mongo; the
51
- # frontend just had nothing to call to list them back out.
52
  @router.get("/conversations")
53
  async def list_conversations(
54
  current_user: UserPublic = Depends(get_current_user),
@@ -84,7 +108,6 @@ async def get_conversation(
84
  return conv
85
 
86
 
87
- # NEW — matches the delete button added to the dashboard
88
  @router.delete("/conversations/{conv_id}", status_code=status.HTTP_204_NO_CONTENT)
89
  async def delete_conversation(
90
  conv_id: str,
@@ -138,21 +161,30 @@ async def send_message(
138
 
139
  client = AsyncGroq(api_key=settings.groq_api_key)
140
  tools = [WEB_SEARCH_TOOL] if enable_web_search else None
 
141
 
142
- chat_history = [system_msg] + [m.dict() for m in messages]
 
 
 
 
143
 
144
  max_tool_loops = 3
145
  for _ in range(max_tool_loops):
146
- completion = await client.chat.completions.create(
147
- model=model,
148
- messages=chat_history,
149
- temperature=1,
150
- max_tokens=700,
151
- top_p=1,
152
- stream=False,
153
- stop=None,
154
- tools=tools,
155
- )
 
 
 
 
156
  choice = completion.choices[0].message
157
  if not choice.tool_calls:
158
  break
@@ -172,15 +204,18 @@ async def send_message(
172
  logger.warning("Max tool loops reached")
173
  raise HTTPException(status_code=500, detail="Too many tool calls")
174
 
175
- completion = await client.chat.completions.create(
176
- model=model,
177
- messages=chat_history,
178
- temperature=1,
179
- max_tokens=8192,
180
- top_p=1,
181
- stream=True,
182
- stop=None,
183
- )
 
 
 
184
 
185
  async def generate():
186
  response_content = ""
 
4
  from motor.motor_asyncio import AsyncIOMotorDatabase
5
  from bson import ObjectId
6
  from groq import AsyncGroq
7
+ import groq
8
  import json
9
  import logging
10
  from datetime import datetime
 
35
  },
36
  }
37
 
38
+ # Single source of truth for completion token budgets — both call sites
39
+ # below read from here, so there's no way for them to drift out of sync
40
+ # with each other again.
41
+ MODEL_MAX_TOKENS = {
42
+ "llama-3.1-8b-instant": 1024,
43
+ "meta-llama/llama-4-maverick-17b-128e-instruct": 1024,
44
+ "moonshotai/kimi-k2-instruct": 1024,
45
+ "qwen/qwen3-32b": 1024,
46
+ "groq/compound": 1024,
47
+ }
48
+ DEFAULT_MAX_TOKENS = 500
49
+
50
+ # Trim conversation history sent to Groq so old turns don't keep eating
51
+ # into the same shared per-minute token budget as the current message.
52
+ MAX_HISTORY_MESSAGES = 8
53
+
54
+
55
+ def _raise_for_groq_error(e: "groq.APIStatusError"):
56
+ logger.error(f"Groq API error ({e.status_code}): {e.message}")
57
+ if e.status_code == 413 or "rate_limit" in str(e.body).lower():
58
+ raise HTTPException(
59
+ status_code=429,
60
+ detail="Message too long or too many requests for the selected model. Try a shorter message, a shorter conversation, or switch models.",
61
+ )
62
+ raise HTTPException(status_code=502, detail="The AI provider returned an error. Please try again.")
63
+
64
 
65
  @router.post("/conversations", status_code=status.HTTP_201_CREATED)
66
  async def create_conversation(
 
73
  return {"conversation_id": conv.id}
74
 
75
 
 
 
 
76
  @router.get("/conversations")
77
  async def list_conversations(
78
  current_user: UserPublic = Depends(get_current_user),
 
108
  return conv
109
 
110
 
 
111
  @router.delete("/conversations/{conv_id}", status_code=status.HTTP_204_NO_CONTENT)
112
  async def delete_conversation(
113
  conv_id: str,
 
161
 
162
  client = AsyncGroq(api_key=settings.groq_api_key)
163
  tools = [WEB_SEARCH_TOOL] if enable_web_search else None
164
+ completion_tokens = MODEL_MAX_TOKENS.get(model, DEFAULT_MAX_TOKENS)
165
 
166
+ # Only send the most recent N messages + system prompt — full history
167
+ # otherwise keeps consuming the same shared per-minute token budget
168
+ # as the current turn, no matter how small max_tokens is set.
169
+ trimmed_messages = messages[-MAX_HISTORY_MESSAGES:]
170
+ chat_history = [system_msg] + [m.dict() for m in trimmed_messages]
171
 
172
  max_tool_loops = 3
173
  for _ in range(max_tool_loops):
174
+ try:
175
+ completion = await client.chat.completions.create(
176
+ model=model,
177
+ messages=chat_history,
178
+ temperature=1,
179
+ max_tokens=completion_tokens,
180
+ top_p=1,
181
+ stream=False,
182
+ stop=None,
183
+ tools=tools,
184
+ )
185
+ except groq.APIStatusError as e:
186
+ _raise_for_groq_error(e)
187
+
188
  choice = completion.choices[0].message
189
  if not choice.tool_calls:
190
  break
 
204
  logger.warning("Max tool loops reached")
205
  raise HTTPException(status_code=500, detail="Too many tool calls")
206
 
207
+ try:
208
+ completion = await client.chat.completions.create(
209
+ model=model,
210
+ messages=chat_history,
211
+ temperature=1,
212
+ max_tokens=completion_tokens,
213
+ top_p=1,
214
+ stream=True,
215
+ stop=None,
216
+ )
217
+ except groq.APIStatusError as e:
218
+ _raise_for_groq_error(e)
219
 
220
  async def generate():
221
  response_content = ""