我做了个 AI 文档阅读神器,免费开源!
我做了个 AI 文档阅读神器,免费开源!
大家好,我是全栈工程师小Q。最近,我用 Python + Vue.js + OpenAI API 做了一个开源的 AI 文档阅读神器,名叫 DocuMind。它能自动解析 PDF、Word、Markdown 文件,并用大模型帮你总结、问答、提取关键信息。今天,我将从实战角度分享它的核心实现,包含完整代码示例,让你也能自己搭建一个!## 项目背景日常工作中,我们经常要阅读长篇文档,比如合同、论文、技术手册。手动翻页找重点太痛苦了,而现有工具要么收费,要么不够灵活。于是,我决定自己做一个免费开源的工具,目标是:- 支持多种文档格式(PDF、DOCX、TXT、MD)- 自动提取文本并分段- 集成大模型(如 GPT、Claude)实现智能问答- 轻量级,可本地部署项目已开源在 GitHub(链接见文末),欢迎 Star 和 Fork!## 技术栈概览- 后端:Python + FastAPI + LangChain + PyMuPDF- 前端:Vue 3 + Vite + Tailwind CSS- AI:OpenAI API / 本地模型(支持 Ollama)- 数据库:SQLite(存储文档元数据)## 核心架构DocuMind 的工作流程如下:1. 用户上传文档 → 后端解析为纯文本2. 文本分块(Chunk)并向量化3. 用户提问 → 检索相关块 → 调用 LLM 生成答案下面,我们直接上代码!## 实战代码:文档解析模块首先,我们实现文档解析的核心函数。使用 PyMuPDF 处理 PDF,python-docx 处理 Word。python# file: document_parser.pyimport fitz # PyMuPDFfrom docx import Documentimport osdef parse_document(file_path: str) -> str: """ 解析上传的文档,返回纯文本内容。 支持 PDF、DOCX、TXT 格式。 """ ext = os.path.splitext(file_path)[1].lower() if ext == '.pdf': # 使用 PyMuPDF 读取 PDF doc = fitz.open(file_path) text = '' for page in doc: text += page.get_text() doc.close() return text elif ext == '.docx': # 使用 python-docx 读取 Word doc = Document(file_path) text = '\n'.join([para.text for para in doc.paragraphs]) return text elif ext == '.txt' or ext == '.md': # 直接读取文本文件 with open(file_path, 'r', encoding='utf-8') as f: return f.read() else: raise ValueError(f"不支持的文件格式: {ext}")# 测试代码(可独立运行)if __name__ == "__main__": sample_pdf = "example.pdf" if os.path.exists(sample_pdf): content = parse_document(sample_pdf) print(f"文档长度:{len(content)} 字符") print("前200字符:", content[:200]) else: print("请准备一个 example.pdf 文件测试")这段代码简洁高效,支持三种主流格式。注意,PyMuPDF 比 pdfplumber 速度更快,适合生产环境。## 实战代码:AI 问答接口接下来,我们实现核心的 RAG(检索增强生成)问答接口。使用 LangChain 简化流程,OpenAI 作为默认模型。python# file: rag_engine.pyfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.vectorstores import FAISSfrom langchain.chat_models import ChatOpenAIfrom langchain.chains import RetrievalQAimport os# 初始化组件def build_qa_chain(documents: list[str]): """ 根据文档列表构建问答链。 参数 documents: 文本块列表(每块约500字符) 返回: RetrievalQA 对象 """ # 1. 文本分割:每块500字符,重叠50字符 text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=50, separators=["\n\n", "\n", "。", "!", "?", " ", ""] ) chunks = text_splitter.create_documents(documents) print(f"文档被分割为 {len(chunks)} 个块") # 2. 向量化并存储(使用 FAISS 本地索引) embeddings = OpenAIEmbeddings( openai_api_key=os.getenv("OPENAI_API_KEY") ) vectorstore = FAISS.from_documents(chunks, embeddings) # 3. 创建检索器(返回最相似的前3块) retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 4. 初始化 LLM(使用 GPT-3.5-turbo) llm = ChatOpenAI( model_name="gpt-3.5-turbo", temperature=0.2, openai_api_key=os.getenv("OPENAI_API_KEY") ) # 5. 构建问答链 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", # 将检索到的文档拼接后一次性输入 retriever=retriever, return_source_documents=True ) return qa_chain# 测试问答def ask_question(qa_chain, question: str) -> dict: """执行问答,返回答案和来源""" result = qa_chain({"query": question}) return { "answer": result["result"], "sources": [doc.page_content[:100] for doc in result["source_documents"]] }# 如果直接运行此文件,进行测试if __name__ == "__main__": # 模拟文档内容 sample_docs = [ "人工智能(AI)是计算机科学的一个分支,旨在创建能够执行通常需要人类智能的任务的系统。", "深度学习是机器学习的一个子集,使用多层神经网络从数据中学习。", "自然语言处理(NLP)使计算机能够理解、解释和生成人类语言。" ] chain = build_qa_chain(sample_docs) response = ask_question(chain, "什么是深度学习?") print(f"答案:{response['answer']}") print(f"来源:{response['sources']}")运行这段代码,你会得到类似这样的输出:文档被分割为 3 个块答案:深度学习是机器学习的一个子集,它使用多层神经网络从数据中学习。这些神经网络模拟人脑的结构,通过多层处理来提取和组合特征,从而解决复杂问题。来源:['深度学习是机器学习的一个子集,使用多层神经网络从数据中学习。']## 前端集成(Vue 3 示例)为了展示完整项目,我简单贴一下前端文件上传组件:html<!-- FileUpload.vue --><template> <div class="p-4 bg-white rounded shadow"> <input type="file" @change="uploadFile" accept=".pdf,.docx,.txt,.md" /> <button @click="submit" :disabled="!file">上传文档</button> <div v-if="loading">解析中...</div> <div v-if="answer">{{ answer }}</div> </div></template><script setup>import { ref } from 'vue'const file = ref(null)const loading = ref(false)const answer = ref('')const uploadFile = (e) => { file.value = e.target.files[0]}const submit = async () => { loading.value = true const formData = new FormData() formData.append('file', file.value) const res = await fetch('/api/upload', { method: 'POST', body: formData }) const data = await res.json() answer.value = data.summary loading.value = false}</script>后端 FastAPI 接收文件后,调用 parse_document 和 build_qa_chain,然后暴露 /api/ask 接口供前端提问。## 部署与开源本项目已开源在 github.com/your-name/documind(请替换为你自己的仓库)。部署方式:1. 克隆仓库2. 安装依赖:pip install -r requirements.txt3. 设置环境变量 OPENAI_API_KEY4. 运行后端:uvicorn main:app --reload5. 运行前端:cd frontend && npm run dev如果你想使用本地模型(如 Llama 2),只需将 ChatOpenAI 替换为 Ollama 的集成即可,代码改动不超过 10 行。## 总结通过这篇文章,我们从零实战了 AI 文档阅读神器的核心功能:- 使用 PyMuPDF 和 python-docx 解析多种文档格式- 利用 LangChain 构建 RAG 问答链,实现文档智能问答- 前端 Vue 3 组件展示上传和结果整个项目代码不到 500 行,但功能完整可用。你可以基于它二次开发,比如添加 OCR 支持扫描件、集成更多模型、或者改为全本地运行。开源的精神在于共享和改进,希望大家能一起参与,让工具变得更好!最后,如果你觉得这个项目有用,欢迎在 GitHub 上点个 Star ⭐,也欢迎提 Issue 或 PR。让我们一起用 AI 解放文档阅读!
更多推荐



所有评论(0)