IBM 官方 RAG 教程:Node.js + Ollama 本地运行项目文档问答

AI教程21小时前更新 程序员阿超
1.1K 0 0

一、背景:项目文档查起来太痛苦

每个程序员都经历过:在 GitHub 仓库的 README、docs 文件夹、wiki 之间来回横跳,只为找一条跑单测的命令、一个重试策略的默认值。文档越全,越难找。MB 级的 Markdown,藏着你此刻要的那三行。

IBM 这篇官方教程给了一个优雅解法:把 Markdown 文档变成可对话的问答助手。你直接问跑单个单元测试的命令是什么,它从你的文档里定位相关段落,用本地大模型(Granite 3.3 跑在 Ollama 上)生成带上下文的回答。全程本地运行:文档不上传云端,断网也能用,敏感项目尤其合适。本文按教程复述并讲透每一步,顺带给出排错和扩展路线。

二、原理:RAG 管道六步走

这套 demo 是标准 RAG 的极简实现,六步:

  1. 输入收集:CLI 问你要一个 Markdown 文件的直链 URL(如 GitHub Raw 链接),不用 clone 整个仓库,不用配 token。
  2. 文档下载:按 URL 拉取 Markdown 全文,保证每次都是最新版。
  3. 切分 chunking:用 LangChain 的文本切分器把长文档切成小块,每块几百 token,带一点重叠,保证语义不断裂。
  4. 向量化索引:每块用 Granite 模型转成 embedding,存进内存向量库(demo 级别,不用外部数据库)。
  5. 检索加生成:你的问题同样转向量,找最相关的几块,和问题一起喂给 Granite,生成 grounded 回答(基于文档,而非模型瞎编)。
  6. 对话循环:CLI 持续问答,输入 exit 退出。

为什么选 Markdown:它是开发者文档的通用语,轻量、结构清晰(标题天然是切分点)、GitHub 上到处都是。从它起步,跑通后再扩展到整个 docs 目录。为什么本地:Ollama 把模型跑在你机器上,文档不出内网,延迟稳定,无 API 账单。

三、环境准备

  • Node.js 18 或 20 以上(推荐 20),跑整套 JS 代码。
  • Ollama(官网下载安装),跑 Granite 3.3 本地模型。
  • 一个公开 GitHub 仓库里的 Markdown 文件链接(点 Raw 拿到的 raw.githubusercontent.com 直链),用于测试。
  • 熟悉基本 JS 和命令行即可,RAG 和 LangChain 零基础可跟。

环境搭建三步:

ollama pull granite3.3:2b
ollama serve
npm install

第一行拉模型(2b 小尺寸,CPU 也能跑);第二行启动 Ollama 服务;第三行在教程示例目录(markdown-rag-tutorial-demo)装依赖(CLI 交互、HTTP 拉取、切分、embedding、Ollama 对接)。macOS 或 Linux 想直接跑可 chmod +x index.js,否则用 node index.js 启动。小内存机器优先 2b 档,流畅后再试大参数版。

四、分步实战:从启动到问答

第 1 步:启动并输入文档 URL

node index.js
# 提示 Enter the URL to your markdown file
# 粘贴如 https://raw.githubusercontent.com/user/repo/main/README.md

程序问你要文档地址。建议第一次用你熟悉的大 README(如某个知名开源项目),你知道答案在哪,才能判断 AI 答得对不对。Raw 链接怎么拿:GitHub 文件页点 Raw,地址栏复制。

第 2 步:文档下载与切分(代码拆解)

核心逻辑:fetch 拉全文,转纯文本,按 Markdown 感知切分。LangChain 的 MarkdownTextSplitter 会按标题层级切,比固定长度切分语义完整得多。切分参数建议:chunkSize 800 到 1000 字符,overlap 100 到 200,保证跨块的表格和代码段不断裂。demo 只处理单个文件,扩展多文件时给每个 chunk 打上文件名和行号元数据,后面引用标注用得上。

第 3 步:Embedding 与内存索引

每个 chunk 调 Ollama 的 embedding 接口(Granite 3.3)转向量,存进内存向量库(MemoryVectorStore)。demo 数据量小,全放内存,省掉 Milvus、Chroma 等外部依赖。注意这是 POC 设计:文档上 MB 级别、成百上千文件时,换持久化向量库并做增量更新,否则每次启动重算 embedding 慢到不可用。

第 4 步:提问、检索、生成

