DeepSeek-OCR-2代码实例:结合LangChain构建文档智能体(Document Agent)
DeepSeek-OCR-2代码实例结合LangChain构建文档智能体Document Agent1. 从文档识别到智能问答的跨越如果你用过传统的OCR工具可能会遇到这样的问题好不容易把图片里的文字识别出来了结果发现格式全乱了——表格变成了乱码标题和正文混在一起想要找个具体信息还得自己手动整理。这就像有人给了你一堆散乱的拼图却要你自己拼出完整的画面。DeepSeek-OCR-2的出现改变了这个局面。它不仅能识别文字还能理解文档的结构把表格、标题、段落都整理得清清楚楚输出标准的Markdown格式。但今天我们要聊的是更进一步的玩法把这些结构化的文档内容变成能对话、能问答的智能体。想象一下这样的场景你有一份50页的产品手册PDF想快速找到某个功能的详细说明或者你手头有一堆扫描的合同文件需要提取关键条款信息。传统做法是先OCR识别再手动搜索费时费力。而我们的目标是让文档自己“说话”——你问问题它直接给出答案。这就是文档智能体Document Agent的价值所在。它把DeepSeek-OCR-2的精准识别能力和LangChain的智能处理框架结合起来让静态文档变成动态的知识库。接下来我会带你一步步实现这个想法。2. 环境准备与核心工具介绍2.1 你需要准备什么在开始之前我们先看看需要哪些工具。别担心大部分都是Python的常用库安装起来很简单。基础环境要求Python 3.8或更高版本建议3.9至少8GB内存处理大文档时需要更多如果有NVIDIA GPU会更好处理速度更快核心Python库# 安装必要的依赖 pip install langchain langchain-community pip install pypdf python-docx # 处理PDF和Word文档 pip install chromadb # 向量数据库用于存储文档片段 pip install sentence-transformers # 文本嵌入模型 pip install streamlit # 可选用于构建Web界面如果你打算用DeepSeek-OCR-2处理图片文档还需要按照官方文档配置相应的环境。不过我们今天主要关注的是已经有了OCR提取的Markdown文档后怎么构建智能体。2.2 理解我们的工具链让我用大白话解释一下各个组件的作用DeepSeek-OCR-2这是我们的“眼睛”。它负责把图片、PDF里的文档内容“看”清楚不仅识别文字还理解结构输出整洁的Markdown。LangChain这是我们的“大脑框架”。它提供了一套完整的工具让AI能够理解文档、记住内容、回答问题。向量数据库ChromaDB这是我们的“记忆库”。它把文档切成小片段转换成数学向量存储起来。当你提问时它能快速找到最相关的片段。大语言模型LLM这是我们的“思考引擎”。我们这里可以用开源的比如ChatGLM、Qwen或者如果你有API权限也可以用GPT系列。整个流程就像这样OCR识别文档 → 切分成片段 → 存入向量数据库 → 用户提问 → 搜索相关片段 → LLM生成答案。3. 构建文档智能体的完整流程3.1 第一步准备你的文档假设我们已经用DeepSeek-OCR-2处理好了文档得到了一个Markdown文件。如果没有我们可以先模拟一个示例文档# 产品使用手册 v2.1 ## 第一章快速入门 ### 1.1 开箱检查 收到产品后请检查包装内是否包含以下物品 - 主机设备 x1 - 电源适配器 x1 - USB数据线 x1 - 用户手册 x1 ### 1.2 设备连接 连接设备的步骤如下 1. 将电源适配器插入设备电源接口 2. 连接USB数据线到电脑 3. 按下电源键启动设备 ## 第二章功能详解 ### 2.1 主要功能 设备支持以下核心功能 - 实时数据监测 - 远程控制 - 自动报警 ### 2.2 技术参数 | 参数名称 | 规格 | 备注 | |---------|------|------| | 工作电压 | 5V DC | ±5% | | 工作温度 | -10℃~50℃ | | | 无线连接 | WiFi 802.11ac | 支持2.4G/5G双频 |这是一个典型的产品手册结构有标题、列表、表格。DeepSeek-OCR-2的优势就在于它能从扫描件中准确提取出这种结构。3.2 第二步加载和处理文档现在我们来写代码加载这个Markdown文档并进行预处理from langchain.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter def load_and_split_document(file_path): 加载Markdown文档并切分成适合处理的片段 参数 file_path: Markdown文件路径 返回 文档片段列表 # 加载文档 loader TextLoader(file_path, encodingutf-8) documents loader.load() # 创建文本分割器 # chunk_size: 每个片段的最大字符数 # chunk_overlap: 片段之间的重叠字符数保持上下文连贯 text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个片段约500字符 chunk_overlap50, # 片段间重叠50字符 separators[\n\n, \n, 。, , , , , , ] ) # 分割文档 splits text_splitter.split_documents(documents) print(f文档已分割成 {len(splits)} 个片段) for i, split in enumerate(splits[:3]): # 显示前3个片段 print(f\n片段 {i1} (前100字符):) print(split.page_content[:100] ...) return splits # 使用示例 if __name__ __main__: splits load_and_split_document(product_manual.md)这里有几个关键点需要注意chunk_size的选择500字符是个不错的起点。太小了可能信息不完整太大了可能包含无关信息。你可以根据实际文档调整。chunk_overlap的作用重叠部分能确保重要的上下文信息不会在切分时丢失。比如一个重要的说明正好在片段边界重叠能保证它在两个片段中都出现。separators的设置我们优先按段落\n\n分割然后是句子标点。这样能尽量保持语义的完整性。3.3 第三步构建向量数据库有了文档片段我们需要把它们“记住”。向量数据库就是这个记忆系统from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import Chroma import os def create_vector_store(documents, persist_directory./chroma_db): 创建向量数据库并存储文档 参数 documents: 文档片段列表 persist_directory: 向量数据库存储目录 返回 向量数据库对象 # 创建存储目录 if not os.path.exists(persist_directory): os.makedirs(persist_directory) # 使用开源的嵌入模型 # 这里用的是轻量级的模型如果需要更好效果可以换更大的 embeddings HuggingFaceEmbeddings( model_namesentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 ) # 创建向量数据库 vectorstore Chroma.from_documents( documentsdocuments, embeddingembeddings, persist_directorypersist_directory ) # 持久化保存 vectorstore.persist() print(f向量数据库已创建包含 {vectorstore._collection.count()} 个文档片段) print(f数据库保存在: {os.path.abspath(persist_directory)}) return vectorstore # 使用示例 if __name__ __main__: # 假设我们已经有了文档片段 from document_loader import load_and_split_document # 加载文档 splits load_and_split_document(product_manual.md) # 创建向量数据库 vectorstore create_vector_store(splits) # 测试检索 test_query 设备怎么连接 results vectorstore.similarity_search(test_query, k2) print(f\n针对问题 {test_query} 检索到的相关片段) for i, doc in enumerate(results): print(f\n{i1}. 相关度: {doc.metadata.get(score, N/A)}) print(f内容: {doc.page_content[:150]}...)这段代码做了几件重要的事文本嵌入把文字转换成数学向量。简单说就是把“设备连接”这样的文字变成一组数字这样计算机就能计算它们之间的相似度。向量存储把这些向量存到ChromaDB里。ChromaDB是轻量级的适合本地使用。相似度搜索当你提问时系统会把问题也转换成向量然后找最相似的文档片段。3.4 第四步创建问答链现在是核心部分——让AI基于文档回答问题from langchain.chains import RetrievalQA from langchain.llms import ChatGLM from langchain.prompts import PromptTemplate def create_qa_chain(vectorstore, model_pathNone, use_apiFalse): 创建文档问答链 参数 vectorstore: 向量数据库对象 model_path: 本地模型路径如果使用本地模型 use_api: 是否使用API如果使用云端模型 返回 问答链对象 # 定义提示词模板 # 这个模板告诉AI怎么回答问题基于上下文不知道就说不知道 prompt_template 基于以下上下文信息回答用户的问题。 如果你不知道答案就说你不知道不要编造答案。 上下文 {context} 问题{question} 请用中文给出详细、准确的答案 PROMPT PromptTemplate( templateprompt_template, input_variables[context, question] ) # 选择LLM if use_api: # 如果使用API比如OpenAI from langchain.chat_models import ChatOpenAI llm ChatOpenAI( model_namegpt-3.5-turbo, temperature0.1 # 温度越低回答越稳定 ) else: # 使用本地模型比如ChatGLM llm ChatGLM( endpoint_urlhttp://localhost:8000, # 本地模型服务地址 max_token512, temperature0.1 ) # 创建检索器 retriever vectorstore.as_retriever( search_typesimilarity, search_kwargs{k: 3} # 每次检索3个最相关的片段 ) # 创建问答链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 最简单的链类型把所有上下文拼在一起 retrieverretriever, chain_type_kwargs{prompt: PROMPT}, return_source_documentsTrue # 返回源文档方便查看参考了哪些内容 ) return qa_chain def ask_question(qa_chain, question): 向文档智能体提问 参数 qa_chain: 问答链对象 question: 用户问题 返回 答案和参考文档 result qa_chain({query: question}) print(f\n问题: {question}) print(f\n答案: {result[result]}) print(\n参考的文档片段:) for i, doc in enumerate(result[source_documents]): print(f\n{i1}. 片段内容:) print(doc.page_content[:200] ... if len(doc.page_content) 200 else doc.page_content) return result # 使用示例 if __name__ __main__: # 加载向量数据库 from langchain.vectorstores import Chroma from langchain.embeddings import HuggingFaceEmbeddings embeddings HuggingFaceEmbeddings( model_namesentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 ) vectorstore Chroma( persist_directory./chroma_db, embedding_functionembeddings ) # 创建问答链 qa_chain create_qa_chain(vectorstore) # 提问 questions [ 产品包装里包含哪些物品, 怎么连接设备, 设备支持哪些无线连接, 设备的工作温度范围是多少 ] for question in questions: ask_question(qa_chain, question) print(\n *50 \n)这个问答链的工作流程很清晰用户提问比如“设备怎么连接”检索相关片段从向量数据库找到最相关的3个文档片段组合上下文把这些片段和问题一起送给AI生成答案AI基于上下文生成回答返回结果包括答案和参考了哪些文档片段4. 实际应用场景与优化建议4.1 场景一产品手册智能客服想象你是一家硬件公司的技术支持。每天都有用户问类似的问题“我的设备开不了机怎么办”“怎么连接WiFi”“包装里应该有哪些配件”传统做法是客服人员手动查手册或者建一个FAQ页面。但有了文档智能体你可以def setup_product_support(): 设置产品支持智能体 # 1. 加载所有产品文档 manuals [ 产品A使用手册.md, 产品B快速指南.md, 常见问题解答.md, 故障排除指南.md ] all_splits [] for manual in manuals: splits load_and_split_document(manual) all_splits.extend(splits) # 2. 创建统一的向量数据库 vectorstore create_vector_store(all_splits, product_support_db) # 3. 创建智能客服链 qa_chain create_qa_chain(vectorstore) return qa_chain # 实际使用 support_agent setup_product_support() # 用户问题 user_questions [ 产品A的电源适配器规格是多少, 设备无法连接WiFi怎么解决, 如何更新产品固件 ] for question in user_questions: print(f用户: {question}) answer ask_question(support_agent, question) print(f客服: {answer[result][:200]}...) # 显示前200字符 print(- * 50)这样新客服人员不需要培训几个月熟悉所有产品智能体已经“读过”所有手册能立即回答大多数问题。4.2 场景二合同文档关键信息提取法律和商务场景中经常需要从合同里提取特定信息def setup_contract_analyzer(): 设置合同分析智能体 # 专门的提示词模板针对合同分析 contract_prompt 你是一个合同分析专家。基于以下合同条款回答用户的问题。 请准确引用合同中的具体条款并说明条款位置。 合同条款 {context} 问题{question} 请按以下格式回答 1. 相关条款内容 2. 条款位置如第X章第X条 3. 关键要点分析 4. 注意事项如有 答案 PROMPT PromptTemplate( templatecontract_prompt, input_variables[context, question] ) # 加载合同文档 contracts [采购合同.md, 服务协议.md, 保密协议.md] all_splits [] for contract in contracts: splits load_and_split_document(contract) # 为合同片段添加元数据 for split in splits: split.metadata[document_type] contract split.metadata[contract_name] contract.replace(.md, ) all_splits.extend(splits) # 创建向量数据库 vectorstore create_vector_store(all_splits, contracts_db) # 创建专门的合同分析链 retriever vectorstore.as_retriever(search_kwargs{k: 4}) qa_chain RetrievalQA.from_chain_type( llmChatGLM(endpoint_urlhttp://localhost:8000), chain_typestuff, retrieverretriever, chain_type_kwargs{prompt: PROMPT}, return_source_documentsTrue ) return qa_chain # 使用示例 contract_agent setup_contract_analyzer() questions [ 合同的付款条款是什么, 违约责任如何规定, 保密协议的期限是多久 ] for question in questions: result ask_question(contract_agent, question) print(\n *60 \n)4.3 性能优化建议如果你的文档很多或者需要快速响应可以考虑这些优化1. 分层检索策略def hierarchical_retrieval(question, vectorstore): 分层检索先找相关文档再在文档内找具体信息 # 第一层文档级检索 doc_results vectorstore.similarity_search(question, k2) # 第二层段落级检索在相关文档内 detailed_results [] for doc in doc_results: # 假设每个文档有自己的向量库 doc_vectorstore load_document_vectorstore(doc.metadata[doc_id]) para_results doc_vectorstore.similarity_search(question, k3) detailed_results.extend(para_results) return detailed_results[:4] # 返回最相关的4个段落2. 缓存常见问题from functools import lru_cache lru_cache(maxsize100) def get_cached_answer(question_hash): 缓存常见问题的答案 # 检查缓存 cached check_cache(question_hash) if cached: return cached # 否则正常处理 result qa_chain({query: question}) cache_result(question_hash, result) return result3. 批量处理优化def batch_process_documents(doc_paths, batch_size5): 批量处理文档提高效率 all_splits [] for i in range(0, len(doc_paths), batch_size): batch doc_paths[i:ibatch_size] batch_splits [] for doc_path in batch: splits load_and_split_document(doc_path) batch_splits.extend(splits) # 批量添加到向量数据库 if batch_splits: vectorstore.add_documents(batch_splits) print(f已处理批次 {i//batch_size 1}/{(len(doc_paths)batch_size-1)//batch_size}) return vectorstore5. 常见问题与解决方案5.1 问题一检索不到相关信息症状AI回答“我不知道”但文档里明明有相关信息。可能原因文档切分得太碎上下文不完整问题表述和文档表述差异太大向量模型不适合你的文档类型解决方案def improve_retrieval(query, vectorstore): 改进检索效果的几种方法 # 方法1查询扩展 expanded_queries [ query, f什么是{query}, # 如果是名词 f如何{query}, # 如果是操作 f{query}的方法, f{query}的步骤 ] all_results [] for q in expanded_queries: results vectorstore.similarity_search(q, k2) all_results.extend(results) # 去重 unique_results [] seen_contents set() for result in all_results: if result.page_content not in seen_contents: seen_contents.add(result.page_content) unique_results.append(result) return unique_results[:4]5.2 问题二回答不够准确症状AI回答了但信息有误或不完整。解决方案调整检索数量多检索几个片段k4或5使用更相关的提示词accurate_prompt 请严格基于以下上下文信息回答问题。不要添加任何上下文之外的信息。 上下文 {context} 问题{question} 如果上下文中的信息不足以完整回答问题请说 根据提供的信息我只能回答部分内容[给出部分答案] 如果需要更多信息才能回答请说 要准确回答这个问题还需要了解[说明需要什么信息] 现在请基于上下文回答5.3 问题三处理速度慢优化建议使用更快的嵌入模型比如all-MiniLM-L6-v2比all-mpnet-base-v2快预计算嵌入如果文档不常更新可以预计算所有嵌入硬件加速使用GPU加速推理def optimize_for_speed(): 速度优化配置 # 使用轻量级嵌入模型 embeddings HuggingFaceEmbeddings( model_namesentence-transformers/all-MiniLM-L6-v2, model_kwargs{device: cuda}, # 使用GPU encode_kwargs{normalize_embeddings: False} # 不归一化更快 ) # 减少检索数量 retriever vectorstore.as_retriever( search_kwargs{k: 2} # 只检索2个最相关的 ) return embeddings, retriever6. 总结6.1 我们实现了什么通过这个项目我们把DeepSeek-OCR-2的文档识别能力和LangChain的智能处理能力结合起来创建了一个真正有用的文档智能体。这个智能体能够理解结构化文档不只是识别文字还能理解文档的层次结构智能检索信息从大量文档中快速找到相关内容自然语言问答用对话的方式获取信息不需要手动搜索持续学习扩展可以随时添加新文档扩展知识库6.2 实际价值对于企业来说这样的系统可以降低客服成本自动回答常见问题提高信息检索效率从小时级降到秒级保证信息一致性基于最新文档回答避免人为错误保护数据隐私完全本地部署敏感文档不出内网对于个人用户可以用来管理个人知识库论文、笔记、资料的智能检索学习辅助工具教材、讲义的问答系统研究助手快速从大量文献中提取信息6.3 下一步建议如果你想让这个系统更强大可以考虑多模态支持除了文本还能处理图片、表格中的信息多轮对话记住对话历史进行更复杂的问答事实核查自动核对答案的准确性个性化推荐根据用户历史推荐相关文档内容最重要的是现在就可以动手试试。从一个小文档开始比如你的个人笔记看看智能体能不能帮你快速找到需要的信息。你会发现当文档真正“活”起来时信息获取的方式会发生根本改变。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关新闻

