gemini_multipdf_chat
基于 Gemini + LangChain 的 PDF 问答机器人,通过 RAG 检索让 AI 回答
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
基于 Gemini + LangChain 的 PDF 问答机器人,通过 RAG 检索让 AI 回答
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
想象一个场景:你是产品经理,收到供应商发来的 80 页技术白皮书,需要从中提炼关键需求;你是法务,拿到对方发来的合同草案,要逐条核对免责条款;你是学生,手握老师上传的课件 PDF,却懒得一页页翻找重点。以前你可能要做的是:打开 PDF → Ctrl+F → 复制 → 粘贴 → 理解 → 再 Ctrl+F……周而复始。
Gemini PDF Chatbot 解决的就是这个痛点:把 PDF 上传进去,然后用"问问题"的方式让 AI 从文档内容中给你答案。它用 Google Gemini 作为大语言模型后端,结合 LangChain 做检索增强生成(RAG),让 AI 的回答严格"绑定"在你上传的文档范围内——不会胡编乱造,答案都有据可查。
这个项目由独立开发者 kaifcoder 创建,GitHub 主页显示其长期活跃于 AI 应用开发社区。项目于 2024 年 1 月开源,随后在 GitHub Trending 上获得关注,目前拥有 223 颗 Stars 和 137 个 Fork,在同类 PDF 聊天机器人中属于起步较早、代码结构清晰的学习参考项目。
图 1:项目使用 Streamlit 作为前端框架
项目的技术流程非常标准,是 RAG(Retrieval-Augmented Generation)领域的经典范式:
PDF上传 → PyPDF2解析 → RecursiveCharacterTextSplitter切分 →
GoogleGenerativeAIEmbeddings向量化 → FAISS向量数据库检索 →
Gemini Pro生成回答 → Streamlit界面展示
整个 Pipeline 的设计对初学者非常友好——每一步都对应一个独立函数,代码结构清晰,易于理解和修改。
项目使用 PyPDF2 库逐页提取 PDF 文本。提取后的原始文本会交由 RecursiveCharacterTextSplitter 处理,该切分器是 LangChain 推荐的切分策略,它按照 "\n\n" → "\n" → " " 的优先级递归切分,最大块大小设为 10000 字符,块间重叠 1000 字符。
重叠设计(overlap)的意义在于:避免在切分边界处丢失跨块的语义信息。比如一个句子的主语在上一个块、谓语在下一个块,如果完全没有 overlap,检索时就会丢失这部分上下文。
项目选用 FAISS-CPU 作为向量数据库。相比 Chroma、Pinecone 等方案,FAISS 的优势在于:
不过需要注意的是,allow_dangerous_deserialization=True 这个参数存在安全风险——它允许从磁盘加载 pickle 序列化的向量索引,在不可信环境下可能被利用。项目代码中包含了这个参数,说明作者对安全性考虑不足,这是使用者需要注意的地方。
项目使用 Google 的 text-embedding-004 模型(即 models/embedding-001),通过 langchain-google-genai 集成接入。这是 Google 官方提供的嵌入服务,每 1000 次调用免费额度,在成本上对个人开发者非常友好。
检索阶段采用 similarity_search(余弦相似度检索),将用户问题同样向量化后在 FAISS 中寻找最相似的 Top-K 文本块,送入 LLM 生成回答。
项目调用 Gemini Pro 作为对话生成模型。通过 langchain_google_genai 的 ChatGoogleGenerativeAI 封装,使用 chain_type="stuff" 模式——即把所有检索到的相关文档一次性塞入上下文窗口。这种方式简单直接,但受限于上下文窗口大小,适合文档量不太大的场景。
温度系数设为 0.3(偏低),意味着模型输出相对确定性高、创意性低,更适合做文档问答这类需要"忠实于原文"的任务。
系统提示词(Prompt Template)也体现了 RAG 问答的核心原则:要求模型"基于提供的上下文回答",如果上下文没有相关信息则明确说"答案不在上下文中",而不是胡乱编造。

