Skip to main content

从YouTube url加载文档 (Loading documents from a YouTube url)

在YouTube视频上构建聊天或问答应用程序是一个非常有趣的话题。

下面我们将展示如何从YouTube url轻松地转换为文本并进行聊天!

我们将使用OpenAIWhisperParser,它将使用OpenAI Whisper API将音频转录为文本, 以及OpenAIWhisperParserLocal用于本地支持和在私有云或本地部署上运行。

注意:您需要提供一个OPENAI_API_KEY

from langchain.document_loaders.generic import GenericLoader
from langchain.document_loaders.parsers import OpenAIWhisperParser, OpenAIWhisperParserLocal
from langchain.document_loaders.blob_loaders.youtube_audio import YoutubeAudioLoader

我们将使用yt_dlp来下载YouTube url的音频。

我们将使用pydub来拆分下载的音频文件(以遵守Whisper API的25MB文件大小限制)。

pip install yt_dlp
pip install pydub
pip install librosa

从YouTube url转换为文本 (YouTube url to text)

使用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()
    [youtube] 提取URL: https://youtu.be/kCc8FmEb1nY
[youtube] kCc8FmEb1nY: 下载网页
[youtube] kCc8FmEb1nY: 下载android播放器API JSON
[info] kCc8FmEb1nY: 下载1个格式: 140
[dashsegments] 总片段数: 11
[download] 目标: /Users/31treehaus/Desktop/AI/langchain-fork/docs/modules/indexes/document_loaders/examples/Let's build GPT: from scratch, in code, spelled out..m4a
[download] 100% 的 107.73MiB 在 00:00:18 内以 5.92MiB/s 完成
[FixupM4a] 正在更正 "/Users/31treehaus/Desktop/AI/langchain-fork/docs/modules/indexes/document_loaders/examples/Let's build GPT: from scratch, in code, spelled out..m4a" 的容器
[ExtractAudio] 不转换音频 /Users/31treehaus/Desktop/AI/langchain-fork/docs/modules/indexes/document_loaders/examples/Let's build GPT: from scratch, in code, spelled out..m4a;文件已经是目标格式m4a
[youtube] 提取URL: https://youtu.be/VMj-3S1tku0
[youtube] VMj-3S1tku0: 下载网页
[youtube] VMj-3S1tku0: 下载android播放器API JSON
[info] VMj-3S1tku0: 下载1个格式: 140
[download] /Users/31treehaus/Desktop/AI/langchain-fork/docs/modules/indexes/document_loaders/examples/The spelled-out intro to neural networks and backpropagation: building micrograd.m4a 已经被下载
[download] 100% 的 134.98MiB
[ExtractAudio] 不转换音频 /Users/31treehaus/Desktop/AI/langchain-fork/docs/modules/indexes/document_loaders/examples/The spelled-out intro to neural networks and backpropagation: building micrograd.m4a;文件已经是目标格式m4a
# 返回一个文档列表,可以轻松查看或解析
docs[0].page_content[0:500]
    "Hello, my name is Andrej and I've been training deep neural networks for a bit more than a decade. And in this lecture I'd like to show you what neural network training looks like under the hood. So in particular we are going to start with a blank Jupyter notebook and by the end of this lecture we will define and train a neural net and you'll get to see everything that goes on under the hood and exactly sort of how that works on an intuitive level. Now specifically what I would like to do is I w"

从YouTube视频构建聊天应用 (Building a chat app from YouTube video)

给定Documents,我们可以轻松地启用聊天/问答。

from langchain.chains import RetrievalQA
from langchain.vectorstores import FAISS
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter 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_name="gpt-3.5-turbo", temperature=0),
chain_type="stuff",
retriever=vectordb.as_retriever(),
)
# 提问!
query = "为什么我们需要在每一步的反向传播之前将梯度归零?"
qa_chain.run(query)
    "我们需要在每一步的反向传播之前将梯度归零,因为反向传播会将梯度累积在每个参数的grad属性中。如果我们不在每次反向传播之前将grad归零,梯度将累积并相加,导致错误的更新和较慢的收敛。通过在每次反向传播之前将grad归零,我们确保梯度计算正确,并且优化过程按预期工作。"
query = "编码器和解码器之间有什么区别?"
qa_chain.run(query)
    '在transformer的上下文中,编码器是一个组件,它读取一系列输入标记并生成一系列隐藏表示。另一方面,解码器是一个组件,它接收一系列隐藏表示并生成一系列输出标记。两者之间的主要区别在于编码器用于将输入序列编码为固定长度的表示,而解码器用于将固定长度的表示解码为输出序列。例如,在机器翻译中,编码器读取源语言句子并生成一个固定长度的表示,然后解码器使用该表示生成目标语言句子。'
query = "对于任何标记,x、k、v和q分别是什么?"
qa_chain.run(query)
    '对于任何标记,x是包含该标记的私有信息的输入向量,k和q分别是通过在x上前向线性模块产生的键和查询向量,v是通过再次在x上传播相同的线性模块计算的向量。键向量表示标记包含的内容,查询向量表示标记正在寻找的内容。如果标记发现其他标记有趣,它将传达给它们的信息是向量v,并且为了自注意机制的目的进行聚合。'