Cursor Free VIP完全指南:突破AI编程限制的5个实战方案

Cursor Free VIP完全指南:突破AI编程限制的5个实战方案

Cursor Free VIP完全指南:突破AI编程限制的5个实战方案 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tr…

2026/7/4 12:01:52 阅读更多 →
Dify Rerank模块面试黑盒揭秘(仅限高级工程师知晓的3层Fallback机制):当LLM生成Query失败时,如何触发Embedding-Level兜底重排?

Dify Rerank模块面试黑盒揭秘(仅限高级工程师知晓的3层Fallback机制):当LLM生成Query失败时,如何触发Embedding-Level兜底重排?

第一章:Dify Rerank模块核心架构与面试定位Dify 的 Rerank 模块是其检索增强生成(RAG)流水线中实现语义相关性精排的关键组件,位于向量检索之后、LLM 生成之前,承担对初始召回文档进行重排序的任务。该模块并非简单封装…

2026/7/3 20:54:34 阅读更多 →
Llama Factory常见问题解决:安装失败、训练报错一站式排查指南

Llama Factory常见问题解决:安装失败、训练报错一站式排查指南

Llama Factory常见问题解决:安装失败、训练报错一站式排查指南 1. 引言:为什么你的Llama Factory总是出问题? 如果你正在尝试使用Llama Factory来微调自己的大模型,大概率已经踩过一些坑了。从安装时莫名其妙的依赖冲突&#xf…

