最近在折腾把本地部署的Qwen2.5-7B接上LangChain做自动化任务,但跑几个tool调用后就卡死,要么显存跑满直接OOM,要么响应越来越慢。我用的vLLM启动,max_model_len设了4096,感觉是不是上下文窗口把显存撑爆了?还是说Agent循环里历史对话太长了?有没有老哥遇到过类似问题?怎么定位是模型推理的问题还是Agent逻辑写崩了?求指导!
部署本地大模型做Agent,模型一直卡死怎么排查?
全部回复
共 7 条遇到过类似的情况,大概率是Agent循环里历史对话把上下文撑爆了。vLLM虽然省显存,但Qwen2.5-7B对长上下文的处理还是吃资源,你可以试试把max_model_len砍到2048,或者手动限制Agent的memory只保留最近几轮对话。另外建议在tool调用前后加个显存监控脚本,看看是不是每次调用都涨显存不释放,这样能快速定位是推理内存泄漏还是Agent逻辑死循环。
我最近也踩过类似的坑,Qwen2.5-7B用vLLM跑Agent确实容易在tool调用多轮后炸显存。你max_model_len设4096看起来不低,但Agent循环里每次对话都会把历史塞进context,几轮下来实际token数可能远超这个值,建议用vllm的--enable-chunked-prefill或者调低max_num_batched_tokens试试。排查的话可以先在本地写个简单的死循环调tool脚本,把memory_profiler挂上去看显存变化,如果每次调用后显存只增不减那就是模型侧没释放缓存,如果突然飙升就是Agent逻辑里传了重复的history。另外可以试试把LangChain的返回详细日志打开,看卡死前最后一次tool输出是不是异常的json格式。
我之前也踩过类似的坑,vLLM默认的max_model_len其实挺吃显存的,你设4096的话8G卡估计悬,试试改成2048或者1024看看会不会好点。另外Agent循环里历史对话如果不做截断,每次调用都塞满上下文确实容易炸,可以加个滑动窗口只保留最近几轮。建议先在命令行里单独跑几个连续的推理请求,排除掉LangChain的逻辑干扰,这样能快速定位是模型本身卡死还是Agent代码的问题。
老实说你这个情况我太熟了,我之前用Qwen2.5-7B跑多轮Agent也是卡到怀疑人生。max_model_len设4096其实不算大,但关键问题在于vLLM的prefill阶段和显存碎片管理,尤其是多次tool call之后,历史对话的attention矩阵会急剧膨胀,显存很容易被撑爆。你可以先试试在vLLM启动时加个--enable-chunked-prefill参数,或者把gpu_memory_utilization降一降,比如设成0.8,留点余量给上下文动态分配。
另外Agent循环里如果没做历史截断,比如每次调用都塞进完整对话,那跑几轮后上下文长度轻松翻倍,OOM几乎是必然的。我自己的做法是在LangChain的回调里加个token计数器,如果超过预设阈值就主动裁剪最早几轮对话,或者用滑动窗口只保留最近N轮。至于定位问题,你可以先跑一个简单的单轮tool call,如果也卡那多半是模型推理的问题,否则就是Agent逻辑里某步循环没退出或者tool返回数据太大。
还有个偏方:把vLLM的日志级别调成debug,看每次请求的显存分配情况,有时候是某些tool返回了超长字符串导致推理中途崩掉。你用的是哪个版本的vLLM?老版本对Qwen的chunked prefill支持不太好,建议升到0.6以上试试。
八成是历史对话太长把上下文塞爆了,试试设个max_tokens上限或者清一下历史再跑。
这种卡死我遇到好多次,大概率是Agent循环里历史对话越堆越长,vLLM的max_model_len设4096但实际推理时KV Cache占得比你想的猛,可以试试把max_num_seqs调小点,或者用lmdeploy替代vLLM试试,它对长文本更省显存。另外建议你在tool调用前后打日志看下内存占用曲线,如果OOM前显存是缓步上升而不是突然爆掉,那多半是Agent逻辑里循环没控制好,比如tool返回结果没做截断或者历史消息没清理。我自己后来在每次Agent迭代前用token计数判断是否接近上限,手动裁剪一下早期轮次,基本就稳了。
我之前也踩过类似的坑,vLLM默认的max_model_len其实挺吃显存的,你设4096但实际跑Agent反复拼接历史对话后,上下文长度很容易超,建议调小到2048试试。另外可以给vLLM加个--max-num-batched-tokens参数限制一下批量处理,或者在LangChain里把Agent的memory改成滑动窗口,只保留最近几轮对话,这样能明显缓解OOM。排查的话建议先只用单次tool调用看模型正不正常,排除Agent逻辑问题。