Node.js搭建RAG实战:拆解《天龙八部》小说存入Milvus全流程
文章目录前言第一步加载EPUB一行代码拆出168章第二步二次切分保住检索精度第三步向量入库核心四步走3.1 初始化Embedding模型3.2 设计集合Schema3.3 构建向量索引3.4 批量并行插入进阶玩法断点续传翻车也不怕最后说两句P.S. 无意间发现了一个巨牛的人工智能教程非常通俗易懂对AI感兴趣的朋友强烈推荐去看看传送门https://blog.csdn.net/HHX_01前言学RAG这事真的太容易陷入“一看就会一写就废”的魔咒了。前阵子我刷了一堆理论文章什么向量检索、增强生成讲得头头是道真打开编辑器动手才发现坑比想象中多十倍。索性拿《天龙八部》电子书练手硬生生把168章小说拆成了3042个向量片段全塞进了Milvus总算是跑通了完整的数据入库流程。今天就给大伙拆解全程的操作还有我踩过的那些哭笑不得的坑正在入门RAG的Node.js开发者直接照着抄就行。第一步加载EPUB一行代码拆出168章搁以前要处理EPUB电子书那叫一个麻烦。本质就是个ZIP包得自己解压、提取HTML、清洗标签一套流程走下来眼睛都快花了跟给古籍做校对似的。现在不用这么费劲了LangChain的EPubLoader直接把这些活全干了一行代码就能按章节拆分好。import{EPubLoader}fromlangchain/community/document_loaders/fs/epub;constloadernewEPubLoader(./天龙八部.epub,{splitChapters:true,});constdocumentsawaitloader.load();console.log(加载完成, 共${documents.length}个章节);// 输出加载完成, 共 168 个章节开启splitChapters之后它会自动按小说的章节边界切分每个章节都是一个独立的Document对象自带章节号、标题这些元信息省心到不行。这里必须吐槽一个巨坑类名是EPubLoaderP是大写的我当初照着网上老教程抄写的是小写p的EpubLoader跑起来一直报找不到导出。我对着文件路径检查了八遍依赖也重装了两次折腾了半小时才发现就是一个字母大小写的问题。说出来都丢人主打一个千里之堤溃于蚁穴。当然按章节拆分只是第一步。一章动辄几千字直接拿去做embedding效果很差信息太杂检索精度会被稀释得没法看。所以还得再切一刀。第二步二次切分保住检索精度为啥非要把章节再切成小片段道理很简单embedding就像给文本拍“语义照片”一段文字里信息越多越杂特征就越模糊。你拿“段誉会什么武功”去搜一个三千字的章节里面连他喝茶吃饭、跟人聊天的内容都有相似度直接被无关内容拉低搜出来的结果经常八竿子打不着。所以得把每章再切成小片段让每块尽量聚焦一个独立的情节检索才能准。我用的是RecursiveCharacterTextSplitter核心思路就是递归切割先按段落切太长就按行切还长就按空格切直到每块都符合设定的长度。import{RecursiveCharacterTextSplitter}fromlangchain/textsplitters;consttextSplitternewRecursiveCharacterTextSplitter({separator:\n,chunkSize:500,chunkOverlap:50,});小说类的文本按换行切最自然所以我把分隔符设成了换行。每块500字符大概就是一个完整的小情节不会太长也不会太碎。这里重点说下chunkOverlap也就是相邻块的重叠字数这东西真的不能省。你想啊要是刚好把一句关键台词切在两块中间比如“段誉使出凌波微步”前一块末尾是“段誉使出凌波”后一块开头是“微步身形飘忽”。那你搜“凌波微步”匹配不到前一块搜“段誉使出”匹配不到后一块关键信息直接就丢了。就跟看电视剧刚好被广告掐在关键剧情一样不上不下的难受死了。留50字的重叠就能完美避开这个问题。第三步向量入库核心四步走切完片段就到最核心的一步了把文本转成向量存进Milvus。拆成四个环节给大伙讲每个环节都有坑。3.1 初始化Embedding模型我用的是千问的embedding模型兼容OpenAI的接口格式所以直接用LangChain的OpenAIEmbeddings就行以后换模型厂商也不用大改代码。import{OpenAIEmbeddings}fromlangchain/openai;constembeddingsnewOpenAIEmbeddings({apiKey:process.env.VITE_QWEN_API_KEY,model:text-embedding-v3,configuration:{baseURL:https://dashscope.aliyuncs.com/compatible-mode/v1,},dimensions:1024,});说个我踩过的低级坑环境变量名一定要对上我一开始代码里写的是VITE_QWEN_BASE_URL结果.env文件里写的是VITE_QWEN_API_URL拿了个undefined就去发请求直接超时。我一开始还以为是网络炸了换了好几个代理都不行最后定睛一看变量名差点给自己一巴掌。这种低级错误说出来都显得我从业年限注水了。3.2 设计集合SchemaMilvus的集合就相当于关系型数据库的表得提前定义好字段结构。我设计的字段如下亲测实用。awaitclient.createCollection({collection_name:ebook2,fields:[{name:id,data_type:DataType.VarChar,max_length:100,is_primary_key:true},{name:book_id,data_type:DataType.VarChar,max_length:100},{name:book_name,data_type:DataType.VarChar,max_length:200},{name:chapter_num,data_type:DataType.Int32},{name:index,data_type:DataType.Int32},{name:content,data_type:DataType.VarChar,max_length:10000},{name:vector,data_type:DataType.FloatVector,dim:1024},],});这里划个重点content字段一定要加我见过不少新手踩这个坑吭哧吭哧把向量全存进去了一检索返回一堆浮点数人直接傻了。大哥RAG的“R”是检索检索出来的原文是要喂给大模型的你只存向量不存原文跟去图书馆借书只借了个目录似的有啥用啊主键我用的是“书ID_章节号_片段序号”的格式天然唯一后面做断点续传也方便。3.3 构建向量索引向量数据量上来之后不建索引的话每次搜索都全量比对慢得像蜗牛爬。我用的是IVF_FLAT索引十万条以内的数据量用它最合适。awaitclient.createIndex({collection_name:ebook2,field_name:vector,index_type:IVF_FLAT,metric_type:COSINE,params:{nlist:1024},});相似度用余弦相似度文本语义搜索的标配。nlist设成1024是按经验公式4×√N算的三千多条数据刚好合适。3.4 批量并行插入插入数据的时候千万别串行调用embedding接口不然速度慢到你怀疑人生。同一章里的片段之间没有依赖关系直接用Promise.all并行调用接口一章几十条片段只需要等最慢的那一个返回就行效率直接翻好几倍。asyncfunctioninsertChunksBatch(chunks,bookId,chapterNum){constinsertDataawaitPromise.all(chunks.map(async(chunk,chunkIndex){constvectorawaitgetEmbedding(chunk);return{id:${bookId}_${chapterNum}_${chunkIndex},book_id:bookId,book_name:BOOK_NAME,chapter_num:chapterNum,index:chunkIndex,content:chunk,vector:vector,};}));constresultawaitclient.insert({collection_name:ebook2,data:insertData,});returnNumber(result.insert_cnt)||0;}别小看这点优化168章跑下来能省出一整集电视剧的时间。进阶玩法断点续传翻车也不怕跑大批量数据最怕啥怕中途翻车啊。要么token用完了要么网络断了要么电脑突然蓝屏要是没做断点续传前面跑的全白费又得从头再来。embedding API可不是免费的重跑一遍那都是真金白银的损失心疼都来不及。实现起来其实很简单每次跑之前先去数据库里查一下哪些章节已经入库了存到一个Set里循环的时候直接跳过就行。asyncfunctiongetProcessedChapters(bookId){constresultawaitclient.query({collection_name:ebook2,filter:book_id ${bookId},output_fields:[chapter_num],limit:100000,});constchaptersresult.data.map(rr.chapter_num);returnnewSet(chapters);}然后在循环里加个判断constprocessedChaptersawaitgetProcessedChapters(bookId);for(leti0;idocuments.length;i){constchapterNumi1;if(processedChapters.has(chapterNum)){console.log(第${chapterNum}章已处理跳过);continue;}// 正常处理流程}用Set存已处理的章节has查询是O(1)的一百多章毫秒级就能判断完。不管你中途断多少次重跑都从断点继续绝不重复干活。最后说两句整套流程跑下来168章全部入库一共生成了3042个向量片段。现在整本《天龙八部》的“数字记忆”已经躺在向量数据库里了。今天讲的是数据入库的部分下一篇我会接着讲怎么用向量搜索找相关片段再让大模型基于原文生成答案让AI真的能“读懂”《天龙八部》到时候想怎么提问都行。完整的项目代码已经整理好了clone下来改个配置就能直接跑新手也能快速复现。P.S. 无意间发现了一个巨牛的人工智能教程非常通俗易懂对AI感兴趣的朋友强烈推荐去看看传送门https://blog.csdn.net/HHX_01

