如何用 LangChain 把 PDF、网页与 YouTube 音频加载为 Document 对象
【免费下载链接】llm-cookbook面向开发者的 LLM 入门教程,吴恩达大模型系列课程中文版项目地址: https://gitcode.com/GitHub_Trending/ll/llm-cookbook
在 llm-cookbook 的《使用 LangChain 访问个人数据》(LangChain Chat with Your Data 课程中文版)中,让大模型基于自有数据回答问题之前,第一步就是把 PDF 文档、网页和 YouTube 视频音频这些非结构化数据加载成 LangChain 统一的Document对象。本文按照课程第二章 2.文档加载 Document Loading.ipynb 的完整做法,给出三类数据源各自的安装依赖、加载代码和加载结果的验证方式,最终得到可以直接用于后续文档切割与检索的List[Document]。
准备 Python 环境与 OpenAI API Key
课程代码在 Jupyter Notebook 中运行,依赖按 环境配置 的方式准备:
# 创建一个名为chatgpt且python版本为3.9的环境 conda create --name chatgpt python=3.9 -y conda activate chatgpt在 Notebook 中安装课程所需的库,并升级到最新版 LangChain:
!pip install -q python-dotenv !pip install -q openai !pip install -q langchain --upgradeOpenAI API Key 需要在 OpenAI 官网创建,以OPENAI_API_KEY="sk-..."的形式保存在项目根目录的.env文件中。每章 Notebook 开头都会读取它:
import os import openai from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) openai.api_key = os.environ['OPENAI_API_KEY']其中find_dotenv()负责定位.env文件,load_dotenv()将其中的环境变量加载到当前运行环境。三类加载器中,YouTube 音频转写使用OpenAIWhisperParser,会调用 OpenAI 的 Whisper 接口,因此必须配置好这个 Key;PDF 与网页加载则只做本地读取或网页抓取。
把 PDF 加载为 Document 列表
PDF 加载依赖pypdf库:
!pip install -q pypdf课程示例加载的是仓库自带的 Stanford CS229 机器学习课程字幕 PDF MachineLearning-Lecture01.pdf(吴恩达 2009 年课程的自动字幕,语句可能不太连贯):
from langchain.document_loaders import PyPDFLoader # 创建一个 PyPDFLoader Class 实例,输入为待加载的pdf文档路径 loader = PyPDFLoader("docs/cs229_lectures/MachineLearning-Lecture01.pdf") # 调用 PyPDFLoader Class 的函数 load对pdf文件进行加载 pages = loader.load()注意代码里的相对路径是相对于课程目录(content/必修四-LangChain Chat with Your Data/)的,实际运行 Notebook 时无需改动;换成自己的 PDF 时替换为对应路径即可。
加载结果按以下方式验证:
print(type(pages)) # <class 'list'> print(len(pages)) # 22文档示例输出22,表示这份 PDF 被加载为 22 个元素,每个元素对应一页。查看单个元素的类型与属性:
page = pages[0] print(type(page)) # <class 'langchain.schema.document.Document'> print(page.page_content[0:500]) print(page.metadata)Document类型包含两个属性:
page_content:该文档页面的内容。文档示例输出以MachineLearning-Lecture01 Instructor (Andrew Ng): Okay. Good morning. Welcome to CS229...开头;metadata:页面相关的描述性数据,文档示例输出为{'source': 'docs/cs229_lectures/MachineLearning-Lecture01.pdf', 'page': 0},page字段标明这是第几页。
把 YouTube 视频音频转写为 Document
这部分做两件事:先用 LangChain 加载器把指定 YouTube 视频的音频下载到本地,再用OpenAIWhisperParser把音频转写成文本。需要额外安装两个第三方库:
!pip -q install yt_dlp !pip -q install pydub加载代码把YoutubeAudioLoader(负责下载音频)和OpenAIWhisperParser(负责转写文本)组合进GenericLoader:
from langchain.document_loaders.generic import GenericLoader from langchain.document_loaders.parsers import OpenAIWhisperParser from langchain.document_loaders.blob_loaders.youtube_audio import YoutubeAudioLoader url="https://www.youtube.com/watch?v=jGwO_UgTS7I" save_dir="docs/youtube/" # 创建一个 GenericLoader Class 实例 loader = GenericLoader( # 将链接url中的Youtube视频的音频下载下来,存在本地路径save_dir YoutubeAudioLoader([url],save_dir), # 使用OpenAIWhisperPaser解析器将音频转化为文本 OpenAIWhisperParser() ) # 调用 GenericLoader Class 的函数 load对视频的音频文件进行加载 docs = loader.load()url替换为你要处理的视频链接,save_dir指定音频的本地保存目录。运行时文档展示的日志形如:
[youtube] Extracting URL: https://www.youtube.com/watch?v=jGwO_UgTS7I [youtube] jGwO_UgTS7I: Downloading webpage ... [download] docs/youtube//Stanford CS229: Machine Learning Course, Lecture 1 - Andrew Ng (Autumn 2018).m4a has already been downloaded [download] 100% of 69.76MiB [ExtractAudio] Not converting audio ...; file is already in target format m4a Transcribing part 1! Transcribing part 2! ...这是一次真实运行的文档示例日志:音频以 m4a 格式下载并缓存到save_dir,已下载的文件会直接复用,随后按分段(Transcribing part N!)调用 Whisper 转写。视频较长时耗时会明显增加,仓库英文版章节中也注明了该视频较长、容易遇到网络问题,可自行运行探索。
加载结果同样是List[Document],验证方式与 PDF 一致:
print(type(docs)) # <class 'list'> print(len(docs)) # 1 doc = docs[0] print(type(doc)) # <class 'langchain.schema.document.Document'> print(doc.page_content[0:500]) print(doc.metadata)文档示例输出中page_content是整段视频的英文转写文本,metadata为{'source': 'docs/youtube/Stanford CS229: Machine Learning Course, Lecture 1 - Andrew Ng (Autumn 2018).m4a', 'chunk': 0},source指向本地已下载的 m4a 文件,chunk标明文本分片编号。
把网页加载为 Document
网页加载不需要额外安装包,WebBaseLoader随 LangChain 提供。课程以 GitHub 上的一份 Markdown 文档为例,并显式传入请求头:
from langchain.document_loaders import WebBaseLoader # 创建一个 WebBaseLoader Class 实例 url = "https://github.com/basecamp/handbook/blob/master/37signals-is-you.md" header = {'User-Agent': 'python-requests/2.27.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive'} loader = WebBaseLoader(web_path=url,header_template=header) # 调用 WebBaseLoader Class 的函数 load对文件进行加载 docs = loader.load()验证类型与长度:
print(type(docs)) # <class 'list'> print(len(docs)) # 1此时直接打印doc.page_content会发现,WebBaseLoader抓到的是 GitHub 页面返回的完整 JSON 载荷(包含fileTree、repo、blob等大量冗余字段),而不是纯正文。课程给出的进一步处理方式是按 JSON 路径取出正文文本:
import json convert_to_json = json.loads(doc.page_content) extracted_markdow = convert_to_json['payload']['blob']['richText'] print(extracted_markdow)处理后的输出即该 Markdown 文件的正文,文档示例输出以37signals Is You Everyone working at 37signals represents 37signals...开头。这一步属于课程所说的 Post Processing:原始网页内容包含许多冗余信息,需要进一步处理才能用于后续的检索与问答。
三类加载结果的共同结构
三种数据源走的是不同的加载器,但结果结构一致,这是后续章节可以直接统一处理的前提:
- 返回值都是
List,元素类型为langchain.schema.document.Document; - 每个
Document都有page_content(正文文本)和metadata(描述性数据)两个属性; metadata的字段随来源不同:PDF 带page页码,YouTube 音频带chunk分片编号,网页的source为原始 URL。
完成加载后,课程目录的下一步是 3.文档分割 Splitting,把这些Document切割为具有语义的段落,再进入向量数据库、检索与问答环节。更多背景可参考 第二章课程文档。
【免费下载链接】llm-cookbook面向开发者的 LLM 入门教程,吴恩达大模型系列课程中文版项目地址: https://gitcode.com/GitHub_Trending/ll/llm-cookbook
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考