├── README.md └── summarize_videos_clean.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # GPT Summarizer 2 | 3 | This notebook can be used to download videos from YouTube, transcribe locally with a distilled version of Whisper and then summarized by calling gpt-4-turbo 4 | 5 | Enjoy! 6 | 7 | PS: if you find it useful, please 🌟 the repo, thanks! 8 | 9 | Obligatory blog self-promotion: 10 | 11 | [👉 Cool machine learning tutorials](https://forecastegy.com/tags/machine-learning/) -------------------------------------------------------------------------------- /summarize_videos_clean.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import json\n", 10 | "import re\n", 11 | "import pathlib\n", 12 | "import openai\n", 13 | "import os\n", 14 | "path = pathlib.Path(\"path_to_good_stuff\")" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": { 21 | "vscode": { 22 | "languageId": "plaintext" 23 | } 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "from yt_dlp import YoutubeDL\n", 28 | "\n", 29 | "URLS = ['channel, video, or playlist urls']\n", 30 | "with YoutubeDL(params={'format': '140', \"paths\": {\"home\": path.as_posix()}}\n", 31 | " ) as ydl:\n", 32 | " ydl.download(URLS)" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": { 39 | "vscode": { 40 | "languageId": "plaintext" 41 | } 42 | }, 43 | "outputs": [], 44 | "source": [ 45 | "import torch\n", 46 | "from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor, pipeline\n", 47 | "\n", 48 | "model_id = \"distil-whisper/distil-large-v2\"\n", 49 | "torch_dtype = torch.float16\n", 50 | "device = \"cuda:0\"\n", 51 | "\n", 52 | "model = AutoModelForSpeechSeq2Seq.from_pretrained(\n", 53 | " model_id, torch_dtype=torch_dtype, \n", 54 | " low_cpu_mem_usage=True, use_safetensors=True, \n", 55 | " use_flash_attention_2=False\n", 56 | " ).to_bettertransformer()\n", 57 | "model.to(device)\n", 58 | "\n", 59 | "processor = AutoProcessor.from_pretrained(model_id)\n", 60 | "\n", 61 | "pipe = pipeline(\"automatic-speech-recognition\",\n", 62 | " model=model,\n", 63 | " tokenizer=processor.tokenizer,\n", 64 | " feature_extractor=processor.feature_extractor,\n", 65 | " torch_dtype=torch_dtype,\n", 66 | " device=device)\n", 67 | "\n", 68 | "for fname in path.glob(\"*.m4a\"):\n", 69 | " if fname.with_suffix(\".txt\").exists():\n", 70 | " continue\n", 71 | " \n", 72 | " print(fname)\n", 73 | " outputs = pipe(fname.as_posix(),\n", 74 | " chunk_length_s=15,\n", 75 | " batch_size=32,\n", 76 | " return_timestamps=True)\n", 77 | "\n", 78 | " text = outputs[\"text\"]\n", 79 | " #chunks = [text[i:i+6000] for i in range(0, len(text), 6000)]\n", 80 | "\n", 81 | " with open(fname.with_suffix(\".txt\"), \"w\") as f:\n", 82 | " #for c in chunks:\n", 83 | " # f.write(c)\n", 84 | " # f.write(\"\\n\\n\\n\")\n", 85 | " f.write(text)\n", 86 | " " 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n", 96 | "\n", 97 | "i = 0\n", 98 | "for fname in path.glob(\"*.txt\"):\n", 99 | " if (path / \"summaries\" / fname.name).exists():\n", 100 | " continue\n", 101 | " if i > 4:\n", 102 | " break\n", 103 | " print(fname)\n", 104 | " transcript = fname.read_text().strip()\n", 105 | " title = re.sub(r'\\[.*?\\]', '', fname.stem).strip()\n", 106 | " \n", 107 | " \n", 108 | " system_msg = f\"\"\"Give me a detailed summary of the following transcript. The title is: {title}\"\"\"\n", 109 | " #print(system_msg)\n", 110 | " prompt = f\"\"\"TRANSCRIPT:\\n\\n{transcript}\"\"\"\n", 111 | "\n", 112 | " completion = openai.ChatCompletion.create(\n", 113 | " model=\"gpt-4-1106-preview\",\n", 114 | " temperature=0.0,\n", 115 | " max_tokens=1000,\n", 116 | " messages=[\n", 117 | " {\"role\": \"system\", \"content\": system_msg},\n", 118 | " {\"role\": \"user\", \"content\": prompt},\n", 119 | " ],\n", 120 | " )\n", 121 | "\n", 122 | " summary = completion['choices'][0].message['content']\n", 123 | "\n", 124 | "\n", 125 | " with open(path / \"summaries\" / fname.name, \"w\") as f:\n", 126 | " f.write(summary)\n", 127 | " i += 1 " 128 | ] 129 | } 130 | ], 131 | "metadata": { 132 | "kernelspec": { 133 | "display_name": "seo", 134 | "language": "python", 135 | "name": "python3" 136 | }, 137 | "language_info": { 138 | "codemirror_mode": { 139 | "name": "ipython", 140 | "version": 3 141 | }, 142 | "file_extension": ".py", 143 | "mimetype": "text/x-python", 144 | "name": "python", 145 | "nbconvert_exporter": "python", 146 | "pygments_lexer": "ipython3", 147 | "version": "3.9.16" 148 | } 149 | }, 150 | "nbformat": 4, 151 | "nbformat_minor": 2 152 | } 153 | --------------------------------------------------------------------------------