rairo commited on
Commit
c134f97
·
verified ·
1 Parent(s): 943ebad

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +65 -31
main.py CHANGED
@@ -45,16 +45,9 @@ except Exception as e:
45
  try:
46
  gemini_api_key = os.environ.get("Gemini")
47
  if not gemini_api_key: raise ValueError("The 'Gemini' environment variable for the API key is not set.")
48
-
49
- # --- FINAL CORRECTED SDK PATTERN ---
50
- # 1. Instantiate the client object.
51
  client = genai.Client(api_key=gemini_api_key)
52
- # 2. Define the model name as a simple string.
53
  MODEL_NAME = 'gemini-2.0-flash'
54
- # --- END OF CORRECTION ---
55
-
56
  logger.info(f"Google GenAI Client initialized successfully for model {MODEL_NAME}.")
57
-
58
  ELEVENLABS_API_KEY = os.environ.get("ELEVENLABS_API_KEY")
59
  if not ELEVENLABS_API_KEY: raise ValueError("The 'ELEVENLABS_API_KEY' environment variable is not set.")
60
  logger.info("ElevenLabs API Key loaded.")
@@ -106,6 +99,37 @@ def extract_text_from_input(file, text):
106
  # -----------------------------------------------------------------------------
107
  # 3. AI LOGIC FUNCTIONS
108
  # -----------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  def detect_use_case_with_gemini(text):
110
  logger.info("Starting use case detection with Gemini.")
111
  prompt = f"""
@@ -115,7 +139,6 @@ def detect_use_case_with_gemini(text):
115
  Text: "{text[:4000]}"
116
  """
117
  try:
118
- # CORRECTED: Use the client.models.generate_content method.
119
  response = client.models.generate_content(model=MODEL_NAME, contents=prompt)
120
  category = response.text.strip().replace("'", "").replace('"', '')
121
  valid_categories = ['Job Interview', 'Investor Pitch', 'Academic Presentation']
