Files

2.9 KiB
Raw Permalink Blame History

20:31 - AI 模块新增完成

改动

  1. 新增 module/ai/ 模块,包含完整的目录结构:
    • config/: AiProperties (baseUrl/apiKey/model 配置), AiRestConfig (RestTemplate Bean)
    • controller/AiController: 3 个端点
    • dto/: DeepSeekChatRequestDTO/ResponseDTO (OpenAI 兼容格式), AiChatRequestDTO/ResponseDTO, ImageUploadResponseDTO
    • service/: AiService 接口 + AiServiceImpl 实现
  2. API 端点
    • POST /ai/upload — 图片上传转 base64
    • POST /ai/chat?text=... — 纯文本对话
    • POST /ai/chat-multi — 多模态(文本+图片 multipart
  3. DeepSeek 配置baseUrl=http://192.168.2.74:3000/v1, model=deepseek-v4-flash(保存在 AiProperties,可通过 yaml 覆写)
  4. 集成测试AiControllerTest):4 个用例全绿
    • 登录 + 图片上传 + 纯文本对话 + 多模态对话
    • 注意:测试图片从 1x1 改为 32x32(模型要求最小 10x10

21:23 - AI 单据识别模块(深刻优化)

业务背景

  • 前端上传采购单/销售单照片 → 后端调 AI 识别 → 模糊匹配供应商/客户/物料 ID → 返回前端表单
  • AI 返回的是自然语言文本("8.5玻璃棒"),后端需要匹配到 DB 中的 Material.id

关键实现决策

DTO 设计(AiRecognitionResultDTO

  • typeValue (Integer: 10/20/30) + typeName (String: 采购入库/销售出库) — 符合后端 Inbound/Outbound 实体字段
  • Counterparty:封装 id + name + recognizedNameAI 原始名)+ exactMatch(前端据此标记需确认)
  • RecognitionItemmaterialId + materialName + materialCode + spec + unit + recognizedName + quantity + price + exactMatch
  • 厂商用 Counterparty 统一供应商和客户;物料用 MaterialFillService.getMaterialInfo() 补全编码/规格/单位

物料模糊匹配(三重降级)

  1. 去空格 LIKEREPLACE(name, ' ', '') 匹配 AI 返回的无空格文本
  2. 分词 LIKE:按非数字/非CJK字符切割,最长片段单独搜索
  3. 数字+CJK 分离"8.5玻璃棒" → 数字段 "8.5" + 汉字段 "玻璃棒",分别搜索后交叉匹配

最终 4 条物料测试全部匹配:

  • 8.5玻璃棒8.5 玻璃棒 (id=31)
  • 4.0玻璃棒8.5 玻璃棒 (id=31) ⚠️ 数字不同但物料名匹配(允许用户调整)
  • 透明A级560*270*61透明 A 级 560*270*61 (id=39)
  • 透明A级580*200*31透明 A 级 580*200*17 (id=40) ⚠️ 规格相近

供应商/客户模糊匹配

  • 去空格 LIKE → 分词 → 最长片段搜索 → 双词组合
  • 待补充:后缀切割降级("老兵店"去掉"店"→"老兵"→匹配"老兵水晶店"

测试

  • 4 个测试用例全绿
  • 使用 application-local.ymllocalhost:31983)而不是 Docker 测试库
  • mvn test -pl :tiny-erp -Dtest=AiControllerTest -Dspring.profiles.active=local -Dmaven.test.failure.ignore=false