兄弟们,最近通过springAI做了一个小功能,调用阿里的通义千问VL模型(也可以是其他AI模型),实现拍照识花功能。代码可以自取。

代码地址https://gitcode.com/m0_68450099/pimode

先看效果:

  • 上传一张花的图片 → 返回花名

  • 可以问“这花适合室内养吗?” → AI结合图片回答问题

  • 平均响应1-2秒

再说人话:这就是一个能直接跑通的SpringBoot项目,不是PPT,不是概念,你把代码拉下来,改个API Key,就能看到识别结果。


一、为什么做这个

说实话,市面上AI识花的App很多,拍照就能识别,挺方便。但问题是——那些代码你能拿到吗?能集成到你自己做的系统里吗?

不能。

我想给自己的小项目加个“拍照识物”功能,但又不想从头研究怎么调用AI接口、怎么处理图片、怎么做缓存限流。于是就折腾了这套代码,把它做成一个可以直接用的模板

识花只是举例。你想识车、识动物、识商品,改几句提示词就行。


二、能干什么

功能 说明
图片上传识别 支持JPG/PNG/WEBP,最大10MB
附加提问 不光是识花,还能问养护、花语
图片自动压缩 省Token = 省钱
缓存去重 相同图片秒返回,不重复调API
IP限流 一分钟最多10次,防刷
前端页面 拖拽上传,开箱即用

三、技术栈(都是Java老熟人了)

技术 版本 干啥用的
Java 17+ 后端语言
Spring Boot 3.4.4 框架
通义千问VL qwen-vl-max-latest 能看懂图片的AI模型
Spring AI Alibaba 1.0.0-M6.1 阿里官方封装,几行代码调AI
Maven - 包管理
Vue 3 - 前端页面(就一个html文件)

四、5分钟跑起来

第1步:搞到API Key

阿里云DashScope控制台注册,创建API Key。

新用户有免费额度,识别几千张花没问题。

第2步:下载代码

bash

git clone https://gitcode.com/m0_68450099/pimode.git
cd pimode

第3步:配置Key

1.推荐使用启动命令配置Key

  java -jar pimode-1.0-SNAPSHOT.jar --spring.ai.dashscope.api-key=sk-你的key

2.如果在本地使用idea,可以在环境变量中配置key

    Run → Edit Configurations → Environment variables →

     添加:DASHSCOPE_API_KEY=sk-你的key

3.如果觉得麻烦,可以放在yal中:

     打开 src/main/resources/application.yml

    yaml

  spring:
    ai:
      dashscope:
        api-key: sk-这里填你的key   # 就改这一个地方

第4步:启动后端

bash

mvn clean install
mvn spring-boot:run

看到这行字就成功了:

text

🌼 拍照识花服务已启动!访问 http://localhost:8080

第5步:打开前端

用浏览器打开项目根目录下的 index.html

后端地址填 http://localhost:8080,上传一张花的图片,点识别,等结果。


五、核心代码长啥样

我把关键代码贴出来,你可以看看,不复杂。

1. AI调用(核心就这几行)

java

// 把图片和问题打包
UserMessage msg = new UserMessage(
    "这是什么花?只回复花名",
    new Media(MediaType.IMAGE_JPEG, 图片文件)
);

// 发给AI,拿结果
String result = chatClient.prompt(msg).call().content();

就是发请求、等响应,和调普通HTTP接口差不多。

2. 图片压缩(省Token的关键)

java

// 压缩到400x400以内,质量50%
private static final int MAX_WIDTH = 400;
private static final float JPEG_QUALITY = 0.5f;

一张5MB的原图压缩完大概50KB,Token消耗能降90%。缺点是细节可能丢失,如果识别不准可以调大参数。

3. 缓存(相同图片不重复调AI)

java

// 计算图片MD5
String md5 = MD5Util.getMD5(图片字节);
// 查缓存
String cached = cacheService.get(md5);
if (cached != null) return cached;  // 命中,直接返回
// 没命中才调AI

