diff --git a/.env.example b/.env.example index 274d777..b02a2e4 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ DISCORD_BOT_TOKEN=your_bot_token_here +OPENAI_API_KEY=your_openai_api_key_here diff --git a/bot/main.py b/bot/main.py index d34dedc..f57e0eb 100644 --- a/bot/main.py +++ b/bot/main.py @@ -11,7 +11,7 @@ from meeting_state import MeetingStateManager, MeetingStatus from audio_recorder import AudioRecordingManager - +from summarizer import process_meeting_recordings, generate_structured_summary logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', @@ -322,10 +322,23 @@ async def end_meeting(interaction: discord.Interaction): ) if recording_info: - response += f"👥 Recorded {recording_info['user_count']} user(s)\n" - response += f"📁 Saved to: `{recording_info['output_dir']}`" - + response += f"Recorded {recording_info['user_count']} user(s)\n" + response += f"Saved to: `{recording_info['output_dir']}`" + await interaction.followup.send(response) + + if recording_info and recording_info.get("user_count", 0) > 0: + await interaction.followup.send("⏳ Transcribing audio and generating summary...") + try: + transcript = process_meeting_recordings(recording_info["output_dir"]) + if transcript: + summary = generate_structured_summary(transcript) + await interaction.followup.send(f"📝 **Meeting Summary**\n\n{summary}") + else: + await interaction.followup.send("⚠️ No audio was captured to summarize.") + except Exception as e: + logger.error(f"Error generating summary: {e}") + await interaction.followup.send("⚠️ Could not generate summary. Check logs for details.") logger.info( f"Meeting ended: {ended_session.meeting_id} in guild {guild_id}, " diff --git a/bot/summarizer.py b/bot/summarizer.py new file mode 100644 index 0000000..7da2da7 --- /dev/null +++ b/bot/summarizer.py @@ -0,0 +1,79 @@ +import os +import openai + +client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY")) + + +def transcribe_audio(audio_path: str) -> str: + """Transcribes a .wav audio file to text using OpenAI Whisper.""" + with open(audio_path, "rb") as audio_file: + response = client.audio.transcriptions.create( + model="whisper-1", + file=audio_file + ) + return response.text + + +def generate_structured_summary(transcript: str) -> str: + """Takes a plain-text transcript and returns a structured AI summary.""" + if not transcript or not transcript.strip(): + return "⚠️ No transcript content to summarize." + + prompt = """ +You are an AI assistant that creates structured meeting summaries. + +Given the raw transcript below, produce a summary with exactly these three sections: + +## 🗝️ Key Topics Discussed +- List the main subjects and themes covered. + +## ✅ Decisions Made +- List any concrete decisions or agreements reached. + +## 📋 Action Items / Follow-ups +- List tasks to be completed, with owner and deadline if mentioned. + +If a section has nothing to report, write: "None identified." + +Keep it concise and professional. Do not add any extra sections. + +--- +Transcript: +{transcript} +""".format(transcript=transcript.strip()) + + response = client.chat.completions.create( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": prompt}], + temperature=0.3, + max_tokens=800 + ) + + return response.choices[0].message.content.strip() + + +def process_meeting_recordings(output_dir: str) -> str: + """ + Finds all .wav files in the meeting directory, + transcribes each one, and combines into a single transcript. + """ + from pathlib import Path + + wav_files = list(Path(output_dir).glob("*.wav")) + + if not wav_files: + return "" + + full_transcript = [] + + for wav_file in wav_files: + # Use filename as speaker label (e.g. user_123456_John) + speaker = wav_file.stem.split("_")[-1] + try: + text = transcribe_audio(str(wav_file)) + if text.strip(): + full_transcript.append(f"{speaker}: {text.strip()}") + except Exception as e: + full_transcript.append(f"[Could not transcribe {wav_file.name}: {e}]") + + return "\n".join(full_transcript) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index ce8ae05..897d057 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ discord.py[voice]>=2.3.0 PyNaCl>=1.5.0 python-dotenv>=1.0.0 +openai>=1.0.0