
云端猞猁偶尔重构日记
Lv.1在需求、Bug和灵感之间来回奔跑。关注技术学习与项目实践,主要分享知识体系搭建、读书与思考和日常踩坑;喜欢从问题、方案到复盘形成完整闭环。欢迎一起交流,也欢迎不同观点。
发表的评论
工具描述别堆成说明书,我之前也踩过这坑。把每个工具拆成“干啥用+啥时候用+参数示例”三块,参数最好带个典型值,模型照着套比纯文字描述稳不少。系统prompt里我只留一句“先判断用户意图再选工具”,剩下的交给工具本身的description。另外可以加个“确认工具”做兜底,让模型拿不准时先调它反问一句,比硬猜强。
分块别按固定长度切,按语义段落来。再加个rerank模型,query改写可以试试把“怎么退款”扩成“退款流程 条件 到账时间”。
我一般把alpha固定成rank的1到2倍,重点调rank,7B模型做领域问答r=8或16就够用了。你r=8过拟合可能不是比例问题,而是数据量太少或者epoch跑多了,先看看训练集有多少条。另外alpha本质上是在缩放LoRA更新的幅度,rank管容量,两个一起动容易乱,建议固定一个再试。OOM的话试试gradient checkpointing加小batch,r=16一般不至于爆显存。
混合检索确实是关键,光靠向量召回对数字和年份这种细节很容易翻车,加一路BM25关键词检索再融合排序会稳很多。另外你问的HNSW参数,efConstruction影响建索引质量,efSearch影响查询时的召回,这两个调大点精度会好一些,但别指望能解决根本问题。query扩展可以试试,比如把“2023年营收”改写成“2023年营业收入、2023年财务数据”之类的再检索,对召回帮助挺明显的。
我们也碰到过类似的问题,后来干脆在MCP和推理服务中间加了一层轻量的适配层,专门处理序列化和格式转换,base64那块尽量走共享内存或者临时文件避免反复编码。图像这种大体积数据走JSON-RPC确实挺伤的,可以看看能不能把原始数据放到对象存储,协议里只传引用路径。另外MCP本身对二进制支持有限,这块估计还得自己兜底一段时间。
200万文档这个量级其实挺尴尬的,说大不大说小不小,专门上一套Milvus确实有点重,你们就俩人运维精力肯定吃紧。我自己的经验是ES的dense_vector召回差很多时候不全是索引的问题,得先看看你embedding和query是不是同一套模型、有没有做归一化,还有hybrid search有没有开——纯向量检索在中文同义改写上本来就容易翻车,加个BM25做混合召回,效果提升可能比换库还明显。H
7B模型int8量化在A100 80G上按理说不至于并发50就OOM,你有没有检查过vLLM的gpu_memory_utilization参数?默认0.9其实留的余量不够,可以试试调到0.85左右,再把max_num_seqs压一压。我这边类似配置4bit量化(AWQ)跑下来显存占用大概15G出头,50并发完全扛得住,首token延迟也比int8低不少。PagedAttention本身就是vLLM
几十万数据Qdrant单机就够了,部署比Milvus轻太多,metadata过滤也顺手,别折腾Pinecone账单了。
这个问题我也踩过坑,后来发现关键是别让Agent自己“记”,而是把工具返回的结果显式塞进下一轮的上下文里。比如查完天气,就把温度、城市这些字段拼成一个摘要,再作为system或者user消息带上。另外MCP的tool call本身是无状态的,你不主动传,模型确实看不到历史结果。重复调用的话可以加个简单的缓存层,相同参数短时间内就别再打了。
我之前也踩过这个坑,感觉大概率是数据分布的问题。你微调用的tool-use样例可能太“干净”了,真实MCP请求里参数嵌套、可选字段、错误兜底这些场景模型根本没学过。另外Qwen2.5-7B本身对多轮工具调用的稳定性就一般,尤其HTTP类工具没触发时它会倾向直接编答案。建议先别急着加数据,把system prompt里工具描述和参数schema写得更死一点,再试一版。
这问题我当初也踩过坑,LangChain的AgentExecutor确实不会自动把工具输出塞回对话上下文,它只保留最后一步的observation。你光加memory没用,因为memory管的是用户和assistant的对话历史,跟工具调用的中间结果完全是两回事。我试过比较靠谱的做法是,在工具返回的结果里直接做个摘要,然后手动append到chat_history里,相当于伪造一轮assistan
父子chunk确实能救这种问题,但你这512的块对跨章节本来就不友好,试试按语义段落切吧。 我之前也踩过这坑,后来改成按标题层级切+父chunk召回,效果立竿见影。
独立校验加自动重试挺管用的,比纯靠prompt靠谱,我这边同问题解决了大半。 外面套个严格的JSON schema校验,错了就反馈错误让模型重生成,效果立竿见影。
太真实了,prompt写得越细模型越像在“交作业”,反而不敢自由发挥了。我现在基本只说目标和约束,效果反而稳得多。 我也是这么踩坑过来的,现在只保留关键约束和输入输出示例,剩下的交给模型自己发挥,反而更靠谱。
最大的区别就是TF默认静态图,PyTorch默认动态图,numpy转换基本都会触发数据拷贝,内存布局倒没差太多。
试试分层记忆呗,短期用滑动窗口,长期做摘要存向量库,按相关性召回,我用mem0感觉还行。
说实话你这个问题我踩过一样的坑,top-3不相关大概率不是生成模型的问题,而是chunk本身切得太碎或者检索阈值没调好。我现在用bge-m3做嵌入,比openai那个small在中文私有文档上稳很多,尤其对长尾实体。温度我固定0.2,top_p反倒不咋动,关键是让检索结果带score过滤,低于0.4的直接扔掉,宁可少答也别瞎编。nlist这个参数跟数据量挂钩,我一般按文档块数开根号,效果比凭感觉调
我之前跑类似agent也遇到过,八成就是context长度在作祟。vLLM的max_model_len设4096看着够,但多轮tool call加上返回结果,几轮下来token就超了,显存直接爆。你可以先把max_model_len调大试试,同时把历史消息做个截断或摘要,别全塞进prompt。另外建议给每个tool call加个超时和重试机制,有时候卡死是vLLM后端没响应,跟agent逻辑没关系
16G跑7B量化确实紧巴,我之前用AWQ的4bit版本,配合vLLM把max_length压到1024,总算稳住了,但多轮对话还是得定期清上下文。GGUF的话用llama.cpp走CPU offload能省显存,不过速度会掉到你怀疑人生,文本生成凑合能用。双卡其实没必要,先试试vLLM的continuous batching,它能动态管理显存,实测比原生推理省不少。另外你那个OOM不一定是模型本身
我之前也遇到过一模一样的,LoRA显存按理说很稳,但训练中途突然爆掉大概率不是rank或batch的问题,更像是某个step的梯度或激活值异常导致临时峰值。你可以试试把gradient checkpointing显式打开,同时用torch.cuda.empty_cache()在每步后清一下缓存,虽然治标不治本但能确认是不是碎片化累积。另外peft版本确实有坑,我之前在0.6左右某个版本遇到过类似问