Spaces:
No application file
No application file
Upload 6 files
Browse files- app.py +217 -0
- config.txt +6 -0
- dockerfile.txt +12 -0
- gemma_handler.py +26 -0
- requirements.txt +19 -0
- voice_handler.py +43 -0
app.py
ADDED
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import google.generativeai as genai
|
3 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
4 |
+
import torch
|
5 |
+
import os
|
6 |
+
import sounddevice as sd
|
7 |
+
import numpy as np
|
8 |
+
import librosa
|
9 |
+
import io
|
10 |
+
from PIL import Image
|
11 |
+
import json
|
12 |
+
import requests
|
13 |
+
from datetime import datetime
|
14 |
+
from streamlit_lottie import st_lottie
|
15 |
+
|
16 |
+
# Configure page
|
17 |
+
st.set_page_config(page_title="HerCorners", page_icon="👑", layout="wide")
|
18 |
+
|
19 |
+
# Initialize Gemini
|
20 |
+
genai.configure(api_key=st.secrets["GEMINI_API_KEY"])
|
21 |
+
|
22 |
+
# Initialize Gemma
|
23 |
+
@st.cache_resource
|
24 |
+
def load_gemma_model():
|
25 |
+
tokenizer = AutoTokenizer.from_pretrained("google/gemma-7b")
|
26 |
+
model = AutoModelForCausalLM.from_pretrained("google/gemma-7b")
|
27 |
+
return tokenizer, model
|
28 |
+
|
29 |
+
tokenizer, gemma_model = load_gemma_model()
|
30 |
+
|
31 |
+
# Mentor profiles
|
32 |
+
MENTORS = {
|
33 |
+
"Oprah Winfrey": {
|
34 |
+
"role": "Media Mogul & Philanthropist",
|
35 |
+
"topics": ["leadership", "personal growth", "media"],
|
36 |
+
"style": "inspiring and wise",
|
37 |
+
"prompt_style": "warm, encouraging, and empowering"
|
38 |
+
},
|
39 |
+
"Sara Blakely": {
|
40 |
+
"role": "Founder of Spanx",
|
41 |
+
"topics": ["entrepreneurship", "innovation", "business"],
|
42 |
+
"style": "practical and motivating",
|
43 |
+
"prompt_style": "direct, practical, with real business examples"
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
# Custom CSS
|
48 |
+
st.markdown("""
|
49 |
+
<style>
|
50 |
+
.mentor-card {
|
51 |
+
padding: 20px;
|
52 |
+
border-radius: 10px;
|
53 |
+
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
54 |
+
box-shadow: 5px 5px 15px rgba(0,0,0,0.1);
|
55 |
+
margin: 10px 0;
|
56 |
+
}
|
57 |
+
.chat-message {
|
58 |
+
padding: 15px;
|
59 |
+
border-radius: 10px;
|
60 |
+
margin: 10px 0;
|
61 |
+
}
|
62 |
+
.user-message {
|
63 |
+
background-color: #e3f2fd;
|
64 |
+
margin-left: 20%;
|
65 |
+
}
|
66 |
+
.mentor-message {
|
67 |
+
background-color: #f5f5f5;
|
68 |
+
margin-right: 20%;
|
69 |
+
}
|
70 |
+
</style>
|
71 |
+
""", unsafe_allow_html=True)
|
72 |
+
|
73 |
+
class HerCorners:
|
74 |
+
def __init__(self):
|
75 |
+
self.initialize_session_state()
|
76 |
+
|
77 |
+
def initialize_session_state(self):
|
78 |
+
if 'messages' not in st.session_state:
|
79 |
+
st.session_state.messages = []
|
80 |
+
if 'current_corner' not in st.session_state:
|
81 |
+
st.session_state.current_corner = None
|
82 |
+
if 'current_mentor' not in st.session_state:
|
83 |
+
st.session_state.current_mentor = None
|
84 |
+
|
85 |
+
def generate_mentor_response(self, mentor, message):
|
86 |
+
"""Generate response using Gemini"""
|
87 |
+
model = genai.GenerativeModel('gemini-pro')
|
88 |
+
prompt = f"""
|
89 |
+
You are {mentor}, {MENTORS[mentor]['role']}.
|
90 |
+
Your communication style is {MENTORS[mentor]['style']}.
|
91 |
+
Respond to this message: {message}
|
92 |
+
Keep your response personal, authentic, and in your voice.
|
93 |
+
"""
|
94 |
+
response = model.generate_content(prompt)
|
95 |
+
return response.text
|
96 |
+
|
97 |
+
def generate_support_response(self, story):
|
98 |
+
"""Generate emotional support response using Gemma"""
|
99 |
+
prompt = f"As a supportive friend, respond with empathy to this story: {story}"
|
100 |
+
inputs = tokenizer(prompt, return_tensors="pt")
|
101 |
+
outputs = gemma_model.generate(**inputs, max_length=200)
|
102 |
+
response = tokenizer.decode(outputs[0])
|
103 |
+
return response
|
104 |
+
|
105 |
+
def she_legends_corner(self):
|
106 |
+
st.title("👑 She-Legends")
|
107 |
+
st.subheader("Chat with Inspiring Women Leaders")
|
108 |
+
|
109 |
+
# Mentor selection
|
110 |
+
mentor = st.selectbox("Choose your mentor", list(MENTORS.keys()))
|
111 |
+
if mentor:
|
112 |
+
st.session_state.current_mentor = mentor
|
113 |
+
|
114 |
+
# Chat interface
|
115 |
+
message = st.text_input("Your message:")
|
116 |
+
if st.button("Send"):
|
117 |
+
response = self.generate_mentor_response(mentor, message)
|
118 |
+
st.session_state.messages.append({"role": "user", "content": message})
|
119 |
+
st.session_state.messages.append({"role": "assistant", "content": response})
|
120 |
+
|
121 |
+
# Display chat history
|
122 |
+
for msg in st.session_state.messages:
|
123 |
+
div_class = "user-message" if msg["role"] == "user" else "mentor-message"
|
124 |
+
st.markdown(f"""
|
125 |
+
<div class="chat-message {div_class}">
|
126 |
+
{msg["content"]}
|
127 |
+
</div>
|
128 |
+
""", unsafe_allow_html=True)
|
129 |
+
|
130 |
+
def she_melted_mascara_corner(self):
|
131 |
+
st.title("💕 She-Melted Mascara")
|
132 |
+
st.subheader("Safe Space for Sharing")
|
133 |
+
|
134 |
+
# Story sharing options
|
135 |
+
share_method = st.radio("How would you like to share?",
|
136 |
+
["Text", "Voice Note", "Upload Image"])
|
137 |
+
|
138 |
+
if share_method == "Text":
|
139 |
+
story = st.text_area("Share your story...")
|
140 |
+
if st.button("Share Anonymously"):
|
141 |
+
response = self.generate_support_response(story)
|
142 |
+
st.markdown(f"""
|
143 |
+
<div class="chat-message mentor-message">
|
144 |
+
{response}
|
145 |
+
</div>
|
146 |
+
""", unsafe_allow_html=True)
|
147 |
+
|
148 |
+
elif share_method == "Voice Note":
|
149 |
+
if st.button("Start Recording"):
|
150 |
+
# Implement voice recording
|
151 |
+
st.write("Recording... (feature in development)")
|
152 |
+
|
153 |
+
elif share_method == "Upload Image":
|
154 |
+
uploaded_file = st.file_uploader("Upload your image")
|
155 |
+
if uploaded_file is not None:
|
156 |
+
image = Image.open(uploaded_file)
|
157 |
+
st.image(image, caption="Your shared image")
|
158 |
+
|
159 |
+
def she_glows_corner(self):
|
160 |
+
st.title("✨ She-Glows")
|
161 |
+
st.subheader("Economic Education Hub")
|
162 |
+
|
163 |
+
# Learning modules
|
164 |
+
modules = {
|
165 |
+
"Financial Literacy": ["Budgeting Basics", "Investment 101", "Credit Management"],
|
166 |
+
"Entrepreneurship": ["Business Planning", "Marketing Basics", "Funding Sources"],
|
167 |
+
"Leadership": ["Communication Skills", "Team Management", "Decision Making"]
|
168 |
+
}
|
169 |
+
|
170 |
+
selected_topic = st.selectbox("Choose your learning path", list(modules.keys()))
|
171 |
+
selected_module = st.selectbox("Select module", modules[selected_topic])
|
172 |
+
|
173 |
+
if st.button("Start Learning"):
|
174 |
+
# Generate educational content using Gemini
|
175 |
+
model = genai.GenerativeModel('gemini-pro')
|
176 |
+
prompt = f"Create a beginner-friendly lesson about {selected_module}"
|
177 |
+
response = model.generate_content(prompt)
|
178 |
+
st.write(response.text)
|
179 |
+
|
180 |
+
def she_fuels_corner(self):
|
181 |
+
st.title("⚡ She-Fuels")
|
182 |
+
st.subheader("Community Support & Achievements")
|
183 |
+
|
184 |
+
# Achievement sharing
|
185 |
+
achievement = st.text_area("Share your achievement")
|
186 |
+
if st.button("Share with Community"):
|
187 |
+
st.success("Achievement shared successfully!")
|
188 |
+
|
189 |
+
# Display community achievements
|
190 |
+
st.subheader("Recent Community Achievements")
|
191 |
+
# Placeholder for community achievements
|
192 |
+
achievements = [
|
193 |
+
"Started my first business!",
|
194 |
+
"Completed financial literacy course",
|
195 |
+
"Secured first investment"
|
196 |
+
]
|
197 |
+
for achievement in achievements:
|
198 |
+
st.markdown(f"🌟 {achievement}")
|
199 |
+
|
200 |
+
def main(self):
|
201 |
+
st.sidebar.title("HerCorners")
|
202 |
+
corner = st.sidebar.radio("Choose your corner",
|
203 |
+
["She-Legends", "She-Melted Mascara",
|
204 |
+
"She-Glows", "She-Fuels"])
|
205 |
+
|
206 |
+
if corner == "She-Legends":
|
207 |
+
self.she_legends_corner()
|
208 |
+
elif corner == "She-Melted Mascara":
|
209 |
+
self.she_melted_mascara_corner()
|
210 |
+
elif corner == "She-Glows":
|
211 |
+
self.she_glows_corner()
|
212 |
+
elif corner == "She-Fuels":
|
213 |
+
self.she_fuels_corner()
|
214 |
+
|
215 |
+
if __name__ == "__main__":
|
216 |
+
app = HerCorners()
|
217 |
+
app.main()
|
config.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[theme]
|
2 |
+
primaryColor="#ff4b4b"
|
3 |
+
backgroundColor="#ffffff"
|
4 |
+
secondaryBackgroundColor="#f0f2f6"
|
5 |
+
textColor="#262730"
|
6 |
+
font="sans serif"
|
dockerfile.txt
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.9-slim
|
2 |
+
|
3 |
+
WORKDIR /app
|
4 |
+
|
5 |
+
COPY requirements.txt .
|
6 |
+
RUN pip install -r requirements.txt
|
7 |
+
|
8 |
+
COPY . .
|
9 |
+
|
10 |
+
EXPOSE 8501
|
11 |
+
|
12 |
+
ENTRYPOINT ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
|
gemma_handler.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from huggingface_hub import InferenceClient
|
2 |
+
|
3 |
+
class GemmaHandler:
|
4 |
+
def __init__(self, api_token):
|
5 |
+
self.client = InferenceClient(token=api_token)
|
6 |
+
self.model = "google/gemma-7b"
|
7 |
+
|
8 |
+
def generate_response(self, prompt):
|
9 |
+
response = self.client.text_generation(
|
10 |
+
prompt,
|
11 |
+
model=self.model,
|
12 |
+
max_new_tokens=100,
|
13 |
+
temperature=0.7,
|
14 |
+
top_p=0.95,
|
15 |
+
repetition_penalty=1.1
|
16 |
+
)
|
17 |
+
return response
|
18 |
+
|
19 |
+
def generate_emotional_support(self, emotion, story):
|
20 |
+
prompt = f"""
|
21 |
+
As a supportive AI friend, respond to someone who is feeling {emotion}.
|
22 |
+
Their story: {story}
|
23 |
+
|
24 |
+
Provide empathetic support and encouragement while maintaining authenticity.
|
25 |
+
"""
|
26 |
+
return self.generate_response(prompt)
|
requirements.txt
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
google-generativeai
|
3 |
+
transformers
|
4 |
+
torch
|
5 |
+
python-dotenv
|
6 |
+
sounddevice
|
7 |
+
librosa
|
8 |
+
soundfile
|
9 |
+
numpy
|
10 |
+
pandas
|
11 |
+
plotly
|
12 |
+
Pillow
|
13 |
+
streamlit-lottie
|
14 |
+
streamlit-webrtc
|
15 |
+
python-multipart
|
16 |
+
requests
|
17 |
+
scipy
|
18 |
+
nltk
|
19 |
+
emoji
|
voice_handler.py
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sounddevice as sd
|
2 |
+
import numpy as np
|
3 |
+
import librosa
|
4 |
+
import torch
|
5 |
+
from transformers import pipeline
|
6 |
+
|
7 |
+
class VoiceHandler:
|
8 |
+
def __init__(self):
|
9 |
+
self.sample_rate = 16000
|
10 |
+
self.emotion_classifier = pipeline("audio-classification",
|
11 |
+
model="ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition")
|
12 |
+
|
13 |
+
def record_audio(self, duration=5):
|
14 |
+
"""Record audio for specified duration"""
|
15 |
+
recording = sd.rec(int(duration * self.sample_rate),
|
16 |
+
samplerate=self.sample_rate,
|
17 |
+
channels=1)
|
18 |
+
sd.wait()
|
19 |
+
return recording
|
20 |
+
|
21 |
+
def process_audio(self, audio_data):
|
22 |
+
"""Process audio and detect emotion"""
|
23 |
+
# Convert to mono if needed
|
24 |
+
if len(audio_data.shape) > 1:
|
25 |
+
audio_data = np.mean(audio_data, axis=1)
|
26 |
+
|
27 |
+
# Normalize audio
|
28 |
+
audio_data = librosa.util.normalize(audio_data)
|
29 |
+
|
30 |
+
# Get emotion
|
31 |
+
emotion = self.emotion_classifier(audio_data)
|
32 |
+
|
33 |
+
return audio_data, emotion[0]['label']
|
34 |
+
|
35 |
+
def enhance_audio(self, audio_data):
|
36 |
+
"""Enhance audio quality"""
|
37 |
+
# Noise reduction
|
38 |
+
y = librosa.effects.preemphasis(audio_data)
|
39 |
+
|
40 |
+
# Normalize
|
41 |
+
y = librosa.util.normalize(y)
|
42 |
+
|
43 |
+
return y
|