# CLI内直接问:
# How do I run a single unit test?
# What's the retry policy for the API?

问题转向量,相似度取 Top-4 chunk,拼进 prompt(instruction 加 retrieved context 加 question),Granite 生成回答。prompt 模板关键一句:只根据提供的文档回答,不知道就说不知道。没有这句,模型会用通用知识编答案,grounded 变成 hallucinated。

第 5 步:验证答案带引用

让回答附上来源 chunk 编号或标题,你人工抽查三次:答案的每句话能在文档找到出处吗?这是 RAG demo 和玩具的本质区别。IBM 示例架构里 retriever 和 generator 解耦,调 Top-K、换切分、换模型都不用动 CLI 层,方便做这种验证迭代。

第 6 步:扩展到整个文档站(路线图)

demo 只吃单文件,生产化三步走。第一,爬整个 docs 目录:遍历仓库 .md 文件,chunk 统一入库,元数据记文件名。第二,换持久化向量库并定时重索引(监听 git push)。第三,包一层 Web UI 或 Slack Bot,从 CLI 升级成团队入口。每一步都不碰核心 RAG 链,只换输入和输出,架构上是干净的。

五、常见坑

  1. Node 版本太旧:LangChain.js 要求 18 以上,旧版报奇怪的 ESM 错误,先 node -v。
  2. Ollama 没启动:表现为 embedding 超时或 connection refused,另起终端跑 ollama serve,保持常驻。
  3. 模型名写错:granite3.3:2b 标签要和 pull 时一致,大小写敏感,先 ollama list 确认。
  4. 用了非 Raw 链接:GitHub 页面 URL(含 blob)拉下来是 HTML 不是 Markdown,必须用 raw.githubusercontent.com 直链。
  5. chunk 太大:整篇 README 一个 chunk,检索等于没检,切到 1000 字符以内。
  6. Top-K 太小:答案跨两节时 K 取 2 会丢一半,demo 建议 4 到 6。
  7. 没写拒答指令:文档外问题模型一本正经编答案,prompt 加只按文档回答、不知道就直说。
  8. 内存向量库当生产用:重启丢索引、大文档慢,demo 验证思路可以,上线换持久化库。
  9. 无 GPU 嫌慢:2b 模型 CPU 可跑但 token 慢,大文档先用小文件验证链路,再考虑量化或 GPU。

六、总结

这篇教程的价值不在代码量,而在链路完整性:一条 URL 进去,可对话的文档助手出来,全程本地、零云端依赖、无 token 配置。个人验证思路、团队敏感文档、离线环境,三种场景直接套用。从单文件 demo 出发,按爬全站、换向量库、包 UI 三步扩展,就是你们团队的文档问答生产系统。对着 docs 提问的那一刻,你会回来感谢这半小时的环境搭建。

七、核心代码逐段讲透(index.js 解剖)

教程示例 index.js 虽然不长,但五脏俱全,逐段拆给你看。第一段是 CLI 输入:用 readline 或 prompts 库问 URL,拿到后做一层校验(必须 http 开头、必须 .md 结尾或 raw 链接),省得后面 fetch 到 HTML 才报错。第二段是下载:fetch 取文本,超时设 15 秒,重试一次,大 README 几百 KB,一次拉完。第三段是切分:MarkdownTextSplitter 设 chunkSize 1000、overlap 150,输出顺手记标题路径(如 README > 安装 > Docker),检索命中后展示出处。第四段是向量化:批量调 Ollama embedding 接口,一次 10 块,别一块一调,往返延迟受不了。第五段是问答循环:while true 读问题,转向量取 Top-4,拼 prompt 调 Granite,打印回答和来源,exit 退出。每段都可独立测试:先测下载打印前 500 字,再测切分打印块数,逐段验收是不出大坑的关键。

LangChain 组件选型说透:文本加载用 Cheerio 或纯 fetch 就够了,单文件不需要 DirectoryLoader;切分首选 MarkdownTextSplitter,纯文本备选 RecursiveCharacterTextSplitter;向量库 demo 用 MemoryVectorStore,上线换 Chroma 或 pgvector;retriever 用相似度 Top-K 起步,数据上规模再加 MMR 多样性。Ollama 侧模型分工:embedding 和生成可以是同一个 Granite,也可以拆(embedding 用小模型提速),demo 同一模型最省事。

八、生产扩展三步与评估

