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/10/31 22:49:58 阅读更多 →
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/10/28 23:56:35 阅读更多 →
MCU时隙控制技术:解决PWM电机调速抖动与响应延迟

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

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

2026/11/2 6:01:21 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/3 1:09:25 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/2 10:46:11 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/2 10:47:40 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/3 2:27:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/2 10:46:31 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/2 10:46:26 阅读更多 →

日新闻

周新闻

月新闻