AIWear 智能衣橱项目实战(总览):我把衣柜接入了 AI

AIWear 智能衣橱项目实战(总览):我把衣柜接入了 AI

AIWear 智能衣橱项目实战(总览):我把衣柜接入了 AI

Spring Boot × LangChain × CLIP:多模态项目从开发到云端部署

如果一个衣物管理系统只能上传图片、显示图片,那么它和普通网盘并没有本质区别。我希望 AIWear 能真正理解图片:知道图片里有什么,允许用户用文字或另一张图片找到它,还能根据自然语言指令编辑或合并图片。

这个想法最终变成了一套由 Vue、Spring Boot 和 Python AI 服务共同组成的应用。它既包含用户、文件、数据库、鉴权等传统软件系统能力,也包含图片理解、向量检索和 Agent 工具调用等 AI 能力。更重要的是,这些模块已经被连接成了从浏览器到云服务器的完整业务流程。

AIWear 能做什么

目前项目包含以下核心功能。

1. 两种方式完成登录或注册

用户可以使用邮箱验证码,也可以使用用户名和密码。邮箱验证码暂存在 Redis 中并设置五分钟有效期;用户名密码使用 BCrypt 保存 Hash;认证成功后由后端生成 JWT,前端后续通过Authorization: Bearer <token>携带身份。

对应接口:

POST /api/user/send-code POST /api/user/auth POST /api/user/logout

2. 上传并管理自己的图片

图片上传并不是直接存入服务器目录。Java 后端先检查文件类型和大小,再调用 Python 服务判断图片是否属于服装、穿搭或人物范围。验证通过后,图片被上传到阿里云 OSS,文件名、大小、用户 ID 和 OSS 地址写入 MySQL。

对应接口:

POST /api/file/upload/image GET /api/file/my-images

3. 使用文字或图片搜索

每张上传成功的图片还会进入 AI 索引流程。Python 从 OSS 下载图片,调用视觉模型生成描述,并用本地 CLIP 模型生成归一化的 512 维图片向量,随后将描述、向量、用户 ID 和 OSS 地址保存到 Redis。

当前代码支持两条检索路径:

  • 文搜图:在视觉模型生成的图片描述中进行文本匹配。
  • 图搜图:将查询图片转换为 CLIP 向量,与已有图片向量计算余弦相似度。

需要特别说明:当前版本没有使用 CLIP 文本编码器做跨模态文本向量检索。文搜图使用描述匹配,图搜图使用 CLIP 向量。这是当前实现的真实边界,也是后续可以继续优化的方向。

对应接口:

POST /api/file/search

4. 使用自然语言编辑或合并图片

蓝色”或“让人物穿上第一张图中的衣服”。Java 校验图片归属后,将用户选择自己上传的图片并输入指令,例如“把衣服改成图片和指令发送给 Python。

Python 中的 Agent 根据输入参数判断应该调用哪个工具:

  • 只有image_path时调用edit_image_tool
  • 同时存在image_path1image_path2时调用merge_image_tool

工具调用 DashScope 图像编辑模型并返回结果 URL。为了避免业务长期依赖模型提供的临时地址,Java 会再次下载结果,并上传到项目自己的 OSS,最后保存操作记录。

对应接口:

POST /api/file/edit POST /api/file/merge GET /api/record/my

整体架构

数据与文件

Python AI 服务

Java 业务服务

访问入口

客户端

推理并选择工具

页面请求与 /api 请求

/api 反向代理

业务数据

验证码与 JWT 状态

上传原图和生成结果

HTTP 调用

图片描述与向量索引

通过 OSS URL 下载图片

浏览器

Vue 3 + Pinia + Axios

Nginx :80
静态资源 + /api 反向代理

Controller
接收参数与统一响应

Service
鉴权与业务编排

MyBatis-Plus Mapper

PythonAiService
跨服务适配层

Flask API :5000

Qwen-VL
图片描述

Qwen Plus
内容审核与 Agent 决策

CLIP ViT-B/16
图片向量

Deep Agent
Skill + Tool

Qwen Image Edit

MySQL
用户 / 文件 / 记录

Redis
验证码 / JWT / AI 索引

阿里云 OSS
原图与处理结果

这个架构可以分成三条主线。

Java 业务系统线

Spring Boot 是系统的业务中心,负责:

  • 接收前端请求并完成参数转换。
  • 解析 JWT,确定当前用户。
  • 约束用户只能操作自己的图片。
  • 读写 MySQL、Redis 和 OSS。
  • 调用 Python 服务并处理返回结果。
  • 使用Result<T>统一前端响应。
  • 使用 AOP 记录带有@ApiLog的接口调用。

传统业务能力留在 Java,可以保持数据一致性、权限边界和接口结构清晰。

