From 878468cd6df69a7699be97ec6392fc224aacfe4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Fri, 31 Jul 2026 17:08:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=9F=E6=88=90=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=BA=E6=99=AF=EF=BC=88occasion=EF=BC=8C?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=80=9A=E5=8B=A4=EF=BC=8C=E8=AF=84=E5=88=86?= =?UTF-8?q?/LLM=20=E4=BE=9D=E6=8D=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/dto/outfit_generation_task_dto.go | 1 + .../service/outfit_generation_task_service.go | 13 ++++-- .../outfit_generation_task_service_test.go | 40 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 styleagent/service/outfit_generation_task_service_test.go diff --git a/styleagent/model/dto/outfit_generation_task_dto.go b/styleagent/model/dto/outfit_generation_task_dto.go index 86445c5..fb38f46 100644 --- a/styleagent/model/dto/outfit_generation_task_dto.go +++ b/styleagent/model/dto/outfit_generation_task_dto.go @@ -9,6 +9,7 @@ type OutfitGenerateReq struct { StartDate string `v:"required|date" json:"start_date"` EndDate string `v:"required|date" json:"end_date"` Location string `v:"required" json:"location"` + Occasion string `v:"in:通勤,约会,聚会,运动" json:"occasion"` } type OutfitGenerateRes struct { diff --git a/styleagent/service/outfit_generation_task_service.go b/styleagent/service/outfit_generation_task_service.go index 970dc08..18cd092 100644 --- a/styleagent/service/outfit_generation_task_service.go +++ b/styleagent/service/outfit_generation_task_service.go @@ -41,10 +41,18 @@ func (s *outfitService) Generate(ctx context.Context, userId int64, req *dto.Out return 0, err } // 异步执行:传入独立 ctx(请求结束不中断任务) - go runGenerateTask(gctx.New(), taskId, userId) + go runGenerateTask(gctx.New(), taskId, userId, normalizeOccasion(req.Occasion)) return taskId, nil } +// normalizeOccasion 空场景默认通勤(评分引擎按 通勤/约会/聚会/运动 匹配) +func normalizeOccasion(o string) string { + if o == "" { + return "通勤" + } + return o +} + // StartWorker 服务启动时恢复未完成任务(标记失败,避免重启后重复消耗 LLM 费用) func (s *outfitService) StartWorker(ctx context.Context) { tasks, err := dao.OutfitGenTask.ListUnfinished(ctx) @@ -59,7 +67,7 @@ func (s *outfitService) StartWorker(ctx context.Context) { } // runGenerateTask 任务核心流程:planning → scoring → done/failed -func runGenerateTask(ctx context.Context, taskId, userId int64) { +func runGenerateTask(ctx context.Context, taskId, userId int64, occasion string) { setTask := func(status, msg string) { _ = dao.OutfitGenTask.UpdateStatus(ctx, taskId, status, msg) } @@ -109,7 +117,6 @@ func runGenerateTask(ctx context.Context, taskId, userId int64) { // 4. LLM 规划(1 次调用) hairstyles := hairstyleListText(ctx) bodyDesc := bodyDescText(ctx, userId) - occasion := "通勤" candidates := make([]agent.CandidateData, 0, len(sets)*3) for si, set := range sets { for _, it := range set.Items { diff --git a/styleagent/service/outfit_generation_task_service_test.go b/styleagent/service/outfit_generation_task_service_test.go new file mode 100644 index 0000000..6acf085 --- /dev/null +++ b/styleagent/service/outfit_generation_task_service_test.go @@ -0,0 +1,40 @@ +package service + +import ( + "context" + "testing" + + "github.com/gogf/gf/v2/frame/g" + + _ "github.com/gogf/gf/contrib/drivers/sqlite/v2" + "slogan-agent/styleagent/model/dto" +) + +func TestGenerateReqOccasionValidation(t *testing.T) { + valid := []string{"", "通勤", "约会", "聚会", "运动"} + for _, v := range valid { + req := &dto.OutfitGenerateReq{ + StartDate: "2026-08-01", EndDate: "2026-08-02", + Location: "上海", Occasion: v, + } + if err := g.Validator().Data(req).Run(context.Background()); err != nil { + t.Fatalf("occasion %q 应通过校验: %v", v, err) + } + } + req := &dto.OutfitGenerateReq{ + StartDate: "2026-08-01", EndDate: "2026-08-02", + Location: "上海", Occasion: "随便", + } + if err := g.Validator().Data(req).Run(context.Background()); err == nil { + t.Fatal("非法 occasion 应被拒绝") + } +} + +func TestNormalizeOccasion(t *testing.T) { + if got := normalizeOccasion(""); got != "通勤" { + t.Fatalf("空场景应默认通勤, got %q", got) + } + if got := normalizeOccasion("约会"); got != "约会" { + t.Fatalf("非空场景应原样返回, got %q", got) + } +}