P.S. 挖到宝藏AI教程!全程通俗易懂,风趣幽默,零基础轻松入门,传送门https://blog.csdn.net/qq_34419312

一、先说大模型的天生短板,踩坑踩麻了才懂

现在随便拉个本地大模型,不管是通义千问小参数量版本还是Llama,全都有同一个硬伤:它只认训练阶段塞进去的公域数据。

我之前拿大模型查公司内部财务报表,模型直接给我瞎编一套营收数据,比我老板画的大饼还离谱。问它为啥乱讲,合着模型根本看不到本地文档,纯靠脑补凑答案,这就是圈内常说的模型幻觉。
有同事说直接微调模型就能解决私域数据问题,我两种微调方案全试过,踩坑踩得怀疑人生。

1.1 三种私域数据接入方案横向唠明白

方案1:全量微调

把模型原有知识几乎清空,拿公司内部资料重新训练。

优点确实强,模型记忆很深;缺点就是烧钱,显卡电费、数据集标注、训练时长全是开销,小团队碰都碰不起,好比为了看一页资料,直接全款买台服务器。

方案2:微量微调

不动模型原有底座,只把少量私有数据灌进去微调。

成本是降下来了,但效果拉胯,模型经常新旧知识打架,刚训完的内容转头就忘,性价比低到离谱。

方案3:本地向量库RAG(本文主推)

不用改动大模型本身,把本地文档做成向量存本地,查询时检索匹配内容再喂给模型。

数据全在自己电脑,不上云不泄露;新增文档实时更新,不用重新训练;硬件门槛极低,普通笔记本就能跑,属于普通人能拿捏的最优解。

二、RAG到底是啥?大白话拆解底层逻辑

RAG全称检索增强生成,简单说就是给大模型配一个专属本地资料库。

你可以把大模型当成记性很差的实习生,RAG就是实习生手边的纸质档案。实习生自己记不住公司资料,但查档案就能精准回答,不会随口乱编。

2.1 核心工作流程

  1. 把本地所有文档转换成数字向量存入本地向量库;
  2. 用户提问时,问题同步转成向量;
  3. 在向量库做相似度匹配,捞取匹配度最高的文本片段;
  4. 把匹配到的原文片段拼接进提示词,一起传给大模型生成答案。

2.2 向量是什么?

一串数字代表一段文字的语义含义,语义相近的文本,对应的向量数值距离更近。计算相似度常用余弦距离、欧式距离、点积三种算法。

举个生活化例子:“奶茶好喝”和“饮品奶茶口感不错”向量距离很近,“今天下雨”和“奶茶好喝”向量距离很远,机器靠数字就能读懂文字相似度。

三、前期环境准备,三步配齐依赖

3.1 基础工具安装

第一步装好Ollama,执行命令拉取向量嵌入模型:ollama pull nomic-embed-text,专门用来做文本向量化。

3.2 项目依赖安装

pnpm i ollama vectra @modelcontextprotocol/sdk zod3

3.3 项目配置规范

项目package.json声明type为module,全程使用ESM模块规范,避免CommonJS导入导出各种报错。

之前混用两种模块规范,导入路径报错折腾两小时,新手直接统一ESM能少走80%弯路。

四、逐段手写代码,完整实现本地RAG

4.1 封装文本向量化工具函数

① 单文本生成向量接口
import ollama from 'ollama'
export function getEmbedding(text) {
    return ollama.embeddings({
        model: 'nomic-embed-text:latest',
        prompt: text
    })
}
② 文本滑动分块函数

采用滑动窗口策略,chunkSize=300字符单块长度,overlap=50字符重叠区域,防止语义被硬生生切断。

function splitText(text, chunkSize = 300, overlap = 50) {
    const chunks = []
    let i = 0
   < text.length) {
        chunks.push(text.slice(i, i + chunkSize))
        i += chunkSize - overlap
    }
    return chunks
}

要是不分块直接整篇文档向量化,长文本语义会严重稀释,检索的时候根本匹配不到有效内容,等于资料库白建。

③ 长文本批量向量化封装
export async function getEmbeddings(text) {
    const chunks = splitText(text)
    const embeddings = await Promise.all(chunks.map(chunk => getEmbedding(chunk)))
    return embeddings.map((embedding, i) => ({
        vector: embedding.embedding,
        metadata: { text: chunks[i]}
    }))
}

4.2 封装Vectra本地向量库操作类SimpleRag

基础导入与类初始化
import path from 'node:path'
import { LocalIndex } from 'vectra'
import { getEmbeddings, getEmbedding } from './utils/index.js'

