Upload 2 files
Browse files- app.py +87 -0
- requirements.txt +10 -0
app.py
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import whisper
|
3 |
+
from transformers import pipeline
|
4 |
+
import spacy
|
5 |
+
from summa import keywords
|
6 |
+
import datetime
|
7 |
+
import os
|
8 |
+
|
9 |
+
@st.cache_resource
|
10 |
+
def load_models():
|
11 |
+
whisper_model = whisper.load_model("base")
|
12 |
+
summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
|
13 |
+
nlp = spacy.load("en_core_web_sm")
|
14 |
+
return whisper_model, summarizer, nlp
|
15 |
+
|
16 |
+
def extract_action_items(text, nlp):
|
17 |
+
doc = nlp(text)
|
18 |
+
actions = []
|
19 |
+
|
20 |
+
for sent in doc.sents:
|
21 |
+
for token in sent:
|
22 |
+
if token.dep_ == "ROOT" and token.pos_ == "VERB":
|
23 |
+
action = {
|
24 |
+
"text": sent.text,
|
25 |
+
"responsible": [],
|
26 |
+
"deadline": []
|
27 |
+
}
|
28 |
+
|
29 |
+
for ent in sent.ents:
|
30 |
+
if ent.label_ == "PERSON":
|
31 |
+
action["responsible"].append(ent.text)
|
32 |
+
elif ent.label_ == "DATE":
|
33 |
+
action["deadline"].append(ent.text)
|
34 |
+
|
35 |
+
actions.append(action)
|
36 |
+
break
|
37 |
+
return actions
|
38 |
+
|
39 |
+
def main():
|
40 |
+
st.title("π€ Smart AI Meeting Assistant")
|
41 |
+
|
42 |
+
whisper_model, summarizer, nlp = load_models()
|
43 |
+
|
44 |
+
audio_file = st.file_uploader("Upload meeting audio", type=["wav", "mp3", "m4a"])
|
45 |
+
|
46 |
+
if audio_file is not None:
|
47 |
+
file_path = f"uploaded_audio_{datetime.datetime.now().timestamp()}"
|
48 |
+
with open(file_path, "wb") as f:
|
49 |
+
f.write(audio_file.getbuffer())
|
50 |
+
|
51 |
+
st.subheader("Meeting Transcription")
|
52 |
+
with st.spinner("Transcribing audio..."):
|
53 |
+
result = whisper_model.transcribe(file_path)
|
54 |
+
transcript = result["text"]
|
55 |
+
st.write(transcript)
|
56 |
+
os.remove(file_path)
|
57 |
+
|
58 |
+
st.subheader("Meeting Summary")
|
59 |
+
with st.spinner("Generating summary..."):
|
60 |
+
truncated_text = transcript[:1024]
|
61 |
+
summary = summarizer(truncated_text, max_length=150, min_length=50)[0]['summary_text']
|
62 |
+
st.write(summary)
|
63 |
+
|
64 |
+
st.subheader("π Action Items")
|
65 |
+
actions = extract_action_items(transcript, nlp)
|
66 |
+
|
67 |
+
if not actions:
|
68 |
+
st.write("No action items detected")
|
69 |
+
else:
|
70 |
+
for i, action in enumerate(actions, 1):
|
71 |
+
responsible = ", ".join(action["responsible"]) or "Unassigned"
|
72 |
+
deadline = ", ".join(action["deadline"]) or "No deadline"
|
73 |
+
st.markdown(f"""
|
74 |
+
**Action {i}**
|
75 |
+
- Task: {action["text"]}
|
76 |
+
- Responsible: {responsible}
|
77 |
+
- Deadline: {deadline}
|
78 |
+
""")
|
79 |
+
|
80 |
+
st.subheader("π Key Terms")
|
81 |
+
# Fixed keyword processing
|
82 |
+
key_phrases_result = keywords.keywords(transcript) or ""
|
83 |
+
key_phrases = [kp.strip() for kp in key_phrases_result.split("\n") if kp.strip()]
|
84 |
+
st.write(", ".join(key_phrases) if key_phrases else "No key terms extracted")
|
85 |
+
|
86 |
+
if __name__ == "__main__":
|
87 |
+
main()
|
requirements.txt
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# requirements.txt (updated)
|
2 |
+
streamlit==1.27.0
|
3 |
+
openai-whisper==20231117
|
4 |
+
torch==2.1.0
|
5 |
+
transformers==4.35.2
|
6 |
+
spacy==3.7.2
|
7 |
+
summa==1.2.0 # Changed from 1.2.3 to available version
|
8 |
+
python-magic==0.4.27
|
9 |
+
ffmpeg-python==0.2.0
|
10 |
+
en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.0/en_core_web_sm-3.7.0-py3-none-any.whl
|