1. 项目概述
在AI应用开发中,Qwen3.5模型默认会在输出中包含<think>推理标签,这在生产环境中往往需要隐藏。本文将详细介绍如何通过Spring AI集成vLLM来关闭Qwen3.5的思考过程输出。
1.1 核心需求解析
Qwen3.5作为一款强大的语言模型,其默认输出包含完整的推理过程,这在调试阶段非常有用。但在生产环境中,我们通常只需要最终的答案输出。因此,需要一种方法来控制是否显示这些中间思考过程。
提示:
<think>标签是Qwen3.5特有的推理过程标记,包含了模型生成答案时的内部思考步骤。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术方案设计
2.1 整体架构
我们的解决方案采用以下技术栈:
- vLLM作为推理服务后端
- Spring AI作为客户端调用框架
- Qwen3.5作为基础模型
2.2 关键组件选型
2.2.1 vLLM版本选择
必须使用vLLM 0.6.4及以上版本,原因如下:
- 低版本不支持
chat_template_kwargs参数 - 0.6.4版本开始支持Qwen3.5特有的推理解析器
- 提供了更稳定的API接口
2.2.2 Spring AI版本
推荐使用Spring AI 1.0.2版本,这是目前最稳定的版本,与vLLM的兼容性最佳。
3. 服务端配置
3.1 vLLM启动命令
以下是完整的vLLM启动命令:
bash复制nohup python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen3.5-9B \
--host 0.0.0.0 \
--port 11454 \
--served-model-name qwen3 \
--max-num-seqs 32 \
--max-model-len 262144 \
--enable-auto-tool-choice \
--tool-call-parser qwen3_coder \
--reasoning-parser qwen3 \
--uvicorn-log-level debug \
> ~/Documents/logs/vllm.log 2>&1 &
3.2 关键参数解析
| 参数 | 说明 | 必要性 |
|---|---|---|
| --model | 指定模型路径 | 必需 |
| --reasoning-parser | 启用Qwen3.5推理解析 | 必需 |
| --tool-call-parser | 匹配工具调用格式 | 可选 |
| --served-model-name | 客户端调用时的模型短名 | 推荐 |
| --max-num-seqs | 最大并发请求数 | 根据硬件调整 |
| --max-model-len | 最大上下文长度 | 根据需求调整 |
注意:
--reasoning-parser qwen3是关闭思考过程的关键参数,缺少此参数会导致enable_thinking设置无效。
4. 客户端实现
4.1 依赖配置
在Spring Boot项目的pom.xml中添加依赖:
xml复制<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.2</version>
</dependency>
4.2 核心代码实现
4.2.1 选项构建器
java复制public ChatOptions optionBuilder(String modelName) {
return OpenAiChatOptions.builder()
.model(modelName) // 对应 --served-model-name
.temperature(0.7) // 温度:高发散/低保守
.maxTokens(32768)
// 关键:通过extraBody传递chat_template_kwargs
.extraBody(Map.of(
"chat_template_kwargs", Map.of("enable_thinking", false)
))
.build();
}
4.2.2 调用示例
java复制ChatResponse response = chatModel.call(
new Prompt("Where is this?", optionBuilder("qwen3"))
);
String content = response.getResult().getOutput().getContent();
System.out.println(content); // 输出不含<think>
4.3 多模态支持
Qwen3.5支持多模态输入,可以通过以下方式实现:
java复制import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.content.Media;
import org.springframework.core.io.UrlResource;
Media media = new Media(
"image/png",
new UrlResource("https://example.com/image.png")
);
UserMessage msg = new UserMessage("Where is this?", List.of(media));
ChatResponse resp = chatModel.call(new Prompt(msg, optionBuilder("qwen3")));
5. 问题排查与解决方案
5.1 常见问题列表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 日志警告参数被忽略 | vLLM版本过低 | 升级到0.6.4或更高版本 |
| 思考标签仍未消失 | 缺少--reasoning-parser参数 | 添加--reasoning-parser qwen3 |
| 服务无响应 | 端口冲突或模型加载失败 | 检查日志和端口占用 |
5.2 详细排查步骤
5.2.1 版本检查
bash复制pip install -U vllm
vllm --version # 确认≥0.6.4
5.2.2 直接测试API
使用curl直接测试服务端,排除客户端问题:
bash复制curl http://localhost:11454/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3",
"messages": [{"role": "user", "content": "Hello"}],
"chat_template_kwargs": {"enable_thinking": false}
}'
6. 性能优化建议
6.1 服务端优化
- 根据硬件调整
--max-num-seqs参数 - 合理设置
--max-model-len以平衡性能和效果 - 考虑使用量化模型减少内存占用
6.2 客户端优化
- 实现请求批处理减少网络开销
- 使用连接池管理HTTP连接
- 实现结果缓存机制
7. 扩展应用
7.1 动态控制思考过程
可以通过修改enable_thinking参数动态控制是否显示思考过程:
java复制// 开启思考过程
.extraBody(Map.of(
"chat_template_kwargs", Map.of("enable_thinking", true)
))
// 关闭思考过程
.extraBody(Map.of(
"chat_template_kwargs", Map.of("enable_thinking", false)
))
7.2 自定义解析器
对于高级用户,可以开发自定义解析器:
- 继承vLLM的基础解析器类
- 实现特定的解析逻辑
- 通过
--reasoning-parser参数指定自定义解析器
8. 安全注意事项
- 不要将服务暴露在公网不加认证
- 实现适当的速率限制
- 对输入内容进行安全检查
- 定期更新vLLM和Spring AI版本
9. 部署建议
9.1 开发环境
- 使用Docker简化环境配置
- 配置本地日志监控
- 实现自动化测试
9.2 生产环境
- 使用Kubernetes进行容器编排
- 实现自动扩缩容
- 配置完善的监控告警系统
- 考虑多副本部署提高可用性
10. 经验分享
在实际项目中,我们发现以下几点特别重要:
- 版本一致性:确保开发、测试和生产环境使用相同的vLLM和Spring AI版本
- 参数调优:需要根据实际业务场景调整temperature等参数
- 日志分析:定期分析服务日志,及时发现潜在问题
- 性能测试:在上线前进行充分的压力测试
提示:在生产环境中,建议将vLLM服务部署在内网,通过API网关对外提供服务,而不是直接暴露vLLM服务端口。