同样的图片第二次识别,从2秒变0.1秒。

4. 限流(防刷)

java

@RateLimit(timeWindow = 60, maxRequests = 10)
@PostMapping("/upload")
public Result<String> upload(...) {
    // 同一个IP一分钟最多10次请求
}

六、说实话,缺点也有

这个项目做的时候就定位是“能用”,不是“完美”。有这几个问题,我说清楚:

❌ 没有向量数据库

AI没法“学习”新品种。如果你想让它认识一株市面上没有的花,做不到。除非往system prompt里塞文字描述,但那样每次调用都多消耗Token。

❌ 压缩参数要自己调

400x400、质量0.5这个配置是我在自己测试图上调出来的。你的业务场景可能需要更大或更小的压缩。代码里参数是写死的,你得自己改、自己试。

❌ 缓存存在内存里

服务重启缓存就没了。只适合单机跑。真要上生产,换成Redis也就十几行代码的事,但我没写,留给你自己加。

❌ 限流也是内存版

同样重启丢、多实例不共享。生产环境需要改。


七、怎么改造成其他识别

想改成识车、识动物?改一行提示词就行:

java

// 原来
private static final String DEFAULT_QUESTION = "这是什么花?只回复花名";

// 改成识车
private static final String DEFAULT_QUESTION = "这是什么车的哪款车型?";

// 改成识动物
private static final String DEFAULT_QUESTION = "这是什么动物?";

压缩参数可能需要根据你的图片重新调一下。


八、代码结构速览

text

pimode/
├── .idea/                          # IDEA配置文件
├── src/
│   ├── main/
│   │   ├── frontend/               # 前端代码,简易前端页面,可直接使用
│   │   ├── java/com/jrl/
│   │   │   ├── annotation/         # 注解
│   │   │   │   └── RateLimit.java      # 限流注解
│   │   │   ├── cache/              # 缓存
│   │   │   │   └── ImageCache.java     # 内存缓存
│   │   │   ├── common/             # 公共类
│   │   │   │   └── Result.java         # 统一响应格式
│   │   │   ├── config/             # 配置类
│   │   │   │   ├── CorsConfig.java     # 跨域配置
│   │   │   │   └── WebConfig.java      # Web配置(拦截器)
│   │   │   ├── controller/         # 控制器
│   │   │   │   └── FlowerController.java
│   │   │   ├── interceptor/        # 拦截器
│   │   │   │   └── RateLimitInterceptor.java
│   │   │   ├── service/            # 服务层
│   │   │   │   ├── FlowerService.java
│   │   │   │   └── impl/
│   │   │   │       └── FlowerServiceImpl.java
│   │   │   ├── util/               # 工具类
│   │   │   │   └── MD5Util.java
│   │   │   └── FlowApplication.java # 启动类
│   │   ├── resources/              # 配置文件
│   │   │   └── application.yml
│   │   └── index.html              # 前端页面(根目录)
│   └── test/                       # 单元测试
├── README.md
└── pom.xml

九、生产环境需要补什么

如果你想把这个项目用到线上,下面这几样东西你自己需要加上:

缺啥 咋补
缓存重启丢 ImageCache里的Map换成Redis
限流不持久 RateLimitInterceptor里的Map换成Redis + 令牌桶
并发高了扛不住 加个异步队列,别让AI调用堵住
想让AI学习新品种 接向量数据库做RAG
我的配置不合适你 自己调MAX_WIDTHJPEG_QUALITY

但这些不在本项目范围内。这个项目给的是一套能跑通的示例,不是生产级框架。


十、最后说两句

这个项目不大,却是一个完整的、能跑的、Java调用通义千问VL的示例。

你觉得有用,就拿去改、拿去用。
你觉得不合适,就看看别的。

代码需要的自取:

👉 https://gitcode.com/m0_68450099/pimode

有问题提Issue,我看到了会回。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