我这个月把B站收藏夹里四百多个吃灰视频变成了一套能直接对话的知识库。说白了就是把收藏的视频字幕、弹幕、简介全部拉下来做成分片、向量化再交给大模型你可以直接用自然语言问它“哪个视频讲过Nginx反向代理怎么配”它给出答案的同时还会告诉你出自哪个视频、大约在第几分钟。整套流程用开源工具和Python就能跑通个人玩成本几乎为零。这件事解决的真实痛点是收藏夹只能按标题模糊搜索根本没法按语义找内容视频里全是干货但你检索不到。适合收藏重度用户、知识管理爱好者以及想从零手搓一套RAG系统实战的开发者。1. 别急着写代码一个收藏夹为什么值得做成知识库1.1 收藏夹的本质重收藏、轻检索几乎所有B站用户都有同一个病看到好视频先收藏然后就没有然后了。收藏夹膨胀到几百个视频之后它本质上已经不是一个“知识库”而是一堆按时间排序的链接。你需要找某条内容时只能靠标题关键词碰运气而视频真正有价值的部分是在音频和画面里搜索引擎既钻不进去也不会帮你做语义匹配。我自己就是因为一次痛苦的经历才下决心做这件事。当时想找一个之前收藏过的、讲系统dmesg日志排查的视频标题里既没有“dmesg”也没有“排查”我只记得博主当时用了一个很有意思的案例。结果翻收藏夹翻了半小时最后放弃了。那半小时的时间如果交给一套语义检索系统大概不到一分钟就能给出答案。把收藏夹变成知识库本质上是做三件事把视频里的内容变成文本把文本组织成可检索的索引再通过对话式交互把结果交还给你。B站天然具备这个条件——大量视频自带CC字幕或AI字幕弹幕也在元数据也在相当于平台已经帮我们做了音视频转写我们要做的只是把这些素材结构化。1.2 RAG到底是什么给大模型递参考资料的机制这个项目最核心的技术就是RAG全称Retrieval-Augmented Generation检索增强生成。名字很唬人原理其实很朴素大模型不是所有知识都知道尤其不知道你收藏夹里这些具体视频讲了什么。但你可以在它回答问题之前先从你的库里检索出最相关的几个片段把这些片段作为参考资料塞进上下文让它“开卷作答”。打个生活比方。你请了一个学识渊博但容易胡编乱造的助手你不能指望他什么都凭空知道。于是你先翻了一遍书架把相关的那几页折好角放到他桌上明确告诉他回答只能依据这几页内容找不到就说不知道。这一整套“翻书架、折角、递材料、监督作答”的过程就是RAG。那为什么不是微调微调意味着要让大模型把收藏夹里的内容背进参数成本高、周期长、每次收藏新视频还得重新训练个人项目根本划不来。RAG则是把知识放在外部“资料库”里收藏了新视频只需要更新索引模型本身不用动。再加上这个场景的典型问题都是“某视频里提过什么”、“怎么做某件事”答案往往锚定在一段具体内容上检索的精准度比模型“硬背”可靠得多。那为什么不用纯关键词搜索关键词搜索在今天的信息环境里基本已经被语义搜索碾压了。你说“NGINX 502排查”收藏的视频标题里可能只有“网关排错实录”两种表述没有共同词但语义高度相关。RAG靠向量检索可以跨词面找到相关内容这正是收藏夹检索最需要的。2. 系统架构从收藏夹到可对话知识库的完整链路2.1 五层架构与数据流动整个系统我按数据流向拆成五层任何环节出了问题都可以单独定位。一开始没按这个思路做导致后面调试时到处抓瞎这里直接把成熟的分层结构写出来。第一层是数据获取层。负责调用B站的开放接口拿到收藏夹列表、视频基本信息、字幕、弹幕。这层解决的问题只有一个如何稳定、合规地把用户自己账号下的收藏数据取下来。第二层是解析清洗层。B站返回的字幕是JSON弹幕是XML夹杂大量重复、无意义内容。这层要做的是把它们解析成结构化文本保留时间戳、视频标题、UP主等关键元数据同时过滤噪声。第三层是索引构建层。把清洗后的文本切分成固定片段用Embedding模型转成向量写入向量数据库。这层决定了后面检索质量的上限也是全项目踩坑最多的环节。第四层是检索对话层。收到你的问题时先转成向量到向量库里召回候选片段再拼装上下文交给大模型生成回答。为了让回答有出处检索层还要承担来源标记的工作。第五层是交互展示层。一个最简单的Gradio页面输入框、输出框、来源列表就足够用了。每层之间通过标准化的数据格式传递。前一层输出的是“一条带元数据的文本记录”后一层只依赖这种结构不关心数据来源是字幕还是弹幕。这种松耦合设计让我后面想加评论、加视频简介都只动了第一层和第二层索引层和对话层完全不用改。2.2 模块选型为什么是字幕、ChromaDB、本地Embedding选型是整个项目里最值得动脑的部分因为每一步都有替代方案但替代方案往往意味着更多的成本或更差的效果。数据源我优先选字幕而不是自己跑语音识别。B站视频很大一部分带AI字幕或CC字幕这些字幕虽然不是100%准确但足以支撑语义检索。如果自己跑ASR转写四百个视频意味着几十小时的GPU算力和一堆需要处理的音频文件个人项目很容易卡在这一步就弃坑。我实测下来B站AI字幕对技术类视频的准确率足够高错误主要出现在专业名词和英文缩写上但RAG检索并不要求文本完美只要能召回正确片段就行。向量数据库我选了ChromaDB而不是Milvus或FAISS。核心原因是个人项目的规模决定了一切按我的估算几百个视频分块后也就是几千条向量ChromaDB作为嵌入式数据库零部署成本支持持久化API简洁完全够用。FAISS虽然快但它本质上是一个索引库还要自己管理元数据存储和持久化Milvus则是更重的基础设施适合多用户和生产环境个人项目用了反而添乱。Embedding模型我选了本地的bge-m3。原因很简单数据隐私好、中文效果好、不用为每次Embedding调用付费。这套系统全程不依赖外部API也能跑通就算哪天不想接大模型API了本地跑一个小参数量的对话模型配bge-m3依然能形成一个完全离线闭环这是我很看重的独立性。2.3 数据量预估先算清楚再动手动手之前我做了一个粗算这一步帮我在选型上省了很多弯路。假设平均每个视频30分钟字幕按5分钟一个片段切一个视频大概6个chunk四百个视频约2400个chunk每个chunk五百字左右全库总文本量一百二十万字上下。2400条向量哪怕每个向量1024维存储开销也不到20MB。这个量级ChromaDB跑检索单次响应在几十毫秒级别几乎不需要优化。如果收藏夹有几千个视频chunk数量大概到三万左右ChromaDB依然能顶住。但如果你要处理几万个视频、百万级chunk就必须升级到Milvus这类分布式向量库同时还要考虑分片和索引压缩。这个估算过程解释了为什么我敢用轻量方案不是因为它听起来简单好用而是规模预算告诉我“够用”。3. 数据采集实战收藏夹、字幕、弹幕一个都别少3.1 拿到收藏夹全量视频列表B站有一个公开的收藏夹内容接口只要带上登录后的Cookie就能拿到自己收藏夹下的视频列表。接口路径是/x/v3/fav/resource/list关键参数是media_id、pn页码、ps每页数量。media_id可以从收藏夹页面URL里直接看到pn从1开始翻页ps最大只能取20所以视频多了要循环翻页。下面是我跑通的简化代码重点在请求头里的Cookie和Referer少了后面两个接口大概率返回需要登录的错误码。import requests def fetch_fav_list(media_id, cookie, max_pagesNone): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Referer: https://www.bilibili.com/, Cookie: cookie, } page 1 videos [] while True: resp requests.get( https://api.bilibili.com/x/v3/fav/resource/list, headersheaders, params{ media_id: media_id, pn: page, ps: 20, platform: web, }, timeout10, ) data resp.json() if data.get(code) ! 0: break items data[data][medias] for item in items: videos.append({ bvid: item[bvid], title: item[title], author: item[upper][name], duration: item[duration], intro: item.get(intro, ), fav_time: item[fav_time], }) # 判断是否还有下一页 if data[data].get(has_more) 0 or (max_pages and page max_pages): break page 1 return videos注意返回结构里intro就是视频简介它的文本质量比字幕更干净我后面把它作为高优先级检索来源。这个接口每页只给20条四百个视频要翻20次但接口响应很快控制好频率十几秒就能全部拉完。3.2 字幕抓取B站提供的现成文本不用白不用字幕获取是整个项目里最核心的一步因为它直接决定了知识库的“内容质量”。B站的字幕分为CC字幕UP主上传或平台生成的和AI字幕视频AI自动识别的两者在接口返回里都有优先选lan为“zh-CN”且subtitle不为空的那条。流程有两步。第一步拿bvid换cid一个视频的唯一标识第二步带着cid去字幕接口拉字幕列表。这里我用一个非常经典的B站播放器信息接口/x/player/v2返回结构里data.subtitle.subtitles就是可用字幕列表。每项里有字幕的下载地址和语言代码。def fetch_subtitle(bvid, cid, headers): player_url https://api.bilibili.com/x/player/v2 resp requests.get( player_url, headersheaders, params{bvid: bvid, cid: cid}, timeout10, ) data resp.json() subtitles data[data][subtitle][subtitles] if not subtitles: return None # 优先中文 for sub in sorted(subtitles, keylambda x: x[lan] ! zh-CN): sub_resp requests.get(sub[subtitle_url], headersheaders, timeout10) return sub_resp.json() # body是字幕片段列表 return None字幕接口返回的JSON结构有点像这样body是一个数组每个元素包含from开始时间单位秒、to结束时间、content文本。我需要把浮点时间转成MM:SS格式存起来比如from754.32转成12:34这样后面在对话回答里能直接给出“在第12分34秒提到”。这里有个特别容易踩的坑部分字幕URL是带签名的直接用浏览器里的Cookie不一定能下载需要复用浏览器请求头里的完整Cookie和UA并且某些URL还要求带Referer为视频页面地址。我最初测试时复制了零散的Cookie结果字幕拉下来一堆401错误。解决办法是打包一套完整的请求头尤其别漏掉浏览器默认带的Accept、Accept-Language这些字段。3.3 弹幕价值与噪声的平衡弹幕是B站内容的特色但对于RAG知识库来说它的定位比较尴尬。弹幕能反映视频里的“梗”和用户关注点可绝大多数弹幕是“哈哈哈哈”“前方高能”“666”这种噪声直接进索引不仅帮不上忙还会把向量空间搅乱。我试过两种处理方式。一种是全量抓取弹幕放进索引结果检索召回经常出现莫名其妙的“名场面”片段对正经问题帮助极小。第二种是加一层清洗规则过滤掉长度小于4个字符的弹幕、去除纯“哈”和“6”的重复文本、过滤带举报率高的屏蔽词时间轴上按弹幕密度聚簇密度大的地方代表高能片段可以作为辅助标签加进元数据。最终我的取舍是弹幕不进向量索引但会把高能弹幕所在的时间点存成“高能标记”作为字幕片段元数据的一个字段。这样既不影响检索精度又能让对话系统在回答“这个视频哪里最好笑”这类主观问题时给出有弹幕依据的建议。如果想省事直接丢弃弹幕也完全不影响核心功能的闭环。3.4 采集合规与风控避坑先说一句重要的整个项目只应该采集你自己账号下能看到、你自己收藏的公开数据而且只用于个人学习研究不要公开传播抓取的内容。B站的服务条款对批量抓取有限制这里强调几件事。一是Cookie有效期很短。B站登录态通常几天就会失效实测中收藏夹接口经常返回-101未登录或-412请求被拦截。遇到这种情况不用慌重新打开浏览器登录一次把新的Cookie替换到配置里即可。我建议把Cookie写进配置文件不要反复硬编码在代码里。二是请求频率一定要克制。翻页接口可以循环调用但我额外加了0.5秒到1秒的随机延时批量字幕下载时每两个请求之间sleep 0.3秒。这样跑下来四百个视频大概耗时二十分钟虽然慢一点但换来的是稳定的成功率。千万不能不加延时并发猛拉那样很容易触发风控连正常网页访问都可能被临时限制。三是字幕URL的签名时效。有些字幕链接在获取后短时间内有效不要先把列表存成JSON、过了好几个小时再去下载那样大概率会遇到签名过期。正确做法是拿到字幕URL后立刻下载内容并落盘。4. 从字幕片段到向量索引分块、Embedding、向量库的选型与硬经验4.1 字幕清洗与结构化时间戳是灵魂如果说采集是体力活清洗就是真正的技术活。B站字幕的原始JSON虽然工整但直接拿来做索引很不靠谱。首先是大量字幕内容是重复的尤其是AI字幕经常在一两秒内重复输出同一句话其次是单条字幕文本太短很多时候只有几个字单独向量化几乎没有语义信息。我的清洗管线按顺序做四件事按视频ID和字幕ID去重把时间上连续、内容语义相近的短句合并过滤掉包含“字幕由AI生成”这类纯声明文本最后统一编码格式、去掉空行。清洗时一定要把时间戳保留下来这是这个项目的关键设计。原因在于知识库最终要给用户可验证的答案如果只返回“来自某视频”而没有具体时间点用户仍然不知道去哪看原始内容。所以我的每条清洗结果都会写成一个字典结构{video_title: ..., video_url: ..., author: ..., start_time: 12:34, text: ...}后面向量化和检索都带着这份元数据走。4.2 分块策略按时间窗口聚合而不是一刀切分块是RAG项目里决定性的一环我在这上面做过好几轮实验。最开始我图省事直接按字幕条一条一条向量化结果检索效果非常差用户的问题是“如何排查CPU负载异常”召回的字幕全是零散句子什么“这个命令看一下”“然后分析这里”上下文根本不够大模型回答。后来我改成了按时间窗口聚合。具体做法是定一个窗口长度比如5分钟把落在同一个窗口里的所有字幕文本合并成一个大片段相邻窗口之间再叠加一定重叠比如30秒防止知识点正好被窗口边界切断。这样做的依据是视频的一个完整知识讲解通常持续几十秒到几分钟单独一句话不足以回答问题而5分钟的窗口基本能覆盖一个知识点的完整表述。我给的窗口参数可以用一个简单规则来调整如果你的收藏夹以长视频为主窗口可以放到8到10分钟如果以短视频为主窗口缩到2到3分钟。重叠比例一般取窗口的10%到20%太大浪费token太小容易切掉上下文。分块之后还有一个关键步骤片段级去重。由于视频可能重复引用同一段落文本尤其是AI字幕会在不同句间重复我计算了一下约10%的片段属于重复内容。去重方法很简单对片段文本取哈希只保留第一次出现的版本更精细一点可以做MinHash去重但对个人项目来说哈希已经够了。4.3 Embedding模型与向量数据库选型Embedding的任务是把文本变成一组浮点数向量语义相近的文本在向量空间里距离也近。我选用的是BAAI/bge-m3支持中文输出1024维向量。这类模型可以通过sentence-transformers库一条命令加载而且本地推理速度很快我笔记本CPU跑几百个片段也就是十几秒的事。from sentence_transformers import SentenceTransformer model SentenceTransformer(BAAI/bge-m3) def embed_texts(texts): # normalize_embeddings会让后续余弦相似度计算更稳定 return model.encode(texts, normalize_embeddingsTrue, show_progress_barTrue)向量库我用ChromaDB因为它就是一个Python库不需要单独启动服务。下面是写入索引的示例注意我额外加了一个where过滤器元数据方便后续只检索某位UP主的视频。import chromadb client chromadb.PersistentClient(path./bili_kb) collection client.get_or_create_collection( namebili_fav, metadata{hnsw:space: cosine}, ) collection.add( ids[str(i) for i in range(len(chunks))], documents[c[text] for c in chunks], metadatas[{ video_title: c[video_title], video_url: c[video_url], author: c[author], start_time: c[start_time], } for c in chunks], embeddingsembed_texts([c[text] for c in chunks]), )如果没条件跑本地模型也可以用OpenAI的Embedding接口或者云厂商的中文向量模型效果都很好但每次调用都要花钱。本地模型的好处是一次加载、无限次使用而且数据不出机器对个人知识库这种敏感场景更友好。4.4 索引构建与增量更新索引构建不是只跑一次就完事因为你的收藏夹会持续更新。我需要考虑增量更新。最简单的方式是给每条向量设一个“视频BVID片段序号”的ID每次构建时先查一下已存在的ID集合只对新增视频做向量化已存在的片段直接跳过。这里有一个细节很容易被忽略ChromaDB的collection.get()可以传ids去重判断但如果视频被删除、或UP主改了标题旧片段会残留。我因此加了一个“全量重建”的开关每周跑一次完整清空重建增量更新则每天跑一次。重建的代价其实不高按前面估算的全库两千多个chunk重构索引加向量化十分钟内就能完成完全能接受。向量化结果的缓存也很重要。我踩过一次坑有一次清理了数据库第二天增量更新时发现Embedding模型重新加载花了好几分钟之后还重复跑了所有旧片段。解决办法是把Embedding结果按片段哈希存在本地文件里重跑时用哈希文件直接跳过已经算过的部分这样增量更新几乎能做到秒级。5. 检索与对话模块让回答有据可查5.1 检索链路召回、过滤、重排检索链路是整个RAG系统给大模型“递资料”的关键环节。我的实现分四步先对用户问题做Embedding然后从向量库召回候选片段再做来源和相似度过滤最后对候选做重排只保留最相关的内容进入Prompt。召回阶段我把n_results设置成8到10个因为候选稍微多一点才能覆盖不同类型的问题。但召回多了会出现相似片段扎堆的问题比如同一个视频的两个相邻窗口都命中了造成上下文重复。我的过滤逻辑是同一个视频最多保留两个候选片段优先保留相似度高的如果两个候选来自同一个视频且时间重叠只保留时间靠前或文本更完整的那一个。这样做能显著降低大模型读重复内容的比例。相似度阈值也很重要。按我的测试bge-m3在余弦相似度0.35以下基本就是无关内容0.5以上才比较可靠。实际阈值定在0.45比较稳妥既能过滤噪声又不会漏掉部分表达不同的答案。重排阶段我尝试过两种方案。简单方案是按相似度从高到低排序直接取前3到5条效果已经不错进阶方案是用bge-reranker这类重排模型它能计算“问题-片段”的语义匹配分数比向量相似度更准。个人项目我不建议一开始就上重排模型先用简单的排序跑通闭环效果不够再上重排避免引入额外模型的复杂度。5.2 提示词设计把参考片段变成有出处的回答RAG的最终效果一半取决于检索质量另一半取决于Prompt怎么写。我的核心要求是回答必须基于参考片段禁止编造回答必须带来源如果没有相关内容直接承认不知道。我用的系统提示词大致长这样你是一个基于用户私人收藏视频内容的知识助手。你会收到用户的问题和若干参考片段每个片段包含视频标题、UP主、视频URL和出现时间。 回答要求 1. 优先依据参考片段回答不要使用片段之外的其他知识。 2. 如果参考片段中没有答案明确回复“收藏夹的视频里没有找到相关内容”。 3. 回答必须简洁保留关键步骤和细节。 4. 每段关键结论后面标注来源格式为来自《视频标题》约12:34。 5. 多个片段信息冲突时如实列出冲突。 用户问题{question} 参考片段 {context}这套提示词里最有用的就是“格式为来自《视频标题》约12:34”它强制大模型把答案来源写清楚而不是笼统说“我了解到”。用户拿到时间点之后可以回到B站看原视频验证这种可溯源体验是纯生成模型给不了的。片段拼装也有一些讲究。我的做法是把候选片段按相似度从高到低排列每条以“标签”开头例如[片段1] 来自《xxx》UP主xxx约12:34具体内容。这样大模型在阅读时能自然把来源和时间点绑定到内容上输出引用时也不太容易出错。5.3 模型部署与对话界面集成LLM的选型我给两条路线。一条是直接调用云端大模型API比如你常用的OpenAI兼容接口优点是无脑、回答质量高缺点是要联网、按token付费。另一条是本地部署例如用Qwen系列或ChatGLM系列跑在显存足够的显卡上隐私性好但回答质量和推理速度会受硬件限制。我做的时候是先接API跑通闭环确定检索和提示词都调好了再切到本地模型。这样可以避免一上来就在本地模型上调试结果分不清到底是检索问题还是模型能力问题。界面用了Gradio两百行代码就搞定。界面核心就三样输入框、输出区、来源表格。Gradio可以直接接收向量库检索结果把来源列表渲染成表格用户体验比纯命令行好太多。如果愿意花些时间用Streamlit做也行两者差别不大看个人习惯。下面是简单的对话接口示例逻辑不是完整项目但能表达清楚结构def answer(question): query_vec embed_texts([question]) hits collection.query( query_embeddingsquery_vec, n_results8, ) # 过滤、重排、组装context context assemble_context(hits) messages [ {role: system, content: system_prompt}, {role: user, content: f问题{question}\n参考片段\n{context}}, ] reply llm_chat(messages) return reply, hits6. 常见问题与排查技巧实录6.1 高频问题速查表我把实际运行中遇到的高频问题整理成了下表方便直接对照排查。问题现象根因解决方案收藏夹接口返回-101Cookie过期或未登录重新登录并更新Cookie检查请求头是否完整收藏夹接口返回-412请求频率过快或风控拦截降低并发加随机延时检查Referer和UA字幕列表为空视频本身没有CC/AI字幕跳过该视频或后续用ASR转写不影响整体字幕下载401字幕URL的签名或Referer缺失携带完整浏览器请求头并立即下载检索结果全是噪声文本清洗不彻底或分块窗口过小清理重复弹幕字幕加大分块窗口并增加重叠回答引用错误视频候选片段扎堆同一视频且上下文重复每个视频限制最多两个候选增加相似度阈值回答明显在编造Prompt没强调“仅依据片段”在系统提示词里明确禁止使用片段外知识本地Embedding加载慢模型文件大未做缓存启动时只加载一次向量结果按哈希缓存到本地新收藏的视频查不到索引未更新运行增量更新脚本只对新视频做向量化6.2 我踩过的几个大坑第一个坑是字幕文本直接入索引没有做分片合并。最开始每个字幕条单独作为一篇文档结果检索出来的都是残缺句子。这个问题花了我两个晚上才意识到核心现象是“检索命中的内容看起来相关但大模型回答缺上下文”。后来翻看了十几个视频的字幕才确定是分块粒度的问题。第二个坑是B站收藏夹接口的“has_more”字段判断。这个字段在最后一页时会返回0但某次网络请求超时导致它返回了None我的循环判断while data[data][has_more] 1直接崩了。后来我改成先判断data和data[data]是否存在再加get默认值代码健壮了很多。第三个坑是Embedding模型的归一化。ChromaDB默认用余弦相似度但如果embedding前不设置normalize_embeddingsTrue向量长度不一致时计算出来的余弦值会有点漂具体表现是阈值怎么调都不稳定。补上归一化之后阈值一下变得好使了。第四个坑是上下文超长。收藏夹里有些长视频5分钟窗口文本可能达到一千多字一次塞进五个片段再让大模型回答后端很容易报超限。我的对策是拼装Prompt时先估算token超过最大值就只保留相似度最高的前三段再不行就用摘要压缩。这个策略保证系统在极限情况下也不会直接崩。6.3 效果调优经验从答非所问到有理有据如果你搭完发现回答还是不太靠谱先不要怀疑大模型按顺序排查三条链路。先查索引质量随机抽十个视频的字幕看清洗后文本里有没有大段重复、时间戳错乱或乱码。索引是原料原料不干净后面再怎么调都是白搭。再查分块参数用同一批视频分别用不同的窗口大小跑一遍检索人工对比召回片段的合理性。我自己从每字幕块切分改成5分钟窗口之后检索准确率提升非常明显之后又把窗口调到4分钟发现对短视频更友好最终定在5分钟。最后才调Prompt把system prompt里的“必须依据片段回答”改成“只能依据片段回答”把“尽量简洁”改成“保留关键步骤”每次只改一处观察输出变化。这种单变量调试法虽然慢但能确凿地定位是哪个环节拉低了效果。调优到后期我会做一个小型评测集准备二十个关于收藏夹内容的模拟问题每个问题手工标一个期望答案片段。每次改动后跑一遍评测集看命中率变化。这套方法虽然粗糙但比感觉靠谱得多能让我知道自己的系统在一点点变好。我个人在做这个项目时还有一个额外的收获以前收藏夹里的视频对我来说只是“鬼知道我什么时候会看”的负担现在它变成了一个能反复查询的资料库。偶尔随手问一句“我之前收藏过讲Shell数组的视频吗”然后顺着答案跳回原视频那种“原来我当时存了这个”的惊喜感比收藏动作本身更让人踏实。再分享一个可以立刻上手的扩展方向当你把字幕、弹幕、简介、收藏时间都结构化之后这套系统理论上还可以做“收藏夹自动分类”“按UP主聚合问答”“视频要点周报”。收藏夹不再是吃灰列表而是一份可以持续挖掘的个人数据资产。对于刚入门RAG的朋友我建议先拿一个几十个视频的收藏夹跑通最小闭环再逐步加功能不要一上来就追求完美基建。数据会给你最大的正反馈。