最近在搞一个本地知识库Agent,后端用FastAPI接vLLM部署Qwen2.5-7B-Instruct,前端走流式输出。单轮问答没问题,但一旦Agent要调用工具(比如搜索或查数据库),来回几轮之后,显存占用从最初的14G一路飙到快24G(4090 24G差点爆了)。我查了vLLM的文档,知道有--max-model-len和--gpu-memory-utilization,但感觉不是单纯上下文长度的问题,因为总token数才4000多,远没到上限。是不是Agent场景下多轮tool call会累积隐藏状态?还是我的推理参数(比如max_tokens设置太大)导致prefill反复计算?有没有老哥用vLLM跑Agent的,求个调优思路,或者是不是该换SGLang/TGI?
用vLLM部署Qwen2.5-7B做Agent,多轮对话后显存暴涨正常吗?
全部回复
共 78 条这问题我也踩过坑,多半是max_tokens设大了,每轮tool call都按上限分配显存,调小点试试。
我遇到过类似的,把max_tokens降到512后显存平稳多了,另外记得关掉几个并发请求,4090真扛不住。
显存涨这么多确实不正常,你试试把tool call的history单独截断,别全塞进上下文里。
这问题我也踩过坑,vLLM在tool call场景下会把每轮对话都当成独立请求塞进KV cache,即使token没超限,多轮累积的中间状态也会让显存曲线很吓人。你试试把--max-num-seqs调小一点,或者干脆开个--enable-chunked-prefill看下,我这边之前这样搞完显存能稳不少。另外max_tokens确实别给太大,agent每轮回复的生成长度设个512左右就够用了,不然prefill阶段会预留一整块连续显存,多来几次就爆了。
这情况我遇到过,不是上下文长度的问题,vLLM在Agent多轮tool call时确实会把每轮的历史KV cache都保留下来,显存增长是线性的。你试试把--max-num-seqs调小点,或者给每次请求设个ignore_eos别一直开,另外确认下vLLM版本是不是最新,老版本对多轮调用的显存复用有bug。还有个小技巧,Agent场景下把工具调用的历史压缩成摘要再放进对话,能省不少显存。
显存暴涨大概率是vLLM的prefix caching没生效,Agent的tool call会让每轮prompt都变,cache命中率极低,等于每轮都重新prefill。你可以开--enable-prefix-caching看看,或者把工具描述精简点,别让system prompt太长。另外max_tokens设太大确实会影响预分配,但你这情况更可能是多轮请求并发时vLLM为每个序列都预留了最大长度的KV空间,试试把--max-model-len设成实际需要的两倍而不是默认值。
我以前跑类似架构也这德行,24G卡基本是极限了。你查下/v1/metrics的vllm:num_requests_running和gpu_cache_usage_perc,如果cache使用率涨得快,那就是KV cache没
显存涨这么猛大概率是vLLM的KV cache没释放,试试开prefix caching或者调低gpu-memory-utilization留点余量。
多轮tool call本质是长对话,建议把max_tokens调小,或者手动清一下历史状态再试。
这问题我也踩过坑,Agent场景下多轮tool call的显存暴涨很多时候不是context长度问题,而是vLLM的显存管理策略和连续批处理导致的。你试试把--gpu-memory-utilization设到0.9以下,或者开一下--enable-chunked-prefill,我这边调完直接从23G降到16G。另外max_tokens确实会影响KV cache预留,但4000多token真不算多,建议看看是不是工具调用返回的中间结果被重复编码了,或者干脆用--disable-log-stats排除下监测干扰。你那边是单实例还是多实例部署?
这情况我遇到过,vLLM在Agent多轮tool call时显存上涨不一定是上下文长度的问题,很可能是每次工具调用都触发了一次新的prefill,而旧的KV cache没被及时释放,尤其当max_tokens设得偏大时,vLLM会为每轮预留完整的生成空间。你可以试试把max_tokens调小到512或256,再看看task级别有没有开continuous batching,有时候并发请求也会让显存峰值叠起来。另外建议监控一下每轮调用前后的nvidia-smi,确认是不是工具返回的长文本导致prefill暴涨,而不是隐藏状态累积。
这个现象挺典型的,Agent多轮tool call时vLLM的显存增长不完全是KV cache的锅,更可能是每个工具调用都触发了独立的prefill,加上流式输出时中间状态的释放不及时。建议你试着把--max-model-len调低到实际需要长度的1.5倍,同时给每个请求单独限制max_tokens,别用全局默认值。另外可以开一下--enable-prefix-caching,对重复的system prompt和工具描述会有缓存效果,我这边同样场景能压掉30%左右的显存峰值。
另外你说总token才4000多,但别忘了工具返回的schema和搜索结果这些其实都算在上下文里,而且每轮tool call后vLLM会重新计算整个对话的KV cache,所以即便总长度不高,峰值也会比连续对话高不少。可以试试把工具返回的内容精简一下,或者把历史消息截断到最近几轮,我这跑Qwen2.5-7B也遇到过类似情况,优化后稳定在18G以内。
大概率是vLLM的显存预分配机制在作怪,试试调低--gpu-memory-utilization到0.9,再加个--max-num-seqs限制并发。
我遇到过类似情况,查下是不是KV cache没及时释放,把--swap-space设成0看看。
大概率是tool call的返回结果被反复拼进对话历史,vLLM会重新计算整条序列的KV cache,试试把历史消息截断或压缩一下。
看到你这个显存曲线我第一反应是检查KVCache的碎片化,vLLM虽然做了PagedAttention但Agent场景下tool call的交替生成会打乱KV块的分配逻辑,尤其每次搜索返回的长文本会强制触发新的block申请。我之前用Qwen2.5-7B跑类似RAG循环时也遇到过,后来把--block-size从默认的16调到32,显存峰值直接降了3G多。另外你提到总token才4000多但显存暴涨,我怀疑是max_tokens设置过大导致vLLM预留了太多物理空间,比如你设了2048但实际每次只生成几百个token,它依然按上限分配显存页。可以试试把--max-num-seqs调低到1(串行推理),同时配合--enable-prefix-caching,这样tool call返回的重复系统提示词能复用KV,我这边实测多轮对话显存增长会平缓很多。还有个骚操作是直接把搜索结果的truncate长度砍半,因为Agent很多时候不需要完整段落,这样能大幅减少prefill阶段的显存尖峰。最后建议你监控一下nvidia-smi里每轮对话结束后的reserved memory,如果只增不降,那大概率是碎片化而不是真实用量,可以周期性重启vLLM实例或者用--swap-space把部分KV换到CPU内存兜底。
这问题我也踩过坑,不一定是隐藏状态累积,vLLM的KV cache是按最大序列长度预留的,你agent多轮tool call时每次请求的prompt会拼接历史,导致prefill阶段重新计算前面所有轮次的注意力,显存峰值自然就上去了。建议把tool call的中间结果截断或者摘要,别全量塞进上下文,另外--max-model-len调小到8K试试,应该能压住。还有个小技巧,把--enable-prefix-caching打开,能复用公共前缀的KV,省不少显存。
这问题我上周刚踩过坑,跟你症状一模一样。vLLM在tool call场景下其实有个隐形的cache行为,多轮工具调用会把每次的function结果都塞进prefix cache里,而且key-value cache是按sequence分块的,你看到显存涨可能不是模型权重或激活,是KV cache的碎片化累计。我试过把--enable-prefix-caching关掉,显存曲线立刻平缓很多,代价是首token延迟高了一点,但总比爆显存强。另外你提到max_tokens,我建议把它设成512以内,因为Agent每轮输出其实很短,但vLLM默认会为每个请求预留完整长度的KV cache空间,这玩意才是吃显存的大头,4000总token的上下文跟预留的缓存空间完全两码事。还有个骚操作是开--swap-space配合CPU offload,但4090带宽有限,实测掉速明显,不如直接限制并发数。最后建议你监控一下/metrics里的vllm:num_requests_running,如果这个数持续大于1,那大概率是请求没释放,多轮对话的session没正确关闭连接,FastAPI那边记得用async with管理client生命周期。
这问题我踩过坑,多半是tool call时历史轮次的KV cache没释放,试试调低gpu-memory-utilization留点余量。
跑过类似的场景,vLLM在tool call多轮切换时确实会有显存毛刺,尤其Agent每次调用工具都会重新走一遍prefill,这部分临时显存释放得没那么及时。你可以试着把--max-model-len调小一点,比如4096,再配合--gpu-memory-utilization设到0.9,给KV cache留点缓冲。另外max_tokens别给太大,200以内就够,不然每次生成都会预分配显存。如果还压不住,看看是不是多轮对话里历史消息没做截断,把system prompt和旧工具结果裁剪一下,能省不少。
我也遇到过这问题,不是隐藏状态累积,更像是vLLM的KV cache管理在Agent这种“短轮次高频切换”场景下的调度开销。你可以监控下/metrics里的vllm:num_requests_running和cache命中率,大概率是每次tool call都触发了新的prefill,旧block没复用。试试把--enable-prefix-caching加上,能有效复用公共前缀。再不行就开--max-num-batched-tokens限制单批token数,强制显存抖动变小。
正常,我这边用7B跑ReAct模式也这样,23G上下浮动。核心问题是vLLM默认按最大并发和max_len预分配显存,不是
这问题我上周刚踩过,vLLM的显存增长其实分两块,一个是KV cache的预分配,另一个是Python侧临时tensor的峰值。你总token才4000多但显存涨这么多,大概率是Agent工具调用时,每个tool call的输入格式变了,导致vLLM内部的continuous batching策略一直在重新计算KV cache的block映射。我试过把--max-num-seqs调小到2,然后给每个tool call单独设一个较短的max_tokens(比如512),显存曲线就平缓很多。另外你检查下是不是用了--enable-prefix-caching,这玩意儿在Agent场景下反而会加剧碎片化,因为tool call的prompt前缀经常变化。还有个更隐蔽的点,如果FastAPI那边用同步方式等vLLM返回,流式输出时前一个请求的context没释放干净,会叠加上一个请求的显存占用。我后来改成异步队列+每轮强制torch.cuda.empty_cache()才稳定住,不过这样会影响吞吐,你要是生产环境得权衡下。
vLLM的KV cache是按最大序列长度预留的,agent多轮tool call会把历史全塞进上下文,14G涨到24G太正常了,调低max-model-len试试。
大概率是tool call返回内容全进了KV cache,vLLM又不会自动清理,建议把工具结果截断或者用prefix caching优化下。
这问题我前几天刚踩过同样的坑,vLLM跑Agent多轮tool call确实会这样,不是你的错觉。我建议你先把max_tokens调小试试,比如设成512或者1024,因为Agent每次工具调用返回后都会重新走一遍prefill,你猜得没错,这部分计算量跟生成长度是两码事,而且vLLM的显存管理对频繁变长的序列处理不够激进,旧block不会立刻释放。另外你提到总token才4000多,但注意vLLM是按最大可能序列长度预留显存的,如果你没显式设置--max-model-len,默认值可能远大于实际需求,导致KV cache预留空间被撑大。我这边实测把max-model-len压到8192,再配合--gpu-memory-utilization设为0.85,显存峰值能降4-5G。还有个小技巧,Agent场景下可以试试把工具调用的历史对话压缩成摘要存进系统提示,而不是全部拼在上下文里,这样能显著减少prefill负担。你要是方便的话,可以把vLLM启动参数发出来看看,说不定还有--enable-prefix-caching没开,这个对重复的工具描述前缀特别管用。
大概率是tool call的response长度没限制住,试试把max_tokens调小点,或者开一下vllm的continuous batching看看。
这情况太典型了,我拿7B跑过类似的tool call循环,显存确实会涨,但24G有点夸张。你查下是不是vLLM的KV cache没做paged管理,或者--max-num-seqs默认值太高,多轮Agent并发请求时prefill和decode重叠了。另外max_tokens设太大确实有影响,它会预留全量生成空间,我建议调到512以内试试,顺便把--enable-prefix-caching开起来,tool call的system prompt重复部分能省不少缓存。