Skip to main content
基于 YouTube 视频构建聊天或问答应用是当前热门话题。 下面演示如何轻松从 YouTube URL视频音频 再到 文本 最终实现 对话 我们将使用 OpenAIWhisperParser,它通过 OpenAI Whisper API 将音频转录为文本;以及 OpenAIWhisperParserLocal,用于本地支持和在私有云或本地部署环境中运行。 注意:您需要提供 OPENAI_API_KEY
from langchain_community.document_loaders.blob_loaders.youtube_audio import (
    YoutubeAudioLoader,
)
from langchain_community.document_loaders.generic import GenericLoader
from langchain_community.document_loaders.parsers.audio import (
    OpenAIWhisperParser,
    OpenAIWhisperParserLocal,
)
我们将使用 yt_dlp 下载 YouTube URL 的音频。 我们将使用 pydub 分割已下载的音频文件(以符合 Whisper API 25MB 的文件大小限制)。
pip install -qU  yt_dlp
pip install -qU  pydub
pip install -qU  librosa

YouTube URL 转文本

使用 YoutubeAudioLoader 获取/下载音频文件。 然后使用 OpenAIWhisperParser() 将其转录为文本。 以 Andrej Karpathy YouTube 课程的第一讲为例!
# 设置标志以切换本地和远程解析
# 如果希望使用本地解析,请将其改为 True
local = False
# Karpathy 的两个讲座视频
urls = ["https://youtu.be/kCc8FmEb1nY", "https://youtu.be/VMj-3S1tku0"]

# 保存音频文件的目录
save_dir = "~/Downloads/YouTube"

# 将视频转录为文本
if local:
    loader = GenericLoader(
        YoutubeAudioLoader(urls, save_dir), OpenAIWhisperParserLocal()
    )
else:
    loader = GenericLoader(YoutubeAudioLoader(urls, save_dir), OpenAIWhisperParser())
docs = loader.load()
# 返回 Document 列表,可轻松查看或解析
docs[0].page_content[0:500]

基于 YouTube 视频构建聊天应用

有了 Documents,我们可以轻松实现聊天/问答功能。
from langchain_classic.chains import RetrievalQA
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 合并文档
combined_docs = [doc.page_content for doc in docs]
text = " ".join(combined_docs)
# 拆分文本
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1500, chunk_overlap=150)
splits = text_splitter.split_text(text)
# 构建索引
embeddings = OpenAIEmbeddings()
vectordb = FAISS.from_texts(splits, embeddings)
# 构建 QA 链
qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-3.5-turbo", temperature=0),
    chain_type="stuff",
    retriever=vectordb.as_retriever(),
)
# 提问!
query = "Why do we need to zero out the gradient before backprop at each step?"
qa_chain.run(query)
query = "What is the difference between an encoder and decoder?"
qa_chain.run(query)
query = "For any token, what are x, k, v, and q?"
qa_chain.run(query)