Files
openclaw-config/workspace-backend/memory/2026-05-28.md
T

50 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 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` + `recognizedName`AI 原始名)+ `exactMatch`(前端据此标记需确认)
- `RecognitionItem``materialId` + `materialName` + `materialCode` + `spec` + `unit` + `recognizedName` + `quantity` + `price` + `exactMatch`
- 厂商用 `Counterparty` 统一供应商和客户;物料用 `MaterialFillService.getMaterialInfo()` 补全编码/规格/单位
### 物料模糊匹配(三重降级)
1. **去空格 LIKE**`REPLACE(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.yml`localhost:31983)而不是 Docker 测试库
- `mvn test -pl :tiny-erp -Dtest=AiControllerTest -Dspring.profiles.active=local -Dmaven.test.failure.ignore=false`