LangChain YouTube トランスクリプトローダー (本番環境で生き残れるもの)

すべてのLangChain YouTubeトランスクリプトチュートリアルは同じ3行を示します: YoutubeLoader.from_youtube_url()、ロード、完了。その後、クラウドボックスにデプロイして、静かに何も返しません。以下は、ホストされたAPIから代わりに適切なDocumentオブジェクトを返すローダーです―約20行、プラス、それが終わりまで機能することを証明するための概要チェーン。
組み込み YoutubeLoader がサーバーで失敗する理由
YoutubeLoaderは公式APIを呼び出しません。それはコードが実行されるマシンからYouTubeの内部字幕エンドポイントをスクレイピングします。住宅用IPからはほぼ機能しています。AWS、GCP、またはHetzner IPからはブロックされるか、空のレスポンスが提供されます。YouTubeはデータセンタートラフィックをボットトラフィックとして扱うためです。YouTubeトランスクリプトスクレイピングがクラウドIPで壊れる理由の詳細を書きました―短いバージョンは、エラーが環境的であるため、すべてのローカルテストに合格し、重要なまさにそこで死にます。
youtube2text.orgは自分の側でフェッチを行い、JSONを渡します。これはローダーを素のHTTPコールに変えます。
ローダー
import requests
from langchain_core.documents import Document
API_KEY = "yt_your_key_here"
def load_youtube_transcript(url: str, max_chars: int = 150000) -> Document:
resp = requests.get(
"https://youtube2text.org/api/transcribe",
params={"url": url, "maxChars": max_chars},
headers={"x-api-key": API_KEY},
timeout=90,
)
resp.raise_for_status()
r = resp.json()["result"]
return Document(
page_content=r["content"],
metadata={
"videoId": r["videoId"],
"title": r["title"],
"pubDate": r["pubDate"],
"source": url,
},
)
API はvideoId、title、pubDate、content、contentSize、およびtruncatedフラグを返します。トランスクリプトテキストはpage_contentに、他のすべてはメタデータに―下流チェーンとベクトルストアが期待する形状です。
まだキーを持っていないですか? 共有デモキーをつかんでください:
curl https://youtube2text.org/api/demo-key
月5ビデオあたりIPに制限され、ローダーをテストするのに十分です。
概要チェーン
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template(
"Summarize this video transcript in five bullet points:\n\n{context}"
)
chain = create_stuff_documents_chain(llm, prompt)
doc = load_youtube_transcript("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
print(chain.invoke({"context": [doc]}))
create_stuff_documents_chainはトランスクリプト全体を1つのプロンプトに詰め込み、maxCharsがデフォルトではペイロードを150,000文字でキャップするため、機能しています。小規模なコンテキストモデルの長時間のポッドキャストの場合、ローダーに下位のmaxCharsを渡すか、マップリダクスパターンに切り替えます。
実際のコードで処理する方法
2つの障害モードは明示的にキャッチする価値があります。字幕が無効なビデオは、エラーコードTRANSCRIPT_UNAVAILABLEでHTTP 404を返します―再試行またはライブラリスワップはそれを修正しません。テキストは単に存在しません。RATE_LIMIT_EXCEEDED(429)はエラーJSONにretryAfterSecondsを含むため、それを読んで、ハンマーリングの代わりにバックオフします:
if resp.status_code == 429:
wait = resp.json()["error"].get("retryAfterSeconds", 60)
1つの正直な制限: contentはタイムスタンプなしのプレーンテキストです。これは要約と検索には問題ありませんが、「12:34にジャンプ」ディープリンクが必要な場合、メタデータのvideoIdを通じてビデオレベルの属性に落ち着く必要があります。
ここから行く場所
同じDocumentオブジェクトはベクトルストアに直接落ちます―YouTube チャネル全体のRAGのフルパイプラインを説明します。スタックがLangChainではなくLlamaIndexの場合、等価なセットアップは短いです。
デモキーの5ビデオが十分でなくなったとき、独自のキーを取得―無料ティアが含まれ、月50ビデオの有料プラン$5.99から。