图 2:项目作者 kaifcoder 的 GitHub 头像
项目提供了完整的容器化部署方案:
| 文件 | 说明 |
|---|---|
Dockerfile | 多阶段构建,基于 python:3.10-slim,使用非 root 用户运行 |
compose.yaml | Docker Compose 配置,端口映射 8501,环境变量加载 .env |
.env.example | 仅需配置 GOOGLE_API_KEY |
Dockerfile 采用了最佳实践:使用 pip cache mount 加速镜像构建、非特权用户运行、Python 环境变量优化(PYTHONDONTWRITEBYTECODE=1、PYTHONUNBUFFERED=1)。总体来看,这是一个容器化程度高、生产可用的 Docker 配置。
Docker Compose 部分还预留了 PostgreSQL 依赖的注释模板,方便后续扩展为持久化数据库方案。
部署流程极为简单:
# 1. 克隆仓库
git clone https://github.com/kaifcoder/gemini_multipdf_chat.git
cd gemini_multipdf_chat
# 2. 配置 Google API Key
cp .env.example .env
# 编辑 .env,填入你的 GOOGLE_API_KEY
# 3. 一键启动
docker compose up --build
服务启动后访问 http://localhost:8501 即可使用。
| 项目 | 要求 |
|---|---|
| GPU | ❌ 不需要(FAISS-CPU 版本) |
| 内存 | 推荐 2GB+ |
| 磁盘 | 约 1GB(含 Docker 镜像) |
| 前置依赖 | Docker + Google API Key |
项目界面采用 Streamlit 原生的左侧边栏布局:
PyPDF2 解析 + 向量化(处理时长取决于 PDF 大小)代码中包含了对 Google 安全系统的异常处理:
BlockedPromptException:用户提问触发安全过滤时,提示重新措辞StopCandidateException:回答生成被安全系统中断时,给出友好提示BrokenResponseError、IncompleteIterationError:Gemini 响应异常兜底处理这些异常处理覆盖了主要的 Gemini API 错误场景,用户体验较为友好。
(1)向量索引安全性:如前所述,FAISS.load_local 使用了 allow_dangerous_deserialization=True,这在共享环境或生产部署中存在 pickle 反序列化风险。改进方案是使用 FAISS 的 save_to_directory / load_from_directory 接口配合受信任的序列化格式。
(2)文档格式支持有限:当前仅支持 PDF 纯文本提取。如果 PDF 是扫描件(图片格式),PyPDF2 无法提取文字,需要引入 OCR 流程(如 Tesseract)。
(3)上下文窗口限制:Gemini Pro 的上下文窗口有上限,当 PDF 文档非常大或用户上传大量文档时,检索到的块可能无法涵盖全部相关内容。需要引入更高级的分块策略(如语义分块、层级索引)。
(4)多模态缺失:Gemini 本身是多模态模型(支持图片输入),但当前项目仅利用了文本能力,未能充分发挥 Gemini 的视觉理解优势。
(5)对话历史有限:仅使用 st.session_state 管理内存中的对话历史,页面刷新后历史丢失。没有接入外部向量数据库存储对话历史。
对于希望以此为基础深入学习的开发者,建议的演进路径:
Gemini PDF Chatbot 的意义不仅在于它本身,更在于它代表了** RAG 应用开发的最小可行路径**。
在 RAG 技术栈中,文档解析、切分、向量化、检索、生成——每一步都有多种技术选型。对于刚接触 LLM 应用开发的工程师而言,从一个功能完整、代码量可控(app.py 仅约 200 行有效代码)的项目入手,远比一开始就去啃 LangChain 官方文档要高效得多。
同时,这个项目也揭示了一个更广泛的趋势:AI 应用正在从"通用聊天"走向"垂直场景"。让 AI 专注在一个有边界的领域("只回答这个 PDF 里的问题"),远比开放式的通用对话更容易获得可信的结果。Gemini PDF Chatbot 正是这一趋势的一个缩影。
如果你想亲自动手体验,可以按以下步骤操作:
# Python >= 3.10
pip install -r requirements.txt
# 设置 API Key
export GOOGLE_API_KEY="your_key_here"
# 启动
streamlit run app.py
docker compose up --build
# 访问 http://localhost:8501
注意:Google API Key 需要在 Google AI Studio 免费申请,首次用户有免费额度。