第一次部署就想把几个模型一起挂上去,结果往往是一个都答不上来:页面能打开,发消息转圈,日志里同时有配置解析、显存不足、端口冲突和模板不匹配几类报错,分不清是哪一层的问题。更稳的顺序是先用最小清单只注册一个模型,确认「前端 → controller → worker → 模型」这条链路能完整走通,再回头追加第二个模型和做切换配置。多模型切换本身不难,难的是在一个不通的链路上继续加变量。
多个模型第一次部署就一起上,故障面会同时覆盖配置解析、显存、端口、对话模板和前端路由,很难定位。建议只注册一个模型,用一次完整问答确认链路可用并把它当基线,再追加第二个模型观察启动日志;切换是否真的生效,要从 controller 与 worker 日志核对实际被调用的模型名,不能只看页面下拉框选了什么。
用最小清单只注册一个模型,确认对话能正常返回
先写一个只有一条记录的清单。字段名在不同 FastChat 版本之间会有差异,下面的骨架只保证结构清晰,具体键名需要结合你本机拉到的那份代码确认,不要直接照抄上线。
[
{
"model_name": "qwen-chat",
"model_path": "/models/Qwen-7B-Chat",
"worker_addr": "http://127.0.0.1:21002",
"num_gpus": 1,
"conv_template": "qwen"
}
]
清单里这几项要一次填对:model_name 是后面切换时唯一使用的标识,model_path 指向本地权重目录,worker_addr 的端口不能和其他进程重复,num_gpus 要和实际可用显卡对应,conv_template 决定提示词怎么拼接。启动顺序通常是先 controller,再 worker,worker 启动时要带上 controller 的地址,最后才是前端页面。
验证方式用一次完整问答,而不是只看进程有没有起来。可以先直接打 worker 接口,确认模型本体能出字:
curl http://127.0.0.1:21002/worker_generate \
-H 'Content-Type: application/json' \
-d '{"model":"qwen-chat","prompt":"用一句话说明你是什么模型","max_new_tokens":64}'
再回到聊天页面用同一个问题问一遍。预期看到的是:返回内容完整、没有中途截断、没有把提示词原样吐回来、页面能显示完整正文。接口路径以本机版本为准,如果 404,看 worker 启动日志里实际注册的路由名。这一步通过之后,这份清单就是基线,后面所有异常都和它对比。
在清单里追加第二个模型,观察启动日志有无解析失败
追加第二条记录时,下面几个字段必须同步改动,否则容易出现「页面能看到两个名字,但只有一个能答」:
model_name:必须与第一条不同,重名会让前端无法区分;worker_addr:端口换一个,例如 21003,避免和第一个 worker 抢占;model_path:指向第二个模型的权重目录,两个模型不要共用同一路径;num_gpus与conv_template:按第二个模型的实际规格填,模板和模型不匹配会出现答非所问或输出格式错乱。
启动第二个 worker 后先看日志,常见的失败特征有几类:清单本身格式错会直接报 JSON 解析失败或 KeyError,通常指向漏了逗号或引号;端口冲突会看到 Address already in use,属于配置问题;显存不够会看到 CUDA out of memory,属于资源问题;权重路径写错则是找不到文件或目录。这两类的处理方向完全不同,日志里先确认是解析、端口还是显存,再决定改清单还是调机器。
在聊天页切换模型,确认请求落到对应模型名
切换生效不能只看下拉框。页面顶部选中的名字只是前端状态,请求最终发给哪个 worker 由后端决定。验证方法是同时看两边日志:在页面切到第二个模型并发送一条消息,观察 controller 日志里这次请求路由到了哪个 model_name,再看对应 worker 日志里是否出现了这条请求的时间戳。只有两边对得上,才说明切换真的生效。
如果日志不方便实时看,可以用回复特征做交叉验证:给两个模型问同一个问题,比较自称的名称、输出格式和模板风格是否明显不同。两个模型返回的内容风格完全一致、连标点习惯都一样,通常说明请求一直走的是同一个后端,这时候要回头检查前端配置里的模型名是否和清单中的 model_name 严格一致。
比较两个模型的响应耗时,判断是排队还是模型本身慢
多模型场景下「慢」有两种来源,需要分开测。记录方式建议做三次:单独请求模型 A、单独请求模型 B、再让两个请求几乎同时发出。每条记录都加上耗时输出:
curl -s -o /dev/null -w '%{time_total}\n' http://127.0.0.1:21002/worker_generate \
-H 'Content-Type: application/json' \
-d '{"model":"qwen-chat","prompt":"写一段五十字左右的说明","max_new_tokens":128}'
把三次结果记成三行,重点看相对关系:如果单独请求时两个模型都还可以,交叉发出后明显变慢,通常是显存或计算资源被抢,属于排队;如果某一个模型单独请求时就一直偏慢,问题更可能在模型自身的参数量、量化方式和推理配置上,而不是切换逻辑。max_new_tokens 会直接拉长耗时,三次测试要保持一致,否则比较没有意义。
把可用的清单结构固定下来,写成可复用的配置文件
跑通之后不要只在终端里手动拼参数。把清单单独存成一个配置文件,字段顺序固定下来,例如统一按 model_name → model_path → worker_addr → num_gpus → conv_template 排列,方便以后增删时对齐。JSON 里写不了注释,就把「每个模型对应的显卡、端口、模板」单独记一份说明,部署时照着填。
改动任何字段之前先备份一份,出问题能直接回退:
cp model_list.json model_list.json.bak
后续每次新增模型,都按「只加一条、启动、看日志、页面验证、记录耗时」这个循环走一遍,而不是一次性把几条一起加进去。单模型链路是否稳定,可以通过重复几次同样的问答来确认;多模型清单是否可用,判据是每个模型都能在日志里找到对应的请求记录。这两条都满足之后,再去调并发、批大小这类参数,才不至于把配置问题和性能问题混在一起排查。