- 人工智能
- 大模型
- 预训练
- 微调
- RLHF
- LoRA
- 本地部署
- 模型量化
【免费下载链接】Chinese-LLaMA-Alpaca-2
中文LLaMA-2 & Alpaca-2大模型二期项目 + 64K超长上下文模型 (Chinese LLaMA-2 & Alpaca-2 LLMs with 64K long context models)
导读
本文围绕 scripts/openai_server_demo/README_vllm.md 展开,系统讲解如何利用 vLLM 作为推理后端,将中文 LLaMA-2 / Alpaca-2 系列模型封装为仿 OpenAI 风格的 RESTful API 服务。读完本文,你将掌握服务启动命令与全部启动参数、/v1/completions(文字接龙)与/v1/chat/completions(多轮聊天)两个核心接口的完整调用方式、采样类高级参数的语义与默认值,并了解服务端背后的对话模板、采样参数映射与长度校验等源码级实现细节,可直接基于此搭建个人网站或各类 Web Demo 的大模型后端。
一、这套 API Demo 的定位与能力边界
README_vllm.md开篇即明确:这是一个使用 FastAPI 实现的简易仿 OpenAI API 风格服务器 Demo,目标是帮助开发者快速搭建基于中文大模型的个人网站以及其他有趣的 Web Demo。
与同目录下的 README.md(基于 🤗 Transformers 的实现)不同,本实现基于 vLLM 部署 LLM 后端服务,因此能力边界存在明显差异,原文档明确写出三点限制:
- 暂不支持加载 LoRA 模型(需先合并 LoRA 权重为完整 HF 格式模型);
- 暂不支持仅 CPU 部署;
- 暂不支持 8bit 推理。
这一点在仓库其他推理脚本中得到印证:scripts/inference/inference_hf.py 与 scripts/inference/gradio_demo.py 中同样对 vLLM 路径做了限制性检查:使用 vLLM 时若同时传入--lora_model、--load_in_8bit/--load_in_4bit、--only_cpu、--speculative_sampling均会直接抛出 ValueError。此外,项目主 README.md 还注明 vLLM 后端不支持长上下文版本模型(16K/64K 版),这些约束在规划部署方案时需一并考虑。
二、环境准备与依赖安装
按照原文档,安装依赖只需一条 pip 命令:
pip install fastapi uvicorn shortuuid vllm fschat其中各依赖的职责可以这样理解:fastapi与uvicorn提供异步 Web 框架与 ASGI 服务器;vllm是推理引擎(负责模型加载、Continuous Batching 与异步生成);fschat(FastChat)则被服务端用于构建对话模板(Conversation 对象)与模型适配器;shortuuid用于生成请求 ID(不过当前 vLLM 版服务实际改用 vLLM 自带的random_uuid)。
三、启动 vLLM 后端服务:命令与参数详解
启动命令
python scripts/openai_server_demo/openai_api_server_vllm.py --model /path/to/base_model --tokenizer-mode slow --served-model-name chinese-llama-alpaca-2启动入口文件为 scripts/openai_server_demo/openai_api_server_vllm.py。服务进程启动后,默认监听localhost:8000。
启动参数说明(来自原文档)
| 参数 | 说明 |
|---|---|
--model {base_model} | 存放 HF 格式的 LLaMA-2 模型权重和配置文件的目录,可以是合并后的中文 Alpaca-2 模型 |
--tokenizer {tokenizer_path} | 存放对应 tokenizer 的目录。若不提供此参数,则其默认值与--model相同 |
--tokenizer-mode {tokenizer-mode} | tokenizer 的模式。使用基于 LLaMA/LLaMA-2 的模型时,固定为slow |
--tensor-parallel-size {tensor_parallel_size} | 使用的 GPU 数量,默认为 1 |
--served-model-name {served-model-name} | API 中使用的模型名。若使用中文 Alpaca-2 系列模型,模型名中务必包含chinese-llama-alpaca-2 |
--host {host_name} | 部署服务的 host name,默认值是localhost |
--port {port} | 部署服务的端口号,默认值是8000 |
参数背后的源码机制
从源码看,服务端在 openai_api_server_vllm.py 的主入口处 依次做了以下事情:
- 解析服务自身参数:
--host、--port、--allow-credentials、--allowed-origins(默认["*"])、--allowed-methods(默认["*"])、--allowed-headers(默认["*"])以及--served-model-name。这些 CORS 参数通过CORSMiddleware注入 FastAPI 应用(L700-L706),方便网页前端跨域调用。 - 透传 vLLM 引擎参数:调用
AsyncEngineArgs.add_cli_args(parser)把 vLLM 引擎的全部 CLI 参数(包括--model、--tokenizer、--tokenizer-mode、--tensor-parallel-size、--trust-remote-code、--max-model-len等)挂载到同一个 parser 上,最终通过AsyncLLMEngine.from_engine_args构建异步推理引擎(L715-L717)。 - 模型名处理:若未提供
--served-model-name,则served_model默认取--model的值(L710-L713)。每个请求都会通过check_model校验model字段是否等于served_model,不一致时返回404(L160-L167)。 - Tokenizer 准备:使用 vLLM 的
get_tokenizer按--tokenizer-mode加载分词器(L719-L722),随后uvicorn.run启动服务。
需要注意:既然--served-model-name决定了 API 请求中必须携带的model值,而服务端注册的中文 Alpaca-2 对话模板与模型适配器都依赖名称中包含chinese-llama-alpaca-2字样(详见下文第五节),因此使用中文 Alpaca-2 系列模型时务必按文档要求保留该命名。
四、接口与数据模型速览
服务暴露的 HTTP 接口与 OpenAI API 对齐:
GET /v1/models:列出当前服务的模型信息(openai_api_server_vllm.py#L260-L268);POST /v1/completions:文字接龙接口(L464);POST /v1/chat/completions:聊天接口(L295)。
所有请求/响应结构由 scripts/openai_server_demo/openai_api_protocol_vllm.py 中的 Pydantic 模型定义。其中两个请求模型的关键字段默认值如下(可直接作为不传参时的行为参考):
| 字段 | CompletionRequest 默认值 | ChatCompletionRequest 默认值 |
|---|---|---|
temperature | 0.2 | 0.2 |
top_p | 0.9 | 0.9 |
top_k | 40 | 40 |
n | 1 | 1 |
max_tokens | 512 | 512 |
stream | False | False |
presence_penalty | 1.0 | 1.0 |
frequency_penalty | 0.0 | 0.0 |
best_of | None | None |
use_beam_search | False | False |
ignore_eos | False | False |
有一点值得提醒:原文档在参数说明中写presence_penalty的默认值为 0,而当前仓库 openai_api_protocol_vllm.py 中该字段默认值实际为 1.0,两者存在出入;实际行为以请求模型定义为准,读者可在调用时显式传入该参数避免歧义。
五、Completion 文字接龙(completion)接口
文字接龙是最基础的 API 接口:输入 prompt,输出语言模型的续写(completion)结果。需要特别注意的是,API Demo 内置了 prompt 模板,输入的 prompt 会被套入 instruction 模板中,因此这里输入的 prompt 应更像指令而非对话。
快速体验
请求命令:
curl http://localhost:8000/v1/completions \ -H "Content-Type: application/json" \ -d '{ "model": "chinese-llama-alpaca-2", "prompt": "告诉我中国的首都在哪里" }'JSON 返回体:
{ "id": "cmpl-41234d71fa034ec3ae90bbf6b5be7", "object": "text_completion", "created": 1690870733, "model": "chinese-llama-alpaca-2", "choices": [ { "index": 0, "text": "中国的首都是北京。" } ] }高级参数示例
请求命令:
curl http://localhost:8000/v1/completions \ -H "Content-Type: application/json" \ -d '{ "model": "chinese-llama-alpaca-2", "prompt": "告诉我中国和美国分别各有哪些优点缺点", "max_tokens": 90, "temperature": 0.7, "num_beams": 4, "top_k": 40 }'JSON 返回体:
{ "id": "cmpl-ceca9906bf0a429989e850368cc3f893", "object": "text_completion", "created": 1690870952, "model": "chinese-llama-alpaca-2", "choices": [ { "index": 0, "text": "中国的优点是拥有丰富的文化和历史,而美国的优点是拥有先进的科技和经济体系。" } ] }高级参数说明(来自原文档)
prompt:生成文字接龙(completion)的提示。max_tokens:新生成的句子的 token 长度。temperature:在 0 和 2 之间选择的采样温度。较高的值如 0.8 会使输出更加随机,而较低的值如 0.2 则会使其输出更具确定性。temperature 越高,使用随机采样作为 decoding 的概率越大。use_beam_search:使用束搜索(beam search),默认为false,即启用随机采样策略(random sampling)。n:输出序列的数量,默认为 1。best_of:当搜索策略为束搜索(beam search)时,该参数为束搜索中所使用的束个数,默认和n相同。top_k:在随机采样(random sampling)时,前 top_k 高概率的 token 将作为候选 token 被随机采样。top_p:在随机采样时,累积概率超过 top_p 的 token 将作为候选 token 被随机采样,越低随机性越大。举个例子,当 top_p 设定为 0.6 时,若概率前 5 的 token 概率分别为 {0.23, 0.20, 0.18, 0.11, 0.10},前三个 token 的累积概率为 0.61,那么第 4 个 token 将被过滤掉,只有前三个 token 将作为候选 token 被随机采样。presence_penalty:重复惩罚,取值范围 -2 ~ 2。值大于 0 表示鼓励模型使用新的 token,反之鼓励重复。stream:设置为true时,按流式输出的形式返回,默认为false。
关于 Decoding 策略:Greedy Decoding、Random Sampling 与 Beam Search 是 LLaMA 系列最常涉及的三种解码策略,top_k、top_p、temperature等高级参数正是建立在随机采样与束搜索基础之上的。
源码机制:提示词模板与采样参数映射
服务端处理/v1/completions请求的核心链路如下:
- 模板套用:
get_gen_prompt_nochat(openai_api_server_vllm.py#L209-L229)会获取与model对应的对话模板,把用户 prompt 追加为conv.roles[0](即[INST]),再追加一个空的conv.roles[1](即[/INST]),最后通过conv.get_prompt()得到完整指令提示词。这正是"prompt 会被套入 instruction 模板"的源码实现。 - 参数映射:请求体经 Pydantic 解析后,服务端构造 vLLM 的
SamplingParams(n, best_of, presence_penalty, frequency_penalty, temperature, top_p, top_k, stop, ignore_eos, max_tokens, logprobs, use_beam_search)传入engine.generate(L517-L531)。注意原文档示例中的num_beams并非 vLLM 版请求模型的合法字段,vLLM 版以best_of + use_beam_search表达束搜索语义,调用时请使用后者。 - 能力限制:由于 vLLM 引擎暂不支持部分 OpenAI 特性,服务端对
echo、suffix、logit_bias直接返回400错误(L485-L499);logprobs在非流式与流式场景下均有实现(create_logprobs,L271-L292)。 - 返回结构:非流式响应包含
choices(text、index、finish_reason)与usage(prompt_tokens / completion_tokens / total_tokens)两部分(L622-L650)。
六、Chat Completion 聊天(chat completion)接口
聊天接口支持多轮对话,是构建聊天机器人最常用的一路 API。
快速体验
请求命令:
curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "chinese-llama-alpaca-2", "messages": [ {"role": "user","content": "给我讲一些有关杭州的故事吧"} ] }'JSON 返回体:
{ "id": "cmpl-8fc1b6356cf64681a41a8739445a8cf8", "object": "chat.completion", "created": 1690872695, "model": "chinese-llama-alpaca-2", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "好的,请问您对杭州有什么特别的偏好吗?" } } ] }多轮对话
请求命令:
curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "chinese-llama-alpaca-2", "messages": [ {"role": "user","content": "给我讲一些有关杭州的故事吧"}, {"role": "assistant","content": "好的,请问您对杭州有什么特别的偏好吗?"}, {"role": "user","content": "我比较喜欢和西湖,可以给我讲一下西湖吗"} ], "repetition_penalty": 1.0 }'JSON 返回体:
{ "id": "cmpl-02bf36497d3543c980ca2ae8cc4feb63", "object": "chat.completion", "created": 1690872676, "model": "chinese-llama-alpaca-2", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "是的,西湖是杭州最著名的景点之一,它被誉为“人间天堂”。 <\\s>" } } ] }多轮对话的用法即:把历史对话(user / assistant 交替)全部放入messages数组,服务端会将其组织为带[INST] ... [/INST]标记的完整对话上下文。
聊天接口高级参数说明(来自原文档)
聊天接口的参数与 completion 接口基本一致,原文档列出了以下要点:
prompt:生成文字接龙(completion)的提示。max_tokens:新生成的句子的 token 长度。temperature:在 0 和 2 之间选择的采样温度,含义同 completion 接口。use_beam_search:使用束搜索(beam search),默认为false。n:输出序列的数量,默认为 1。best_of:束搜索时使用的束个数,默认和n相同。top_k:随机采样时前 top_k 高概率 token 作为候选。top_p:随机采样时累积概率超过 top_p 的 token 作为候选。presence_penalty:重复惩罚,取值范围 -2 ~ 2,默认值为 0(注:如第四节所述,当前仓库请求模型的默认值实际为 1.0)。stream:设置为true时按流式输出返回,默认为false。
源码机制:对话模板与长度检查
聊天接口在源码层面有几处值得展开:
- 对话模板注册:服务端启动时注册了两套模板——一代
chinese-llama-alpaca(NO_COLON_SINGLE 风格)与二代chinese-llama-alpaca-2(LLAMA2 风格,system 为[INST] <<SYS>>\nYou are a helpful assistant. 你是一个乐于助人的助手。\n<</SYS>>\n\n,角色标记[INST]/[/INST],stop_token_ids=[2]),并分别注册对应模型适配器(openai_api_server_vllm.py#L87-L146)。这就是--served-model-name必须包含chinese-llama-alpaca-2的根因——模板与适配器的匹配依赖名称前缀。 - 消息组装:
get_gen_prompt(L170-L206)遍历messages:system角色覆盖系统提示,user/assistant角色依次追加到 Conversation,末尾追加一个空 assistant 消息后生成完整 prompt。 - 上下文长度校验:
check_length(L232-L257)从模型配置中读取max_sequence_length/seq_length/max_position_embeddings(兜底 2048),当"输入 token 数 +max_tokens"超过上下文长度时返回400错误,避免生成阶段越界。 - 流式与非流式:
request.stream为真时返回 SSE 流;非流式时同样携带usage统计与finish_reason(L414-L461)。目前不支持function_call与logit_bias(L302-L316),如需这些能力需自行扩展。
七、流式输出(SSE)详解
当请求体设置"stream": true时,服务端通过StreamingResponse(media_type="text/event-stream")返回 Server-Sent Events 格式的数据:
- 聊天接口先发送一个携带
role: "assistant"的首个 chunk,随后逐 token 增量推送delta.content,每个事件形如data: {json}\n\n,生成结束(finish_reason非空)后推送data: [DONE]\n\n(L368-L403); - completion 接口的流式行为与 OpenAI 对齐:当
n != best_of或启用束搜索时不启用流式(L537-L541),否则同样逐段推送 delta 文本; - 客户端断开时,服务端通过
BackgroundTasks调用engine.abort(request_id)取消对应生成任务,及时释放显存资源(L405-L412)。
这套 SSE 格式与 OpenAI 官方流式协议一致,因此可以无缝对接基于 ChatGPT 的各类前端应用。
八、与其他部署方式的取舍
同目录的 README.md 给出了基于 🤗 Transformers 的另一种 API Demo(入口为openai_api_server.py)。两者可以对照选择:
| 维度 | Transformers 版(README.md) | vLLM 版(本文主题) |
|---|---|---|
| 加载 LoRA 模型 | 支持(--lora_model) | 不支持,需先合并权重 |
| 仅 CPU 推理 | 支持(--only_cpu) | 不支持 |
| 8bit / 4bit 量化 | 支持(--load_in_8bit/--load_in_4bit) | 不支持 |
| 长上下文扩展 | 支持 NTK(--alpha、--use_ntk)、FlashAttention-2 | 不支持长上下文版本模型 |
| 推理吞吐 | 常规 transformers 生成 | 依赖 vLLM 的 Continuous Batching,吞吐更高 |
| 请求参数风格 | num_beams、repetition_penalty、do_sample | best_of、use_beam_search、presence_penalty |
| 额外接口 | 含/v1/embeddings文本嵌入接口 | 含/v1/models模型列表接口 |
简言之:需要 LoRA / CPU / 量化 / 长上下文能力时选择 Transformers 版;追求高并发与吞吐、且已持有合并后的完整 HF 格式模型时,选择 vLLM 版。两个版本在messages、prompt、max_tokens、temperature、top_k、top_p、stream等常用字段的调用方式上保持一致,切换成本较低。
九、注意事项与排错要点
- 模型名称必须匹配:请求体中的
model必须与启动时的--served-model-name完全一致,否则返回The model ... does not exist.(404)。 - tokenizer 模式固定为 slow:基于 LLaMA/LLaMA-2 的模型需使用
--tokenizer-mode slow,不要使用 fast 模式。 - 上下文超长:请求 token 数加上
max_tokens超过模型上下文长度时返回 400,请检查提示词长度与max_tokens设置(长文本任务可考虑合并 16K/64K 版模型,但注意 vLLM 后端不支持长上下文版本)。 - 不支持字段:
echo、suffix、logit_bias、function_call在当前版本会返回 400,num_beams也不是 vLLM 版请求模型的合法字段,请改用best_of与use_beam_search。 - 跨域访问:默认
--allowed-origins为["*"],如需收紧,可在启动时通过--allowed-origins指定具体来源。 - GPU 数量:多卡环境通过
--tensor-parallel-size指定参与的张量并行 GPU 数量,需保证该值不超过实际可用 GPU 数。
以上要点与启动参数、接口用法全部对应仓库实际代码,可直接照此部署并二次开发。
- 人工智能
- 大模型
- 预训练
- 微调
- RLHF
- LoRA
- 本地部署
- 模型量化
【免费下载链接】Chinese-LLaMA-Alpaca-2
中文LLaMA-2 & Alpaca-2大模型二期项目 + 64K超长上下文模型 (Chinese LLaMA-2 & Alpaca-2 LLMs with 64K long context models)
相关推荐
TaskingAI OpenAI 兼容 API 实战指南:无状态调用 Chat Completion 端点
TaskingAI OpenAI 兼容 API 实战指南:无状态调用 Chat Completion 端点 本篇技术指南围绕 TaskingAI 社区版提供的
人工智能大模型AI AgentRAG后端前端基于 Chinese-LLaMA-Alpaca 的 OpenAI 兼容 API 服务器:部署、源码解析与三大接口调用实战
基于 Chinese LLaMA Alpaca 的 OpenAI 兼容 API 服务器:部署、源码解析与三大接口调用实战 本文以 scripts/openai_
大模型人工智能预训练微调LoRA本地部署NLP模型评测TaskingAI OpenAI 兼容 API 无状态 Chat Completion 调用指南:单轮与多轮对话实战
TaskingAI OpenAI 兼容 API 无状态 Chat Completion 调用指南:单轮与多轮对话实战 本指南以 TaskingAI 官方代码模板
人工智能大模型AI AgentRAG后端前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考