我第一次用 LlamaIndex 处理 PDF 文档时,折腾了整整两天才成功读取中文内容。当时在网上搜到的教程大多是英文环境,配置复杂得让人头疼。今天我把这段踩坑经历整理成这篇教程,手把手带你从零开始,让文档加载变得像喝水一样简单。

什么是 LlamaIndex 文档加载器

LlamaIndex 是一个强大的数据框架,专门用来连接你的本地文档和大语言模型。它就像一座桥梁,能把 PDF、网页、Word 文档等各种格式的文件,转换成 AI 能够理解和处理的数据结构。作为初学者,你不需要懂太多技术细节,只需要知道:有了文档加载器,你的 AI 就能“读懂”你的文件内容了。

在正式开始之前,我建议你先注册一个 API 账号。国内开发者在使用 AI 接口时,经常会遇到充值麻烦、网络延迟高等问题。我自己现在用的是 立即注册 HolySheep AI,它支持微信和支付宝充值,而且国内直连延迟小于 50 毫秒,对于文档解析这类频繁调用接口的场景,体验非常好。

环境准备与安装

在开始之前,你需要确保电脑上已经安装了 Python(建议 3.8 以上版本)。打开命令行工具,输入以下命令安装 LlamaIndex 和相关依赖:

# 安装核心依赖
pip install llama-index
pip install llama-index-readers-file
pip install llama-index-readers-web

如果要处理 PDF,还需要安装这个

pip install pypdf

如果要解析 HTML 网页

pip install beautifulsoup4

处理 Microsoft Office 文档

pip install python-docx

我在第一次安装时漏掉了 pypdf 包,结果运行时报错说找不到 PDF 解析器,折腾了半天才发现是依赖没装全。所以建议你把上面的命令一口气全部执行,不要分批安装。

使用 HolySheep API 的基础配置

配置好环境后,我们来设置 API 连接。这里用 HolySheheep AI 作为示例,它家有个很大的优势是汇率按 ¥1=$1 计算,比官方 ¥7.3=$1 便宜很多,而且 2026 年主流模型的价格也很实惠:GPT-4.1 每百万 Token 8 美元,Claude Sonnet 4.5 每百万 Token 15 美元,DeepSeek V3.2 每百万 Token 只要 0.42 美元,对于文档解析这种需要大量 Token 的场景,能省下不少钱。

import os

设置 HolySheep API 配置

