Girish Jeswani commited on
Commit
05e445e
·
1 Parent(s): 00b17e7

modify response length

Browse files
multi_llm_chatbot_backend/app/llm/gemini_client.py CHANGED
@@ -1,11 +1,13 @@
1
  import httpx
2
  import os
3
- import json
4
  from typing import List
5
  from app.llm.llm_client import LLMClient
6
 
7
  class GeminiClient(LLMClient):
8
- def __init__(self, model_name: str = os.getenv("GEMINI_MODEL")):
 
 
 
9
  self.model_name = model_name
10
  self.api_key = os.getenv("GEMINI_API_KEY")
11
  if not self.api_key:
@@ -14,36 +16,31 @@ class GeminiClient(LLMClient):
14
  self.base_url = "https://generativelanguage.googleapis.com/v1beta/models"
15
 
16
  async def generate(self, system_prompt: str, context: List[dict]) -> str:
 
 
 
17
  # Format messages for Gemini API
18
  formatted_messages = []
19
 
20
- # Add system instruction
21
  if system_prompt:
22
  formatted_messages.append({
23
  "role": "user",
24
- "parts": [{"text": f"System instruction: {system_prompt}"}]
25
  })
26
  formatted_messages.append({
27
  "role": "model",
28
- "parts": [{"text": "I understand. I'll follow these instructions in our conversation."}]
29
  })
30
 
31
- # Add conversation history
32
- for msg in context:
33
- role = msg['role'].lower()
34
- content = msg['content']
35
-
36
- if role == "user":
37
  formatted_messages.append({
38
  "role": "user",
39
- "parts": [{"text": content}]
40
- })
41
- elif role in ["methodist", "theorist", "pragmatist"]:
42
- # These are previous advisor responses, treat as model responses
43
- formatted_messages.append({
44
- "role": "model",
45
- "parts": [{"text": content}]
46
  })
 
47
 
48
  payload = {
49
  "contents": formatted_messages,
@@ -51,8 +48,8 @@ class GeminiClient(LLMClient):
51
  "temperature": 0.7,
52
  "topK": 40,
53
  "topP": 0.9,
54
- "maxOutputTokens": 200,
55
- "stopSequences": []
56
  },
