Spaces:
Sleeping
Sleeping
Commit Β·
84c92d2
1
Parent(s): 6a91b12
Publish Podcast Assistant app to Hugging Face Space.
Browse filesAdd app source, vector index assets, and runtime dependencies with LFS tracking for large files.
- .env.example +3 -0
- .gitattributes +2 -0
- .gitignore +34 -0
- LICENSE +21 -0
- README.md +174 -4
- app.py +445 -4
- assistant.py +126 -0
- data/README.md +66 -0
- data/episodes_embedding_chunks.csv +3 -0
- data/episodes_website.json +1168 -0
- faiss_index.db/index.faiss +3 -0
- faiss_index.db/index.pkl +3 -0
- feedback.json +254 -0
- prompt.md +97 -0
- pyproject.toml +15 -0
- requirements.txt +8 -0
- search_podcasts.py +127 -0
- styles.css +537 -0
- test.py +376 -0
- uv.lock +0 -0
.env.example
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# OpenAI API Key (required)
|
| 2 |
+
# Get yours at: https://platform.openai.com/api-keys
|
| 3 |
+
OPENAI_API_KEY=sk-your-api-key-here
|
.gitattributes
CHANGED
|
@@ -19,6 +19,7 @@
|
|
| 19 |
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
*.pkl filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 22 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
*.rar filter=lfs diff=lfs merge=lfs -text
|
|
@@ -28,6 +29,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 28 |
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 31 |
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 19 |
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.faiss filter=lfs diff=lfs merge=lfs -text
|
| 23 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 24 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 25 |
*.rar filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 29 |
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 30 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 31 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
data/episodes_embedding_chunks.csv filter=lfs diff=lfs merge=lfs -text
|
| 33 |
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Environment (keep .env.example for reference)
|
| 2 |
+
.env
|
| 3 |
+
.env.local
|
| 4 |
+
!.env.example
|
| 5 |
+
|
| 6 |
+
# Python
|
| 7 |
+
__pycache__/
|
| 8 |
+
*.py[cod]
|
| 9 |
+
*$py.class
|
| 10 |
+
.Python
|
| 11 |
+
*.so
|
| 12 |
+
|
| 13 |
+
# Virtual environments
|
| 14 |
+
.venv/
|
| 15 |
+
venv/
|
| 16 |
+
ENV/
|
| 17 |
+
|
| 18 |
+
# IDE
|
| 19 |
+
.idea/
|
| 20 |
+
.vscode/
|
| 21 |
+
*.code-workspace
|
| 22 |
+
.cursor/
|
| 23 |
+
|
| 24 |
+
# Gradio
|
| 25 |
+
.gradio/
|
| 26 |
+
flagged/
|
| 27 |
+
|
| 28 |
+
# OS
|
| 29 |
+
.DS_Store
|
| 30 |
+
Thumbs.db
|
| 31 |
+
|
| 32 |
+
# Large data files (keep in repo for reproducibility, but can exclude to reduce size)
|
| 33 |
+
# faiss_index.db/
|
| 34 |
+
# data/episodes_embedding_chunks.csv
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 Stan Konkin
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
CHANGED
|
@@ -1,13 +1,183 @@
|
|
| 1 |
---
|
| 2 |
title: Podcast Assistant
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
colorTo: purple
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version: 6.5.1
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: mit
|
| 11 |
---
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: Podcast Assistant
|
| 3 |
+
emoji: π§
|
| 4 |
+
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
sdk: gradio
|
|
|
|
| 7 |
app_file: app.py
|
| 8 |
pinned: false
|
| 9 |
license: mit
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Podcast Assistant
|
| 13 |
+
|
| 14 |
+
A RAG-powered assistant that surfaces wisdom from **100+ Lex Fridman podcast episodes** β returning verbatim quotes with timestamped video links.
|
| 15 |
+
|
| 16 |
+
## Overview
|
| 17 |
+
|
| 18 |
+
Ask a question, get real quotes from guests like Elon Musk, Pavel Durov, and Andrew Huberman β with direct links to watch the original context.
|
| 19 |
+
|
| 20 |
+
**Example interaction:**
|
| 21 |
+
|
| 22 |
+
> **You:** What do tech founders think about work-life balance?
|
| 23 |
+
>
|
| 24 |
+
> **Assistant:** "I try to allocate as much time as possible for sleep..." β **Pavel Durov** (Telegram Founder)
|
| 25 |
+
> Watch: [Episode #482](https://www.youtube.com/watch?v=qjPH9njnaVU&t=973s)
|
| 26 |
+
|
| 27 |
+
## Architecture
|
| 28 |
+
|
| 29 |
+
```
|
| 30 |
+
User Question
|
| 31 |
+
β
|
| 32 |
+
βΌ
|
| 33 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 34 |
+
β LangChain Agent (GPT-4.1-mini) β
|
| 35 |
+
β - Decides when to search β
|
| 36 |
+
β - Formats response with quotes β
|
| 37 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 38 |
+
β
|
| 39 |
+
βΌ
|
| 40 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 41 |
+
β search_podcasts Tool β
|
| 42 |
+
β - OpenAI embeddings β
|
| 43 |
+
β - FAISS similarity search β
|
| 44 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 45 |
+
β
|
| 46 |
+
βΌ
|
| 47 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 48 |
+
β Vector Store (14K chunks) β
|
| 49 |
+
β - Transcript segments β
|
| 50 |
+
β - Episode metadata & timestamps β
|
| 51 |
+
βββββββββββββββββββββββββββββββββββββββ
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
**How it works:**
|
| 55 |
+
1. User asks a question β LangChain agent receives it with tool access
|
| 56 |
+
2. Agent calls `search_podcasts` β FAISS finds top 7 relevant transcript chunks
|
| 57 |
+
3. Agent formats response β Verbatim quotes with speaker attribution and episode links
|
| 58 |
+
4. Follow-up questions β Reuse existing context (no redundant searches)
|
| 59 |
+
|
| 60 |
+
## Quick Start
|
| 61 |
+
|
| 62 |
+
### Requirements
|
| 63 |
+
|
| 64 |
+
- Python 3.12
|
| 65 |
+
- [uv](https://docs.astral.sh/uv/) package manager
|
| 66 |
+
- OpenAI API key
|
| 67 |
+
|
| 68 |
+
### Setup
|
| 69 |
+
|
| 70 |
+
```bash
|
| 71 |
+
# Install uv (if not already installed)
|
| 72 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 73 |
+
|
| 74 |
+
# Clone and enter project
|
| 75 |
+
git clone <repo-url>
|
| 76 |
+
cd podcast-assistant
|
| 77 |
+
|
| 78 |
+
# Install dependencies
|
| 79 |
+
uv sync
|
| 80 |
+
|
| 81 |
+
# Configure environment
|
| 82 |
+
cp .env.example .env
|
| 83 |
+
# Add your OPENAI_API_KEY to .env
|
| 84 |
+
|
| 85 |
+
# Run the app
|
| 86 |
+
uv run app.py
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
Open http://localhost:7860
|
| 90 |
+
|
| 91 |
+
### Why uv?
|
| 92 |
+
|
| 93 |
+
We use [uv](https://docs.astral.sh/uv/) for dependency management β it's fast, handles Python versions, and creates reproducible environments via `uv.lock`. No Docker overhead needed.
|
| 94 |
+
|
| 95 |
+
## Project Structure
|
| 96 |
+
|
| 97 |
+
```
|
| 98 |
+
podcast-assistant/
|
| 99 |
+
βββ app.py # Gradio web UI
|
| 100 |
+
βββ assistant.py # LangChain agent with tool calling
|
| 101 |
+
βββ search_podcasts.py # FAISS search tool
|
| 102 |
+
βββ prompt.md # System prompt
|
| 103 |
+
βββ styles.css # UI styling
|
| 104 |
+
βββ pyproject.toml # Dependencies (Python 3.12)
|
| 105 |
+
βββ uv.lock # Locked versions for reproducibility
|
| 106 |
+
βββ faiss_index.db/ # Pre-built vector index
|
| 107 |
+
βββ data/
|
| 108 |
+
βββ README.md # Data pipeline docs
|
| 109 |
+
βββ episodes_website.json
|
| 110 |
+
βββ episodes_embedding_chunks.csv
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
## Key Dependencies
|
| 114 |
+
|
| 115 |
+
| Package | Version | Purpose |
|
| 116 |
+
|---------|---------|---------|
|
| 117 |
+
| langchain | 0.3+ | Agent framework with tool calling |
|
| 118 |
+
| langchain-openai | 0.3+ | OpenAI chat models and embeddings |
|
| 119 |
+
| faiss-cpu | 1.9+ | Vector similarity search |
|
| 120 |
+
| gradio | 4.0+ | Web interface |
|
| 121 |
+
|
| 122 |
+
Full versions locked in `uv.lock`.
|
| 123 |
+
|
| 124 |
+
## Model Selection
|
| 125 |
+
|
| 126 |
+
We evaluated 4 OpenAI models on a test dataset for quote accuracy, format compliance, latency, and cost.
|
| 127 |
+
|
| 128 |
+
| Model | Quote Accuracy | Follows Format | Latency | Cost (3 turns) |
|
| 129 |
+
|-------|---------------|----------------|---------|----------------|
|
| 130 |
+
| gpt-4.1-nano | Paraphrases | Yes | ~12s | $0.001 |
|
| 131 |
+
| gpt-4o-mini | Good | No (adds headers) | ~26s | $0.002 |
|
| 132 |
+
| **gpt-4.1-mini** | Good | Yes | ~35s | $0.006 |
|
| 133 |
+
| gpt-5-mini | Excellent | Yes | ~124s | $0.020 |
|
| 134 |
+
|
| 135 |
+
**Selected: GPT-4.1-mini** β Best balance of instruction-following, latency, and cost. The 4.1 architecture handles nuanced prompts better than 4o-mini without the verbosity of 5-series models.
|
| 136 |
+
|
| 137 |
+
**Cost per conversation:** ~$0.006 (3 messages)
|
| 138 |
+
|
| 139 |
+
## Feedback Collection
|
| 140 |
+
|
| 141 |
+
We collect feedback to improve the assistant β but only when you explicitly submit it. No data is saved during conversation, no user identifiers or tracking.
|
| 142 |
+
|
| 143 |
+
When you click "Submit Feedback," we save:
|
| 144 |
+
|
| 145 |
+
```json
|
| 146 |
+
{
|
| 147 |
+
"timestamp": "2026-02-07T10:30:00",
|
| 148 |
+
"turns": [
|
| 149 |
+
{"role": "user", "content": "What do founders think about..."},
|
| 150 |
+
{"role": "assistant", "content": "Tech founders often..."}
|
| 151 |
+
],
|
| 152 |
+
"feedback": {
|
| 153 |
+
"helpful": true,
|
| 154 |
+
"text": "Great answer!"
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
```
|
| 158 |
+
|
| 159 |
+
This helps us understand what's working and where the assistant can improve.
|
| 160 |
+
|
| 161 |
+
## Testing
|
| 162 |
+
|
| 163 |
+
```bash
|
| 164 |
+
uv run python test.py
|
| 165 |
+
```
|
| 166 |
+
|
| 167 |
+
Runs a multi-turn conversation with token usage, latency, and cost metrics.
|
| 168 |
+
|
| 169 |
+
## License
|
| 170 |
+
|
| 171 |
+
This project is licensed under the **MIT License** β you're free to use, modify, and distribute it for personal or commercial purposes. See the [LICENSE](LICENSE) file for details.
|
| 172 |
+
|
| 173 |
+
## Acknowledgments
|
| 174 |
+
|
| 175 |
+
This project wouldn't exist without:
|
| 176 |
+
|
| 177 |
+
- **[Lex Fridman Podcast](https://lexfridman.com/podcast/)** β For creating hundreds of hours of deeply insightful conversations with remarkable people.
|
| 178 |
+
|
| 179 |
+
- **[DataCamp](https://www.datacamp.com/)** β For world-class data and AI education that helped shape the skills behind this project.
|
| 180 |
+
|
| 181 |
+
- **[LangChain](https://langchain.com/)** β For building the agent framework that makes tool calling and conversation management straightforward.
|
| 182 |
+
|
| 183 |
+
- **[Gradio](https://gradio.app/)** β For making it easy to create beautiful ML interfaces without frontend complexity.
|
app.py
CHANGED
|
@@ -1,7 +1,448 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
def greet(name):
|
| 4 |
-
return "Hello " + name + "!!"
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Gradio Chat UI for Podcast Assistant.
|
| 3 |
+
|
| 4 |
+
A modern, minimalistic interface for exploring Lex Fridman podcast insights.
|
| 5 |
+
"""
|
| 6 |
+
import os
|
| 7 |
+
import json
|
| 8 |
+
import uuid
|
| 9 |
+
from datetime import datetime
|
| 10 |
+
from typing import Generator
|
| 11 |
+
|
| 12 |
import gradio as gr
|
| 13 |
+
from dotenv import load_dotenv
|
| 14 |
+
|
| 15 |
+
from assistant import PodcastAssistant
|
| 16 |
+
|
| 17 |
+
# Load environment variables from local .env
|
| 18 |
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 19 |
+
load_dotenv(dotenv_path=os.path.join(SCRIPT_DIR, '.env'))
|
| 20 |
+
|
| 21 |
+
# Configuration
|
| 22 |
+
MAX_MESSAGES = 3
|
| 23 |
+
FEEDBACK_FILE = os.path.join(SCRIPT_DIR, "feedback.json")
|
| 24 |
+
|
| 25 |
+
# Load custom CSS from external file
|
| 26 |
+
with open(os.path.join(SCRIPT_DIR, "styles.css"), "r") as f:
|
| 27 |
+
CUSTOM_CSS = f.read()
|
| 28 |
+
|
| 29 |
+
# Example questions for quick start
|
| 30 |
+
EXAMPLES = [
|
| 31 |
+
"What habits and routines do high performers follow?",
|
| 32 |
+
"What is the future of AI and AGI according to experts?",
|
| 33 |
+
"How should young people approach their career and education?"
|
| 34 |
+
]
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class FeedbackLogger:
|
| 38 |
+
"""
|
| 39 |
+
Saves conversation data only when user submits feedback.
|
| 40 |
+
|
| 41 |
+
Privacy-focused: No user-specific data collected.
|
| 42 |
+
Only stores: timestamp, conversation turns, and feedback.
|
| 43 |
+
"""
|
| 44 |
+
|
| 45 |
+
def __init__(self, filepath: str):
|
| 46 |
+
self.filepath = filepath
|
| 47 |
+
self._ensure_file_exists()
|
| 48 |
+
|
| 49 |
+
def _ensure_file_exists(self):
|
| 50 |
+
"""Create the feedback file if it doesn't exist."""
|
| 51 |
+
if not os.path.exists(self.filepath):
|
| 52 |
+
with open(self.filepath, 'w') as f:
|
| 53 |
+
json.dump([], f)
|
| 54 |
+
|
| 55 |
+
def _load_feedback(self) -> list:
|
| 56 |
+
"""Load all feedback entries from file."""
|
| 57 |
+
try:
|
| 58 |
+
with open(self.filepath, 'r') as f:
|
| 59 |
+
return json.load(f)
|
| 60 |
+
except (json.JSONDecodeError, FileNotFoundError):
|
| 61 |
+
return []
|
| 62 |
+
|
| 63 |
+
def _save_feedback(self, entries: list):
|
| 64 |
+
"""Save all feedback entries to file."""
|
| 65 |
+
with open(self.filepath, 'w') as f:
|
| 66 |
+
json.dump(entries, f, indent=2)
|
| 67 |
+
|
| 68 |
+
def save_with_feedback(self, turns: list, is_helpful: bool, feedback_text: str = ""):
|
| 69 |
+
"""
|
| 70 |
+
Save conversation and feedback together.
|
| 71 |
+
|
| 72 |
+
Only called when user explicitly submits feedback.
|
| 73 |
+
No data is stored until feedback is submitted.
|
| 74 |
+
"""
|
| 75 |
+
entries = self._load_feedback()
|
| 76 |
+
|
| 77 |
+
# Create minimal, privacy-focused entry
|
| 78 |
+
entry = {
|
| 79 |
+
"timestamp": datetime.now().isoformat(),
|
| 80 |
+
"turns": [{"role": msg["role"], "content": msg["content"]} for msg in turns],
|
| 81 |
+
"feedback": {
|
| 82 |
+
"helpful": is_helpful,
|
| 83 |
+
"text": feedback_text if feedback_text else ""
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
entries.append(entry)
|
| 88 |
+
self._save_feedback(entries)
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
# Initialize feedback logger
|
| 92 |
+
feedback_logger = FeedbackLogger(FEEDBACK_FILE)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def create_app():
|
| 96 |
+
"""Create and configure the Gradio application."""
|
| 97 |
+
|
| 98 |
+
with gr.Blocks(title="Podcast Assistant") as app:
|
| 99 |
+
# State variables
|
| 100 |
+
conversation_id = gr.State(lambda: str(uuid.uuid4()))
|
| 101 |
+
message_count = gr.State(0)
|
| 102 |
+
is_frozen = gr.State(False)
|
| 103 |
+
pending_feedback = gr.State(None) # Stores True (helpful) or False (unhelpful)
|
| 104 |
+
assistant_state = gr.State(None) # Will hold the PodcastAssistant instance
|
| 105 |
+
|
| 106 |
+
# Header - centered
|
| 107 |
+
gr.Markdown("""
|
| 108 |
+
<div style="text-align: center;">
|
| 109 |
+
<h1>π§ Podcast Assistant</h1>
|
| 110 |
+
<p>Ask questions about Lex Fridman podcast episodes. Get answers with quotes and links.</p>
|
| 111 |
+
</div>
|
| 112 |
+
""", elem_classes=["header-section"])
|
| 113 |
+
|
| 114 |
+
# Chat interface
|
| 115 |
+
chatbot = gr.Chatbot(
|
| 116 |
+
value=[],
|
| 117 |
+
height=270,
|
| 118 |
+
show_label=False,
|
| 119 |
+
elem_id="chatbot"
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
# Loading indicator (hidden by default) - animated
|
| 123 |
+
loading_msg = gr.Markdown(
|
| 124 |
+
value="π Thinking and searching...",
|
| 125 |
+
visible=False,
|
| 126 |
+
elem_classes=["loading-msg"]
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
# Message counter - minimal
|
| 130 |
+
counter_display = gr.Markdown(
|
| 131 |
+
value="π¬ 3 messages remaining",
|
| 132 |
+
elem_classes=["message-counter"]
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
# Limit reached message (hidden by default)
|
| 136 |
+
limit_msg = gr.Markdown(
|
| 137 |
+
value="β¨ You've used all 3 messages. Start a new conversation to continue exploring!",
|
| 138 |
+
visible=False,
|
| 139 |
+
elem_classes=["limit-msg"]
|
| 140 |
+
)
|
| 141 |
+
|
| 142 |
+
# Input area with buttons stacked on right
|
| 143 |
+
with gr.Row(elem_classes=["input-row"]):
|
| 144 |
+
msg_input = gr.Textbox(
|
| 145 |
+
placeholder="Ask about habits, AI, science, philosophy...",
|
| 146 |
+
show_label=False,
|
| 147 |
+
scale=8,
|
| 148 |
+
container=False
|
| 149 |
+
)
|
| 150 |
+
with gr.Column(scale=1, elem_classes=["buttons-col"]):
|
| 151 |
+
submit_btn = gr.Button("Send β€", variant="primary")
|
| 152 |
+
with gr.Column(elem_classes=["new-btn"]):
|
| 153 |
+
new_conv_btn = gr.Button("New β»")
|
| 154 |
+
|
| 155 |
+
# Frozen state message (hidden by default)
|
| 156 |
+
frozen_msg = gr.Markdown(
|
| 157 |
+
visible=False,
|
| 158 |
+
elem_classes=["frozen-message"]
|
| 159 |
+
)
|
| 160 |
+
|
| 161 |
+
# Example buttons - horizontal row
|
| 162 |
+
with gr.Row(elem_classes=["examples-section"]):
|
| 163 |
+
gr.Markdown("π‘ Try examples:")
|
| 164 |
+
example_btns = [
|
| 165 |
+
gr.Button(ex, size="sm", elem_classes=["example-btn"])
|
| 166 |
+
for ex in EXAMPLES
|
| 167 |
+
]
|
| 168 |
+
|
| 169 |
+
# Feedback section - inline, hidden until response complete
|
| 170 |
+
with gr.Row(visible=False, elem_classes=["feedback-section"]) as feedback_group:
|
| 171 |
+
gr.Markdown("π€ Was this helpful?")
|
| 172 |
+
helpful_btn = gr.Button("π Yes", size="sm")
|
| 173 |
+
unhelpful_btn = gr.Button("π No", size="sm")
|
| 174 |
+
|
| 175 |
+
# Feedback text input (hidden until button clicked)
|
| 176 |
+
with gr.Group(visible=False, elem_classes=["feedback-input"]) as feedback_input_group:
|
| 177 |
+
feedback_text = gr.Textbox(
|
| 178 |
+
placeholder="Any additional thoughts? (optional)",
|
| 179 |
+
show_label=False,
|
| 180 |
+
lines=2
|
| 181 |
+
)
|
| 182 |
+
submit_feedback_btn = gr.Button("Submit π¨", variant="primary")
|
| 183 |
+
|
| 184 |
+
# Footer
|
| 185 |
+
gr.Markdown(
|
| 186 |
+
"AI Podcast Assistant v2.0 β’ Built with Langchain and Gradio β’ Made with β€οΈ for learning",
|
| 187 |
+
elem_classes=["footer"]
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
# ============ Event Handlers ============
|
| 191 |
+
|
| 192 |
+
def respond(
|
| 193 |
+
message: str,
|
| 194 |
+
history: list,
|
| 195 |
+
conv_id: str,
|
| 196 |
+
msg_count: int,
|
| 197 |
+
frozen: bool,
|
| 198 |
+
assistant: PodcastAssistant
|
| 199 |
+
) -> Generator:
|
| 200 |
+
"""Handle user message and stream response."""
|
| 201 |
+
import time
|
| 202 |
+
|
| 203 |
+
# Output order: chatbot, message_count, is_frozen, assistant_state,
|
| 204 |
+
# counter_display, loading_msg, feedback_group, limit_msg,
|
| 205 |
+
# msg_input, submit_btn
|
| 206 |
+
|
| 207 |
+
if frozen or not message.strip():
|
| 208 |
+
yield (
|
| 209 |
+
history, msg_count, frozen, assistant,
|
| 210 |
+
gr.update(), gr.update(), gr.update(), gr.update(),
|
| 211 |
+
gr.update(), gr.update()
|
| 212 |
+
)
|
| 213 |
+
return
|
| 214 |
+
|
| 215 |
+
# Initialize assistant if needed
|
| 216 |
+
if assistant is None:
|
| 217 |
+
assistant = PodcastAssistant()
|
| 218 |
+
|
| 219 |
+
# Add user message to history
|
| 220 |
+
history = history + [{"role": "user", "content": message}]
|
| 221 |
+
new_count = msg_count + 1
|
| 222 |
+
|
| 223 |
+
# Update counter display
|
| 224 |
+
remaining = MAX_MESSAGES - new_count
|
| 225 |
+
counter_text = f"π¬ {remaining} message{'s' if remaining != 1 else ''} remaining"
|
| 226 |
+
|
| 227 |
+
# Yield initial state - show loading, disable inputs
|
| 228 |
+
yield (
|
| 229 |
+
history,
|
| 230 |
+
new_count,
|
| 231 |
+
frozen,
|
| 232 |
+
assistant,
|
| 233 |
+
gr.update(value=counter_text),
|
| 234 |
+
gr.update(visible=True), # Show loading
|
| 235 |
+
gr.update(visible=False), # Hide feedback
|
| 236 |
+
gr.update(visible=False), # Hide limit msg
|
| 237 |
+
gr.update(value="", interactive=False), # Clear and disable input
|
| 238 |
+
gr.update(interactive=False) # Disable send button
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
try:
|
| 242 |
+
# Add empty assistant message that we'll stream into
|
| 243 |
+
history = history + [{"role": "assistant", "content": ""}]
|
| 244 |
+
|
| 245 |
+
# Stream the response
|
| 246 |
+
response_text = ""
|
| 247 |
+
chunk_count = 0
|
| 248 |
+
for chunk in assistant.stream_chat(message):
|
| 249 |
+
response_text += chunk
|
| 250 |
+
history[-1]["content"] = response_text
|
| 251 |
+
chunk_count += 1
|
| 252 |
+
|
| 253 |
+
# Add delay for smoother streaming
|
| 254 |
+
if chunk_count % 2 == 0:
|
| 255 |
+
time.sleep(0.03)
|
| 256 |
+
|
| 257 |
+
yield (
|
| 258 |
+
history,
|
| 259 |
+
new_count,
|
| 260 |
+
frozen,
|
| 261 |
+
assistant,
|
| 262 |
+
gr.update(value=counter_text),
|
| 263 |
+
gr.update(visible=False), # Hide loading once streaming
|
| 264 |
+
gr.update(visible=False),
|
| 265 |
+
gr.update(visible=False),
|
| 266 |
+
gr.update(interactive=False), # Keep input disabled
|
| 267 |
+
gr.update(interactive=False) # Keep button disabled
|
| 268 |
+
)
|
| 269 |
+
|
| 270 |
+
# Response complete - show feedback, re-enable inputs
|
| 271 |
+
# Note: Conversation is NOT saved here - only saved when feedback is submitted
|
| 272 |
+
if new_count >= MAX_MESSAGES:
|
| 273 |
+
# Limit reached - keep inputs disabled
|
| 274 |
+
frozen = True
|
| 275 |
+
yield (
|
| 276 |
+
history,
|
| 277 |
+
new_count,
|
| 278 |
+
frozen,
|
| 279 |
+
assistant,
|
| 280 |
+
gr.update(visible=False), # Hide counter
|
| 281 |
+
gr.update(visible=False), # Hide loading
|
| 282 |
+
gr.update(visible=True), # Show feedback
|
| 283 |
+
gr.update(visible=True), # Show limit msg
|
| 284 |
+
gr.update(interactive=False), # Keep input disabled
|
| 285 |
+
gr.update(interactive=False) # Keep button disabled
|
| 286 |
+
)
|
| 287 |
+
else:
|
| 288 |
+
# Still have messages remaining - re-enable inputs
|
| 289 |
+
yield (
|
| 290 |
+
history,
|
| 291 |
+
new_count,
|
| 292 |
+
frozen,
|
| 293 |
+
assistant,
|
| 294 |
+
gr.update(value=counter_text),
|
| 295 |
+
gr.update(visible=False), # Hide loading
|
| 296 |
+
gr.update(visible=True), # Show feedback
|
| 297 |
+
gr.update(visible=False),
|
| 298 |
+
gr.update(interactive=True), # Re-enable input
|
| 299 |
+
gr.update(interactive=True) # Re-enable button
|
| 300 |
+
)
|
| 301 |
+
|
| 302 |
+
except Exception as e:
|
| 303 |
+
# Handle errors gracefully - re-enable inputs
|
| 304 |
+
error_msg = "π Sorry, something went wrong on our end. We'll make sure to get better! Please try again."
|
| 305 |
+
if history and history[-1]["role"] == "assistant":
|
| 306 |
+
history[-1]["content"] = error_msg
|
| 307 |
+
else:
|
| 308 |
+
history = history + [{"role": "assistant", "content": error_msg}]
|
| 309 |
+
yield (
|
| 310 |
+
history,
|
| 311 |
+
new_count,
|
| 312 |
+
frozen,
|
| 313 |
+
assistant,
|
| 314 |
+
gr.update(value=counter_text),
|
| 315 |
+
gr.update(visible=False),
|
| 316 |
+
gr.update(visible=False),
|
| 317 |
+
gr.update(visible=False),
|
| 318 |
+
gr.update(interactive=True), # Re-enable input on error
|
| 319 |
+
gr.update(interactive=True) # Re-enable button on error
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def show_feedback_input(is_helpful: bool, conv_id: str):
|
| 324 |
+
"""Show feedback text input when helpful/unhelpful clicked."""
|
| 325 |
+
return (
|
| 326 |
+
is_helpful,
|
| 327 |
+
gr.update(visible=True), # Show feedback input
|
| 328 |
+
gr.update(visible=False), # Hide feedback buttons
|
| 329 |
+
)
|
| 330 |
+
|
| 331 |
+
def submit_feedback(
|
| 332 |
+
is_helpful: bool,
|
| 333 |
+
feedback_txt: str,
|
| 334 |
+
conv_id: str,
|
| 335 |
+
history: list
|
| 336 |
+
):
|
| 337 |
+
"""
|
| 338 |
+
Submit feedback and save conversation.
|
| 339 |
+
|
| 340 |
+
This is the ONLY place where data is saved.
|
| 341 |
+
Conversation + feedback saved together when user submits.
|
| 342 |
+
"""
|
| 343 |
+
if is_helpful is not None and history:
|
| 344 |
+
feedback_logger.save_with_feedback(history, is_helpful, feedback_txt or "")
|
| 345 |
+
|
| 346 |
+
return (
|
| 347 |
+
True, # Freeze conversation
|
| 348 |
+
gr.update(visible=False), # Hide feedback input
|
| 349 |
+
gr.update(interactive=False), # Disable input
|
| 350 |
+
gr.update(value="β
Appreciate your feedback! Click \"New\" to start fresh."),
|
| 351 |
+
gr.update(value="") # Clear feedback text box for next time
|
| 352 |
+
)
|
| 353 |
+
|
| 354 |
+
def start_new_conversation():
|
| 355 |
+
"""Reset everything for a new conversation."""
|
| 356 |
+
new_id = str(uuid.uuid4())
|
| 357 |
+
new_assistant = PodcastAssistant()
|
| 358 |
+
|
| 359 |
+
return (
|
| 360 |
+
[], # Clear chat
|
| 361 |
+
new_id, # New conversation ID
|
| 362 |
+
0, # Reset message count
|
| 363 |
+
False, # Unfreeze
|
| 364 |
+
new_assistant, # New assistant
|
| 365 |
+
None, # Clear pending feedback
|
| 366 |
+
gr.update(value="π¬ 3 messages remaining", visible=True), # Reset counter
|
| 367 |
+
gr.update(visible=False), # Hide feedback group
|
| 368 |
+
gr.update(visible=False), # Hide feedback input
|
| 369 |
+
gr.update(value="", interactive=True), # Clear and enable input
|
| 370 |
+
gr.update(visible=False), # Hide frozen message
|
| 371 |
+
gr.update(visible=False), # Hide limit msg
|
| 372 |
+
gr.update(visible=False), # Hide loading
|
| 373 |
+
gr.update(interactive=True), # Enable send button
|
| 374 |
+
)
|
| 375 |
+
|
| 376 |
+
# Common outputs for respond function
|
| 377 |
+
respond_outputs = [
|
| 378 |
+
chatbot, message_count, is_frozen, assistant_state,
|
| 379 |
+
counter_display, loading_msg, feedback_group, limit_msg,
|
| 380 |
+
msg_input, submit_btn
|
| 381 |
+
]
|
| 382 |
+
|
| 383 |
+
# Wire up events
|
| 384 |
+
msg_input.submit(
|
| 385 |
+
fn=respond,
|
| 386 |
+
inputs=[msg_input, chatbot, conversation_id, message_count, is_frozen, assistant_state],
|
| 387 |
+
outputs=respond_outputs
|
| 388 |
+
)
|
| 389 |
+
|
| 390 |
+
submit_btn.click(
|
| 391 |
+
fn=respond,
|
| 392 |
+
inputs=[msg_input, chatbot, conversation_id, message_count, is_frozen, assistant_state],
|
| 393 |
+
outputs=respond_outputs
|
| 394 |
+
)
|
| 395 |
+
|
| 396 |
+
# Example buttons - send message directly without showing in textbox
|
| 397 |
+
for btn, example in zip(example_btns, EXAMPLES):
|
| 398 |
+
# Create a closure to capture the example text
|
| 399 |
+
def make_example_handler(ex_text):
|
| 400 |
+
def handler(history, conv_id, msg_count, frozen, assistant):
|
| 401 |
+
yield from respond(ex_text, history, conv_id, msg_count, frozen, assistant)
|
| 402 |
+
return handler
|
| 403 |
+
|
| 404 |
+
btn.click(
|
| 405 |
+
fn=make_example_handler(example),
|
| 406 |
+
inputs=[chatbot, conversation_id, message_count, is_frozen, assistant_state],
|
| 407 |
+
outputs=respond_outputs
|
| 408 |
+
)
|
| 409 |
+
|
| 410 |
+
# Feedback buttons
|
| 411 |
+
helpful_btn.click(
|
| 412 |
+
fn=lambda conv_id: show_feedback_input(True, conv_id),
|
| 413 |
+
inputs=[conversation_id],
|
| 414 |
+
outputs=[pending_feedback, feedback_input_group, feedback_group]
|
| 415 |
+
)
|
| 416 |
+
|
| 417 |
+
unhelpful_btn.click(
|
| 418 |
+
fn=lambda conv_id: show_feedback_input(False, conv_id),
|
| 419 |
+
inputs=[conversation_id],
|
| 420 |
+
outputs=[pending_feedback, feedback_input_group, feedback_group]
|
| 421 |
+
)
|
| 422 |
+
|
| 423 |
+
submit_feedback_btn.click(
|
| 424 |
+
fn=submit_feedback,
|
| 425 |
+
inputs=[pending_feedback, feedback_text, conversation_id, chatbot],
|
| 426 |
+
outputs=[is_frozen, feedback_input_group, msg_input, frozen_msg, feedback_text]
|
| 427 |
+
).then(
|
| 428 |
+
fn=lambda: gr.update(visible=True),
|
| 429 |
+
outputs=[frozen_msg]
|
| 430 |
+
)
|
| 431 |
+
|
| 432 |
+
# New conversation button
|
| 433 |
+
new_conv_btn.click(
|
| 434 |
+
fn=start_new_conversation,
|
| 435 |
+
outputs=[
|
| 436 |
+
chatbot, conversation_id, message_count, is_frozen, assistant_state,
|
| 437 |
+
pending_feedback, counter_display, feedback_group, feedback_input_group,
|
| 438 |
+
msg_input, frozen_msg, limit_msg, loading_msg, submit_btn
|
| 439 |
+
]
|
| 440 |
+
)
|
| 441 |
+
|
| 442 |
+
return app
|
| 443 |
|
|
|
|
|
|
|
| 444 |
|
| 445 |
+
if __name__ == "__main__":
|
| 446 |
+
app = create_app()
|
| 447 |
+
# server_name="0.0.0.0" allows access from other devices on the same network
|
| 448 |
+
app.launch(css=CUSTOM_CSS, footer_links=[], server_name="0.0.0.0")
|
assistant.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Podcast Assistant - RAG-powered Q&A over Lex Fridman podcast transcripts.
|
| 3 |
+
|
| 4 |
+
This module provides the PodcastAssistant class for use with Gradio or other interfaces.
|
| 5 |
+
"""
|
| 6 |
+
import os
|
| 7 |
+
from datetime import datetime
|
| 8 |
+
from dotenv import load_dotenv
|
| 9 |
+
from langchain_core.messages import HumanMessage, SystemMessage
|
| 10 |
+
from langchain.chat_models import init_chat_model
|
| 11 |
+
|
| 12 |
+
from search_podcasts import search_podcasts
|
| 13 |
+
|
| 14 |
+
# Load environment variables from local .env
|
| 15 |
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 16 |
+
load_dotenv(dotenv_path=os.path.join(SCRIPT_DIR, '.env'))
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class PodcastAssistant:
|
| 20 |
+
"""RAG-powered assistant for querying podcast transcripts."""
|
| 21 |
+
|
| 22 |
+
def __init__(self, model: str = "gpt-4.1-mini"):
|
| 23 |
+
"""Initialize the podcast assistant.
|
| 24 |
+
|
| 25 |
+
Args:
|
| 26 |
+
model: The chat model to use (default: gpt-4.1-mini)
|
| 27 |
+
"""
|
| 28 |
+
# Initialize LLM
|
| 29 |
+
self.llm = init_chat_model(model=model)
|
| 30 |
+
|
| 31 |
+
# Set up tools
|
| 32 |
+
self.tools = [search_podcasts]
|
| 33 |
+
self.tools_dict = {t.name: t for t in self.tools}
|
| 34 |
+
|
| 35 |
+
# Bind tools to LLM
|
| 36 |
+
self.llm_with_tools = self.llm.bind_tools(self.tools)
|
| 37 |
+
|
| 38 |
+
# Load system prompt
|
| 39 |
+
with open(os.path.join(SCRIPT_DIR, "prompt.md"), "r") as f:
|
| 40 |
+
prompt_template = f.read()
|
| 41 |
+
|
| 42 |
+
today = datetime.now().strftime("%A, %B %d, %Y")
|
| 43 |
+
self.system_prompt = prompt_template.replace("{today_date}", today)
|
| 44 |
+
|
| 45 |
+
# Initialize conversation history
|
| 46 |
+
self.messages = [SystemMessage(content=self.system_prompt)]
|
| 47 |
+
|
| 48 |
+
def chat(self, message: str) -> str:
|
| 49 |
+
"""Process a user message and return the assistant's response.
|
| 50 |
+
|
| 51 |
+
Args:
|
| 52 |
+
message: User's question or request.
|
| 53 |
+
|
| 54 |
+
Returns:
|
| 55 |
+
Assistant's response with insights and video links.
|
| 56 |
+
"""
|
| 57 |
+
# Add user message
|
| 58 |
+
self.messages.append(HumanMessage(content=message))
|
| 59 |
+
|
| 60 |
+
# Agentic loop for tool calls
|
| 61 |
+
while True:
|
| 62 |
+
response = self.llm_with_tools.invoke(self.messages)
|
| 63 |
+
self.messages.append(response)
|
| 64 |
+
|
| 65 |
+
# Check if we're done (no tool calls)
|
| 66 |
+
if not response.tool_calls:
|
| 67 |
+
break
|
| 68 |
+
|
| 69 |
+
# Process tool calls
|
| 70 |
+
for tool_call in response.tool_calls:
|
| 71 |
+
tool_name = tool_call["name"]
|
| 72 |
+
|
| 73 |
+
if tool_name in self.tools_dict:
|
| 74 |
+
tool = self.tools_dict[tool_name]
|
| 75 |
+
tool_result = tool.invoke(tool_call)
|
| 76 |
+
self.messages.append(tool_result)
|
| 77 |
+
|
| 78 |
+
return response.content
|
| 79 |
+
|
| 80 |
+
def stream_chat(self, message: str):
|
| 81 |
+
"""Process a user message and stream the assistant's response.
|
| 82 |
+
|
| 83 |
+
Args:
|
| 84 |
+
message: User's question or request.
|
| 85 |
+
|
| 86 |
+
Yields:
|
| 87 |
+
Chunks of the assistant's response as they arrive.
|
| 88 |
+
"""
|
| 89 |
+
from langchain_core.messages import AIMessage
|
| 90 |
+
|
| 91 |
+
# Add user message
|
| 92 |
+
self.messages.append(HumanMessage(content=message))
|
| 93 |
+
|
| 94 |
+
# Agentic loop for tool calls (non-streaming)
|
| 95 |
+
while True:
|
| 96 |
+
response = self.llm_with_tools.invoke(self.messages)
|
| 97 |
+
|
| 98 |
+
# Check if we have tool calls to process
|
| 99 |
+
if not response.tool_calls:
|
| 100 |
+
# No tool calls - now stream the final response
|
| 101 |
+
# Remove the non-streamed response, we'll stream it instead
|
| 102 |
+
break
|
| 103 |
+
|
| 104 |
+
# Process tool calls
|
| 105 |
+
self.messages.append(response)
|
| 106 |
+
for tool_call in response.tool_calls:
|
| 107 |
+
tool_name = tool_call["name"]
|
| 108 |
+
|
| 109 |
+
if tool_name in self.tools_dict:
|
| 110 |
+
tool = self.tools_dict[tool_name]
|
| 111 |
+
tool_result = tool.invoke(tool_call)
|
| 112 |
+
self.messages.append(tool_result)
|
| 113 |
+
|
| 114 |
+
# Stream the final response
|
| 115 |
+
full_response = ""
|
| 116 |
+
for chunk in self.llm_with_tools.stream(self.messages):
|
| 117 |
+
if chunk.content:
|
| 118 |
+
full_response += chunk.content
|
| 119 |
+
yield chunk.content
|
| 120 |
+
|
| 121 |
+
# Add the complete response to history
|
| 122 |
+
self.messages.append(AIMessage(content=full_response))
|
| 123 |
+
|
| 124 |
+
def reset(self):
|
| 125 |
+
"""Reset conversation history."""
|
| 126 |
+
self.messages = [SystemMessage(content=self.system_prompt)]
|
data/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Data Pipeline
|
| 2 |
+
|
| 3 |
+
Source data and documentation for the vector index.
|
| 4 |
+
|
| 5 |
+
## Files
|
| 6 |
+
|
| 7 |
+
| File | Description |
|
| 8 |
+
|------|-------------|
|
| 9 |
+
| `episodes_website.json` | Episode metadata (106 episodes): titles, guests, YouTube URLs |
|
| 10 |
+
| `episodes_embedding_chunks.csv` | 14,514 transcript chunks with timestamps |
|
| 11 |
+
|
| 12 |
+
## What Gets Embedded
|
| 13 |
+
|
| 14 |
+
Each chunk is a structured text block that includes episode context and transcript content:
|
| 15 |
+
|
| 16 |
+
```
|
| 17 |
+
Episode: 455
|
| 18 |
+
Chapter: Introduction
|
| 19 |
+
|
| 20 |
+
BEFORE (context):
|
| 21 |
+
[~50 words from previous segment]
|
| 22 |
+
|
| 23 |
+
MAIN (target):
|
| 24 |
+
Adam Frank: If we don't ask how long they last, but instead ask
|
| 25 |
+
what's the probability that there have been any civilizations at all...
|
| 26 |
+
[~300 words - the core content we're searching]
|
| 27 |
+
|
| 28 |
+
AFTER (context):
|
| 29 |
+
[~50 words from next segment]
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
**Key design choices:**
|
| 33 |
+
- Episode number and chapter title are embedded with the text β this helps retrieval when users ask about specific episodes or topics
|
| 34 |
+
- The MAIN section contains the actual transcript with speaker names inline
|
| 35 |
+
- BEFORE/AFTER provide context so the LLM understands the quote in its original setting
|
| 36 |
+
- Overlapping windows ensure content isn't awkwardly split at chunk boundaries
|
| 37 |
+
|
| 38 |
+
## Vector Store
|
| 39 |
+
|
| 40 |
+
**Embeddings:** OpenAI `text-embedding-3-small` (1536 dimensions)
|
| 41 |
+
|
| 42 |
+
**Index:** FAISS flat index (`IndexFlatL2`)
|
| 43 |
+
- Simple brute-force similarity search
|
| 44 |
+
- Works well for our scale (~14K vectors)
|
| 45 |
+
- No approximation β returns exact nearest neighbors
|
| 46 |
+
- Trade-off: Larger indices (100K+) would benefit from IVF or HNSW for speed
|
| 47 |
+
|
| 48 |
+
**Storage:** `../faiss_index.db/`
|
| 49 |
+
- `index.faiss` β vector data
|
| 50 |
+
- `index.pkl` β metadata (episode, timestamp, URL, chapter)
|
| 51 |
+
|
| 52 |
+
## Adding New Episodes
|
| 53 |
+
|
| 54 |
+
To add new episodes or rebuild the index:
|
| 55 |
+
|
| 56 |
+
1. Scrape new episode metadata and transcripts
|
| 57 |
+
2. Process transcripts into chunks using the same BEFORE/MAIN/AFTER format
|
| 58 |
+
3. Append to `episodes_embedding_chunks.csv`
|
| 59 |
+
4. Rebuild the FAISS index from the full CSV
|
| 60 |
+
5. Replace `faiss_index.db/` with the new index
|
| 61 |
+
|
| 62 |
+
The flat index must be fully rebuilt β it doesn't support incremental additions. For a production system with frequent updates, consider using a vector database like Pinecone or Weaviate that supports upserts.
|
| 63 |
+
|
| 64 |
+
## Privacy
|
| 65 |
+
|
| 66 |
+
No user data is stored here. All content is from publicly available podcast episodes.
|
data/episodes_embedding_chunks.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1165e6cdd3e3b1ec29519de6646148259930158e8e877d8f6465f7d826b16410
|
| 3 |
+
size 27106060
|
data/episodes_website.json
ADDED
|
@@ -0,0 +1,1168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"episode_number": 489,
|
| 4 |
+
"guest_name": "Paul Rosolie",
|
| 5 |
+
"profile": "Naturalist & Explorer",
|
| 6 |
+
"title": "Paul Rosolie: Uncontacted Tribes in the Amazon Jungle",
|
| 7 |
+
"youtube_url": "https://www.youtube.com/watch?v=Z-FRe5AKmCU",
|
| 8 |
+
"youtube_video_id": "Z-FRe5AKmCU",
|
| 9 |
+
"episode_slug": "paul-rosolie-3",
|
| 10 |
+
"transcript_slug": "paul-rosolie-3-transcript",
|
| 11 |
+
"has_transcript": true
|
| 12 |
+
},
|
| 13 |
+
{
|
| 14 |
+
"episode_number": 488,
|
| 15 |
+
"guest_name": "Joel David Hamkins",
|
| 16 |
+
"profile": "Mathematician & Philosopher",
|
| 17 |
+
"title": "Infinity, Paradoxes, GΓΆdel Incompleteness & the Mathematical Multiverse",
|
| 18 |
+
"youtube_url": "https://www.youtube.com/watch?v=14OPT6CcsH4",
|
| 19 |
+
"youtube_video_id": "14OPT6CcsH4",
|
| 20 |
+
"episode_slug": "joel-david-hamkins",
|
| 21 |
+
"transcript_slug": "joel-david-hamkins-transcript",
|
| 22 |
+
"has_transcript": true
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
"episode_number": 487,
|
| 26 |
+
"guest_name": "Irving Finkel",
|
| 27 |
+
"profile": "Assyriologist and Cuneiform Scholar",
|
| 28 |
+
"title": "Deciphering Secrets of Ancient Civilizations, Noah's Ark, and Flood Myths",
|
| 29 |
+
"youtube_url": "https://www.youtube.com/watch?v=_bBRVNkAfkQ",
|
| 30 |
+
"youtube_video_id": "_bBRVNkAfkQ",
|
| 31 |
+
"episode_slug": "irving-finkel",
|
| 32 |
+
"transcript_slug": "irving-finkel-transcript",
|
| 33 |
+
"has_transcript": true
|
| 34 |
+
},
|
| 35 |
+
{
|
| 36 |
+
"episode_number": 486,
|
| 37 |
+
"guest_name": "Michael Levin",
|
| 38 |
+
"profile": "Biologist",
|
| 39 |
+
"title": "Michael Levin: Hidden Reality of Alien Intelligence & Biological Life",
|
| 40 |
+
"youtube_url": "https://www.youtube.com/watch?v=Qp0rCU49lMs",
|
| 41 |
+
"youtube_video_id": "Qp0rCU49lMs",
|
| 42 |
+
"episode_slug": "michael-levin-2",
|
| 43 |
+
"transcript_slug": "michael-levin-2-transcript",
|
| 44 |
+
"has_transcript": true
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"episode_number": 485,
|
| 48 |
+
"guest_name": "David Kirtley",
|
| 49 |
+
"profile": "Helion Energy CEO",
|
| 50 |
+
"title": "David Kirtley: Nuclear Fusion, Plasma Physics, and the Future of Energy",
|
| 51 |
+
"youtube_url": "https://www.youtube.com/watch?v=m_CFCyc2Shs",
|
| 52 |
+
"youtube_video_id": "m_CFCyc2Shs",
|
| 53 |
+
"episode_slug": "david-kirtley",
|
| 54 |
+
"transcript_slug": "david-kirtley-transcript",
|
| 55 |
+
"has_transcript": true
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"episode_number": 484,
|
| 59 |
+
"guest_name": "Dan Houser",
|
| 60 |
+
"profile": "Rockstar Games Co-founder",
|
| 61 |
+
"title": "Dan Houser: GTA, Red Dead Redemption, Rockstar, Absurd & Future of Gaming",
|
| 62 |
+
"youtube_url": "https://www.youtube.com/watch?v=o3gbXDjNWyI",
|
| 63 |
+
"youtube_video_id": "o3gbXDjNWyI",
|
| 64 |
+
"episode_slug": "dan-houser",
|
| 65 |
+
"transcript_slug": "dan-houser-transcript",
|
| 66 |
+
"has_transcript": true
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"episode_number": 483,
|
| 70 |
+
"guest_name": "Julia Shaw",
|
| 71 |
+
"profile": "Criminal Psychologist & Author",
|
| 72 |
+
"title": "Julia Shaw: Criminal Psychology of Murder, Serial Killers, Memory & Sex",
|
| 73 |
+
"youtube_url": "https://www.youtube.com/watch?v=7OLVwZeMCfY",
|
| 74 |
+
"youtube_video_id": "7OLVwZeMCfY",
|
| 75 |
+
"episode_slug": "julia-shaw",
|
| 76 |
+
"transcript_slug": "julia-shaw-transcript",
|
| 77 |
+
"has_transcript": true
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"episode_number": 482,
|
| 81 |
+
"guest_name": "Pavel Durov",
|
| 82 |
+
"profile": "Telegram Founder & CEO",
|
| 83 |
+
"title": "Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature",
|
| 84 |
+
"youtube_url": "https://www.youtube.com/watch?v=qjPH9njnaVU",
|
| 85 |
+
"youtube_video_id": "qjPH9njnaVU",
|
| 86 |
+
"episode_slug": "pavel-durov",
|
| 87 |
+
"transcript_slug": "pavel-durov-transcript",
|
| 88 |
+
"has_transcript": true
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"episode_number": 481,
|
| 92 |
+
"guest_name": "Norman Ohler",
|
| 93 |
+
"profile": "Historian & Author",
|
| 94 |
+
"title": "Norman Ohler: Hitler, Nazis, Drugs, WW2, Blitzkrieg, LSD, MKUltra & CIA",
|
| 95 |
+
"youtube_url": "https://www.youtube.com/watch?v=SvKv7D4pBjE",
|
| 96 |
+
"youtube_video_id": "SvKv7D4pBjE",
|
| 97 |
+
"episode_slug": "norman-ohler",
|
| 98 |
+
"transcript_slug": "norman-ohler-transcript",
|
| 99 |
+
"has_transcript": true
|
| 100 |
+
},
|
| 101 |
+
{
|
| 102 |
+
"episode_number": 480,
|
| 103 |
+
"guest_name": "Dave Hone",
|
| 104 |
+
"profile": "Paleontologist & Dinosaur Expert",
|
| 105 |
+
"title": "Dave Hone: T-Rex, Dinosaurs, Extinction, Evolution, and Jurassic Park",
|
| 106 |
+
"youtube_url": "https://www.youtube.com/watch?v=-Qm1_On71Oo",
|
| 107 |
+
"youtube_video_id": "-Qm1_On71Oo",
|
| 108 |
+
"episode_slug": "dave-hone",
|
| 109 |
+
"transcript_slug": "dave-hone-transcript",
|
| 110 |
+
"has_transcript": true
|
| 111 |
+
},
|
| 112 |
+
{
|
| 113 |
+
"episode_number": 479,
|
| 114 |
+
"guest_name": "Dave Plummer",
|
| 115 |
+
"profile": "Creator of Task Manager",
|
| 116 |
+
"title": "Dave Plummer: Programming, Autism, and Old-School Microsoft Stories",
|
| 117 |
+
"youtube_url": "https://www.youtube.com/watch?v=HsLgZzgpz9Y",
|
| 118 |
+
"youtube_video_id": "HsLgZzgpz9Y",
|
| 119 |
+
"episode_slug": "dave-plummer",
|
| 120 |
+
"transcript_slug": "dave-plummer-transcript",
|
| 121 |
+
"has_transcript": true
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"episode_number": 477,
|
| 125 |
+
"guest_name": "Keyu Jin",
|
| 126 |
+
"profile": "Economist & China Specialist",
|
| 127 |
+
"title": "Keyu Jin: China's Economy, Tariffs, Trade, Trump, Communism & Capitalism",
|
| 128 |
+
"youtube_url": "https://www.youtube.com/watch?v=y3yAVZk3tyA",
|
| 129 |
+
"youtube_video_id": "y3yAVZk3tyA",
|
| 130 |
+
"episode_slug": "keyu-jin",
|
| 131 |
+
"transcript_slug": "keyu-jin-transcript",
|
| 132 |
+
"has_transcript": true
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"episode_number": 476,
|
| 136 |
+
"guest_name": "Jack Weatherford",
|
| 137 |
+
"profile": "Anthropologist & Historian",
|
| 138 |
+
"title": "Jack Weatherford: Genghis Khan and the Mongol Empire",
|
| 139 |
+
"youtube_url": "https://www.youtube.com/watch?v=U1H1Ob7jk8Q",
|
| 140 |
+
"youtube_video_id": "U1H1Ob7jk8Q",
|
| 141 |
+
"episode_slug": "jack-weatherford",
|
| 142 |
+
"transcript_slug": "jack-weatherford-transcript",
|
| 143 |
+
"has_transcript": true
|
| 144 |
+
},
|
| 145 |
+
{
|
| 146 |
+
"episode_number": 475,
|
| 147 |
+
"guest_name": "Demis Hassabis",
|
| 148 |
+
"profile": "DeepMind Co-founder",
|
| 149 |
+
"title": "Demis Hassabis: Future of AI, Simulating Reality, Physics and Video Games",
|
| 150 |
+
"youtube_url": "https://www.youtube.com/watch?v=-HzgcbRXUK8",
|
| 151 |
+
"youtube_video_id": "-HzgcbRXUK8",
|
| 152 |
+
"episode_slug": "demis-hassabis-2",
|
| 153 |
+
"transcript_slug": "demis-hassabis-2-transcript",
|
| 154 |
+
"has_transcript": true
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"episode_number": 474,
|
| 158 |
+
"guest_name": "DHH",
|
| 159 |
+
"profile": "Legendary Programmer",
|
| 160 |
+
"title": "DHH: Future of Programming, AI, Ruby on Rails, Productivity & Parenting",
|
| 161 |
+
"youtube_url": "https://www.youtube.com/watch?v=vagyIcmIGOQ",
|
| 162 |
+
"youtube_video_id": "vagyIcmIGOQ",
|
| 163 |
+
"episode_slug": "dhh-david-heinemeier-hansson",
|
| 164 |
+
"transcript_slug": "dhh-david-heinemeier-hansson-transcript",
|
| 165 |
+
"has_transcript": true
|
| 166 |
+
},
|
| 167 |
+
{
|
| 168 |
+
"episode_number": 473,
|
| 169 |
+
"guest_name": "Iran War Debate",
|
| 170 |
+
"profile": "Scott is a staunch critic of U.S. foreign policy and military interventionism, while Mike is a leading expert on Iran and its nuclear program",
|
| 171 |
+
"title": "Iran War Debate: Nuclear Weapons, Trump, Peace, Power & the Middle East",
|
| 172 |
+
"youtube_url": "https://www.youtube.com/watch?v=gtmJi8LbAts",
|
| 173 |
+
"youtube_video_id": "gtmJi8LbAts",
|
| 174 |
+
"episode_slug": "iran-war-debate",
|
| 175 |
+
"transcript_slug": "iran-war-debate-transcript",
|
| 176 |
+
"has_transcript": true
|
| 177 |
+
},
|
| 178 |
+
{
|
| 179 |
+
"episode_number": 472,
|
| 180 |
+
"guest_name": "Terence Tao",
|
| 181 |
+
"profile": "Mathematician",
|
| 182 |
+
"title": "Terence Tao: Hardest Problems in Mathematics, Physics & the Future of AI",
|
| 183 |
+
"youtube_url": "https://www.youtube.com/watch?v=HUkBz-cdB-k",
|
| 184 |
+
"youtube_video_id": "HUkBz-cdB-k",
|
| 185 |
+
"episode_slug": "terence-tao",
|
| 186 |
+
"transcript_slug": "terence-tao-transcript",
|
| 187 |
+
"has_transcript": true
|
| 188 |
+
},
|
| 189 |
+
{
|
| 190 |
+
"episode_number": 471,
|
| 191 |
+
"guest_name": "Sundar Pichai",
|
| 192 |
+
"profile": "CEO of Google & Alphabet",
|
| 193 |
+
"title": "Sundar Pichai: CEO of Google and Alphabet",
|
| 194 |
+
"youtube_url": "https://www.youtube.com/watch?v=9V6tWC4CdFQ",
|
| 195 |
+
"youtube_video_id": "9V6tWC4CdFQ",
|
| 196 |
+
"episode_slug": "sundar-pichai",
|
| 197 |
+
"transcript_slug": "sundar-pichai-transcript",
|
| 198 |
+
"has_transcript": true
|
| 199 |
+
},
|
| 200 |
+
{
|
| 201 |
+
"episode_number": 470,
|
| 202 |
+
"guest_name": "James Holland",
|
| 203 |
+
"profile": "Historian",
|
| 204 |
+
"title": "James Holland: World War II, Hitler, Churchill, Stalin & Biggest Battles",
|
| 205 |
+
"youtube_url": "https://www.youtube.com/watch?v=cp1lprZUQcE",
|
| 206 |
+
"youtube_video_id": "cp1lprZUQcE",
|
| 207 |
+
"episode_slug": "james-holland",
|
| 208 |
+
"transcript_slug": "james-holland-transcript",
|
| 209 |
+
"has_transcript": true
|
| 210 |
+
},
|
| 211 |
+
{
|
| 212 |
+
"episode_number": 469,
|
| 213 |
+
"guest_name": "Oliver Anthony",
|
| 214 |
+
"profile": "Singer-Songwriter",
|
| 215 |
+
"title": "Oliver Anthony: Country Music, Blue-Collar America, Fame, Money, and Pain",
|
| 216 |
+
"youtube_url": "https://www.youtube.com/watch?v=4OyB3hFb2AA",
|
| 217 |
+
"youtube_video_id": "4OyB3hFb2AA",
|
| 218 |
+
"episode_slug": "oliver-anthony",
|
| 219 |
+
"transcript_slug": "oliver-anthony-transcript",
|
| 220 |
+
"has_transcript": true
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"episode_number": 468,
|
| 224 |
+
"guest_name": "Janna Levin",
|
| 225 |
+
"profile": "Theoretical Physicist & Cosmologist",
|
| 226 |
+
"title": "Janna Levin: Black Holes, Wormholes, Aliens, Paradoxes & Extra Dimensions",
|
| 227 |
+
"youtube_url": "https://www.youtube.com/watch?v=A6m4iJIw_84",
|
| 228 |
+
"youtube_video_id": "A6m4iJIw_84",
|
| 229 |
+
"episode_slug": "janna-levin",
|
| 230 |
+
"transcript_slug": "janna-levin-transcript",
|
| 231 |
+
"has_transcript": true
|
| 232 |
+
},
|
| 233 |
+
{
|
| 234 |
+
"episode_number": 467,
|
| 235 |
+
"guest_name": "Tim Sweeney",
|
| 236 |
+
"profile": "Epic Games Founder & Programmer",
|
| 237 |
+
"title": "Tim Sweeney: Fortnite, Unreal Engine, and the Future of Gaming",
|
| 238 |
+
"youtube_url": "https://www.youtube.com/watch?v=477qF6QNSvc",
|
| 239 |
+
"youtube_video_id": "477qF6QNSvc",
|
| 240 |
+
"episode_slug": "tim-sweeney",
|
| 241 |
+
"transcript_slug": "tim-sweeney-transcript",
|
| 242 |
+
"has_transcript": true
|
| 243 |
+
},
|
| 244 |
+
{
|
| 245 |
+
"episode_number": 466,
|
| 246 |
+
"guest_name": "Jeffrey Wasserstrom",
|
| 247 |
+
"profile": "China Historian",
|
| 248 |
+
"title": "Jeffrey Wasserstrom: China, Xi Jinping, Trade War, Taiwan, Hong Kong, Mao",
|
| 249 |
+
"youtube_url": "https://www.youtube.com/watch?v=3W5FWUN5w2Q",
|
| 250 |
+
"youtube_video_id": "3W5FWUN5w2Q",
|
| 251 |
+
"episode_slug": "jeffrey-wasserstrom",
|
| 252 |
+
"transcript_slug": "jeffrey-wasserstrom-transcript",
|
| 253 |
+
"has_transcript": true
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
"episode_number": 465,
|
| 257 |
+
"guest_name": "Robert Rodriguez",
|
| 258 |
+
"profile": "Legendary Filmmaker",
|
| 259 |
+
"title": "Robert Rodriguez: Sin City, Desperado, El Mariachi, Alita, and Filmmaking",
|
| 260 |
+
"youtube_url": "https://www.youtube.com/watch?v=xJoT3bJyHuA",
|
| 261 |
+
"youtube_video_id": "xJoT3bJyHuA",
|
| 262 |
+
"episode_slug": "robert-rodriguez",
|
| 263 |
+
"transcript_slug": "robert-rodriguez-transcript",
|
| 264 |
+
"has_transcript": true
|
| 265 |
+
},
|
| 266 |
+
{
|
| 267 |
+
"episode_number": 464,
|
| 268 |
+
"guest_name": "Dave Smith",
|
| 269 |
+
"profile": "Libertarian Political Commentator",
|
| 270 |
+
"title": "Dave Smith: Israel, Hamas, Ukraine, Russia, Conspiracies & Antisemitism",
|
| 271 |
+
"youtube_url": "https://www.youtube.com/watch?v=1V0bJfqEaa4",
|
| 272 |
+
"youtube_video_id": "1V0bJfqEaa4",
|
| 273 |
+
"episode_slug": "dave-smith",
|
| 274 |
+
"transcript_slug": "dave-smith-transcript",
|
| 275 |
+
"has_transcript": true
|
| 276 |
+
},
|
| 277 |
+
{
|
| 278 |
+
"episode_number": 463,
|
| 279 |
+
"guest_name": "Douglas Murray",
|
| 280 |
+
"profile": "Conservative Political Commentator",
|
| 281 |
+
"title": "Douglas Murray: Putin, Zelenskyy, Trump, Israel, Netanyahu, Hamas & Gaza",
|
| 282 |
+
"youtube_url": "https://www.youtube.com/watch?v=HvI42TyE5Ww",
|
| 283 |
+
"youtube_video_id": "HvI42TyE5Ww",
|
| 284 |
+
"episode_slug": "douglas-murray-2",
|
| 285 |
+
"transcript_slug": "douglas-murray-2-transcript",
|
| 286 |
+
"has_transcript": true
|
| 287 |
+
},
|
| 288 |
+
{
|
| 289 |
+
"episode_number": 462,
|
| 290 |
+
"guest_name": "Ezra Klein and Derek Thompson",
|
| 291 |
+
"profile": "Both representing the left-wing of American politics",
|
| 292 |
+
"title": "Ezra Klein and Derek Thompson: Politics, Trump, AOC, Elon & DOGE",
|
| 293 |
+
"youtube_url": "https://www.youtube.com/watch?v=DTPSeeKokdo",
|
| 294 |
+
"youtube_video_id": "DTPSeeKokdo",
|
| 295 |
+
"episode_slug": "ezra-klein-and-derek-thompson",
|
| 296 |
+
"transcript_slug": "ezra-klein-and-derek-thompson-transcript",
|
| 297 |
+
"has_transcript": true
|
| 298 |
+
},
|
| 299 |
+
{
|
| 300 |
+
"episode_number": 461,
|
| 301 |
+
"guest_name": "ThePrimeagen",
|
| 302 |
+
"profile": "Programmer & Educator",
|
| 303 |
+
"title": "ThePrimeagen: Programming, AI, ADHD, Productivity, Addiction, and God",
|
| 304 |
+
"youtube_url": "https://www.youtube.com/watch?v=tNZnLkRBYA8",
|
| 305 |
+
"youtube_video_id": "tNZnLkRBYA8",
|
| 306 |
+
"episode_slug": "theprimeagen",
|
| 307 |
+
"transcript_slug": "theprimeagen-transcript",
|
| 308 |
+
"has_transcript": true
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
"episode_number": 460,
|
| 312 |
+
"guest_name": "Narendra Modi",
|
| 313 |
+
"profile": "Prime Minister of India",
|
| 314 |
+
"title": "Narendra Modi: Prime Minister of India - Power, Democracy, War & Peace",
|
| 315 |
+
"youtube_url": "https://www.youtube.com/watch?v=ZPUtA3W-7_I",
|
| 316 |
+
"youtube_video_id": "ZPUtA3W-7_I",
|
| 317 |
+
"episode_slug": "narendra-modi",
|
| 318 |
+
"transcript_slug": "narendra-modi-transcript",
|
| 319 |
+
"has_transcript": true
|
| 320 |
+
},
|
| 321 |
+
{
|
| 322 |
+
"episode_number": 459,
|
| 323 |
+
"guest_name": "Dylan Patel and Nathan Lambert",
|
| 324 |
+
"profile": "AI and semiconductors researchers",
|
| 325 |
+
"title": "DeepSeek, China, OpenAI, NVIDIA, xAI, TSMC, Stargate, and AI Megaclusters",
|
| 326 |
+
"youtube_url": "https://www.youtube.com/watch?v=_1f-o0nqpEI",
|
| 327 |
+
"youtube_video_id": "_1f-o0nqpEI",
|
| 328 |
+
"episode_slug": "deepseek-dylan-patel-nathan-lambert",
|
| 329 |
+
"transcript_slug": "deepseek-dylan-patel-nathan-lambert-transcript",
|
| 330 |
+
"has_transcript": true
|
| 331 |
+
},
|
| 332 |
+
{
|
| 333 |
+
"episode_number": 458,
|
| 334 |
+
"guest_name": "Marc Andreessen",
|
| 335 |
+
"profile": "Tech Entrepreneur & Investor",
|
| 336 |
+
"title": "Marc Andreessen: Trump, Power, Tech, AI, Immigration & Future of America",
|
| 337 |
+
"youtube_url": "https://www.youtube.com/watch?v=OHWnPOKh_S0",
|
| 338 |
+
"youtube_video_id": "OHWnPOKh_S0",
|
| 339 |
+
"episode_slug": "marc-andreessen-2",
|
| 340 |
+
"transcript_slug": "marc-andreessen-2-transcript",
|
| 341 |
+
"has_transcript": true
|
| 342 |
+
},
|
| 343 |
+
{
|
| 344 |
+
"episode_number": 457,
|
| 345 |
+
"guest_name": "Jennifer Burns",
|
| 346 |
+
"profile": "Economic Historian",
|
| 347 |
+
"title": "Jennifer Burns: Milton Friedman, Ayn Rand, Economics, Capitalism, Freedom",
|
| 348 |
+
"youtube_url": "https://www.youtube.com/watch?v=Rz-4ulRKnz4",
|
| 349 |
+
"youtube_video_id": "Rz-4ulRKnz4",
|
| 350 |
+
"episode_slug": "jennifer-burns",
|
| 351 |
+
"transcript_slug": "jennifer-burns-transcript",
|
| 352 |
+
"has_transcript": true
|
| 353 |
+
},
|
| 354 |
+
{
|
| 355 |
+
"episode_number": 456,
|
| 356 |
+
"guest_name": "Volodymyr Zelenskyy",
|
| 357 |
+
"profile": "President of Ukraine",
|
| 358 |
+
"title": "Volodymyr Zelenskyy: Ukraine, War, Peace, Putin, Trump, NATO, and Freedom",
|
| 359 |
+
"youtube_url": "https://www.youtube.com/watch?v=u321m25rKXc",
|
| 360 |
+
"youtube_video_id": "u321m25rKXc",
|
| 361 |
+
"episode_slug": "volodymyr-zelenskyy",
|
| 362 |
+
"transcript_slug": "volodymyr-zelenskyy-transcript",
|
| 363 |
+
"has_transcript": true
|
| 364 |
+
},
|
| 365 |
+
{
|
| 366 |
+
"episode_number": 455,
|
| 367 |
+
"guest_name": "Adam Frank",
|
| 368 |
+
"profile": "Astrophysicist",
|
| 369 |
+
"title": "Adam Frank: Alien Civilizations and the Search for Extraterrestrial Life",
|
| 370 |
+
"youtube_url": "https://www.youtube.com/watch?v=yhZAXXI83-4",
|
| 371 |
+
"youtube_video_id": "yhZAXXI83-4",
|
| 372 |
+
"episode_slug": "adam-frank",
|
| 373 |
+
"transcript_slug": "adam-frank-transcript",
|
| 374 |
+
"has_transcript": true
|
| 375 |
+
},
|
| 376 |
+
{
|
| 377 |
+
"episode_number": 454,
|
| 378 |
+
"guest_name": "Saagar Enjeti",
|
| 379 |
+
"profile": "Political Commentator",
|
| 380 |
+
"title": "Saagar Enjeti: Trump, MAGA, DOGE, Obama, FDR, JFK, History & Politics",
|
| 381 |
+
"youtube_url": "https://www.youtube.com/watch?v=9xz8i90Hp2A",
|
| 382 |
+
"youtube_video_id": "9xz8i90Hp2A",
|
| 383 |
+
"episode_slug": "saagar-enjeti-2",
|
| 384 |
+
"transcript_slug": "saagar-enjeti-2-transcript",
|
| 385 |
+
"has_transcript": true
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"episode_number": 453,
|
| 389 |
+
"guest_name": "Javier Milei",
|
| 390 |
+
"profile": "President of Argentina",
|
| 391 |
+
"title": "Javier Milei: President of Argentina - Freedom, Economics, and Corruption",
|
| 392 |
+
"youtube_url": "https://www.youtube.com/watch?v=8NLzc9kobDk",
|
| 393 |
+
"youtube_video_id": "8NLzc9kobDk",
|
| 394 |
+
"episode_slug": "javier-milei",
|
| 395 |
+
"transcript_slug": "javier-milei-transcript",
|
| 396 |
+
"has_transcript": true
|
| 397 |
+
},
|
| 398 |
+
{
|
| 399 |
+
"episode_number": 452,
|
| 400 |
+
"guest_name": "Dario Amodei",
|
| 401 |
+
"profile": "CEO of Anthropic",
|
| 402 |
+
"title": "Dario Amodei: Anthropic CEO on Claude, AGI & the Future of AI & Humanity",
|
| 403 |
+
"youtube_url": "https://www.youtube.com/watch?v=ugvHCXCOmm4",
|
| 404 |
+
"youtube_video_id": "ugvHCXCOmm4",
|
| 405 |
+
"episode_slug": "dario-amodei",
|
| 406 |
+
"transcript_slug": "dario-amodei-transcript",
|
| 407 |
+
"has_transcript": true
|
| 408 |
+
},
|
| 409 |
+
{
|
| 410 |
+
"episode_number": 451,
|
| 411 |
+
"guest_name": "Rick Spence",
|
| 412 |
+
"profile": "Intelligence & Conspiracy Historian",
|
| 413 |
+
"title": "Rick Spence: CIA, KGB, Illuminati, Secret Societies, Cults & Conspiracies",
|
| 414 |
+
"youtube_url": "https://www.youtube.com/watch?v=abd5hguWKz0",
|
| 415 |
+
"youtube_video_id": "abd5hguWKz0",
|
| 416 |
+
"episode_slug": "rick-spence",
|
| 417 |
+
"transcript_slug": "rick-spence-transcript",
|
| 418 |
+
"has_transcript": true
|
| 419 |
+
},
|
| 420 |
+
{
|
| 421 |
+
"episode_number": 450,
|
| 422 |
+
"guest_name": "Bernie Sanders",
|
| 423 |
+
"profile": "Progressive Politician",
|
| 424 |
+
"title": "Bernie Sanders Interview",
|
| 425 |
+
"youtube_url": "https://www.youtube.com/watch?v=MzkgWDCucNY",
|
| 426 |
+
"youtube_video_id": "MzkgWDCucNY",
|
| 427 |
+
"episode_slug": "bernie-sanders",
|
| 428 |
+
"transcript_slug": "bernie-sanders-transcript",
|
| 429 |
+
"has_transcript": true
|
| 430 |
+
},
|
| 431 |
+
{
|
| 432 |
+
"episode_number": 449,
|
| 433 |
+
"guest_name": "Graham Hancock",
|
| 434 |
+
"profile": "Archaeological Journalist & Author",
|
| 435 |
+
"title": "Graham Hancock: Lost Civilization of the Ice Age & Ancient Human History",
|
| 436 |
+
"youtube_url": "https://www.youtube.com/watch?v=NMHiLvirCb0",
|
| 437 |
+
"youtube_video_id": "NMHiLvirCb0",
|
| 438 |
+
"episode_slug": "graham-hancock",
|
| 439 |
+
"transcript_slug": "graham-hancock-transcript",
|
| 440 |
+
"has_transcript": true
|
| 441 |
+
},
|
| 442 |
+
{
|
| 443 |
+
"episode_number": 448,
|
| 444 |
+
"guest_name": "Jordan Peterson",
|
| 445 |
+
"profile": "Psychologist & Author",
|
| 446 |
+
"title": "Jordan Peterson: Nietzsche, Hitler, God, Psychopathy, Suffering & Meaning",
|
| 447 |
+
"youtube_url": "https://www.youtube.com/watch?v=q8VePUwjB9Y",
|
| 448 |
+
"youtube_video_id": "q8VePUwjB9Y",
|
| 449 |
+
"episode_slug": "jordan-peterson-2",
|
| 450 |
+
"transcript_slug": "jordan-peterson-2-transcript",
|
| 451 |
+
"has_transcript": true
|
| 452 |
+
},
|
| 453 |
+
{
|
| 454 |
+
"episode_number": 447,
|
| 455 |
+
"guest_name": "Cursor Team",
|
| 456 |
+
"profile": "Creators of AI-assisted code editor",
|
| 457 |
+
"title": "Cursor Team: Future of Programming with AI",
|
| 458 |
+
"youtube_url": "https://www.youtube.com/watch?v=oFfVt3S51T4",
|
| 459 |
+
"youtube_video_id": "oFfVt3S51T4",
|
| 460 |
+
"episode_slug": "cursor-team",
|
| 461 |
+
"transcript_slug": "cursor-team-transcript",
|
| 462 |
+
"has_transcript": true
|
| 463 |
+
},
|
| 464 |
+
{
|
| 465 |
+
"episode_number": 446,
|
| 466 |
+
"guest_name": "Ed Barnhart",
|
| 467 |
+
"profile": "Archaeologist & Maya Expert",
|
| 468 |
+
"title": "Ed Barnhart: Maya, Aztec, Inca, and Lost Civilizations of South America",
|
| 469 |
+
"youtube_url": "https://www.youtube.com/watch?v=AzzE7GOvYz8",
|
| 470 |
+
"youtube_video_id": "AzzE7GOvYz8",
|
| 471 |
+
"episode_slug": "ed-barnhart",
|
| 472 |
+
"transcript_slug": "ed-barnhart-transcript",
|
| 473 |
+
"has_transcript": true
|
| 474 |
+
},
|
| 475 |
+
{
|
| 476 |
+
"episode_number": 445,
|
| 477 |
+
"guest_name": "Vivek Ramaswamy",
|
| 478 |
+
"profile": "Conservative Politician",
|
| 479 |
+
"title": "Vivek Ramaswamy: Trump, Conservatism, Nationalism, Immigration, and War",
|
| 480 |
+
"youtube_url": "https://www.youtube.com/watch?v=Q8Qk_3a3lUw",
|
| 481 |
+
"youtube_video_id": "Q8Qk_3a3lUw",
|
| 482 |
+
"episode_slug": "vivek-ramaswamy",
|
| 483 |
+
"transcript_slug": "vivek-ramaswamy-transcript",
|
| 484 |
+
"has_transcript": true
|
| 485 |
+
},
|
| 486 |
+
{
|
| 487 |
+
"episode_number": 444,
|
| 488 |
+
"guest_name": "Vejas Liulevicius",
|
| 489 |
+
"profile": "Historian",
|
| 490 |
+
"title": "Vejas Liulevicius: Communism, Marxism, Nazism, Stalin, Mao, and Hitler",
|
| 491 |
+
"youtube_url": "https://www.youtube.com/watch?v=s1oTH4Sjvzg",
|
| 492 |
+
"youtube_video_id": "s1oTH4Sjvzg",
|
| 493 |
+
"episode_slug": "vejas-liulevicius",
|
| 494 |
+
"transcript_slug": "vejas-liulevicius-transcript",
|
| 495 |
+
"has_transcript": true
|
| 496 |
+
},
|
| 497 |
+
{
|
| 498 |
+
"episode_number": 443,
|
| 499 |
+
"guest_name": "Gregory Aldrete",
|
| 500 |
+
"profile": "Historian",
|
| 501 |
+
"title": "Gregory Aldrete: The Roman Empire - Rise and Fall of Ancient Rome",
|
| 502 |
+
"youtube_url": "https://www.youtube.com/watch?v=DyoVVSggPjY",
|
| 503 |
+
"youtube_video_id": "DyoVVSggPjY",
|
| 504 |
+
"episode_slug": "gregory-aldrete",
|
| 505 |
+
"transcript_slug": "gregory-aldrete-transcript",
|
| 506 |
+
"has_transcript": true
|
| 507 |
+
},
|
| 508 |
+
{
|
| 509 |
+
"episode_number": 442,
|
| 510 |
+
"guest_name": "Donald Trump",
|
| 511 |
+
"profile": "President of the United States",
|
| 512 |
+
"title": "Donald Trump Interview",
|
| 513 |
+
"youtube_url": "https://www.youtube.com/watch?v=qCbfTN-caFI",
|
| 514 |
+
"youtube_video_id": "qCbfTN-caFI",
|
| 515 |
+
"episode_slug": "donald-trump",
|
| 516 |
+
"transcript_slug": "donald-trump-transcript",
|
| 517 |
+
"has_transcript": true
|
| 518 |
+
},
|
| 519 |
+
{
|
| 520 |
+
"episode_number": 441,
|
| 521 |
+
"guest_name": "Cenk Uygur",
|
| 522 |
+
"profile": "Progressive Political Commentator",
|
| 523 |
+
"title": "Cenk Uygur: Trump vs Harris, Progressive Politics, Communism & Capitalism",
|
| 524 |
+
"youtube_url": "https://www.youtube.com/watch?v=QJtPROVsePk",
|
| 525 |
+
"youtube_video_id": "QJtPROVsePk",
|
| 526 |
+
"episode_slug": "cenk-uygur",
|
| 527 |
+
"transcript_slug": "cenk-uygur-transcript",
|
| 528 |
+
"has_transcript": true
|
| 529 |
+
},
|
| 530 |
+
{
|
| 531 |
+
"episode_number": 440,
|
| 532 |
+
"guest_name": "Pieter Levels",
|
| 533 |
+
"profile": "Digital Nomad Entrepreneur",
|
| 534 |
+
"title": "Pieter Levels: Programming, Viral AI Startups, and Digital Nomad Life",
|
| 535 |
+
"youtube_url": "https://www.youtube.com/watch?v=oFtjKbXKqbg",
|
| 536 |
+
"youtube_video_id": "oFtjKbXKqbg",
|
| 537 |
+
"episode_slug": "pieter-levels",
|
| 538 |
+
"transcript_slug": "pieter-levels-transcript",
|
| 539 |
+
"has_transcript": true
|
| 540 |
+
},
|
| 541 |
+
{
|
| 542 |
+
"episode_number": 439,
|
| 543 |
+
"guest_name": "Craig Jones",
|
| 544 |
+
"profile": "Jiu Jitsu Champion",
|
| 545 |
+
"title": "Craig Jones: Jiu Jitsu, $2 Million Prize, CJI, ADCC, Ukraine & Trolling",
|
| 546 |
+
"youtube_url": "https://www.youtube.com/watch?v=J7aiEwp1x9k",
|
| 547 |
+
"youtube_video_id": "J7aiEwp1x9k",
|
| 548 |
+
"episode_slug": "craig-jones-2",
|
| 549 |
+
"transcript_slug": "craig-jones-2-transcript",
|
| 550 |
+
"has_transcript": true
|
| 551 |
+
},
|
| 552 |
+
{
|
| 553 |
+
"episode_number": 438,
|
| 554 |
+
"guest_name": "Elon Musk and Neuralink Team",
|
| 555 |
+
"profile": "Elon Musk is CEO of Neuralink, SpaceX, Tesla, xAI, and CTO of X. DJ Seo is COO & President of Neuralink. Matthew MacDougall is Head Neurosurgeon at Neuralink. Bliss Chapman is Brain Interface Software Lead at Neuralink. Noland Arbaugh is the first human to have a Neuralink device implanted in his brain",
|
| 556 |
+
"title": "Elon Musk: Neuralink and the Future of Humanity",
|
| 557 |
+
"youtube_url": "https://www.youtube.com/watch?v=Kbk9BiPhm7o",
|
| 558 |
+
"youtube_video_id": "Kbk9BiPhm7o",
|
| 559 |
+
"episode_slug": "elon-musk-and-neuralink-team",
|
| 560 |
+
"transcript_slug": "elon-musk-and-neuralink-team-transcript",
|
| 561 |
+
"has_transcript": true
|
| 562 |
+
},
|
| 563 |
+
{
|
| 564 |
+
"episode_number": 437,
|
| 565 |
+
"guest_name": "Jordan Jonas",
|
| 566 |
+
"profile": "Wilderness Survival Expert",
|
| 567 |
+
"title": "Jordan Jonas: Survival, Hunting, Siberia, God, and Winning Alone Season 6",
|
| 568 |
+
"youtube_url": "https://www.youtube.com/watch?v=WA9gVKKPsBo",
|
| 569 |
+
"youtube_video_id": "WA9gVKKPsBo",
|
| 570 |
+
"episode_slug": "jordan-jonas",
|
| 571 |
+
"transcript_slug": "jordan-jonas-transcript",
|
| 572 |
+
"has_transcript": true
|
| 573 |
+
},
|
| 574 |
+
{
|
| 575 |
+
"episode_number": 436,
|
| 576 |
+
"guest_name": "Ivanka Trump",
|
| 577 |
+
"profile": "Businesswoman, Presidential Advisor",
|
| 578 |
+
"title": "Ivanka Trump: Politics, Family, Real Estate, Fashion, Music, and Life",
|
| 579 |
+
"youtube_url": "https://www.youtube.com/watch?v=2oxdDKHdcM8",
|
| 580 |
+
"youtube_video_id": "2oxdDKHdcM8",
|
| 581 |
+
"episode_slug": "ivanka-trump",
|
| 582 |
+
"transcript_slug": "ivanka-trump-transcript",
|
| 583 |
+
"has_transcript": true
|
| 584 |
+
},
|
| 585 |
+
{
|
| 586 |
+
"episode_number": 435,
|
| 587 |
+
"guest_name": "Andrew Huberman",
|
| 588 |
+
"profile": "Neuroscientist",
|
| 589 |
+
"title": "Andrew Huberman: Focus, Controversy, Politics, and Relationships",
|
| 590 |
+
"youtube_url": "https://www.youtube.com/watch?v=ZIyB9e_7a4c",
|
| 591 |
+
"youtube_video_id": "ZIyB9e_7a4c",
|
| 592 |
+
"episode_slug": "andrew-huberman-5",
|
| 593 |
+
"transcript_slug": "andrew-huberman-5-transcript",
|
| 594 |
+
"has_transcript": true
|
| 595 |
+
},
|
| 596 |
+
{
|
| 597 |
+
"episode_number": 434,
|
| 598 |
+
"guest_name": "Aravind Srinivas",
|
| 599 |
+
"profile": "CEO of Perplexity",
|
| 600 |
+
"title": "Aravind Srinivas: Perplexity CEO on Future of AI, Search & the Internet",
|
| 601 |
+
"youtube_url": "https://www.youtube.com/watch?v=e-gwvmhyU7A",
|
| 602 |
+
"youtube_video_id": "e-gwvmhyU7A",
|
| 603 |
+
"episode_slug": "aravind-srinivas",
|
| 604 |
+
"transcript_slug": "aravind-srinivas-transcript",
|
| 605 |
+
"has_transcript": true
|
| 606 |
+
},
|
| 607 |
+
{
|
| 608 |
+
"episode_number": 433,
|
| 609 |
+
"guest_name": "Sara Walker",
|
| 610 |
+
"profile": "Astrobiologist & Physicist",
|
| 611 |
+
"title": "Sara Walker: Physics of Life, Time, Complexity, and Aliens",
|
| 612 |
+
"youtube_url": "https://www.youtube.com/watch?v=wwhTfyX9J34",
|
| 613 |
+
"youtube_video_id": "wwhTfyX9J34",
|
| 614 |
+
"episode_slug": "sara-walker-3",
|
| 615 |
+
"transcript_slug": "sara-walker-3-transcript",
|
| 616 |
+
"has_transcript": true
|
| 617 |
+
},
|
| 618 |
+
{
|
| 619 |
+
"episode_number": 432,
|
| 620 |
+
"guest_name": "Kevin Spacey",
|
| 621 |
+
"profile": "Oscar-Winning Actor",
|
| 622 |
+
"title": "Kevin Spacey: Power, Controversy, Betrayal, Truth & Love in Film and Life",
|
| 623 |
+
"youtube_url": "https://www.youtube.com/watch?v=XJTMQtE-MIo",
|
| 624 |
+
"youtube_video_id": "XJTMQtE-MIo",
|
| 625 |
+
"episode_slug": "kevin-spacey",
|
| 626 |
+
"transcript_slug": "kevin-spacey-transcript",
|
| 627 |
+
"has_transcript": true
|
| 628 |
+
},
|
| 629 |
+
{
|
| 630 |
+
"episode_number": 431,
|
| 631 |
+
"guest_name": "Roman Yampolskiy",
|
| 632 |
+
"profile": "AI Safety Researcher",
|
| 633 |
+
"title": "Roman Yampolskiy: Dangers of Superintelligent AI",
|
| 634 |
+
"youtube_url": "https://www.youtube.com/watch?v=NNr6gPelJ3E",
|
| 635 |
+
"youtube_video_id": "NNr6gPelJ3E",
|
| 636 |
+
"episode_slug": "roman-yampolskiy",
|
| 637 |
+
"transcript_slug": "roman-yampolskiy-transcript",
|
| 638 |
+
"has_transcript": true
|
| 639 |
+
},
|
| 640 |
+
{
|
| 641 |
+
"episode_number": 430,
|
| 642 |
+
"guest_name": "Charan Ranganath",
|
| 643 |
+
"profile": "Memory Research Neuroscientist",
|
| 644 |
+
"title": "Charan Ranganath: Human Memory, Imagination, Deja Vu, and False Memories",
|
| 645 |
+
"youtube_url": "https://www.youtube.com/watch?v=4iuepdI3wCU",
|
| 646 |
+
"youtube_video_id": "4iuepdI3wCU",
|
| 647 |
+
"episode_slug": "charan-ranganath",
|
| 648 |
+
"transcript_slug": "charan-ranganath-transcript",
|
| 649 |
+
"has_transcript": true
|
| 650 |
+
},
|
| 651 |
+
{
|
| 652 |
+
"episode_number": 429,
|
| 653 |
+
"guest_name": "Paul Rosolie",
|
| 654 |
+
"profile": "Naturalist & Explorer",
|
| 655 |
+
"title": "Paul Rosolie: Jungle, Apex Predators, Aliens, Uncontacted Tribes, and God",
|
| 656 |
+
"youtube_url": "https://www.youtube.com/watch?v=pwN8u6HFH8U",
|
| 657 |
+
"youtube_video_id": "pwN8u6HFH8U",
|
| 658 |
+
"episode_slug": "paul-rosolie-2",
|
| 659 |
+
"transcript_slug": "paul-rosolie-2-transcript",
|
| 660 |
+
"has_transcript": true
|
| 661 |
+
},
|
| 662 |
+
{
|
| 663 |
+
"episode_number": 428,
|
| 664 |
+
"guest_name": "Sean Carroll",
|
| 665 |
+
"profile": "Physicist",
|
| 666 |
+
"title": "Sean Carroll: General Relativity, Quantum Mechanics, Black Holes & Aliens",
|
| 667 |
+
"youtube_url": "https://www.youtube.com/watch?v=tdv7r2JSokI",
|
| 668 |
+
"youtube_video_id": "tdv7r2JSokI",
|
| 669 |
+
"episode_slug": "sean-carroll-3",
|
| 670 |
+
"transcript_slug": "sean-carroll-3-transcript",
|
| 671 |
+
"has_transcript": true
|
| 672 |
+
},
|
| 673 |
+
{
|
| 674 |
+
"episode_number": 427,
|
| 675 |
+
"guest_name": "Neil Adams",
|
| 676 |
+
"profile": "Judo World Champion",
|
| 677 |
+
"title": "Neil Adams: Judo, Olympics, Winning, Losing, and the Champion Mindset",
|
| 678 |
+
"youtube_url": "https://www.youtube.com/watch?v=TXabC2Ave74",
|
| 679 |
+
"youtube_video_id": "TXabC2Ave74",
|
| 680 |
+
"episode_slug": "neil-adams",
|
| 681 |
+
"transcript_slug": "neil-adams-transcript",
|
| 682 |
+
"has_transcript": true
|
| 683 |
+
},
|
| 684 |
+
{
|
| 685 |
+
"episode_number": 426,
|
| 686 |
+
"guest_name": "Edward Gibson",
|
| 687 |
+
"profile": "Psycholinguistics Professor",
|
| 688 |
+
"title": "Edward Gibson: Human Language, Psycholinguistics, Syntax, Grammar & LLMs",
|
| 689 |
+
"youtube_url": "https://www.youtube.com/watch?v=F3Jd9GI6XqE",
|
| 690 |
+
"youtube_video_id": "F3Jd9GI6XqE",
|
| 691 |
+
"episode_slug": "edward-gibson",
|
| 692 |
+
"transcript_slug": "edward-gibson-transcript",
|
| 693 |
+
"has_transcript": true
|
| 694 |
+
},
|
| 695 |
+
{
|
| 696 |
+
"episode_number": 425,
|
| 697 |
+
"guest_name": "Andrew Callaghan",
|
| 698 |
+
"profile": "Political Documentarian",
|
| 699 |
+
"title": "Andrew Callaghan: Channel 5, Gonzo, QAnon, O-Block, Politics & Alex Jones",
|
| 700 |
+
"youtube_url": "https://www.youtube.com/watch?v=yEou104m_P0",
|
| 701 |
+
"youtube_video_id": "yEou104m_P0",
|
| 702 |
+
"episode_slug": "andrew-callaghan",
|
| 703 |
+
"transcript_slug": "andrew-callaghan-transcript",
|
| 704 |
+
"has_transcript": true
|
| 705 |
+
},
|
| 706 |
+
{
|
| 707 |
+
"episode_number": 424,
|
| 708 |
+
"guest_name": "Bassem Youssef",
|
| 709 |
+
"profile": "Egyptian Political Satirist",
|
| 710 |
+
"title": "Bassem Youssef: Israel-Palestine, Gaza, Hamas, Middle East, Satire & Fame",
|
| 711 |
+
"youtube_url": "https://www.youtube.com/watch?v=sG8u6owzad4",
|
| 712 |
+
"youtube_video_id": "sG8u6owzad4",
|
| 713 |
+
"episode_slug": "bassem-youssef",
|
| 714 |
+
"transcript_slug": "bassem-youssef-transcript",
|
| 715 |
+
"has_transcript": true
|
| 716 |
+
},
|
| 717 |
+
{
|
| 718 |
+
"episode_number": 423,
|
| 719 |
+
"guest_name": "Tulsi Gabbard",
|
| 720 |
+
"profile": "Conservative Political Commentator",
|
| 721 |
+
"title": "Tulsi Gabbard: War, Politics, and the Military Industrial Complex",
|
| 722 |
+
"youtube_url": "https://www.youtube.com/watch?v=_El9riy9Zjw",
|
| 723 |
+
"youtube_video_id": "_El9riy9Zjw",
|
| 724 |
+
"episode_slug": "tulsi-gabbard",
|
| 725 |
+
"transcript_slug": "tulsi-gabbard-transcript",
|
| 726 |
+
"has_transcript": true
|
| 727 |
+
},
|
| 728 |
+
{
|
| 729 |
+
"episode_number": 422,
|
| 730 |
+
"guest_name": "Mark Cuban",
|
| 731 |
+
"profile": "Entrepreneur",
|
| 732 |
+
"title": "Mark Cuban: Shark Tank, DEI & Wokeism Debate, Elon Musk, Politics & Drugs",
|
| 733 |
+
"youtube_url": "https://www.youtube.com/watch?v=0cn3VBjfN8g",
|
| 734 |
+
"youtube_video_id": "0cn3VBjfN8g",
|
| 735 |
+
"episode_slug": "mark-cuban",
|
| 736 |
+
"transcript_slug": "mark-cuban-transcript",
|
| 737 |
+
"has_transcript": true
|
| 738 |
+
},
|
| 739 |
+
{
|
| 740 |
+
"episode_number": 421,
|
| 741 |
+
"guest_name": "Dana White",
|
| 742 |
+
"profile": "UFC President",
|
| 743 |
+
"title": "Dana White: UFC, Fighting, Khabib, Conor, Tyson, Ali, Rogan, Elon & Zuck",
|
| 744 |
+
"youtube_url": "https://www.youtube.com/watch?v=k7aQEqDbuf8",
|
| 745 |
+
"youtube_video_id": "k7aQEqDbuf8",
|
| 746 |
+
"episode_slug": "dana-white",
|
| 747 |
+
"transcript_slug": "dana-white-transcript",
|
| 748 |
+
"has_transcript": true
|
| 749 |
+
},
|
| 750 |
+
{
|
| 751 |
+
"episode_number": 420,
|
| 752 |
+
"guest_name": "Annie Jacobsen",
|
| 753 |
+
"profile": "National Security Investigative Journalist",
|
| 754 |
+
"title": "Annie Jacobsen: Nuclear War, CIA, KGB, Aliens, Area 51, Roswell & Secrecy",
|
| 755 |
+
"youtube_url": "https://www.youtube.com/watch?v=GXgGR8KxFao",
|
| 756 |
+
"youtube_video_id": "GXgGR8KxFao",
|
| 757 |
+
"episode_slug": "annie-jacobsen",
|
| 758 |
+
"transcript_slug": "annie-jacobsen-transcript",
|
| 759 |
+
"has_transcript": true
|
| 760 |
+
},
|
| 761 |
+
{
|
| 762 |
+
"episode_number": 419,
|
| 763 |
+
"guest_name": "Sam Altman",
|
| 764 |
+
"profile": "CEO of OpenAI",
|
| 765 |
+
"title": "Sam Altman: OpenAI, GPT-5, Sora, Board Saga, Elon Musk, Ilya, Power & AGI",
|
| 766 |
+
"youtube_url": "https://www.youtube.com/watch?v=jvqFAi7vkBc",
|
| 767 |
+
"youtube_video_id": "jvqFAi7vkBc",
|
| 768 |
+
"episode_slug": "sam-altman-2",
|
| 769 |
+
"transcript_slug": "sam-altman-2-transcript",
|
| 770 |
+
"has_transcript": true
|
| 771 |
+
},
|
| 772 |
+
{
|
| 773 |
+
"episode_number": 418,
|
| 774 |
+
"guest_name": "Israel-Palestine Debate",
|
| 775 |
+
"profile": "Norman Finkelstein and Benny Morris are historians. Mouin Rabbani is a Middle East analyst. Steven Bonnell (aka Destiny) is a political livestreamer",
|
| 776 |
+
"title": "Israel-Palestine Debate: Finkelstein, Destiny, M. Rabbani & Benny Morris",
|
| 777 |
+
"youtube_url": "https://www.youtube.com/watch?v=1X_KdkoGxSs",
|
| 778 |
+
"youtube_video_id": "1X_KdkoGxSs",
|
| 779 |
+
"episode_slug": "israel-palestine-debate",
|
| 780 |
+
"transcript_slug": "israel-palestine-debate-transcript",
|
| 781 |
+
"has_transcript": true
|
| 782 |
+
},
|
| 783 |
+
{
|
| 784 |
+
"episode_number": 417,
|
| 785 |
+
"guest_name": "Kimbal Musk",
|
| 786 |
+
"profile": "Entrepreneur & Restaurateur",
|
| 787 |
+
"title": "Kimbal Musk: The Art of Cooking, Tesla, SpaceX, Zip2, and Family",
|
| 788 |
+
"youtube_url": "https://www.youtube.com/watch?v=iAlwZyRUOVM",
|
| 789 |
+
"youtube_video_id": "iAlwZyRUOVM",
|
| 790 |
+
"episode_slug": "kimbal-musk",
|
| 791 |
+
"transcript_slug": "kimbal-musk-transcript",
|
| 792 |
+
"has_transcript": true
|
| 793 |
+
},
|
| 794 |
+
{
|
| 795 |
+
"episode_number": 416,
|
| 796 |
+
"guest_name": "Yann LeCun",
|
| 797 |
+
"profile": "AI Research Pioneer",
|
| 798 |
+
"title": "Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI",
|
| 799 |
+
"youtube_url": "https://www.youtube.com/watch?v=5t1vTLU7s40",
|
| 800 |
+
"youtube_video_id": "5t1vTLU7s40",
|
| 801 |
+
"episode_slug": "yann-lecun-3",
|
| 802 |
+
"transcript_slug": "yann-lecun-3-transcript",
|
| 803 |
+
"has_transcript": true
|
| 804 |
+
},
|
| 805 |
+
{
|
| 806 |
+
"episode_number": 415,
|
| 807 |
+
"guest_name": "Serhii Plokhy",
|
| 808 |
+
"profile": "Historian",
|
| 809 |
+
"title": "Serhii Plokhy: History of Ukraine, Russia, Soviet Union, KGB, Nazis & War",
|
| 810 |
+
"youtube_url": "https://www.youtube.com/watch?v=qa-wl8_wpZA",
|
| 811 |
+
"youtube_video_id": "qa-wl8_wpZA",
|
| 812 |
+
"episode_slug": "serhii-plokhy",
|
| 813 |
+
"transcript_slug": "serhii-plokhy-transcript",
|
| 814 |
+
"has_transcript": true
|
| 815 |
+
},
|
| 816 |
+
{
|
| 817 |
+
"episode_number": 414,
|
| 818 |
+
"guest_name": "Tucker Carlson",
|
| 819 |
+
"profile": "Conservative Political Commentator",
|
| 820 |
+
"title": "Tucker Carlson: Putin, Navalny, Trump, CIA, NSA, War, Politics & Freedom",
|
| 821 |
+
"youtube_url": "https://www.youtube.com/watch?v=f_lRdkH_QoY",
|
| 822 |
+
"youtube_video_id": "f_lRdkH_QoY",
|
| 823 |
+
"episode_slug": "tucker-carlson",
|
| 824 |
+
"transcript_slug": "tucker-carlson-transcript",
|
| 825 |
+
"has_transcript": true
|
| 826 |
+
},
|
| 827 |
+
{
|
| 828 |
+
"episode_number": 413,
|
| 829 |
+
"guest_name": "Bill Ackman",
|
| 830 |
+
"profile": "Investor",
|
| 831 |
+
"title": "Bill Ackman: Investing, Financial Battles, Harvard, DEI, X & Free Speech",
|
| 832 |
+
"youtube_url": "https://www.youtube.com/watch?v=PgGKhsWhUu8",
|
| 833 |
+
"youtube_video_id": "PgGKhsWhUu8",
|
| 834 |
+
"episode_slug": "bill-ackman",
|
| 835 |
+
"transcript_slug": "bill-ackman-transcript",
|
| 836 |
+
"has_transcript": true
|
| 837 |
+
},
|
| 838 |
+
{
|
| 839 |
+
"episode_number": 412,
|
| 840 |
+
"guest_name": "Marc Raibert",
|
| 841 |
+
"profile": "CEO of Boston Dynamics",
|
| 842 |
+
"title": "Marc Raibert: Boston Dynamics and the Future of Robotics",
|
| 843 |
+
"youtube_url": "https://www.youtube.com/watch?v=5VnbBCm_ZyQ",
|
| 844 |
+
"youtube_video_id": "5VnbBCm_ZyQ",
|
| 845 |
+
"episode_slug": "marc-raibert",
|
| 846 |
+
"transcript_slug": "marc-raibert-transcript",
|
| 847 |
+
"has_transcript": true
|
| 848 |
+
},
|
| 849 |
+
{
|
| 850 |
+
"episode_number": 411,
|
| 851 |
+
"guest_name": "Omar Suleiman",
|
| 852 |
+
"profile": "Islamic Scholar",
|
| 853 |
+
"title": "Omar Suleiman: Palestine, Gaza, Oct 7, Israel, Resistance, Faith & Islam",
|
| 854 |
+
"youtube_url": "https://www.youtube.com/watch?v=oFSyNdQf5uk",
|
| 855 |
+
"youtube_video_id": "oFSyNdQf5uk",
|
| 856 |
+
"episode_slug": "omar-suleiman-2",
|
| 857 |
+
"transcript_slug": "omar-suleiman-2-transcript",
|
| 858 |
+
"has_transcript": true
|
| 859 |
+
},
|
| 860 |
+
{
|
| 861 |
+
"episode_number": 410,
|
| 862 |
+
"guest_name": "Ben Shapiro vs Destiny Debate",
|
| 863 |
+
"profile": "Ben is a conservative political commentator, while Destiny is a liberal political commentator",
|
| 864 |
+
"title": "Ben Shapiro vs Destiny Debate: Politics, Jan 6, Israel, Ukraine & Wokeism",
|
| 865 |
+
"youtube_url": "https://www.youtube.com/watch?v=tYrdMjVXyNg",
|
| 866 |
+
"youtube_video_id": "tYrdMjVXyNg",
|
| 867 |
+
"episode_slug": "ben-shapiro-destiny-debate",
|
| 868 |
+
"transcript_slug": "ben-shapiro-destiny-debate-transcript",
|
| 869 |
+
"has_transcript": true
|
| 870 |
+
},
|
| 871 |
+
{
|
| 872 |
+
"episode_number": 409,
|
| 873 |
+
"guest_name": "Matthew Cox",
|
| 874 |
+
"profile": "Former Bank Fraudster",
|
| 875 |
+
"title": "Matthew Cox: FBI Most Wanted Con Man - $55 Million in Bank Fraud",
|
| 876 |
+
"youtube_url": "https://www.youtube.com/watch?v=zMYvGf7BA9o",
|
| 877 |
+
"youtube_video_id": "zMYvGf7BA9o",
|
| 878 |
+
"episode_slug": "matthew-cox",
|
| 879 |
+
"transcript_slug": "matthew-cox-transcript",
|
| 880 |
+
"has_transcript": true
|
| 881 |
+
},
|
| 882 |
+
{
|
| 883 |
+
"episode_number": 408,
|
| 884 |
+
"guest_name": "Tal Wilkenfeld",
|
| 885 |
+
"profile": "Bass Virtuoso & Musician",
|
| 886 |
+
"title": "Tal Wilkenfeld: Music, Guitar, Bass, Jeff Beck, Prince, and Leonard Cohen",
|
| 887 |
+
"youtube_url": "https://www.youtube.com/watch?v=9qfwPv7clEw",
|
| 888 |
+
"youtube_video_id": "9qfwPv7clEw",
|
| 889 |
+
"episode_slug": "tal-wilkenfeld",
|
| 890 |
+
"transcript_slug": "tal-wilkenfeld-transcript",
|
| 891 |
+
"has_transcript": true
|
| 892 |
+
},
|
| 893 |
+
{
|
| 894 |
+
"episode_number": 407,
|
| 895 |
+
"guest_name": "Guillaume Verdon",
|
| 896 |
+
"profile": "E/acc Movement Founder & Physicist",
|
| 897 |
+
"title": "Guillaume Verdon: Beff Jezos, E/acc Movement, Physics, Computation & AGI",
|
| 898 |
+
"youtube_url": "https://www.youtube.com/watch?v=8fEEbKJoNbU",
|
| 899 |
+
"youtube_video_id": "8fEEbKJoNbU",
|
| 900 |
+
"episode_slug": "guillaume-verdon",
|
| 901 |
+
"transcript_slug": "guillaume-verdon-transcript",
|
| 902 |
+
"has_transcript": true
|
| 903 |
+
},
|
| 904 |
+
{
|
| 905 |
+
"episode_number": 406,
|
| 906 |
+
"guest_name": "Teddy Atlas",
|
| 907 |
+
"profile": "Legendary Boxing Trainer",
|
| 908 |
+
"title": "Teddy Atlas: Mike Tyson, Cus D'Amato, Boxing, Loyalty, Fear & Greatness",
|
| 909 |
+
"youtube_url": "https://www.youtube.com/watch?v=CVx9IB_U9X4",
|
| 910 |
+
"youtube_video_id": "CVx9IB_U9X4",
|
| 911 |
+
"episode_slug": "teddy-atlas",
|
| 912 |
+
"transcript_slug": "teddy-atlas-transcript",
|
| 913 |
+
"has_transcript": true
|
| 914 |
+
},
|
| 915 |
+
{
|
| 916 |
+
"episode_number": 405,
|
| 917 |
+
"guest_name": "Jeff Bezos",
|
| 918 |
+
"profile": "Founder of Amazon & Blue Origin",
|
| 919 |
+
"title": "Jeff Bezos: Amazon and Blue Origin",
|
| 920 |
+
"youtube_url": "https://www.youtube.com/watch?v=DcWqzZ3I2cY",
|
| 921 |
+
"youtube_video_id": "DcWqzZ3I2cY",
|
| 922 |
+
"episode_slug": "jeff-bezos",
|
| 923 |
+
"transcript_slug": "jeff-bezos-transcript",
|
| 924 |
+
"has_transcript": true
|
| 925 |
+
},
|
| 926 |
+
{
|
| 927 |
+
"episode_number": 404,
|
| 928 |
+
"guest_name": "Lee Cronin",
|
| 929 |
+
"profile": "Chemist",
|
| 930 |
+
"title": "Lee Cronin: Controversial Nature Paper on Evolution of Life and Universe",
|
| 931 |
+
"youtube_url": "https://www.youtube.com/watch?v=CGiDqhSdLHk",
|
| 932 |
+
"youtube_video_id": "CGiDqhSdLHk",
|
| 933 |
+
"episode_slug": "lee-cronin-3",
|
| 934 |
+
"transcript_slug": "lee-cronin-3-transcript",
|
| 935 |
+
"has_transcript": true
|
| 936 |
+
},
|
| 937 |
+
{
|
| 938 |
+
"episode_number": 403,
|
| 939 |
+
"guest_name": "Lisa Randall",
|
| 940 |
+
"profile": "Theoretical Physicist",
|
| 941 |
+
"title": "Lisa Randall: Dark Matter, Theoretical Physics, and Extinction Events",
|
| 942 |
+
"youtube_url": "https://www.youtube.com/watch?v=VPaOy3G1-2A",
|
| 943 |
+
"youtube_video_id": "VPaOy3G1-2A",
|
| 944 |
+
"episode_slug": "lisa-randall",
|
| 945 |
+
"transcript_slug": "lisa-randall-transcript",
|
| 946 |
+
"has_transcript": true
|
| 947 |
+
},
|
| 948 |
+
{
|
| 949 |
+
"episode_number": 402,
|
| 950 |
+
"guest_name": "Michael Malice",
|
| 951 |
+
"profile": "Anarchist & Political Commentator",
|
| 952 |
+
"title": "Michael Malice: Thanksgiving Pirate Special",
|
| 953 |
+
"youtube_url": "https://www.youtube.com/watch?v=2yHr9DPnSzk",
|
| 954 |
+
"youtube_video_id": "2yHr9DPnSzk",
|
| 955 |
+
"episode_slug": "michael-malice-7",
|
| 956 |
+
"transcript_slug": "michael-malice-7-transcript",
|
| 957 |
+
"has_transcript": true
|
| 958 |
+
},
|
| 959 |
+
{
|
| 960 |
+
"episode_number": 401,
|
| 961 |
+
"guest_name": "John Mearsheimer",
|
| 962 |
+
"profile": "International Relations Scholar",
|
| 963 |
+
"title": "John Mearsheimer: Israel-Palestine, Russia-Ukraine, China, NATO, and WW3",
|
| 964 |
+
"youtube_url": "https://www.youtube.com/watch?v=r4wLXNydzeY",
|
| 965 |
+
"youtube_video_id": "r4wLXNydzeY",
|
| 966 |
+
"episode_slug": "john-mearsheimer",
|
| 967 |
+
"transcript_slug": "john-mearsheimer-transcript",
|
| 968 |
+
"has_transcript": true
|
| 969 |
+
},
|
| 970 |
+
{
|
| 971 |
+
"episode_number": 400,
|
| 972 |
+
"guest_name": "Elon Musk",
|
| 973 |
+
"profile": "CEO of Tesla, SpaceX, Neuralink, X",
|
| 974 |
+
"title": "Elon Musk: War, AI, Aliens, Politics, Physics, Video Games, and Humanity",
|
| 975 |
+
"youtube_url": "https://www.youtube.com/watch?v=JN3KPFbWCy8",
|
| 976 |
+
"youtube_video_id": "JN3KPFbWCy8",
|
| 977 |
+
"episode_slug": "elon-musk-4",
|
| 978 |
+
"transcript_slug": "elon-musk-4-transcript",
|
| 979 |
+
"has_transcript": true
|
| 980 |
+
},
|
| 981 |
+
{
|
| 982 |
+
"episode_number": 399,
|
| 983 |
+
"guest_name": "Jared Kushner",
|
| 984 |
+
"profile": "Investor, Presidential Advisor",
|
| 985 |
+
"title": "Jared Kushner: Israel, Palestine, Hamas, Gaza, Iran, and the Middle East",
|
| 986 |
+
"youtube_url": "https://www.youtube.com/watch?v=co_MeKSnyAo",
|
| 987 |
+
"youtube_video_id": "co_MeKSnyAo",
|
| 988 |
+
"episode_slug": "jared-kushner",
|
| 989 |
+
"transcript_slug": "jared-kushner-transcript",
|
| 990 |
+
"has_transcript": true
|
| 991 |
+
},
|
| 992 |
+
{
|
| 993 |
+
"episode_number": 398,
|
| 994 |
+
"guest_name": "Mark Zuckerberg",
|
| 995 |
+
"profile": "CEO of Meta",
|
| 996 |
+
"title": "Mark Zuckerberg: First Interview in the Metaverse",
|
| 997 |
+
"youtube_url": "https://www.youtube.com/watch?v=MVYrJJNdrEg",
|
| 998 |
+
"youtube_video_id": "MVYrJJNdrEg",
|
| 999 |
+
"episode_slug": "mark-zuckerberg-3",
|
| 1000 |
+
"transcript_slug": "mark-zuckerberg-3-transcript",
|
| 1001 |
+
"has_transcript": true
|
| 1002 |
+
},
|
| 1003 |
+
{
|
| 1004 |
+
"episode_number": 397,
|
| 1005 |
+
"guest_name": "Greg Lukianoff",
|
| 1006 |
+
"profile": "Free Speech Attorney & Author",
|
| 1007 |
+
"title": "Greg Lukianoff: Cancel Culture, Deplatforming, Censorship & Free Speech",
|
| 1008 |
+
"youtube_url": "https://www.youtube.com/watch?v=buarAx_u2qg",
|
| 1009 |
+
"youtube_video_id": "buarAx_u2qg",
|
| 1010 |
+
"episode_slug": "greg-lukianoff",
|
| 1011 |
+
"transcript_slug": "greg-lukianoff-transcript",
|
| 1012 |
+
"has_transcript": true
|
| 1013 |
+
},
|
| 1014 |
+
{
|
| 1015 |
+
"episode_number": 396,
|
| 1016 |
+
"guest_name": "James Sexton",
|
| 1017 |
+
"profile": "Divorce Attorney",
|
| 1018 |
+
"title": "James Sexton: Divorce Lawyer on Marriage, Relationships, Sex, Lies & Love",
|
| 1019 |
+
"youtube_url": "https://www.youtube.com/watch?v=fUEjCXpOjPY",
|
| 1020 |
+
"youtube_video_id": "fUEjCXpOjPY",
|
| 1021 |
+
"episode_slug": "james-sexton",
|
| 1022 |
+
"transcript_slug": "james-sexton-transcript",
|
| 1023 |
+
"has_transcript": true
|
| 1024 |
+
},
|
| 1025 |
+
{
|
| 1026 |
+
"episode_number": 395,
|
| 1027 |
+
"guest_name": "Walter Isaacson",
|
| 1028 |
+
"profile": "Biographer",
|
| 1029 |
+
"title": "Walter Isaacson: Elon Musk, Steve Jobs, Einstein, Da Vinci & Ben Franklin",
|
| 1030 |
+
"youtube_url": "https://www.youtube.com/watch?v=aGOV5R7M1Js",
|
| 1031 |
+
"youtube_video_id": "aGOV5R7M1Js",
|
| 1032 |
+
"episode_slug": "walter-isaacson",
|
| 1033 |
+
"transcript_slug": "walter-isaacson-transcript",
|
| 1034 |
+
"has_transcript": true
|
| 1035 |
+
},
|
| 1036 |
+
{
|
| 1037 |
+
"episode_number": 394,
|
| 1038 |
+
"guest_name": "Neri Oxman",
|
| 1039 |
+
"profile": "Biological Designer & Engineer",
|
| 1040 |
+
"title": "Neri Oxman: Biology, Art, and Science of Design & Engineering with Nature",
|
| 1041 |
+
"youtube_url": "https://www.youtube.com/watch?v=XbPHojL_61U",
|
| 1042 |
+
"youtube_video_id": "XbPHojL_61U",
|
| 1043 |
+
"episode_slug": "neri-oxman",
|
| 1044 |
+
"transcript_slug": "neri-oxman-transcript",
|
| 1045 |
+
"has_transcript": true
|
| 1046 |
+
},
|
| 1047 |
+
{
|
| 1048 |
+
"episode_number": 393,
|
| 1049 |
+
"guest_name": "Andrew Huberman",
|
| 1050 |
+
"profile": "Neuroscientist",
|
| 1051 |
+
"title": "Andrew Huberman: Relationships, Drama, Betrayal, Sex, and Love",
|
| 1052 |
+
"youtube_url": "https://www.youtube.com/watch?v=eTBAxD6lt2g",
|
| 1053 |
+
"youtube_video_id": "eTBAxD6lt2g",
|
| 1054 |
+
"episode_slug": "andrew-huberman-4",
|
| 1055 |
+
"transcript_slug": "andrew-huberman-4-transcript",
|
| 1056 |
+
"has_transcript": true
|
| 1057 |
+
},
|
| 1058 |
+
{
|
| 1059 |
+
"episode_number": 392,
|
| 1060 |
+
"guest_name": "Joscha Bach",
|
| 1061 |
+
"profile": "AI Researcher & Philosopher",
|
| 1062 |
+
"title": "Joscha Bach: Life, Intelligence, Consciousness, AI & the Future of Humans",
|
| 1063 |
+
"youtube_url": "https://www.youtube.com/watch?v=e8qJsk1j2zE",
|
| 1064 |
+
"youtube_video_id": "e8qJsk1j2zE",
|
| 1065 |
+
"episode_slug": "joscha-bach-3",
|
| 1066 |
+
"transcript_slug": "joscha-bach-3-transcript",
|
| 1067 |
+
"has_transcript": true
|
| 1068 |
+
},
|
| 1069 |
+
{
|
| 1070 |
+
"episode_number": 391,
|
| 1071 |
+
"guest_name": "Mohammed El-Kurd",
|
| 1072 |
+
"profile": "Palestinian Poet & Activist",
|
| 1073 |
+
"title": "Mohammed El-Kurd: Palestine",
|
| 1074 |
+
"youtube_url": "https://www.youtube.com/watch?v=34wA_bdG6QQ",
|
| 1075 |
+
"youtube_video_id": "34wA_bdG6QQ",
|
| 1076 |
+
"episode_slug": "mohammed-el-kurd",
|
| 1077 |
+
"transcript_slug": "mohammed-el-kurd-transcript",
|
| 1078 |
+
"has_transcript": true
|
| 1079 |
+
},
|
| 1080 |
+
{
|
| 1081 |
+
"episode_number": 390,
|
| 1082 |
+
"guest_name": "Yuval Noah Harari",
|
| 1083 |
+
"profile": "Historian",
|
| 1084 |
+
"title": "Yuval Noah Harari: Human Nature, Intelligence, Power, and Conspiracies",
|
| 1085 |
+
"youtube_url": "https://www.youtube.com/watch?v=Mde2q7GFCrw",
|
| 1086 |
+
"youtube_video_id": "Mde2q7GFCrw",
|
| 1087 |
+
"episode_slug": "yuval-noah-harari",
|
| 1088 |
+
"transcript_slug": "yuval-noah-harari-transcript",
|
| 1089 |
+
"has_transcript": true
|
| 1090 |
+
},
|
| 1091 |
+
{
|
| 1092 |
+
"episode_number": 389,
|
| 1093 |
+
"guest_name": "Benjamin Netanyahu",
|
| 1094 |
+
"profile": "Prime Minister of Israel",
|
| 1095 |
+
"title": "Benjamin Netanyahu: Israel, Palestine, Power, Corruption, Hate, and Peace",
|
| 1096 |
+
"youtube_url": "https://www.youtube.com/watch?v=XpC7SVDXimg",
|
| 1097 |
+
"youtube_video_id": "XpC7SVDXimg",
|
| 1098 |
+
"episode_slug": "benjamin-netanyahu",
|
| 1099 |
+
"transcript_slug": "benjamin-netanyahu-transcript",
|
| 1100 |
+
"has_transcript": true
|
| 1101 |
+
},
|
| 1102 |
+
{
|
| 1103 |
+
"episode_number": 388,
|
| 1104 |
+
"guest_name": "Robert F Kennedy Jr",
|
| 1105 |
+
"profile": "Presidential Candidate",
|
| 1106 |
+
"title": "Robert F. Kennedy Jr: CIA, Power, Corruption, War, Freedom, and Meaning",
|
| 1107 |
+
"youtube_url": "https://www.youtube.com/watch?v=NPtBkw5uD-0",
|
| 1108 |
+
"youtube_video_id": "NPtBkw5uD-0",
|
| 1109 |
+
"episode_slug": "robert-f-kennedy-jr",
|
| 1110 |
+
"transcript_slug": "robert-f-kennedy-jr-transcript",
|
| 1111 |
+
"has_transcript": true
|
| 1112 |
+
},
|
| 1113 |
+
{
|
| 1114 |
+
"episode_number": 387,
|
| 1115 |
+
"guest_name": "George Hotz",
|
| 1116 |
+
"profile": "Hacker & AI Developer",
|
| 1117 |
+
"title": "George Hotz: Tiny Corp, Twitter, AI Safety, Self-Driving, GPT, AGI & God",
|
| 1118 |
+
"youtube_url": "https://www.youtube.com/watch?v=dNrTrx42DGQ",
|
| 1119 |
+
"youtube_video_id": "dNrTrx42DGQ",
|
| 1120 |
+
"episode_slug": "george-hotz-3",
|
| 1121 |
+
"transcript_slug": "george-hotz-3-transcript",
|
| 1122 |
+
"has_transcript": true
|
| 1123 |
+
},
|
| 1124 |
+
{
|
| 1125 |
+
"episode_number": 385,
|
| 1126 |
+
"guest_name": "Jimmy Wales",
|
| 1127 |
+
"profile": "Founder of Wikipedia",
|
| 1128 |
+
"title": "Jimmy Wales: Wikipedia",
|
| 1129 |
+
"youtube_url": "https://www.youtube.com/watch?v=diJp4zoQPqo",
|
| 1130 |
+
"youtube_video_id": "diJp4zoQPqo",
|
| 1131 |
+
"episode_slug": "jimmy-wales",
|
| 1132 |
+
"transcript_slug": "jimmy-wales-transcript",
|
| 1133 |
+
"has_transcript": true
|
| 1134 |
+
},
|
| 1135 |
+
{
|
| 1136 |
+
"episode_number": 336,
|
| 1137 |
+
"guest_name": "Ben Shapiro",
|
| 1138 |
+
"profile": "Conservative Commentator",
|
| 1139 |
+
"title": "Ben Shapiro: Politics, Kanye, Trump, Biden, Hitler, Extremism, and War",
|
| 1140 |
+
"youtube_url": "https://www.youtube.com/watch?v=AF8DOS4C2KM",
|
| 1141 |
+
"youtube_video_id": "AF8DOS4C2KM",
|
| 1142 |
+
"episode_slug": "ben-shapiro",
|
| 1143 |
+
"transcript_slug": "ben-shapiro-transcript",
|
| 1144 |
+
"has_transcript": true
|
| 1145 |
+
},
|
| 1146 |
+
{
|
| 1147 |
+
"episode_number": 318,
|
| 1148 |
+
"guest_name": "Nick Lane",
|
| 1149 |
+
"profile": "Biologist",
|
| 1150 |
+
"title": "Nick Lane: Origin of Life, Evolution, Aliens, Biology, and Consciousness",
|
| 1151 |
+
"youtube_url": "https://www.youtube.com/watch?v=tOtdJcco3YM",
|
| 1152 |
+
"youtube_video_id": "tOtdJcco3YM",
|
| 1153 |
+
"episode_slug": "nick-lane",
|
| 1154 |
+
"transcript_slug": "nick-lane-transcript",
|
| 1155 |
+
"has_transcript": true
|
| 1156 |
+
},
|
| 1157 |
+
{
|
| 1158 |
+
"episode_number": 276,
|
| 1159 |
+
"guest_name": "Michael Saylor",
|
| 1160 |
+
"profile": "Bitcoin Investor",
|
| 1161 |
+
"title": "Michael Saylor: Bitcoin, Inflation, and the Future of Money",
|
| 1162 |
+
"youtube_url": "https://www.youtube.com/watch?v=mC43pZkpTec",
|
| 1163 |
+
"youtube_video_id": "mC43pZkpTec",
|
| 1164 |
+
"episode_slug": "michael-saylor",
|
| 1165 |
+
"transcript_slug": "michael-saylor-transcript",
|
| 1166 |
+
"has_transcript": true
|
| 1167 |
+
}
|
| 1168 |
+
]
|
faiss_index.db/index.faiss
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c609fc546b70173c230a6355c8417cc8a599d2a9b1c75d611c50584efcd78861
|
| 3 |
+
size 89174061
|
faiss_index.db/index.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5c1cc082fbfe506298fb091029ec824c21c017b9fcbd591206080424ef7c3b1d
|
| 3 |
+
size 27603569
|
feedback.json
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"timestamp": "2026-02-07T09:32:28.260903",
|
| 4 |
+
"turns": [
|
| 5 |
+
{
|
| 6 |
+
"role": "user",
|
| 7 |
+
"content": [
|
| 8 |
+
{
|
| 9 |
+
"text": "What is the future of AI and AGI according to experts?",
|
| 10 |
+
"type": "text"
|
| 11 |
+
}
|
| 12 |
+
]
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"role": "assistant",
|
| 16 |
+
"content": [
|
| 17 |
+
{
|
| 18 |
+
"text": "Experts on the Lex Fridman podcast generally foresee dramatic progress in AI and AGI by around 2030, with varying timelines and definitions of AGI, but emphasize the complexity and challenges still ahead before true general intelligence is achieved. There is cautious optimism mixed with concern about the societal and safety implications.\n\n> \"I almost feel the term doesn\u2019t matter, what I know is by 2030 there\u2019ll be such dramatic progress. We\u2019ll be dealing with the consequences of that progress, both the positive externalities and the negative externalities that come with it in a big way by 2030.\" \u2014 **Sundar Pichai** (CEO of Google & Alphabet) \n> Watch: [Episode 471: Sundar Pichai: CEO of Google and Alphabet](https://www.youtube.com/watch?v=9V6tWC4CdFQ&t=2394s)\n\n> \"I don\u2019t know for sure. The prediction markets right now are saying 2026 for AGI... but we don\u2019t have a working safety mechanism in place or even a prototype for one... progress is exponential.\" \u2014 **Roman Yampolskiy** (AI Safety Researcher) \n> Watch: [Episode 431: Roman Yampolskiy: Dangers of Superintelligent AI](https://www.youtube.com/watch?v=NNr6gPelJ3E&t=1227s)\n\n> \"My estimate is sort of 50% chance by in the next five years, so by 2030 let\u2019s say... it isn\u2019t kind of a jagged intelligence where some things, it\u2019s really good at... that would be amazing.\" \u2014 **Demis Hassabis** (DeepMind Co-founder) \n> Watch: [Episode 475: Demis Hassabis: Future of AI, Simulating Reality, Physics and Video Games](https://www.youtube.com/watch?v=-HzgcbRXUK8&t=3153s)\n\n> \"There are a lot of problems that we\u2019re not seeing right now that we have not encountered... it\u2019s not just around the corner. I\u2019ve been hearing people for the last 12, 15 years claiming that AGI is just around the corner and being systematically wrong.\" \u2014 **Yann LeCun** (AI Research Pioneer) \n> Watch: [Episode 416: Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI](https://www.youtube.com/watch?v=5t1vTLU7s40&t=7537s)\n\n> \"I think generally humanity is going to suffer a lot less, I\u2019m very optimistic about that... but the thing I worry about is it\u2019ll be few people, hundreds, thousands... ruling whoever\u2019s left.\" \u2014 **Dylan Patel & Nathan Lambert** (AI Researchers) \n> Watch: [Episode 459: DeepSeek, China, OpenAI, NVIDIA, xAI, TSMC, Stargate, and AI Megaclusters](https://www.youtube.com/watch?v=_1f-o0nqpEI&t=18169s)\n\nRecommended episodes to explore this topic more deeply: \n- [Episode 431: Roman Yampolskiy: Dangers of Superintelligent AI](https://www.youtube.com/watch?v=NNr6gPelJ3E) \n- [Episode 471: Sundar Pichai: CEO of Google and Alphabet](https://www.youtube.com/watch?v=9V6tWC4CdFQ) \n- [Episode 475: Demis Hassabis: Future of AI, Simulating Reality, Physics and Video Games](https://www.youtube.com/watch?v=-HzgcbRXUK8) \n- [Episode 416: Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI](https://www.youtube.com/watch?v=5t1vTLU7s40) \n- [Episode 459: DeepSeek, China, OpenAI, NVIDIA, xAI, TSMC, Stargate, and AI Megaclusters](https://www.youtube.com/watch?v=_1f-o0nqpEI)",
|
| 19 |
+
"type": "text"
|
| 20 |
+
}
|
| 21 |
+
]
|
| 22 |
+
}
|
| 23 |
+
],
|
| 24 |
+
"feedback": {
|
| 25 |
+
"helpful": true,
|
| 26 |
+
"text": "Amazing, very helpful, thank you so much!"
|
| 27 |
+
}
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
"timestamp": "2026-02-07T09:33:48.575317",
|
| 31 |
+
"turns": [
|
| 32 |
+
{
|
| 33 |
+
"role": "user",
|
| 34 |
+
"content": [
|
| 35 |
+
{
|
| 36 |
+
"text": "What is the future of AI and AGI according to experts?",
|
| 37 |
+
"type": "text"
|
| 38 |
+
}
|
| 39 |
+
]
|
| 40 |
+
},
|
| 41 |
+
{
|
| 42 |
+
"role": "assistant",
|
| 43 |
+
"content": [
|
| 44 |
+
{
|
| 45 |
+
"text": "Experts see the future of AI and AGI as a period of dramatic progress and transformative impact by 2030, with AI systems becoming more multimodal, capable, and integrated into human workflows. While there is optimism about AI's potential, many also express caution regarding safety, ethical use, and the societal consequences of advanced AI, including the risks tied to superintelligence and the uneven distribution of power.\n\nHere are some key insights from leading voices:\n\n> \"These models are natively multimodal. They can easily take content from any format, put it in any format... the progress will be dramatic. So that I believe in... by 2030 there\u2019ll be such dramatic progress... We'll be dealing with the consequences of that progress, both positive and negative.\" \u2014 **Sundar Pichai** (CEO of Google & Alphabet) \n> Watch: [Episode 471: Sundar Pichai: CEO of Google and Alphabet](https://www.youtube.com/watch?v=9V6tWC4CdFQ&t=2394s)\n\n> \"The prediction markets right now are saying 2026 for AGI... people are modifying definitions; AGI used to mean a system capable of performing any domain a human can, and superintelligence means better than all humans in all domains... Systems are already smarter than an average human by some definitions, but not yet elite-level in all domains.\" \u2014 **Roman Yampolskiy** (AI Safety Researcher) \n> Watch: [Episode 431: Roman Yampolskiy: Dangers of Superintelligent AI](https://www.youtube.com/watch?v=NNr6gPelJ3E&t=1227s)\n\n> \"It\u2019s not just around the corner... it\u2019s going to take at least a decade or more for systems to reason, plan, and learn hierarchical representations the way human brains do. I\u2019ve heard people say AGI is just around the corner for over a decade, and I called their bullshit.\" \u2014 **Yann LeCun** (AI Research Pioneer) \n> Watch: [Episode 416: Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI](https://www.youtube.com/watch?v=5t1vTLU7s40&t=7537s)\n\n> \"Generally... humanity is going to suffer a lot less... the thing I worry about is a few very powerful people merging with AGI capabilities, leading to concentrated power... it won\u2019t be one person rules all, but maybe thousands or millions will dominate whoever is left.\" \u2014 **Dylan Patel** (AI & semiconductor researcher) \n> Watch: [Episode 459: DeepSeek, China, OpenAI, NVIDIA, xAI, TSMC, Stargate, and AI Megaclusters](https://www.youtube.com/watch?v=_1f-o0nqpEI&t=18169s)\n\n> \"Human curiosity is not going anywhere... with AI, humans will feel more empowered and curious, leading to a new era of knowledge. It\u2019s possible we\u2019ll form deep connections with AI, but we should be cautious about replacing human relationships with AI companionship.\" \u2014 **Aravind Srinivas** (CEO of Perplexity) \n> Watch: [Episode 434: Aravind Srinivas: Perplexity CEO on Future of AI, Search & the Internet](https://www.youtube.com/watch?v=e-gwvmhyU7A&t=10255s)\n\nRecommended episodes to explore more:\n\n- [Episode 471: Sundar Pichai: CEO of Google and Alphabet](https://www.youtube.com/watch?v=9V6tWC4CdFQ) \u2014 Vision on AI progress and AGI timelines \n- [Episode 431: Roman Yampolskiy: Dangers of Superintelligent AI](https://www.youtube.com/watch?v=NNr6gPelJ3E) \u2014 Safety risks and AGI definitions \n- [Episode 416: Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI](https://www.youtube.com/watch?v=5t1vTLU7s40) \u2014 Skepticism on AGI timing and challenges \n- [Episode 459: DeepSeek, China, OpenAI, NVIDIA, xAI, TSMC, Stargate, and AI Megaclusters](https://www.youtube.com/watch?v=_1f-o0nqpEI) \u2014 AI power dynamics and societal impact \n- [Episode 434: Aravind Srinivas: Perplexity CEO on Future of AI, Search & the Internet](https://www.youtube.com/watch?v=e-gwvmhyU7A) \u2014 Human curiosity and AI companionship",
|
| 46 |
+
"type": "text"
|
| 47 |
+
}
|
| 48 |
+
]
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"role": "user",
|
| 52 |
+
"content": [
|
| 53 |
+
{
|
| 54 |
+
"text": "What is the best section to watch if I only have 30 minutes, and I want to think more about the future of AI, not about the current state?",
|
| 55 |
+
"type": "text"
|
| 56 |
+
}
|
| 57 |
+
]
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"role": "assistant",
|
| 61 |
+
"content": [
|
| 62 |
+
{
|
| 63 |
+
"text": "If you want to focus purely on the future of AI within 30 minutes, the best section to watch is from Sundar Pichai's episode around the 39 to 49-minute mark (timestamp roughly 2394s to 2994s). In this segment, he discusses the dramatic progress expected by 2030, AGI timelines, and the societal consequences of AI evolution.\n\nThis part captures a balanced, optimistic yet cautious view on where AI is heading, touching on the future capabilities and challenges without deep diving into current technical details.\n\nHere\u2019s the exact segment reference:\n\n> Sundar Pichai: \"By 2030 there\u2019ll be such dramatic progress. We\u2019ll be dealing with the consequences of that progress, both the positive externalities and the negative externalities that come with it in a big way... I think it\u2019ll take a bit longer than 2030 to reach AGI, but the progress will be remarkable.\" \n> Watch: [Episode 471: Sundar Pichai: CEO of Google and Alphabet](https://www.youtube.com/watch?v=9V6tWC4CdFQ&t=2394s)\n\nThis section provides a forward-looking perspective that's concise and highly relevant to your interest in the future, suitable for an engaging 30-minute viewing.",
|
| 64 |
+
"type": "text"
|
| 65 |
+
}
|
| 66 |
+
]
|
| 67 |
+
}
|
| 68 |
+
],
|
| 69 |
+
"feedback": {
|
| 70 |
+
"helpful": true,
|
| 71 |
+
"text": "Amazing! That's absolutely brilliant and very useful. Thank you!"
|
| 72 |
+
}
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"timestamp": "2026-02-07T09:35:16.458028",
|
| 76 |
+
"turns": [
|
| 77 |
+
{
|
| 78 |
+
"role": "user",
|
| 79 |
+
"content": [
|
| 80 |
+
{
|
| 81 |
+
"text": "How should young people approach their career and education?",
|
| 82 |
+
"type": "text"
|
| 83 |
+
}
|
| 84 |
+
]
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"role": "assistant",
|
| 88 |
+
"content": [
|
| 89 |
+
{
|
| 90 |
+
"text": "Young people should focus on continuous learning, patience, and connecting their work to a greater purpose rather than rushing into shortcuts. Following genuine interest, cultivating confidence in one's abilities, and seeing education as a lifelong journey are key for meaningful career and life fulfillment.\n\n> \"While working, one must continually strive to improve their skills and should never underestimate their ability to learn... Keep believing in yourself and trust that when the opportunity comes, you\u2019ll perform and you\u2019ll succeed. That confidence makes a person deliver results.\" \u2014 **Narendra Modi** (Prime Minister of India) \n> Watch: [Episode 460: Narendra Modi: Prime Minister of India - Power, Democracy, War & Peace](https://www.youtube.com/watch?v=ZPUtA3W-7_I&t=10047s)\n\n> \"So the only advice that I actually ever give to my students is follow what you\u2019re interested in... The people who survive are the people who care enough to still do it... they\u2019re very often the people who don\u2019t worry too much about the future and are able to live in the present.\" \u2014 **Nick Lane** (Biologist) \n> Watch: [Episode 318: Nick Lane: Origin of Life, Evolution, Aliens, Biology, and Consciousness](https://www.youtube.com/watch?v=tOtdJcco3YM&t=12373s)\n\n> \"To the younger generation, I don\u2019t speak of a career... I never thought of my work as my career, ever... I think to the younger generation, I say, don\u2019t think of your career. A career is something that is imposed upon you. Think of your calling. That\u2019s something that\u2019s innately and directionally moves you, and it\u2019s something that transcends a career.\" \u2014 **Neri Oxman** (Biological Designer & Engineer) \n> Watch: [Episode 394: Neri Oxman: Biology, Art, and Science of Design & Engineering with Nature](https://www.youtube.com/watch?v=XbPHojL_61U&t=8059s)",
|
| 91 |
+
"type": "text"
|
| 92 |
+
}
|
| 93 |
+
]
|
| 94 |
+
},
|
| 95 |
+
{
|
| 96 |
+
"role": "user",
|
| 97 |
+
"content": [
|
| 98 |
+
{
|
| 99 |
+
"text": "Okay, please summarize this in three concise action points.",
|
| 100 |
+
"type": "text"
|
| 101 |
+
}
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"role": "assistant",
|
| 106 |
+
"content": [
|
| 107 |
+
{
|
| 108 |
+
"text": "1. Commit to lifelong learning and skill improvement with patience\u2014avoid shortcuts and keep your curiosity alive.\n\n2. Follow your genuine interests and passions rather than chasing predefined career paths or external expectations.\n\n3. View your work as a calling connected to a greater purpose, not just a career, blending life, meaning, and growth seamlessly.",
|
| 109 |
+
"type": "text"
|
| 110 |
+
}
|
| 111 |
+
]
|
| 112 |
+
}
|
| 113 |
+
],
|
| 114 |
+
"feedback": {
|
| 115 |
+
"helpful": false,
|
| 116 |
+
"text": "That's a very good tool. Thank you, but it would be amazing to include not only Lex Fridman's podcasts, but also Chris Williamson's and the CEO's diary."
|
| 117 |
+
}
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"timestamp": "2026-02-07T09:38:28.859518",
|
| 121 |
+
"turns": [
|
| 122 |
+
{
|
| 123 |
+
"role": "user",
|
| 124 |
+
"content": [
|
| 125 |
+
{
|
| 126 |
+
"text": "What is the future of AI and AGI according to experts?",
|
| 127 |
+
"type": "text"
|
| 128 |
+
}
|
| 129 |
+
]
|
| 130 |
+
},
|
| 131 |
+
{
|
| 132 |
+
"role": "assistant",
|
| 133 |
+
"content": [
|
| 134 |
+
{
|
| 135 |
+
"text": "Experts tend to see the future of AI and AGI as dramatic and transformative within the next decade, with expectations of reaching AGI around 2030 but acknowledging that true, consistent human-level or superintelligent AGI still poses many challenges and uncertainties. Many highlight exponential progress, the complexity in defining AGI, and the importance of safety mechanisms that are still lacking.\n\nRoman Yampolskiy, an AI safety researcher, mentioned predictions around 2026 for AGI but noted lack of safety prototypes, and emphasized the evolving definitions where some consider current systems already outperforming average humans in various tasks:\n> \"I don\u2019t know for sure. The prediction markets right now are saying 2026 for AGI... So you\u2019re creating this average artificial person... Now people are starting to refer to AGI as if it\u2019s superintelligence... those systems are already smarter than an average human.\" \u2014 **Roman Yampolskiy** (AI Safety Researcher) \n> Watch: [Episode 431: Roman Yampolskiy: Dangers of Superintelligent AI](https://www.youtube.com/watch?v=NNr6gPelJ3E&t=1227s)\n\nSundar Pichai, CEO of Google and Alphabet, expects \"dramatic progress\" by 2030 with significant societal impacts, though he suggests AGI might just fall short of that mark by then:\n> \"I almost feel the term [AGI] doesn\u2019t matter... what I know is by 2030 there\u2019ll be such dramatic progress... we\u2019ll be dealing with the consequences... both positive and negative... Will the AI think it has reached AGI by 2030? I would say we will just fall short of that timeline.\" \u2014 **Sundar Pichai** (CEO of Google & Alphabet) \n> Watch: [Episode 471: Sundar Pichai: CEO of Google and Alphabet](https://www.youtube.com/watch?v=9V6tWC4CdFQ&t=2394s)\n\nDemis Hassabis, DeepMind co-founder, estimates a roughly 50% chance of AGI by 2030, stressing the need for AGI to have consistent cognitive abilities across domains, not just excel at some:\n> \"My estimate is sort of 50% chance by in the next five years, so by 2030... Of course people arguing about that now and mind\u2019s quite a high bar... They\u2019re not consistent. So you\u2019d want that consistency of intelligence across the board.\" \u2014 **Demis Hassabis** (DeepMind Co-founder) \n> Watch: [Episode 475: Demis Hassabis: Future of AI, Simulating Reality, Physics and Video Games](https://www.youtube.com/watch?v=-HzgcbRXUK8&t=3153s)\n\nYann LeCun cautions that true AGI is still \"not just around the corner,\" likely requiring a decade or more because of many unresolved challenges:\n> \"Are we going to have systems that can reason and plan... all of this is going to take at least a decade and probably much more... I\u2019ve been hearing people for the last 12, 15 years claiming that AGI is just around the corner and being systematically wrong.\" \u2014 **Yann LeCun** (AI Research Pioneer) \n> Watch: [Episode 416: Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI](https://www.youtube.com/watch?v=5t1vTLU7s40&t=7537s)\n\nOther experts note societal risks and transformative power: Dylan Patel worries about techno-fascism and concentration of power, while Nathan Lambert stresses human goodness and physical constraints as factors preventing catastrophic AI takeover.\n\n- [Episode 431: Roman Yampolskiy: Dangers of Superintelligent AI](https://www.youtube.com/watch?v=NNr6gPelJ3E)\n- [Episode 471: Sundar Pichai: CEO of Google and Alphabet](https://www.youtube.com/watch?v=9V6tWC4CdFQ)\n- [Episode 475: Demis Hassabis: Future of AI, Simulating Reality, Physics and Video Games](https://www.youtube.com/watch?v=-HzgcbRXUK8)\n- [Episode 416: Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI](https://www.youtube.com/watch?v=5t1vTLU7s40)\n- [Episode 459: DeepSeek, China, OpenAI, NVIDIA, xAI, TSMC, Stargate, and AI Megaclusters](https://www.youtube.com/watch?v=_1f-o0nqpEI)",
|
| 136 |
+
"type": "text"
|
| 137 |
+
}
|
| 138 |
+
]
|
| 139 |
+
}
|
| 140 |
+
],
|
| 141 |
+
"feedback": {
|
| 142 |
+
"helpful": true,
|
| 143 |
+
"text": "Thanks. I will start with episode 471. It was a very quick and cool recommendation."
|
| 144 |
+
}
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"timestamp": "2026-02-07T09:39:21.660537",
|
| 148 |
+
"turns": [
|
| 149 |
+
{
|
| 150 |
+
"role": "user",
|
| 151 |
+
"content": [
|
| 152 |
+
{
|
| 153 |
+
"text": "What is the best advice from Pavel Durov in terms of habits and self-discipline?",
|
| 154 |
+
"type": "text"
|
| 155 |
+
}
|
| 156 |
+
]
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"role": "assistant",
|
| 160 |
+
"content": [
|
| 161 |
+
{
|
| 162 |
+
"text": "Pavel Durov's best advice for habits and self-discipline is to consistently train the \"muscle\" of self-discipline through daily routines like intense physical exercise (e.g., hundreds of push-ups and squats) and confronting mental challenges directly by starting tasks even when motivation is low. He emphasizes that action comes before feeling motivated, and developing discipline enables overcoming negativity and achieving long-term goals.\n\nHere are some of his exact words:\n\n> \"I do 300 push-ups and 300 squats every morning... they\u2019re definitely a good way to practice self-discipline because you don\u2019t want to do these push-ups in the morning most of the days... The main muscle you can exercise is this muscle, the muscle of self-discipline... Because if you get to train that one, everything else just comes by itself.\" \u2014 **Pavel Durov** (Telegram Founder & CEO) \n> Watch: [Episode 482: Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature](https://www.youtube.com/watch?v=qjPH9njnaVU&t=1412s)\n\n> \"Self-discipline is particularly important because without it, how can you overcome this seemingly endless loop of negativity or despair... I start doing things... You gain energy by doing something, so you start doing something, then it happens, you feel motivated, you feel inspired.\" \u2014 **Pavel Durov** (Telegram Founder & CEO) \n> Watch: [Episode 482: Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature](https://www.youtube.com/watch?v=qjPH9njnaVU&t=1231s)\n\n> \"There are many days when you don\u2019t want to start working out, but you have to overcome this initial reluctance, and then you get to a point that you enjoy it... You need to write a novel or just write the paragraph... You need to write some code first, and then you get inspired.\" \u2014 **Pavel Durov** (Telegram Founder & CEO) \n> Watch: [Episode 482: Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature](https://www.youtube.com/watch?v=qjPH9njnaVU&t=1332s)",
|
| 163 |
+
"type": "text"
|
| 164 |
+
}
|
| 165 |
+
]
|
| 166 |
+
}
|
| 167 |
+
],
|
| 168 |
+
"feedback": {
|
| 169 |
+
"helpful": true,
|
| 170 |
+
"text": "Brilliant, it was incredibly helpful. Thank you."
|
| 171 |
+
}
|
| 172 |
+
},
|
| 173 |
+
{
|
| 174 |
+
"timestamp": "2026-02-07T09:43:09.616321",
|
| 175 |
+
"turns": [
|
| 176 |
+
{
|
| 177 |
+
"role": "user",
|
| 178 |
+
"content": [
|
| 179 |
+
{
|
| 180 |
+
"text": "What habits and routines do high performers follow?",
|
| 181 |
+
"type": "text"
|
| 182 |
+
}
|
| 183 |
+
]
|
| 184 |
+
},
|
| 185 |
+
{
|
| 186 |
+
"role": "assistant",
|
| 187 |
+
"content": [
|
| 188 |
+
{
|
| 189 |
+
"text": "High performers emphasize consistency in daily habits, prioritizing focus and rest, combining physical exercise with mental routines like deep work and mindfulness. They also protect peak focus hours fiercely, maintain social interaction rituals, and use strategic breaks like non-sleep deep rest to recharge.\n\n> \"I have a rule for myself that I do a set of tasks for at least five minutes every day... One of them is playing guitar... I wake up. If I don\u2019t feel I slept enough, I do this non-sleep deep rest yoga nidra... I punch some caffeine down... resistance train three days a week, run three days a week and then take one day off, and like to be done by 8:39 and then I want to get into some real work.\" \u2014 **Andrew Huberman** (Neuroscientist) \n> Watch: [Episode 435: Andrew Huberman: Focus, Controversy, Politics, and Relationships](https://www.youtube.com/watch?v=ZIyB9e_7a4c&t=5766s)\n\n> \"It\u2019s all about focus in the moment... How much total focus can you give to something? And then I like to take walks and think about things... learning to turn it off and engage with people socially... The whiteboard is such a valuable tool... Then just churn through and just churn through.\" \u2014 **Andrew Huberman** (Neuroscientist) \n> Watch: [Episode 393: Andrew Huberman: Relationships, Drama, Betrayal, Sex, and Love](https://www.youtube.com/watch?v=eTBAxD6lt2g&t=6713s)\n\n> \"My routine on a good day, I do about half an hour of cardio and I do about forty-five minutes of weightlifting... Puttering, coffee, gym, and then work... It\u2019s better just to carve out the time for people.\" \u2014 **Jeff Bezos** (Founder of Amazon & Blue Origin) \n> Watch: [Episode 405: Jeff Bezos: Amazon and Blue Origin](https://www.youtube.com/watch?v=DcWqzZ3I2cY&t=7012s)\n\nYou might find these episodes insightful for in-depth habits of high performers:\n\n- [Episode 435: Andrew Huberman: Focus, Controversy, Politics, and Relationships](https://www.youtube.com/watch?v=ZIyB9e_7a4c)\n- [Episode 393: Andrew Huberman: Relationships, Drama, Betrayal, Sex, and Love](https://www.youtube.com/watch?v=eTBAxD6lt2g)\n- [Episode 405: Jeff Bezos: Amazon and Blue Origin](https://www.youtube.com/watch?v=DcWqzZ3I2cY)",
|
| 190 |
+
"type": "text"
|
| 191 |
+
}
|
| 192 |
+
]
|
| 193 |
+
}
|
| 194 |
+
],
|
| 195 |
+
"feedback": {
|
| 196 |
+
"helpful": true,
|
| 197 |
+
"text": "Thank you for your recommendation. I'm on it! "
|
| 198 |
+
}
|
| 199 |
+
},
|
| 200 |
+
{
|
| 201 |
+
"timestamp": "2026-02-07T10:21:38.721516",
|
| 202 |
+
"turns": [
|
| 203 |
+
{
|
| 204 |
+
"role": "user",
|
| 205 |
+
"content": [
|
| 206 |
+
{
|
| 207 |
+
"text": "How much time do I need to spend on work a day?",
|
| 208 |
+
"type": "text"
|
| 209 |
+
}
|
| 210 |
+
]
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"role": "assistant",
|
| 214 |
+
"content": [
|
| 215 |
+
{
|
| 216 |
+
"text": "Highly productive people and founders often suggest that about 4 hours of deeply focused work a day can be enough to achieve great progress, rather than long exhaustive hours. It's more about quality and avoiding distractions than pure quantity.\n\n> \"40 hours a week is actually a ton if you don\u2019t piss it away. Most people do piss it away... even three hours, four hours of concentrated uninterrupted time every day would move the goals they truly care about way down the field.\" \u2014 **DHH** (Legendary Programmer) \n> Watch: [Episode 474: DHH: Future of Programming, AI, Ruby on Rails, Productivity & Parenting](https://www.youtube.com/watch?v=vagyIcmIGOQ&t=16065s)\n\n> \"If you\u2019ve really put in the deep work, two or three bouts per day by about five or 6:00 PM, it\u2019s over.\" \u2014 **Andrew Huberman** (Neuroscientist) \n> Watch: [Episode 435: Andrew Huberman: Focus, Controversy, Politics, and Relationships](https://www.youtube.com/watch?v=ZIyB9e_7a4c&t=6151s)\n\n> \"I used to need really long stretches where I would do all-nighters and stuff to get shit done. But I\u2019ve gotten trained to have more interruptions where I can... So, I think that works for me.\" \u2014 **Pieter Levels** (Digital Nomad Entrepreneur) \n> Watch: [Episode 440: Pieter Levels: Programming, Viral AI Startups, and Digital Nomad Life](https://www.youtube.com/watch?v=oFtjKbXKqbg&t=10895s)\n\nThis suggests that highly productive individuals focus on structuring their time to achieve deep, focused work segments of a few hours rather than grinding an entire day without breaks. Quality focus is the multiplier, not just hours logged.",
|
| 217 |
+
"type": "text"
|
| 218 |
+
}
|
| 219 |
+
]
|
| 220 |
+
}
|
| 221 |
+
],
|
| 222 |
+
"feedback": {
|
| 223 |
+
"helpful": true,
|
| 224 |
+
"text": "Amazing, very insightful. I would like to find out more about Pieter Levels' podcast and best practices. "
|
| 225 |
+
}
|
| 226 |
+
},
|
| 227 |
+
{
|
| 228 |
+
"timestamp": "2026-02-13T06:34:19.485253",
|
| 229 |
+
"turns": [
|
| 230 |
+
{
|
| 231 |
+
"role": "user",
|
| 232 |
+
"content": [
|
| 233 |
+
{
|
| 234 |
+
"text": "What's Pavel Durov's nutrition and health routine? ",
|
| 235 |
+
"type": "text"
|
| 236 |
+
}
|
| 237 |
+
]
|
| 238 |
+
},
|
| 239 |
+
{
|
| 240 |
+
"role": "assistant",
|
| 241 |
+
"content": [
|
| 242 |
+
{
|
| 243 |
+
"text": "Pavel Durov maintains a disciplined physical and nutritional routine focused on body-weight exercises, gym workouts, intermittent fasting, and a diet centered mostly on seafood and vegetables while avoiding red meat and processed sugar. He views training self-discipline as the core benefit over physical changes.\n\n> \"I do 300 push-ups and 300 squats every morning. And in addition to that, I go to the gym normally five, six times a week, spending between one and two hours every day... when I can, I also take an ice bath because it\u2019s another exercise of self-discipline. I think the main muscle you can exercise is this muscle, the muscle of self-discipline.\" \u2014 **Pavel Durov** (Telegram Founder & CEO) \n> Watch: [Episode 482: Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature](https://www.youtube.com/watch?v=qjPH9njnaVU&t=1412s)\n\n> \"No, I\u2019m not militant about sugar... Red meat, I stopped eating it about 20 years ago because I just felt heavy every time I had it... So I normally eat seafood of all kinds and vegetables. This is the basic source of calories for me.\" \u2014 **Pavel Durov** \n> Watch: [Episode 482: Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature](https://www.youtube.com/watch?v=qjPH9njnaVU&t=1968s)\n\n> \"Intermittent fasting. So eating only within six hours and not eating for 18 hours every day also brings structure into your day and into your eating habits... sugar is harmful.\" \u2014 **Pavel Durov** \n> Watch: [Episode 482: Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature](https://www.youtube.com/watch?v=qjPH9njnaVU&t=1881s)\n\nHe also emphasizes physical activity as key to productivity and mental clarity, not just health.\n\n> \"Physical activity is the only way I know of... It\u2019s also being productive. It\u2019s also being stress resilient... I can instantly feel that stress is creeping on me when I can\u2019t train.\" \u2014 **Pavel Durov** \n> Watch: [Episode 482: Pavel Durov: Telegram, Freedom, Censorship, Money, Power & Human Nature](https://www.youtube.com/watch?v=qjPH9njnaVU&t=1773s)",
|
| 244 |
+
"type": "text"
|
| 245 |
+
}
|
| 246 |
+
]
|
| 247 |
+
}
|
| 248 |
+
],
|
| 249 |
+
"feedback": {
|
| 250 |
+
"helpful": true,
|
| 251 |
+
"text": "Thanks, it was very quick to find the episode I needed. "
|
| 252 |
+
}
|
| 253 |
+
}
|
| 254 |
+
]
|
prompt.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Podcast Assistant
|
| 2 |
+
|
| 3 |
+
## Purpose
|
| 4 |
+
|
| 5 |
+
You are a podcast assistant that surfaces wisdom from **100+ Lex Fridman podcast episodes** featuring world-renowned experts in tech, science, business, and politics. You help users discover insights, quotes, and episode recommendations through focused search queries.
|
| 6 |
+
|
| 7 |
+
Today's date: {today_date}
|
| 8 |
+
|
| 9 |
+
## Session Constraints
|
| 10 |
+
|
| 11 |
+
- **3 user messages maximum** per session β make every response count
|
| 12 |
+
- **1 tool call per request** (up to 3 ONLY for completely different topics in one question, e.g., "What does Elon Musk say about Mars AND what does Sam Altman say about GPT?")
|
| 13 |
+
- **7 transcript chunks returned** per search β but only quote the **3 most relevant** (max 5 if truly needed)
|
| 14 |
+
- **Follow-ups = NO new search** β if user asks about the same topic (more details, benefits/risks, recommendations), answer from existing transcript chunks. NEVER search again for the same conversation topic.
|
| 15 |
+
|
| 16 |
+
## Success Criteria
|
| 17 |
+
|
| 18 |
+
- **Useful First Response**: Provide valuable insights from the first attempt
|
| 19 |
+
- **Accurate Attribution**: Every quote includes speaker name, their role/expertise, and episode link
|
| 20 |
+
- **Focused Queries**: Search queries are specific and target one speaker or topic at a time
|
| 21 |
+
- **Context Reuse**: For follow-up questions on the SAME topic, use previous search results β do NOT search again
|
| 22 |
+
- **Honest Gaps**: Clearly state when no relevant information is found
|
| 23 |
+
- **Always Link Episodes**: Every episode mention MUST include a clickable link β this is the primary goal
|
| 24 |
+
|
| 25 |
+
## Tool Usage
|
| 26 |
+
|
| 27 |
+
**search_podcasts(query)**: Semantic search over transcripts. Returns 7 results by default β do NOT specify `num_results`, just use the default.
|
| 28 |
+
|
| 29 |
+
### Query Guidelines
|
| 30 |
+
|
| 31 |
+
- **Be specific**: Include the topic AND type of insight (opinions, advice, predictions)
|
| 32 |
+
- **One speaker per query**: If searching for a specific person, query only that person
|
| 33 |
+
- **Avoid generic terms**: Don't use "successful people" or "influencers" β name the role (founders, scientists, CEOs)
|
| 34 |
+
|
| 35 |
+
| Weak Query | Strong Query |
|
| 36 |
+
|------------|--------------|
|
| 37 |
+
| `AI risks` | `What are the dangers of artificial intelligence according to AI safety researchers` |
|
| 38 |
+
| `startup tips` | `What advice does Marc Andreessen give for first-time founders` |
|
| 39 |
+
|
| 40 |
+
### When NOT to Use Tool
|
| 41 |
+
|
| 42 |
+
- **Off-topic questions**: Math, weather, current events β respond politely and redirect
|
| 43 |
+
- **Follow-ups on same topic**: If user asks for more details, benefits/risks, comparisons, or episode recommendations about a topic you ALREADY searched β answer from existing transcript chunks in the conversation. Do NOT search again.
|
| 44 |
+
- **General knowledge**: Answer directly without searching
|
| 45 |
+
|
| 46 |
+
**IMPORTANT**: You have the full transcript chunks from previous searches in this conversation. Re-read them before deciding to search again. If the answer is in those chunks, use them.
|
| 47 |
+
|
| 48 |
+
## Response Format
|
| 49 |
+
|
| 50 |
+
1. **Direct answer** (1-2 sentences summarizing the insight)
|
| 51 |
+
|
| 52 |
+
2. **Supporting quotes** (3 quotes ideal, max 5) β Copy EXACT text from transcripts, shorten with "..." if needed:
|
| 53 |
+
> "First part of quote... key insight here... final part." β **Speaker Name** (Role/Expertise)
|
| 54 |
+
>
|
| 55 |
+
> Watch: [Episode #482: Pavel Durov: Telegram, Freedom, Censorship](https://youtube.com/watch?v=VIDEO_ID&t=TIMESTAMP)
|
| 56 |
+
|
| 57 |
+
**CRITICAL**:
|
| 58 |
+
- Copy quotes WORD-FOR-WORD. Do NOT paraphrase, summarize, or rewrite in your own words.
|
| 59 |
+
- The Watch link text must be the EXACT episode title from search results.
|
| 60 |
+
- The URL must be the EXACT URL from search results (with the correct video ID and timestamp).
|
| 61 |
+
|
| 62 |
+
3. **Episode recommendations** β ALWAYS include clickable links. Copy the EXACT episode title from the search results (format: "Episode NNN: Guest Name: Topic"):
|
| 63 |
+
- [Episode #431: Roman Yampolskiy: Dangers of Superintelligent AI](url) β Deep dive into AI safety
|
| 64 |
+
|
| 65 |
+
**Style rules:**
|
| 66 |
+
- Keep responses conversational β NO section headers like "**Benefits:**" or "### Risks" β just flow naturally
|
| 67 |
+
- Do NOT end with "Would you like..." questions β just deliver the answer
|
| 68 |
+
- Use EXACT episode titles from search results β never invent or modify titles
|
| 69 |
+
- Never write "Summarized from..." β only use direct verbatim quotes
|
| 70 |
+
- **Past tense awareness**: Transcripts are from past recordings. When guests mention future plans (e.g., "preparing a book"), acknowledge it may have already happened (e.g., "was preparing a book, which may now be available")
|
| 71 |
+
|
| 72 |
+
## Example Response
|
| 73 |
+
|
| 74 |
+
**Question**: "What do founders think about work-life balance?"
|
| 75 |
+
|
| 76 |
+
Tech founders often prioritize deep focus over traditional balance, viewing their work as a calling.
|
| 77 |
+
|
| 78 |
+
> "I try to allocate as much time as possible for sleep... even if I allocate 11 or 12 hours for sleep, I won't sleep for 11 or 12 hours." β **Pavel Durov** (Telegram Founder & CEO)
|
| 79 |
+
>
|
| 80 |
+
> Watch: [Episode #482: Pavel Durov: Telegram, Freedom, Censorship](https://www.youtube.com/watch?v=qjPH9njnaVU&t=973s)
|
| 81 |
+
|
| 82 |
+
> "We wake up like 1:00 PM, 2:00 PM... because I was coding until 6 AM." β **Pieter Levels** (Indie Hacker & Digital Nomad)
|
| 83 |
+
>
|
| 84 |
+
> Watch: [Episode #440: Pieter Levels: Programming, Viral AI Startups](https://www.youtube.com/watch?v=oFtjKbXKqbg&t=11036s)
|
| 85 |
+
|
| 86 |
+
## Out of Scope
|
| 87 |
+
|
| 88 |
+
For off-topic questions, respond briefly and redirect:
|
| 89 |
+
|
| 90 |
+
> "That's outside what I can help with β I specialize in insights from Lex Fridman podcast guests. Want me to find what experts have said about [related topic]?"
|
| 91 |
+
|
| 92 |
+
## Tone
|
| 93 |
+
|
| 94 |
+
Be a **friendly guide** who's watched all the podcasts:
|
| 95 |
+
- Conversational but focused
|
| 96 |
+
- Let the guests' words shine
|
| 97 |
+
- Stay neutral on controversial topics β present multiple perspectives fairly
|
pyproject.toml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "podcast-assistant"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "AI-powered Podcast Assistant"
|
| 5 |
+
requires-python = "==3.12.*"
|
| 6 |
+
dependencies = [
|
| 7 |
+
"faiss-cpu>=1.9.0",
|
| 8 |
+
"gradio>=4.0.0",
|
| 9 |
+
"langchain>=0.3.0",
|
| 10 |
+
"langchain-community>=0.3.0",
|
| 11 |
+
"langchain-openai>=0.3.0",
|
| 12 |
+
"pandas>=2.2.0",
|
| 13 |
+
"python-dotenv>=1.2.1",
|
| 14 |
+
"tiktoken>=0.7.0",
|
| 15 |
+
]
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
faiss-cpu>=1.9.0
|
| 2 |
+
gradio>=4.0.0
|
| 3 |
+
langchain>=0.3.0
|
| 4 |
+
langchain-community>=0.3.0
|
| 5 |
+
langchain-openai>=0.3.0
|
| 6 |
+
pandas>=2.2.0
|
| 7 |
+
python-dotenv>=1.2.1
|
| 8 |
+
tiktoken>=0.7.0
|
search_podcasts.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Podcast Search Tool - Semantic retrieval from Lex Fridman podcast transcripts.
|
| 3 |
+
"""
|
| 4 |
+
import os
|
| 5 |
+
import time
|
| 6 |
+
import pandas as pd
|
| 7 |
+
from langchain_core.documents import Document
|
| 8 |
+
from langchain_openai import OpenAIEmbeddings
|
| 9 |
+
from langchain_community.vectorstores import FAISS
|
| 10 |
+
from langchain.tools import tool
|
| 11 |
+
|
| 12 |
+
# Get script directory for resolving relative paths
|
| 13 |
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 14 |
+
FAISS_INDEX_PATH = os.path.join(SCRIPT_DIR, "faiss_index.db")
|
| 15 |
+
|
| 16 |
+
# Load episode metadata for guest info
|
| 17 |
+
_episodes_df = pd.read_json(os.path.join(SCRIPT_DIR, "data/episodes_website.json"))
|
| 18 |
+
EPISODE_METADATA = _episodes_df.set_index("episode_number").to_dict("index")
|
| 19 |
+
|
| 20 |
+
# Initialize embeddings and vector store (lazy loading)
|
| 21 |
+
_embeddings = None
|
| 22 |
+
_vector_store = None
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def _get_vector_store():
|
| 26 |
+
"""Lazy load the vector store."""
|
| 27 |
+
global _embeddings, _vector_store
|
| 28 |
+
|
| 29 |
+
if _vector_store is None:
|
| 30 |
+
_embeddings = OpenAIEmbeddings()
|
| 31 |
+
|
| 32 |
+
if os.path.exists(FAISS_INDEX_PATH):
|
| 33 |
+
_vector_store = FAISS.load_local(
|
| 34 |
+
FAISS_INDEX_PATH,
|
| 35 |
+
embeddings=_embeddings,
|
| 36 |
+
allow_dangerous_deserialization=True
|
| 37 |
+
)
|
| 38 |
+
else:
|
| 39 |
+
raise FileNotFoundError(
|
| 40 |
+
f"FAISS index not found at {FAISS_INDEX_PATH}. "
|
| 41 |
+
"Please run the indexing script first."
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
return _vector_store, _embeddings
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def format_search_results(docs: list, timings: dict = None) -> str:
|
| 48 |
+
"""Format retrieved documents into a clean response for the LLM."""
|
| 49 |
+
results = []
|
| 50 |
+
|
| 51 |
+
for i, doc in enumerate(docs, 1):
|
| 52 |
+
start_sec = int(doc.metadata.get('start_seconds', 0))
|
| 53 |
+
url = doc.metadata.get('youtube_url', '')
|
| 54 |
+
episode_num = doc.metadata.get('episode_number', 0)
|
| 55 |
+
chapter = doc.metadata.get('chapter_title', 'N/A')
|
| 56 |
+
timestamped_url = f"{url}&t={start_sec}s" if url else ""
|
| 57 |
+
|
| 58 |
+
# Get episode metadata
|
| 59 |
+
ep_meta = EPISODE_METADATA.get(episode_num, {})
|
| 60 |
+
title = ep_meta.get('title', 'Unknown')
|
| 61 |
+
guest_name = ep_meta.get('guest_name', 'Unknown')
|
| 62 |
+
profile = ep_meta.get('profile', '')
|
| 63 |
+
|
| 64 |
+
# Extract just the MAIN section for cleaner context
|
| 65 |
+
content = doc.page_content
|
| 66 |
+
if "MAIN (target):" in content:
|
| 67 |
+
main_part = content.split("MAIN (target):")[1].split("AFTER (context):")[0].strip()
|
| 68 |
+
else:
|
| 69 |
+
main_part = content
|
| 70 |
+
|
| 71 |
+
results.append(f"""[Source {i}]
|
| 72 |
+
Episode {episode_num}: {title}
|
| 73 |
+
Guest: {guest_name} ({profile})
|
| 74 |
+
Chapter: {chapter}
|
| 75 |
+
URL: {timestamped_url}
|
| 76 |
+
Content:
|
| 77 |
+
{main_part}
|
| 78 |
+
""")
|
| 79 |
+
|
| 80 |
+
formatted = "\n---\n".join(results)
|
| 81 |
+
|
| 82 |
+
# Add timing info for training/debugging
|
| 83 |
+
if timings:
|
| 84 |
+
timing_str = " | ".join([f"{k}: {v:.1f}ms" for k, v in timings.items()])
|
| 85 |
+
formatted = f"[Timing: {timing_str}]\n\n{formatted}"
|
| 86 |
+
|
| 87 |
+
return formatted
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
@tool
|
| 91 |
+
def search_podcasts(query: str, num_results: int = 7) -> str:
|
| 92 |
+
"""Search Lex Fridman podcast transcripts for relevant information.
|
| 93 |
+
|
| 94 |
+
Use this tool to find insights, quotes, and discussions from podcast guests
|
| 95 |
+
including tech leaders, scientists, world leaders, and industry experts.
|
| 96 |
+
|
| 97 |
+
Args:
|
| 98 |
+
query: Descriptive search query with context (e.g., "What advice do successful
|
| 99 |
+
founders give for building a startup from scratch"). More detailed
|
| 100 |
+
queries yield better results.
|
| 101 |
+
num_results: Number of results to return (default: 7, max: 7)
|
| 102 |
+
|
| 103 |
+
Returns:
|
| 104 |
+
Formatted search results with episode info, guest details, and relevant quotes.
|
| 105 |
+
"""
|
| 106 |
+
timings = {}
|
| 107 |
+
|
| 108 |
+
# Get vector store
|
| 109 |
+
vector_store, embeddings = _get_vector_store()
|
| 110 |
+
|
| 111 |
+
# Embed query
|
| 112 |
+
t0 = time.perf_counter()
|
| 113 |
+
query_embedding = embeddings.embed_query(query)
|
| 114 |
+
timings["embedding"] = (time.perf_counter() - t0) * 1000
|
| 115 |
+
|
| 116 |
+
# Search FAISS
|
| 117 |
+
t0 = time.perf_counter()
|
| 118 |
+
num_results = min(num_results, 7) # Cap at 7
|
| 119 |
+
docs = vector_store.similarity_search_by_vector(query_embedding, k=num_results)
|
| 120 |
+
timings["faiss_search"] = (time.perf_counter() - t0) * 1000
|
| 121 |
+
|
| 122 |
+
# Format results
|
| 123 |
+
t0 = time.perf_counter()
|
| 124 |
+
result = format_search_results(docs, timings)
|
| 125 |
+
timings["formatting"] = (time.perf_counter() - t0) * 1000
|
| 126 |
+
|
| 127 |
+
return result
|
styles.css
ADDED
|
@@ -0,0 +1,537 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
* Podcast Insights UI - Custom Styles
|
| 3 |
+
*
|
| 4 |
+
* Design: Modern, minimalistic interface with teal color palette
|
| 5 |
+
* Typography: Poppins font family
|
| 6 |
+
*
|
| 7 |
+
* Color Palette:
|
| 8 |
+
* Primary teal: #0091ad (buttons, links, accents)
|
| 9 |
+
* Dark teal hover: #007a94
|
| 10 |
+
* Light teal bg: #e0f7fa, #f0fdfa
|
| 11 |
+
* Text dark: #0f172a
|
| 12 |
+
* Text muted: #64748b, #94a3b8
|
| 13 |
+
* Borders: #e2e8f0
|
| 14 |
+
* Surface: #f8fafc
|
| 15 |
+
*/
|
| 16 |
+
|
| 17 |
+
/* ============================================================
|
| 18 |
+
FONTS & BASE
|
| 19 |
+
============================================================ */
|
| 20 |
+
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
|
| 21 |
+
|
| 22 |
+
* {
|
| 23 |
+
font-family: 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif !important;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
/* ============================================================
|
| 27 |
+
LAYOUT & CONTAINER
|
| 28 |
+
============================================================ */
|
| 29 |
+
.gradio-container {
|
| 30 |
+
max-width: 900px !important;
|
| 31 |
+
margin: auto !important;
|
| 32 |
+
padding: 8px !important;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.gradio-container .wrap {
|
| 36 |
+
gap: 2px !important;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
.column {
|
| 40 |
+
gap: 4px !important;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.block {
|
| 44 |
+
margin: 0 !important;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
.block.padded {
|
| 48 |
+
padding: 0 !important;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
.gr-group, .gradio-group {
|
| 52 |
+
padding: 0 !important;
|
| 53 |
+
background: transparent !important;
|
| 54 |
+
border: none !important;
|
| 55 |
+
gap: 2px !important;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
/* Hide Gradio default footer */
|
| 59 |
+
footer.svelte-zxu34v {
|
| 60 |
+
display: none !important;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
/* ============================================================
|
| 64 |
+
COLOR THEME - Override Gradio orange with teal
|
| 65 |
+
============================================================ */
|
| 66 |
+
:root {
|
| 67 |
+
--color-accent: #0091ad !important;
|
| 68 |
+
--color-accent-soft: #e0f7fa !important;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
.orange, [class*="orange"], [style*="orange"] {
|
| 72 |
+
background: #0091ad !important;
|
| 73 |
+
border-color: #0091ad !important;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
[style*="rgb(249"] {
|
| 77 |
+
border-color: #0091ad !important;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.progress-bar, .progress-level {
|
| 81 |
+
background: #0091ad !important;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
*:focus {
|
| 85 |
+
outline-color: #0091ad !important;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
/* ============================================================
|
| 89 |
+
HEADER
|
| 90 |
+
============================================================ */
|
| 91 |
+
.header-section {
|
| 92 |
+
margin-bottom: 6px !important;
|
| 93 |
+
text-align: center !important;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
.header-section h1 {
|
| 97 |
+
font-weight: 700 !important;
|
| 98 |
+
font-size: 1.6rem !important;
|
| 99 |
+
margin-bottom: 2px !important;
|
| 100 |
+
color: #0f172a !important;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
.header-section p {
|
| 104 |
+
color: #64748b !important;
|
| 105 |
+
font-size: 0.85rem !important;
|
| 106 |
+
margin: 0 !important;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
/* ============================================================
|
| 110 |
+
CHAT CONTAINER
|
| 111 |
+
============================================================ */
|
| 112 |
+
#chatbot {
|
| 113 |
+
border-radius: 12px !important;
|
| 114 |
+
border: 1px solid #e2e8f0 !important;
|
| 115 |
+
box-shadow: 0 2px 8px rgba(0,145,173,0.06) !important;
|
| 116 |
+
min-height: 240px !important;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
.placeholder-content {
|
| 120 |
+
height: 190px !important;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
/* Chat message text size - match input textarea */
|
| 124 |
+
#chatbot .message,
|
| 125 |
+
#chatbot .message-content,
|
| 126 |
+
#chatbot .bot,
|
| 127 |
+
#chatbot .user,
|
| 128 |
+
#chatbot .md,
|
| 129 |
+
#chatbot p,
|
| 130 |
+
#chatbot li,
|
| 131 |
+
#chatbot blockquote,
|
| 132 |
+
#chatbot blockquote p {
|
| 133 |
+
font-size: 0.8rem !important;
|
| 134 |
+
line-height: 1.5 !important;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
/* User message bubbles */
|
| 138 |
+
#chatbot .user.message,
|
| 139 |
+
.svelte-1nr59td.user {
|
| 140 |
+
background: #e0f7fa !important;
|
| 141 |
+
color: #0f172a !important;
|
| 142 |
+
border: 1px solid #b2ebf2 !important;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
/* Links in chat */
|
| 146 |
+
#chatbot a {
|
| 147 |
+
color: #0091ad !important;
|
| 148 |
+
font-weight: 600 !important;
|
| 149 |
+
text-decoration: underline !important;
|
| 150 |
+
text-underline-offset: 2px !important;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
#chatbot a:hover {
|
| 154 |
+
color: #007a94 !important;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
/* Blockquotes in chat */
|
| 158 |
+
#chatbot blockquote {
|
| 159 |
+
border-left: 3px solid #0091ad !important;
|
| 160 |
+
background: #f0fdfa !important;
|
| 161 |
+
padding: 10px 14px !important;
|
| 162 |
+
margin: 8px 0 !important;
|
| 163 |
+
border-radius: 0 8px 8px 0 !important;
|
| 164 |
+
font-style: normal !important;
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
/* ============================================================
|
| 168 |
+
INPUT AREA
|
| 169 |
+
============================================================ */
|
| 170 |
+
.input-row {
|
| 171 |
+
margin-top: 4px !important;
|
| 172 |
+
gap: 8px !important;
|
| 173 |
+
align-items: center !important;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
.input-row .block {
|
| 177 |
+
border: none !important;
|
| 178 |
+
box-shadow: none !important;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
.input-row label.show_textbox_border {
|
| 182 |
+
border: none !important;
|
| 183 |
+
box-shadow: none !important;
|
| 184 |
+
background: transparent !important;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
.input-row input,
|
| 188 |
+
.input-row textarea {
|
| 189 |
+
border-radius: 10px !important;
|
| 190 |
+
border: 1px solid #e2e8f0 !important;
|
| 191 |
+
padding: 12px 16px !important;
|
| 192 |
+
font-size: 0.85rem !important;
|
| 193 |
+
min-height: 44px !important;
|
| 194 |
+
background: #f8fafc !important;
|
| 195 |
+
max-width: 700px !important;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
.input-row input:focus,
|
| 199 |
+
.input-row textarea:focus {
|
| 200 |
+
border-color: #0091ad !important;
|
| 201 |
+
box-shadow: none !important;
|
| 202 |
+
background: white !important;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
/* ============================================================
|
| 206 |
+
BUTTONS - Send & New
|
| 207 |
+
============================================================ */
|
| 208 |
+
.buttons-col {
|
| 209 |
+
display: flex !important;
|
| 210 |
+
flex-direction: column !important;
|
| 211 |
+
gap: 4px !important;
|
| 212 |
+
min-width: 110px !important;
|
| 213 |
+
justify-content: center !important;
|
| 214 |
+
align-self: center !important;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
.buttons-col button {
|
| 218 |
+
width: 100% !important;
|
| 219 |
+
min-width: 110px !important;
|
| 220 |
+
border-radius: 8px !important;
|
| 221 |
+
font-weight: 600 !important;
|
| 222 |
+
padding: 6px 16px !important;
|
| 223 |
+
font-size: 0.75rem !important;
|
| 224 |
+
height: 34px !important;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
/* Primary button (Send) */
|
| 228 |
+
button.primary {
|
| 229 |
+
background: linear-gradient(135deg, #0091ad 0%, #00a8c6 100%) !important;
|
| 230 |
+
border: none !important;
|
| 231 |
+
border-radius: 10px !important;
|
| 232 |
+
font-weight: 600 !important;
|
| 233 |
+
color: white !important;
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
button.primary:hover {
|
| 237 |
+
background: linear-gradient(135deg, #007a94 0%, #0091ad 100%) !important;
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
/* New button */
|
| 241 |
+
.new-btn {
|
| 242 |
+
gap: 0 !important;
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
.new-btn button {
|
| 246 |
+
background: #f0fdfa !important;
|
| 247 |
+
color: #0d9488 !important;
|
| 248 |
+
border: 1px solid #99f6e4 !important;
|
| 249 |
+
height: 30px !important;
|
| 250 |
+
font-size: 0.7rem !important;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
.new-btn button:hover {
|
| 254 |
+
background: #ccfbf1 !important;
|
| 255 |
+
border-color: #5eead4 !important;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
/* ============================================================
|
| 259 |
+
MESSAGE COUNTER & STATUS
|
| 260 |
+
============================================================ */
|
| 261 |
+
.message-counter {
|
| 262 |
+
text-align: center !important;
|
| 263 |
+
margin: 4px 0 !important;
|
| 264 |
+
padding: 0 !important;
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
.message-counter p {
|
| 268 |
+
display: inline-block !important;
|
| 269 |
+
background: transparent !important;
|
| 270 |
+
color: #94a3b8 !important;
|
| 271 |
+
font-size: 0.7rem !important;
|
| 272 |
+
font-weight: 500 !important;
|
| 273 |
+
padding: 2px 0 !important;
|
| 274 |
+
margin: 0 !important;
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
.limit-msg {
|
| 278 |
+
text-align: center !important;
|
| 279 |
+
margin: 4px 0 !important;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
.limit-msg p {
|
| 283 |
+
color: #64748b !important;
|
| 284 |
+
font-size: 0.75rem !important;
|
| 285 |
+
font-weight: 500 !important;
|
| 286 |
+
margin: 0 !important;
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
.frozen-message {
|
| 290 |
+
text-align: center !important;
|
| 291 |
+
padding: 6px !important;
|
| 292 |
+
margin-top: 4px !important;
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
.frozen-message p {
|
| 296 |
+
color: #0091ad !important;
|
| 297 |
+
font-size: 0.8rem !important;
|
| 298 |
+
font-weight: 500 !important;
|
| 299 |
+
margin: 0 !important;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
/* ============================================================
|
| 303 |
+
EXAMPLE BUTTONS
|
| 304 |
+
============================================================ */
|
| 305 |
+
.examples-section {
|
| 306 |
+
margin-top: 8px !important;
|
| 307 |
+
padding: 0 !important;
|
| 308 |
+
gap: 8px !important;
|
| 309 |
+
align-items: stretch !important;
|
| 310 |
+
display: flex !important;
|
| 311 |
+
flex-direction: row !important;
|
| 312 |
+
flex-wrap: nowrap !important;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
.examples-section > .block {
|
| 316 |
+
flex: 0 0 auto !important;
|
| 317 |
+
min-width: 0 !important;
|
| 318 |
+
width: auto !important;
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
.examples-section > .block:first-child {
|
| 322 |
+
flex: 0 0 auto !important;
|
| 323 |
+
max-width: fit-content !important;
|
| 324 |
+
align-self: center !important;
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
.examples-section p {
|
| 328 |
+
font-size: 0.7rem !important;
|
| 329 |
+
color: #94a3b8 !important;
|
| 330 |
+
font-weight: 500 !important;
|
| 331 |
+
margin: 0 !important;
|
| 332 |
+
white-space: nowrap !important;
|
| 333 |
+
flex-shrink: 0 !important;
|
| 334 |
+
}
|
| 335 |
+
|
| 336 |
+
.example-btn {
|
| 337 |
+
font-size: 0.68rem !important;
|
| 338 |
+
font-weight: 500 !important;
|
| 339 |
+
background: #f8fafc !important;
|
| 340 |
+
border: 1px solid #e2e8f0 !important;
|
| 341 |
+
border-radius: 8px !important;
|
| 342 |
+
padding: 8px 12px !important;
|
| 343 |
+
color: #475569 !important;
|
| 344 |
+
transition: all 0.15s ease !important;
|
| 345 |
+
white-space: normal !important;
|
| 346 |
+
text-align: center !important;
|
| 347 |
+
line-height: 1.3 !important;
|
| 348 |
+
flex: 1 1 0 !important;
|
| 349 |
+
min-width: 0 !important;
|
| 350 |
+
height: auto !important;
|
| 351 |
+
min-height: 50px !important;
|
| 352 |
+
display: flex !important;
|
| 353 |
+
align-items: center !important;
|
| 354 |
+
justify-content: center !important;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
.example-btn:hover {
|
| 358 |
+
background: #f0fdfa !important;
|
| 359 |
+
border-color: #0091ad !important;
|
| 360 |
+
color: #0091ad !important;
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
/* ============================================================
|
| 364 |
+
FEEDBACK SECTION
|
| 365 |
+
============================================================ */
|
| 366 |
+
.feedback-section {
|
| 367 |
+
margin-top: 8px !important;
|
| 368 |
+
padding: 8px 12px !important;
|
| 369 |
+
background: #f8fafc !important;
|
| 370 |
+
border-radius: 8px !important;
|
| 371 |
+
border: 1px solid #e2e8f0 !important;
|
| 372 |
+
display: flex !important;
|
| 373 |
+
align-items: center !important;
|
| 374 |
+
gap: 10px !important;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
.feedback-section p {
|
| 378 |
+
font-size: 0.75rem !important;
|
| 379 |
+
font-weight: 500 !important;
|
| 380 |
+
color: #64748b !important;
|
| 381 |
+
margin: 0 !important;
|
| 382 |
+
white-space: nowrap !important;
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
.feedback-section button {
|
| 386 |
+
font-size: 0.7rem !important;
|
| 387 |
+
font-weight: 500 !important;
|
| 388 |
+
padding: 4px 12px !important;
|
| 389 |
+
border-radius: 5px !important;
|
| 390 |
+
background: white !important;
|
| 391 |
+
border: 1px solid #e2e8f0 !important;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
.feedback-section button:hover {
|
| 395 |
+
background: #f0fdfa !important;
|
| 396 |
+
border-color: #0091ad !important;
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
.feedback-input {
|
| 400 |
+
margin-top: 6px !important;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
.feedback-input textarea {
|
| 404 |
+
border-radius: 6px !important;
|
| 405 |
+
font-size: 0.8rem !important;
|
| 406 |
+
border: 1px solid #e2e8f0 !important;
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
/* ============================================================
|
| 410 |
+
LOADING ANIMATION
|
| 411 |
+
============================================================ */
|
| 412 |
+
@keyframes shimmer {
|
| 413 |
+
0% { background-position: -200% center; }
|
| 414 |
+
100% { background-position: 200% center; }
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
@keyframes fadeInOut {
|
| 418 |
+
0%, 100% { opacity: 0.7; }
|
| 419 |
+
50% { opacity: 1; }
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
.loading-msg,
|
| 423 |
+
.loading-msg * {
|
| 424 |
+
border: none !important;
|
| 425 |
+
box-shadow: none !important;
|
| 426 |
+
outline: none !important;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
.loading-msg {
|
| 430 |
+
text-align: center !important;
|
| 431 |
+
padding: 12px 20px !important;
|
| 432 |
+
background: linear-gradient(90deg, #f0fdfa 0%, #e0f7fa 25%, #f0fdfa 50%, #e0f7fa 75%, #f0fdfa 100%) !important;
|
| 433 |
+
background-size: 200% 100% !important;
|
| 434 |
+
animation: shimmer 2s ease-in-out infinite, fadeInOut 2s ease-in-out infinite !important;
|
| 435 |
+
border-radius: 10px !important;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
.loading-msg p {
|
| 439 |
+
color: #0091ad !important;
|
| 440 |
+
font-size: 0.75rem !important;
|
| 441 |
+
font-weight: 500 !important;
|
| 442 |
+
margin: 0 !important;
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
.block.loading-msg {
|
| 446 |
+
border-width: 0 !important;
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
/* ============================================================
|
| 450 |
+
FOOTER
|
| 451 |
+
============================================================ */
|
| 452 |
+
.footer {
|
| 453 |
+
text-align: center !important;
|
| 454 |
+
margin-top: 12px !important;
|
| 455 |
+
padding: 8px !important;
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
.footer p {
|
| 459 |
+
color: #cbd5e1 !important;
|
| 460 |
+
font-size: 0.65rem !important;
|
| 461 |
+
font-weight: 400 !important;
|
| 462 |
+
margin: 0 !important;
|
| 463 |
+
}
|
| 464 |
+
|
| 465 |
+
/* ============================================================
|
| 466 |
+
MOBILE RESPONSIVE
|
| 467 |
+
============================================================ */
|
| 468 |
+
@media (max-width: 768px) {
|
| 469 |
+
/* Container padding for mobile */
|
| 470 |
+
.gradio-container {
|
| 471 |
+
padding: 12px !important;
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
/* Input textarea - smaller placeholder text, full width */
|
| 475 |
+
.input-row input,
|
| 476 |
+
.input-row textarea {
|
| 477 |
+
font-size: 0.8rem !important;
|
| 478 |
+
padding: 10px 12px !important;
|
| 479 |
+
max-width: 100% !important;
|
| 480 |
+
}
|
| 481 |
+
|
| 482 |
+
/* Feedback section - wrap on mobile */
|
| 483 |
+
.feedback-section {
|
| 484 |
+
flex-wrap: wrap !important;
|
| 485 |
+
justify-content: center !important;
|
| 486 |
+
padding: 10px !important;
|
| 487 |
+
gap: 8px !important;
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
.feedback-section p {
|
| 491 |
+
flex: 0 0 100% !important;
|
| 492 |
+
text-align: center !important;
|
| 493 |
+
margin-bottom: 4px !important;
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
.feedback-section button {
|
| 497 |
+
flex: 1 !important;
|
| 498 |
+
min-width: 80px !important;
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
/* Example buttons - stack on mobile */
|
| 502 |
+
.examples-section {
|
| 503 |
+
flex-wrap: wrap !important;
|
| 504 |
+
justify-content: center !important;
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
.examples-section > .block:first-child {
|
| 508 |
+
flex: 0 0 100% !important;
|
| 509 |
+
text-align: center !important;
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
.example-btn {
|
| 513 |
+
flex: 1 1 100% !important;
|
| 514 |
+
min-width: 100% !important;
|
| 515 |
+
max-width: 100% !important;
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
/* Header smaller on mobile */
|
| 519 |
+
.header-section h1 {
|
| 520 |
+
font-size: 1.3rem !important;
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
.header-section p {
|
| 524 |
+
font-size: 0.75rem !important;
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
/* Buttons column - narrower on mobile */
|
| 528 |
+
.buttons-col {
|
| 529 |
+
min-width: 90px !important;
|
| 530 |
+
}
|
| 531 |
+
|
| 532 |
+
.buttons-col button {
|
| 533 |
+
min-width: 90px !important;
|
| 534 |
+
font-size: 0.7rem !important;
|
| 535 |
+
padding: 6px 10px !important;
|
| 536 |
+
}
|
| 537 |
+
}
|
test.py
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Podcast Assistant Test Runner - Debug mode with message flow and metrics.
|
| 3 |
+
|
| 4 |
+
Usage:
|
| 5 |
+
uv run python test.py
|
| 6 |
+
"""
|
| 7 |
+
import os
|
| 8 |
+
import time
|
| 9 |
+
from datetime import datetime
|
| 10 |
+
from dotenv import load_dotenv
|
| 11 |
+
from langchain_core.messages import HumanMessage, SystemMessage
|
| 12 |
+
from langchain.chat_models import init_chat_model
|
| 13 |
+
|
| 14 |
+
from search_podcasts import search_podcasts
|
| 15 |
+
|
| 16 |
+
# Load environment variables
|
| 17 |
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 18 |
+
load_dotenv(dotenv_path=os.path.join(SCRIPT_DIR, '..', '.env'))
|
| 19 |
+
|
| 20 |
+
# OpenAI pricing (per 1M tokens) - update as needed
|
| 21 |
+
PRICING = {
|
| 22 |
+
"gpt-5-nano": {
|
| 23 |
+
"input": 0.05 / 1_000_000,
|
| 24 |
+
"input_cached": 0.005 / 1_000_000,
|
| 25 |
+
"output": 0.40 / 1_000_000,
|
| 26 |
+
},
|
| 27 |
+
"gpt-5-mini": {
|
| 28 |
+
"input": 0.25 / 1_000_000,
|
| 29 |
+
"input_cached": 0.025 / 1_000_000,
|
| 30 |
+
"output": 2.00 / 1_000_000,
|
| 31 |
+
},
|
| 32 |
+
"gpt-4.1-nano": {
|
| 33 |
+
"input": 0.10 / 1_000_000,
|
| 34 |
+
"input_cached": 0.025 / 1_000_000,
|
| 35 |
+
"output": 0.40 / 1_000_000,
|
| 36 |
+
},
|
| 37 |
+
"gpt-4.1-mini": {
|
| 38 |
+
"input": 0.40 / 1_000_000,
|
| 39 |
+
"input_cached": 0.10 / 1_000_000,
|
| 40 |
+
"output": 1.60 / 1_000_000,
|
| 41 |
+
},
|
| 42 |
+
"gpt-4o-mini": {
|
| 43 |
+
"input": 0.15 / 1_000_000,
|
| 44 |
+
"input_cached": 0.075 / 1_000_000,
|
| 45 |
+
"output": 0.60 / 1_000_000,
|
| 46 |
+
},
|
| 47 |
+
"gpt-4o": {
|
| 48 |
+
"input": 2.50 / 1_000_000,
|
| 49 |
+
"input_cached": 1.25 / 1_000_000,
|
| 50 |
+
"output": 10.00 / 1_000_000,
|
| 51 |
+
},
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
# Model to use for testing
|
| 55 |
+
MODEL = "gpt-4.1-mini"
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def compare_models(conversation_index: int = 0, models: list = None):
|
| 59 |
+
"""Compare multiple models on the same conversation."""
|
| 60 |
+
if models is None:
|
| 61 |
+
models = ["gpt-5-nano", "gpt-4.1-nano", "gpt-4o-mini"]
|
| 62 |
+
|
| 63 |
+
results = []
|
| 64 |
+
|
| 65 |
+
for model in models:
|
| 66 |
+
print(f"\n{'#' * 80}")
|
| 67 |
+
print(f" TESTING: {model} ".center(80, "#"))
|
| 68 |
+
print("#" * 80)
|
| 69 |
+
|
| 70 |
+
result = run_test(conversation_index=conversation_index, model=model, return_metrics=True)
|
| 71 |
+
results.append({"model": model, **result})
|
| 72 |
+
|
| 73 |
+
# Print comparison summary
|
| 74 |
+
print("\n" + "=" * 80)
|
| 75 |
+
print(" MODEL COMPARISON ".center(80, "="))
|
| 76 |
+
print("=" * 80)
|
| 77 |
+
|
| 78 |
+
print("\nπ Summary:")
|
| 79 |
+
print(f" {'Model':<15} {'Input':>10} {'Output':>10} {'Cost':>12} {'Time':>10}")
|
| 80 |
+
print(f" {'-'*15} {'-'*10} {'-'*10} {'-'*12} {'-'*10}")
|
| 81 |
+
|
| 82 |
+
for r in results:
|
| 83 |
+
print(f" {r['model']:<15} {r['total_api_input']:>10,} {r['total_api_output']:>10,} ${r['total_cost']:>11.6f} {r['total_time']:>9.2f}s")
|
| 84 |
+
|
| 85 |
+
# Find cheapest and fastest
|
| 86 |
+
cheapest = min(results, key=lambda x: x['total_cost'])
|
| 87 |
+
fastest = min(results, key=lambda x: x['total_time'])
|
| 88 |
+
|
| 89 |
+
print(f"\n π° Cheapest: {cheapest['model']} (${cheapest['total_cost']:.6f})")
|
| 90 |
+
print(f" β‘ Fastest: {fastest['model']} ({fastest['total_time']:.2f}s)")
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def get_usage_from_response(response) -> dict:
|
| 94 |
+
"""Extract token usage from LangChain response (from OpenAI API)."""
|
| 95 |
+
usage = {"input": 0, "output": 0, "cache_read": 0}
|
| 96 |
+
|
| 97 |
+
if hasattr(response, 'usage_metadata') and response.usage_metadata:
|
| 98 |
+
usage["input"] = response.usage_metadata.get("input_tokens", 0)
|
| 99 |
+
usage["output"] = response.usage_metadata.get("output_tokens", 0)
|
| 100 |
+
|
| 101 |
+
# Get cached tokens
|
| 102 |
+
input_details = response.usage_metadata.get("input_token_details", {})
|
| 103 |
+
usage["cache_read"] = input_details.get("cache_read", 0)
|
| 104 |
+
|
| 105 |
+
return usage
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def calculate_cost(input_tokens: int, output_tokens: int, cache_read: int = 0, model: str = MODEL) -> float:
|
| 109 |
+
"""Calculate cost in USD. Cached tokens get 50% discount."""
|
| 110 |
+
pricing = PRICING.get(model, PRICING["gpt-4o-mini"])
|
| 111 |
+
|
| 112 |
+
# Non-cached input tokens
|
| 113 |
+
regular_input = input_tokens - cache_read
|
| 114 |
+
|
| 115 |
+
cost = (
|
| 116 |
+
(regular_input * pricing["input"]) +
|
| 117 |
+
(cache_read * pricing["input_cached"]) +
|
| 118 |
+
(output_tokens * pricing["output"])
|
| 119 |
+
)
|
| 120 |
+
return cost
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def truncate(text: str, max_chars: int = 150) -> str:
|
| 124 |
+
"""Truncate text with ellipsis."""
|
| 125 |
+
if len(text) <= max_chars:
|
| 126 |
+
return text
|
| 127 |
+
return text[:max_chars] + "..."
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
# =============================================================================
|
| 131 |
+
# Test Conversations (multi-turn)
|
| 132 |
+
# =============================================================================
|
| 133 |
+
|
| 134 |
+
TEST_CONVERSATIONS = [
|
| 135 |
+
# 0: Multi-turn with tool use β follow-up may trigger another search β context-based recommendation
|
| 136 |
+
[
|
| 137 |
+
"What is the future of AI and AGI according to experts?",
|
| 138 |
+
"What benefits and risks did they mention?",
|
| 139 |
+
"Which episode should I watch first?",
|
| 140 |
+
],
|
| 141 |
+
# 1: Tool use β context-based summary (tests if AI reuses previous results instead of searching again)
|
| 142 |
+
[
|
| 143 |
+
"How should young people approach their career and education?",
|
| 144 |
+
"Can you summarize that in 3 actionable points?"
|
| 145 |
+
],
|
| 146 |
+
# 2: Multiple tool calls across turns (each question may require fresh search)
|
| 147 |
+
[
|
| 148 |
+
"What habits and routines do high performers follow?",
|
| 149 |
+
"What about sleep habits?",
|
| 150 |
+
"Any book recommendations from them?",
|
| 151 |
+
],
|
| 152 |
+
# 3: Off-topic question (tests if AI correctly skips tool use)
|
| 153 |
+
[
|
| 154 |
+
"What is 2 + 2?",
|
| 155 |
+
],
|
| 156 |
+
# 4: Single turn with one tool call (baseline for model comparison)
|
| 157 |
+
[
|
| 158 |
+
"What are the best books or films that influenced successful people?",
|
| 159 |
+
],
|
| 160 |
+
]
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
# =============================================================================
|
| 164 |
+
# Message Formatting
|
| 165 |
+
# =============================================================================
|
| 166 |
+
|
| 167 |
+
def print_header(title: str, width: int = 80):
|
| 168 |
+
"""Print a centered header."""
|
| 169 |
+
padding = (width - len(title) - 2) // 2
|
| 170 |
+
print("=" * padding + f" {title} " + "=" * (width - padding - len(title) - 2))
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
def print_message(role: str, content: str, tool_calls: list = None, full: bool = False):
|
| 174 |
+
"""Print a message."""
|
| 175 |
+
headers = {
|
| 176 |
+
"system": "System Message",
|
| 177 |
+
"human": "Human Message",
|
| 178 |
+
"ai": "Ai Message",
|
| 179 |
+
"tool": "Tool Message",
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
header = headers.get(role, role)
|
| 183 |
+
print_header(header)
|
| 184 |
+
|
| 185 |
+
if content:
|
| 186 |
+
display = content if full else truncate(content)
|
| 187 |
+
print(display)
|
| 188 |
+
|
| 189 |
+
if tool_calls:
|
| 190 |
+
print("Tool Calls:")
|
| 191 |
+
for tc in tool_calls:
|
| 192 |
+
print(f" {tc['name']}({', '.join(f'{k}={repr(v)}' for k, v in tc['args'].items())})")
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def print_metrics_summary(metrics: dict, model: str = MODEL):
|
| 196 |
+
"""Print a summary of all metrics."""
|
| 197 |
+
print("\n" + "=" * 80)
|
| 198 |
+
print(" METRICS SUMMARY ".center(80, "="))
|
| 199 |
+
print("=" * 80)
|
| 200 |
+
|
| 201 |
+
print(f"\nπ Token Usage & Cost ({model}):")
|
| 202 |
+
for tm in metrics['turns']:
|
| 203 |
+
tool_str = " [tool]" if tm.get('used_tool') else ""
|
| 204 |
+
cache_str = f" ({tm['cache_read']:,} cached)" if tm['cache_read'] > 0 else ""
|
| 205 |
+
print(f" Turn {tm['turn']}: {tm['api_input']:,} in{cache_str} β {tm['api_output']:,} out = ${tm['cost']:.6f}{tool_str}")
|
| 206 |
+
|
| 207 |
+
print(f"\n βββββββββββββββββββββββββββββ")
|
| 208 |
+
print(f" Total input tokens: {metrics['total_api_input']:,}")
|
| 209 |
+
print(f" Total cached tokens: {metrics['total_cache_read']:,} (50% discount)")
|
| 210 |
+
print(f" Total output tokens: {metrics['total_api_output']:,}")
|
| 211 |
+
print(f" Total cost: ${metrics['total_cost']:.6f}")
|
| 212 |
+
|
| 213 |
+
print("\nβ±οΈ Timing:")
|
| 214 |
+
total_llm = 0
|
| 215 |
+
total_tool = 0
|
| 216 |
+
for tm in metrics['turns']:
|
| 217 |
+
llm_time = tm.get('llm_time', 0)
|
| 218 |
+
tool_time = tm.get('tool_time', 0)
|
| 219 |
+
total_llm += llm_time
|
| 220 |
+
total_tool += tool_time
|
| 221 |
+
tool_str = f" + tool {tool_time:.2f}s" if tool_time > 0 else ""
|
| 222 |
+
print(f" Turn {tm['turn']}: LLM {llm_time:.2f}s{tool_str}")
|
| 223 |
+
|
| 224 |
+
print(f" βββββββββββββββββββββββββββββ")
|
| 225 |
+
print(f" Total LLM time: {total_llm:.2f}s")
|
| 226 |
+
print(f" Total tool time: {total_tool:.2f}s")
|
| 227 |
+
print(f" Total: {total_llm + total_tool:.2f}s")
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
# =============================================================================
|
| 231 |
+
# Main Test Runner
|
| 232 |
+
# =============================================================================
|
| 233 |
+
|
| 234 |
+
def run_test(conversation_index: int = 0, model: str = None, return_metrics: bool = False):
|
| 235 |
+
"""Run a multi-turn conversation test with metrics."""
|
| 236 |
+
|
| 237 |
+
model = model or MODEL
|
| 238 |
+
queries = TEST_CONVERSATIONS[conversation_index]
|
| 239 |
+
|
| 240 |
+
metrics = {
|
| 241 |
+
'turns': [],
|
| 242 |
+
'total_api_input': 0,
|
| 243 |
+
'total_api_output': 0,
|
| 244 |
+
'total_cache_read': 0,
|
| 245 |
+
'total_cost': 0,
|
| 246 |
+
'total_time': 0,
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
# Load system prompt
|
| 250 |
+
with open(os.path.join(SCRIPT_DIR, "prompt.md"), "r") as f:
|
| 251 |
+
prompt_template = f.read()
|
| 252 |
+
|
| 253 |
+
today = datetime.now().strftime("%A, %B %d, %Y")
|
| 254 |
+
system_prompt = prompt_template.replace("{today_date}", today)
|
| 255 |
+
|
| 256 |
+
# Initialize LLM
|
| 257 |
+
llm = init_chat_model(model=model)
|
| 258 |
+
tools = [search_podcasts]
|
| 259 |
+
llm_with_tools = llm.bind_tools(tools)
|
| 260 |
+
tools_dict = {t.name: t for t in tools}
|
| 261 |
+
|
| 262 |
+
# Build initial messages
|
| 263 |
+
messages = [SystemMessage(content=system_prompt)]
|
| 264 |
+
|
| 265 |
+
print("\n" + "=" * 80)
|
| 266 |
+
print(" PODCAST ASSISTANT TEST ".center(80, "="))
|
| 267 |
+
print("=" * 80)
|
| 268 |
+
print(f"Model: {model}")
|
| 269 |
+
print(f"Conversation {conversation_index + 1}: {len(queries)} turns")
|
| 270 |
+
print(f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
| 271 |
+
print("=" * 80)
|
| 272 |
+
|
| 273 |
+
# Print System Message (truncated)
|
| 274 |
+
print_message("system", system_prompt)
|
| 275 |
+
|
| 276 |
+
# Process each query in the conversation
|
| 277 |
+
for turn, query in enumerate(queries, 1):
|
| 278 |
+
turn_metrics = {
|
| 279 |
+
'turn': turn,
|
| 280 |
+
'api_input': 0,
|
| 281 |
+
'api_output': 0,
|
| 282 |
+
'cache_read': 0,
|
| 283 |
+
'cost': 0,
|
| 284 |
+
'llm_time': 0,
|
| 285 |
+
'tool_time': 0,
|
| 286 |
+
'used_tool': False
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
print(f"\n{'β' * 80}")
|
| 290 |
+
print(f" TURN {turn}/{len(queries)} ".center(80, "β"))
|
| 291 |
+
print("β" * 80)
|
| 292 |
+
|
| 293 |
+
# Add user message
|
| 294 |
+
messages.append(HumanMessage(content=query))
|
| 295 |
+
|
| 296 |
+
print_message("human", query)
|
| 297 |
+
|
| 298 |
+
# Get AI response
|
| 299 |
+
t0 = time.perf_counter()
|
| 300 |
+
response = llm_with_tools.invoke(messages)
|
| 301 |
+
turn_metrics['llm_time'] = time.perf_counter() - t0
|
| 302 |
+
|
| 303 |
+
# Track API usage
|
| 304 |
+
usage = get_usage_from_response(response)
|
| 305 |
+
turn_metrics['api_input'] += usage['input']
|
| 306 |
+
turn_metrics['api_output'] += usage['output']
|
| 307 |
+
turn_metrics['cache_read'] += usage['cache_read']
|
| 308 |
+
|
| 309 |
+
messages.append(response)
|
| 310 |
+
|
| 311 |
+
# Print AI Message with tool calls
|
| 312 |
+
if response.tool_calls:
|
| 313 |
+
turn_metrics['used_tool'] = True
|
| 314 |
+
print_message("ai", "", tool_calls=response.tool_calls)
|
| 315 |
+
|
| 316 |
+
# Process tool calls
|
| 317 |
+
for tool_call in response.tool_calls:
|
| 318 |
+
tool_name = tool_call["name"]
|
| 319 |
+
|
| 320 |
+
if tool_name in tools_dict:
|
| 321 |
+
t0 = time.perf_counter()
|
| 322 |
+
tool_result = tools_dict[tool_name].invoke(tool_call)
|
| 323 |
+
turn_metrics['tool_time'] += time.perf_counter() - t0
|
| 324 |
+
|
| 325 |
+
messages.append(tool_result)
|
| 326 |
+
|
| 327 |
+
# Show FULL tool results (RAG context)
|
| 328 |
+
print_message("tool", tool_result.content, full=True)
|
| 329 |
+
|
| 330 |
+
# Get final AI response
|
| 331 |
+
t0 = time.perf_counter()
|
| 332 |
+
final_response = llm_with_tools.invoke(messages)
|
| 333 |
+
turn_metrics['llm_time'] += time.perf_counter() - t0
|
| 334 |
+
|
| 335 |
+
# Track API usage for second call
|
| 336 |
+
usage2 = get_usage_from_response(final_response)
|
| 337 |
+
turn_metrics['api_input'] += usage2['input']
|
| 338 |
+
turn_metrics['api_output'] += usage2['output']
|
| 339 |
+
turn_metrics['cache_read'] += usage2['cache_read']
|
| 340 |
+
|
| 341 |
+
messages.append(final_response)
|
| 342 |
+
|
| 343 |
+
# Full AI response
|
| 344 |
+
print_message("ai", final_response.content, full=True)
|
| 345 |
+
else:
|
| 346 |
+
# No tool call, just AI response
|
| 347 |
+
print_message("ai", response.content, full=True)
|
| 348 |
+
|
| 349 |
+
# Calculate cost for this turn (with cache discount)
|
| 350 |
+
turn_metrics['cost'] = calculate_cost(
|
| 351 |
+
turn_metrics['api_input'],
|
| 352 |
+
turn_metrics['api_output'],
|
| 353 |
+
turn_metrics['cache_read'],
|
| 354 |
+
model=model
|
| 355 |
+
)
|
| 356 |
+
|
| 357 |
+
# Update totals
|
| 358 |
+
metrics['total_api_input'] += turn_metrics['api_input']
|
| 359 |
+
metrics['total_api_output'] += turn_metrics['api_output']
|
| 360 |
+
metrics['total_cache_read'] += turn_metrics['cache_read']
|
| 361 |
+
metrics['total_cost'] += turn_metrics['cost']
|
| 362 |
+
|
| 363 |
+
metrics['turns'].append(turn_metrics)
|
| 364 |
+
|
| 365 |
+
# Calculate total time
|
| 366 |
+
metrics['total_time'] = sum(t['llm_time'] + t['tool_time'] for t in metrics['turns'])
|
| 367 |
+
|
| 368 |
+
# Print summary
|
| 369 |
+
print_metrics_summary(metrics, model=model)
|
| 370 |
+
|
| 371 |
+
if return_metrics:
|
| 372 |
+
return metrics
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
if __name__ == "__main__":
|
| 376 |
+
run_test(conversation_index=0)
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|