Spaces:
Build error
Build error
Update session_analysis.py
Browse files- session_analysis.py +142 -218
session_analysis.py
CHANGED
|
@@ -317,66 +317,76 @@ def show_manual_input_form():
|
|
| 317 |
analyze_session_content(st.session_state.current_transcript)
|
| 318 |
|
| 319 |
|
| 320 |
-
def analyze_session_content(
|
|
|
|
| 321 |
try:
|
| 322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
model = genai.GenerativeModel('gemini-pro')
|
| 324 |
|
| 325 |
-
#
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
3
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
"""
|
|
|
|
|
|
|
|
|
|
| 365 |
|
| 366 |
-
#
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
# Process and structure the analysis results
|
| 370 |
-
analysis_results = process_analysis_results(response.text)
|
| 371 |
-
|
| 372 |
-
# Store results in session state
|
| 373 |
-
st.session_state.analysis_results = analysis_results
|
| 374 |
-
|
| 375 |
-
# Show success message
|
| 376 |
-
st.success("Analysis completed successfully!")
|
| 377 |
|
|
|
|
|
|
|
| 378 |
except Exception as e:
|
| 379 |
-
st.error(f"Error
|
|
|
|
| 380 |
|
| 381 |
|
| 382 |
def generate_transcript(audio_content):
|
|
@@ -795,78 +805,16 @@ def format_session_data(session_data):
|
|
| 795 |
"""
|
| 796 |
return formatted_text
|
| 797 |
|
| 798 |
-
def analyze_session_content(transcript):
|
| 799 |
-
"""Analyze the session transcript using Gemini"""
|
| 800 |
-
try:
|
| 801 |
-
if not transcript:
|
| 802 |
-
st.warning("Please provide a transcript for analysis.")
|
| 803 |
-
return
|
| 804 |
-
|
| 805 |
-
# Configure the model
|
| 806 |
-
model = genai.GenerativeModel('gemini-pro')
|
| 807 |
-
|
| 808 |
-
# Prepare prompt with structured output request
|
| 809 |
-
prompt = """
|
| 810 |
-
Analyze this MI (Motivational Interviewing) session transcript and provide analysis in the following structured format:
|
| 811 |
-
|
| 812 |
-
MI Adherence Score: [0-100]
|
| 813 |
-
|
| 814 |
-
Key Themes:
|
| 815 |
-
- [Theme 1]
|
| 816 |
-
- [Theme 2]
|
| 817 |
-
- [Theme 3]
|
| 818 |
-
|
| 819 |
-
Technique Usage:
|
| 820 |
-
- Open Questions: [count]
|
| 821 |
-
- Reflections: [count]
|
| 822 |
-
- Affirmations: [count]
|
| 823 |
-
- Summaries: [count]
|
| 824 |
-
|
| 825 |
-
Strengths:
|
| 826 |
-
- [Strength 1]
|
| 827 |
-
- [Strength 2]
|
| 828 |
-
- [Strength 3]
|
| 829 |
-
|
| 830 |
-
Areas for Improvement:
|
| 831 |
-
- [Area 1]
|
| 832 |
-
- [Area 2]
|
| 833 |
-
- [Area 3]
|
| 834 |
-
|
| 835 |
-
Change Talk Instances:
|
| 836 |
-
- [Example 1]
|
| 837 |
-
- [Example 2]
|
| 838 |
-
|
| 839 |
-
Sustain Talk Instances:
|
| 840 |
-
- [Example 1]
|
| 841 |
-
- [Example 2]
|
| 842 |
-
|
| 843 |
-
Session Summary:
|
| 844 |
-
[Brief summary of the session flow and key moments]
|
| 845 |
-
|
| 846 |
-
Transcript to analyze:
|
| 847 |
-
{transcript}
|
| 848 |
-
"""
|
| 849 |
-
|
| 850 |
-
# Generate response
|
| 851 |
-
response = model.generate_content(prompt)
|
| 852 |
-
|
| 853 |
-
# Store results in session state
|
| 854 |
-
st.session_state.analysis_results = response.text
|
| 855 |
-
|
| 856 |
-
# Trigger results display
|
| 857 |
-
show_analysis_results()
|
| 858 |
-
|
| 859 |
-
except Exception as e:
|
| 860 |
-
st.error(f"Error analyzing session: {str(e)}")
|
| 861 |
-
|
| 862 |
|
| 863 |
def show_analysis_results():
|
| 864 |
-
"""Display the analysis results in
|
| 865 |
if 'analysis_results' not in st.session_state or not st.session_state.analysis_results:
|
| 866 |
-
st.info("
|
| 867 |
return
|
| 868 |
|
| 869 |
-
|
|
|
|
|
|
|
| 870 |
tabs = st.tabs([
|
| 871 |
"MI Adherence",
|
| 872 |
"Technical Skills",
|
|
@@ -877,10 +825,10 @@ def show_analysis_results():
|
|
| 877 |
|
| 878 |
# MI Adherence Tab
|
| 879 |
with tabs[0]:
|
| 880 |
-
st.subheader("MI Adherence
|
| 881 |
|
| 882 |
-
# Extract score
|
| 883 |
-
score_match = re.search(r'
|
| 884 |
if score_match:
|
| 885 |
score = int(score_match.group(1))
|
| 886 |
|
|
@@ -889,120 +837,96 @@ def show_analysis_results():
|
|
| 889 |
mode="gauge+number",
|
| 890 |
value=score,
|
| 891 |
domain={'x': [0, 1], 'y': [0, 1]},
|
| 892 |
-
gauge={
|
| 893 |
-
|
| 894 |
-
|
| 895 |
-
|
| 896 |
-
|
| 897 |
-
|
| 898 |
-
|
|
|
|
|
|
|
|
|
|
| 899 |
st.plotly_chart(fig)
|
| 900 |
|
| 901 |
-
#
|
| 902 |
-
|
| 903 |
-
|
| 904 |
st.subheader("Strengths")
|
| 905 |
-
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
| 910 |
-
|
| 911 |
-
|
| 912 |
-
|
| 913 |
-
|
| 914 |
-
|
| 915 |
-
|
| 916 |
-
|
| 917 |
-
|
| 918 |
-
|
| 919 |
-
# Technical Skills Tab
|
| 920 |
-
with tabs[1]:
|
| 921 |
-
st.subheader("MI Technique Usage")
|
| 922 |
-
|
| 923 |
-
# Extract technique counts
|
| 924 |
-
techniques = {
|
| 925 |
-
'Open Questions': 0,
|
| 926 |
-
'Reflections': 0,
|
| 927 |
-
'Affirmations': 0,
|
| 928 |
-
'Summaries': 0
|
| 929 |
-
}
|
| 930 |
-
|
| 931 |
-
for technique in techniques.keys():
|
| 932 |
-
count_match = re.search(f'{technique}:\s*(\d+)', st.session_state.analysis_results)
|
| 933 |
-
if count_match:
|
| 934 |
-
techniques[technique] = int(count_match.group(1))
|
| 935 |
-
|
| 936 |
-
# Create bar chart
|
| 937 |
-
fig = go.Figure(data=[
|
| 938 |
-
go.Bar(
|
| 939 |
-
x=list(techniques.keys()),
|
| 940 |
-
y=list(techniques.values()),
|
| 941 |
-
marker_color='rgb(26, 118, 255)'
|
| 942 |
-
)
|
| 943 |
-
])
|
| 944 |
-
|
| 945 |
-
fig.update_layout(
|
| 946 |
-
title="Technique Usage Frequency",
|
| 947 |
-
xaxis_title="Technique",
|
| 948 |
-
yaxis_title="Count",
|
| 949 |
-
template="plotly_white"
|
| 950 |
-
)
|
| 951 |
-
st.plotly_chart(fig)
|
| 952 |
|
| 953 |
# Client Language Tab
|
| 954 |
with tabs[2]:
|
| 955 |
st.subheader("Client Language Analysis")
|
| 956 |
|
| 957 |
-
|
| 958 |
-
|
| 959 |
-
if change_talk:
|
| 960 |
st.markdown("### Change Talk 🌱")
|
| 961 |
-
|
| 962 |
-
|
| 963 |
-
|
| 964 |
-
|
| 965 |
-
|
| 966 |
-
|
| 967 |
-
|
| 968 |
-
if sustain_talk:
|
| 969 |
st.markdown("### Sustain Talk 🔄")
|
| 970 |
-
|
| 971 |
-
|
| 972 |
-
|
| 973 |
-
|
|
|
|
| 974 |
|
| 975 |
# Session Flow Tab
|
| 976 |
with tabs[3]:
|
| 977 |
st.subheader("Session Flow Analysis")
|
| 978 |
|
| 979 |
-
#
|
| 980 |
-
|
| 981 |
-
|
| 982 |
-
|
| 983 |
-
|
| 984 |
-
|
| 985 |
-
|
| 986 |
-
|
| 987 |
-
|
| 988 |
-
|
| 989 |
-
|
| 990 |
-
if
|
| 991 |
-
|
| 992 |
-
|
|
|
|
| 993 |
|
| 994 |
# Recommendations Tab
|
| 995 |
with tabs[4]:
|
| 996 |
-
st.subheader("Recommendations
|
| 997 |
|
| 998 |
-
#
|
| 999 |
-
|
| 1000 |
-
|
| 1001 |
-
|
| 1002 |
-
for
|
| 1003 |
-
if
|
| 1004 |
-
st.markdown(f"
|
| 1005 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1006 |
|
| 1007 |
|
| 1008 |
def get_technique_description(technique):
|
|
|
|
| 317 |
analyze_session_content(st.session_state.current_transcript)
|
| 318 |
|
| 319 |
|
| 320 |
+
def analyze_session_content(transcript):
|
| 321 |
+
"""Analyze the session transcript using Gemini"""
|
| 322 |
try:
|
| 323 |
+
if not transcript:
|
| 324 |
+
st.warning("Please provide a transcript for analysis.")
|
| 325 |
+
return
|
| 326 |
+
|
| 327 |
+
# Configure the model
|
| 328 |
model = genai.GenerativeModel('gemini-pro')
|
| 329 |
|
| 330 |
+
# Structured prompt for MI analysis
|
| 331 |
+
prompt = f"""
|
| 332 |
+
As an MI (Motivational Interviewing) expert, analyze this therapy session transcript and provide detailed feedback in the following format:
|
| 333 |
+
|
| 334 |
+
=== MI Adherence ===
|
| 335 |
+
Score: [Provide a score from 0-100]
|
| 336 |
+
Strengths:
|
| 337 |
+
- [List 3 specific strengths with examples]
|
| 338 |
+
Areas for Growth:
|
| 339 |
+
- [List 3 specific areas needing improvement with examples]
|
| 340 |
+
|
| 341 |
+
=== Technical Analysis ===
|
| 342 |
+
OARS Usage Count:
|
| 343 |
+
- Open Questions: [number]
|
| 344 |
+
- Affirmations: [number]
|
| 345 |
+
- Reflections: [number]
|
| 346 |
+
- Summaries: [number]
|
| 347 |
+
|
| 348 |
+
=== Client Language Analysis ===
|
| 349 |
+
Change Talk Examples:
|
| 350 |
+
- [List 3-4 specific quotes showing change talk]
|
| 351 |
+
Sustain Talk Examples:
|
| 352 |
+
- [List 2-3 specific quotes showing sustain talk]
|
| 353 |
+
Change Talk/Sustain Talk Ratio: [X:Y]
|
| 354 |
+
|
| 355 |
+
=== Session Flow ===
|
| 356 |
+
Key Moments:
|
| 357 |
+
1. [Describe key moment 1]
|
| 358 |
+
2. [Describe key moment 2]
|
| 359 |
+
3. [Describe key moment 3]
|
| 360 |
+
|
| 361 |
+
Therapeutic Process:
|
| 362 |
+
- [Describe how the session progressed]
|
| 363 |
+
- [Note any significant shifts]
|
| 364 |
+
|
| 365 |
+
=== Recommendations ===
|
| 366 |
+
Priority Actions:
|
| 367 |
+
1. [Specific recommendation 1]
|
| 368 |
+
2. [Specific recommendation 2]
|
| 369 |
+
3. [Specific recommendation 3]
|
| 370 |
+
|
| 371 |
+
Development Strategies:
|
| 372 |
+
- [Practical strategy 1]
|
| 373 |
+
- [Practical strategy 2]
|
| 374 |
+
|
| 375 |
+
Analyze this transcript:
|
| 376 |
+
{transcript}
|
| 377 |
"""
|
| 378 |
+
|
| 379 |
+
# Generate response
|
| 380 |
+
response = model.generate_content(prompt)
|
| 381 |
|
| 382 |
+
# Store results
|
| 383 |
+
st.session_state.analysis_results = response.text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 384 |
|
| 385 |
+
return True
|
| 386 |
+
|
| 387 |
except Exception as e:
|
| 388 |
+
st.error(f"Error in analysis: {str(e)}")
|
| 389 |
+
return False
|
| 390 |
|
| 391 |
|
| 392 |
def generate_transcript(audio_content):
|
|
|
|
| 805 |
"""
|
| 806 |
return formatted_text
|
| 807 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 808 |
|
| 809 |
def show_analysis_results():
|
| 810 |
+
"""Display the analysis results in organized tabs"""
|
| 811 |
if 'analysis_results' not in st.session_state or not st.session_state.analysis_results:
|
| 812 |
+
st.info("Please analyze a transcript first.")
|
| 813 |
return
|
| 814 |
|
| 815 |
+
results = st.session_state.analysis_results
|
| 816 |
+
|
| 817 |
+
# Create tabs
|
| 818 |
tabs = st.tabs([
|
| 819 |
"MI Adherence",
|
| 820 |
"Technical Skills",
|
|
|
|
| 825 |
|
| 826 |
# MI Adherence Tab
|
| 827 |
with tabs[0]:
|
| 828 |
+
st.subheader("MI Adherence Analysis")
|
| 829 |
|
| 830 |
+
# Extract score
|
| 831 |
+
score_match = re.search(r'Score:\s*(\d+)', results)
|
| 832 |
if score_match:
|
| 833 |
score = int(score_match.group(1))
|
| 834 |
|
|
|
|
| 837 |
mode="gauge+number",
|
| 838 |
value=score,
|
| 839 |
domain={'x': [0, 1], 'y': [0, 1]},
|
| 840 |
+
gauge={
|
| 841 |
+
'axis': {'range': [0, 100]},
|
| 842 |
+
'bar': {'color': "rgb(26, 118, 255)"},
|
| 843 |
+
'steps': [
|
| 844 |
+
{'range': [0, 33], 'color': "lightgray"},
|
| 845 |
+
{'range': [33, 66], 'color': "gray"},
|
| 846 |
+
{'range': [66, 100], 'color': "darkgray"}
|
| 847 |
+
]
|
| 848 |
+
}
|
| 849 |
+
))
|
| 850 |
st.plotly_chart(fig)
|
| 851 |
|
| 852 |
+
# Display strengths and areas for growth
|
| 853 |
+
col1, col2 = st.columns(2)
|
| 854 |
+
with col1:
|
| 855 |
st.subheader("Strengths")
|
| 856 |
+
strengths = re.findall(r'Strengths:\n((?:- .*\n)*)', results)
|
| 857 |
+
if strengths:
|
| 858 |
+
for strength in strengths[0].strip().split('\n'):
|
| 859 |
+
if strength.startswith('- '):
|
| 860 |
+
st.markdown(f"✅ {strength[2:]}")
|
| 861 |
+
|
| 862 |
+
with col2:
|
| 863 |
+
st.subheader("Areas for Growth")
|
| 864 |
+
growth = re.findall(r'Areas for Growth:\n((?:- .*\n)*)', results)
|
| 865 |
+
if growth:
|
| 866 |
+
for area in growth[0].strip().split('\n'):
|
| 867 |
+
if area.startswith('- '):
|
| 868 |
+
st.markdown(f"🔄 {area[2:]}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 869 |
|
| 870 |
# Client Language Tab
|
| 871 |
with tabs[2]:
|
| 872 |
st.subheader("Client Language Analysis")
|
| 873 |
|
| 874 |
+
col1, col2 = st.columns(2)
|
| 875 |
+
with col1:
|
|
|
|
| 876 |
st.markdown("### Change Talk 🌱")
|
| 877 |
+
change_talk = re.findall(r'Change Talk Examples:\n((?:- .*\n)*)', results)
|
| 878 |
+
if change_talk:
|
| 879 |
+
for talk in change_talk[0].strip().split('\n'):
|
| 880 |
+
if talk.startswith('- '):
|
| 881 |
+
st.markdown(f"- {talk[2:]}")
|
| 882 |
+
|
| 883 |
+
with col2:
|
|
|
|
| 884 |
st.markdown("### Sustain Talk 🔄")
|
| 885 |
+
sustain_talk = re.findall(r'Sustain Talk Examples:\n((?:- .*\n)*)', results)
|
| 886 |
+
if sustain_talk:
|
| 887 |
+
for talk in sustain_talk[0].strip().split('\n'):
|
| 888 |
+
if talk.startswith('- '):
|
| 889 |
+
st.markdown(f"- {talk[2:]}")
|
| 890 |
|
| 891 |
# Session Flow Tab
|
| 892 |
with tabs[3]:
|
| 893 |
st.subheader("Session Flow Analysis")
|
| 894 |
|
| 895 |
+
# Key Moments
|
| 896 |
+
st.markdown("### Key Moments")
|
| 897 |
+
key_moments = re.findall(r'Key Moments:\n((?:\d\. .*\n)*)', results)
|
| 898 |
+
if key_moments:
|
| 899 |
+
for moment in key_moments[0].strip().split('\n'):
|
| 900 |
+
if moment.strip():
|
| 901 |
+
st.markdown(f"{moment}")
|
| 902 |
+
|
| 903 |
+
# Therapeutic Process
|
| 904 |
+
st.markdown("### Therapeutic Process")
|
| 905 |
+
process = re.findall(r'Therapeutic Process:\n((?:- .*\n)*)', results)
|
| 906 |
+
if process:
|
| 907 |
+
for item in process[0].strip().split('\n'):
|
| 908 |
+
if item.startswith('- '):
|
| 909 |
+
st.markdown(f"- {item[2:]}")
|
| 910 |
|
| 911 |
# Recommendations Tab
|
| 912 |
with tabs[4]:
|
| 913 |
+
st.subheader("Recommendations")
|
| 914 |
|
| 915 |
+
# Priority Actions
|
| 916 |
+
st.markdown("### Priority Actions 🎯")
|
| 917 |
+
priorities = re.findall(r'Priority Actions:\n((?:\d\. .*\n)*)', results)
|
| 918 |
+
if priorities:
|
| 919 |
+
for priority in priorities[0].strip().split('\n'):
|
| 920 |
+
if priority.strip():
|
| 921 |
+
st.markdown(f"{priority}")
|
| 922 |
+
|
| 923 |
+
# Development Strategies
|
| 924 |
+
st.markdown("### Development Strategies 📈")
|
| 925 |
+
strategies = re.findall(r'Development Strategies:\n((?:- .*\n)*)', results)
|
| 926 |
+
if strategies:
|
| 927 |
+
for strategy in strategies[0].strip().split('\n'):
|
| 928 |
+
if strategy.startswith('- '):
|
| 929 |
+
st.markdown(f"- {strategy[2:]}")
|
| 930 |
|
| 931 |
|
| 932 |
def get_technique_description(technique):
|