2026/7/4 2:22:39 阅读更多 →

最新新闻

特征工程实战:大数据预处理与模型优化技巧

特征工程实战:大数据预处理与模型优化技巧

1. 特征工程在大数据预处理中的核心价值 数据科学家们常说"数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限"。这句话道出了特征工程在数据预处理环节的关键地位。在实际项目中,我们常常遇到这样的情况:同样的算法&a…

2026/7/4 12:55:11 阅读更多 →
基于ARM Cortex-M4的LED矩阵显示系统设计与优化

基于ARM Cortex-M4的LED矩阵显示系统设计与优化

1. 项目概述:基于MK51DN512CLQ10的LED矩阵信息显示系统 在嵌入式显示领域,16x12像素的LED矩阵提供了一种经济高效的视觉信息传递方案。本项目采用NXP的MK51DN512CLQ10微控制器(基于ARM Cortex-M4内核)驱动IS31FL3733芯片控制的192…

2026/7/4 12:53:11 阅读更多 →
Claude Code Skill功能详解:从重复指令到可复用AI开发技能

Claude Code Skill功能详解:从重复指令到可复用AI开发技能

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度 在实际的 AI 辅助开发工作流中,我们经常需要向 Claude 重复解释项目特定的编码规范、部署流程或复杂的多步骤任务。每次…