@@ -146,30 +169,26 @@ def analyze_transcript_with_gemini(uid, project_id, transcript, duration_seconds
146
  project_data = project_ref.get()
147
  if not project_data: raise ValueError("Project not found for analysis.")
148
  use_case = project_data.get('detectedUseCase', 'General')
149
- briefing_text = project_data.get('originalBriefingText', '')
 
150
  prompt = f"""
151
- You are an expert performance coach and communication analyst. Your task is to analyze the following transcript of a mock '{use_case}'.
152
- The user's original goal was based on this document: "{briefing_text[:2000]}"
153
- Your analysis must be structured as a valid JSON object. Do not include any text before or after the JSON object.
154
- Evaluate the user's performance on these four core criteria:
155
- 1. Communication Skills (clarity, conciseness, confidence)
156
- 2. Content Mastery (subject knowledge, ability to logically support claims)
157
- 3. Engagement & Delivery (tone, pacing, audience awareness)
158
- 4. Resilience Under Pressure (staying composed when challenged, handling unexpected questions)
159
- Based on these criteria, provide the following in your JSON response:
160
- - A score from 0 to 100 for each of the four criteria.
161
- - A "qualitativeStrengths" string summarizing 2-3 key things the user did well.
162
- - A "qualitativeImprovements" string outlining 2-3 actionable areas for improvement.
163
- - A "contextSpecificFeedback" string with feedback tailored to the '{use_case}' context. {_get_context_specific_instructions(use_case)}
164
  The JSON structure MUST be:
165
  {{
166
  "communicationScore": <integer>, "contentMasteryScore": <integer>, "engagementDeliveryScore": <integer>,
167
  "resilienceScore": <integer>, "qualitativeStrengths": "<string>", "qualitativeImprovements": "<string>",
168
  "contextSpecificFeedback": "<string>"
169
  }}
170
- Transcript to analyze: "{transcript}"
 
171
  """
172
- # CORRECTED: Use the client.models.generate_content method.
173
  response = client.models.generate_content(model=MODEL_NAME, contents=prompt)
174
  feedback_json_text = response.text.strip().lstrip("```json").rstrip("```")
175
  feedback_data = json.loads(feedback_json_text)
@@ -201,9 +220,13 @@ def generate_agent_briefing(uid, project_id):
201
  project_data = project_ref.get()
202
  if not project_data: raise ValueError("Project not found.")
203
  use_case = project_data.get('detectedUseCase', 'General')
204
- briefing_text = project_data.get('originalBriefingText', '')
 
 
 
 
 
205
  sessions = project_data.get('practiceSessions', {})
206
- base_briefing = f"This is a mock '{use_case}'. The user's context is based on the following document: '{briefing_text[:1000]}'. Your goal is to act as a realistic {use_case.split(' ')[0]} interviewer/panelist."
207
  if not sessions: return f"{base_briefing} This is the user's first practice session for this project. Start with some introductory questions."
208
  try:
209
  past_feedback_summary = []
@@ -223,7 +246,6 @@ def generate_agent_briefing(uid, project_id):
223
  - "The user struggles with concise communication. Ask multi-part questions to test their ability to stay on track."
224
  Your directive for the agent:
225
  """
226
- # CORRECTED: Use the client.models.generate_content method.
227
  response = client.models.generate_content(model=MODEL_NAME, contents=summary_prompt)
228
  dynamic_directive = response.text.strip()
229
  logger.info(f"Generated dynamic directive for agent: {dynamic_directive}")
@@ -232,6 +254,7 @@ def generate_agent_briefing(uid, project_id):
232
  logger.error(f"Could not generate dynamic briefing for project {project_id}: {e}")
233
  return base_briefing
234
 
 
235
  # -----------------------------------------------------------------------------
236
  # 4. USER & AUTHENTICATION ENDPOINTS
237
  # -----------------------------------------------------------------------------
@@ -300,14 +323,24 @@ def create_project():
300
  return jsonify({'error': 'Insufficient credits to create a project.'}), 402
301
  try:
302
  briefing_text = extract_text_from_input(request.files.get('file'), request.form.get('text'))
 
 
 
303
  detected_use_case = detect_use_case_with_gemini(briefing_text)
 
304
  project_id = str(uuid.uuid4())
305
  project_ref = db_ref.child(f'projects/{uid}/{project_id}')
306
- title = ' '.join(briefing_text.split()[:8]) + '...'
307
  project_data = {
308
- "projectId": project_id, "userId": uid, "title": title,
309
- "detectedUseCase": detected_use_case, "originalBriefingText": briefing_text,
310
- "createdAt": datetime.utcnow().isoformat() + "Z", "practiceSessions": {}
 
 
 
 
 
 
311
  }
312
  project_ref.set(project_data)
313
  user_ref.update({'credits': user_data.get('credits', 0) - 1})
@@ -318,6 +351,7 @@ def create_project():
318
  logger.error(f"Project creation failed for user {uid}: {e}")
319
  return jsonify({'error': 'An internal server error occurred.'}), 500
320
 
 
321
  @app.route('/api/projects', methods=['GET'])
322
  def list_projects():
323
  uid = verify_token(request.headers.get('Authorization'))
 
45
  try:
46
  gemini_api_key = os.environ.get("Gemini")
47
  if not gemini_api_key: raise ValueError("The 'Gemini' environment variable for the API key is not set.")
 
 
 
48
  client = genai.Client(api_key=gemini_api_key)
 
49
  MODEL_NAME = 'gemini-2.0-flash'
 
 
50
  logger.info(f"Google GenAI Client initialized successfully for model {MODEL_NAME}.")
 
51
  ELEVENLABS_API_KEY = os.environ.get("ELEVENLABS_API_KEY")
52
  if not ELEVENLABS_API_KEY: raise ValueError("The 'ELEVENLABS_API_KEY' environment variable is not set.")
53
  logger.info("ElevenLabs API Key loaded.")
 
99
  # -----------------------------------------------------------------------------
100
  # 3. AI LOGIC FUNCTIONS
101
  # -----------------------------------------------------------------------------
102
+
103
+ def summarize_and_extract_context_with_gemini(text):
104
+ """
105
+ **NEW**: Uses Gemini to intelligently summarize the user's document.
106
+ """
107
+ logger.info("Starting intelligent context extraction with Gemini.")
108
+ prompt = f"""
109
+ You are an expert document analyst. Analyze the following document text and perform two tasks:
110
+ 1. Generate a concise, one-sentence "short_description" of the document's overall purpose.
111
+ 2. Extract the "key_points" that are most critical for a mock interview or pitch scenario. This should be a dense paragraph or a few bullet points.
112
+
113
+ Your entire response MUST be a single, valid JSON object with the keys "short_description" and "key_points". Do not include any text before or after the JSON.
114
+
115
+ Document Text:
116
+ "{text}"
117
+ """
118
+ try:
119
+ response = client.models.generate_content(model=MODEL_NAME, contents=prompt)
120
+ # Clean up the response to ensure it's valid JSON
121
+ json_text = response.text.strip().lstrip("```json").rstrip("```")
122
+ data = json.loads(json_text)
123
+ logger.info("Successfully extracted intelligent context.")
124
+ return data
125
+ except Exception as e:
126
+ logger.error(f"Error during intelligent context extraction: {e}")
127
+ # Fallback to a simple truncation if the AI fails
128
+ return {
129
+ "short_description": "User-provided project document.",
130
+ "key_points": text[:1000]
131
+ }
132
+
133
  def detect_use_case_with_gemini(text):
134
  logger.info("Starting use case detection with Gemini.")
135
  prompt = f"""
 
139
  Text: "{text[:4000]}"
140
  """
141
  try:
 
142
  response = client.models.generate_content(model=MODEL_NAME, contents=prompt)
143
  category = response.text.strip().replace("'", "").replace('"', '')
144
  valid_categories = ['Job Interview', 'Investor Pitch', 'Academic Presentation']
 
169
  project_data = project_ref.get()
170
  if not project_data: raise ValueError("Project not found for analysis.")
171
  use_case = project_data.get('detectedUseCase', 'General')
172
+ # **MODIFIED**: Use the high-quality key_points for context in the analysis prompt
173
+ context_text = project_data.get('key_points', project_data.get('originalBriefingText', ''))
174
  prompt = f"""
175
+ You are an expert performance coach. The user was practicing for a mock '{use_case}'.
176
+ Their session was based on a document with these key points: "{context_text}"
177
+
178
+ Your task is to analyze the following transcript. Your analysis must be a valid JSON object.
179
+ Evaluate on: Communication Skills, Content Mastery, Engagement & Delivery, and Resilience Under Pressure.
180
+
181
+ Provide: A score (0-100) for each, "qualitativeStrengths", "qualitativeImprovements", and "contextSpecificFeedback".
182
+
 
 
 
 
 
183
  The JSON structure MUST be:
184
  {{
185
  "communicationScore": <integer>, "contentMasteryScore": <integer>, "engagementDeliveryScore": <integer>,
186
  "resilienceScore": <integer>, "qualitativeStrengths": "<string>", "qualitativeImprovements": "<string>",
187
  "contextSpecificFeedback": "<string>"
188
  }}
189
+
190
+ Transcript: "{transcript}"
191
  """
 
192
  response = client.models.generate_content(model=MODEL_NAME, contents=prompt)
193
  feedback_json_text = response.text.strip().lstrip("```json").rstrip("```")
194
  feedback_data = json.loads(feedback_json_text)
 
220
  project_data = project_ref.get()
221
  if not project_data: raise ValueError("Project not found.")
222
  use_case = project_data.get('detectedUseCase', 'General')
223
+
224
+ # **MODIFIED**: Use the high-quality key_points instead of raw text truncation.
225
+ key_points = project_data.get('key_points', 'No specific context was extracted.')
226
+
227
+ base_briefing = f"This is a mock '{use_case}'. The user's context is based on a document with these key points: '{key_points}'. Your goal is to act as a realistic {use_case.split(' ')[0]} interviewer/panelist and ask relevant questions."
228
+
229
  sessions = project_data.get('practiceSessions', {})
 
230
  if not sessions: return f"{base_briefing} This is the user's first practice session for this project. Start with some introductory questions."
231
  try:
232
  past_feedback_summary = []
 
246
  - "The user struggles with concise communication. Ask multi-part questions to test their ability to stay on track."
247
  Your directive for the agent:
248
  """
 
249
  response = client.models.generate_content(model=MODEL_NAME, contents=summary_prompt)
250
  dynamic_directive = response.text.strip()
251
  logger.info(f"Generated dynamic directive for agent: {dynamic_directive}")
 
254
  logger.error(f"Could not generate dynamic briefing for project {project_id}: {e}")
255
  return base_briefing
256
 
257
+
258
  # -----------------------------------------------------------------------------
259
  # 4. USER & AUTHENTICATION ENDPOINTS
260
  # -----------------------------------------------------------------------------
 
323
  return jsonify({'error': 'Insufficient credits to create a project.'}), 402
324
  try:
325
  briefing_text = extract_text_from_input(request.files.get('file'), request.form.get('text'))
326
+
327
+ # **MODIFIED**: Call the new AI functions for intelligent processing
328
+ context_data = summarize_and_extract_context_with_gemini(briefing_text)
329
  detected_use_case = detect_use_case_with_gemini(briefing_text)
330
+
331
  project_id = str(uuid.uuid4())
332
  project_ref = db_ref.child(f'projects/{uid}/{project_id}')
333
+
334
  project_data = {
335
+ "projectId": project_id,
336
+ "userId": uid,
337
+ "title": context_data.get('short_description', 'New Project'), # Use intelligent description for title
338
+ "detectedUseCase": detected_use_case,
339
+ "originalBriefingText": briefing_text, # Keep the original for reference
340
+ "key_points": context_data.get('key_points'), # **NEW** field
341
+ "short_description": context_data.get('short_description'), # **NEW** field
342
+ "createdAt": datetime.utcnow().isoformat() + "Z",
343
+ "practiceSessions": {}
344
  }
345
  project_ref.set(project_data)
346
  user_ref.update({'credits': user_data.get('credits', 0) - 1})
 
351
  logger.error(f"Project creation failed for user {uid}: {e}")
352
  return jsonify({'error': 'An internal server error occurred.'}), 500
353
 
354
+ # ... [The rest of the endpoints from /api/projects (GET) to the end of the file remain unchanged] ...
355
  @app.route('/api/projects', methods=['GET'])
356
  def list_projects():
357
  uid = verify_token(request.headers.get('Authorization'))