)
本地文档问答实战用 ModernBERT 向量模型与 Llama 3.2 构建全本地 RAG 应用modernbert-rag【免费下载链接】ai-engineering-hubIn-depth tutorials on LLMs, RAGs and real-world AI agent applications.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-hub本篇文章围绕 ai-engineering-hub 仓库中的 modernbert-rag 示例展开剖析一套完全运行在本机、可对 PDF 文档进行即问即答的 RAG检索增强生成应用Embedding 由 ModernBERTnomic-ai/modernbert-embed-base承担问答生成交给通过 Ollama 托管的本地 Llama 3.2界面由 Streamlit 提供。读完本文你将掌握基于 LlamaIndex Ollama Hugging Face Embedding 组装最小可用本地 RAG 的完整链路包括环境搭建、源码级参数配置与流式问答 UI 的实现细节。技术栈与项目定位在仓库顶层 README.md 中modernbert-rag被收录为 Basic RAG 基础示例定位是RAG with ModernBert embeddings。与仓库中其他 RAG 变体如 github-rag、document-chat-rag相比本示例的差异化点在于使用 ModernBERT 家族模型替换常见的中文/通用句子嵌入模型并通过三项能力拼装出完整的本地问答闭环组件承担角色具体实现ModernBERT文档与查询的向量化Embeddingnomic-ai/modernbert-embed-base经llama_index-embeddings-huggingface加载Llama 3.2答案生成LLMOllama 本地托管经llama_index-llms-ollama接入LlamaIndexRAG 编排文档加载SimpleDirectoryReader、向量索引VectorStoreIndex、查询引擎Query EngineStreamlitWeb UI文件上传、PDF 预览、流式聊天界面需要留意的是原文档modernbert-rag/README.md描述为 a locally Llama 3.2即 LLM 完全运行在本地不依赖外部 APIEmbedding 模型首次运行需要从 Hugging Face Hub 下载权重。这也意味着整套系统对数据隐私友好适合企业内部文档本地问答场景的原型验证。运行原理从 PDF 上传到流式问答的完整链路从 rag-modernbert.py 的源码执行顺序看整个应用的核心链路可以概括为五个阶段上传与落盘用户在侧边栏选择 PDF代码将文件字节流写入临时目录tempfile.TemporaryDirectory加载与切分SimpleDirectoryReader从临时目录读取.pdf文件并完成文本抽取与切块加载调用点向量化与建索引先加载 ModernBERT Embedding 模型再通过VectorStoreIndex.from_documents(docs, show_progressTrue)把文档块编码为向量并构建内存索引建索引调用点生成查询引擎绑定 Llama 3.2 后执行index.as_query_engine(streamingTrue)得到支持流式输出的查询引擎并替换为自定义的 QA 提示词模板查询引擎构建聊天问答用户提问进入query_engine.query(prompt)检索相关文档块后交给 Llama 3.2 生成答案答案以流式response_gen方式逐块渲染到聊天界面流式渲染。整体是典型的Retrieve → Augment → Generate结构检索质量由 ModernBERT 向量模型保证生成质量由本地 LLM 与精心设计的提示词保证。环境准备与依赖安装原文档的环境搭建包含三个关键步骤且其中藏着本示例最容易踩坑的版本约束下面逐一展开。3.1 创建虚拟环境并安装 main 分支版 transformersModernBERT 模型较新原文档明确提示截至文档编写时ModernBERT 需要从 transformers 仓库的 stable main 分支安装下一个官方 release4.48.x 之后才会被打包进常规发行版。python -m venv modernbert-env source modernbert-env/bin/activate pip install githttps://github.com/huggingface/transformers这里把 pip 安装目标指向githttps://github.com/huggingface/transformers即直接从 GitHub 拉取最新稳定分支源码构建。需要 Python 3.11 或更高版本。如果你在运行应用时遇到与 ModernBERT 架构或分词器相关的报错首要排查项就是当前transformers是否满足该版本约束。3.2 安装 Ollama 并拉取 Llama 3.2LLM 通过 Ollama 在本地运行安装与拉取模型同样只需两条命令# 在 Linux 上安装 ollama curl -fsSL https://ollama.com/install.sh | sh # 拉取 llama 3.2 权重 ollama pull llama3.2使用提示确保 Ollama 服务处于运行状态Linux 下安装后通常作为后台服务启动并可用ollama list确认llama3.2已就绪再启动 Streamlit 应用。3.3 安装 Python 依赖及其角色映射在原文档给出的依赖清单之上结合源码中的 import 语句文件头导入段各依赖与代码用途的对应关系如下pip install streamlit ollama llama_index-llms-ollama llama_index-embeddings-huggingface依赖源码中的用途streamlitWeb 界面框架文件上传、会话状态、聊天 UIollamaPython 侧连接本地 Ollama 服务llama_index-llms-ollama提供llama_index.llms.ollama.Ollama类把 Llama 3.2 接入 LlamaIndexllama_index-embeddings-huggingface提供HuggingFaceEmbedding加载 ModernBERT 模型其中streamlit、ollama之外的llama_index-*是 LlamaIndex 官方的模型集成插件会自动把llama_index.core等核心依赖带入环境中。此外PDF 文本抽取依赖 LlamaIndex 内部的文档解析能力SimpleDirectoryReader默认依赖pypdf一类解析库如解析 PDF 报缺库错误需补充相应解析依赖这一点从源码选用required_exts[.pdf]加载参数可以印证——应用只面向 PDF 输入。启动并体验应用依赖装齐后在modernbert-rag目录下执行streamlit run rag-modernbert.py浏览器会自动打开本地 Streamlit 地址默认http://localhost:8501。参考源码界面布局如下左侧边栏标题 Add your documents!提供 PDF 上传控件上传后显示 Indexing your document... 进度提示索引完成后出现绿色 Ready to Chat! 状态并在侧边栏内嵌 PDF 预览侧边栏逻辑主区域标题 Chat with Docs, powered by ModernBert and Llama-3.2右上角提供 Clear ↺ 按钮用于清空对话与释放内存底部为聊天输入框主区域布局。仓库内还附带了一段演示视频 modernbert-demo.mp4展示从上传文档到对话的完整操作过程可作为上手前的直观参考。源码级实现剖析关键参数与调用链下文以 rag-modernbert.py 为准逐层讲解各环节的实现要点方便你在自己的项目中按需调整。4.1 模型的加载超时、缓存与 trust_remote_codeLLM 通过st.cache_resource装饰器做资源级缓存load_llm保证每次 Streamlit 脚本重跑时不会重复创建连接st.cache_resource def load_llm(): llm Ollama(modelllama3.2, request_timeout120.0) return llmrequest_timeout120.0是关键调参项本地模型在长上下文或弱机器上生成较慢如果单次请求超过 120 秒会超时可依硬件情况适当放大。Embedding 模型在每次新建索引时加载模型加载行embed_model HuggingFaceEmbedding( model_namenomic-ai/modernbert-embed-base, trust_remote_codeTrue, cache_folder./hf_cache )三个参数含义如下model_namenomic-ai/modernbert-embed-base指定 ModernBERT 嵌入模型。当前仓库2026-09 快照的 transformers 发行版已原生支持 ModernBERT 架构因此可以指定模型名称直接使用而无需再像原文档编写时那样依赖 main 分支安装 transformerstrust_remote_codeTrue该模型来自 HF Hub 且需要执行其自定义代码才能正确构造分词器/模型。安全性提醒该选项会运行远端仓库中的代码生产环境务必改为使用经过审查的自定义模型配置或镜像cache_folder./hf_cache权重下载缓存目录。默认情况下首次运行会联网下载 ModernBERT 权重第二次起从本地缓存加载可显著缩短启动时间。加载完成后通过Settings.embed_model embed_model将模型写入 LlamaIndex 全局配置后续建索引的编码过程即自动使用该 ModernBERT 模型Settings 配置。4.2 文档解析与向量索引只看 PDF、带进度条上传文件先以临时目录方式落盘临时目录随with块退出自动清理避免长期占用磁盘随后交给SimpleDirectoryReaderloader SimpleDirectoryReader( input_dirtemp_dir, required_exts[.pdf], recursiveTrue ) docs loader.load_data() index VectorStoreIndex.from_documents(docs, show_progressTrue)required_exts[.pdf]只处理 PDF其他文件被忽略recursiveTrue递归扫描子目录对临时目录场景而言是防御性配置VectorStoreIndex.from_documents(...)内部依次完成文本切块、调用Settings.embed_model批量编码、构建内存向量索引show_progressTrue让长文档的索引过程在终端可见。4.3 查询引擎与自定义提示词让回答先思考再作答索引构建后生成查询引擎对应代码段Settings.llm llm query_engine index.as_query_engine(streamingTrue) qa_prompt_tmpl_str ( Context information is below.\n ---------------------\n {context_str}\n ---------------------\n Given the context information above I want you to think step by step to answer the query in a crisp manner, incase case you dont know the answer say I dont know!.\n Query: {query_str}\n Answer: ) qa_prompt_tmpl PromptTemplate(qa_prompt_tmpl_str) query_engine.update_prompts( {response_synthesizer:text_qa_template: qa_prompt_tmpl} )这段代码体现了 LlamaIndex 提示词注入的标准写法text_qa_template是响应合成阶段response synthesizer渲染上下文 问题的模板{context_str}与{query_str}是两个内置占位符。本示例在提示词中加入了三层约束限定信息来源强调只依据给定上下文作答减少幻觉要求逐步思考think step by step引导模型进行链式推理兜底机制不确定时直接回答 I dont know!避免强行编造。4.4 会话状态与多文档缓存避免重复索引Streamlit 每次交互都会自上而下重跑脚本若每次都重新加载模型、重建索引会非常耗时。源码用两处机制解决会话状态初始化if id not in st.session_state: st.session_state.id uuid.uuid4() st.session_state.file_cache {}每个浏览器会话生成唯一uuid4()作为session_id文档以f{session_id}-{uploaded_file.name}为键存入file_cache字典命中缓存时直接复用查询引擎缓存命中逻辑若需为同一会话上传多份文档每个文件键都有独立的查询引擎实例理论上可支持按文档并行维护多个索引从当前代码结构看聊天主区域绑定的是最近一次赋值的query_engine多文档的自由切换还需自行扩展。会话历史st.session_state.messages保存用户与助手的消息列表脚本重跑后仍可完整回显历史对话历史渲染。4.5 流式聊天 UI 与清空会话聊天的核心在模拟打字机式的流式渲染完整聊天逻辑streaming_response query_engine.query(prompt) for chunk in streaming_response.response_gen: full_response chunk message_placeholder.markdown(full_response ▌) message_placeholder.markdown(full_response)由于建查询引擎时启用了streamingTruequery()返回的是流式响应对象其response_gen生成器逐块吐出文本每收到一块就整体重绘一次并追加光标符号▌最后一帧去掉光标完成整句渲染。st.chat_message(user/assistant)负责按角色分区展示消息气泡。Clear ↺ 按钮调用reset_chat()重置函数清空消息历史与上下文并显式执行gc.collect()回收内存避免长时间对话导致内存膨胀。4.6 PDF 预览与异常兜底上传后侧边栏会内嵌展示当前 PDFdisplay_pdf 函数将文件内容做 base64 编码后放入iframe的data:application/pdf;base64,...数据源无需额外 PDF 查看组件即可预览。同时上传处理块整体被try/except包裹解析失败时会在侧边栏显示 An error occurred 并通过st.stop()终止本次脚本执行异常处理。关键参数速查表位置参数取值示例默认作用load_llm()modelllama3.2指定 Ollama 托管的 LLM 模型名须与ollama pull一致load_llm()request_timeout120.0秒单次 LLM 请求超时阈值弱机/长文档可调大Embedding 加载model_namenomic-ai/modernbert-embed-baseModernBERT 嵌入模型决定检索质量Embedding 加载trust_remote_codeTrue允许加载并执行 HF Hub 仓库自定义代码Embedding 加载cache_folder./hf_cache权重本地缓存目录二次加载免下载SimpleDirectoryReaderrequired_exts[.pdf]限定参与索引的文件类型as_query_enginestreamingTrue开启流式响应配合response_gen逐块输出上传控件typepdfStreamlit 文件上传器只接受 PDF注意事项与实践建议综合原文档说明与源码实现运行本应用时有几点值得留意依赖版本是最大变量ModernBERT 曾依赖 transformers 的 main 分支版本原文档明确标注 4.48.x 之前的约束如今该架构已合入正式发行版。若更换环境后遇到加载失败应优先核对 transformers 与llama_index-embeddings-huggingface的版本组合本地资源占用Embedding 模型首次需联网下载与 Llama 3.2 均在本地运行问答时对内存/显存有一定占用reset_chat()中的gc.collect()说明开发者已把长会话的内存回收纳入考量先上传再提问从代码结构看聊天主区域直接引用上传流程中生成的query_engine若跳过上传直接输入问题该变量尚未定义因此正确使用顺序是先上传文档、等待 Ready to Chat! 提示后再提问索引为内存态VectorStoreIndex建立在进程内存中重启应用即失效需重新上传如需持久化可在此基础上扩展 LlamaIndex 的存储持久化或接入向量数据库如仓库中 fastest-rag-milvus-groq 一类的方案扩展方向在保持上传文档 → 索引 → 对话主流程不变的前提下可将file_cache的键控粒度做得更细以实现真正的多文档选择问答或将 PDF 解析替换为对 Word、网页等多格式支持只需调整required_exts与对应解析器。小结modernbert-rag 是一个结构清晰、可端到端运行的本地 RAG 入门示例。它把 LlamaIndex 的文档加载、ModernBERT 向量索引、Ollama 托管的 Llama 3.2 与 Streamlit 流式界面组合在一起仅用一个 Python 文件便演示了 RAG 应用从文件上传到逐字流式回答的全流程。对照仓库源码逐一调整其中的超时参数、缓存目录、文件类型过滤与提示词模板你就能快速将其改造成贴合自身业务文档的本地问答原型。【免费下载链接】ai-engineering-hubIn-depth tutorials on LLMs, RAGs and real-world AI agent applications.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-hub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考