os.environ["OPENAI_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY" os.environ["OPENAI_API_BASE"] = "https://api.holysheep.ai/v1"

验证配置是否正确

from llama_index.core import Settings print("API 基础地址:", os.environ["OPENAI_API_BASE"]) print("配置完成,可以开始使用文档加载器了")

注意:代码中的 YOUR_HOLYSHEEP_API_KEY 需要替换成你在 HolySheep 注册后获取的真实密钥。获取方式很简单,登录后在个人中心的 API 密钥管理页面点击“创建新密钥”即可。

PDF 文档加载实战

现在进入正题,先从最常见的 PDF 加载开始。假设你有一个名为 document.pdf 的文件想要让 AI 读取。

基础 PDF 加载方法

from llama_index.core import SimpleDirectoryReader
from llama_index.readers.file import PDFReader

方法一:使用内置的 PDF 解析器

loader = SimpleDirectoryReader( input_dir="./documents", # PDF 文件所在文件夹 file_extractor={".pdf": PDFReader()}, # 明确指定 PDF 解析器 recursive=True, # 是否递归搜索子文件夹 num_workers=4, # 并行处理的线程数 )

加载所有 PDF 文件

documents = loader.load_data() print(f"成功加载 {len(documents)} 个文档")

查看第一个文档的内容预览

if documents: print("文档前500字符预览:") print(documents[0].text[:500])

我在实际项目中发现,如果 PDF 文件比较大或者有加密,直接用这种方式可能会失败。这时候需要用专门的 PDF 解析库来处理。我自己在处理中文 PDF 时,发现 pypdf 对中文支持不太好,后来换用了一个自定义的解析方法:

# 针对中文 PDF 的优化加载方法
from llama_index.core import Document
import pypdf

def load_chinese_pdf(file_path: str) -> Document:
    """专门处理中文 PDF 的加载函数"""
    reader = pypdf.PdfReader(file_path)
    
    full_text = []
    for page_num, page in enumerate(reader.pages):
        text = page.extract_text()
        if text:
            full_text.append(f"--- 第 {page_num + 1} 页 ---\n{text}")
    
    return Document(
        text="\n".join(full_text),
        metadata={
            "source": file_path,
            "total_pages": len(reader.pages),
            "file_type": "pdf"
        }
    )

使用示例

pdf_path = "./documents/中文报告.pdf" doc = load_chinese_pdf(pdf_path) print(f"文档元数据: {doc.metadata}") print(f"提取的文字长度: {len(doc.text)} 字符")

网页内容加载详解

除了本地文件,LlamaIndex 还能直接抓取网页内容。这个功能在做一些舆情分析、竞品调研时特别有用。

from llama_index.readers.web import SimpleWebPageReader

加载单个网页

reader = SimpleWebPageReader() url = "https://www.example.com/article" documents = reader.load_data(urls=[url]) print(f"网页标题: {documents[0].metadata.get('title', '无标题')}") print(f"网页内容前300字符:\n{documents[0].text[:300]}")

我在做市场调研时,经常需要从多个网页同时提取数据。LlamaIndex 支持批量加载,只需要把多个 URL 放到列表里就行:

# 批量加载多个网页
urls = [
    "https://news.example.com/tech-1",
    "https://news.example.com/tech-2",
    "https://blog.example.com/ai-trends",
]

web_documents = reader.load_data(urls=urls)

打印每个文档的摘要

for i, doc in enumerate(web_documents): print(f"文档 {i+1}: {doc.metadata.get('title', '无标题')}") print(f" 字符数: {len(doc.text)}") print("-" * 50)

高级用法:自定义文档解析器

有时候默认的解析器不能满足需求,比如你需要提取 PDF 中的表格、图表说明,或者过滤掉网页中的广告和导航栏。这时候可以创建自定义的解析器:

from llama_index.core import NodeParser
from llama_index.core.schema import TextNode

class CustomDocumentParser:
    """自定义文档解析器,可以根据需求扩展"""
    
    def __init__(self, min_word_count: int = 10):
        self.min_word_count = min_word_count
    
    def parse_pdf(self, file_path: str):
        """解析 PDF 文件"""
        import pypdf
        reader = pypdf.PdfReader(file_path)
        nodes = []
        
        for page_num, page in enumerate(reader.pages):
            text = page.extract_text()
            # 过滤掉太短的文本块(通常是页眉页脚)
            if text and len(text.split()) >= self.min_word_count:
                node = TextNode(
                    text=text,
                    metadata={
                        "page": page_num + 1,
                        "source": file_path,
                        "type": "pdf_page"
                    }
                )
                nodes.append(node)
        
        return nodes
    
    def parse_webpage(self, url: str):
        """解析网页并过滤噪音内容"""
        import requests
        from bs4 import BeautifulSoup
        
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 移除脚本、样式和导航元素
        for tag in soup(['script', 'style', 'nav', 'header', 'footer']):
            tag.decompose()
        
        # 只保留正文段落
        paragraphs = soup.find_all('p')
        content = ' '.join([p.get_text() for p in paragraphs if p.get_text()])
        
        return [TextNode(
            text=content,
            metadata={"url": url, "type": "webpage"}
        )]

使用自定义解析器

parser = CustomDocumentParser(min_word_count=15) pdf_nodes = parser.parse_pdf("./documents/report.pdf") web_nodes = parser.parse_webpage("https://blog.example.com/post") print(f"PDF 解析得到 {len(pdf_nodes)} 个有效节点") print(f"网页解析得到 {len(web_nodes)} 个节点")

将加载的文档用于问答

加载文档只是第一步,更重要的是让 AI 能够基于这些文档回答问题。下面是一个完整的问答示例:

from llama_index.core import VectorStoreIndex

使用之前加载的文档创建索引

index = VectorStoreIndex.from_documents(documents)

创建查询引擎

query_engine = index.as_query_engine( similarity_top_k=3, # 返回最相关的3个结果 streaming=True, # 启用流式输出 )

提问

question = "这份文档的核心内容是什么?" response = query_engine.query(question) print("问题:", question) print("\n回答:") print(response)

如果启用了流式输出,可以这样逐字显示

print("\n--- 流式输出演示 ---") stream_response = query_engine.query("请详细说明文档中的第一个要点") for text in stream_response.response_gen: print(text, end="", flush=True) print()

常见报错排查

在实际使用过程中,我遇到了各种各样的报错,把它们整理成下面的排查清单:

错误1:PDF 解析失败,报错 "No pdf reader provided"

原因:没有为 PDF 文件指定解析器,或者 pypdf 库没有正确安装。

解决方法:

# 解决方案:明确指定 PDFReader
from llama_index.readers.file import PDFReader

loader = SimpleDirectoryReader(
    input_dir="./documents",
    file_extractor={".pdf": PDFReader()}  # 关键:添加这行
)
documents = loader.load_data()

同时确保 pypdf 已安装

pip install pypdf --upgrade

错误2:网页加载超时,报错 "HTTPSConnectionPool" 或 "Connection timeout"

原因:目标网站响应慢,或者网络环境无法访问该网站。

解决方法:

# 方案一:添加超时配置和重试机制
from llama_index.readers.web import SimpleWebPageReader
import requests

class RobustWebReader(SimpleWebPageReader):
    def __init__(self, timeout=30, max_retries=3):
        super().__init__(html_to_text=True)
        self.timeout = timeout
        self.max_retries = max_retries
    
    def load_data_with_retry(self, urls):
        for attempt in range(self.max_retries):
            try:
                return self.load_data(urls)
            except Exception as e:
                print(f"第 {attempt+1} 次尝试失败: {e}")
                if attempt == self.max_retries - 1:
                    raise
        return []

使用示例

reader = RobustWebReader(timeout=60, max_retries=3) docs = reader.load_data_with_retry(["https://slow-site.com/page"])

错误3:中文 PDF 显示乱码或提取为空

原因:PDF 文件使用了特殊的字体编码,pypdf 无法正确识别中文字符。

解决方法:

# 方案一:使用 PyMuPDF (fitz) 库处理中文 PDF
import fitz  # pip install pymupdf

def load_chinese_pdf_mupdf(file_path):
    doc = fitz.open(file_path)
    full_text = []
    
    for page_num, page in enumerate(doc):
        # 使用 OCR 模式提取文本,对中文支持更好
        text = page.get_text("text")
        full_text.append(f"=== 第 {page_num + 1} 页 ===\n{text}")
    
    return "\n".join(full_text)

方案二:使用百度 OCR API 进行文字识别(针对扫描版 PDF)

需要安装 pip install baidu-aip

from aip import AipOcr def ocr_pdf_to_text(pdf_path): client = AipOcr(APP_ID, API_KEY, SECRET_KEY) # 详细的 OCR 实现代码略过 pass

错误4:API 调用报错 "AuthenticationError" 或 "Invalid API key"

原因:API 密钥配置错误或已过期,或者 base_url 设置不正确。

解决方法:

# 仔细检查配置,确保 base_url 正确
import os

错误的写法(会导致认证失败)

os.environ["OPENAI_API_BASE"] = "https://api.openai.com/v1" # ❌

正确的写法(以 HolySheep 为例)

os.environ["OPENAI_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY" # 替换为真实密钥 os.environ["OPENAI_API_BASE"] = "https://api.holysheep.ai/v1" # ✅ 正确地址

验证配置

print(f"API 地址: {os.environ['OPENAI_API_BASE']}") print(f"密钥状态: {'已设置' if os.environ.get('OPENAI_API_KEY') else '未设置'}")

如果用的是自定义 URL,需要确保末尾没有斜杠

错误:https://api.holysheep.ai/v1/ ❌

正确:https://api.holysheep.ai/v1 ✅

错误5:内存不足,报错 "MemoryError" 或加载大文件时程序卡死

原因:PDF 文件太大或者网页内容太多,一次性加载导致内存溢出。

解决方法:

# 方案一:分页加载大 PDF
def load_large_pdf_chunked(file_path, chunk_size=10):
    """分批次加载大 PDF,每次只加载指定页数"""
    import pypdf
    
    reader = pypdf.PdfReader(file_path)
    total_pages = len(reader.pages)
    all_docs = []
    
    for start in range(0, total_pages, chunk_size):
        end = min(start + chunk_size, total_pages)
        chunk_text = []
        
        for page_num in range(start, end):
            page = reader.pages[page_num]
            chunk_text.append(page.extract_text())
        
        all_docs.append({
            "chunk_id": start // chunk_size,
            "pages": f"{start+1}-{end}",
            "text": "\n".join(chunk_text)
        })
        print(f"已加载第 {start+1} 到 {end} 页...")
    
    return all_docs

使用示例:每次加载 10 页

chunks = load_large_pdf_chunked("large_document.pdf", chunk_size=10)

实战经验总结

我在使用 LlamaIndex 文档加载器的过程中,总结了几个实用的经验:

对于刚开始学习 AI 开发的同学,我建议先用 立即注册 HolySheep AI 试试水。它家的注册赠送额度足够完成这篇教程的所有练习,而且微信支付宝直接充值对于国内用户来说非常方便。等你熟练了,再考虑切换到其他平台。

文档加载是 RAG(检索增强生成)系统的第一步,掌握好这个基础,后续的向量检索、问答系统搭建都会顺畅很多。祝你学习愉快!

👉 免费注册 HolySheep AI,获取首月赠额度