珠海网站建设怎么样,樱花16q808a,十堰网站建设电话,适合网站开发的python目录 一、概论
二、代码实现
第一步#xff1a;新增请求实体类 QvqReasoningRequest
第二步#xff1a;新增 QVQ 推理服务接口 QvqReasoningService
第三步#xff1a;新增 QVQ 推理服务实现类 QvqReasoningServiceImpl
第四步 VideoController
三、演示
五、视觉推理…目录一、概论二、代码实现第一步新增请求实体类 QvqReasoningRequest第二步新增 QVQ 推理服务接口 QvqReasoningService第三步新增 QVQ 推理服务实现类 QvqReasoningServiceImpl第四步 VideoController三、演示五、视觉推理模型核心总结QVQ 视觉推理模型服务实现类QvqReasoningServiceImpl实现过程详细总结一、初始化准备基础配置与线程模型搭建二、前置参数构建贴合 SDK 规范封装输入三、流式 API 调用对接 SDK 的流式能力四、流式结果解析与 SSE 推送拆分 “思考过程 最终回复”五、流式收尾与异常处理保证服务健壮性核心设计细节与适配点一、概论视觉推理模型能够先输出思考过程再输出回答内容适用于处理复杂的视觉分析任务如解读数学题、分析图表数据或复杂视频理解等任务。简单来说视觉推理模型的核心特点是 **“先拆解逻辑再给出结论”**—— 它不仅能完成复杂视觉分析任务还能像人一样暴露背后的思考逻辑彻底区别于普通视觉模型 “直接输出结果” 的模式尤其适配需要深度逻辑推导的场景比如处理数学几何题时它不会直接给出答案而是先输出思考过程“首先观察图片中的图形结构识别出三角形的类型等腰直角三角形→ 提取已知条件直角边长度为 5cm→ 回忆勾股定理公式a²b²c²→ 代入数值计算斜边长度→ 验证计算结果是否符合图形比例”之后再给出明确的解题答案和最终结果分析图表数据如柱状图、折线图时思考过程会是“先确定图表类型为年度销售额折线图→ 解读横轴年份 2020-2024和纵轴销售额单位万元→ 提取各年份关键数据2020 年 800 万、2021 年 1200 万…→ 计算年度增长率2021 年同比增长 50%→ 分析增长趋势2022-2023 年增速放缓”再输出整合后的数据分析结论理解复杂视频如事件类短视频、监控画面时思考过程会围绕 “事件顺序、因果关系” 展开“先梳理视频帧中的关键场景第 1 帧车辆正常行驶第 3 帧行人横穿马路第 5 帧车辆刹车避让→ 还原事件时间线行人未走斑马线→ 司机发现后紧急刹车→ 未发生碰撞→ 提炼核心事件车辆避让违规横穿马路的行人”最终给出完整的视频内容总结。这种 “思考过程 最终答案” 的输出模式让模型的决策逻辑可追溯、可解释不仅能应对复杂视觉任务的深度分析需求还能帮助用户理解结论的由来尤其适合对逻辑严谨性要求高的场景如教育解题、专业数据分析、事件溯源等。二、代码实现以下是基于官方qvq-max模型支持思考过程输出的前后端分离后端接口实现包含请求实体、服务接口、实现类、控制器适配流式返回「思考过程 最终回复」第一步新增请求实体类QvqReasoningRequestpackage gzj.spring.ai.Request; import lombok.Data; import javax.validation.constraints.NotBlank; /** * QVQ模型推理请求参数支持思考过程最终回复流式输出 * author DELL */ Data public class QvqReasoningRequest { /** 图片URL支持HTTPS */ NotBlank(message 图片URL不能为空) private String imageUrl; /** 提问文本如解题、分析图片等 */ NotBlank(message 提问文本不能为空) private String question; /** 模型名称默认qvq-max需SDK≥2.19.0 */ private String modelName qvq-max; }第二步新增 QVQ 推理服务接口QvqReasoningServicepackage gzj.spring.ai.Service; import com.alibaba.dashscope.exception.ApiException; import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; import com.alibaba.dashscope.exception.UploadFileException; import gzj.spring.ai.Request.QvqReasoningRequest; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; /** * QVQ模型推理服务接口支持思考过程流式输出 * author DELL */ public interface QvqReasoningService { /** * QVQ模型流式推理返回思考过程最终回复 * param request 推理请求参数 * return SseEmitter 用于前端接收流式结果区分思考过程/最终回复 */ SseEmitter streamReasoningCall(QvqReasoningRequest request); }第三步新增 QVQ 推理服务实现类QvqReasoningServiceImplpackage gzj.spring.ai.Service.ServiceImpl; import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation; import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam; import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult; import com.alibaba.dashscope.common.MultiModalMessage; import com.alibaba.dashscope.common.Role; import com.alibaba.dashscope.exception.ApiException; import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; import com.alibaba.dashscope.exception.UploadFileException; import gzj.spring.ai.Request.QvqReasoningRequest; import gzj.spring.ai.Service.QvqReasoningService; import io.reactivex.Flowable; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.*; /** * QVQ模型推理服务实现支持思考过程最终回复流式输出 * 要求dashscope SDK版本 ≥ 2.19.0 * author DELL */ Slf4j Service public class QvqReasoningServiceImpl implements QvqReasoningService { Value(${dashscope.api-key}) private String apiKey; /** * 构建多模态消息图片文本 */ private MultiModalMessage buildUserMessage(QvqReasoningRequest request) { return MultiModalMessage.builder() .role(Role.USER.getValue()) .content(Arrays.asList( Collections.singletonMap(image, request.getImageUrl()), Collections.singletonMap(text, request.getQuestion()) )).build(); } /** * 构建请求参数开启增量输出 */ private MultiModalConversationParam buildConversationParam(QvqReasoningRequest request, MultiModalMessage userMsg) { return MultiModalConversationParam.builder() .apiKey(apiKey) .model(request.getModelName()) .messages(Arrays.asList(userMsg)) .incrementalOutput(true) // 增量输出流式核心 .build(); } /** * 处理流式结果拆分思考过程和最终回复推送到前端 */ private void handleStreamResult(MultiModalConversationResult result, SseEmitter emitter) { try { // 1. 处理思考过程reasoningContent String reasoning Optional.ofNullable(result.getOutput().getChoices().get(0).getMessage().getReasoningContent()).orElse(); if (!reasoning.isEmpty()) { // 推送思考过程事件名reasoning emitter.send(SseEmitter.event().name(reasoning).data(reasoning)); log.debug(推送思考过程片段{}, reasoning); } // 2. 处理最终回复text ListMapString, Object content result.getOutput().getChoices().get(0).getMessage().getContent(); if (content ! null !content.isEmpty()) { String text Optional.ofNullable(content.get(0).get(text)).orElse().toString(); if (!text.isEmpty()) { // 推送最终回复事件名answer emitter.send(SseEmitter.event().name(answer).data(text)); log.debug(推送回复片段{}, text); } } } catch (Exception e) { log.error(流式结果处理失败, e); handleEmitterError(emitter, 结果推送失败 e.getMessage()); } } /** * 统一处理SSE发射器异常 */ private void handleEmitterError(SseEmitter emitter, String errorMsg) { try { emitter.send(SseEmitter.event().name(error).data(errorMsg)); emitter.completeWithError(new RuntimeException(errorMsg)); } catch (Exception e) { log.error(发射器异常处理失败, e); } } /** * QVQ模型流式推理核心方法 */ Override public SseEmitter streamReasoningCall(QvqReasoningRequest request) { // 设置超时时间60秒推理类任务耗时更长 SseEmitter emitter new SseEmitter(60000L); new Thread(() - { MultiModalConversation conv new MultiModalConversation(); try { // 1. 构建用户消息和请求参数 MultiModalMessage userMsg buildUserMessage(request); MultiModalConversationParam param buildConversationParam(request, userMsg); // 2. 流式调用API FlowableMultiModalConversationResult resultFlow conv.streamCall(param); resultFlow.blockingForEach(result - handleStreamResult(result, emitter)); // 3. 流式结束标记 emitter.send(SseEmitter.event().name(complete).data(推理完成)); emitter.complete(); } catch (ApiException | NoApiKeyException | UploadFileException | InputRequiredException e) { log.error(QVQ模型API调用失败, e); handleEmitterError(emitter, API调用失败 e.getMessage()); } catch (Exception e) { log.error(QVQ模型流式推理未知异常, e); handleEmitterError(emitter, 系统异常 e.getMessage()); } }).start(); return emitter; } }第四步 VideoControllerpackage gzj.spring.ai.Controller; import com.alibaba.dashscope.exception.ApiException; import com.alibaba.dashscope.exception.NoApiKeyException; import com.alibaba.dashscope.exception.UploadFileException; import gzj.spring.ai.Request.QvqReasoningRequest; import gzj.spring.ai.Request.VideoFrameListRequest; import gzj.spring.ai.Request.VideoRequest; import gzj.spring.ai.Service.QvqReasoningService; import gzj.spring.ai.Service.VideoFrameListService; import gzj.spring.ai.Service.VideoService; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; /** * author DELL */ RestController RequestMapping(/api/multimodal/video) RequiredArgsConstructor CrossOrigin // 跨域支持生产环境建议限定域名 public class VideoController { private final VideoService videoService; private final VideoFrameListService videoFrameListService; private final QvqReasoningService qvqReasoningService; RequestMapping(/simple) public String simpleVideoCall(RequestBody VideoRequest request) throws ApiException, NoApiKeyException, UploadFileException { return videoService.simpleVideoCall(request); } /** * 视频帧列表理解-普通调用非流式 */ PostMapping(/simpleFrame) public String simpleFrameListCall(Validated RequestBody VideoFrameListRequest request) throws ApiException, NoApiKeyException, UploadFileException { return videoFrameListService.simpleFrameListCall(request); } /** * 视频帧列表理解-流式调用SSE推送 */ PostMapping(/streamFrame) public SseEmitter streamFrameListCall(Validated RequestBody VideoFrameListRequest request) { return videoFrameListService.streamFrameListCall(request); } /** * QVQ模型流式推理接口 * param request 推理请求参数图片URL提问文本 * return SseEmitter 流式返回结果 */ PostMapping(/stream-reasoning) public SseEmitter streamReasoning(Validated RequestBody QvqReasoningRequest request) { return qvqReasoningService.streamReasoningCall(request); } }三、演示参postman参数{ imageUrl: https://img.alicdn.com/imgextra/i1/O1CN01gDEY8M1W114Hi3XcN_!!6000000002727-0-tps-1024-406.jpg, question: 请解答这道题, modelName: qvq-max }结果一大串因为是流式的后续我们更新前端的页面就可以看到了总之测试结果没有问题。五、视觉推理模型核心总结QVQ 视觉推理模型服务实现类QvqReasoningServiceImpl实现过程详细总结该实现类是视觉推理模型QVQ 系列工程化落地的核心层基于 DashScope SDK≥2.19.0将官方控制台示例转化为适配前后端分离的 SSE 流式服务完整实现 “思考过程 最终回复” 的拆分推送其实现过程可拆解为初始化准备、参数构建、流式调用、结果解析推送、收尾与异常处理五大核心阶段具体如下一、初始化准备基础配置与线程模型搭建依赖注入与基础配置通过Value注入 DashScope 的 API Key作为调用模型的身份凭证定义 SSE 发射器SseEmitter超时时间为 60 秒适配视觉推理如数学题解读的长耗时特性避免过早断开连接。线程隔离设计创建独立线程处理流式调用逻辑避免 SSE 推送阻塞 Web 容器的请求线程保证接口响应性符合 Spring Web 的线程模型规范。二、前置参数构建贴合 SDK 规范封装输入核心是将前端请求参数转化为 DashScope SDK 要求的格式分为两步构建用户多模态消息通过buildUserMessage方法将请求中的imageUrl图片 HTTPS 链接和question提问文本封装为MultiModalMessage指定角色为USER内容按 “图片 文本” 的列表格式组织完全对齐 SDK 的消息结构要求。构建请求参数通过buildConversationParam方法基于MultiModalConversationParam构建器配置核心参数 ——API Key、模型名默认qvq-max支持请求自定义、消息列表并开启incrementalOutput(true)增量输出确保模型返回流式结果而非一次性返回。三、流式 API 调用对接 SDK 的流式能力实例化MultiModalConversation客户端调用streamCall方法传入构建好的参数获取FlowableMultiModalConversationResult类型的流式结果RxJava 流适配 SDK 的响应式设计通过blockingForEach遍历流式结果逐段处理模型返回的每一批数据增量输出的核心载体。四、流式结果解析与 SSE 推送拆分 “思考过程 最终回复”这是视觉推理模型 “先思考、后回答” 核心特性的工程化落地通过handleStreamResult方法实现精细化解析思考过程解析推送提取结果中的ReasoningContent字段QVQ 模型专属需 SDK≥2.19.0通过Optional.ofNullable做空值保护非空时以 SSE 事件名reasoning推送前端可单独监听思考过程最终回复解析推送解析结果中content列表的text字段同样做空值保护非空时以 SSE 事件名answer推送与思考过程拆分便于前端差异化渲染日志埋点为每段推送的思考过程 / 回复片段添加调试日志便于问题排查。五、流式收尾与异常处理保证服务健壮性正常收尾所有流式结果处理完成后推送complete事件内容为 “推理完成”调用emitter.complete()关闭 SSE 连接释放资源异常分层处理捕获 SDK 专属异常ApiException/NoApiKeyException/UploadFileException等定位模型调用层面的问题如 API Key 错误、图片无法读取捕获通用异常Exception兜底处理未知错误异常标准化推送通过抽离的handleEmitterError工具方法统一推送error事件携带错误信息调用emitter.completeWithError()标记异常结束保证前端能感知错误类型工具方法复用将 SSE 异常处理逻辑抽离为独立方法减少代码冗余保证异常处理逻辑的一致性。核心设计细节与适配点事件拆分设计按reasoning/answer/error/complete四类 SSE 事件拆分输出精准贴合视觉推理模型 “先输出思考过程、再输出回答” 的核心特性前端可按需监听不同事件实现差异化渲染健壮性保障全链路空值保护Optional、分层异常捕获避免空指针或单一异常导致服务崩溃扩展性设计模型名通过请求参数自定义无需修改代码即可切换 QVQ 系列其他模型工程化适配完全贴合 Spring Boot 服务层规范可直接集成到现有多模态服务体系中与此前的图片 / 视频理解服务保持一致的代码风格和异常处理逻辑。综上该实现类的核心价值是将 QVQ 视觉推理模型的 “思考 回答” 能力从官方示例的控制台输出转化为工程化、可复用、适配前后端分离的 SSE 流式服务既保留了模型的核心特性又符合企业级后端开发的规范与健壮性要求。