设计网站做多大合适,企业网站需要什么,php企业网站模板下载,wordpress站点大全一、概论 官方给出的解释#xff1a;视觉推理模型能够先输出思考过程#xff0c;再输出回答内容#xff0c;适用于处理复杂的视觉分析任务#xff0c;如解读数学题、分析图表数据或复杂视频理解等任务。 简单来说#xff0c;视觉推理是人工智能的一个分支#xff0c;核心…一、概论官方给出的解释视觉推理模型能够先输出思考过程再输出回答内容适用于处理复杂的视觉分析任务如解读数学题、分析图表数据或复杂视频理解等任务。简单来说视觉推理是人工智能的一个分支核心是让模型像人一样 “看懂” 图像并进行逻辑分析而非仅识别表面元素。只要训练好智能体你甚至可以拍摄一个人的样貌然后智能体可以根据知识库来判断出一个人的心理活动当然这需要大量的训练二、视觉推理模型核心技术与典型应用清单核心是通过 “图像理解 逻辑推理” 实现复杂视觉任务处理以下是关键技术与落地场景梳理1、核心技术支撑模型推理能力多模态融合技术将图像像素信息与文字、数学符号等跨模态数据关联打破单一模态的信息局限。视觉元素解析技术精准提取图像中的关键元素如图表的坐标轴 / 数据点、数学题的图形条件、视频的场景物体。逻辑推理引擎基于提取的信息搭建推理链条处理因果、逻辑运算、数据关联等复杂关系。可解释性模块专门生成推理过程把 “如何从图像到结论” 的步骤清晰输出提升结果可信度。2、典型应用场景落地价值体现教育领域解读数学几何题、物理示意图拆解解题条件与推导步骤。数据处理领域分析柱状图 / 折线图 / 饼图不仅提取数字还计算增长率、占比、趋势变化。视频分析领域理解长视频中的事件逻辑如监控视频中异常行为的因果推导、影视剧情的关键情节梳理。医疗领域辅助解读医学影像结合病灶形态与临床知识推理可能病症及诊断依据。工业领域质检时识别产品缺陷同时推理缺陷产生的可能环节如零件装配偏差、材料问题。三、代码实现在前文 大模型通义千问3-VL-Plus - 视觉理解-CSDN博客 中我们已经简单的写了一个需要https图片链接的视觉理解功能现在我们改造一下要做到可以上传本地文件。1、Base64通义千问VL 提供两种本地文件上传方式Base64 编码上传和文件路径直接上传。可根据文件大小、SDK类型选择上传方式.两者的区别Base64编码将文件转换为 Base64 编码字符串再传入模型。适用于 OpenAI 和 DashScope SDK 及 HTTP 方式本地文件路径直接向模型传入本地文件路径仅 DashScope Python 和 Java SDK 支持不支持 DashScope HTTP 和OpenAI 兼容方式。这里为了方便各位后续可以使用 OpenAI 的内容所以我们直接用 Base64编码当然我也会给出本地文件路径的核心修改代码但是就不做演示啦。注意通义千问VL API对单张图像编码后的视觉 Token 数量设有限制默认配置下高分辨率图像会被压缩可能丢失细节影响理解准确性。启用vl_high_resolution_images或调整max_pixels可增加视觉 Token 数量从而保留更多图像细节提升理解效果。1.1 调整请求参数实体MultimodalRequest新增本地图片路径字段用于接收本地文件路径二选一imageUrl 传网络图片localImagePath 传本地图片import lombok.Data; Data public class MultimodalRequest { /** 图片URL */ private String imageUrl; /** 提问文本 */ private String question; /** 本地图片路径如/usr/local/images/test.png 或 D:/images/test.jpg */ private String localImagePath; }1.2 修改核心服务类MultimodalServiceImpl核心修改说明新增工具方法encodeLocalImageToBase64读取本地图片文件并转换为带data:image/xxx;base64,前缀的 Base64 字符串兼容 png/jpg/jpeg 格式buildImageContent统一处理图片来源优先本地文件其次网络 URL避免重复逻辑handleEmitterError统一处理 SSE 发射器的异常推送简化代码兼容两种图片来源通过判断localImagePath/imageUrl是否为空自动选择图片处理方式本地图片转 Base64 后传入 API网络图片直接传入 URL完善异常处理新增IOException捕获本地文件读取失败新增参数校验必须传入图片来源流式调用中统一异常处理确保前端能收到错误信息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.NoApiKeyException; import com.alibaba.dashscope.exception.UploadFileException; import gzj.spring.ai.Request.MultimodalRequest; import gzj.spring.ai.Service.MultimodalService; 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.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.Base64; /** * 多模态服务封装支持网络图片URL 本地图片文件 * author DELL */ Slf4j Service public class MultimodalServiceImpl implements MultimodalService { Value(${dashscope.api-key}) private String apiKey; /** * 工具方法将本地图片编码为Base64字符串带data:image前缀 * param localPath 本地图片绝对路径 * return 带前缀的Base64字符串 * throws IOException 文件读取异常 */ private String encodeLocalImageToBase64(String localPath) throws IOException { Path imagePath Paths.get(localPath); // 校验文件是否存在 if (!Files.exists(imagePath)) { throw new IOException(本地图片文件不存在 localPath); } // 读取文件并编码 byte[] imageBytes Files.readAllBytes(imagePath); String base64Str Base64.getEncoder().encodeToString(imageBytes); // 自动识别图片格式支持png/jpg/jpeg String suffix localPath.substring(localPath.lastIndexOf(.) 1).toLowerCase(); if (!Arrays.asList(png, jpg, jpeg).contains(suffix)) { suffix png; // 默认png格式 } return String.format(data:image/%s;base64,%s, suffix, base64Str); } /** * 工具方法构建图片内容兼容URL/本地文件 * param request 请求参数 * return 图片内容字符串URL或Base64 * throws IOException 本地文件读取异常 */ private String buildImageContent(MultimodalRequest request) throws IOException { // 优先级本地文件 网络URL可根据业务调整 if (request.getLocalImagePath() ! null !request.getLocalImagePath().isEmpty()) { log.info(使用本地图片{}, request.getLocalImagePath()); return encodeLocalImageToBase64(request.getLocalImagePath()); } else if (request.getImageUrl() ! null !request.getImageUrl().isEmpty()) { log.info(使用网络图片URL{}, request.getImageUrl()); return request.getImageUrl(); } else { throw new IllegalArgumentException(必须传入imageUrl网络图片或localImagePath本地图片); } } /** * 普通调用非流式- 支持网络/本地图片 */ Override public String simpleCall(MultimodalRequest request) throws ApiException, NoApiKeyException, UploadFileException, IOException { MultiModalConversation conv new MultiModalConversation(); // 构建图片内容兼容URL/本地文件 String imageContent buildImageContent(request); // 构建用户消息图片文本 MultiModalMessage userMessage MultiModalMessage.builder() .role(Role.USER.getValue()) .content(Arrays.asList( Collections.singletonMap(image, imageContent), Collections.singletonMap(text, request.getQuestion()) )).build(); // 构建请求参数 MultiModalConversationParam param MultiModalConversationParam.builder() .apiKey(apiKey) .model(qwen3-vl-plus) .messages(Arrays.asList(userMessage)) .build(); // 同步调用 MultiModalConversationResult result conv.call(param); // 解析返回结果 ListMapString, Object content result.getOutput().getChoices().get(0).getMessage().getContent(); if (content ! null !content.isEmpty()) { return content.get(0).get(text).toString(); } return 未获取到有效结果; } /** * 流式调用SSE推送- 支持网络/本地图片 */ Override public SseEmitter streamCall(MultimodalRequest request) { // 设置超时时间30秒 SseEmitter emitter new SseEmitter(30000L); new Thread(() - { MultiModalConversation conv new MultiModalConversation(); try { // 构建图片内容兼容URL/本地文件 String imageContent buildImageContent(request); // 构建用户消息 MultiModalMessage userMessage MultiModalMessage.builder() .role(Role.USER.getValue()) .content(Arrays.asList( Collections.singletonMap(image, imageContent), Collections.singletonMap(text, request.getQuestion()) )).build(); // 构建请求参数 MultiModalConversationParam param MultiModalConversationParam.builder() .apiKey(apiKey) .model(qwen3-vl-plus) .messages(Arrays.asList(userMessage)) .incrementalOutput(true) // 增量输出流式 .build(); // 流式调用 FlowableMultiModalConversationResult resultFlow conv.streamCall(param); resultFlow.blockingForEach(item - { try { ListMapString, Object content item.getOutput().getChoices().get(0).getMessage().getContent(); if (content ! null !content.isEmpty()) { String text content.get(0).get(text).toString(); // 推送流式数据到前端 emitter.send(SseEmitter.event().data(text)); } } catch (Exception e) { log.error(流式推送单条数据失败, e); try { emitter.send(SseEmitter.event().name(error).data(数据推送失败 e.getMessage())); } catch (Exception ex) { log.error(推送错误信息失败, ex); } } }); // 流式结束标记 emitter.send(SseEmitter.event().name(complete).data(流结束)); emitter.complete(); } catch (IOException e) { log.error(读取本地图片失败, e); handleEmitterError(emitter, 读取本地图片失败 e.getMessage()); } catch (ApiException | NoApiKeyException | UploadFileException e) { log.error(多模态API调用失败, e); handleEmitterError(emitter, API调用失败 e.getMessage()); } catch (IllegalArgumentException e) { log.error(请求参数异常, e); handleEmitterError(emitter, 参数错误 e.getMessage()); } catch (Exception e) { log.error(流式调用未知异常, e); handleEmitterError(emitter, 系统异常 e.getMessage()); } }).start(); return emitter; } /** * 工具方法统一处理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); } } }2、 本地路径如果只做传本地路径只需要修改以下内容四、效果示例五、总结本次代码修改围绕让多模态服务同时兼容 HTTPS 网络图片和本地图片文件展开核心总结如下一、核心目标在保留原有 “普通调用非流式” 和 “流式调用SSE 推送” 能力的基础上新增本地图片处理能力实现「网络图片 URL」和「本地图片文件」两种输入方式的无缝兼容。二、关键改动请求参数扩展给MultimodalRequest新增localImagePath字段与原有imageUrl字段配合分别接收本地图片绝对路径、HTTPS 图片 URL二选一传入。新增核心工具方法encodeLocalImageToBase64读取本地图片文件校验文件存在性自动识别 png/jpg/jpeg 格式并转换为带data:image/xxx;base64,前缀的 Base64 字符串符合通义千问 VL 模型要求buildImageContent统一处理图片来源优先本地文件其次网络 URL可灵活调整优先级参数校验确保必传图片来源handleEmitterError流式调用中统一处理异常向前端推送标准化错误信息简化异常处理逻辑。核心业务方法改造simpleCall/streamCall均接入buildImageContent方法无需改动原有模型调用、参数构建、结果解析逻辑仅扩展图片内容构建环节新增IOException文件读取、IllegalArgumentException参数缺失等异常捕获覆盖本地图片处理的异常场景。三、核心能力双源兼容调用时只需传入imageUrl网络图或localImagePath本地图无需修改调用逻辑格式自适应自动识别本地图片格式默认兜底 png避免格式不兼容问题异常友好文件不存在、参数缺失、API 调用失败等场景均有明确错误提示流式调用错误可实时推送到前端。四、使用与注意事项使用方式网络图片传imageUrl字段保持原有调用逻辑本地图片传localImagePath字段需绝对路径自动转 Base64 后调用 API。关键注意本地图片需保证应用进程有文件读取权限图片大小需符合通义千问 VL 模型要求单张≤10MBLinux/Windows 路径分隔符需适配Linux 用/Windows 用\\或/图片源优先级可通过修改buildImageContent的判断逻辑调整。希望这个兼容网络图 本地图的多模态服务小改造能帮到正在折腾 AI 开发的你呀✨ 代码跑通的瞬间是不是超有成就感如果觉得这份修改实用、总结清晰别忘了动动小手点个赞再关注一下呀 后续还会分享更多 AI 接口封装、代码优化的干货技巧一起解锁更多好用的功能少踩坑多提效 你的支持就是我更新的最大动力咱们下次分享再见呀