|
import os |
|
from anthropic import Anthropic |
|
import gradio as gr |
|
|
|
|
|
class ClinicalVoiceAnalyzer: |
|
def __init__(self): |
|
|
|
self.anthropic = None |
|
self.model = "claude-3-opus-20240229" |
|
self.api_key = os.getenv('ANTHROPIC_API_KEY') |
|
|
|
|
|
self.reference_ranges = { |
|
'pitch': {'min': 150, 'max': 400}, |
|
'tempo': {'min': 90, 'max': 130}, |
|
'energy': {'min': 0.01, 'max': 0.05} |
|
} |
|
|
|
|
|
self._initialize_anthropic() |
|
|
|
def _initialize_anthropic(self): |
|
"""Safely initialize the Anthropic client""" |
|
try: |
|
if self.api_key: |
|
self.anthropic = Anthropic(api_key=self.api_key) |
|
print("Anthropic client initialized successfully") |
|
else: |
|
print("Warning: ANTHROPIC_API_KEY not found in environment variables") |
|
except Exception as e: |
|
print(f"Error initializing Anthropic client: {str(e)}") |
|
self.anthropic = None |
|
|
|
def generate_clinical_analysis(self, voice_features): |
|
"""Generate clinical analysis with fallback behavior""" |
|
if not self.anthropic: |
|
return self._generate_fallback_analysis(voice_features), {} |
|
|
|
try: |
|
prompt = self._construct_analysis_prompt(voice_features) |
|
response = self.anthropic.messages.create( |
|
model=self.model, |
|
max_tokens=1000, |
|
messages=[{ |
|
"role": "user", |
|
"content": prompt |
|
}] |
|
) |
|
return response.content, self._parse_clinical_response(response.content) |
|
except Exception as e: |
|
print(f"Error in clinical analysis: {str(e)}") |
|
return self._generate_fallback_analysis(voice_features), {} |
|
|
|
def _generate_fallback_analysis(self, features): |
|
"""Generate basic analysis when Anthropic API is unavailable""" |
|
pitch_status = "elevated" if features['pitch_mean'] > self.reference_ranges['pitch']['max'] else "normal" |
|
tempo_status = "elevated" if features['tempo'] > self.reference_ranges['tempo']['max'] else "normal" |
|
|
|
return f"""Basic Voice Analysis: |
|
|
|
Pitch Analysis: {pitch_status} ({features['pitch_mean']:.2f} Hz) |
|
Speech Rate: {tempo_status} ({features['tempo']:.2f} BPM) |
|
Energy Level: {features['energy_mean']:.4f} |
|
|
|
Note: This is a basic analysis. For detailed clinical interpretation, please ensure the Anthropic API key is configured.""" |
|
|
|
|
|
|
|
|
|
def analyze_audio(audio_input): |
|
try: |
|
|
|
|
|
|
|
clinical_analyzer = ClinicalVoiceAnalyzer() |
|
clinical_analysis, clinical_insights = clinical_analyzer.generate_clinical_analysis(features) |
|
|
|
|
|
summary = f"""Voice Analysis Summary: |
|
|
|
Speech Content: |
|
{transcription} |
|
|
|
Voice Characteristics: |
|
- Average Pitch: {features['pitch_mean']:.2f} Hz |
|
- Pitch Variation: {features['pitch_std']:.2f} Hz |
|
- Speech Rate (Tempo): {features['tempo']:.2f} BPM |
|
- Voice Energy: {features['energy_mean']:.4f} |
|
|
|
Dominant Emotion: {max(emotion_scores.items(), key=lambda x: x[1])[0]} |
|
|
|
Clinical Analysis: |
|
{clinical_analysis} |
|
""" |
|
return summary, emotion_viz, feature_viz, clinical_insights |
|
|
|
except Exception as e: |
|
error_msg = f"Error in audio analysis: {str(e)}" |
|
print(error_msg) |
|
return error_msg, None, None, None |
|
|
|
|
|
|
|
|
|
demo = gr.Interface( |
|
fn=analyze_audio, |
|
inputs=gr.Audio( |
|
sources=["microphone", "upload"], |
|
type="filepath", |
|
label="Audio Input" |
|
), |
|
outputs=[ |
|
gr.Textbox(label="Analysis Summary", lines=15), |
|
gr.HTML(label="Emotion Analysis"), |
|
gr.HTML(label="Voice Feature Analysis"), |
|
gr.JSON(label="Clinical Insights") |
|
], |
|
title="Advanced Voice Analysis System", |
|
description="""This system provides comprehensive voice analysis with clinical interpretation. |
|
Upload an audio file or record directly through your microphone.""" |
|
) |