130 lines
3.7 KiB
Go
130 lines
3.7 KiB
Go
package services
|
||
|
||
import (
|
||
"ai_scheduler/internal/config"
|
||
errorcode "ai_scheduler/internal/data/error"
|
||
"ai_scheduler/internal/pkg/util"
|
||
"ai_scheduler/internal/pkg/utils_ollama"
|
||
"context"
|
||
"fmt"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/gofiber/fiber/v2"
|
||
"github.com/ollama/ollama/api"
|
||
)
|
||
|
||
// CapabilityService 统一回调入口
|
||
type CapabilityService struct {
|
||
cfg *config.Config
|
||
}
|
||
|
||
func NewCapabilityService(cfg *config.Config) *CapabilityService {
|
||
return &CapabilityService{
|
||
cfg: cfg,
|
||
}
|
||
}
|
||
|
||
// 产品数据提取入参
|
||
type ProductIngestReq struct {
|
||
Url string `json:"url"` // 商品详情页URL
|
||
Title string `json:"title"` // 商品标题
|
||
Text string `json:"text"` // 商品描述
|
||
Images []string `json:"images"` // 商品图片URL列表
|
||
Timestamp int64 `json:"timestamp"` // 商品发布时间戳
|
||
}
|
||
|
||
const (
|
||
// 货易通商品属性模板-中文
|
||
HYTProductPropertyTemplateZH = `{
|
||
"条码": "string", // 商品编号
|
||
"分类名称": "string", // 商品分类
|
||
"货品名称": "string", // 商品名称
|
||
"货品编号": "string", // 商品编号
|
||
"商品货号": "string", // 商品编号
|
||
"品牌": "string", // 商品品牌
|
||
"单位": "string", // 商品单位,若无则使用'个'
|
||
"规格参数": "string", // 商品规格参数
|
||
"货品说明": "string", // 商品说明
|
||
"保质期": "string", // 商品保质期
|
||
"保质期单位": "string", // 商品保质期单位
|
||
"链接": "string", //
|
||
"货品图片": ["string"], // 商品多图,取1-2个即可
|
||
"电商销售价格": "decimal(10,2)", // 商品电商销售价格
|
||
"销售价": "decimal(10,2)", // 商品销售价格
|
||
"供应商报价": "decimal(10,2)", // 商品供应商报价
|
||
"税率": "number%", // 商品税率 x%
|
||
"默认供应商": "", // 空即可
|
||
"默认存放仓库": "", // 空即可
|
||
"备注": "", // 备注
|
||
"长": "string", // 商品长度,decimal(10,2)+单位
|
||
"宽": "string", // 商品宽度,decimal(10,2)+单位
|
||
"高": "string", // 商品高度,decimal(10,2)+单位
|
||
"重量": "string", // 商品重量(kg)
|
||
"SPU名称": "string", // 商品SPU名称
|
||
"SPU编码": "string" // 编码串,jd_{timestamp}_rand(1000-999)
|
||
}`
|
||
|
||
SystemPrompt = `你是一个专业的商品属性提取助手,你的任务是根据用户输入提取商品的属性信息。
|
||
目标属性模板:%s。
|
||
最终输出格式为纯JSON字符串,键值对对应目标属性和提取到的属性值。
|
||
最终输出不要携带markdown标识,不要携带回车换行`
|
||
)
|
||
|
||
// ProductIngest 产品数据提取
|
||
func (s *CapabilityService) ProductIngest(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 != "A7f9KQ3mP2X8LZC4R5e" {
|
||
// return errorcode.KeyErr()
|
||
}
|
||
|
||
// 解析请求参数
|
||
req := ProductIngestReq{}
|
||
if err := c.BodyParser(&req); err != nil {
|
||
return errorcode.ParamErr("invalid request body: %v", err)
|
||
}
|
||
|
||
// 必要参数校验
|
||
if req.Text == "" {
|
||
return errorcode.ParamErr("missing required fields")
|
||
}
|
||
|
||
// 模型调用
|
||
client, cleanup, err := utils_ollama.NewClient(s.cfg)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer cleanup()
|
||
|
||
res, err := client.Chat(context.Background(), []api.Message{
|
||
{
|
||
Role: "system",
|
||
Content: fmt.Sprintf(SystemPrompt, HYTProductPropertyTemplateZH),
|
||
},
|
||
{
|
||
Role: "user",
|
||
Content: req.Text,
|
||
},
|
||
{
|
||
Role: "user",
|
||
Content: "商品图片URL列表:" + strings.Join(req.Images, ","),
|
||
},
|
||
})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 解析模型输出
|
||
c.JSON(res.Message.Content)
|
||
|
||
return nil
|
||
}
|