2026/7/4 12:51:10 阅读更多 →
AI可解释性工程实战:三层架构与四大硬编码模块

AI可解释性工程实战:三层架构与四大硬编码模块

1. 这不是“解释性”科普,而是一场AI控制权的实操复盘“Understanding Interpretability”这个标题乍看像学术讲座预告,但过去三年我带团队落地的7个工业级AI项目里,它实际意味着:产线质检模型突然把合格品标成缺陷时,…

2026/7/4 12:47:09 阅读更多 →
本科生论文写作利器:AI工具全流程指南

本科生论文写作利器:AI工具全流程指南

1. 本科生论文写作痛点与AI工具价值 写毕业论文是每个本科生都要经历的"成人礼",但现实中90%的学生都会遇到这些典型问题:文献综述找不到方向、数据分析耗时费力、格式调整反复折腾、查重降重痛苦不堪。作为带过上百篇本科论文的指导老师&…

2026/7/4 12:43:07 阅读更多 →
如何3步完成iOS激活锁绕过:面向A9-A11设备的完整指南

如何3步完成iOS激活锁绕过:面向A9-A11设备的完整指南

如何3步完成iOS激活锁绕过:面向A9-A11设备的完整指南 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 你是否曾遇到过这样的情况:购买二手iPhone后却卡在激活锁界面无法使用&…

2026/7/4 12:39:05 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