├── README.md └── opensource_notebooklm.ipynb /README.md: -------------------------------------------------------------------------------- 1 | Notebook by [Build Fast with AI](https://www.buildfastwithai.com/genai-course) 2 | 3 | # Open Source NotebookLM Implementation 4 | 5 | An open-source implementation of NotebookLM using Deepseek-V3 and PlayHT TTS. 6 | 7 | This project combines the power of Deepseek-V3 for language understanding and PlayHT for text-to-speech capabilities. 8 | 9 | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1lSzgEXw9F4X65qSSgOs47ejMGRDkbuZH?usp=sharing) 10 | 11 | ## Features 12 | 13 | - **AI-Powered Conversations**: Uses Deepseek-V3 model for generating natural, educational dialogues 14 | - **Text-to-Speech**: Integrates PlayHT for converting conversations into realistic audio 15 | - **Interactive Format**: Generates engaging podcast-style conversations between two speakers 16 | - **Educational Content**: Creates deep, insightful discussions on any given topic 17 | 18 | ## Requirements 19 | 20 | - Python 3.x 21 | - FAL API key 22 | - OpenRouter API key 23 | 24 | -------------------------------------------------------------------------------- /opensource_notebooklm.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "markdown", 19 | "source": [ 20 | "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1lSzgEXw9F4X65qSSgOs47ejMGRDkbuZH?usp=sharing)" 21 | ], 22 | "metadata": { 23 | "id": "hboiaQUnxx6B" 24 | } 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "source": [ 29 | "## Open Source Implementation of NotebookLM\n", 30 | "\n", 31 | "- Open source alternative to Google's NotebookLM\n", 32 | "- Uses Deepseek-V3 for language understanding and generation\n", 33 | "- Integrates PlayHT for text-to-speech capabilities\n", 34 | "- Demonstrates interactive notebook-based AI assistance" 35 | ], 36 | "metadata": { 37 | "id": "QNXyjixrwiTj" 38 | } 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "source": [ 43 | "Notebook by [Build Fast with AI](https://www.buildfastwithai.com/genai-course)" 44 | ], 45 | "metadata": { 46 | "id": "iWkvJYD-xVlr" 47 | } 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 1, 52 | "metadata": { 53 | "colab": { 54 | "base_uri": "https://localhost:8080/" 55 | }, 56 | "id": "SnKUkFDXthcO", 57 | "outputId": "4072b441-1c52-466b-c7ed-14a33ad58351" 58 | }, 59 | "outputs": [ 60 | { 61 | "output_type": "stream", 62 | "name": "stdout", 63 | "text": [ 64 | "\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/50.9 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.9/50.9 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 65 | "\u001b[?25h\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/411.6 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m411.6/411.6 kB\u001b[0m \u001b[31m20.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 66 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m454.8/454.8 kB\u001b[0m \u001b[31m24.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 67 | "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m54.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", 68 | "\u001b[?25h" 69 | ] 70 | } 71 | ], 72 | "source": [ 73 | "!pip install -qU fal-client langchain-openai" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "source": [ 79 | "import os\n", 80 | "from google.colab import userdata\n", 81 | "\n", 82 | "os.environ[\"FAL_KEY\"] = userdata.get('FAL_KEY')\n", 83 | "os.environ[\"OPENROUTER_API_KEY\"] = userdata.get('OPENROUTER_API_KEY')" 84 | ], 85 | "metadata": { 86 | "id": "pBBXMSTKucUE" 87 | }, 88 | "execution_count": 3, 89 | "outputs": [] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "source": [ 94 | "from langchain.prompts import ChatPromptTemplate\n", 95 | "from langchain_openai import ChatOpenAI\n", 96 | "\n", 97 | "def generate_podcast_transcript(topic):\n", 98 | " # Modify this template as per your requirement!\n", 99 | " podcast_template = ChatPromptTemplate.from_template(\"\"\"\n", 100 | " Create an engaging conversation between two speakers discussing the topic: {topic}\n", 101 | "\n", 102 | " Requirements:\n", 103 | " - Generate exactly 5 back-and-forth exchanges\n", 104 | " - Make it natural and conversational\n", 105 | " - Include specific details about the {topic}\n", 106 | " - Each line should start with either \"Speaker 1:\" or \"Speaker 2:\"\n", 107 | "\n", 108 | " Here's an example of the format (but create NEW content about {topic}, don't copy this example):\n", 109 | " Speaker 1: [First speaker's line]\n", 110 | " Speaker 2: [Second speaker's line]\n", 111 | "\n", 112 | " The response of the each speaker should be at most 20 words. The conversation has to be insightful, engaging, explanatory, deep diving and educational.\n", 113 | "\n", 114 | " It should be in the style of a podcast where one speaker slightly is more knowledgeable than the other.\n", 115 | "\n", 116 | " You are allowed to write only in the below format. Just give the output in the below format in a single string. No additional delimiters.\n", 117 | "\n", 118 | " The content should be explanatory, deep diving and educational.\n", 119 | "\n", 120 | " Speaker 1: Hey, did you catch the game last night?\n", 121 | " Speaker 2: Of course! What a match—it had me on the edge of my seat.\n", 122 | " Speaker 1: Same here! That last-minute goal was unreal. Who's your MVP?\n", 123 | " Speaker 2: Gotta be the goalie. Those saves were unbelievable.\n", 124 | "\n", 125 | "\n", 126 | " Remember: Create completely new dialogue about {topic}, don't use the above example.\n", 127 | " \"\"\")\n", 128 | "\n", 129 | " # Initialize the ChatOpenAI model\n", 130 | " llm = ChatOpenAI(\n", 131 | " model=\"deepseek/deepseek-chat\",\n", 132 | " openai_api_key=os.getenv(\"OPENROUTER_API_KEY\"),\n", 133 | " openai_api_base=\"https://openrouter.ai/api/v1\"\n", 134 | " )\n", 135 | "\n", 136 | " # Create the chain\n", 137 | " chain = podcast_template | llm\n", 138 | "\n", 139 | " response = chain.invoke({\"topic\": topic})\n", 140 | " return response.content" 141 | ], 142 | "metadata": { 143 | "id": "2nnzdQQDqH8z" 144 | }, 145 | "execution_count": 6, 146 | "outputs": [] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "source": [ 151 | "response = generate_podcast_transcript(\"Quantum Random Walks\")\n", 152 | "print(response)" 153 | ], 154 | "metadata": { 155 | "colab": { 156 | "base_uri": "https://localhost:8080/" 157 | }, 158 | "id": "bEVhAuW1txhR", 159 | "outputId": "fa1a663a-9dd3-4365-ed1e-bb66a333f3b4" 160 | }, 161 | "execution_count": 8, 162 | "outputs": [ 163 | { 164 | "output_type": "stream", 165 | "name": "stdout", 166 | "text": [ 167 | "Speaker 1: Have you heard about quantum random walks? They’re like classical random walks but with a quantum twist. \n", 168 | "Speaker 2: Yeah, but how do they differ? Classical walks spread linearly, right? \n", 169 | "Speaker 1: Exactly! Quantum walks spread quadratically faster due to superposition and interference. It’s mind-blowing! \n", 170 | "Speaker 2: So, does that mean they’re more efficient for algorithms? \n", 171 | "Speaker 1: Absolutely! They’re used in quantum search and optimization problems, outperforming classical methods. \n", 172 | "Speaker 2: That’s fascinating! How do they handle decoherence, though? \n", 173 | "Speaker 1: Great question! Decoherence is a challenge, but error correction techniques help maintain quantum coherence. \n", 174 | "Speaker 2: Makes sense. So, are quantum walks practical yet, or still theoretical? \n", 175 | "Speaker 1: Mostly experimental, but progress is rapid. They’re paving the way for quantum computing breakthroughs! \n", 176 | "Speaker 2: Can’t wait to see where this leads. Quantum walks sound like the future!\n" 177 | ] 178 | } 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "source": [ 184 | "def generate_podcast(topic):\n", 185 | " print(f\"\\n🎙️ Generating podcast transcript about: {topic}\")\n", 186 | " print(\"-\" * 50)\n", 187 | "\n", 188 | " # Get transcript first using generate_podcast_transcript\n", 189 | " transcript_result = generate_podcast_transcript(topic)\n", 190 | "\n", 191 | " print(\"\\n✍️ Generated transcript:\")\n", 192 | " print(\"-\" * 50)\n", 193 | " print(transcript_result)\n", 194 | "\n", 195 | " print(\"\\n🔊 Converting transcript to audio...\")\n", 196 | " print(\"-\" * 50)\n", 197 | "\n", 198 | " # Progress callback for fal-client\n", 199 | " def on_queue_update(update):\n", 200 | " if isinstance(update, fal_client.InProgress):\n", 201 | " for log in update.logs:\n", 202 | " print(f\"🎵 {log['message']}\")\n", 203 | "\n", 204 | " # Generate audio using fal-client\n", 205 | " try:\n", 206 | " result = fal_client.subscribe(\n", 207 | " \"fal-ai/playht/tts/ldm\",\n", 208 | " {\n", 209 | " \"input\": transcript_result,\n", 210 | " \"voices\": [\n", 211 | " {\n", 212 | " \"voice\": \"Jennifer (English (US)/American)\",\n", 213 | " \"turn_prefix\": \"Speaker 1: \"\n", 214 | " },\n", 215 | " {\n", 216 | " \"voice\": \"Dexter (English (US)/American)\",\n", 217 | " \"turn_prefix\": \"Speaker 2: \"\n", 218 | " }\n", 219 | " ]\n", 220 | " },\n", 221 | " with_logs=True,\n", 222 | " on_queue_update=on_queue_update,\n", 223 | " )\n", 224 | "\n", 225 | " print(\"\\n✅ Audio generation complete!\")\n", 226 | " print(f\"🔗 Audio URL: {result['audio']['url']}\")\n", 227 | "\n", 228 | " return {\n", 229 | " \"conversation\": transcript_result,\n", 230 | " \"audio_url\": result['audio']['url']\n", 231 | " }\n", 232 | "\n", 233 | " except Exception as e:\n", 234 | " print(f\"\\n❌ Error generating audio: {str(e)}\")\n", 235 | " return {\n", 236 | " \"conversation\": transcript_result,\n", 237 | " \"audio_url\": None,\n", 238 | " \"error\": str(e)\n", 239 | " }" 240 | ], 241 | "metadata": { 242 | "id": "ocPp1ws8wU-9" 243 | }, 244 | "execution_count": 11, 245 | "outputs": [] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "source": [ 250 | "generate_podcast(\"Quantum Random Walks\")" 251 | ], 252 | "metadata": { 253 | "colab": { 254 | "base_uri": "https://localhost:8080/" 255 | }, 256 | "id": "Q3k81CQJwYjU", 257 | "outputId": "90cef993-6904-4b89-ecf2-a683dc4ad5a3" 258 | }, 259 | "execution_count": 12, 260 | "outputs": [ 261 | { 262 | "output_type": "stream", 263 | "name": "stdout", 264 | "text": [ 265 | "\n", 266 | "🎙️ Generating podcast transcript about: Quantum Random Walks\n", 267 | "--------------------------------------------------\n", 268 | "\n", 269 | "✍️ Generated transcript:\n", 270 | "--------------------------------------------------\n", 271 | "Speaker 1: Have you heard about quantum random walks? They’re like classical random walks but with quantum weirdness. \n", 272 | "Speaker 2: Yeah, but instead of probabilities, they use amplitudes, right? Superposition makes it way more powerful. \n", 273 | "Speaker 1: Exactly! The walker can explore multiple paths simultaneously, leading to faster spread than classical walks. \n", 274 | "Speaker 2: That’s why they’re used in quantum algorithms, like search problems. The speedup is mind-blowing. \n", 275 | "Speaker 1: True! And the interference effects? They can amplify or cancel paths, making it a game-changer for computation.\n", 276 | "\n", 277 | "🔊 Converting transcript to audio...\n", 278 | "--------------------------------------------------\n", 279 | "\n", 280 | "✅ Audio generation complete!\n", 281 | "🔗 Audio URL: https://v3.fal.media/files/penguin/TencvNVwGMCgAXACDYIYn_de8c5432-cfb7-4b4b-9f40-e8c3b819674b.mp3\n" 282 | ] 283 | }, 284 | { 285 | "output_type": "execute_result", 286 | "data": { 287 | "text/plain": [ 288 | "{'conversation': 'Speaker 1: Have you heard about quantum random walks? They’re like classical random walks but with quantum weirdness. \\nSpeaker 2: Yeah, but instead of probabilities, they use amplitudes, right? Superposition makes it way more powerful. \\nSpeaker 1: Exactly! The walker can explore multiple paths simultaneously, leading to faster spread than classical walks. \\nSpeaker 2: That’s why they’re used in quantum algorithms, like search problems. The speedup is mind-blowing. \\nSpeaker 1: True! And the interference effects? They can amplify or cancel paths, making it a game-changer for computation.',\n", 289 | " 'audio_url': 'https://v3.fal.media/files/penguin/TencvNVwGMCgAXACDYIYn_de8c5432-cfb7-4b4b-9f40-e8c3b819674b.mp3'}" 290 | ] 291 | }, 292 | "metadata": {}, 293 | "execution_count": 12 294 | } 295 | ] 296 | } 297 | ] 298 | } --------------------------------------------------------------------------------