From e981115cc13555a61058660ab43fb4cc11edd7f9 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Mon, 2 Mar 2026 17:30:49 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=AD=96=E7=95=A5=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=9C=B0=E5=9D=80=E6=8F=90=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/provider_set.go | 2 + internal/biz/support/address_ingest_hyt.go | 81 ++++++++++++++++ .../biz/support/address_ingest_interface.go | 22 +++++ internal/server/router/router.go | 2 +- internal/services/support.go | 97 +++++-------------- 5 files changed, 131 insertions(+), 73 deletions(-) create mode 100644 internal/biz/support/address_ingest_hyt.go create mode 100644 internal/biz/support/address_ingest_interface.go diff --git a/internal/biz/provider_set.go b/internal/biz/provider_set.go index 2054c54..d075605 100644 --- a/internal/biz/provider_set.go +++ b/internal/biz/provider_set.go @@ -3,6 +3,7 @@ package biz import ( "ai_scheduler/internal/biz/do" "ai_scheduler/internal/biz/llm_service" + "ai_scheduler/internal/biz/support" "github.com/google/wire" ) @@ -22,4 +23,5 @@ var ProviderSetBiz = wire.NewSet( NewQywxAppBiz, NewGroupConfigBiz, do.NewMacro, + support.NewHytAddressIngester, ) diff --git a/internal/biz/support/address_ingest_hyt.go b/internal/biz/support/address_ingest_hyt.go new file mode 100644 index 0000000..61281c5 --- /dev/null +++ b/internal/biz/support/address_ingest_hyt.go @@ -0,0 +1,81 @@ +package support + +import ( + "ai_scheduler/internal/config" + "ai_scheduler/internal/data/constants" + errorcode "ai_scheduler/internal/data/error" + "ai_scheduler/internal/pkg/util" + "ai_scheduler/internal/pkg/utils_vllm" + "context" + "encoding/json" + "strings" + "time" + + "github.com/cloudwego/eino/schema" + "github.com/gofiber/fiber/v2" +) + +// HytAddressIngester 货易通地址提取实现 +type HytAddressIngester struct { + cfg *config.Config +} + +func NewHytAddressIngester(cfg *config.Config) *HytAddressIngester { + return &HytAddressIngester{cfg: cfg} +} + +// Auth 鉴权逻辑 +func (s *HytAddressIngester) Auth(c *fiber.Ctx) error { + // 读取头 + token := strings.TrimSpace(c.Get("X-Source-Key")) + ts := strings.TrimSpace(c.Get("X-Timestamp")) + + // 时间窗口校验 + if ts != "" && !util.IsInTimeWindow(ts, 5*time.Minute) { + return errorcode.AuthNotFound + } + // token校验 + if token == "" || token != constants.TokenAddressIngestHyt { + return errorcode.KeyNotFound + } + return nil +} + +// Ingest 执行提取逻辑 +func (s *HytAddressIngester) Ingest(ctx context.Context, text string) (*AddressIngestResp, error) { + // 模型调用 + client, cleanup, err := utils_vllm.NewClient(s.cfg) + if err != nil { + return nil, err + } + defer cleanup() + + res, err := client.Chat(ctx, []*schema.Message{ + { + Role: "system", + Content: constants.SystemPromptAddressIngestHyt, + }, + { + Role: "user", + Content: text, + }, + }) + if err != nil { + return nil, err + } + + // 解析模型返回结果 + var addr AddressIngestResp + // 尝试直接解析 + if err := json.Unmarshal([]byte(res.Content), &addr); err != nil { + // 修复json字符串 + repairedContent, err := util.JSONRepair(res.Content) + if err != nil { + return nil, errorcode.ParamErrf("invalid response body: %v", err) + } + if err := json.Unmarshal([]byte(repairedContent), &addr); err != nil { + return nil, errorcode.ParamErrf("invalid response body: %v", err) + } + } + return &addr, nil +} diff --git a/internal/biz/support/address_ingest_interface.go b/internal/biz/support/address_ingest_interface.go new file mode 100644 index 0000000..eaf1e70 --- /dev/null +++ b/internal/biz/support/address_ingest_interface.go @@ -0,0 +1,22 @@ +package support + +import ( + "context" + + "github.com/gofiber/fiber/v2" +) + +// AddressIngestResp 通用地址提取响应 +type AddressIngestResp struct { + Recipient string `json:"recipient"` // 收货人 + Phone string `json:"phone"` // 联系电话 + Address string `json:"address"` // 收货地址 +} + +// AddressIngester 地址提取接口 +type AddressIngester interface { + // Auth 鉴权逻辑 + Auth(c *fiber.Ctx) error + // Ingest 执行提取逻辑 + Ingest(ctx context.Context, text string) (*AddressIngestResp, error) +} diff --git a/internal/server/router/router.go b/internal/server/router/router.go index da763fe..a088f4a 100644 --- a/internal/server/router/router.go +++ b/internal/server/router/router.go @@ -100,7 +100,7 @@ func SetupRoutes(app *fiber.App, ChatService *services.ChatService, sessionServi r.Post("/capability/product/ingest/:thread_id/confirm", capabilityService.ProductIngestConfirm) // 商品数据提取确认 // 外部系统支持 - r.Post("/support/address/ingest/hyt", supportService.AddressIngestHyt) // 货易通收获地址提取 + r.Post("/support/address/ingest/:platform", supportService.AddressIngest) // 通用收获地址提取 } func routerSocket(app *fiber.App, chatService *services.ChatService) { diff --git a/internal/services/support.go b/internal/services/support.go index ac34626..f0a2196 100644 --- a/internal/services/support.go +++ b/internal/services/support.go @@ -1,50 +1,48 @@ package services import ( + "ai_scheduler/internal/biz/support" "ai_scheduler/internal/config" - "ai_scheduler/internal/data/constants" errorcode "ai_scheduler/internal/data/error" - "ai_scheduler/internal/pkg/util" - "ai_scheduler/internal/pkg/utils_vllm" - "context" - "encoding/json" - "strings" - "time" - "github.com/cloudwego/eino/schema" "github.com/gofiber/fiber/v2" ) type SupportService struct { - cfg *config.Config + cfg *config.Config + addressIngester map[string]support.AddressIngester + addressIngestHyt *support.HytAddressIngester } -func NewSupportService(cfg *config.Config) *SupportService { - return &SupportService{ +func NewSupportService(cfg *config.Config, addressIngestHyt *support.HytAddressIngester) *SupportService { + s := &SupportService{ cfg: cfg, + addressIngester: map[string]support.AddressIngester{ + "hyt": addressIngestHyt, + }, } + return s } -type AddressIngestHytReq struct { +type AddressIngestReq struct { Text string `json:"text"` // 待提取文本 } -type AddressIngestHytResp struct { - Recipient string `json:"recipient"` // 收货人 - Phone string `json:"phone"` // 联系电话 - Address string `json:"address"` // 收货地址 -} +// AddressIngest 收获地址提取 +func (s *SupportService) AddressIngest(c *fiber.Ctx) error { + platform := c.Params("platform") + ingester, ok := s.addressIngester[platform] + if !ok { + return errorcode.ParamErrf("unsupported platform: %s", platform) + } -// AddressIngestHyt 货易通收获地址提取 -func (s *SupportService) AddressIngestHyt(c *fiber.Ctx) error { - ctx := context.Background() - - // 请求头校验 - if err := s.checkRequestHeader(c); err != nil { + // 鉴权 + if err := ingester.Auth(c); err != nil { return err } + // 解析请求参数 body - req := AddressIngestHytReq{} + req := AddressIngestReq{} if err := c.BodyParser(&req); err != nil { return errorcode.ParamErrf("invalid request body: %v", err) } @@ -53,56 +51,11 @@ func (s *SupportService) AddressIngestHyt(c *fiber.Ctx) error { return errorcode.ParamErrf("missing required fields") } - // 模型调用 - client, cleanup, err := utils_vllm.NewClient(s.cfg) - if err != nil { - return err - } - defer cleanup() - res, err := client.Chat(ctx, []*schema.Message{ - { - Role: "system", - Content: constants.SystemPromptAddressIngestHyt, - }, - { - Role: "user", - Content: req.Text, - }, - }) + // 执行提取 + res, err := ingester.Ingest(c.Context(), req.Text) if err != nil { return err } - // 解析模型返回结果 - var addr AddressIngestHytResp - if err := json.Unmarshal([]byte(res.Content), &addr); err != nil { - // 修复json字符串 - res.Content, err = util.JSONRepair(res.Content) - if err != nil { - return errorcode.ParamErrf("invalid response body: %v", err) - } - if err := json.Unmarshal([]byte(res.Content), &addr); err != nil { - return errorcode.ParamErrf("invalid response body: %v", err) - } - } - - return c.JSON(addr) -} - -// checkRequestHeader 校验请求头 -func (s *SupportService) checkRequestHeader(c *fiber.Ctx) error { - // 读取头 - token := strings.TrimSpace(c.Get("X-Source-Key")) - ts := strings.TrimSpace(c.Get("X-Timestamp")) - - // 时间窗口校验 - if ts != "" && !util.IsInTimeWindow(ts, 5*time.Minute) { - return errorcode.AuthNotFound - } - // token校验 - if token == "" || token != constants.TokenAddressIngestHyt { - return errorcode.KeyNotFound - } - - return nil + return c.JSON(res) }