diff --git a/week3/community-contributions/AI_Minute_Taker.ipynb b/week3/community-contributions/AI_Minute_Taker.ipynb new file mode 100644 index 0000000..d189aef --- /dev/null +++ b/week3/community-contributions/AI_Minute_Taker.ipynb @@ -0,0 +1,186 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [], + "gpuType": "T4" + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Create meeting minutes from an Audio file\n", + "For this project, the UI allows you to either upload meeting minutes, or record something of your own!" + ], + "metadata": { + "id": "MYOLn_FzYAF4" + } + }, + { + "cell_type": "code", + "source": [ + "# --- Install deps ---\n", + "!pip install -q gradio torch==2.5.1+cu124 torchvision==0.20.1+cu124 torchaudio==2.5.1+cu124 --index-url https://download.pytorch.org/whl/cu124\n", + "!pip install -q requests bitsandbytes==0.46.0 transformers==4.48.3 accelerate==1.3.0 openai" + ], + "metadata": { + "id": "M01YO75ITfXF" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# --- Imports ---\n", + "import gradio as gr\n", + "import torch\n", + "from transformers import AutoTokenizer, AutoModelForCausalLM, TextStreamer, BitsAndBytesConfig\n", + "from openai import OpenAI\n", + "from huggingface_hub import login\n", + "from google.colab import userdata\n", + "from google.colab import drive\n", + "import os" + ], + "metadata": { + "id": "DGE8_oAwZJBo" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# --- Constants ---\n", + "AUDIO_MODEL = \"whisper-1\"\n", + "LLAMA = \"meta-llama/Meta-Llama-3.1-8B-Instruct\"" + ], + "metadata": { + "id": "JPu-aNxDTmDi" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# --- Auth ---\n", + "# assumes Colab userdata or your own env vars\n", + "hf_token = userdata.get('HF_TOKEN')\n", + "login(hf_token, add_to_git_credential=True)" + ], + "metadata": { + "id": "JfWUrEVJTmET" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "openai_api_key = userdata.get('OPENAI_API_KEY')\n", + "openai = OpenAI(api_key=openai_api_key)" + ], + "metadata": { + "id": "AiUtJ0mjTpVE" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# --- Model setup ---\n", + "quant_config = BitsAndBytesConfig(\n", + " load_in_4bit=True,\n", + " bnb_4bit_use_double_quant=True,\n", + " bnb_4bit_compute_dtype=torch.bfloat16,\n", + " bnb_4bit_quant_type=\"nf4\"\n", + ")\n", + "\n", + "tokenizer = AutoTokenizer.from_pretrained(LLAMA)\n", + "tokenizer.pad_token = tokenizer.eos_token\n", + "model = AutoModelForCausalLM.from_pretrained(\n", + " LLAMA, device_map=\"auto\", quantization_config=quant_config\n", + ")" + ], + "metadata": { + "id": "hMb4dggMW2s5" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "XTEW5qAwRN4Y" + }, + "outputs": [], + "source": [ + "# --- Processing function ---\n", + "def process_meeting(audio_file):\n", + " # Step 1: Transcribe\n", + " with open(audio_file, \"rb\") as f:\n", + " transcription = openai.audio.transcriptions.create(\n", + " model=AUDIO_MODEL, file=f, response_format=\"text\"\n", + " )\n", + "\n", + " # Step 2: Prepare prompt\n", + " system_message = (\n", + " \"You are an assistant that produces minutes of meetings from transcripts, \"\n", + " \"with summary, key discussion points, takeaways and action items with owners, \"\n", + " \"in markdown.\"\n", + " )\n", + " user_prompt = (\n", + " f\"Below is an extract transcript of a meeting. Please write minutes in markdown, \"\n", + " f\"including a summary with attendees, location and date; discussion points; \"\n", + " f\"takeaways; and action items with owners.\\n{transcription}\"\n", + " )\n", + " messages = [\n", + " {\"role\": \"system\", \"content\": system_message},\n", + " {\"role\": \"user\", \"content\": user_prompt}\n", + " ]\n", + "\n", + " # Step 3: Run through LLaMA\n", + " inputs = tokenizer.apply_chat_template(messages, return_tensors=\"pt\").to(\"cuda\")\n", + " streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)\n", + " outputs = model.generate(inputs, max_new_tokens=2000)\n", + "\n", + " response = tokenizer.decode(outputs[0], skip_special_tokens=True)\n", + " return response\n", + "\n", + "# --- Gradio UI ---\n", + "with gr.Blocks() as demo:\n", + " gr.Markdown(\"## 📝 Meeting Minutes Generator\\nUpload an audio file and get structured meeting minutes.\")\n", + " with gr.Row():\n", + " audio_in = gr.Audio(type=\"filepath\", label=\"Upload Meeting Audio\")\n", + " btn = gr.Button(\"Generate Minutes\")\n", + " md_out = gr.Markdown()\n", + "\n", + " btn.click(fn=process_meeting, inputs=audio_in, outputs=md_out)" + ] + }, + { + "cell_type": "code", + "source": [ + "demo.launch()" + ], + "metadata": { + "id": "Yh4-imrmY8MH" + }, + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file