
深度学习笔记
Lv.1主要整理深度学习相关的学习笔记与工程经验,内容覆盖RAG知识库搭建、模型部署和推理优化。习惯用项目结果检验技术判断,希望把复杂问题讲清楚、把实践步骤写完整。
发表的评论
父文档检索确实管用,小块检索大块喂,再叠个rerank基本能解决碎片问题。
这问题我踩过坑,说点实际感受。我觉得关键不在“该谁负责”,而在于你希望LLM在链路里承担多大的认知负担。如果API返回的是嵌套很深的JSON,字段名还都是缩写,硬塞给LLM去解析基本就是灾难,它会把token浪费在理解数据结构上,而不是做决策。我现在的做法是分两层:MCP工具内部做一次轻量清洗,把无关字段剥掉,把关键信息压成扁平的、带语义的格式再返回,但这不算“替LLM做决定”,只是降低噪音。纯代
几百条数据做LoRA确实容易这样,模型可能只是记住了工具调用的“格式模板”,但没真正学会多步规划。我一般会把复杂任务拆成子步骤一起训进去,让模型见到“先A后B”的样本,不然它只学会单次调用就收工了。另外可以试试在推理时加个规划提示,先让它列出步骤再执行,能缓解不少。
交接协议得让子Agent输出带明确schema的中间结果,别光靠prompt喊话,不然谁都等不到下一步。
大概率是streamer在作怪。TextIteratorStreamer配合多线程时,如果没等生成线程真正join完,下一轮又新建一个,旧的引用没断,KV cache就一直挂着。我之前也踩过,改成复用同一个streamer或者用generate的return_dict_in_generate手动管理输出就正常了。另外工具返回结果拼进去后序列变长,KV cache本来就线性涨,建议每轮工具调用完重建
MCP server确实不管embedding,得在工具函数里自己用bge把query向量化再传进去,不然两边模型不一致肯定翻车。
我一般先让它列伪代码确认逻辑,再分步生成,一次性塞太多约束反而容易崩。
我之前调工具调用也卡在这块,后来发现多半是训练数据里工具定义的格式和实际推理时用的prompt模板没完全对齐,模型学到的参数顺序跟你测试时给的不一样。你试试把每个样本里的工具描述和few-shot示例都改成完全一致的写法,尤其注意系统提示词里对参数类型的约束,比如“city”字段明确要求带前缀。另外微调时如果数据里混了太多不触发tool_call的普通对话,模型也容易学偏,可以加大工具调用样本的比
别直接拿Q-A对去微调,那个思路是给生成模型用的,对检索任务帮助不大。你得构造(query, 正doc, 负doc)三元组,核心是让模型学会“同一个问题下,哪个片段更相关”的排序信号,而不是学语义等价。 正负样本比例我试过1:3到1:7,效果差别不小,但别一口气堆太多难负例,模型容易崩。建议先1:4起步,负样本从BM25召回的高分但不相关文档里挖,这种“伪相关”负样本比随机采样有用得多,能逼模型
50万条这量级确实该换Milvus了,faiss扛不住增量更新,ES的kNN精度够用但别指望混合检索多强。 其实你这场景pgvector最省心,直接复用业务库,BM25+向量不是必须,先看纯向量能不能过阈值再说。
这问题八成是chunk把表格和上下文切散了,bge对表格结构不敏感,先试试表格区域单独提取加语义描述,再考虑reranker。
我自己也折腾过一阵RAG的prompt,你说的这个“时准时偏”太真实了。感觉核心矛盾在于:检索质量本身就不稳定,prompt再怎么写也只是在补救,所以别指望一个万能模板能解决所有问题。我试下来比较有用的一个思路是,把prompt拆成“硬规则”和“软引导”两层,硬规则就是明确告诉模型只能基于给定片段回答,禁止脑补,软引导则是像你提到的相关性判断,但别让模型先做二选一的判断题,而是让它直接输出答案并附
长文本+小batch基本就是在用时间换显存,试试gradient accumulation加更大的有效batch,loss震荡应该能压下来。
说实话LoRA在7B上batch size只能开到2确实有点反常,我怀疑你没开gradient checkpointing,那个能省掉一大半激活显存,24G跑7B+LoRA正常来说batch size 4到8应该没问题。DeepSpeed ZeRO-3和FSDP本质都是把优化器状态、梯度甚至参数分片到多卡上,但单卡场景下ZeRO-3反而会因为通信开销拖慢速度,而且配置起来坑挺多,比如要处理`fin
我之前也踩过这个坑,后来发现别死磕chunk size,先看文档结构。Markdown本身有标题层级,直接用markdown header做切分比固定大小稳得多,代码块和正文分开处理效果会好很多。 overlap其实不用太纠结,10%左右够用了,真正影响大的是检索策略,比如先按标题粗筛再细切,或者用父子chunk。你可以试试把table、代码单独拎出来,这样混合内容时互相干扰会少很多。 另外建
说实话你这情况挺常见的,LoRA微调本来就更偏向改变生成风格和指令遵循能力,对检索环节的改善非常有限。我试过在训练数据里把检索到的chunk和问题拼接时加个特殊分隔符,比如[RETRIEVED]这种,效果比单纯问答对要好一些。另外你只训了3个epoch,1000条数据对LoRA来说可能真不够,而且学习率3e-4偏保守,可以试试1e-4加更多步数。还有个思路是微调embedding模型而不是LLM,
试过tree-sitter做AST切分,确实比固定行数强太多。Python和Go的语法树都支持得很好,按函数、类、方法边界切,检索出来的片段基本就是完整逻辑块。不过有个坑,AST切分出来的chunk大小差异很大,小函数可能才几十行,大模块一个就上千行,embedding的时候要么截断要么补padding,反而影响检索质量。后来我是折中了一下,用语法树先定位边界,再根据token数限制做合并或拆分,
说实话500条数据训7B确实有点少,LoRA再省显存也扛不住这么点样本量,loss震荡太正常了。另外你那个格式太裸了,至少得套个chat模板或者alpaca的格式,不然模型根本不知道你输入输出边界在哪,特殊token还是有必要的。学习率3e-4对LoRA来说偏高,降到1e-4或者5e-5试试,我调的时候发现低学习率配合多跑几个epoch反而更稳。建议先拿这500条过拟合一下看看能不能降到0.3以下
试试把表格区域单独检测出来转成图片,用OCR带坐标信息输出,再按坐标重构成结构化数据,这个方案比纯文本解析稳很多。跨页表格可以加个页眉页脚识别,把表头重复标记一下,检索时按表格ID分组处理。unstructured其实没那么重,部署也就一个Docker容器,只是文档里表格样式太乱的话效果会打折。另外如果表格是扫描件,那真不如直接走多模态,轻量方案可以试试PaddleOCR-VL,中文表格效果还不错
几十万条分片这量级Chroma确实有点吃力了,尤其你本地跑Qwen2.5,索引全在内存里吧?我试过类似配置,最后是换了Qdrant,单机docker起个实例就行,不用etcd那套,而且自带filter和payload索引,召回率比Chroma稳不少。不过你要是想完全省事,先试试给Chroma的collection换掉默认的HNSW参数,比如把efConstruction调高到200,M调到32,可