相关新闻

Claude code Hookify 实践:把团队规则写成可执行的轻量策略

Claude code Hookify 实践:把团队规则写成可执行的轻量策略

团队使用 AI 编码工具时,很多问题并不是模型不会写代码,而是团队规则没有进入执行路径。比如不要运行危险删除命令、不要提交调试输出、不要编辑敏感文件、停止前必须跑测试。这些规则如果只靠口头提醒,很容易在高频开发中失效。 plugins/hoo…

2026/7/31 1:27:59 阅读更多 →
F3D 3D查看器:如何在5分钟内快速上手这款轻量级3D文件查看神器

F3D 3D查看器:如何在5分钟内快速上手这款轻量级3D文件查看神器

F3D 3D查看器:如何在5分钟内快速上手这款轻量级3D文件查看神器 【免费下载链接】f3d Fast and minimalist 3D viewer. 项目地址: https://gitcode.com/GitHub_Trending/f3/f3d 还在为查看3D模型而安装笨重的专业软件吗?F3D(Fast and m…

2026/7/31 1:26:59 阅读更多 →
MCU时隙控制技术:解决PWM电机调速抖动与响应延迟

MCU时隙控制技术:解决PWM电机调速抖动与响应延迟

如果你正在开发需要精确控制电机转速的项目,可能会遇到这样的困境:使用简单的PWM调速时,电机在低速运行时抖动明显,高速时响应不够平滑。这种问题在机器人、无人机、智能小车等对运动控制要求较高的场景中尤为突出。传统PWM控制虽…

