
实战派LLM应用札记
Lv.1Open-sourceenthusiast,关注工具与工程实践,技术方向以缓存与高并发为主。持续整理分析方法与可视化、工程化处理流程和可复用的工程方法;重视可维护性、稳定性与协作效率。
发表的评论
我们后来加了一层参数schema校验,不合法就直接打回让模型重生成,最多重试两次,基本能压住大部分乱编字段的情况。不过prompt里最好把每个字段的类型和枚举值写死,别指望模型自己理解。还有个坑是模型偶尔会把嵌套结构拍平,这种校验层也得能兜住。
SSE的keep-alive没配的话,中间层很容易60秒断连,先查这个。
我现在是短期和长期分两个collection,短期那个只留最近N轮,超了就摘要成一条塞进长期,这样检索干扰小很多。时间戳加session_id做filter我也试过,问题是embedding本身不区分时效,filter再准也救不了召回质量。短期过期我一般不是直接删,而是压缩成摘要归档,省得以后想追溯对话线索时啥都没有。你们那边如果用Pinecone,其实可以试试namespace按session隔
官方胜在可控,社区胜在好用,我一般敏感目录只给官方,社区的先看源码再跑。
这个问题我也踩过坑,说点实际感受。把对话历史直接拼进query再检索,基本等于往索引里灌噪声,尤其是历史里出现过相似词但不同意图的时候,召回结果会跑偏得很离谱。我现在更倾向于先做一轮轻量的query改写,但不是让LLM自由发挥,而是限定它只做指代消解和省略补全,比如“那第二个方案呢”改成“XX产品的第二个方案是什么”,这样检索目标明确很多。历史embedding我是不建议跟知识库混在一个索引里的,
我习惯把每步结果单独存state里,别全塞prompt,不然确实容易串。
2000条数据做客服问答确实偏少,loss卡在2.3多半是数据质量和多样性不够,模型没东西可学只能摆烂。你验证集输出重复提问内容,很可能是训练样本里本身就有一堆类似模板,建议先清洗下数据,把重复和低质对话去掉。LoRA rank=8对客服场景可能偏小,可以试试调到16或32,学习率2e-4也有点高,降到1e-4左右更稳。24G跑全量肯定不现实,别折腾了,先把数据和rank调一调看看效果。
vLLM的显存占用确实不能只看模型权重本身。你算的5-6G只是权重部分,但实际跑起来KV cache才是大头,尤其你开了continuous batching之后,vLLM会预分配一大块显存给KV cache池,默认gpu_memory_utilization是0.9,也就是它会尽量把A10的24G吃到九成左右,14G其实还算克制了。想确认的话可以看启动日志里那行"GPU blocks"和"KV
batch size降到1还OOM确实有点离谱,A100 40G跑7B微调按理说没那么夸张。你forward中间层爆显存,大概率是激活值没清干净,可以试试torch.cuda.empty_cache()配合手动del中间变量,或者直接上FSDP把参数和梯度都分片。fp16 loss震荡的话换bf16试试,A100原生支持bf16稳定性好很多,基本不用调loss scale。另外dataloader
我理解的 MCP 更像是给模型和工具之间定的一套标准接口,不是 gRPC 那种纯通信层,重点在工具的发现和调用规范上。你现在 vLLM 加 FastAPI 的架构,MCP Server 单独起进程比较省事,训练脚本里直接嵌会跟推理服务耦合太紧。跟 LangChain 的 Tool 抽象比,MCP 更像跨应用复用的协议层,LangChain 那套还是绑在它自己生态里。建议先把工具注册抽出来独立跑,模
Milvus集群部署挺折腾的,小团队直接上Qdrant省心不少,但数据量大了再迁移也头疼。
int4本来就慢,换vLLM或TensorRT-LLM提速明显,flash attention也值得开。
PDF技术手册有个坑是表格和图文混排,ada-002对这类结构基本没辙,切出来全是碎句子。建议先别急着换模型,拿二三十个badcase手动看看切出来的chunk到底长啥样,大概率能发现问题。bge-large-zh中文确实强不少,但你这场景可能混合检索加rerank比单换embedding收益更大。
stdio最容易踩的坑就是日志混进stdout,把print全改成stderr试试,JSON解析一乱就报invalid request。
试试父文档召回,小块检索大块喂,实体和结论就不会被拆散了。
你提到ONNX输出和PyTorch一致,那基本能排除转换本身的问题,锅大概率在TRT解析ONNX那步。我遇到过类似的,最后定位到是Resize算子被TRT改成了最近邻插值,边缘直接糊掉,建议你把ONNX里所有Resize的mode和coordinate_transformation_mode打出来对一遍。另外BN折叠在TRT里默认会做,但如果有GN或者自定义norm就可能出岔子,可以试着用trte
20万条数据用lists=100有点太粗了,按官方建议大概sqrt(n)来算,200左右才比较合适,聚类太粗确实会漏召回。另外L2在归一化向量上其实和cosine差不多,但bge官方推荐的是cosine,你可以先确认下向量有没有归一化。还有probes=10偏小,试试调到20-30,能明显改善长尾。真要说的话,IVFFlat在高维上确实不如HNSW稳,但你这个量级调好参数应该能救回来。
不同模型向量空间确实不一样,别直接比距离。我一般用测试集跑几组top-k,看召回和噪声的平衡点,硬试最靠谱。
这个问题我也踩过坑,说实话换数据库不是关键,Chroma和Milvus在召回质量上的差距远没有想象中大。你说的“相关但没用”本质上是embedding只算了语义相似度,完全没有时间维度和重要性的概念,上个月的总结和去年的代码片段在向量空间里可能挨得特别近。我的做法是在metadata里存时间戳和来源类型,检索时先做一轮硬过滤再排序,比如限定最近30天或者只搜笔记类的内容,效果立竿见影。另外chun
20 tokens/s确实有点低了,A100跑7B不该是这个水平。你先看下是不是请求batch size太小了,vLLM的吞吐得靠并发撑起来,单条请求测出来的数没太大参考意义。另外docker默认可能没挂上nvidia的完整驱动,可以进容器跑nvidia-smi确认下,还有tensor-parallel-size设对没。建议用benchmark脚本压一下,看实际并发吞吐再判断瓶颈在哪。