--- name: tokenhub 与 model 对齐优化 overview: 优化 tokenhub 包:让穿搭推荐充分利用 Clothes 模型字段、将品类枚举统一为 6 大类、整理运势映射与公共结构,使代码与 mysqlmodel 数据模型对齐。 todos: - id: refactor-client content: 更新 client.go 包注释并将 chatResponse 结构下沉至 client.go status: completed - id: fortune-model-align content: 为 FortuneItem 新增 ToHoroscope 方法并让 scheduler.go 改用 status: completed - id: outfit-fields-enum content: 重写 FormatClothesInfo 补全字段并统一六类品类枚举与 prompt/schema status: completed - id: outfit-validate content: 增强 ValidateClothesIDs 类型对齐与去重,GetClothesIDs 去重 status: completed dependencies: - outfit-fields-enum - id: verify-build content: 执行 go build 与 go vet 验证 tokenhub 包编译通过 status: completed dependencies: - refactor-client - fortune-model-align - outfit-fields-enum - outfit-validate --- ## 产品概述 对 `pkg/tokenhub` 包做一次与数据模型(`mysqlmodel`)对齐的代码优化,使穿搭推荐和星座运势生成更贴合现有 `Clothes`、`Horoscope` 等模型定义,提升 LLM 推荐质量与代码可维护性。仅改动 tokenhub 包内代码,不接入新接口、不修改 `main.go`。 ## 核心功能 - **穿搭推荐字段补全**:将传给大模型的衣物摘要从 8 个字段扩充到 `Clothes` 模型的完整穿搭属性(副色、厚度、袖型、衣长、领型、正式度、场合、视觉冲击力、名称等),并采用「字段名:值」标注格式,让模型准确理解每项属性。 - **品类枚举统一为 6 大类**:将推荐品类从「上装/下装/鞋」扩展并统一为 `Clothes.CategoryMain` 的 6 大类(上装/下装/连衣裙/外套/鞋/配饰),同步更新结构体注释、prompt 搭配规则与 JSON Schema 枚举,消除「鞋/鞋子」措辞不一致。 - **推荐结果校验增强**:校验大模型返回的 `clothes_id` 是否存在,并按实际衣物 `CategoryMain` 对齐 `type` 字段,同时对重复衣物去重。 - **运势映射收敛**:为 `FortuneItem` 增加到 `Horoscope` 模型的转换方法,将散落在调度器中的字段映射逻辑收拢到模型转换处。 - **公共结构整理**:将共享的 `chatResponse` 响应结构下沉到 `client.go`,并更新过时的包注释。 ## 视觉与交互 本次为纯逻辑层优化,不涉及界面或交互变化。 ## 技术栈 - 语言:Go(沿用现有项目技术栈) - 依赖:仅使用标准库(`encoding/json`、`strings`、`fmt` 等),不新增任何外部依赖 - 包结构:仅修改 `/root/zt-closet-backend/pkg/tokenhub/` 下 4 个文件,`mysqlmodel` 仅作只读引用 ## 实现方法 ### 总体策略 以 `mysqlmodel` 的字段定义为单一事实来源,消除 tokenhub 包中的硬编码字段列表与品类枚举漂移:衣物信息统一通过「字段名标注 + 全量字段」输出,品类统一通过包级常量切片管理,运势字段映射统一通过模型转换方法收敛。 ### 关键决策 1. **品类枚举集中管理**:新增包级常量 `outfitCategories`,作为 prompt 文案、JSON Schema `enum`、类型校验的唯一来源,避免多处字符串硬编码不一致。 2. **衣物摘要字段名标注**:`FormatClothesInfo` 改为 `- ID:1 | 大类:上装 | 小类:T恤 | ...` 格式,补全 `ColorSub/Thickness/SleeveType/ClothesType/NecklineType/Formality/Occasions/VisualImpact/Name` 等字段;继续使用 `strings.Builder` 拼接以保证性能。 3. **推荐结果以 model 为准做纠偏**:`ValidateClothesIDs` 先按 `clothes_id` 是否在衣橱过滤,再将保留项的 `Type` 规范化为衣橱中该衣物实际的 `CategoryMain`(比简单丢弃更鲁棒),最后按 `clothes_id` 去重;`GetClothesIDs` 同步去重。均使用 `map` 保证 O(n) 复杂度。 4. **运势映射下沉到模型转换方法**:为 `FortuneItem` 增加 `ToHoroscope(statDate int64) *mysqlmodel.Horoscope`,`scheduler.go` 中的逐字段构造改为调用该方法,职责更清晰。 5. **保持导出 API 兼容**:`GenerateDailyFortunes`、`GenerateOutfitRecommendation`、`FormatClothesInfo` 的函数签名与返回类型不变,仅改内部实现,避免影响未来接入方。 ### 性能与可靠性 - 所有列表处理均为单次遍历,`map` 去重 O(n),无额外性能负担。 - 不引入网络调用、不改变模型加载/调用流程,对启动与运行期无副作用。 - 新增的 `ToHoroscope` 与 `outfitCategories` 均无并发写入,可安全复用。 ## 目录结构 仅改动 `pkg/tokenhub/` 下 4 个文件: ``` pkg/tokenhub/ ├── client.go # [MODIFY] 更新 package 注释(补充穿搭推荐);新增 chatResponse 通用响应结构 ├── fortune.go # [MODIFY] 移除 chatResponse;FortuneItem 新增 ToHoroscope 方法;统一「混元→Tokenhub」措辞 ├── outfit_recommend.go # [MODIFY] 新增 outfitCategories 常量;重写 FormatClothesInfo;更新 prompt/schema/Type 注释为 6 大类;增强 ValidateClothesIDs 与 GetClothesIDs └── scheduler.go # [MODIFY] runFortuneGeneration 改用 FortuneItem.ToHoroscope 构造 Horoscope ``` ## 关键代码结构 ``` // outfitCategories 穿搭推荐支持的衣物大类,与 mysqlmodel.Clothes.CategoryMain 取值对齐。 var outfitCategories = []string{"上装", "下装", "连衣裙", "外套", "鞋", "配饰"} // ToHoroscope 将 LLM 返回的运势项转换为 Horoscope 模型。 func (f FortuneItem) ToHoroscope(statDate int64) *mysqlmodel.Horoscope ```