基于 LangChain 框架的可扩展知识库问答系统,采用 Tool + Agent 架构,支持多种文档格式的智能解析、向量化存储与 AI 问答。
知识库问答系统 是一个完整的 RAG(检索增强生成)应用框架,用户只需将文档放入 knowledge/ 目录,系统会自动完成文档解析、向量化切片、AI 分类打标签,并提供交互式问答能力。
核心工作流:
放入文档 → 自动解析 → 智能分块 → AI 打标签 → 问答交互
- 多格式文档解析 — 支持 .txt、.md、.pdf、.docx、.png/.jpg 等格式
- 智能缓存机制 — 自动检测文件变化,按需重建,秒级启动
- AI 自动分类 — 为每个文档块自动生成分类和标签,提升检索精度
- 强制更新模式 — 通过环境变量一键刷新全部缓存
- 问答交互 — 基于文档内容的 AI 问答,支持推理回答
- 可扩展架构 — 基于抽象类的模块化设计,即插即用
- 图片 OCR — 集成通义千问 VL 多模态模型,自动提取图片文字
# 创建虚拟环境
python -m venv .venv
# 激活(Windows)
.venv\Scripts\activate
# 安装依赖
pip install langchain langchain-openai langchain-community python-dotenv pypdf dashscope httpx python-docx olefile编辑项目根目录下的 .env 文件:
# 通义千问 API
DASHSCOPE_API_KEY=your_api_key_here将文档放入 knowledge/ 目录下,支持多级子目录:
knowledge/
├── page1/ # 示例目录
│ ├── 背影.txt
│ ├── 背景.txt
│ └── 注释.txt
├── page2/
│ └── 匆匆.txt
├── pdf1/
│ └── Attention Is All You Need.pdf
├── md/
│ └── 茶馆.md
├── word/
│ └── 流浪地球.docx
└── image/
└── 城南旧事.png
python main.py首次运行会自动解析所有文档并进行 AI 分类,后续秒启。
KnowledgeBase/
├── .env # 环境变量(API Key 与配置)
├── .gitignore
├── main.py # 主程序入口
├── readme.md # 项目文档
│
├── agents/ # 智能体层(业务逻辑)
│ ├── __init__.py
│ ├── base_agent.py # Agent 抽象基类
│ ├── qa_agent.py # 问答 Agent(核心)
│ └── analyze_agent.py # 文档分析 Agent(分类打标签)
│
├── tools/ # 工具层(文档解析)
│ ├── __init__.py # 工具注册中心
│ ├── base_tool.py # 工具抽象基类
│ ├── text_tool.py # .txt / .md 解析
│ ├── pdf_tool.py # .pdf 解析
│ ├── image_tool.py # 图片 OCR(通义 VL API)
│ └── word_tool.py # .docx 解析
│
├── knowledge/ # 知识库目录(放文档)
│ ├── page1/ # 分类目录
│ ├── page2/
│ ├── pdf1/
│ ├── md/
│ ├── word/
│ └── image/
│
├── vector_db/ # 向量缓存目录
│ ├── chunks.pkl # 文档块缓存(pickle)
│ └── meta.json # 文件元数据(用于变化检测)
│
├── logs/ # 日志目录
├── versions/ # 版本存档(可选)
└── .venv/ # Python 虚拟环境
负责文件解析,每个文件类型对应一个 Tool:
| 工具 | 解析格式 | 说明 |
|---|---|---|
TextTool |
.txt, .md | 读取 UTF-8 文本内容 |
PdfTool |
使用 PyPDF 逐页提取文字 | |
ImageTool |
.png, .jpg, .jpeg | 调用通义千问 VL API 进行 OCR |
WordTool |
.docx | 使用 python-docx 提取段落文字 |
扩展方式: 继承 BaseFileTool,实现 parse() 方法,并在 TOOL_REGISTRY 中注册即可。
# tools/__init__.py
TOOL_REGISTRY = {
"txt": TextTool(),
"md": TextTool(),
"pdf": PdfTool(),
"png": ImageTool(),
"jpg": ImageTool(),
"jpeg": ImageTool(),
"docx": WordTool(),
}负责业务逻辑与 AI 决策:
| 智能体 | 功能 |
|---|---|
QAAgent |
基于全部文档上下文进行问答,支持推理回答 |
DocumentAnalyzeAgent |
统计文档信息,调用 LLM 为每个文档块生成分类与标签 |
扩展方式: 继承 BaseAgent,实现 run() 方法,在 __init__.py 中导出即可。
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
DASHSCOPE_API_KEY |
✅ | — | 通义千问 API Key |
KNOWLEDGE_BASE_DIR |
knowledge |
知识库根目录路径 | |
VECTOR_DB_DIR |
vector_db |
向量缓存目录路径 | |
CHUNK_SIZE |
500 |
文档分块大小 | |
CHUNK_OVERLAP |
50 |
文档分块重叠大小 | |
QA_MODEL |
qwen-turbo |
QA Agent 使用的模型 | |
IMAGE_MODEL |
qwen-vl-lite |
图片 OCR 使用的模型 | |
MAX_RECENT_ROUND |
5 |
对话历史保留的最大轮数 | |
TOP_CHUNKS |
3 |
检索返回最相关块数 | |
RETRIEVE_TOP_K |
3 |
检索返回最相关块数 | |
FORCE_UPDATE_DATABASE |
false |
是否强制清理并重建缓存 |
当需要重新解析全部文档并重新执行 AI 分类时,设置环境变量:
FORCE_UPDATE_DATABASE=true效果:
- 清空
vector_db/目录下的所有缓存 - 重新扫描并解析
knowledge/目录下的所有文档 - 重新执行文档切分(
RecursiveCharacterTextSplitter) - 重新调用 AI 进行文档分类和打标签
- 将结果重新保存到缓存
注意: 此操作会消耗 API 调用次数(AI 分类),完成后建议恢复为
false。
系统通过以下方式实现高效缓存:
首次运行: 解析文档 → 切片 → AI 分类 → 写入缓存
后续运行: 读取缓存 → 对比文件修改时间 → 仅变更时重建
强制更新: 删除所有缓存 → 完整重建
- chunks.pkl — 序列化的 Document 对象,包含内容、元数据、AI 标签
- meta.json — 所有文件的修改时间戳,用于增量变化检测
你是严格根据文档回答的助手。
情况1:可推理 → 答,并标注【推理回答】
情况2:无法回答 → 说:抱歉,基于现有内容无法回答
文档:{context}
问题:{question}你是文档分类助手。
根据文件名和内容,给出一个分类和3~6个标签。
输出格式:
分类:xxx
标签:标签1,标签2,标签3# tools/excel_tool.py
from .base_tool import BaseFileTool
import pandas as pd
class ExcelTool(BaseFileTool):
def parse(self, file_path):
df = pd.read_excel(file_path)
return df.to_string()
# tools/__init__.py
from .excel_tool import ExcelTool
TOOL_REGISTRY["xlsx"] = ExcelTool()# agents/summary_agent.py
from .base_agent import BaseAgent
class SummaryAgent(BaseAgent):
def run(self):
# 调用 LLM 生成摘要
passQ: 系统提示"不支持的文件类型"
A: 检查文件扩展名是否在 TOOL_REGISTRY 中注册,当前支持 .txt / .md / .pdf / .png / .jpg / .jpeg / .docx。
Q: 图片 OCR 解析失败
A: 检查 DASHSCOPE_API_KEY 是否正确,并确保网络能访问 dashscope 服务。图片 OCR 依赖通义千问 VL API。
Q: 回答不准确或无法回答
A: 当前 QAAgent 将全部文档块拼接为单一上下文,大数据集时可能超出模型窗口。后续可升级为向量检索(FAISS)实现精确检索。
Q: 如何手动清理缓存?
A: 删除 vector_db/ 目录下的 chunks.pkl 和 meta.json,或设置 FORCE_UPDATE_DATABASE=true 运行一次。
Q: Windows 控制台乱码?
A: 运行前设置 $env:PYTHONIOENCODING="utf-8"。
| 技术 | 用途 |
|---|---|
| LangChain | AI 链式调用框架 |
| 通义千问 API | 大语言模型 & 多模态 OCR |
| PyPDF | PDF 文本提取 |
| python-docx | Word 文档解析 |
| httpx | HTTP 客户端(图片 OCR) |
| python-dotenv | 环境变量管理 |
| pickle | 文档块序列化缓存 |