2026/7/31 1:26:59 阅读更多 →

最新新闻

HY-Motion+Unity实战:AI驱动3D数字人实时交互动作生成方案

HY-Motion+Unity实战:AI驱动3D数字人实时交互动作生成方案

1. 项目概述:当数字人需要“活”起来最近在做一个虚拟展厅的项目,客户的核心需求是让里面的3D数字人导览员能和访客进行实时问答互动。这听起来很酷,但实现起来第一个拦路虎就是动作——你总不能指望数字人像个木头桩子一样杵在那里&#xff…

2026/7/31 2:16:14 阅读更多 →
Footprint图表与订单流分析:金融交易中的成交量洞察技术

Footprint图表与订单流分析:金融交易中的成交量洞察技术

在金融交易领域,成交量分析是判断市场参与者行为的关键技术之一。Footprint 图表作为一种高级成交量分析工具,能够直观展示每个价格水平上的买卖力量对比,帮助交易者识别潜在的支持阻力位和市场转折点。本文将深入解析 Footprint 交易的核心原…

2026/7/31 2:16:14 阅读更多 →
Python、C++、JavaScript三语言实现猜数字游戏:从核心逻辑到工程实践

Python、C++、JavaScript三语言实现猜数字游戏:从核心逻辑到工程实践

1. 项目概述:为什么选择“猜数字”作为多语言入门示例在编程教学和自学领域,“猜数字”游戏几乎是一个图腾般的存在。它简单到一句话就能说清规则,却又完整地涵盖了输入输出、条件判断、循环控制、随机数生成等核心编程概念。对于初学者而言&…

2026/7/31 2:16:14 阅读更多 →
智能网络资源捕获工具:3步掌握全网数据提取终极秘籍

智能网络资源捕获工具:3步掌握全网数据提取终极秘籍

智能网络资源捕获工具:3步掌握全网数据提取终极秘籍 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 还在为无法下…

2026/7/31 2:16:14 阅读更多 →
Unity资源管理实战:YooAsset核心技巧与热更新全解析

Unity资源管理实战:YooAsset核心技巧与热更新全解析

1. 项目概述:为什么YooAsset值得你投入时间如果你是一名Unity开发者,最近在项目资源管理上感到力不从心,比如热更新流程繁琐、内存管理混乱,或者单纯厌倦了Addressables的复杂配置,那么“YooAsset”这个名字很可能已经…

2026/7/31 2:16:14 阅读更多 →
SpringBoot企业资产管理系统开发实践与架构设计

SpringBoot企业资产管理系统开发实践与架构设计

1. 企业资产管理系统的核心价值与SpringBoot技术选型企业资产管理系统(Enterprise Asset Management System)是现代企业数字化转型的基础设施。作为IT负责人,我经历过从Excel表格到专业系统的转变过程,深知一套好的资产管理系统能…

2026/7/31 2:15:14 阅读更多 →

日新闻

物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:34 阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:34 阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:34 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/31 1:03:03 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