57
  "safetySettings": [
58
  {
@@ -91,18 +88,65 @@ class GeminiClient(LLMClient):
91
  if len(parts) > 0 and "text" in parts[0]:
92
  text = parts[0]["text"].strip()
93
 
94
- # Clean up common response patterns
95
- text = text.replace("Here are 2-3 sentence", "").strip()
96
- text = text.replace("Here's an expansion of the advice:", "").strip()
97
 
98
- if len(text) < 10 or text in [":", ".", ""]:
99
- return "I'd be happy to help with that. Could you provide more specific details about what you're looking for?"
 
100
 
101
  return text
102
 
103
- return "I apologize, but I'm having trouble generating a response right now. Please try again."
104
 
105
  except httpx.HTTPError as e:
106
- return f"I apologize, but I'm having trouble connecting to generate a response. Please try again."
 
107
  except Exception as e:
108
- return f"I apologize, but I'm having trouble generating a response right now. Please try again."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import httpx
2
  import os
 
3
  from typing import List
4
  from app.llm.llm_client import LLMClient
5
 
6
  class GeminiClient(LLMClient):
7
+ def __init__(self, model_name: str = None):
8
+ if model_name is None:
9
+ model_name = os.getenv("GEMINI_MODEL", "gemini-2.0-flash-exp")
10
+
11
  self.model_name = model_name
12
  self.api_key = os.getenv("GEMINI_API_KEY")
13
  if not self.api_key:
 
16
  self.base_url = "https://generativelanguage.googleapis.com/v1beta/models"
17
 
18
  async def generate(self, system_prompt: str, context: List[dict]) -> str:
19
+ # Build focused context - only include recent relevant messages
20
+ recent_context = context[-3:] if len(context) > 3 else context
21
+
22
  # Format messages for Gemini API
23
  formatted_messages = []
24
 
25
+ # Add system instruction as initial conversation
26
  if system_prompt:
27
  formatted_messages.append({
28
  "role": "user",
29
+ "parts": [{"text": system_prompt}]
30
  })
31
  formatted_messages.append({
32
  "role": "model",
33
+ "parts": [{"text": "I understand. I'll follow these instructions."}]
34
  })
35
 
36
+ # Add only the user's current question
37
+ for msg in recent_context:
38
+ if msg['role'] == 'user':
 
 
 
39
  formatted_messages.append({
40
  "role": "user",
41
+ "parts": [{"text": msg['content']}]
 
 
 
 
 
 
42
  })
43
+ break # Only use most recent user message
44
 
45
  payload = {
46
  "contents": formatted_messages,
 
48
  "temperature": 0.7,
49
  "topK": 40,
50
  "topP": 0.9,
51
+ "maxOutputTokens": 150, # Reduced from default to ensure concise responses
52
+ "stopSequences": ["Student:", "Question:", "\n\nStudent:", "\n\nQuestion:"]
53
  },
54
  "safetySettings": [
55
  {
 
88
  if len(parts) > 0 and "text" in parts[0]:
89
  text = parts[0]["text"].strip()
90
 
91
+ # Clean up response
92
+ text = self._clean_response(text)
 
93
 
94
+ # Validate response quality
95
+ if len(text) < 20 or self._is_poor_quality(text):
96
+ return self._get_fallback_response()
97
 
98
  return text
99
 
100
+ return self._get_fallback_response()
101
 
102
  except httpx.HTTPError as e:
103
+ print(f"HTTP error calling Gemini API: {e}")
104
+ return "I'm having trouble connecting to generate a response. Please try again."
105
  except Exception as e:
106
+ print(f"Error calling Gemini API: {e}")
107
+ return "I'm having trouble generating a response right now. Please try again."
108
+
109
+ def _clean_response(self, response: str) -> str:
110
+ """Clean up Gemini responses"""
111
+ # Remove common prefixes that indicate AI confusion
112
+ prefixes_to_remove = [
113
+ "Dr. Methodist:", "Dr. Theorist:", "Dr. Pragmatist:",
114
+ "Methodist Advisor:", "Theorist Advisor:", "Pragmatist Advisor:",
115
+ "As Dr.", "Here's my response:", "Response:", "Assistant:",
116
+ "Here are 2-3 sentence", "Here's an expansion of the advice:",
117
+ ]
118
+
119
+ for prefix in prefixes_to_remove:
120
+ if response.startswith(prefix):
121
+ response = response[len(prefix):].strip()
122
+
123
+ # Remove excessive academic fluff
124
+ fluff_patterns = [
125
+ "conceptual insights:", "actionable advice:", "my inquisitive student",
126
+ "excellent question", "thank you for", "assistant!", "excellent discussion"
127
+ ]
128
+
129
+ for pattern in fluff_patterns:
130
+ response = response.replace(pattern, "").strip()
131
+
132
+ # Remove trailing incomplete sentences
133
+ sentences = response.split('.')
134
+ if len(sentences) > 1 and len(sentences[-1].strip()) < 10:
135
+ response = '.'.join(sentences[:-1]) + '.'
136
+
137
+ return response
138
+
139
+ def _is_poor_quality(self, response: str) -> bool:
140
+ """Check if response quality is poor"""
141
+ poor_indicators = [
142
+ "Thank you, Dr." in response, # AI confusion about identity
143
+ "Assistant:" in response,
144
+ len(response.split()) > 100, # Too verbose
145
+ response.count("?") > 3, # Too many questions
146
+ "excellent discussion, Assistant" in response,
147
+ ]
148
+ return any(poor_indicators)
149
+
150
+ def _get_fallback_response(self) -> str:
151
+ """Return a simple fallback when quality is poor"""
152
+ return "I'd be happy to help with that. Could you provide more specific details about what you're looking for?"