使用Nodejs基于DeepSeek加chromadb实现RAG检索增强生成 本地知识库

定义

检索增强生成(RAG)的基本定义

检索增强生成(Retrieval-Augmented Generation,简称RAG)是一种结合了信息检索技术与语言生成模型的人工智能技术。RAG通过从外部知识库中检索相关信息,并将其作为提示(Prompt)输入给大型语言模型(LLMs),以增强模型处理知识密集型任务的能力。这种技术能够有效提升模型在问答、文本摘要、内容生成等自然语言处理任务中的表现。

RAG的工作机制

RAG的工作机制主要包括三个核心部分:检索(Retrieval)、增强(Augmentation)和生成(Generation)。

检索(Retrieval):RAG流程的第一步是从预先建立的知识库中检索与问题相关的信息。这一步骤的目的是为后续的生成过程提供有用的上下文信息和知识支撑。检索模块通常依赖于向量检索技术,将查询转换为向量表示,然后与知识库中的向量进行比对,找到最相似的内容。

增强(Augmentation):在RAG中增强是将检索到的信息用作生成模型(即大语言模型)的上下文输入,以增强模型对特定问题的理解和回答能力。这一步的目的是将外部知识融入生成过程中,使生成的文本内容更加丰富、准确和符合用户需求。

生成(Generation):生成是RAG流程的最后一步。这一步的目的是结合LLM生成符合用户需求的回答。生成器会利用检索到的信息作为上下文输入,并结合大语言模型来生成文本内容,最终输出准确、有用的回答。

实现

实现思路

文件上传 读取 语句的分割还有向量化 然后对用户的提问在向量库中进行检索

通过langchain文档工具进行文档的分割

通过chromadb进行向量转换和语义检索

其实完全可以通过python实现但是我看官方有提供的js的插件包 于是在用node写了一套 之后又用python写了一套

怎么说呢 看你喜欢用哪一种吧 反正离不开python环境

第一步安装python环境

有更多教你安装的帖子链接在下面 可以去看看

https://blog.csdn.net/qq_45502336/article/details/109531599?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522d97c47b484bd158f0638dbc85d5e8b2c%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=d97c47b484bd158f0638dbc85d5e8b2c&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-109531599-null-null.14 2

第二步安装chromadb

chromadb 官网地址

pip install chromadb

然后肯定要持久化客户端运行

官网有几种启动方式 既然我们要用node实现 那其他的都不用看了 cmd 命令行启动客户端

搞个空的文件夹就行 (注意 安装完环境之后 把py环境变量搞上 要不然可能chroma run 无法运行)

chroma run --path C:\Users\Administrator\Desktop\database

# 本地数据库地址

注意 这里有坑 因为我用的win系统 chroma-hnswlib 最新版本有问题所以每个集合只能插入99条坑爹 然后客户端莫名就报错崩溃

我以为是官方提供的node包有问题 后来我用python实现了一遍 不报错但就是插不进去🙂 一查只有99条

所以在启动之前把chroma-hnswlib版本降下来!!! 可能会有提示版本不兼容 无需理会

pip install chroma-hnswlib==0.7.3 -i https://pypi.tuna.tsinghua.edu.cn/simple

看一下版本降下来没有

pip show chroma-hnswlib

开始安装node插件包

安装chromadb 和 chromadb-default-embed

npm install --save chromadb chromadb-default-embed

插入示例

import { ChromaClient } from "chromadb";
//path 是chroma启动的客户端地址默认是8000
const client = new ChromaClient({path: "http://localhost:8000"});
//name 是集合名 getOrCreateCollection 查询集合没有就创建集合
const collection = await client.getOrCreateCollection({ name: "test-8" }); 
//根据id进行更新插入 有就更新没有就添加 这里如果说没有对 chroma-hnswlib进行降级每个集合插入99条之后客户端就会崩溃
await collection.upsert({ids: ["id1", "id2", "id3"],  metadatas: [ { chapter: "3", verse: "16" },{ chapter: "3", verse: "5" },{ chapter: "29", verse: "11" },],documents: ["i am ggbond", "she is cat", "he is dog"],
});

查询示例

当然还有其他查询参数可以查看官网

await collection.query({queryTexts: ["Who is a dog"],nResults: 10, //返回前10条
})

然后就可以拿着这些数据作为提示词给DeepSeek做参考回答用户问题了

以上示例是最基础的默认的embeddings模型是 all-MiniLM-L6-v2 所以不用传embeddings也是可以的虽然说可能对中文的调教不是很好 当然也可以自定义embeddings模型 下面有示例

综合示例 结合 langchain 文件分割插入数据库

我这里用了langchain提供的包方便一些

文档地址 langchainChroma 

npm i langchain @langchain/community @langchain/core chromadb pdf-parse 

