Skip to content

Commit bc4d68d

Browse files
thewindwillstopfreshspflin040204
authored
feat(spx-backend):add image filter (#2276)
* fix(spx-backend): optimize image recommendation algorithm and reduce search threshold * perf(spx-backend): optimize image recommendation sorting and remove redundant database validation * remove reduntant log * assComplete * refactor(spx-backend):move systemprompt to package * fix:fix no result when input english * fix:remove underline between prompt * fix:edit ai prompt * fix: optimize structure * feat(spx-backend):add image filter * docs:complete doc * complete sql file * fix:fix queryid not consistent * refactor:optimize search * update some threshold --------- Co-authored-by: spf <[email protected]> Co-authored-by: lin040204 <[email protected]> Co-authored-by: Pengfei Shen <[email protected]>
1 parent 9f6b758 commit bc4d68d

18 files changed

+1838
-93
lines changed

spx-backend/.env.dev

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,18 @@ RECRAFT_TIMEOUT=
7373
RECRAFT_MAX_RETRIES=
7474
RECRAFT_API_KEY=
7575

76+
# Image Recommendation Filtering
77+
# Enable/disable the image filtering feature
78+
IMAGE_FILTER_ENABLED=true
79+
# Default filter window in days (how far back to check for duplicates)
80+
IMAGE_FILTER_DEFAULT_WINDOW_DAYS=30
81+
# Maximum filter ratio (0-1, triggers degradation when exceeded)
82+
IMAGE_FILTER_DEFAULT_MAX_RATIO=0.8
83+
# Search expansion ratio (multiply search results before filtering)
84+
IMAGE_FILTER_SEARCH_EXPANSION_RATIO=2.0
85+
# Enable degradation strategies when filtering is too aggressive
86+
IMAGE_FILTER_ENABLE_DEGRADATION=true
87+
# Enable metrics collection for monitoring filtering performance
88+
IMAGE_FILTER_ENABLE_METRICS=true
89+
7690

spx-backend/cmd/spx-backend/post_images_instant_recommend.yap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
)
99

1010
ctx := &Context
11+
if _, ok := ensureAuthenticatedUser(ctx); !ok {
12+
return
13+
}
1114

1215
params := &controller.InstantRecommendParams{}
1316
if !parseJSON(ctx, params) {

spx-backend/cmd/spx-backend/post_images_recommend.yap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
)
99

1010
ctx := &Context
11+
if _, ok := ensureAuthenticatedUser(ctx); !ok {
12+
return
13+
}
1114

1215

1316
params := &controller.ImageRecommendParams{}

spx-backend/cmd/spx-backend/xgo_autogen.go

