《AI大模型应用开发实战从入门到精通共60篇》028、OpenAI API兼容接口:用FastChat搭建自己的API服务
028、OpenAI API兼容接口用FastChat搭建自己的API服务昨晚调试到凌晨三点客户那边反馈说GPT-4调用量超限了业务直接卡死。我盯着终端里那行“Rate limit exceeded”看了半天突然意识到一个问题——为什么非要死磕OpenAI的官方API本地部署一个兼容接口既能跑开源模型又能无缝切换回GPT-4这不香吗FastChat就是干这个的。它能把LLaMA、Vicuna、ChatGLM这些模型包装成和OpenAI API一模一样的接口你代码里那些openai.ChatCompletion.create()调用改个base_url就能直接怼到本地服务上。今天就把这套搭建流程掰开揉碎讲清楚。环境准备别在Python版本上翻车先说我踩过的坑。FastChat对Python版本有隐性要求3.8以下直接报typing模块缺失3.11以上某些依赖包还没适配。我建议锁死在3.10省心。# 这里踩过坑别用conda默认的3.7conda create-nfastchatpython3.10conda activate fastchat安装FastChat时有个坑——如果你在墙内pip install fschat会卡在flash-attn这个依赖上。这玩意儿是加速库但编译巨慢。解决方案是加个--no-deps先装主体再单独装其他依赖# 别这样写pip install fschat # 会卡死pipinstallfschat --no-deps pipinstalltransformers accelerate sentencepiece protobuf# flash-attn可选没有也能跑就是慢点模型下载选对模型省一半功夫模型选择上我建议新手别碰LLaMA原版那玩意儿需要申请权重流程繁琐。直接上ChatGLM3-6B或者Qwen-7BHuggingFace上直接下中文效果还更好。# 这里踩过坑用git lfs clone会下半天还容易断# 推荐用huggingface_hub的snapshot_download支持断点续传fromhuggingface_hubimportsnapshot_download# 别这样写model_path ./models/chatglm3-6b # 手动下载容易缺文件model_pathsnapshot_download(repo_idTHUDM/chatglm3-6b,local_dir./models/chatglm3-6b,resume_downloadTrue,# 断点续传网络不稳时救命ignore_patterns[*.h5,*.ot,*.msgpack]# 这些文件用不上省空间)如果你在服务器上跑记得先检查显存。ChatGLM3-6B的FP16版本大概需要13GB显存Qwen-7B差不多。显存不够就上4bit量化后面会讲。启动Controller和Worker理解FastChat的架构FastChat的架构分三层Controller调度中心、Worker模型工人、API Server对外接口。我第一次启动时直接跳过了Controller结果API Server一直报连接拒绝。先启动Controller它负责管理所有Worker的状态# 这个进程不能关关了所有Worker都会掉线python-mfastchat.serve.controller--host0.0.0.0--port21001然后启动Worker把模型加载进去。这里有个关键参数——--num-gpus如果你有多卡别一股脑全用上留一张给API Server和其他服务# 别这样写--num-gpus 4 # 把所有卡都占了其他服务没得用python-mfastchat.serve.model_worker\--model-path ./models/chatglm3-6b\--controllerhttp://localhost:21001\--workerhttp://localhost:21002\--host0.0.0.0\--port21002\--num-gpus1\--load-8bit# 显存不够时加这个8bit量化Worker启动时会加载模型这个过程慢是正常的。我第一次等了两分钟没反应以为卡死了差点CtrlC。实际上它在下载tokenizer和配置文件耐心等。启动API Server让接口和OpenAI一模一样这是最爽的一步。API Server启动后你的本地模型就拥有了和OpenAI完全兼容的接口python-mfastchat.serve.openai_api_server\--controllerhttp://localhost:21001\--host0.0.0.0\--port8000启动成功后你会看到类似这样的输出INFO: Uvicorn running on http://0.0.0.0:8000现在用curl测试一下注意看请求格式——和OpenAI的ChatCompletion API完全一致curlhttp://localhost:8000/v1/chat/completions\-HContent-Type: application/json\-d{ model: chatglm3-6b, messages: [{role: user, content: 你好请用中文回答}], temperature: 0.7, max_tokens: 512 }返回的JSON结构和OpenAI一模一样有id、object、choices这些字段。这意味着你现有的OpenAI SDK代码只需要改一行就能切过来。客户端代码改造一行代码切换模型假设你原来用的是OpenAI的Python SDK# 原来的代码importopenai openai.api_keysk-xxxx# 这里踩过坑本地服务不需要key但SDK会校验格式openai.api_basehttps://api.openai.com/v1# 改成这样importopenai openai.api_keyEMPTY# 随便填但不能为空字符串否则报错openai.api_basehttp://localhost:8000/v1# 指向本地FastChat# 调用方式完全不变responseopenai.ChatCompletion.create(modelchatglm3-6b,messages[{role:user,content:讲个冷笑话}])print(response.choices[0].message.content)注意那个api_key我一开始填了空字符串结果SDK直接抛异常说API key格式不对。后来发现只要填个非空字符串就行FastChat根本不校验。多模型切换一个API服务挂多个模型FastChat支持同时加载多个模型每个模型一个Worker。比如我再加一个Qwen-7B# 第二个Worker端口不能冲突python-mfastchat.serve.model_worker\--model-path ./models/Qwen-7B-Chat\--controllerhttp://localhost:21001\--workerhttp://localhost:21003\--host0.0.0.0\--port21003\--num-gpus1然后在客户端调用时model参数填对应的模型名就行。FastChat会自动把请求路由到对应的Worker上。这个特性在A/B测试时特别有用——同一个API服务不同用户用不同模型代码层面零改动。性能调优别让模型跑成蜗牛如果你发现响应速度慢先检查这几个地方Worker数量默认每个模型只有一个Worker并发请求会排队。可以加--worker-num 2参数启动多个Worker实例但注意显存占用会翻倍。批处理FastChat支持--batch-size参数把多个请求合并成一个batch推理。我实测batch_size4时吞吐量提升3倍但延迟会增加。适合离线批量处理不适合实时对话。量化显存不够时用--load-8bit或--load-4bit。4bit量化后ChatGLM3-6B的显存占用降到4GB左右但生成质量会下降。我一般只在开发环境用4bit生产环境至少8bit。流式输出客户端请求时加streamTrue服务端会逐token返回。但FastChat的流式实现有个bug——如果模型生成过程中报错流会直接断掉客户端收不到错误信息。建议在客户端加超时重试逻辑。生产部署别忘了加鉴权和负载均衡如果你把这个服务暴露到公网有几个坑必须填鉴权FastChat默认没有鉴权谁都能调。可以用Nginx加个API Key校验或者用FastAPI的中间件自己写一个。我写了个简单的装饰器检查请求头里的Authorization字段。负载均衡单机扛不住并发时可以启动多个Worker实例前面挂Nginx做负载均衡。注意每个Worker的--worker-address要不同否则Controller会报地址冲突。健康检查Controller和Worker之间有心跳机制但API Server没有。我写了个定时任务每30秒调一次/v1/models接口如果返回非200就重启服务。个人经验什么时候该用FastChat什么时候不该用FastChat最大的价值不是性能而是接口兼容性。如果你的团队已经基于OpenAI API开发了一套完整的工具链比如LangChain、AutoGPT用FastChat做本地部署几乎是零迁移成本。但别指望它替代生产级的推理服务。FastChat的Worker是单进程的一个Worker挂了整个模型就不可用。而且它没有内置的请求排队、限流、监控这些功能。真要上生产还是得用vLLM、TGI这些专门优化的推理引擎。我的建议是开发测试阶段用FastChat快速验证上线前再迁移到vLLM。vLLM也兼容OpenAI API格式迁移成本极低。后面我会专门写一篇vLLM的部署实战到时候你就知道怎么无缝切换了。最后说一句别在模型选择上纠结太久。ChatGLM3-6B和Qwen-7B在中文场景下差距不大先跑起来再说。模型可以换架构不能等。