SreekarB commited on
Commit
b5be089
·
verified ·
1 Parent(s): d1b6c1c

Upload simple_casl_app.py

Browse files
Files changed (1) hide show
  1. simple_casl_app.py +192 -23
simple_casl_app.py CHANGED
@@ -107,7 +107,7 @@ else:
107
  logger.warning("Claude API key not found - using demo mode")
108
 
109
  def validate_analysis_completeness(response_text):
110
- """Validate that all 12 sections are present in the analysis"""
111
  required_sections = [
112
  "1. SPEECH FACTORS",
113
  "2. LANGUAGE SKILLS ASSESSMENT",
@@ -124,25 +124,129 @@ def validate_analysis_completeness(response_text):
124
  ]
125
 
126
  missing_sections = []
 
 
 
127
  for section in required_sections:
128
- if section not in response_text:
 
 
129
  missing_sections.append(section)
 
 
 
 
 
 
 
 
 
130
 
131
  if missing_sections:
132
  print(f"\n⚠️ MISSING SECTIONS: {missing_sections}")
133
- return False
 
 
 
134
  else:
135
- print(f"\n✅ ALL 12 SECTIONS PRESENT")
136
- return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
  def call_claude_api_with_continuation(prompt, max_continuations=3):
139
  """Call Claude API with continuation prompting to ensure complete responses"""
140
  if not ANTHROPIC_API_KEY:
141
  return "❌ Claude API key not configured. Please set ANTHROPIC_API_KEY environment variable."
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  try:
144
- full_response = ""
145
  continuation_count = 0
 
146
 
147
  # Add continuation instruction to original prompt
148
  initial_prompt = prompt + "\n\nIMPORTANT: If your response is cut off or incomplete, end with <CONTINUE> to indicate more content is needed. Ensure you complete all sections of the analysis."
@@ -190,29 +294,28 @@ def call_claude_api_with_continuation(prompt, max_continuations=3):
190
  print(f"Last 200 chars: {response_text[-200:]}...")
191
  print("=" * 50)
192
 
193
- # Simple string combination - no complex processing
194
- if continuation_count == 0:
195
- full_response = response_text
196
- else:
197
- # Just add a newline and append the continuation
198
- full_response += "\n\n" + response_text
 
199
 
200
  # Check if response indicates continuation is needed
201
  needs_continuation = "<CONTINUE>" in response_text
202
 
203
  print(f"Needs continuation: {needs_continuation}")
204
  print(f"Continuation count: {continuation_count}/{max_continuations}")
 
 
205
 
206
  # Continue if <CONTINUE> is present and we haven't reached max
207
  if needs_continuation and continuation_count < max_continuations:
208
- # Remove the CONTINUE marker
209
- full_response = full_response.replace("<CONTINUE>", "")
210
  continuation_count += 1
211
  logger.info(f"Continuing analysis (attempt {continuation_count}/{max_continuations})")
212
  continue
213
  else:
214
- # Clean up any remaining continuation markers
215
- full_response = full_response.replace("<CONTINUE>", "")
216
  break
217
  else:
218
  logger.error(f"Claude API error: {response.status_code} - {response.text}")
@@ -222,16 +325,36 @@ def call_claude_api_with_continuation(prompt, max_continuations=3):
222
  logger.error(f"Error calling Claude API: {str(e)}")
223
  return f"❌ Error: {str(e)}"
224
 
225
- # Add completion indicator
226
- if continuation_count > 0:
227
- full_response += f"\n\n[Analysis completed in {continuation_count + 1} parts]"
 
 
 
 
 
228
 
229
- # Log final response for debugging
230
- print(f"\n=== FINAL COMPLETE RESPONSE ===")
231
- print(f"Total length: {len(full_response)} characters")
232
- print(f"Number of parts: {continuation_count + 1}")
 
 
 
 
 
 
 
 
 
 
 
233
  print("=" * 50)
234
 
 
 
 
 
235
  # Print the entire final response for debugging
236
  print(f"\n=== ENTIRE FINAL RESPONSE ===")
237
  print(full_response)
@@ -750,6 +873,30 @@ def analyze_transcript_content(transcript_content, age, gender, slp_notes):
750
 
751
  # Get analysis from Claude API
752
  result = call_claude_api_with_continuation(prompt, max_continuations=5)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