单文件跑通后扩展三步。第一步吃全站:写个脚本遍历仓库所有 .md,统一 chunk 入库,metadata 记文件路径和更新时间,回答时标注来自哪篇文档的哪节,这是团队信任的基础。第二步持久化与增量:向量库落盘,监听 git webhook,文档变了只重算变的几块,全量重算在千级文件时会慢到怀疑人生。第三步换形态:CLI 包成 Web 页面或 Slack 机器人,问题加上用户身份,答案可追溯谁问的。评估别用感觉:准备 20 个你知道答案的问题,跑一遍记答对率,改切分、改 Top-K、换模型,每次只动一个变量,答对率涨了才算优化。 grounded 检查抽 5 个回答逐句找出处,找不到出处的句子就是幻觉,回去收紧 prompt 的拒答指令。

九、排错手册与 Python 替代路线

排错按症状查表。问什么都说不知道:检查 Top-K 是否命中了相关 chunk,把检索到的 chunk 打印出来看,八成是切分太粗或 K 太小。回答牛头不对马嘴:prompt 缺拒答和引用指令,加上只按文档回答、附来源。embedding 巨慢:改批量调用,一次 10 到 20 块;再慢就换更小的 embedding 模型,demo 精度损失可接受。Ollama 报内存不足:关掉其他模型,只留 granite3.3:2b,或加量化版本。中文文档回答掺英文:system 指令要求用中文回答,并给一段中文问答示例。

如果你更熟 Python,整套链路有对等实现:LangChain Python 版组件一一对应,Ollama 官方有 Python 客户端,向量库用 Chroma 三行启动。JS 版的优势是和前端栈统一,Python 版的优势是数据科学生态(pandas 清洗文档、jieba 中文切分)。选你团队主力语言,别为教程换栈。核心链路(下载切分向量检索生成)与语言无关,本文的排错和评估方法两边通用。

十、私有化部署与团队知识库蓝图

demo 验证通过后,画一张生产蓝图。数据源:全量 Markdown 进 git 仓库,CI 触发切分和向量化,索引落盘到 Chroma 或 pgvector。服务层:检索 API 独立部署,Top-K 和切分参数走配置中心,灰度可调。应用层:Web 问答页加引用折叠展示,Slack 机器人接 at 提问,CLI 留给运维。安全层:敏感仓库走内网 Ollama,审计日志记问题和引用,定期抽查 grounded 率。评估层:每月 20 题回归,答对率进 dashboard,掉线报警。这张图不用一次建成,按数据源、服务、应用、安全、评估的顺序,每月落地一块,半年就是团队级知识库。单文件 demo 是种子,蓝图是它长成的样子。

成本和隐私是本地路线最大的卖点:一次环境搭建,之后零 token 账单,文档不出内网,过等保和审计都硬气。代价是机器配置和你半小时的搭建时间,这笔账对任何有代码资产的团队都划算。今晚就跑起来:拉模型、起服务、粘一条 README 链接,问出第一个有引用的答案,RAG 在你手里就从概念变成工具了。

附:今晚行动清单。装 Node 20 和 Ollama,拉 granite3.3:2b 并启动服务;下教程示例装依赖跑 node index.js;找一条你最熟的 README 粘 Raw 链接;连问五个你知道答案的问题,核对引用;把 Top-K 从 2 调到 6 对比效果。一晚跑通,RAG 的整条链路就在你手里了,明天就可以吃你们自己的 docs 目录。

一句话收束:一条 URL 进去、可对话的文档助手出来,全程本地零账单。单文件 demo 今晚跑通,吃全站、换向量库、包 UI 三步扩成生产,数据源服务应用安全评估五层每月落一块。引用是信任之源,评估是优化之尺,拒答是幻觉之锁。三把钥匙配齐,项目文档从此开口说话。 点击阅读原文

写在最后:别收藏吃灰,今晚就动手。环境 half 小时,第一个带引用的答案十分钟,跑通后截图发团队群,明天就会有人把自家仓库的 docs 链接丢给你。从回答一个 README 到 answers 整个知识库,起点就是今晚这一次运行。去把 ollama pull 敲下去吧。 点击阅读原文

参考资料:IBM Developer 官方教程《Build a RAG-powered Markdown documentation assistant》(Node.js + LangChain + Ollama Granite 3.3)。 点击阅读原文

© 版权声明

相关文章

暂无评论

暂无评论...