const { Chroma } = require("@langchain/community/vectorstores/chroma");
const { HuggingFaceTransformersEmbeddings } = require("@langchain/community/embeddings/huggingface_transformers");
const { PDFLoader } = require("@langchain/community/document_loaders/fs/pdf");
const { TextLoader } = require("langchain/document_loaders/fs/text");
const { DocxLoader } = require("@langchain/community/document_loaders/fs/docx");
const { EPubLoader } = require("@langchain/community/document_loaders/fs/epub");
const { RecursiveCharacterTextSplitter } = require("langchain/text_splitter");
//加载模型 其实不用这一步也可以 有默认的模型的 主要是提示一下可以通过model使用自定义模型
const allMiniLML6V2 = new HuggingFaceTransformersEmbeddings({model: "Xenova/all-MiniLM-L6-v2",
});
//文档分割
async function documentReading(filepath, filename) {let mimeType = filepath.split(".")[1];console.log("文件类型", mimeType);//加载分块const splitter = new RecursiveCharacterTextSplitter({chunkSize: 500, //500字符一分割 这个参数可能影响最终查询的质量 根据自己实际情况来});// 加载const loader = this.documentClassification(filepath, mimeType);console.log("文档读取");const docs = await loader.load();// 分割const splitterDocs = await splitter.splitDocuments(docs);console.log(splitterDocs, "文档分割完成");return { splitterDocs };
}
//文件分类加载
function documentClassification(filepath, mimeType) {if (!filepath) throw new Error(`路径出现问题:${filepath}`);let loader = null;switch (mimeType) {case "pdf":loader = new PDFLoader(filepath);break;case "epub":loader = new EPubLoader(filepath);break;case "txt":loader = new TextLoader(filepath);break;case "docx":loader = new DocxLoader(filepath);break;default:break;}if (!loader) throw new Error(`无法解析的类型:${mimeType}`);return loader;
}
// 查询
async function query(collectionName, queryText) {const vectorStore = new Chroma(allMiniLML6V2, {url: "http://localhost:8000", //客户端地址collectionName, //  注意 集合名 一般都是文件名的英文 filename 我这里随便写的});return await vectorStore.similaritySearch(queryText, 2);
}
// 上传示例
documentReading(filepath, filename).then(({ splitterDocs }) => {const vectorStore = new Chroma(allMiniLML6V2, {url: "http://localhost:8000", //客户端地址collectionName: "test", //  注意 集合名 一般都是文件名的英文 filename 我这里随便写的});//二次分割 文件比较大的话插入会很卡const chunkSize = 20;const chunkedDocs = Array.from({length: Math.ceil(splitterDocs.length / chunkSize),},(_, index) => splitterDocs.slice(index * chunkSize, (index + 1) * chunkSize));// 开始插入chunkedDocs.forEach(async (docs, index) => {await vectorStore.addDocuments(docs).then((res) => {console.log(index, "插入成功");}).catch((err) => {console.log(index, "插入失败");});});
});

补充关于自定义模型

const allMiniLML6V2 = new HuggingFaceTransformersEmbeddings({ model: "Xenova/all-MiniLM-L6-v2", });

再进行这一步的时候可能因为下载的地址在国内访问会导致很慢

可以在node_models 下 @xenova/transformers/src/env 文件下remoteHost 地址更换为国内镜像地址 https://hf-mirror.com/

或则直接在.cache文件下加你下好的模型 Xenova/all-MiniLM-L6-v2 就是 .cache/Xenova/all-MiniLM-L6-v2

结束

剩下和DeepSeek对接需要根据每个人的项目来

chromadb只能作为检索工具来作为提示词为AI提供额外的定制化数据 来增强 AI

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/32270.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeeCode题库第五十二题

52.N皇后 项目场景: n 皇后问题 研究的是如何将 n 个皇后放置在 n n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。 示例 1: 输入:n 4 输出:2…

48. 旋转图像(C++)

题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]…

Ragflow技术栈分析及二次开发指南

Ragflow是目前团队化部署大模型+RAG的优质方案,不过其仍不适合直接部署使用,本文将从实际使用的角度,对其进行二次开发。 1. Ragflow 存在问题 Ragflow 开源仓库地址:https://github.com/infiniflow/ragflow Ragflow 当前版本: v0.17.0 Ragflow 目前主要存在以下问题: …

【医院成本核算专题】8.大数据与医院成本核算的关联点:开启医疗成本管理新时代

医院成本核算、绩效管理、运营统计、内部控制、管理会计专题索引 一、引言 在当今数字化飞速发展的时代,大数据已成为各行业变革与发展的关键驱动力。自 2011 年麦肯锡公司提出 “大数据时代” 以来,数据量呈爆发式增长。据 IDC 统计,2011 年全世界创建和复制的数据总量达…

QT:串口上位机

创建工程 布局UI界面 设置名称 设置数据 设置波特率 波特率默认9600 设置数据位 数据位默认8 设置停止位 设置校验位 调整串口设置、接收设置、发送设置为Group Box 修改配置 QT core gui serialport 代码详解 mianwindow.h 首先在mianwindow.h当中定义一个串口指…

C# Enumerable类 之 集合操作

总目录 前言 在 C# 中,System.Linq.Enumerable 类是 LINQ(Language Integrated Query)的核心组成部分,它提供了一系列静态方法,用于操作实现了 IEnumerable 接口的集合。通过这些方法,我们可以轻松地对集合…

网络安全 api 网络安全 ast技术

随着应用或者API被攻击利用已经越来越多,虽然来自开源组件的漏洞加剧了这一现象的发生,但是,其实主要还是在于应用程序或者API本身没有做好防范,根源在于源代码本身的质量没有严格把控。AST是指Application Security Testing&…

【2025前端高频面试题——系列一之MVC和MVVM】

前端高频面试题——系列一之MVC和MVVM 前言一、MVC的基本逻辑二、MVVM的基本逻辑总结 提示:片尾总结了要点,硬背的话直接跳到最后 前言 相信持续关注我文章的小伙伴知道我之前就MVC和MVVM做过较为详细的讲解,但是我发现,他依旧是…

axure11安装教程包含下载、安装、汉化、授权(附安装包)图文详细教程

文章目录 前言一、axure11安装包下载二、axure11安装教程1.启动安装程序2.安装向导界面3.安装协议协议页面2.选择安装位置3.开始安装4.完成安装 三、axure11汉化教程1.axure11汉化包2.axure11汉化设置 四、axure11授权教程1.打开axure112.设置使用方式3.输入许可证号4.axure11安…

Ubuntu 22.04使用pigz多线程快速解压/压缩文件

最近搞项目,资料太大,解压时间太久,于是想办法解决。 开贴记录。 1.安装pigz sudo apt install pigz 2.解压资料 解压命令为 tar --use-compress-programpigz -xvpf ***.tar.gz 将最后的部分***.tar.gz换成你自己的文件即可 例如 ti…

版本控制器Git(3)

文章目录 前言一、分支管理策略二、Bug分支管理遇到Bug时的处理方法使用 git stash 暂存工作区内容创建并切换到Bug修复分支恢复之前的工作 三、临时分支的删除总结 前言 我们在上篇讲到了分支,现在我们就着这个继续来讲解! 一、分支管理策略 master分支…

pytest+allure+jenkins

本地运行参考:pytestallure 入门-CSDN博客 jenkins运行如下: 安装插件:allure 配置allure安装目录 配置pytest、allure 环境变量 配置流水线 进行build,结果如下 ,点击allure report 查看结果

AI术语整理(持续更新)

在AI相关的学习和使用中,经常会被各种术语混淆,搞清楚术语本来的含义是关键,本文收集整理了部分AI相关术语,会持续更新。 基础概念 人工智能(Artificial Intelligence,AI):一种模…

【蓝桥杯单片机】第十一届省赛

一、真题 二、创建工程 1.在C盘以外的盘新建文件夹,并在文件夹里面创建两个文件夹Driver 和Project 2.打开keil软件,在新建工程并选择刚刚建好的project文件夹,以准考证号命名 3.选择对应的芯片型号 4.选择否,即不创建启动文件 …

GMT绘图笔记:用深度作为表面高度(Z 值),用其他物理量(泊松比)给表面着色

之前用GMT绘制莫霍面的三维示意图是用的莫霍面的深度作为表面着色。 GMT绘图笔记:绘制堆叠三维图_gmt画图-CSDN博客 如果要换成其他的物理场,比如泊松比,则需要使用以下的代码 gmt begin BS_figures2 png,pdf E600 # 绘制底图 # Chistrong…

docker搭建elk

文章目录 1.拉取镜像2.ES配置3.logstash配置4.kibana配置5.创建自定义网络6.docker-compose.yml文件7.springboot对接Logstash1.创建一个springboot项目引入主要依赖2.application.yml配置3.resources目录中新增logback-spring.xml4.启动项目,搞点日志5.进入kibana控…

golang算法快慢指针

876. 链表的中间结点 给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 示例 1: 输入:head [1,2,3,4,5] 输出:[3,4,5] 解释:链表只有一个中间结…

瑞云渲染专访奥斯卡提名制片人兼女性动画人协会副主席Jinko Gotoh!

都说CG行业男多女少,女同胞都是珍稀资源,但艺术领域怎么可以没有女性视角呢?本期推文我们邀请到了动画行业资深大佬后藤纯子Jinko Gotoh,作为奥斯卡提名制片人兼女性动画人协会副主席,后藤纯子始终以多元文化倡导者与创…

道路运输安全员考试:备考中的心理调适与策略

备考道路运输安全员考试,心理调适同样重要。考试压力往往会影响考生的学习效率和考试发挥。​ 首先,要正确认识考试压力。适度的压力可以激发学习动力,但过度的压力则会适得其反。当感到压力过大时,要学会自我调节。可以通过运动…

卡尔曼滤波算法从理论到实践:在STM32中的嵌入式实现

摘要:卡尔曼滤波(Kalman Filter)是传感器数据融合领域的经典算法,在姿态解算、导航定位等嵌入式场景中广泛应用。本文将从公式推导、代码实现、参数调试三个维度深入解析卡尔曼滤波,并给出基于STM32硬件的完整工程案例…