Lines changed: 39 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# 图片推荐过滤功能设计文档
2+
3+
## 1. 概述
4+
5+
### 1.1 背景
6+
当前图片推荐系统会从图库搜索和AI生成两个渠道获取图片,但缺乏过滤机制,导致用户可能重复看到相同的推荐图片,影响用户体验。
7+
8+
### 1.2 目标
9+
- 为每个用户维护已推荐图片的历史记录
10+
- 在后续推荐中过滤掉已推荐过的图片
11+
- 解决过度过滤导致无图可推的问题
12+
- 保持推荐系统的性能和用户体验
13+
14+
### 1.3 适用范围
15+
- 图片推荐接口 (`/api/images/recommend`)
16+
17+
## 2. 当前系统分析
18+
19+
### 2.1 现有架构
20+
```
21+
用户请求 → 双路径搜索 → 结果合并 → AI生成补充 → 返回推荐结果
22+
↳ 语义搜索 ↳ 去重排序 ↳ SVG生成 ↳ 缓存queryID
23+
↳ 主题搜索
24+
```
25+
26+
### 2.2 现有数据流
27+
1. **推荐流程**
28+
- 生成queryID追踪推荐
29+
- 使用Redis缓存推荐结果(24小时TTL)
30+
- 双路径搜索:语义搜索(70%) + 主题搜索(30%)
31+
- AI生成补充不足的图片
32+
33+
2. **反馈流程**
34+
- 通过queryID验证用户选择
35+
- 防重复提交机制
36+
- 调用算法服务反馈接口
37+
38+
### 2.3 存在问题
39+
- ✅ 重复推荐相同图片 **(已解决)**
40+
41+
## 3. 解决方案
42+
43+
### 3.1 系统架构
44+
45+
```mermaid
46+
graph TD
47+
A[用户请求] --> B[检查用户认证]
48+
B --> C[获取用户过滤配置]
49+
C --> D[扩大搜索量2倍]
50+
D --> E[执行双路径搜索]
51+
E --> F[应用历史过滤]
52+
F --> G{过滤率检查}
53+
G -->|<80%| H[AI生成补充]
54+
G -->|>80%| I[应用降级策略]
55+
I --> J[时间窗口缩减]
56+
J --> K{结果充足?}
57+
K -->|是| H
58+
K -->|否| L[相似度阈值混合]
59+
L --> H
60+
H --> M[异步记录历史]
61+
M --> N[返回结果]
62+
63+
O[用户反馈] --> P[验证选择]
64+
P --> Q[调用算法服务]
65+
Q --> R[异步标记选择]
66+
```
67+
68+
### 3.2 数据库设计
69+
70+
71+
#### 3.2.2 用户过滤配置表
72+
```sql
73+
CREATE TABLE `user_image_filter_config` (
74+
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
75+
`user_id` bigint NOT NULL COMMENT '用户ID',
76+
`filter_window_days` int DEFAULT 30 COMMENT '过滤窗口期(天)',
77+
`max_filter_ratio` decimal(3,2) DEFAULT 0.80 COMMENT '最大过滤比例(0-1)',
78+
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
79+
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
80+
PRIMARY KEY (`id`),
81+
UNIQUE KEY `uk_user_id` (`user_id`)
82+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户图片过滤配置表';
83+
```
84+
85+
#### 3.2.3 过滤性能指标表
86+
```sql
87+
CREATE TABLE `image_filter_metrics` (
88+
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
89+
`user_id` bigint NOT NULL COMMENT '用户ID',
90+
`query_id` varchar(36) NOT NULL COMMENT '查询ID',
91+
`total_candidates` int NOT NULL COMMENT '总候选数量',
92+
`filtered_count` int NOT NULL COMMENT '过滤数量',
93+
`filter_ratio` decimal(5,3) COMMENT '过滤比例',
94+
`degradation_level` int DEFAULT 0 COMMENT '降级等级',
95+
`degradation_strategy` varchar(100) COMMENT '降级策略',
96+
`final_result_count` int NOT NULL COMMENT '最终结果数量',
97+
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
98+
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
99+
`deleted_at` timestamp NULL,
100+
PRIMARY KEY (`id`),
101+
KEY `idx_user_id` (`user_id`),
102+
KEY `idx_query_id` (`query_id`)
103+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='图片过滤指标表';
104+
```
105+
106+
### 3.3 实现流程
107+
108+
#### 3.3.1 推荐流程
109+
1. 检查用户认证状态
110+
2. 获取用户过滤配置(如无则创建默认配置)
111+
3. 扩大搜索量(默认2倍)补偿过滤损失
112+
4. 执行图片搜索(语义搜索 + 主题搜索)
113+
5. 应用过滤逻辑,排除历史推荐图片
114+
6. 检测过滤饱和度,必要时触发降级策略
115+
7. AI生成补充不足的图片
116+
8. 异步记录推荐历史和性能指标
117+
9. 返回推荐结果
118+
119+
#### 3.3.2 反馈流程
120+
1. 验证queryID和选择的图片ID
121+
2. 调用算法服务反馈接口
122+
3. 异步标记用户选择的图片
123+
124+
### 3.4 降级策略
125+
126+
当过滤率过高时(默认>80%,后续根据情况改),按优先级依次尝试:
127+
128+
#### ✅ 已实现策略
129+
1. **时间窗口缩减**:30天→15天→7天→3天→1天
130+
- 逐步缩小过滤窗口期,增加可推荐图片池
131+
2. **相似度阈值混合**:保留相似度>0.7的高质量图片
132+
- 从被过滤图片中挑选高相似度内容混入结果
133+
134+
### 3.5 性能优化
135+
136+
#### ✅ 已实现优化
137+
- **异步处理**:推荐历史记录和指标数据异步写入
138+
- **搜索扩展**:预先请求2倍搜索结果补偿过滤损失
139+
- **数据库索引**:用户ID + 图片ID复合索引,查询ID索引
140+
- **配置缓存**:服务启动时加载配置,减少数据库查询
141+
- **无数据库模式**:支持无数据库环境,自动降级到默认配置
142+
143+
### 4.2 用户个性化配置
144+
- 用户可通过数据库表 `user_image_filter_config` 自定义过滤参数
145+
- 支持个性化窗口期和过滤比例设置
146+
- 新用户自动创建默认配置