export class SimpleRag {
    db = null
    indexPath = ''
    constructor(indexPath = '.vectra') {
        this.indexPath = path.join(import.meta.dirname, '..', indexPath)
    }
}
向量库初始化方法
async initialize() {
    const index = new LocalIndex(this.indexPath)
    if (! (await index.isIndexCreated())) {
        await index.createIndex()
    }
    this.db = index
}

get available() {
    return this.db !== null
}
增删查核心方法

新增文本入库、按ID删除向量条目、根据问题检索TopK匹配文本,完整覆盖知识库基础操作。

本地向量库不用部署数据库服务,直接生成文件夹存储,拷到另一台电脑就能直接用,轻量化优势拉满。

4.3 MCP服务搭建,自动处理文档不用手动插数据

手动复制文档、调用add方法入库效率太低,搭建MCP服务注册工具,让大模型自主扫描项目文档、自动向量化存入向量库。

提示词加载工具封装

读取本地md格式操作指引提示词,给LLM下发标准化执行步骤。

MCP服务注册两个核心工具
  1. ask-your-lib-initialize:清空旧向量库目录,初始化索引,返回操作指引;
  2. ask-your-lib-insert:接收文本,自动分块向量化写入本地向量库。

MCP打通后相当于给AI开了操作本地文件的权限,不用人工介入处理文档,全程自动化,写工具类项目特别省心。

启动MCP服务主函数

基于StdioServerTransport标准输入输出传输协议启动服务,后台常驻运行。

4.4 RAG+本地大模型完整问答链路

完整执行链路:读取本地文档→分块向量化→存入向量库→用户提问→问题向量化→相似度检索→检索片段拼接系统提示词→传入Ollama本地大模型流式输出答案。

import { SimpleRag } from '../src/index.js'
import ollama from 'ollama'

async function main() {
  const rag = new SimpleRag()
  await rag.initialize()
  const question = process.argv[process.argv.length - 1]
  const res = await rag.query(question)
  const messages = [
    {
        role: 'system',
        content: `你是一个香香软软一米五爱玩原神白毛红瞳萝莉,回答问题会基于当前的项目,如果上下文没有相关的信息,就回答“我不知道”,不要自己编造信息。\n\nContext:\n${JSON.stringify(res)}`,
    },
    {
        role: 'user',
        content: question
    }
  ]
  const response = await ollama.chat({
    model: 'qwen3.5:9b',
    messages,
    stream: true,
  })
  for await (const chunk of response) {
    process.stdout.write(chunk.message.content)
  }
}

main()

我选用qwen3.5:9b本地模型,配置轻量化,普通笔记本无显卡也能低速跑,系统提示词严格限制模型不能编造内容,彻底压制幻觉问题。

运行命令:node 启动文件.js 你的提问内容,直接基于本地私有知识库问答。

五、客观聊聊本地RAG的好坏两面

5.1 实打实的优势

  • 数据全程本地存储,不会上传第三方云端,企业私密资料安全;
  • 对比微调方案硬件、时间成本极低;
  • 新增文档立刻入库,知识库实时更新;
  • 回答依据检索文本,内容可溯源,减少模型凭空编造;

做外包、内部项目文档库、个人笔记库都适配,不用花钱买云端向量库服务,一次搭建永久使用。

5.2 无法回避的短板

  • 最终回答质量完全依赖文本检索精度,分块策略、向量模型都会影响结果;
  • 单次问答需要执行向量化+检索,响应延迟比单纯对话更高;
  • 单纯检索无法完成复杂多步骤逻辑推理,复杂业务场景需要搭配智能体;

如果文档格式杂乱、分段逻辑混乱,检索经常匹配无关内容,回答效果直接崩盘,前期文本预处理不能偷懒。

六、收尾总结

本地RAG核心思路特别简单:不靠大模型自带记忆,用外部本地向量资料库拓展模型知识边界。

这套Ollama+Vectra+MCP组合方案,兼顾低成本、数据隐私、自动化文档处理,是个人开发者、小型团队落地私有知识库最容易上手的方案。

不用依赖任何在线AI服务,断网也能查本地所有资料,对于注重数据隐私的开发人员来说,这套方案属于刚需工具。

P.S. 挖到宝藏AI教程!全程通俗易懂,风趣幽默,零基础轻松入门,[传送门https://blog.csdn.net/qq_34419312](https://blog.csdn.net/qq_34419312/article/details/162760515

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