753
  return result
754
 
755
  def analyze_transcript(file, age, gender, slp_notes):
@@ -874,6 +1021,14 @@ def targeted_analysis(transcript, custom_question, age, gender, slp_notes):
874
 
875
  # Get targeted analysis from Claude API
876
  result = call_claude_api_with_continuation(prompt, max_continuations=3)
 
 
 
 
 
 
 
 
877
  return result
878
 
879
  # Create enhanced interface with tabs
@@ -1312,6 +1467,20 @@ with gr.Blocks(title="Enhanced CASL Analysis", theme=gr.themes.Soft()) as app:
1312
  """
1313
 
1314
  result = call_claude_api_with_continuation(prompt, max_continuations=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1315
  progress_msg = "✅ Quick analysis completed" if "[Analysis completed in" in result else "🔄 Quick analysis in progress..."
1316
  return result, progress_msg
1317
 
 
107
  logger.warning("Claude API key not found - using demo mode")
108
 
109
  def validate_analysis_completeness(response_text):
110
+ """Validate that all 12 sections are present in the analysis exactly once"""
111
  required_sections = [
112
  "1. SPEECH FACTORS",
113
  "2. LANGUAGE SKILLS ASSESSMENT",
 
124
  ]
125
 
126
  missing_sections = []
127
+ duplicate_sections = []
128
+ section_counts = {}
129
+
130
  for section in required_sections:
131
+ count = response_text.count(section)
132
+ section_counts[section] = count
133
+ if count == 0:
134
  missing_sections.append(section)
135
+ elif count > 1:
136
+ duplicate_sections.append(section)
137
+
138
+ # Log detailed validation results
139
+ print(f"\n=== COMPREHENSIVE VALIDATION ===")
140
+ print(f"Total response length: {len(response_text)} characters")
141
+ print(f"Missing sections: {missing_sections}")
142
+ print(f"Duplicate sections: {duplicate_sections}")
143
+ print(f"Section counts: {section_counts}")
144
 
145
  if missing_sections:
146
  print(f"\n⚠️ MISSING SECTIONS: {missing_sections}")
147
+ return False, missing_sections, duplicate_sections, section_counts
148
+ elif duplicate_sections:
149
+ print(f"\n⚠️ DUPLICATE SECTIONS: {duplicate_sections}")
150
+ return False, missing_sections, duplicate_sections, section_counts
151
  else:
152
+ print(f"\n✅ ALL 12 SECTIONS PRESENT EXACTLY ONCE")
153
+ return True, missing_sections, duplicate_sections, section_counts
154
+
155
+ def fix_incomplete_analysis(response_text, missing_sections):
156
+ """Attempt to fix incomplete analysis by requesting missing sections"""
157
+ if not missing_sections:
158
+ return response_text
159
+
160
+ if not ANTHROPIC_API_KEY:
161
+ return response_text + "\n\n❌ Cannot fix incomplete analysis - API key not configured"
162
+
163
+ try:
164
+ # Create a focused prompt for missing sections
165
+ missing_sections_text = "\n".join([f"- {section}" for section in missing_sections])
166
+
167
+ fix_prompt = f"""
168
+ The following sections are missing from the CASL analysis. Please provide ONLY these missing sections:
169
+
170
+ {missing_sections_text}
171
+
172
+ IMPORTANT:
173
+ - Provide ONLY the missing sections listed above
174
+ - Do not repeat any sections that are already present
175
+ - Use the exact section headers as shown above
176
+ - Make each section comprehensive and detailed
177
+ - Ensure clinical accuracy and appropriate depth for SLP assessment
178
+ """
179
+
180
+ headers = {
181
+ "Content-Type": "application/json",
182
+ "x-api-key": ANTHROPIC_API_KEY,
183
+ "anthropic-version": "2023-06-01"
184
+ }
185
+
186
+ data = {
187
+ "model": "claude-3-5-sonnet-20241022",
188
+ "max_tokens": 4096,
189
+ "messages": [
190
+ {
191
+ "role": "user",
192
+ "content": fix_prompt
193
+ }
194
+ ]
195
+ }
196
+
197
+ response = requests.post(
198
+ "https://api.anthropic.com/v1/messages",
199
+ headers=headers,
200
+ json=data,
201
+ timeout=90
202
+ )
203
+
204
+ if response.status_code == 200:
205
+ response_json = response.json()
206
+ fix_text = response_json['content'][0]['text']
207
+
208
+ # Combine original response with fix
209
+ complete_response = response_text + "\n\n" + fix_text
210
+
211
+ print(f"\n=== FIXED INCOMPLETE ANALYSIS ===")
212
+ print(f"Added missing sections: {missing_sections}")
213
+ print(f"Fix text length: {len(fix_text)} characters")
214
+ print("=" * 50)
215
+
216
+ return complete_response
217
+ else:
218
+ logger.error(f"Error fixing incomplete analysis: {response.status_code}")
219
+ return response_text + f"\n\n❌ Error fixing incomplete analysis: {response.status_code}"
220
+
221
+ except Exception as e:
222
+ logger.error(f"Error in fix_incomplete_analysis: {str(e)}")
223
+ return response_text + f"\n\n❌ Error fixing incomplete analysis: {str(e)}"
224
 
225
  def call_claude_api_with_continuation(prompt, max_continuations=3):
226
  """Call Claude API with continuation prompting to ensure complete responses"""
227
  if not ANTHROPIC_API_KEY:
228
  return "❌ Claude API key not configured. Please set ANTHROPIC_API_KEY environment variable."
229
 
230
+ # Define all required sections
231
+ required_sections = [
232
+ "1. SPEECH FACTORS",
233
+ "2. LANGUAGE SKILLS ASSESSMENT",
234
+ "3. COMPLEX SENTENCE ANALYSIS",
235
+ "4. FIGURATIVE LANGUAGE ANALYSIS",
236
+ "5. PRAGMATIC LANGUAGE ASSESSMENT",
237
+ "6. VOCABULARY AND SEMANTIC ANALYSIS",
238
+ "7. MORPHOLOGICAL AND PHONOLOGICAL ANALYSIS",
239
+ "8. COGNITIVE-LINGUISTIC FACTORS",
240
+ "9. FLUENCY AND RHYTHM ANALYSIS",
241
+ "10. QUANTITATIVE METRICS",
242
+ "11. CLINICAL IMPLICATIONS",
243
+ "12. PROGNOSIS AND SUMMARY"
244
+ ]
245
+
246
  try:
247
+ response_parts = [] # Store each part as a separate item
248
  continuation_count = 0
249
+ completed_sections = set() # Track which sections have been completed
250
 
251
  # Add continuation instruction to original prompt
252
  initial_prompt = prompt + "\n\nIMPORTANT: If your response is cut off or incomplete, end with <CONTINUE> to indicate more content is needed. Ensure you complete all sections of the analysis."
 
294
  print(f"Last 200 chars: {response_text[-200:]}...")
295
  print("=" * 50)
296
 
297
+ # Store this part
298
+ response_parts.append(response_text)
299
+
300
+ # Check which sections are present in this part
301
+ for section in required_sections:
302
+ if section in response_text:
303
+ completed_sections.add(section)
304
 
305
  # Check if response indicates continuation is needed
306
  needs_continuation = "<CONTINUE>" in response_text
307
 
308
  print(f"Needs continuation: {needs_continuation}")
309
  print(f"Continuation count: {continuation_count}/{max_continuations}")
310
+ print(f"Completed sections: {len(completed_sections)}/12")
311
+ print(f"Missing sections: {[s for s in required_sections if s not in completed_sections]}")
312
 
313
  # Continue if <CONTINUE> is present and we haven't reached max
314
  if needs_continuation and continuation_count < max_continuations:
 
 
315
  continuation_count += 1
316
  logger.info(f"Continuing analysis (attempt {continuation_count}/{max_continuations})")
317
  continue
318
  else:
 
 
319
  break
320
  else:
321
  logger.error(f"Claude API error: {response.status_code} - {response.text}")
 
325
  logger.error(f"Error calling Claude API: {str(e)}")
326
  return f"❌ Error: {str(e)}"
327
 
328
+ # Combine all parts and clean up
329
+ full_response = "\n\n".join(response_parts)
330
+ full_response = full_response.replace("<CONTINUE>", "")
331
+
332
+ # Validate completeness
333
+ missing_sections = []
334
+ duplicate_sections = []
335
+ section_counts = {}
336
 
337
+ for section in required_sections:
338
+ count = full_response.count(section)
339
+ section_counts[section] = count
340
+ if count == 0:
341
+ missing_sections.append(section)
342
+ elif count > 1:
343
+ duplicate_sections.append(section)
344
+
345
+ # Log validation results
346
+ print(f"\n=== VALIDATION RESULTS ===")
347
+ print(f"Total response length: {len(full_response)} characters")
348
+ print(f"Number of parts: {len(response_parts)}")
349
+ print(f"Missing sections: {missing_sections}")
350
+ print(f"Duplicate sections: {duplicate_sections}")
351
+ print(f"Section counts: {section_counts}")
352
  print("=" * 50)
353
 
354
+ # Add completion indicator
355
+ if len(response_parts) > 1:
356
+ full_response += f"\n\n[Analysis completed in {len(response_parts)} parts]"
357
+
358
  # Print the entire final response for debugging
359
  print(f"\n=== ENTIRE FINAL RESPONSE ===")
360
  print(full_response)
 
873
 
874
  # Get analysis from Claude API
875
  result = call_claude_api_with_continuation(prompt, max_continuations=5)
876
+
877
+ # Validate completeness and fix if needed
878
+ is_complete, missing_sections, duplicate_sections, section_counts = validate_analysis_completeness(result)
879
+
880
+ if not is_complete:
881
+ print(f"\n🔧 ATTEMPTING TO FIX INCOMPLETE ANALYSIS...")
882
+ print(f"Missing sections: {missing_sections}")
883
+ print(f"Duplicate sections: {duplicate_sections}")
884
+
885
+ # Try to fix missing sections
886
+ if missing_sections:
887
+ result = fix_incomplete_analysis(result, missing_sections)
888
+
889
+ # Re-validate after fix
890
+ is_complete_after_fix, missing_after_fix, duplicate_after_fix, counts_after_fix = validate_analysis_completeness(result)
891
+
892
+ if not is_complete_after_fix:
893
+ print(f"\n⚠️ ANALYSIS STILL INCOMPLETE AFTER FIX ATTEMPT")
894
+ print(f"Still missing: {missing_after_fix}")
895
+ print(f"Still duplicate: {duplicate_after_fix}")
896
+ result += f"\n\n⚠️ WARNING: Analysis may be incomplete. Missing sections: {missing_after_fix}"
897
+ else:
898
+ print(f"\n✅ ANALYSIS FIXED SUCCESSFULLY")
899
+
900
  return result
901
 
902
  def analyze_transcript(file, age, gender, slp_notes):
 
1021
 
1022
  # Get targeted analysis from Claude API
1023
  result = call_claude_api_with_continuation(prompt, max_continuations=3)
1024
+
1025
+ # For targeted analysis, we don't need the full 12-section validation
1026
+ # but we can still validate that the response is complete and well-structured
1027
+ if len(result.strip()) < 500: # Basic length check
1028
+ print(f"\n⚠️ TARGETED ANALYSIS MAY BE INCOMPLETE")
1029
+ print(f"Response length: {len(result)} characters")
1030
+ result += f"\n\n⚠️ WARNING: This targeted analysis may be incomplete. Please review the results carefully."
1031
+
1032
  return result
1033
 
1034
  # Create enhanced interface with tabs
 
1467
  """
1468
 
1469
  result = call_claude_api_with_continuation(prompt, max_continuations=2)
1470
+
1471
+ # For quick analysis, validate that all selected questions were addressed
1472
+ if questions and len(questions) > 0:
1473
+ missing_questions = []
1474
+ for question in questions:
1475
+ # Check if the question was addressed (basic check)
1476
+ if question.lower() not in result.lower():
1477
+ missing_questions.append(question)
1478
+
1479
+ if missing_questions:
1480
+ print(f"\n⚠️ QUICK ANALYSIS MAY BE INCOMPLETE")
1481
+ print(f"Missing questions: {missing_questions}")
1482
+ result += f"\n\n⚠️ WARNING: Some selected questions may not have been fully addressed: {missing_questions}"
1483
+
1484
  progress_msg = "✅ Quick analysis completed" if "[Analysis completed in" in result else "🔄 Quick analysis in progress..."
1485
  return result, progress_msg
1486