spx-backend/internal/config/config.go

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import (
66

77
// Config holds all configuration for the application.
88
type Config struct {
9-
Server ServerConfig
10-
Database DatabaseConfig
11-
Redis RedisConfig
12-
Kodo KodoConfig
13-
Casdoor CasdoorConfig
14-
OpenAI OpenAIConfig
15-
AIGC AIGCConfig
16-
Algorithm AlgorithmConfig
17-
Providers ProvidersConfig
9+
Server ServerConfig
10+
Database DatabaseConfig
11+
Redis RedisConfig
12+
Kodo KodoConfig
13+
Casdoor CasdoorConfig
14+
OpenAI OpenAIConfig
15+
AIGC AIGCConfig
16+
Algorithm AlgorithmConfig
17+
Providers ProvidersConfig
18+
ImageFilter ImageFilterConfig
1819
}
1920

2021
// ServerConfig holds server configuration.
@@ -202,6 +203,51 @@ type RecraftEndpoints struct {
202203

203204

204205

206+
// ImageFilterConfig holds image recommendation filtering configuration.
207+
type ImageFilterConfig struct {
208+
// Enabled controls whether image filtering is enabled globally
209+
Enabled bool `default:"true"`
210+
211+
// DefaultWindowDays is the default filter window in days
212+
DefaultWindowDays int `default:"30"`
213+
214+
// DefaultMaxFilterRatio is the default maximum filter ratio (0-1)
215+
DefaultMaxFilterRatio float64 `default:"0.8"`
216+
217+
// SearchExpansionRatio controls how much to expand search results before filtering
218+
SearchExpansionRatio float64 `default:"2.0"`
219+
220+
// EnableDegradation controls whether degradation strategies are enabled
221+
EnableDegradation bool `default:"true"`
222+
223+
// EnableMetrics controls whether to store filtering metrics
224+
EnableMetrics bool `default:"true"`
225+
}
226+
227+
// GetDefaultWindowDays returns the default window days, with fallback.
228+
func (c *ImageFilterConfig) GetDefaultWindowDays() int {
229+
if c.DefaultWindowDays > 0 {
230+
return c.DefaultWindowDays
231+
}
232+
return 30
233+
}
234+
235+
// GetDefaultMaxFilterRatio returns the default max filter ratio, with fallback.
236+
func (c *ImageFilterConfig) GetDefaultMaxFilterRatio() float64 {
237+
if c.DefaultMaxFilterRatio > 0 && c.DefaultMaxFilterRatio <= 1 {
238+
return c.DefaultMaxFilterRatio
239+
}
240+
return 0.8
241+
}
242+
243+
// GetSearchExpansionRatio returns the search expansion ratio, with fallback.
244+
func (c *ImageFilterConfig) GetSearchExpansionRatio() float64 {
245+
if c.SearchExpansionRatio > 1 {
246+
return c.SearchExpansionRatio
247+
}
248+
return 2.0
249+
}
250+
205251
// IsProviderEnabled checks if a provider is enabled.
206252
func (c *Config) IsProviderEnabled(provider string) bool {
207253
switch provider {

spx-backend/internal/config/loader.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ func Load(logger *log.Logger) (*Config, error) {
9292
},
9393
},
9494
},
95+
96+
ImageFilter: ImageFilterConfig{
97+
Enabled: getEnvAsBool("IMAGE_FILTER_ENABLED", true),
98+
DefaultWindowDays: getEnvAsInt("IMAGE_FILTER_DEFAULT_WINDOW_DAYS", 30),
99+
DefaultMaxFilterRatio: getEnvAsFloat("IMAGE_FILTER_DEFAULT_MAX_RATIO", 0.8),
100+
SearchExpansionRatio: getEnvAsFloat("IMAGE_FILTER_SEARCH_EXPANSION_RATIO", 2.0),
101+
EnableDegradation: getEnvAsBool("IMAGE_FILTER_ENABLE_DEGRADATION", true),
102+
EnableMetrics: getEnvAsBool("IMAGE_FILTER_ENABLE_METRICS", true),
103+
},
95104
}
96105
return config, nil
97106
}

0 commit comments

Comments
 (0)