Python AI 能力线

Python 服务集中负责更适合 Python 生态的工作:

  • 使用 LangChain 调用通义千问模型。
  • 使用 Transformers 和 PyTorch 加载本地 CLIP。
  • 生成图片描述和图片向量。
  • 计算搜索相似度。
  • 创建 Deep Agent,并注册图片编辑和合并工具。

Java 不需要理解模型加载和推理细节,只依赖稳定的 HTTP 接口。

部署与基础设施线

Docker Compose 管理 MySQL、Redis 和 Nginx。Java JAR 与 Python Flask 服务运行在 Linux 宿主机上,Nginx 容器通过host.docker.internal/api请求转发到宿主机的8081端口。

前端执行npm run build后生成dist,再挂载进 Nginx 容器。这样用户只需要访问 80 端口,不需要感知 Java 和 Python 的内部端口。

一张图片上传后经历了什么

下面这条流程连接了项目中的大部分组件。

RedisMySQLOSSPython AISpring BootNginxVue用户RedisMySQLOSSPython AISpring BootNginxVue用户multipart/form-data + Bearer TokenJSON:userId + ossUrl当前实现记录警告,基础上传仍成功alt[索引成功][索引失败]alt[图片不符合要求][图片符合要求]选择图片并点击上传POST /api/file/upload/image反向代理到 8081解析 JWT、检查类型和大小POST /api/validate-imageQwen-VL 生成描述Qwen Plus 判断业务范围allow=true/false返回业务错误上传失败上传原图返回 OSS URL写入 files 表POST /api/upload-image通过 URL 下载图片生成描述与 CLIP 向量保存图片 AI 索引返回 imageId、描述和向量维度返回错误或调用异常Result<FileUploadResponse>返回上传结果显示上传结果

这条链路体现了 AIWear 的核心设计:Java 控制业务顺序和数据归属,Python提供模型能力,MySQL保存可查询的业务事实,Redis保存短期状态和 AI 索引,OSS承担文件存储。

Agent、Skill 和 Tool 在项目里分别做什么

这三个概念容易混在一起,在 AIWear 中可以这样理解:

  • Tool 是可执行函数。edit_image_toolmerge_image_tool真正读取图片并调用图像模型。
  • Skill 是写给 Agent 的操作说明。SKILL.md描述何时使用工具及输入输出要求。
  • Agent 是决策和编排者。它阅读当前输入、工具参数和 Skill 说明,选择工具并组织调用参数。

Java 传给 Python 的不是一句模糊聊天内容,而是图片文件和明确的操作指令。Python 再将临时文件路径组织成 Prompt:

instruction: 把衣服改成蓝色 image_path: /tmp/aiwear_xxx.bin

Agent 根据存在的字段选择edit_image_tool。两张图片时字段变为image_path1image_path2,Agent 则选择merge_image_tool

数据分别保存在哪里

数据保存位置原因
用户、文件、操作记录MySQL结构固定、需要持久化查询
邮箱验证码Redis有过期时间,验证后立即删除
JWT 缓存Redis支持复用、登出和服务端失效
图片描述与向量Redis当前版本便于快速读取和相似度计算
原图与处理结果OSS文件体积大,不适合直接放入数据库
前端静态资源Nginx 挂载目录直接通过 80 端口访问
CLIP 模型Python 服务本地目录避免每次启动从网络下载

我从项目中真正学到了什么

项目最有价值的部分不是记住某个注解或某条 Docker 命令,而是理解不同组件如何共同完成一条业务链路:

  1. 前端请求格式必须和 Java Controller 的参数来源一致。
  2. Controller 只负责接口边界,Service 负责业务编排。
  3. Java 与 Python 的连接本质上是一组明确的 HTTP 契约。
  4. 模型生成的结果仍然需要权限校验、持久化和错误处理。
  5. Redis、MySQL 和 OSS 解决的是不同类型的数据问题。
  6. 本地可运行不等于服务器可部署,环境变量、网络边界和进程管理同样重要。

当前实现边界

为了准确描述项目,当前版本仍有以下可改进点:

  • 文搜图目前使用图片描述的关键词匹配,可升级为 CLIP 文本向量或独立 Embedding 服务。
  • Python 使用 Flask 开发服务器,正式部署可改为 Gunicorn 等 WSGI 服务。
  • Java 跨服务调用使用直接创建的RestTemplate,可增加统一超时、重试和错误映射。
  • 自动化测试覆盖较少,需要补充 Service、Controller 和 Python API 测试。
  • Java 与 Python 目前使用后台命令运行,可改为 systemd 或容器化服务。
  • 代码中部分早期中文文本存在编码显示问题,需要统一为 UTF-8。