RAG untuk Kanal YouTube: Dari RSS Menjadi Jawaban Bersitasi

Membangun RAG untuk sebuah kanal YouTube berarti menjawab "apa yang pernah dikatakan kreator ini tentang X, dan di video yang mana?" — di seluruh konten yang pernah mereka terbitkan. Pipeline-nya terdiri dari empat langkah: temukan video lewat RSS, ambil transkrip, potong dan embed, jawab dengan atribusi. Berikut setiap langkahnya dalam Python yang bisa langsung dijalankan, termasuk bagian yang dilewatkan kebanyakan tulisan: penanganan kuota dan seperti apa sitasi yang jujur tanpa timestamp.
Langkah 1: video ID dari feed RSS kanal
YouTube masih menyediakan feed RSS sungguhan per kanal, tanpa perlu API key:
import requests
import xml.etree.ElementTree as ET
CHANNEL_ID = "UCxxxxxxxxxxxxxxxxxxxxxx"
NS = "{http://www.youtube.com/xml/schemas/2015}"
feed = requests.get(
f"https://www.youtube.com/feeds/videos.xml?channel_id={CHANNEL_ID}",
timeout=30,
).text
video_ids = [el.text for el in ET.fromstring(feed).iter(f"{NS}videoId")]
Peringatan: feed ini hanya mengembalikan sekitar 15 unggahan terbaru. Untuk kanal yang aktif, jalankan ini secara terjadwal dan akumulasikan ID di sebuah file atau tabel; katalog lama di luar itu memerlukan YouTube Data API atau daftar manual sekali jalan. Namun untuk menjaga indeks tetap segar, RSS sempurna — ia juga tulang punggung pipeline kanal-ke-newsletter.
Langkah 2: ambil transkrip, hormati kuota
import time
API_KEY = "yt_your_key_here"
def fetch(video_id: str) -> dict | None:
resp = requests.get(
"https://youtube2text.org/api/transcribe",
params={"url": f"https://www.youtube.com/watch?v={video_id}"},
headers={"x-api-key": API_KEY},
timeout=90,
)
if resp.status_code == 404:
return None # TRANSCRIPT_UNAVAILABLE — no captions, skip
if resp.status_code == 429:
time.sleep(resp.json()["error"].get("retryAfterSeconds", 30))
return fetch(video_id)
resp.raise_for_status()
return resp.json()["result"]
transcripts = [t for vid in video_ids if (t := fetch(vid))]
Hitung dulu paket Anda sebelum melakukan loop atas sebuah kanal: paket gratis 5 video per bulan, yang cukup untuk proof of concept dan tidak lebih. Basic ($5,99) memberi 50, pro ($9,99) memberi 500 — pro adalah batas bawah yang realistis untuk mengindeks sebuah kanal plus unggahan barunya.
Langkah 3: potong dan embed
Vector store apa pun bisa; Chroma membuat contohnya tetap ringkas. Auto-caption sering tidak punya tanda baca, jadi saya memotong berdasarkan jumlah kata alih-alih kalimat:
import chromadb
def chunk(text: str, size: int = 300, overlap: int = 50):
words = text.split()
for i in range(0, len(words), size - overlap):
yield " ".join(words[i:i + size])
client = chromadb.PersistentClient(path="./channel_index")
col = client.get_or_create_collection("channel")
for t in transcripts:
for i, piece in enumerate(chunk(t["content"])):
col.add(
ids=[f'{t["videoId"]}-{i}'],
documents=[piece],
metadatas=[{"videoId": t["videoId"], "title": t["title"]}],
)
Langkah 4: jawab dengan sitasi — versi jujur
API ini mengembalikan teks polos tanpa timestamp, jadi saya akan jujur kepada Anda: Anda tidak bisa menyitasi "pada 23:41" dari data ini. Yang bisa Anda lakukan — dan yang biasanya sudah cukup — adalah atribusi video di tingkat chunk: setiap chunk yang diambil tahu videoId dan title-nya, sehingga jawaban menyitasi video mana yang mengatakannya, dengan tautan yang berfungsi.
hits = col.query(query_texts=["what's their take on electric trucks?"], n_results=5)
context = "\n\n".join(
f'[{m["title"]}] (https://www.youtube.com/watch?v={m["videoId"]})\n{doc}'
for doc, m in zip(hits["documents"][0], hits["metadatas"][0])
)
prompt = (
"Answer using only the excerpts below. After each claim, "
f"cite the video title in brackets.\n\n{context}\n\nQuestion: ..."
)
Suplai prompt ke LLM mana pun yang Anda suka — model lokal berfungsi dengan baik di sini, setup yang sama dengan pipa ringkasan Ollama.
Catatan perakitan
Bagi penggemar framework: ini terpetakan satu-satu ke LlamaIndex atau LangChain jika Anda tidak ingin membuat chunking sendiri. Apa pun pilihannya, lapisan transkripnya identik, dan itulah satu-satunya bagian yang bermeteran — ambil key di youtube2text.org/app/keys dan mulailah dengan paket gratis untuk memvalidasi pipeline sebelum mengarahkannya ke 300 video.