update
This commit is contained in:
@ -28,6 +28,8 @@ type Config struct {
|
||||
Ingest IngestConfig `yaml:"ingest"`
|
||||
// S4 缤纷云对象存储配置(S3 兼容,爬虫入库图片上传目标)。
|
||||
S4 S4Config `yaml:"s4"`
|
||||
// Vision 视觉服务(FashionSigLIP)配置,用于「疑似同款」提示。
|
||||
Vision VisionConfig `yaml:"vision"`
|
||||
|
||||
// loadedFrom 记录实际生效的配置文件绝对路径,仅用于启动日志。
|
||||
// 小写不导出,yml 无法覆盖它。
|
||||
@ -154,6 +156,36 @@ type S4Config struct {
|
||||
StyleThumb string `yaml:"style_thumb"`
|
||||
}
|
||||
|
||||
// VisionConfig 视觉服务(FashionSigLIP)配置。
|
||||
//
|
||||
// 入库时把每张图编码成 768 维归一化向量写入 image_embeddings(HNSW 余弦索引),
|
||||
// 后台图集页据此提示「疑似同款」。服务不可用时自动降级为「不产出向量」,绝不阻断入库。
|
||||
//
|
||||
// 维度 768 为 M0 spike 实测值(模型 Marqo/marqo-fashionSigLIP 输出 768 维,非 512)。
|
||||
// 生产部署无 GPU,CPU 推理;本地开发可用项目 .venv(CUDA torch),两者算出的向量数值一致。
|
||||
type VisionConfig struct {
|
||||
// Enabled 总开关;关闭则完全跳过 embed 调用。env: VISION_ENABLED
|
||||
Enabled bool `yaml:"enabled"`
|
||||
// Endpoint 服务地址,仅监听内网。env: VISION_ENDPOINT
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
// TimeoutSeconds 单批 embed 超时(秒),默认 5。env: VISION_TIMEOUT
|
||||
TimeoutSeconds int `yaml:"timeout_seconds"`
|
||||
// Dim 向量维度,必须与模型一致;M0 实测为 768。env: VISION_DIM
|
||||
Dim int `yaml:"dim"`
|
||||
// SimilarThreshold 「疑似同款」余弦相似度阈值,由真实 runway 数据实测校准。
|
||||
// env: VISION_SIMILAR_THRESHOLD
|
||||
//
|
||||
// 默认 0.93。实测依据(已排除同图集,只比跨图集):
|
||||
// - 「不同图」的跨图集最佳相似度:min 0.676 / 中位 0.781 / 上限约 0.90
|
||||
// (同品牌各季同风格,语义相似度天然偏高)
|
||||
// - 「同一张照片」的跨图集重复:整齐落在 1.0000
|
||||
// 0.93 取在噪音上限与真重复之间的空隙里。参照:0.68 时实测 100% 的图都会挂提示
|
||||
// (纯噪音);而 0.85 已能滤掉绝大多数噪音。
|
||||
SimilarThreshold float64 `yaml:"similar_threshold"`
|
||||
// FailThreshold 连续失败多少次后熔断冷却(5 分钟)。env: VISION_FAIL_THRESHOLD
|
||||
FailThreshold int `yaml:"fail_threshold"`
|
||||
}
|
||||
|
||||
// ClientSignConfig 公开接口「前端 JS 签名」配置。
|
||||
//
|
||||
// 给 /runway-looks(列表)与 /brands 两个批量查询接口加一层请求签名校验,
|
||||
@ -230,8 +262,8 @@ func defaultConfig() *Config {
|
||||
Burst: 40,
|
||||
},
|
||||
Ingest: IngestConfig{
|
||||
Secret: "",
|
||||
TTLSeconds: 300,
|
||||
Secret: "",
|
||||
TTLSeconds: 300,
|
||||
DownloadProxy: "",
|
||||
},
|
||||
S4: S4Config{
|
||||
@ -378,6 +410,14 @@ func (c *Config) applyEnv() {
|
||||
envStrFirst(&c.S4.BaseURL, "S4_BASE_URL", "QINIU_BASE_URL")
|
||||
envStrFirst(&c.S4.StyleDisplay, "S4_STYLE_DISPLAY", "QINIU_STYLE_NORMAL")
|
||||
envStr("S4_STYLE_THUMB", &c.S4.StyleThumb)
|
||||
|
||||
// 视觉服务(FashionSigLIP):入库时产出「疑似同款」用的语义向量。
|
||||
envBool("VISION_ENABLED", &c.Vision.Enabled)
|
||||
envStr("VISION_ENDPOINT", &c.Vision.Endpoint)
|
||||
envInt("VISION_TIMEOUT", &c.Vision.TimeoutSeconds)
|
||||
envInt("VISION_DIM", &c.Vision.Dim)
|
||||
envFloat("VISION_SIMILAR_THRESHOLD", &c.Vision.SimilarThreshold)
|
||||
envInt("VISION_FAIL_THRESHOLD", &c.Vision.FailThreshold)
|
||||
}
|
||||
|
||||
// normalize 兜底与校验:修正非法值,避免运行期出现难以定位的问题。
|
||||
@ -432,6 +472,23 @@ func (c *Config) normalize() {
|
||||
if len(c.CORS.AllowOrigins) == 0 {
|
||||
c.CORS.AllowOrigins = []string{"*"}
|
||||
}
|
||||
// 视觉服务(FashionSigLIP)默认值:留空时兜底为本地服务与实测维度。
|
||||
if c.Vision.Endpoint == "" {
|
||||
c.Vision.Endpoint = "http://127.0.0.1:8900"
|
||||
}
|
||||
if c.Vision.TimeoutSeconds <= 0 {
|
||||
c.Vision.TimeoutSeconds = 5
|
||||
}
|
||||
if c.Vision.Dim <= 0 {
|
||||
c.Vision.Dim = 768
|
||||
}
|
||||
if c.Vision.FailThreshold <= 0 {
|
||||
c.Vision.FailThreshold = 3
|
||||
}
|
||||
if c.Vision.SimilarThreshold <= 0 {
|
||||
// 0.93 为实测校准值:跨图集「不同图」上限约 0.90,真重复落在 1.0000,取空隙中点。
|
||||
c.Vision.SimilarThreshold = 0.93
|
||||
}
|
||||
}
|
||||
|
||||
func envStr(key string, dst *string) {
|
||||
@ -473,3 +530,11 @@ func envBool(key string, dst *bool) {
|
||||
*dst = v == "1" || v == "true" || v == "yes"
|
||||
}
|
||||
}
|
||||
|
||||
func envFloat(key string, dst *float64) {
|
||||
if v := strings.TrimSpace(os.Getenv(key)); v != "" {
|
||||
if f, err := strconv.ParseFloat(v, 64); err == nil {
|
||||
*dst = f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user