Commit 1211812579e87ed6d9c44956c630b1b6fde127f9

Authored by tangwang
1 parent 5b61955e

offline tasks: mem optimize

Showing 45 changed files with 3338 additions and 4079 deletions   Show diff stats
offline_tasks/B2B_LOW_FREQUENCY_OPTIMIZATION.md deleted
@@ -1,223 +0,0 @@ @@ -1,223 +0,0 @@
1 -# B2B低频场景优化总结  
2 -  
3 -## 📋 优化背景  
4 -  
5 -B2B场景的特点:  
6 -- ✅ 用户行为频次**非常低**  
7 -- ✅ 行为间隔时间**可能很长**  
8 -- ✅ 历史行为**依然重要**,不应过度衰减  
9 -  
10 -## ✅ 已完成的优化  
11 -  
12 -### 1. **i2i_session_w2v.py** - Session分割策略优化  
13 -  
14 -#### 修改前(基于时间间隔)  
15 -```python  
16 -# 问题:B2B场景下,用户可能几个月才有一次行为  
17 -# 基于30分钟间隔分割session不合适  
18 -session_gap_minutes = 30  
19 -if (current_time - last_time).total_seconds() / 60 > session_gap_minutes:  
20 - # 新session  
21 -```  
22 -  
23 -#### 修改后(固定长度分块)  
24 -```python  
25 -# 参考: graphembedding/session_w2v/prepare_data.py  
26 -# 按固定长度分块,不考虑时间间隔  
27 -max_session_length = 50 # 最大会话长度  
28 -min_session_length = 2 # 最小会话长度  
29 -  
30 -# 按用户行为序列分块  
31 -user_sessions = [  
32 - item_sequence[i:i + max_session_length]  
33 - for i in range(0, len(item_sequence), max_session_length)  
34 -]  
35 -```  
36 -  
37 -**优势:**  
38 -- 不依赖时间间隔,适合低频场景  
39 -- 逻辑简化,性能更好  
40 -- 保留用户行为的顺序信息  
41 -  
42 -**新增参数:**  
43 -```bash  
44 ---max_session_length 50 # 最大会话长度  
45 ---min_session_length 2 # 最小会话长度(过滤太短的序列)  
46 -```  
47 -  
48 ----  
49 -  
50 -### 2. **i2i_swing.py** - 关闭时间衰减  
51 -  
52 -#### 修改前  
53 -```python  
54 ---time_decay # 默认True,开启时间衰减  
55 -# 30天前权重: 0.95  
56 -# 60天前权重: 0.90  
57 -# 180天前权重: 0.74 (衰减过快)  
58 -```  
59 -  
60 -#### 修改后  
61 -```python  
62 ---time_decay # 默认False,关闭时间衰减  
63 -# 所有历史行为权重相同,更适合低频场景  
64 -```  
65 -  
66 -**原因:**  
67 -在B2B低频场景下,6个月前的行为可能依然很有价值,不应该被大幅衰减。  
68 -  
69 ----  
70 -  
71 -### 3. **interest_aggregation.py** - 关闭时间衰减  
72 -  
73 -#### 修改内容  
74 -```python  
75 -# 热门商品索引 - 关闭时间衰减  
76 -list_type_indices['hot'] = aggregate_by_dimensions(  
77 - df_hot, behavior_weights, time_decay=False # 改为False  
78 -)  
79 -  
80 -# 加购商品索引 - 关闭时间衰减  
81 -list_type_indices['cart'] = aggregate_by_dimensions(  
82 - df_cart, behavior_weights, time_decay=False # 改为False  
83 -)  
84 -  
85 -# 全局索引 - 关闭时间衰减  
86 -global_aggregations = aggregate_by_dimensions(  
87 - df, behavior_weights, time_decay=False # 改为False  
88 -)  
89 -  
90 -# 新品索引 - 本来就不用时间衰减(保持不变)  
91 -list_type_indices['new'] = aggregate_by_dimensions(  
92 - df_new, behavior_weights, time_decay=False  
93 -)  
94 -```  
95 -  
96 ----  
97 -  
98 -## 🚀 使用方法  
99 -  
100 -### Session W2V(已自动优化)  
101 -```bash  
102 -# 使用新的固定长度分块策略  
103 -python3 scripts/i2i_session_w2v.py \  
104 - --lookback_days 365 \  
105 - --max_session_length 50 \  
106 - --min_session_length 2 \  
107 - --top_n 50 \  
108 - --debug  
109 -```  
110 -  
111 -### Swing算法(默认已关闭时间衰减)  
112 -```bash  
113 -# 默认不使用时间衰减,适合B2B场景  
114 -python3 scripts/i2i_swing.py \  
115 - --lookback_days 365 \  
116 - --top_n 50 \  
117 - --debug  
118 -  
119 -# 如果需要开启时间衰减(不推荐)  
120 -python3 scripts/i2i_swing.py \  
121 - --lookback_days 365 \  
122 - --time_decay \  
123 - --decay_factor 0.99 # 更缓慢的衰减  
124 -```  
125 -  
126 -### 兴趣聚合(已自动优化)  
127 -```bash  
128 -# 已默认关闭时间衰减  
129 -python3 scripts/interest_aggregation.py \  
130 - --lookback_days 365 \  
131 - --top_n 100 \  
132 - --debug  
133 -```  
134 -  
135 -### 运行所有任务  
136 -```bash  
137 -cd /home/tw/recommendation/offline_tasks  
138 -  
139 -# 使用更长的回溯天数,适合低频场景  
140 -python3 run_all.py --lookback_days 365 --top_n 50 --debug  
141 -```  
142 -  
143 ----  
144 -  
145 -## 📊 其他索引(无需修改)  
146 -  
147 -### i2i_deepwalk.py  
148 -- ✅ 不涉及session分割  
149 -- ✅ 不使用时间衰减  
150 -- ✅ 无需修改  
151 -  
152 -### i2i_content_similar.py  
153 -- ✅ 基于商品属性的相似度  
154 -- ✅ 不涉及时间因素  
155 -- ✅ 无需修改  
156 -  
157 ----  
158 -  
159 -## 💡 建议的配置调整  
160 -  
161 -### 1. 增加回溯天数  
162 -```python  
163 -# offline_tasks/config/offline_config.py  
164 -DEFAULT_LOOKBACK_DAYS = 365 # 从默认值改为365天  
165 -```  
166 -  
167 -### 2. 如果需要重新启用时间衰减(特殊场景)  
168 -```bash  
169 -# Swing算法  
170 -python3 scripts/i2i_swing.py --time_decay --decay_factor 0.99  
171 -  
172 -# 修改interest_aggregation.py中的hard-coded值  
173 -# 将 time_decay=False 改回 time_decay=True  
174 -```  
175 -  
176 ----  
177 -  
178 -## ✨ 优化效果  
179 -  
180 -### 预期改进  
181 -1. **Session W2V**:  
182 - - 不再因为时间间隔过长而丢失用户行为序列  
183 - - 能够更好地捕捉低频用户的行为模式  
184 -  
185 -2. **Swing算法**:  
186 - - 历史行为不会因时间衰减而被低估  
187 - - 在数据稀疏的情况下充分利用所有历史数据  
188 -  
189 -3. **兴趣聚合**:  
190 - - 长期累积的用户偏好得到保留  
191 - - 推荐结果更稳定  
192 -  
193 -### 需要监控的指标  
194 -- [ ] Session数量变化  
195 -- [ ] 相似物品覆盖率  
196 -- [ ] 推荐效果指标(CTR、转化率等)  
197 -  
198 ----  
199 -  
200 -## 📝 回滚方法  
201 -  
202 -如果需要恢复之前的逻辑:  
203 -  
204 -```bash  
205 -# 1. 恢复i2i_swing.py的时间衰减  
206 -git diff offline_tasks/scripts/i2i_swing.py  
207 -# 将 default=False 改回 default=True  
208 -  
209 -# 2. 恢复interest_aggregation.py的时间衰减  
210 -git diff offline_tasks/scripts/interest_aggregation.py  
211 -# 将所有 time_decay=False 改回 time_decay=True  
212 -  
213 -# 3. 恢复i2i_session_w2v.py的时间分割  
214 -git diff offline_tasks/scripts/i2i_session_w2v.py  
215 -# 恢复基于时间间隔的session分割逻辑  
216 -```  
217 -  
218 ----  
219 -  
220 -**修改时间**: 2025-10-16  
221 -**适用场景**: B2B低频交易场景  
222 -**核心原则**: 在低频场景下,所有历史数据都很宝贵,不要过度衰减  
223 -  
offline_tasks/CHANGES_SUMMARY.md deleted
@@ -1,326 +0,0 @@ @@ -1,326 +0,0 @@
1 -# 离线任务更新总结  
2 -  
3 -## 更新日期  
4 -2025-10-17  
5 -  
6 -## 更新内容  
7 -  
8 -### 1. 重构内容相似索引 (`i2i_content_similar.py`)  
9 -  
10 -#### 变化  
11 -- **从**: 基于数据库商品属性计算(TF-IDF + 余弦相似度)  
12 -- **到**: 基于Elasticsearch向量计算(KNN查询)  
13 -  
14 -#### 简化  
15 -- **移除**: 所有命令行参数(`--method`, `--top_n`, `--output`, `--debug`)  
16 -- **保留**: 无参数,配置内置在代码中  
17 -- **生成**: 两份索引文件(名称向量 + 图片向量)  
18 -  
19 -### 2. 简化运行脚本 (`run_all.py`)  
20 -  
21 -#### 移除的参数  
22 -- `--skip-i2i` - 跳过i2i任务  
23 -- `--skip-interest` - 跳过兴趣聚合  
24 -- `--only-swing` - 只运行Swing  
25 -- `--only-w2v` - 只运行W2V  
26 -- `--only-deepwalk` - 只运行DeepWalk  
27 -- `--only-content` - 只运行内容相似  
28 -- `--only-interest` - 只运行兴趣聚合  
29 -- `--lookback_days` - 回看天数  
30 -- `--top_n` - Top N数量  
31 -  
32 -#### 保留的参数  
33 -- `--debug` - 调试模式(唯一参数)  
34 -  
35 -#### 使用  
36 -```bash  
37 -# 之前  
38 -python run_all.py --lookback_days 30 --top_n 50 --skip-interest  
39 -  
40 -# 现在  
41 -python run_all.py  
42 -# 或者  
43 -python run_all.py --debug  
44 -```  
45 -  
46 -### 3. 更新Redis数据规范 (`REDIS_DATA_SPEC.md`)  
47 -  
48 -#### 新增索引  
49 -- `i2i_content_name`: 基于名称向量的相似索引  
50 -- `i2i_content_pic`: 基于图片向量的相似索引  
51 -  
52 -#### 更新统计  
53 -- Key数量: 245,000 → 270,000  
54 -- 总内存: ~135MB → ~160MB  
55 -  
56 -### 4. 更新索引加载器 (`load_index_to_redis.py`)  
57 -  
58 -#### 更新  
59 -- 添加 `content_name` 到i2i索引类型列表  
60 -- 添加 `content_pic` 到i2i索引类型列表  
61 -- 自动加载两个新的内容相似索引  
62 -  
63 -### 5. 更新依赖 (`requirements.txt`)  
64 -  
65 -#### 新增  
66 -```  
67 -elasticsearch>=8.0.0  
68 -```  
69 -  
70 -### 6. 新增文档  
71 -  
72 -#### ES向量相似度说明 (`ES_VECTOR_SIMILARITY.md`)  
73 -- ES配置说明  
74 -- 工作流程详解  
75 -- 性能说明和优化建议  
76 -- 故障排查指南  
77 -  
78 -#### 更新说明 (`CONTENT_SIMILARITY_UPDATE.md`)  
79 -- 更新概述  
80 -- 主要变化  
81 -- 使用指南  
82 -- 技术细节  
83 -- 性能说明  
84 -- 与其他算法对比  
85 -  
86 -#### 本文档 (`CHANGES_SUMMARY.md`)  
87 -- 所有变更的简要总结  
88 -  
89 -### 7. 新增测试脚本 (`test_es_connection.py`)  
90 -  
91 -测试ES连接和向量查询功能:  
92 -- 测试ES连接  
93 -- 测试索引是否存在  
94 -- 测试向量字段映射  
95 -- 测试查询商品向量  
96 -- 测试KNN向量查询  
97 -  
98 -## 文件清单  
99 -  
100 -### 修改的文件  
101 -1. ✅ `offline_tasks/scripts/i2i_content_similar.py` - 完全重写  
102 -2. ✅ `offline_tasks/run_all.py` - 简化参数  
103 -3. ✅ `offline_tasks/REDIS_DATA_SPEC.md` - 更新规范  
104 -4. ✅ `offline_tasks/scripts/load_index_to_redis.py` - 添加新索引类型  
105 -5. ✅ `requirements.txt` - 添加elasticsearch依赖  
106 -  
107 -### 新增的文件  
108 -6. ✅ `offline_tasks/scripts/ES_VECTOR_SIMILARITY.md` - ES向量说明  
109 -7. ✅ `offline_tasks/CONTENT_SIMILARITY_UPDATE.md` - 更新说明  
110 -8. ✅ `offline_tasks/CHANGES_SUMMARY.md` - 本文档  
111 -9. ✅ `offline_tasks/scripts/test_es_connection.py` - ES测试脚本  
112 -  
113 -## 使用指南  
114 -  
115 -### 1. 安装依赖  
116 -  
117 -```bash  
118 -pip install -r requirements.txt  
119 -```  
120 -  
121 -### 2. 测试ES连接  
122 -  
123 -```bash  
124 -cd /home/tw/recommendation/offline_tasks  
125 -python scripts/test_es_connection.py  
126 -```  
127 -  
128 -### 3. 运行内容相似索引生成  
129 -  
130 -```bash  
131 -# 单独运行  
132 -python scripts/i2i_content_similar.py  
133 -  
134 -# 或通过run_all运行所有任务  
135 -python run_all.py  
136 -```  
137 -  
138 -### 4. 加载到Redis  
139 -  
140 -```bash  
141 -python scripts/load_index_to_redis.py  
142 -```  
143 -  
144 -## 输出文件  
145 -  
146 -### 新增的输出文件  
147 -- `output/i2i_content_name_YYYYMMDD.txt` - 名称向量相似索引  
148 -- `output/i2i_content_pic_YYYYMMDD.txt` - 图片向量相似索引  
149 -  
150 -### 文件格式  
151 -```  
152 -item_id \t item_name \t similar_id1:score1,similar_id2:score2,...  
153 -```  
154 -  
155 -### 示例  
156 -```  
157 -3302275 香蕉干 3302276:0.9234,3302277:0.8756,3302278:0.8432  
158 -```  
159 -  
160 -## Redis Keys  
161 -  
162 -### 新增的Key格式  
163 -```  
164 -item:similar:content_name:{item_id}  
165 -item:similar:content_pic:{item_id}  
166 -```  
167 -  
168 -### Value格式  
169 -```json  
170 -[[similar_id1,score1],[similar_id2,score2],...]  
171 -```  
172 -  
173 -### 查询示例  
174 -```python  
175 -import redis  
176 -import json  
177 -  
178 -r = redis.Redis(host='localhost', port=6379, db=0)  
179 -  
180 -# 名称向量相似  
181 -similar = json.loads(r.get('item:similar:content_name:3302275'))  
182 -# 返回: [[3302276, 0.9234], [3302277, 0.8756], ...]  
183 -  
184 -# 图片向量相似  
185 -similar = json.loads(r.get('item:similar:content_pic:3302275'))  
186 -# 返回: [[4503826, 0.8123], [4503827, 0.7856], ...]  
187 -```  
188 -  
189 -## 性能指标  
190 -  
191 -### 内容相似索引生成  
192 -- 活跃商品: ~50,000  
193 -- 运行时间: 50-60分钟  
194 -- 内存占用: < 2GB  
195 -  
196 -### Redis存储  
197 -- 新增Keys: ~100,000 (两份索引各50,000)  
198 -- 新增内存: ~50MB  
199 -- TTL: 30天  
200 -  
201 -## 兼容性  
202 -  
203 -### 向后兼容  
204 -- ✅ 其他i2i算法(Swing, W2V, DeepWalk)不受影响  
205 -- ✅ 兴趣聚合算法不受影响  
206 -- ✅ Redis加载器向后兼容  
207 -- ✅ 在线查询API不受影响  
208 -  
209 -### 不兼容的变化  
210 -- ❌ `i2i_content_similar.py` 命令行参数全部改变  
211 -- ❌ 旧的 `i2i_content_hybrid_*.txt` 文件不再生成  
212 -  
213 -## 迁移指南  
214 -  
215 -### 如果之前使用了内容相似索引  
216 -  
217 -1. **更新脚本调用**  
218 - ```bash  
219 - # 旧版本  
220 - python i2i_content_similar.py --top_n 50 --method hybrid  
221 -  
222 - # 新版本  
223 - python i2i_content_similar.py # 无需参数  
224 - ```  
225 -  
226 -2. **更新Redis Key**  
227 - ```python  
228 - # 旧版本  
229 - r.get('item:similar:content:{item_id}')  
230 -  
231 - # 新版本(两个选择)  
232 - r.get('item:similar:content_name:{item_id}') # 名称相似  
233 - r.get('item:similar:content_pic:{item_id}') # 图片相似  
234 - ```  
235 -  
236 -3. **更新在线API**  
237 - - 如果API使用了 `content` 算法,需要更新为 `content_name` 或 `content_pic`  
238 - - 建议支持两种算法,让前端选择或混合使用  
239 -  
240 -## 技术栈  
241 -  
242 -### 新增技术  
243 -- **Elasticsearch**: 向量存储和KNN查询  
244 -- **KNN算法**: 基于向量的相似度计算  
245 -  
246 -### ES配置  
247 -```python  
248 -ES_CONFIG = {  
249 - 'host': 'http://localhost:9200',  
250 - 'index_name': 'spu',  
251 - 'username': 'essa',  
252 - 'password': '4hOaLaf41y2VuI8y'  
253 -}  
254 -```  
255 -  
256 -### 向量字段  
257 -- `embedding_name_zh`: 名称文本向量 (1024维, dot_product)  
258 -- `embedding_pic_h14.vector`: 图片向量 (1024维, dot_product)  
259 -  
260 -## 优势  
261 -  
262 -### 相比旧版本  
263 -1. **更简单**: 无需参数配置  
264 -2. **更快**: ES KNN查询比TF-IDF快  
265 -3. **更准**: 深度学习向量比手工特征准  
266 -4. **更多维度**: 名称 + 图片两个维度  
267 -  
268 -### 使用场景  
269 -- **名称向量**: 语义相似推荐(同类但不同品牌)  
270 -- **图片向量**: 视觉相似推荐(外观相似商品)  
271 -  
272 -## 注意事项  
273 -  
274 -1. **ES依赖**: 需要Elasticsearch服务可用  
275 -2. **向量数据**: 需要ES中有向量数据  
276 -3. **网络延迟**: ES查询受网络影响  
277 -4. **首次运行**: 可能较慢,建议先测试连接  
278 -  
279 -## 故障排查  
280 -  
281 -### ES连接失败  
282 -```bash  
283 -# 检查ES是否可访问  
284 -curl -u essa:4hOaLaf41y2VuI8y http://localhost:9200  
285 -  
286 -# 运行测试脚本  
287 -python scripts/test_es_connection.py  
288 -```  
289 -  
290 -### 向量字段不存在  
291 -```bash  
292 -# 检查ES mapping  
293 -curl -u essa:4hOaLaf41y2VuI8y http://localhost:9200/spu/_mapping  
294 -```  
295 -  
296 -### 查询超时  
297 -- 增加 `request_timeout` 参数  
298 -- 检查网络连接  
299 -- 减少 `KNN_CANDIDATES` 参数  
300 -  
301 -## 后续优化  
302 -  
303 -1. **批量查询**: 使用 `_mget` 批量获取向量  
304 -2. **并发处理**: 多线程提高查询效率  
305 -3. **增量更新**: 只处理变化的商品  
306 -4. **缓存向量**: 避免重复查询ES  
307 -5. **监控告警**: 添加性能监控和异常告警  
308 -  
309 -## 相关文档  
310 -  
311 -- `ES_VECTOR_SIMILARITY.md` - ES向量详细说明  
312 -- `CONTENT_SIMILARITY_UPDATE.md` - 更新详细说明  
313 -- `REDIS_DATA_SPEC.md` - Redis数据规范  
314 -- `README.md` - 项目概述  
315 -  
316 -## 总结  
317 -  
318 -本次更新大幅简化了内容相似索引的使用,从基于属性的相似度改为基于深度学习向量的相似度,提供了更准确和多维度的相似商品推荐。同时简化了参数配置,降低了使用和维护成本。  
319 -  
320 ----  
321 -  
322 -**变更**: 9个文件(5个修改,4个新增)  
323 -**影响**: 内容相似索引生成和使用方式  
324 -**破坏性**: 中等(API兼容,但参数和Key格式改变)  
325 -**优先级**: 高(建议尽快更新)  
326 -  
offline_tasks/CONTENT_SIMILARITY_UPDATE.md deleted
@@ -1,243 +0,0 @@ @@ -1,243 +0,0 @@
1 -# 内容相似索引更新说明  
2 -  
3 -## 📋 更新概述  
4 -  
5 -重构了 `i2i_content_similar.py`,从基于数据库属性计算改为基于Elasticsearch向量计算,生成两份内容相似索引。  
6 -  
7 -## 🔄 主要变化  
8 -  
9 -### 1. 算法改变  
10 -  
11 -**之前 (旧版本):**  
12 -- 基于商品属性(分类、供应商、包装等)  
13 -- 使用TF-IDF + 余弦相似度  
14 -- 提供 `--method` 参数选择: tfidf / category / hybrid  
15 -- 复杂的参数配置  
16 -  
17 -**现在 (新版本):**  
18 -- 基于Elasticsearch的向量相似度  
19 -- 使用KNN向量查询  
20 -- **无需任何参数,开箱即用**  
21 -- 自动生成两份索引  
22 -  
23 -### 2. 生成的索引  
24 -  
25 -| 索引名称 | 向量来源 | 文件名 | Redis Key | TTL |  
26 -|---------|---------|--------|-----------|-----|  
27 -| **名称向量相似** | `embedding_name_zh` | `i2i_content_name_YYYYMMDD.txt` | `item:similar:content_name:{item_id}` | 30天 |  
28 -| **图片向量相似** | `embedding_pic_h14` | `i2i_content_pic_YYYYMMDD.txt` | `item:similar:content_pic:{item_id}` | 30天 |  
29 -  
30 -### 3. 参数简化  
31 -  
32 -**之前:**  
33 -```bash  
34 -python i2i_content_similar.py --top_n 50 --method hybrid --debug  
35 -```  
36 -  
37 -**现在:**  
38 -```bash  
39 -python i2i_content_similar.py  
40 -# 就这么简单!无需任何参数  
41 -```  
42 -  
43 -所有配置都在代码中预设好:  
44 -- `TOP_N = 50`: 返回前50个相似商品  
45 -- `KNN_K = 100`: KNN查询返回100个候选  
46 -- `KNN_CANDIDATES = 200`: 候选池大小200  
47 -  
48 -## 📝 更新的文件  
49 -  
50 -### 核心代码  
51 -1. ✅ `offline_tasks/scripts/i2i_content_similar.py` - 完全重写  
52 - - 连接Elasticsearch  
53 - - 查询最近1年活跃商品  
54 - - 获取向量并计算相似度  
55 - - 生成两份索引  
56 -  
57 -### 配置文档  
58 -2. ✅ `offline_tasks/REDIS_DATA_SPEC.md` - 更新Redis数据规范  
59 - - 添加 `i2i_content_name` 规范  
60 - - 添加 `i2i_content_pic` 规范  
61 - - 更新内存占用估算(270,000 keys, ~160MB)  
62 -  
63 -### 调度脚本  
64 -3. ✅ `offline_tasks/run_all.py` - 简化参数  
65 - - 移除 `--only-*` 参数  
66 - - 移除 `--skip-*` 参数  
67 - - 移除 `--lookback_days` 和 `--top_n` 参数  
68 - - 只保留 `--debug` 参数  
69 - - 添加内容相似任务  
70 -  
71 -4. ✅ `offline_tasks/scripts/load_index_to_redis.py` - 更新加载逻辑  
72 - - 添加 `content_name` 和 `content_pic` 到索引类型列表  
73 -  
74 -### 新增文档  
75 -5. ✅ `offline_tasks/scripts/ES_VECTOR_SIMILARITY.md` - ES向量相似度说明  
76 - - ES配置说明  
77 - - 工作流程详解  
78 - - 性能说明和优化建议  
79 - - 故障排查指南  
80 -  
81 -6. ✅ `offline_tasks/CONTENT_SIMILARITY_UPDATE.md` - 本文档  
82 -  
83 -## 🚀 使用指南  
84 -  
85 -### 安装依赖  
86 -  
87 -需要安装Elasticsearch客户端:  
88 -```bash  
89 -pip install elasticsearch  
90 -```  
91 -  
92 -### 配置ES连接  
93 -  
94 -在 `i2i_content_similar.py` 中修改ES配置(如需要):  
95 -```python  
96 -ES_CONFIG = {  
97 - 'host': 'http://localhost:9200',  
98 - 'index_name': 'spu',  
99 - 'username': 'essa',  
100 - 'password': '4hOaLaf41y2VuI8y'  
101 -}  
102 -```  
103 -  
104 -### 运行脚本  
105 -  
106 -#### 单独运行  
107 -```bash  
108 -cd /home/tw/recommendation/offline_tasks  
109 -python scripts/i2i_content_similar.py  
110 -```  
111 -  
112 -#### 通过run_all运行  
113 -```bash  
114 -python run_all.py  
115 -```  
116 -  
117 -### 加载到Redis  
118 -```bash  
119 -python scripts/load_index_to_redis.py --date 20251017  
120 -```  
121 -  
122 -## 📊 输出示例  
123 -  
124 -### 文件格式  
125 -```  
126 -3302275 香蕉干 3302276:0.9234,3302277:0.8756,3302278:0.8432  
127 -```  
128 -  
129 -### Redis存储  
130 -```python  
131 -# 名称向量相似  
132 -GET item:similar:content_name:3302275  
133 -# 返回: [[3302276,0.9234],[3302277,0.8756],[3302278,0.8432]]  
134 -  
135 -# 图片向量相似  
136 -GET item:similar:content_pic:3302275  
137 -# 返回: [[4503826,0.8123],[4503827,0.7856],[4503828,0.7645]]  
138 -```  
139 -  
140 -## 🔍 技术细节  
141 -  
142 -### 数据源  
143 -  
144 -1. **活跃商品列表**  
145 - - 来源: 数据库 `sensors_events` 表  
146 - - 条件: 最近1年内有行为记录  
147 - - 行为类型: click, contactFactory, addToPool, addToCart, purchase  
148 -  
149 -2. **向量数据**  
150 - - 来源: Elasticsearch `spu` 索引  
151 - - 字段:  
152 - - `embedding_name_zh`: 名称文本向量 (1024维)  
153 - - `embedding_pic_h14.vector`: 图片向量 (1024维)  
154 - - `name_zh`: 商品中文名称  
155 -  
156 -### ES查询  
157 -  
158 -#### 1. 获取商品向量  
159 -```json  
160 -{  
161 - "query": {  
162 - "term": {"_id": "商品ID"}  
163 - },  
164 - "_source": {  
165 - "includes": ["_id", "name_zh", "embedding_name_zh", "embedding_pic_h14"]  
166 - }  
167 -}  
168 -```  
169 -  
170 -#### 2. KNN相似度查询  
171 -```json  
172 -{  
173 - "knn": {  
174 - "field": "embedding_name_zh",  
175 - "query_vector": [向量],  
176 - "k": 100,  
177 - "num_candidates": 200  
178 - },  
179 - "_source": ["_id", "name_zh"],  
180 - "size": 100  
181 -}  
182 -```  
183 -  
184 -## ⚡ 性能说明  
185 -  
186 -### 运行时间  
187 -- 活跃商品数: ~50,000  
188 -- 向量查询: ~50,000次 × 10ms = 8-10分钟  
189 -- KNN查询: ~50,000次 × 50ms = 40-50分钟  
190 -- **总计: 约50-60分钟**  
191 -  
192 -### 优化建议  
193 -1. 批量查询: 使用 `_mget` 批量获取向量  
194 -2. 并发处理: 多线程/异步IO  
195 -3. 增量更新: 只处理变化的商品  
196 -4. 缓存向量: 避免重复查询  
197 -  
198 -## 🆚 与其他算法对比  
199 -  
200 -| 算法 | 数据源 | 计算方式 | 特点 | 更新频率 |  
201 -|-----|-------|---------|------|---------|  
202 -| **Swing** | 用户行为 | 共现关系 | 捕获真实交互 | 每天 |  
203 -| **W2V** | 用户会话 | 序列学习 | 捕获序列关系 | 每天 |  
204 -| **DeepWalk** | 行为图 | 图游走 | 发现深层关联 | 每天 |  
205 -| **名称向量** | ES向量 | KNN查询 | 语义相似 | 每周 |  
206 -| **图片向量** | ES向量 | KNN查询 | 视觉相似 | 每周 |  
207 -  
208 -## 📋 待办事项  
209 -  
210 -- [x] 重写 `i2i_content_similar.py`  
211 -- [x] 更新 `REDIS_DATA_SPEC.md`  
212 -- [x] 简化 `run_all.py` 参数  
213 -- [x] 更新 `load_index_to_redis.py`  
214 -- [x] 编写技术文档  
215 -- [ ] 添加单元测试  
216 -- [ ] 性能优化(批量查询)  
217 -- [ ] 添加监控和告警  
218 -  
219 -## ⚠️ 注意事项  
220 -  
221 -1. **ES连接**: 确保能访问ES服务器  
222 -2. **向量缺失**: 部分商品可能没有向量,会被跳过  
223 -3. **网络延迟**: ES查询受网络影响,建议内网部署  
224 -4. **内存占用**: 处理大量商品时注意内存使用  
225 -5. **依赖安装**: 需要安装 `elasticsearch` Python包  
226 -  
227 -## 🔗 相关文档  
228 -  
229 -- `ES_VECTOR_SIMILARITY.md` - ES向量相似度详细说明  
230 -- `REDIS_DATA_SPEC.md` - Redis数据规范  
231 -- `OFFLINE_INDEX_SPEC.md` - 离线索引规范  
232 -- `QUICKSTART.md` - 快速开始指南  
233 -  
234 -## 📞 联系方式  
235 -  
236 -如有问题或建议,请联系开发团队。  
237 -  
238 ----  
239 -  
240 -**更新日期**: 2025-10-17  
241 -**版本**: v2.0  
242 -**作者**: AI Assistant  
243 -  
offline_tasks/CURRENT_STATUS.md deleted
@@ -1,229 +0,0 @@ @@ -1,229 +0,0 @@
1 -# 当前状态说明  
2 -  
3 -## ✅ 已完成并可用的功能  
4 -  
5 -### 1. i2i 行为相似算法(100%可用)  
6 -- ✅ **Swing算法** - 已适配实际数据库字段  
7 -- ✅ **Session W2V** - 已适配实际数据库字段  
8 -- ✅ **DeepWalk** - 已适配实际数据库字段  
9 -  
10 -**使用的字段**(已验证存在):  
11 -- `sensors_events.anonymous_id`  
12 -- `sensors_events.item_id`  
13 -- `sensors_events.event`  
14 -- `sensors_events.create_time`  
15 -- `prd_goods_sku.id`  
16 -- `prd_goods_sku.name`  
17 -  
18 -**输出格式**:  
19 -```  
20 -item_id \t item_name \t similar_item_id1:score1,similar_item_id2:score2,...  
21 -```  
22 -  
23 -**运行命令**:  
24 -```bash  
25 -# 单独运行  
26 -python3 scripts/i2i_swing.py --lookback_days 730 --top_n 50  
27 -python3 scripts/i2i_session_w2v.py --lookback_days 730 --top_n 50  
28 -python3 scripts/i2i_deepwalk.py --lookback_days 730 --top_n 50  
29 -```  
30 -  
31 ----  
32 -  
33 -### 2. 兴趣点聚合(部分可用)  
34 -  
35 -#### 已适配的维度:  
36 -✅ **business_platform** - 业务平台维度  
37 -```  
38 -platform:pc → item_id1:score1,item_id2:score2,...  
39 -platform:mobile → ...  
40 -```  
41 -  
42 -✅ **client_platform** - 客户端平台维度  
43 -```  
44 -client_platform:web → item_id1:score1,item_id2:score2,...  
45 -client_platform:app → ...  
46 -```  
47 -  
48 -✅ **platform_client** - 组合维度  
49 -```  
50 -platform_client:pc_web → item_id1:score1,item_id2:score2,...  
51 -```  
52 -  
53 -#### 已适配的列表类型:  
54 -✅ **hot** - 热门商品(基于最近180天)  
55 -✅ **cart** - 加购商品  
56 -✅ **new** - 新品(基于create_time)  
57 -  
58 -**运行命令**:  
59 -```bash  
60 -python3 scripts/interest_aggregation.py --lookback_days 730 --top_n 1000  
61 -```  
62 -  
63 ----  
64 -  
65 -## ⚠️ 原计划但未实现的功能(因字段不存在)  
66 -  
67 -### sensors_events 表缺失字段:  
68 -- ❌ `country` - 国家/销售区域  
69 -- ❌ `customer_type` - 客户类型  
70 -  
71 -### prd_goods_sku 表缺失字段:  
72 -- ❌ `category_level2_id` - 二级分类  
73 -- ❌ `category_level3_id` - 三级分类  
74 -  
75 -### 影响的索引:  
76 -- ❌ country:{country}  
77 -- ❌ customer_type:{type}  
78 -- ❌ category_level2:{cat_id}  
79 -- ❌ category_level3:{cat_id}  
80 -- ❌ 相关的组合维度索引  
81 -  
82 ----  
83 -  
84 -## 📊 业务场景映射(更新后)  
85 -  
86 -### 场景1: 首页猜你喜欢  
87 -**可用索引**:  
88 -```python  
89 -# 按平台推荐  
90 -interest:hot:platform:pc  
91 -interest:hot:platform:mobile  
92 -  
93 -# 按客户端平台推荐  
94 -interest:hot:client_platform:web  
95 -interest:hot:client_platform:app  
96 -  
97 -# 组合维度  
98 -interest:hot:platform_client:pc_web  
99 -```  
100 -  
101 -### 场景2: 详情页大家都在看  
102 -**可用索引**:  
103 -```python  
104 -# i2i相似度(完全可用)  
105 -i2i:swing:{item_id}  
106 -i2i:session_w2v:{item_id}  
107 -i2i:deepwalk:{item_id}  
108 -```  
109 -  
110 -### 场景3: 搜索结果页推荐  
111 -**可用索引**:  
112 -```python  
113 -# 按平台的全局推荐  
114 -interest:global:platform:pc  
115 -interest:global:client_platform:web  
116 -  
117 -# 或使用 page_type(需要扩展)  
118 -interest:global:page_type:search  
119 -```  
120 -  
121 ----  
122 -  
123 -## 🎯 当前可用的完整索引列表  
124 -  
125 -### i2i索引(完全可用)  
126 -```  
127 -i2i:swing:{item_id}  
128 -i2i:session_w2v:{item_id}  
129 -i2i:deepwalk:{item_id}  
130 -```  
131 -  
132 -### 兴趣点聚合索引(部分可用)  
133 -  
134 -**单维度**:  
135 -```  
136 -platform:{business_platform} # 如:platform:pc  
137 -client_platform:{client_platform} # 如:client_platform:web  
138 -```  
139 -  
140 -**组合维度**:  
141 -```  
142 -platform_client:{platform}_{client} # 如:platform_client:pc_web  
143 -```  
144 -  
145 -**列表类型前缀**:  
146 -```  
147 -interest:hot:...  
148 -interest:cart:...  
149 -interest:new:...  
150 -interest:global:...  
151 -```  
152 -  
153 -**完整示例**:  
154 -```  
155 -interest:hot:platform:pc  
156 -interest:hot:client_platform:web  
157 -interest:hot:platform_client:pc_web  
158 -interest:cart:platform:mobile  
159 -interest:new:client_platform:app  
160 -interest:global:platform:pc  
161 -```  
162 -  
163 ----  
164 -  
165 -## 🚀 快速运行  
166 -  
167 -### 测试i2i功能(完全可用)  
168 -```bash  
169 -cd /home/tw/recommendation/offline_tasks  
170 -  
171 -# 运行Swing算法(小数据量测试)  
172 -python3 scripts/i2i_swing.py --lookback_days 30 --top_n 10  
173 -  
174 -# 查看输出  
175 -head -n 5 output/i2i_swing_*.txt  
176 -```  
177 -  
178 -### 测试兴趣点聚合(部分可用)  
179 -```bash  
180 -# 运行兴趣点聚合(小数据量测试)  
181 -python3 scripts/interest_aggregation.py --lookback_days 30 --top_n 100  
182 -  
183 -# 查看输出  
184 -head -n 10 output/interest_aggregation_hot_*.txt  
185 -grep "^platform:" output/interest_aggregation_hot_*.txt | head -5  
186 -```  
187 -  
188 -### 运行所有可用任务  
189 -```bash  
190 -# 运行全部  
191 -python3 run_all.py --lookback_days 730 --top_n 50  
192 -  
193 -# 查看日志  
194 -tail -f logs/run_all_*.log  
195 -```  
196 -  
197 ----  
198 -  
199 -## 💡 建议  
200 -  
201 -### 短期建议(立即可用)  
202 -1. **优先使用 i2i 功能** - 这部分功能完整且经过验证  
203 -2. **使用现有平台维度** - platform 和 client_platform 可以满足基本需求  
204 -3. **测试小数据量** - 先用30天数据测试,确认无误后再用完整数据  
205 -  
206 -### 中期建议(需要扩展)  
207 -1. **添加更多维度** - 可以考虑使用 `page_type`、`item_type` 等现有字段  
208 -2. **关联其他表** - 如果其他表有分类信息,可以通过 JOIN 获取  
209 -3. **解析JSON字段** - `__properties` 可能包含额外信息  
210 -  
211 -### 长期建议(需要数据支持)  
212 -1. **补充用户特征字段** - 在 sensors_events 表中添加 country、customer_type 字段  
213 -2. **补充商品分类字段** - 在 prd_goods_sku 表或关联表中添加分类信息  
214 -3. **建立用户画像表** - 单独维护用户属性信息  
215 -  
216 ----  
217 -  
218 -## 📞 文档索引  
219 -  
220 -- **FIELD_MAPPING.md** - 字段映射详细说明  
221 -- **DATABASE_SETUP.md** - 数据库配置指南  
222 -- **TROUBLESHOOTING.md** - 故障排除  
223 -- **CHANGELOG.md** - 更新日志  
224 -- **README.md** - 完整文档  
225 -  
226 ----  
227 -  
228 -**更新时间**: 2025-10-16  
229 -**状态**: i2i功能完全可用,兴趣点聚合部分可用  
offline_tasks/DELIVERY.md deleted
@@ -1,335 +0,0 @@ @@ -1,335 +0,0 @@
1 -# 推荐系统离线任务 - 交付文档  
2 -  
3 -## 📋 项目概述  
4 -  
5 -根据您的需求,已完成推荐系统的离线任务部分构建,包括:  
6 -  
7 -1. **i2i 行为相似索引**:实现了3种算法(Swing、Session W2V、DeepWalk)  
8 -2. **兴趣点聚合索引**:支持多维度(平台、国家、客户类型、分类)和多列表类型(热门、加购、新品)  
9 -  
10 -## ✅ 已完成的工作  
11 -  
12 -### 1. 核心功能实现  
13 -  
14 -#### 1.1 i2i 行为相似算法(参考 item_sim.py 改写)  
15 -  
16 -| 算法 | 文件 | 状态 | 说明 |  
17 -|------|------|------|------|  
18 -| **Swing** | `scripts/i2i_swing.py` | ✅ 完成 | 改写自collaboration/swing.cc,适配现有数据格式 |  
19 -| **Session W2V** | `scripts/i2i_session_w2v.py` | ✅ 完成 | 改写自graphembedding/session_w2v,支持用户会话序列 |  
20 -| **DeepWalk** | `scripts/i2i_deepwalk.py` | ✅ 完成 | 改写自graphembedding/deepwalk,支持图随机游走 |  
21 -  
22 -**特性**:  
23 -- ✅ 适配真实数据库(SelectDB)  
24 -- ✅ 支持时间衰减(2年数据,权重衰减)  
25 -- ✅ 支持行为权重(click/addToCart/contactFactory/purchase等)  
26 -- ✅ 输出格式与 item_sim.py 一致  
27 -  
28 -#### 1.2 兴趣点聚合索引  
29 -  
30 -| 维度类型 | 示例 | 状态 |  
31 -|---------|------|------|  
32 -| 平台 | platform:PC | ✅ 完成 |  
33 -| 国家/销售区域 | country:US | ✅ 完成 |  
34 -| 客户类型 | customer_type:retailer | ✅ 完成 |  
35 -| 二级分类 | category_level2:100 | ✅ 完成 |  
36 -| 三级分类 | category_level3:200 | ✅ 完成 |  
37 -| 组合维度 | platform_country:PC_US | ✅ 完成 |  
38 -  
39 -| 列表类型 | 说明 | 状态 |  
40 -|---------|------|------|  
41 -| **热门** (hot) | 最近180天高交互商品 | ✅ 完成 |  
42 -| **加购** (cart) | 基于加购行为 | ✅ 完成 |  
43 -| **新品** (new) | 最近90天上架商品 | ✅ 完成 |  
44 -| **全局** (global) | 所有数据综合 | ✅ 完成 |  
45 -  
46 -**特性**:  
47 -- ✅ 时间衰减(最近2年,权重随时间衰减)  
48 -- ✅ 多维度组合支持  
49 -- ✅ 可配置的top N输出  
50 -  
51 -### 2. 基础设施  
52 -  
53 -| 组件 | 文件 | 状态 | 说明 |  
54 -|------|------|------|------|  
55 -| 数据库连接 | `db_service.py` | ✅ 完成 | 统一的数据库连接服务 |  
56 -| 配置管理 | `config/offline_config.py` | ✅ 完成 | 集中的配置管理 |  
57 -| 统一调度 | `run_all.py` | ✅ 完成 | 一键运行所有任务 |  
58 -| Redis加载 | `scripts/load_index_to_redis.py` | ✅ 完成 | 索引加载到Redis |  
59 -| 连接测试 | `test_connection.py` | ✅ 完成 | 验证环境配置 |  
60 -| 查询示例 | `example_query_redis.py` | ✅ 完成 | 演示如何使用索引 |  
61 -  
62 -### 3. 文档  
63 -  
64 -| 文档 | 文件 | 状态 | 说明 |  
65 -|------|------|------|------|  
66 -| 详细文档 | `README.md` | ✅ 完成 | 完整的使用说明 |  
67 -| 快速开始 | `QUICKSTART.md` | ✅ 完成 | 快速上手指南 |  
68 -| 项目总结 | `PROJECT_SUMMARY.md` | ✅ 完成 | 技术架构和原理 |  
69 -| 目录结构 | `STRUCTURE.md` | ✅ 完成 | 目录和数据流说明 |  
70 -| 安装脚本 | `install.sh` | ✅ 完成 | 自动化安装 |  
71 -| 依赖清单 | `requirements.txt` | ✅ 完成 | Python依赖包 |  
72 -  
73 -## 📁 交付文件清单  
74 -  
75 -```  
76 -/home/tw/recommendation/  
77 -├── db_service.py # 数据库连接服务  
78 -├── requirements.txt # 依赖包清单  
79 -│  
80 -└── offline_tasks/ # 离线任务主目录  
81 - ├── config/  
82 - │ └── offline_config.py # 配置文件  
83 - │  
84 - ├── scripts/ # 核心算法脚本  
85 - │ ├── i2i_swing.py # ✅ Swing算法  
86 - │ ├── i2i_session_w2v.py # ✅ Session W2V  
87 - │ ├── i2i_deepwalk.py # ✅ DeepWalk  
88 - │ ├── interest_aggregation.py # ✅ 兴趣点聚合  
89 - │ └── load_index_to_redis.py # ✅ Redis加载  
90 - │  
91 - ├── output/ # 输出目录(运行后生成)  
92 - ├── logs/ # 日志目录(运行后生成)  
93 - │  
94 - ├── run_all.py # ✅ 统一调度脚本  
95 - ├── install.sh # ✅ 安装脚本  
96 - ├── test_connection.py # ✅ 连接测试  
97 - ├── example_query_redis.py # ✅ 查询示例  
98 - │  
99 - └── 文档/  
100 - ├── README.md # ✅ 详细文档  
101 - ├── QUICKSTART.md # ✅ 快速开始  
102 - ├── PROJECT_SUMMARY.md # ✅ 项目总结  
103 - ├── STRUCTURE.md # ✅ 目录结构  
104 - └── DELIVERY.md # ✅ 本文档  
105 -```  
106 -  
107 -## 🚀 快速开始  
108 -  
109 -### 步骤1: 安装依赖  
110 -  
111 -```bash  
112 -cd /home/tw/recommendation/offline_tasks  
113 -bash install.sh  
114 -```  
115 -  
116 -### 步骤2: 配置数据库  
117 -  
118 -编辑 `config/offline_config.py`,确保数据库连接信息正确。  
119 -  
120 -### 步骤3: 测试连接  
121 -  
122 -```bash  
123 -python3 test_connection.py  
124 -```  
125 -  
126 -### 步骤4: 运行离线任务  
127 -  
128 -```bash  
129 -# 运行所有任务  
130 -python3 run_all.py --lookback_days 730 --top_n 50  
131 -  
132 -# 或者运行单个任务  
133 -python3 scripts/i2i_swing.py --lookback_days 730 --top_n 50  
134 -python3 scripts/interest_aggregation.py --lookback_days 730 --top_n 1000  
135 -```  
136 -  
137 -### 步骤5: 加载索引到Redis  
138 -  
139 -```bash  
140 -python3 scripts/load_index_to_redis.py --redis-host localhost --redis-port 6379  
141 -```  
142 -  
143 -### 步骤6: 查询验证  
144 -  
145 -```bash  
146 -python3 example_query_redis.py  
147 -```  
148 -  
149 -## 📊 数据格式说明  
150 -  
151 -### i2i索引格式  
152 -```  
153 -item_id \t item_name \t similar_item_id1:score1,similar_item_id2:score2,...  
154 -```  
155 -  
156 -**示例**:  
157 -```  
158 -123456 商品A 234567:0.8523,345678:0.7842,456789:0.7234  
159 -```  
160 -  
161 -### 兴趣点聚合索引格式  
162 -```  
163 -dimension_key \t item_id1:score1,item_id2:score2,...  
164 -```  
165 -  
166 -**示例**:  
167 -```  
168 -platform:PC 12345:98.52,23456:87.34,34567:76.89  
169 -country:US 45678:156.23,56789:142.87,67890:128.45  
170 -platform_country:PC_US 78901:234.56,89012:198.76,90123:187.23  
171 -```  
172 -  
173 -## 🎯 业务场景对应  
174 -  
175 -根据您提供的业务场景,索引使用方式如下:  
176 -  
177 -### 1. 首页猜你喜欢  
178 -**使用索引**:兴趣点聚合 (hot + global)  
179 -  
180 -```python  
181 -# 获取用户特征  
182 -platform = user.platform # PC/Mobile  
183 -country = user.country # US/UK/CN...  
184 -customer_type = user.customer_type # retailer/wholesaler...  
185 -  
186 -# 查询多个维度的热门商品  
187 -hot_items_1 = redis.get(f"interest:hot:platform_country:{platform}_{country}")  
188 -hot_items_2 = redis.get(f"interest:hot:customer_type:{customer_type}")  
189 -hot_items_3 = redis.get(f"interest:global:country:{country}")  
190 -  
191 -# 融合多个结果  
192 -recommended_items = merge_and_rerank(hot_items_1, hot_items_2, hot_items_3)  
193 -```  
194 -  
195 -### 2. 详情页的大家都在看  
196 -**使用索引**:i2i 行为相似  
197 -  
198 -```python  
199 -# 当前浏览的商品ID  
200 -current_item_id = "123456"  
201 -  
202 -# 查询相似商品(可以组合多个算法)  
203 -similar_swing = redis.get(f"i2i:swing:{current_item_id}")  
204 -similar_w2v = redis.get(f"i2i:session_w2v:{current_item_id}")  
205 -similar_deepwalk = redis.get(f"i2i:deepwalk:{current_item_id}")  
206 -  
207 -# 融合结果  
208 -recommended_items = merge_i2i_results(similar_swing, similar_w2v, similar_deepwalk)  
209 -```  
210 -  
211 -### 3. 搜索结果页底部的供应商推荐  
212 -**使用索引**:兴趣点聚合 (按分类)  
213 -  
214 -```python  
215 -# 用户搜索的分类  
216 -category_level2 = search_query.category_level2  
217 -  
218 -# 查询该分类下的推荐商品  
219 -items = redis.get(f"interest:global:category_level2:{category_level2}")  
220 -  
221 -# 结合用户特征进行个性化排序  
222 -personalized_items = personalize_ranking(items, user_profile)  
223 -```  
224 -  
225 -## ⚙️ 配置参数说明  
226 -  
227 -### 关键配置(config/offline_config.py)  
228 -  
229 -```python  
230 -# 时间范围  
231 -LOOKBACK_DAYS = 730 # 回溯天数(2年)  
232 -RECENT_DAYS = 180 # 热门商品统计天数  
233 -NEW_DAYS = 90 # 新品定义天数  
234 -  
235 -# 时间衰减  
236 -time_decay_factor = 0.95 # 每30天衰减5%  
237 -  
238 -# 行为权重  
239 -behavior_weights = {  
240 - 'click': 1.0, # 点击  
241 - 'addToPool': 2.0, # 加入询盘池  
242 - 'addToCart': 3.0, # 加入购物车  
243 - 'contactFactory': 5.0, # 联系工厂  
244 - 'purchase': 10.0 # 购买  
245 -}  
246 -  
247 -# 输出数量  
248 -i2i_top_n = 50 # 每个商品的相似商品数  
249 -interest_top_n = 1000 # 每个维度的推荐商品数  
250 -```  
251 -  
252 -## 📈 性能参考  
253 -  
254 -基于100万条用户行为数据的预估:  
255 -  
256 -| 任务 | 预估时间 | 内存占用 | 输出大小 |  
257 -|------|---------|---------|---------|  
258 -| Swing算法 | 2-4小时 | 4-8GB | ~50MB |  
259 -| Session W2V | 30-60分钟 | 2-4GB | ~30MB |  
260 -| DeepWalk | 1-2小时 | 2-4GB | ~40MB |  
261 -| 兴趣点聚合 | 30-60分钟 | 2-4GB | ~100MB |  
262 -| **总计** | **5-8小时** | **8-16GB** | **~220MB** |  
263 -  
264 -## 🔧 定时任务设置  
265 -  
266 -建议使用crontab设置每天运行:  
267 -  
268 -```bash  
269 -# 编辑crontab  
270 -crontab -e  
271 -  
272 -# 添加以下行(每天凌晨2点运行)  
273 -0 2 * * * cd /home/tw/recommendation/offline_tasks && /usr/bin/python3 run_all.py >> logs/cron.log 2>&1  
274 -  
275 -# 凌晨6点加载到Redis  
276 -0 6 * * * cd /home/tw/recommendation/offline_tasks && /usr/bin/python3 scripts/load_index_to_redis.py >> logs/load_redis.log 2>&1  
277 -```  
278 -  
279 -## 🐛 常见问题  
280 -  
281 -### Q1: 数据库连接失败  
282 -**解决方案**:  
283 -1. 检查 `config/offline_config.py` 中的数据库配置  
284 -2. 运行 `python3 test_connection.py` 测试连接  
285 -3. 确认网络连接和防火墙设置  
286 -  
287 -### Q2: 任务运行时间过长  
288 -**解决方案**:  
289 -1. 减少 `--lookback_days` 参数(如改为365天)  
290 -2. 使用 `--only-xxx` 参数只运行特定任务  
291 -3. 考虑使用C++版本的Swing算法(性能提升10倍)  
292 -  
293 -### Q3: 内存不足  
294 -**解决方案**:  
295 -1. 先运行DeepWalk或Session W2V(内存占用较小)  
296 -2. 使用 `--skip-i2i` 跳过Swing算法  
297 -3. 分批处理数据  
298 -  
299 -## 📚 参考文档  
300 -  
301 -- **README.md**: 完整的功能说明和使用指南  
302 -- **QUICKSTART.md**: 快速上手步骤  
303 -- **PROJECT_SUMMARY.md**: 技术架构和算法原理  
304 -- **STRUCTURE.md**: 项目结构和数据流向  
305 -  
306 -## ✨ 技术亮点  
307 -  
308 -1. **适配真实数据**:参考 item_sim.py,完全适配现有数据库结构  
309 -2. **多算法支持**:实现了3种主流i2i算法,可以融合使用  
310 -3. **多维度聚合**:支持单维度和组合维度,灵活满足不同场景  
311 -4. **时间衰减**:考虑时间因素,近期行为权重更高  
312 -5. **行为加权**:不同行为类型赋予不同权重,购买权重最高  
313 -6. **统一调度**:一键运行所有任务,自动化程度高  
314 -7. **配置灵活**:所有参数可配置,便于调优  
315 -8. **文档完善**:提供了完整的使用文档和示例代码  
316 -  
317 -## 🎉 交付状态  
318 -  
319 -**状态**: ✅ 已完成  
320 -  
321 -所有功能已实现并测试通过,可以直接使用。建议先在测试环境运行验证,确认无误后再部署到生产环境。  
322 -  
323 -## 📞 后续支持  
324 -  
325 -如有问题,请查看:  
326 -1. 日志文件:`logs/` 目录下的日志  
327 -2. 文档:各个 `.md` 文档  
328 -3. 示例代码:`example_query_redis.py`  
329 -  
330 ----  
331 -  
332 -**交付日期**: 2025-10-16  
333 -**版本**: v1.0  
334 -**状态**: 已完成 ✅  
335 -  
offline_tasks/FIELD_MAPPING.md deleted
@@ -1,172 +0,0 @@ @@ -1,172 +0,0 @@
1 -# 数据库字段映射说明  
2 -  
3 -## 实际表结构  
4 -  
5 -根据检查结果,实际的表结构如下:  
6 -  
7 -### sensors_events 表(用户行为事件表)  
8 -  
9 -| 代码中使用的字段 | 实际字段名 | 说明 |  
10 -|----------------|-----------|------|  
11 -| `user_id` | `anonymous_id` | 匿名用户ID |  
12 -| `item_id` | `item_id` | 商品ID |  
13 -| `event_type` | `event` | 事件类型 |  
14 -| `create_time` | `create_time` | 创建时间 |  
15 -| `platform` | `business_platform` | 业务平台 |  
16 -| `client_platform` | `client_platform` | 客户端平台 |  
17 -  
18 -**不存在的字段**:  
19 -- ❌ `country` - 国家字段(原计划支持,但表中不存在)  
20 -- ❌ `customer_type` - 客户类型字段(原计划支持,但表中不存在)  
21 -  
22 -**其他可用字段**:  
23 -- `ip` - IP地址  
24 -- `item_type` - 商品类型  
25 -- `location_src` - 位置来源  
26 -- `search_content` - 搜索内容  
27 -- `page_type` - 页面类型  
28 -- `session_id` - 会话ID  
29 -  
30 -### prd_goods_sku 表(商品SKU表)  
31 -  
32 -| 代码中使用的字段 | 实际字段名 | 说明 |  
33 -|----------------|-----------|------|  
34 -| `item_id` | `id` | 商品ID |  
35 -| `item_name` | `name` | 商品名称 |  
36 -| `item_create_time` | `create_time` | 商品创建时间 |  
37 -  
38 -**不存在的字段**:  
39 -- ❌ `category_level2_id` - 二级分类ID  
40 -- ❌ `category_level3_id` - 三级分类ID  
41 -  
42 -**其他可用字段**:  
43 -- `goods_id` - 关联商品主表ID  
44 -- `buyer_id` - 买家ID  
45 -- `factory_no` - 工厂编号  
46 -- `package_type_name` - 包装类型名称  
47 -- `on_sell_time` - 上架时间  
48 -- `price_base` - 基础价格  
49 -  
50 -## 当前支持的维度  
51 -  
52 -基于实际表结构,当前代码支持以下维度:  
53 -  
54 -### 单维度  
55 -1. ✅ `platform` - 业务平台(business_platform)  
56 -2. ✅ `client_platform` - 客户端平台  
57 -3. ❌ `country` - 国家(字段不存在)  
58 -4. ❌ `customer_type` - 客户类型(字段不存在)  
59 -5. ❌ `category_level2` - 二级分类(字段不存在)  
60 -6. ❌ `category_level3` - 三级分类(字段不存在)  
61 -  
62 -### 组合维度  
63 -1. ✅ `platform_client` - 业务平台 + 客户端平台  
64 -  
65 -### 列表类型  
66 -1. ✅ `hot` - 热门商品  
67 -2. ✅ `cart` - 加购商品  
68 -3. ✅ `new` - 新品  
69 -  
70 -## 如何扩展更多维度  
71 -  
72 -### 方案1: 使用现有字段  
73 -  
74 -可以考虑使用表中已有的其他字段来扩展维度:  
75 -  
76 -```python  
77 -# 在 interest_aggregation.py 的 SQL 查询中添加  
78 -sql_query = f"""  
79 -SELECT  
80 - ...  
81 - se.page_type, # 页面类型  
82 - se.item_type, # 商品类型  
83 - pgs.package_type_name, # 包装类型  
84 - ...  
85 -"""  
86 -  
87 -# 在聚合函数中添加新维度  
88 -if pd.notna(row.get('page_type')):  
89 - key = f"page_type:{row['page_type']}"  
90 - aggregations[key][item_id] += weight  
91 -  
92 -if pd.notna(row.get('item_type')):  
93 - key = f"item_type:{row['item_type']}"  
94 - aggregations[key][item_id] += weight  
95 -```  
96 -  
97 -### 方案2: 关联其他表获取分类信息  
98 -  
99 -如果分类信息在其他表中,可以通过 JOIN 获取:  
100 -  
101 -```python  
102 -sql_query = f"""  
103 -SELECT  
104 - se.anonymous_id AS user_id,  
105 - se.item_id,  
106 - ...  
107 - gc.category_level2_id,  
108 - gc.category_level3_id  
109 -FROM  
110 - sensors_events se  
111 -LEFT JOIN prd_goods_sku pgs ON se.item_id = pgs.id  
112 -LEFT JOIN goods_category gc ON pgs.goods_id = gc.goods_id # 假设有这个表  
113 -...  
114 -"""  
115 -```  
116 -  
117 -### 方案3: 从 JSON 字段提取  
118 -  
119 -如果 `__properties` 字段包含额外信息,可以解析JSON:  
120 -  
121 -```python  
122 -# 在查询中  
123 -sql_query = f"""  
124 -SELECT  
125 - ...  
126 - se.__properties as properties_json  
127 -...  
128 -"""  
129 -  
130 -# 在处理时  
131 -import json  
132 -props = json.loads(row.get('properties_json', '{}'))  
133 -if 'country' in props:  
134 - key = f"country:{props['country']}"  
135 - aggregations[key][item_id] += weight  
136 -```  
137 -  
138 -## 推荐的实际使用维度  
139 -  
140 -基于现有字段,建议使用以下维度组合:  
141 -  
142 -1. **业务平台维度** - `platform:{business_platform}`  
143 - - 示例:platform:pc, platform:mobile  
144 -  
145 -2. **客户端平台维度** - `client_platform:{client_platform}`  
146 - - 示例:client_platform:web, client_platform:app  
147 -  
148 -3. **页面类型维度** - `page_type:{page_type}` (需添加)  
149 - - 示例:page_type:detail, page_type:list  
150 -  
151 -4. **商品类型维度** - `item_type:{item_type}` (需添加)  
152 - - 示例:item_type:normal, item_type:special  
153 -  
154 -## 更新后的输出示例  
155 -  
156 -```  
157 -# 实际可用的索引键  
158 -platform:pc → 12345:98.5,23456:87.3,...  
159 -platform:mobile → 34567:76.2,45678:65.1,...  
160 -client_platform:web → 56789:54.3,67890:43.2,...  
161 -client_platform:app → 78901:32.1,89012:21.0,...  
162 -platform_client:pc_web → 90123:123.4,01234:112.3,...  
163 -```  
164 -  
165 -## 总结  
166 -  
167 -1. **已实现**: 基于 `business_platform` 和 `client_platform` 的索引  
168 -2. **未实现**: country、customer_type、分类相关索引(因字段不存在)  
169 -3. **可扩展**: page_type、item_type 等其他维度  
170 -  
171 -如需支持更多维度,请参考上述方案进行扩展。  
172 -  
offline_tasks/FINAL_SUMMARY.md deleted
@@ -1,269 +0,0 @@ @@ -1,269 +0,0 @@
1 -# 内容相似索引重构 - 最终总结  
2 -  
3 -## ✅ 已完成的工作  
4 -  
5 -### 1. 核心功能实现  
6 -  
7 -#### 重写 `i2i_content_similar.py`  
8 -- ✅ 从数据库属性计算 → ES向量计算  
9 -- ✅ 生成两份索引:名称向量 + 图片向量  
10 -- ✅ 移除所有命令行参数,配置内置  
11 -- ✅ **加入 `on_sell_days_boost` 提权** ⭐新增  
12 - - 取值范围:0.9~1.1  
13 - - 自动应用到所有相似度分数  
14 - - 异常值保护,默认1.0  
15 -  
16 -#### 提权逻辑  
17 -```python  
18 -# KNN查询获取基础分数  
19 -base_score = knn_result['_score']  
20 -  
21 -# 获取上架天数提权值  
22 -boost = knn_result['_source']['on_sell_days_boost'] # 0.9~1.1  
23 -  
24 -# 应用提权  
25 -final_score = base_score * boost  
26 -```  
27 -  
28 -### 2. 简化运行脚本  
29 -  
30 -#### `run_all.py` 参数简化  
31 -- ❌ 移除:`--skip-i2i`, `--skip-interest`, `--only-*`, `--lookback_days`, `--top_n`  
32 -- ✅ 保留:`--debug` (唯一参数)  
33 -- ✅ 添加:内容相似任务  
34 -  
35 -#### 使用方式  
36 -```bash  
37 -# 之前(复杂)  
38 -python run_all.py --lookback_days 30 --top_n 50 --skip-interest --only-content  
39 -  
40 -# 现在(简单)  
41 -python run_all.py  
42 -```  
43 -  
44 -### 3. 更新配置和文档  
45 -  
46 -#### 修改的文件  
47 -1. ✅ `offline_tasks/scripts/i2i_content_similar.py` - 完全重写,加入提权  
48 -2. ✅ `offline_tasks/run_all.py` - 简化参数  
49 -3. ✅ `offline_tasks/REDIS_DATA_SPEC.md` - 新增2个索引规范  
50 -4. ✅ `offline_tasks/scripts/load_index_to_redis.py` - 支持新索引  
51 -5. ✅ `requirements.txt` - 添加elasticsearch依赖  
52 -  
53 -#### 新增的文件  
54 -6. ✅ `offline_tasks/scripts/ES_VECTOR_SIMILARITY.md` - 技术文档  
55 -7. ✅ `offline_tasks/scripts/test_es_connection.py` - 测试工具  
56 -8. ✅ `offline_tasks/CONTENT_SIMILARITY_UPDATE.md` - 更新说明  
57 -9. ✅ `offline_tasks/CHANGES_SUMMARY.md` - 变更总结  
58 -10. ✅ `offline_tasks/QUICKSTART_NEW.md` - 快速开始  
59 -11. ✅ `offline_tasks/FINAL_SUMMARY.md` - 本文档  
60 -  
61 -### 4. 测试工具增强  
62 -  
63 -#### `test_es_connection.py` 功能  
64 -- ✅ 测试ES连接  
65 -- ✅ 测试索引存在  
66 -- ✅ 测试字段映射(包含 `on_sell_days_boost`)  
67 -- ✅ 测试向量查询  
68 -- ✅ 测试KNN查询  
69 -- ✅ **显示提权计算过程** ⭐新增  
70 - ```  
71 - 基础分数: 0.8523, 提权: 1.05, 最终分数: 0.8949  
72 - ```  
73 -  
74 -## 📊 生成的索引  
75 -  
76 -### 索引文件  
77 -| 文件名 | 向量类型 | Redis Key | 提权 | TTL |  
78 -|-------|---------|-----------|------|-----|  
79 -| `i2i_content_name_YYYYMMDD.txt` | 名称向量 | `item:similar:content_name:{id}` | ✅ | 30天 |  
80 -| `i2i_content_pic_YYYYMMDD.txt` | 图片向量 | `item:similar:content_pic:{id}` | ✅ | 30天 |  
81 -  
82 -### 文件格式  
83 -```  
84 -item_id \t item_name \t similar_id1:boosted_score1,similar_id2:boosted_score2,...  
85 -```  
86 -  
87 -### 示例(分数已包含提权)  
88 -```  
89 -3302275 香蕉干 3302276:0.9686,3302277:0.9182,3302278:0.8849  
90 - ↑ 已应用on_sell_days_boost提权  
91 -```  
92 -  
93 -## 🔍 技术细节  
94 -  
95 -### ES查询字段  
96 -```python  
97 -_source = [  
98 - "_id", # 商品ID  
99 - "name_zh", # 中文名称  
100 - "on_sell_days_boost" # 提权值 ⭐  
101 -]  
102 -```  
103 -  
104 -### 提权处理  
105 -```python  
106 -# 1. 获取提权值  
107 -boost = hit['_source'].get('on_sell_days_boost', 1.0)  
108 -  
109 -# 2. 范围验证(0.9~1.1)  
110 -if boost is None or boost < 0.9 or boost > 1.1:  
111 - boost = 1.0 # 异常值使用默认值  
112 -  
113 -# 3. 应用提权  
114 -final_score = base_score * boost  
115 -```  
116 -  
117 -### 提权说明  
118 -- **> 1.0**: 提权(新品、热门商品)  
119 -- **= 1.0**: 不提权(正常商品)  
120 -- **< 1.0**: 降权(长尾商品)  
121 -  
122 -## 🚀 使用指南  
123 -  
124 -### 1. 安装依赖  
125 -```bash  
126 -pip install -r requirements.txt  
127 -# 新增: elasticsearch>=8.0.0  
128 -```  
129 -  
130 -### 2. 测试ES连接(含提权测试)  
131 -```bash  
132 -python scripts/test_es_connection.py  
133 -```  
134 -  
135 -输出示例:  
136 -```  
137 -✓ 找到商品 3302275  
138 - 名称: 香蕉干  
139 - 上架天数提权: 1.05  
140 -  
141 -✓ 名称向量KNN查询成功  
142 - 1. ID: 3302276, 名称: 香蕉片  
143 - 基础分数: 0.9220, 提权: 1.05, 最终分数: 0.9681  
144 - 2. ID: 3302277, 名称: 芒果干  
145 - 基础分数: 0.8746, 提权: 1.05, 最终分数: 0.9183  
146 -```  
147 -  
148 -### 3. 运行生成  
149 -```bash  
150 -# 单独运行  
151 -python scripts/i2i_content_similar.py  
152 -  
153 -# 或全部运行  
154 -python run_all.py  
155 -```  
156 -  
157 -### 4. 加载到Redis  
158 -```bash  
159 -python scripts/load_index_to_redis.py  
160 -```  
161 -  
162 -### 5. 查询使用  
163 -```python  
164 -import redis  
165 -import json  
166 -  
167 -r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)  
168 -  
169 -# 获取名称向量相似(分数已含提权)  
170 -similar = json.loads(r.get('item:similar:content_name:3302275'))  
171 -# 返回: [[3302276, 0.9686], [3302277, 0.9182], ...]  
172 -# ↑ 分数已应用on_sell_days_boost  
173 -  
174 -# 获取图片向量相似(分数已含提权)  
175 -similar = json.loads(r.get('item:similar:content_pic:3302275'))  
176 -# 返回: [[4503826, 0.8523], [4503827, 0.8245], ...]  
177 -# ↑ 分数已应用on_sell_days_boost  
178 -```  
179 -  
180 -## 🎯 核心改进  
181 -  
182 -### 1. 简化使用  
183 -- **无参数**: `i2i_content_similar.py` 无需任何参数  
184 -- **无选择**: `run_all.py` 自动运行所有任务  
185 -- **易维护**: 配置集中在代码中  
186 -  
187 -### 2. 更强大  
188 -- **深度学习**: 基于ES向量,比TF-IDF更准确  
189 -- **多维度**: 名称 + 图片两个维度  
190 -- **智能提权**: 自动应用上架天数提权 ⭐  
191 -- **更快**: ES KNN查询性能优秀  
192 -  
193 -### 3. 提权优势  
194 -- **动态调整**: 根据商品上架天数动态提权  
195 -- **平滑过渡**: 0.9~1.1小范围提权,避免剧烈变化  
196 -- **异常保护**: 自动处理缺失或异常值  
197 -- **透明计算**: 测试工具显示提权过程  
198 -  
199 -## 📈 性能指标  
200 -  
201 -| 指标 | 值 |  
202 -|-----|---|  
203 -| 活跃商品数 | ~50,000 |  
204 -| 运行时间 | 50-60分钟 |  
205 -| Redis Keys | +100,000 |  
206 -| Redis内存 | +50MB |  
207 -| 提权开销 | 可忽略(简单乘法) |  
208 -  
209 -## ⚠️ 重要说明  
210 -  
211 -### 提权应用  
212 -- ✅ 所有相似度分数都已应用提权  
213 -- ✅ 输出文件中的分数是最终分数  
214 -- ✅ Redis中存储的分数是最终分数  
215 -- ✅ 无需在应用层再次应用提权  
216 -  
217 -### 向后兼容  
218 -- ✅ 其他i2i算法不受影响  
219 -- ✅ Redis加载器向后兼容  
220 -- ❌ 命令行参数全部改变  
221 -- ❌ Redis Key格式改变  
222 -  
223 -### 迁移建议  
224 -1. 更新API调用,使用新的Redis Key  
225 -2. 无需修改分数处理逻辑(已含提权)  
226 -3. 建议同时支持两种向量算法  
227 -  
228 -## 📚 文档导航  
229 -  
230 -| 文档 | 说明 |  
231 -|------|------|  
232 -| `QUICKSTART_NEW.md` | 5分钟快速开始 |  
233 -| `ES_VECTOR_SIMILARITY.md` | ES向量技术详解 |  
234 -| `CONTENT_SIMILARITY_UPDATE.md` | 完整更新说明 |  
235 -| `CHANGES_SUMMARY.md` | 所有变更总结 |  
236 -| `FINAL_SUMMARY.md` | 本文档 |  
237 -  
238 -## 🎉 总结  
239 -  
240 -本次重构实现了三大目标:  
241 -  
242 -1. **简化使用** ✅  
243 - - 移除复杂参数  
244 - - 一键运行所有任务  
245 -  
246 -2. **提升能力** ✅  
247 - - 深度学习向量  
248 - - 多维度相似度  
249 - - 智能上架天数提权 ⭐  
250 -  
251 -3. **易于维护** ✅  
252 - - 代码清晰简洁  
253 - - 文档完整详细  
254 - - 测试工具完善  
255 -  
256 -### 关键特性  
257 -  
258 -- **🚀 无参数运行**: `python scripts/i2i_content_similar.py`  
259 -- **🎯 智能提权**: 自动应用 `on_sell_days_boost` (0.9~1.1)  
260 -- **🔍 双向量**: 名称语义 + 图片视觉  
261 -- **📊 高性能**: ES KNN查询快速准确  
262 -- **🛡️ 异常保护**: 提权值验证和默认值处理  
263 -  
264 ----  
265 -  
266 -**重构完成时间**: 2025-10-17  
267 -**影响范围**: 内容相似索引生成和使用  
268 -**状态**: ✅ 已完成,可投入使用  
269 -  
offline_tasks/FINAL_UPDATE.md deleted
@@ -1,301 +0,0 @@ @@ -1,301 +0,0 @@
1 -# 最终更新说明  
2 -  
3 -## 📅 更新日期:2025-10-16  
4 -  
5 -## ✅ 已完成的功能(完整版)  
6 -  
7 -### 1. i2i 相似度索引(4种算法)  
8 -  
9 -#### 1.1 行为相似(3种)  
10 -基于用户行为计算商品相似度:  
11 -  
12 -| 算法 | 文件 | 特点 | 状态 |  
13 -|------|------|------|------|  
14 -| **Swing** | `i2i_swing.py` | 基于用户共同行为,效果最好 | ✅ 已完成 |  
15 -| **Session W2V** | `i2i_session_w2v.py` | 基于会话序列,捕获序列关系 | ✅ 已完成 |  
16 -| **DeepWalk** | `i2i_deepwalk.py` | 基于图游走,发现深层关系 | ✅ 已完成 |  
17 -  
18 -#### 1.2 内容相似(新增)  
19 -基于商品属性计算商品相似度:  
20 -  
21 -| 算法 | 文件 | 特点 | 状态 |  
22 -|------|------|------|------|  
23 -| **Content-based** | `i2i_content_similar.py` | 基于分类、供应商、属性等 | ✅ 新增完成 |  
24 -  
25 -**支持的方法**:  
26 -- `tfidf` - 基于TF-IDF的文本相似度  
27 -- `category` - 基于分类的相似度  
28 -- `hybrid` - 混合方法(推荐)  
29 -  
30 -**使用的特征**:  
31 -- 商品分类(一级到四级)  
32 -- 供应商信息  
33 -- 包装类型和包装方式  
34 -- 商品名称关键词  
35 -  
36 -**运行命令**:  
37 -```bash  
38 -# 使用混合方法(推荐)  
39 -python3 scripts/i2i_content_similar.py --top_n 50 --method hybrid  
40 -  
41 -# 只使用TF-IDF  
42 -python3 scripts/i2i_content_similar.py --top_n 50 --method tfidf  
43 -  
44 -# 只使用分类  
45 -python3 scripts/i2i_content_similar.py --top_n 50 --method category  
46 -```  
47 -  
48 ----  
49 -  
50 -### 2. 兴趣点聚合索引(已完善)  
51 -  
52 -#### 支持的维度(从2个扩展到7个)  
53 -  
54 -**单维度**:  
55 -1. ✅ `platform` - 业务平台  
56 -2. ✅ `client_platform` - 客户端平台  
57 -3. ✅ `supplier` - 供应商  
58 -4. ✅ `category_level1` - 一级分类  
59 -5. ✅ `category_level2` - 二级分类  
60 -6. ✅ `category_level3` - 三级分类  
61 -7. ✅ `category_level4` - 四级分类  
62 -  
63 -**组合维度**:  
64 -1. ✅ `platform_client` - 业务平台 + 客户端平台  
65 -2. ✅ `platform_category2` - 平台 + 二级分类  
66 -3. ✅ `platform_category3` - 平台 + 三级分类  
67 -4. ✅ `client_category2` - 客户端平台 + 二级分类  
68 -  
69 -**列表类型**:  
70 -1. ✅ `hot` - 热门商品  
71 -2. ✅ `cart` - 加购商品  
72 -3. ✅ `new` - 新品  
73 -  
74 ----  
75 -  
76 -## 🎯 完整的索引输出  
77 -  
78 -### i2i索引(4种)  
79 -```  
80 -# 行为相似  
81 -i2i:swing:{item_id}  
82 -i2i:session_w2v:{item_id}  
83 -i2i:deepwalk:{item_id}  
84 -  
85 -# 内容相似(新增)  
86 -i2i:content_hybrid:{item_id}  
87 -i2i:content_tfidf:{item_id}  
88 -i2i:content_category:{item_id}  
89 -```  
90 -  
91 -### 兴趣点聚合索引(大幅扩展)  
92 -  
93 -**单维度示例**:  
94 -```  
95 -interest:hot:platform:pc  
96 -interest:hot:client_platform:web  
97 -interest:hot:supplier:10001  
98 -interest:hot:category_level1:100  
99 -interest:hot:category_level2:200  
100 -interest:hot:category_level3:300  
101 -interest:hot:category_level4:400  
102 -```  
103 -  
104 -**组合维度示例**:  
105 -```  
106 -interest:hot:platform_client:pc_web  
107 -interest:hot:platform_category2:pc_200  
108 -interest:hot:platform_category3:mobile_300  
109 -interest:hot:client_category2:web_200  
110 -```  
111 -  
112 -**列表类型示例**:  
113 -```  
114 -interest:hot:category_level2:200  
115 -interest:cart:category_level3:300  
116 -interest:new:supplier:10001  
117 -interest:global:platform_category2:pc_200  
118 -```  
119 -  
120 ----  
121 -  
122 -## 📊 业务场景应用(更新)  
123 -  
124 -### 场景1: 首页猜你喜欢  
125 -```python  
126 -# 1. 基于平台推荐  
127 -items_1 = redis.get("interest:hot:platform:pc")  
128 -  
129 -# 2. 基于用户常购分类推荐  
130 -items_2 = redis.get("interest:hot:category_level2:200")  
131 -  
132 -# 3. 基于平台+分类组合  
133 -items_3 = redis.get("interest:hot:platform_category2:pc_200")  
134 -  
135 -# 融合多个维度  
136 -recommended = merge_and_personalize(items_1, items_2, items_3)  
137 -```  
138 -  
139 -### 场景2: 详情页大家都在看  
140 -```python  
141 -item_id = "12345"  
142 -  
143 -# 1. 行为相似(用户行为)  
144 -similar_behavior = redis.get(f"i2i:swing:{item_id}")  
145 -  
146 -# 2. 内容相似(商品属性)  
147 -similar_content = redis.get(f"i2i:content_hybrid:{item_id}")  
148 -  
149 -# 3. 融合推荐  
150 -recommended = merge_i2i(similar_behavior, similar_content, weight1=0.6, weight2=0.4)  
151 -```  
152 -  
153 -### 场景3: 分类页推荐  
154 -```python  
155 -category_id = "200"  
156 -  
157 -# 1. 该分类的热门商品  
158 -hot_items = redis.get(f"interest:hot:category_level2:{category_id}")  
159 -  
160 -# 2. 该分类的新品  
161 -new_items = redis.get(f"interest:new:category_level2:{category_id}")  
162 -  
163 -# 3. 组合展示  
164 -display(hot_items, new_items)  
165 -```  
166 -  
167 -### 场景4: 供应商页推荐  
168 -```python  
169 -supplier_id = "10001"  
170 -  
171 -# 该供应商的热门商品  
172 -hot_items = redis.get(f"interest:hot:supplier:{supplier_id}")  
173 -```  
174 -  
175 ----  
176 -  
177 -## 🚀 运行所有任务  
178 -  
179 -```bash  
180 -cd /home/tw/recommendation/offline_tasks  
181 -  
182 -# 运行全部任务(包括新增的内容相似)  
183 -python3 run_all.py --lookback_days 730 --top_n 50  
184 -  
185 -# 只运行内容相似  
186 -python3 run_all.py --only-content --top_n 50  
187 -  
188 -# 跳过内容相似,只运行其他  
189 -python3 run_all.py --skip-content --lookback_days 730 --top_n 50  
190 -```  
191 -  
192 ----  
193 -  
194 -## 📈 性能参考(更新)  
195 -  
196 -| 任务 | 数据依赖 | 预估时间 | 内存占用 |  
197 -|------|---------|---------|---------|  
198 -| Swing | 用户行为(730天) | 2-4小时 | 4-8GB |  
199 -| Session W2V | 用户行为(730天) | 30-60分钟 | 2-4GB |  
200 -| DeepWalk | 用户行为(730天) | 1-2小时 | 2-4GB |  
201 -| **Content-based** | **商品属性(全量)** | **10-30分钟** | **2-4GB** |  
202 -| 兴趣点聚合 | 用户行为(730天) | 30-60分钟 | 2-4GB |  
203 -  
204 -**总计**:约6-10小时  
205 -  
206 ----  
207 -  
208 -## 📝 数据表依赖关系  
209 -  
210 -### i2i 行为相似  
211 -- `sensors_events` - 用户行为事件  
212 -- `prd_goods_sku` - 商品SKU信息  
213 -  
214 -### i2i 内容相似(新增)  
215 -- `prd_goods_sku` - 商品SKU信息  
216 -- `prd_goods` - 商品主表  
217 -- `sup_supplier` - 供应商信息  
218 -- `prd_category` - 分类信息(层级结构)  
219 -- `prd_goods_sku_attribute` - 商品属性  
220 -- `prd_option` - 属性选项  
221 -- `prd_attribute` - 属性定义  
222 -  
223 -### 兴趣点聚合(已完善)  
224 -- `sensors_events` - 用户行为事件  
225 -- `prd_goods_sku` - 商品SKU信息  
226 -- `prd_goods` - 商品主表  
227 -- `prd_category` - 分类信息(新增)  
228 -  
229 ----  
230 -  
231 -## 🔄 与原有代码的对比  
232 -  
233 -### 原计划维度(文档中)  
234 -- ❌ 国家/销售区域(字段不存在)  
235 -- ❌ 客户类型(字段不存在)  
236 -- ⚠️ 二级分类(原以为不存在,现已支持)  
237 -- ⚠️ 三级分类(原以为不存在,现已支持)  
238 -  
239 -### 实际实现维度(完善后)  
240 -- ✅ 业务平台  
241 -- ✅ 客户端平台  
242 -- ✅ 供应商(新增)  
243 -- ✅ 一级分类(新增)  
244 -- ✅ 二级分类(新增支持)  
245 -- ✅ 三级分类(新增支持)  
246 -- ✅ 四级分类(新增)  
247 -  
248 ----  
249 -  
250 -## 💡 优势总结  
251 -  
252 -### 1. 内容相似的优势  
253 -- ✅ **冷启动友好**:新商品立即可用  
254 -- ✅ **不依赖行为数据**:商品上架即可生成相似推荐  
255 -- ✅ **可解释性强**:基于分类、属性等明确特征  
256 -- ✅ **计算快速**:只需要商品属性数据  
257 -  
258 -### 2. 多维度聚合的优势  
259 -- ✅ **分类粒度丰富**:支持4级分类  
260 -- ✅ **供应商维度**:支持供应商页推荐  
261 -- ✅ **组合查询**:支持平台+分类等组合维度  
262 -- ✅ **灵活性高**:可根据需要查询不同粒度  
263 -  
264 -### 3. 算法融合的优势  
265 -- ✅ **行为 + 内容**:可以融合4种i2i算法  
266 -- ✅ **短期 + 长期**:热门、新品等不同时效性  
267 -- ✅ **粗粒度 + 细粒度**:一级到四级分类  
268 -  
269 ----  
270 -  
271 -## 🎉 完成状态  
272 -  
273 -**✅ 全部完成!**  
274 -  
275 -1. ✅ i2i 行为相似(3种算法)  
276 -2. ✅ i2i 内容相似(1种算法,3种方法)  
277 -3. ✅ 兴趣点聚合(7个单维度 + 4个组合维度 + 3种列表类型)  
278 -4. ✅ 统一调度脚本  
279 -5. ✅ Redis加载工具  
280 -6. ✅ 完整文档  
281 -  
282 ----  
283 -  
284 -## 📚 相关文档  
285 -  
286 -- **CURRENT_STATUS.md** - 当前功能状态  
287 -- **FIELD_MAPPING.md** - 字段映射说明  
288 -- **DATABASE_SETUP.md** - 数据库配置  
289 -- **TROUBLESHOOTING.md** - 故障排除  
290 -- **README.md** - 完整文档  
291 -  
292 ----  
293 -  
294 -**更新版本**: v1.1  
295 -**更新日期**: 2025-10-16  
296 -**主要变化**:  
297 -- 新增内容相似算法  
298 -- 完善分类维度支持(1-4级)  
299 -- 新增供应商维度  
300 -- 扩展组合维度查询  
301 -  
offline_tasks/FIX_NAME_MAPPING.md deleted
@@ -1,186 +0,0 @@ @@ -1,186 +0,0 @@
1 -# 商品名称映射问题修复  
2 -  
3 -## 问题描述  
4 -  
5 -在Debug模式生成的明文文件中,商品名称显示为"Unknown":  
6 -  
7 -```  
8 -[7] i2i:swing:3667845  
9 ---------------------------------------------------------------------------------  
10 - 1. ID:3588590(Unknown) - Score:0.2857  
11 - 2. ID:3623446(Unknown) - Score:...  
12 -```  
13 -  
14 -## 根本原因  
15 -  
16 -数据类型不匹配导致名称映射失败:  
17 -  
18 -1. **fetch_name_mappings()** 从数据库获取的映射,key是**字符串类型**:  
19 - ```python  
20 - mappings['item'] = dict(zip(df['id'].astype(str), df['name']))  
21 - # 结果: {'12345': '香蕉干', '67890': '芒果干', ...}  
22 - ```  
23 -  
24 -2. **item_name_map** 从DataFrame创建的映射,key是**整数类型**:  
25 - ```python  
26 - item_name_map = dict(zip(df['item_id'].unique(), ...))  
27 - # 结果: {12345: '香蕉干', 67890: '芒果干', ...}  
28 - ```  
29 -  
30 -3. **更新操作失败**:  
31 - ```python  
32 - name_mappings['item'].update(item_name_map)  
33 - # int类型的key和str类型的key不匹配,实际上没有更新成功  
34 - ```  
35 -  
36 -4. **查询时找不到**:  
37 - ```python  
38 - name = name_mappings.get('item', {}).get(str(item_id), 'Unknown')  
39 - # 将int的item_id转为str查询,但dict中只有int类型的key,所以返回'Unknown'  
40 - ```  
41 -  
42 -## 修复方案  
43 -  
44 -### 方法1:统一转为字符串(已采用)  
45 -  
46 -```python  
47 -# 修改前  
48 -item_name_map = dict(zip(df['item_id'].unique(), df.groupby('item_id')['item_name'].first()))  
49 -  
50 -# 修改后(key转为字符串)  
51 -item_name_map = dict(zip(df['item_id'].unique().astype(str), df.groupby('item_id')['item_name'].first()))  
52 -```  
53 -  
54 -### 方法2:update时转换(备选)  
55 -  
56 -```python  
57 -# 转换key类型后再更新  
58 -name_mappings['item'].update({str(k): v for k, v in item_name_map.items()})  
59 -```  
60 -  
61 -## 验证修复  
62 -  
63 -修复后运行debug模式:  
64 -  
65 -```bash  
66 -cd /home/tw/recommendation/offline_tasks  
67 -python3 scripts/i2i_swing.py --lookback_days 7 --top_n 10 --debug  
68 -```  
69 -  
70 -检查明文文件:  
71 -  
72 -```bash  
73 -more output/debug/i2i_swing_*_readable.txt  
74 -```  
75 -  
76 -应该看到:  
77 -  
78 -```  
79 -[7] i2i:swing:3667845(商品名称)  
80 ---------------------------------------------------------------------------------  
81 - 1. ID:3588590(香蕉干) - Score:0.2857  
82 - 2. ID:3623446(芒果干) - Score:0.2143  
83 -```  
84 -  
85 -## 数据库字段确认  
86 -  
87 -正确的查询关系:  
88 -  
89 -```sql  
90 -SELECT  
91 - pgs.id as 'sku_id',  
92 - pgs.name as '商品名称',  
93 - ss.name as '供应商名称',  
94 - pc_1.name as '一级类目',  
95 - pc_2.name as '二级类目'  
96 -FROM prd_goods_sku pgs  
97 -LEFT JOIN sup_supplier ss ON pgs.supplier_id = ss.id  
98 -LEFT JOIN prd_category pc_1 ON ...  
99 -```  
100 -  
101 -## 其他脚本  
102 -  
103 -这个问题也可能存在于其他脚本,需要同样修复:  
104 -- ✅ i2i_swing.py (已修复)  
105 -- ⚠️ i2i_session_w2v.py (如果有debug功能需要检查)  
106 -- ⚠️ i2i_deepwalk.py (如果有debug功能需要检查)  
107 -- ⚠️ i2i_content_similar.py (如果有debug功能需要检查)  
108 -- ⚠️ interest_aggregation.py (如果有debug功能需要检查)  
109 -  
110 -## 预防措施  
111 -  
112 -为避免类似问题,建议:  
113 -  
114 -1. **统一数据类型约定**:  
115 - - 所有ID映射的key统一使用字符串类型  
116 - - 在debug_utils.py中明确文档说明  
117 -  
118 -2. **添加类型检查**:  
119 - ```python  
120 - def safe_update_mapping(target_dict, source_dict):  
121 - """安全更新映射,自动转换key类型"""  
122 - for k, v in source_dict.items():  
123 - target_dict[str(k)] = v  
124 - ```  
125 -  
126 -3. **添加调试日志**:  
127 - ```python  
128 - if debug:  
129 - logger.debug(f"更新前: {len(name_mappings['item'])} 个名称")  
130 - name_mappings['item'].update(item_name_map)  
131 - logger.debug(f"更新后: {len(name_mappings['item'])} 个名称")  
132 - ```  
133 -  
134 ----  
135 -  
136 -**状态**: ✅ 已修复  
137 -**影响范围**: i2i_swing.py  
138 -**修复时间**: 2025-10-16  
139 -  
140 -## 补充修复 - 主输出文件  
141 -  
142 -问题同样存在于主输出文件中:  
143 -  
144 -```  
145 -1070176 Unknown 2786217:0.4000  
146 -2786217 Unknown 1070176:0.4000  
147 -```  
148 -  
149 -### 原因  
150 -  
151 -主输出代码中使用整数item_id作为key查询:  
152 -  
153 -```python  
154 -for item_id, sims in result.items():  
155 - item_name = item_name_map.get(item_id, 'Unknown') # item_id是int,但map的key是str  
156 -```  
157 -  
158 -### 修复  
159 -  
160 -统一转换为字符串:  
161 -  
162 -```python  
163 -for item_id, sims in result.items():  
164 - item_name = item_name_map.get(str(item_id), 'Unknown') # 转换为字符串查询  
165 -```  
166 -  
167 -### 验证  
168 -  
169 -```bash  
170 -# 重新运行  
171 -python3 scripts/i2i_swing.py --lookback_days 7 --top_n 10  
172 -  
173 -# 检查输出  
174 -more output/i2i_swing_20251016.txt  
175 -```  
176 -  
177 -应该看到:  
178 -```  
179 -1070176 商品名称A 2786217:0.4000  
180 -2786217 商品名称B 1070176:0.4000  
181 -```  
182 -  
183 ----  
184 -  
185 -**更新时间**: 2025-10-16 20:30  
186 -**状态**: ✅ 完全修复  
offline_tasks/LATEST_UPDATES.md deleted
@@ -1,155 +0,0 @@ @@ -1,155 +0,0 @@
1 -# 最新更新 (2025-10-17)  
2 -  
3 -## 🎉 本次更新内容  
4 -  
5 -### 1. ✅ ES向量相似度 + on_sell_days_boost提权  
6 -  
7 -#### 功能  
8 -- 基于Elasticsearch向量计算相似度(名称向量 + 图片向量)  
9 -- 自动应用 `on_sell_days_boost` 提权(0.9~1.1)  
10 -- 无需任何命令行参数,开箱即用  
11 -  
12 -#### 使用  
13 -```bash  
14 -python scripts/i2i_content_similar.py  
15 -```  
16 -  
17 -### 2. ✅ 代码规范:统一使用 logger  
18 -  
19 -#### 变更  
20 -- 移除所有 `print` 语句  
21 -- 统一使用 `logger` 记录日志  
22 -- 更好的日志级别控制  
23 -  
24 -### 3. ✅ run.sh 内存监控  
25 -  
26 -#### 功能  
27 -- **25GB警告**: 打印警告日志,继续运行  
28 -- **30GB终止**: 强制kill进程,防止OOM  
29 -- **每10秒检查**: 实时监控内存使用  
30 -- **详细日志**: `logs/memory_monitor.log`  
31 -  
32 -#### 使用  
33 -```bash  
34 -./run.sh  
35 -```  
36 -  
37 -## 📋 快速开始  
38 -  
39 -### 1. 测试ES连接和向量  
40 -```bash  
41 -python scripts/test_es_connection.py  
42 -```  
43 -  
44 -### 2. 测试内存监控  
45 -```bash  
46 -./test_memory_monitor.sh  
47 -```  
48 -  
49 -### 3. 运行所有任务(含监控)  
50 -```bash  
51 -./run.sh  
52 -```  
53 -  
54 -### 4. 查看监控日志  
55 -```bash  
56 -tail -f logs/memory_monitor.log  
57 -```  
58 -  
59 -## 📊 生成的索引  
60 -  
61 -| 索引文件 | Redis Key | 提权 | TTL |  
62 -|---------|-----------|------|-----|  
63 -| `i2i_content_name_YYYYMMDD.txt` | `item:similar:content_name:{id}` | ✅ | 30天 |  
64 -| `i2i_content_pic_YYYYMMDD.txt` | `item:similar:content_pic:{id}` | ✅ | 30天 |  
65 -  
66 -## 📚 文档  
67 -  
68 -| 文档 | 说明 |  
69 -|------|------|  
70 -| `QUICKSTART_NEW.md` | 5分钟快速开始 |  
71 -| `ES_VECTOR_SIMILARITY.md` | ES向量技术详解 |  
72 -| `RUN_SCRIPT_GUIDE.md` | 运行脚本使用指南 |  
73 -| `MEMORY_MONITORING_UPDATE.md` | 内存监控详细说明 |  
74 -| `FINAL_SUMMARY.md` | 完整更新总结 |  
75 -  
76 -## 🔍 关键特性  
77 -  
78 -### ES向量相似度  
79 -```python  
80 -# 自动应用提权  
81 -base_score = knn_result['_score']  
82 -boost = knn_result['on_sell_days_boost'] # 0.9~1.1  
83 -final_score = base_score * boost  
84 -```  
85 -  
86 -### 内存监控  
87 -```bash  
88 -# 自动监控每个任务  
89 -python3 run_all.py &  
90 -PID=$!  
91 -check_memory $PID & # 后台监控  
92 -  
93 -# 日志输出  
94 -[2025-10-17 15:20:15] ⚠️ 内存警告!当前使用: 26.45GB (>= 25GB)  
95 -[2025-10-17 15:24:45] ❌ 内存超限!当前使用: 31.20GB, 强制终止  
96 -```  
97 -  
98 -## ⚠️ 重要说明  
99 -  
100 -### 向量相似度  
101 -- ✅ 分数已包含 `on_sell_days_boost` 提权  
102 -- ✅ 输出到文件和Redis的都是最终分数  
103 -- ✅ 应用层无需再次应用提权  
104 -  
105 -### 内存监控  
106 -- ⚠️ 默认阈值:25GB警告,30GB终止  
107 -- ⚠️ 可在 `run.sh` 中修改阈值  
108 -- ⚠️ 监控日志保存在 `logs/memory_monitor.log`  
109 -  
110 -### run_all.py 简化  
111 -- ❌ 移除了所有 `--only-*`, `--skip-*` 参数  
112 -- ✅ 只保留 `--debug` 参数  
113 -- ✅ 配置集中在 `offline_config.py`  
114 -  
115 -## 🚀 一键运行  
116 -  
117 -```bash  
118 -# 完整流程(含内存监控)  
119 -cd /home/tw/recommendation/offline_tasks  
120 -./run.sh  
121 -  
122 -# 输出:  
123 -# ======================================================================  
124 -# 开始运行离线任务 - 2025-10-17 14:00:00  
125 -# 内存监控: 警告阈值=25GB, 强制终止阈值=30GB  
126 -# ======================================================================  
127 -#  
128 -# >>> 步骤1: 调试模式运行(小数据量)  
129 -# ✓ 调试模式完成  
130 -#  
131 -# >>> 步骤2: 生产模式运行(大数据量)  
132 -# ✓ 生产模式完成  
133 -#  
134 -# >>> 步骤3: 加载到Redis  
135 -# ✓ Redis加载完成  
136 -#  
137 -# ======================================================================  
138 -# 所有任务完成 - 2025-10-17 16:30:00  
139 -# ======================================================================  
140 -```  
141 -  
142 -## 🎯 核心改进  
143 -  
144 -1. **更智能**: ES向量 + 上架天数提权  
145 -2. **更简单**: 无需参数,一键运行  
146 -3. **更安全**: 内存监控保护系统  
147 -4. **更规范**: 统一使用logger  
148 -5. **更完整**: 详细文档和测试工具  
149 -  
150 ----  
151 -  
152 -**更新日期**: 2025-10-17  
153 -**版本**: v2.1  
154 -**状态**: ✅ 已完成,可投入使用  
155 -  
offline_tasks/MEMORY_MONITORING_UPDATE.md deleted
@@ -1,376 +0,0 @@ @@ -1,376 +0,0 @@
1 -# 内存监控功能更新  
2 -  
3 -## 更新日期  
4 -2025-10-17  
5 -  
6 -## 更新内容  
7 -  
8 -### 1. ✅ 代码规范:移除 print,统一使用 logger  
9 -  
10 -#### 检查结果  
11 -- ✅ `i2i_content_similar.py` - 已全部使用 logger  
12 -- ✅ `test_es_connection.py` - print用于测试工具输出(符合预期)  
13 -- ✅ 所有核心代码已使用 logger  
14 -  
15 -### 2. ✅ run.sh 添加内存监控功能  
16 -  
17 -#### 核心功能  
18 -  
19 -**内存监控函数**:  
20 -```bash  
21 -check_memory() {  
22 - local pid=$1  
23 - local threshold_warn=25 # 25GB警告阈值  
24 - local threshold_kill=30 # 30GB强制kill阈值  
25 -  
26 - while kill -0 $pid 2>/dev/null; do  
27 - 获取进程内存使用(MB)  
28 - 转换为GB  
29 -  
30 - if 内存 >= 30GB:  
31 - 打印错误日志到终端和文件  
32 - 强制kill进程  
33 - break  
34 - elif 内存 >= 25GB:  
35 - 打印警告日志到终端和文件  
36 -  
37 - sleep 10秒检查一次  
38 - done  
39 -}  
40 -```  
41 -  
42 -#### 监控特性  
43 -  
44 -| 特性 | 说明 |  
45 -|------|------|  
46 -| **警告阈值** | 25GB - 打印警告但继续运行 |  
47 -| **终止阈值** | 30GB - 强制kill进程 |  
48 -| **检查频率** | 每10秒检查一次 |  
49 -| **日志输出** | 终端 + `logs/memory_monitor.log` |  
50 -| **自动清理** | 任务完成后自动终止监控 |  
51 -  
52 -#### 日志格式  
53 -  
54 -**警告日志**:  
55 -```  
56 -[2025-10-17 14:30:25] ⚠️ 内存警告!当前使用: 26.45GB (>= 25GB), PID=12345  
57 -```  
58 -  
59 -**强制终止日志**:  
60 -```  
61 -[2025-10-17 14:35:30] ❌ 内存超限!当前使用: 31.20GB (>= 30GB), 强制终止进程 PID=12345  
62 -```  
63 -  
64 -### 3. ✅ 增强的运行流程  
65 -  
66 -#### 更新后的执行流程  
67 -  
68 -```bash  
69 -#!/bin/bash  
70 -  
71 -1. 定义内存监控函数  
72 -2. 清理旧进程和输出  
73 -3. 创建logs目录  
74 -4. 显示开始信息(包含监控阈值)  
75 -  
76 -# 调试模式  
77 -5. 启动调试任务(后台)  
78 -6. 启动内存监控(后台)  
79 -7. 等待任务完成  
80 -8. 终止监控进程  
81 -9. 检查退出码  
82 -  
83 -# 生产模式  
84 -10. 启动生产任务(后台)  
85 -11. 启动内存监控(后台)  
86 -12. 等待任务完成  
87 -13. 终止监控进程  
88 -14. 检查退出码  
89 -  
90 -# 加载Redis  
91 -15. 加载索引到Redis  
92 -16. 检查退出码  
93 -  
94 -17. 显示完成信息  
95 -```  
96 -  
97 -### 4. ✅ 新增文件  
98 -  
99 -| 文件 | 说明 |  
100 -|------|------|  
101 -| `run.sh` | 更新:添加内存监控 |  
102 -| `RUN_SCRIPT_GUIDE.md` | 新增:运行脚本使用指南 |  
103 -| `test_memory_monitor.sh` | 新增:内存监控测试脚本 |  
104 -| `MEMORY_MONITORING_UPDATE.md` | 新增:本文档 |  
105 -  
106 -## 使用指南  
107 -  
108 -### 基本使用  
109 -  
110 -```bash  
111 -# 1. 运行脚本(自动监控内存)  
112 -cd /home/tw/recommendation/offline_tasks  
113 -./run.sh  
114 -  
115 -# 2. 查看监控日志  
116 -tail -f logs/memory_monitor.log  
117 -  
118 -# 3. 查看系统内存  
119 -free -h  
120 -```  
121 -  
122 -### 测试监控功能  
123 -  
124 -```bash  
125 -# 运行测试脚本  
126 -./test_memory_monitor.sh  
127 -```  
128 -  
129 -### 自定义阈值  
130 -  
131 -编辑 `run.sh` 第8-9行:  
132 -```bash  
133 -local threshold_warn=25 # 修改警告阈值  
134 -local threshold_kill=30 # 修改强制kill阈值  
135 -```  
136 -  
137 -## 技术细节  
138 -  
139 -### 内存获取  
140 -  
141 -```bash  
142 -# 获取进程内存(RSS,单位KB)  
143 -ps -p $pid -o rss=  
144 -  
145 -# 转换为MB  
146 -mem_mb=$(ps -p $pid -o rss= | awk '{print int($1/1024)}')  
147 -  
148 -# 转换为GB  
149 -mem_gb=$(echo "scale=2; $mem_mb/1024" | bc)  
150 -```  
151 -  
152 -### 进程检查  
153 -  
154 -```bash  
155 -# 检查进程是否存在  
156 -kill -0 $pid 2>/dev/null  
157 -  
158 -# 返回值:  
159 -# 0 - 进程存在  
160 -# 非0 - 进程不存在  
161 -```  
162 -  
163 -### 强制终止  
164 -  
165 -```bash  
166 -# 发送SIGKILL信号  
167 -kill -9 $pid  
168 -  
169 -# 特点:  
170 -# - 立即终止,不可捕获  
171 -# - 不执行清理代码  
172 -# - 确保进程被终止  
173 -```  
174 -  
175 -## 输出示例  
176 -  
177 -### 正常运行(内存未超限)  
178 -  
179 -```  
180 -======================================================================  
181 -开始运行离线任务 - 2025-10-17 14:00:00  
182 -内存监控: 警告阈值=25GB, 强制终止阈值=30GB  
183 -======================================================================  
184 -  
185 ->>> 步骤1: 调试模式运行(小数据量)  
186 -调试任务 PID: 12345  
187 -✓ 调试模式完成  
188 -  
189 ->>> 步骤2: 生产模式运行(大数据量)  
190 -生产任务 PID: 12346  
191 -✓ 生产模式完成  
192 -  
193 ->>> 步骤3: 加载到Redis  
194 -✓ Redis加载完成  
195 -  
196 -======================================================================  
197 -所有任务完成 - 2025-10-17 16:30:00  
198 -======================================================================  
199 -```  
200 -  
201 -### 内存警告(25GB-30GB)  
202 -  
203 -```  
204 ->>> 步骤2: 生产模式运行(大数据量)  
205 -生产任务 PID: 12346  
206 -[2025-10-17 15:20:15] ⚠️ 内存警告!当前使用: 26.45GB (>= 25GB), PID=12346  
207 -[2025-10-17 15:22:30] ⚠️ 内存警告!当前使用: 27.80GB (>= 25GB), PID=12346  
208 -[2025-10-17 15:24:45] ⚠️ 内存警告!当前使用: 28.95GB (>= 25GB), PID=12346  
209 -✓ 生产模式完成  
210 -```  
211 -  
212 -### 内存超限(>=30GB)  
213 -  
214 -```  
215 ->>> 步骤2: 生产模式运行(大数据量)  
216 -生产任务 PID: 12346  
217 -[2025-10-17 15:20:15] ⚠️ 内存警告!当前使用: 26.45GB (>= 25GB), PID=12346  
218 -[2025-10-17 15:22:30] ⚠️ 内存警告!当前使用: 28.80GB (>= 25GB), PID=12346  
219 -[2025-10-17 15:24:45] ❌ 内存超限!当前使用: 31.20GB (>= 30GB), 强制终止进程 PID=12346  
220 -✗ 生产模式失败,退出码: 137  
221 -```  
222 -  
223 -## 监控日志示例  
224 -  
225 -`logs/memory_monitor.log`:  
226 -```  
227 -[2025-10-17 15:20:15] ⚠️ 内存警告!当前使用: 26.45GB (>= 25GB), PID=12346  
228 -[2025-10-17 15:22:30] ⚠️ 内存警告!当前使用: 28.80GB (>= 25GB), PID=12346  
229 -[2025-10-17 15:24:45] ❌ 内存超限!当前使用: 31.20GB (>= 30GB), 强制终止进程 PID=12346  
230 -```  
231 -  
232 -## 故障处理  
233 -  
234 -### 内存持续增长  
235 -  
236 -**现象**: 警告日志频繁出现,内存持续增长  
237 -  
238 -**原因**:  
239 -- 数据量过大  
240 -- 内存泄漏  
241 -- 批处理大小不合理  
242 -  
243 -**解决方案**:  
244 -1. 减小批处理大小  
245 -2. 增加垃圾回收频率  
246 -3. 优化算法减少内存占用  
247 -4. 考虑分批运行  
248 -  
249 -### 进程被误杀  
250 -  
251 -**现象**: 任务未完成就被终止  
252 -  
253 -**原因**:  
254 -- 阈值设置过低  
255 -- 系统其他进程占用内存  
256 -  
257 -**解决方案**:  
258 -1. 提高阈值(修改 run.sh)  
259 -2. 优化代码减少内存使用  
260 -3. 关闭不必要的系统进程  
261 -  
262 -### 监控不生效  
263 -  
264 -**检查清单**:  
265 -- [ ] `bc` 命令是否安装:`which bc`  
266 -- [ ] 脚本是否有执行权限:`ls -l run.sh`  
267 -- [ ] logs目录是否存在:`ls -ld logs/`  
268 -- [ ] 进程是否在后台运行:`ps aux | grep run_all`  
269 -  
270 -## 性能影响  
271 -  
272 -### 监控开销  
273 -  
274 -| 项目 | 影响 |  
275 -|------|------|  
276 -| CPU | < 0.1% (每10秒运行一次ps命令) |  
277 -| 内存 | < 10MB (监控脚本本身) |  
278 -| 磁盘I/O | 极小 (仅写日志) |  
279 -  
280 -### 建议  
281 -  
282 -- ✅ 检查频率10秒合理,不建议小于5秒  
283 -- ✅ 警告阈值25GB为系统总内存的合理比例  
284 -- ✅ 终止阈值30GB留有5GB缓冲空间  
285 -- ⚠️ 根据实际情况调整阈值  
286 -  
287 -## 最佳实践  
288 -  
289 -### 1. 定期查看日志  
290 -```bash  
291 -# 每天检查  
292 -cat logs/memory_monitor.log  
293 -  
294 -# 统计警告次数  
295 -grep "⚠️" logs/memory_monitor.log | wc -l  
296 -  
297 -# 统计终止次数  
298 -grep "❌" logs/memory_monitor.log | wc -l  
299 -```  
300 -  
301 -### 2. 设置定时任务  
302 -```bash  
303 -# 每周一凌晨2点运行  
304 -0 2 * * 1 /home/tw/recommendation/offline_tasks/run.sh >> /var/log/offline_tasks.log 2>&1  
305 -```  
306 -  
307 -### 3. 配置告警  
308 -```bash  
309 -# 在 run.sh 末尾添加  
310 -if grep -q "❌" logs/memory_monitor.log; then  
311 - echo "内存超限告警" | mail -s "[告警] 离线任务内存超限" admin@example.com  
312 -fi  
313 -```  
314 -  
315 -### 4. 监控系统资源  
316 -```bash  
317 -# 安装监控工具  
318 -apt install htop sysstat  
319 -  
320 -# 实时监控  
321 -htop -p $(pgrep -f run_all.py)  
322 -  
323 -# 查看历史  
324 -sar -r 1 10 # 内存使用情况  
325 -```  
326 -  
327 -## 对比  
328 -  
329 -### 更新前  
330 -```bash  
331 -# 无内存监控  
332 -python3 run_all.py --lookback_days 730 --top_n 50  
333 -  
334 -# 问题:  
335 -# - 内存可能无限增长  
336 -# - OOM导致系统崩溃  
337 -# - 无法及时发现问题  
338 -```  
339 -  
340 -### 更新后  
341 -```bash  
342 -# 自动内存监控  
343 -./run.sh  
344 -  
345 -# 优势:  
346 -# ✅ 25GB警告提醒  
347 -# ✅ 30GB自动终止  
348 -# ✅ 详细日志记录  
349 -# ✅ 保护系统稳定  
350 -```  
351 -  
352 -## 总结  
353 -  
354 -本次更新实现了:  
355 -  
356 -1. ✅ **代码规范化**: 统一使用logger,移除print  
357 -2. ✅ **内存监控**: 25GB警告,30GB强制终止  
358 -3. ✅ **自动化运行**: 集成监控到运行流程  
359 -4. ✅ **日志记录**: 详细的监控日志  
360 -5. ✅ **测试工具**: 提供测试脚本验证功能  
361 -6. ✅ **完整文档**: 使用指南和故障处理  
362 -  
363 -### 核心价值  
364 -  
365 -- 🛡️ **保护系统**: 防止内存溢出导致系统崩溃  
366 -- 📊 **实时监控**: 每10秒检查一次内存使用  
367 -- 🔔 **及时告警**: 25GB警告,30GB终止  
368 -- 📝 **日志完整**: 所有监控事件都有记录  
369 -- 🔧 **易于调整**: 阈值和频率可轻松修改  
370 -  
371 ----  
372 -  
373 -**更新完成时间**: 2025-10-17  
374 -**状态**: ✅ 已完成,可投入使用  
375 -**建议**: 先在测试环境验证后再用于生产  
376 -  
offline_tasks/PROJECT_SUMMARY.md deleted
@@ -1,276 +0,0 @@ @@ -1,276 +0,0 @@
1 -# 推荐系统离线任务 - 项目总结  
2 -  
3 -## 项目概述  
4 -  
5 -本项目实现了一个完整的推荐系统离线任务框架,用于生成各种推荐索引。主要包括两大模块:  
6 -  
7 -1. **i2i 行为相似索引**:基于用户行为计算物品之间的相似度  
8 -2. **兴趣点聚合索引**:按多维度聚合用户行为,生成不同场景的推荐列表  
9 -  
10 -## 技术架构  
11 -  
12 -### 数据来源  
13 -- 数据库:SelectDB(兼容MySQL协议)  
14 -- 主要表:  
15 - - `sensors_events`:用户行为事件表  
16 - - `prd_goods_sku`:商品SKU表  
17 -  
18 -### 算法实现  
19 -  
20 -#### 1. i2i 行为相似算法  
21 -  
22 -| 算法 | 原理 | 优势 | 适用场景 |  
23 -|------|------|------|---------|  
24 -| **Swing** | 基于用户共同行为的物品相似度,考虑用户重叠度 | 效果好,能发现深层关系 | 详情页推荐、相关商品 |  
25 -| **Session W2V** | 基于用户会话序列训练Word2Vec | 能捕获序列关系 | 下一个可能感兴趣的商品 |  
26 -| **DeepWalk** | 基于图随机游走训练Word2Vec | 能发现图结构特征 | 发现潜在关联商品 |  
27 -  
28 -#### 2. 兴趣点聚合  
29 -  
30 -**维度分类:**  
31 -  
32 -- **单维度**:  
33 - - 平台(PC/Mobile/App)  
34 - - 国家/销售区域  
35 - - 客户类型(零售商/批发商等)  
36 - - 二级分类  
37 - - 三级分类  
38 -  
39 -- **组合维度**:  
40 - - 平台 + 国家  
41 - - 平台 + 客户类型  
42 - - 国家 + 客户类型  
43 - - 平台 + 国家 + 客户类型  
44 -  
45 -**列表类型:**  
46 -  
47 -- **hot(热门)**:基于最近180天的高交互商品  
48 -- **cart(加购)**:基于加购行为的高频商品  
49 -- **new(新品)**:基于商品创建时间的新品  
50 -- **global(全局)**:基于所有数据的综合排序  
51 -  
52 -## 核心特性  
53 -  
54 -### 1. 时间衰减  
55 -- 使用指数衰减模型,越近期的行为权重越高  
56 -- 衰减因子:0.95(每30天衰减一次)  
57 -- 公式:`weight = decay_factor ^ (days / 30)`  
58 -  
59 -### 2. 行为权重  
60 -不同行为类型赋予不同权重:  
61 -  
62 -| 行为类型 | 权重 | 说明 |  
63 -|---------|------|------|  
64 -| click | 1.0 | 点击 |  
65 -| addToPool | 2.0 | 加入询盘池 |  
66 -| addToCart | 3.0 | 加入购物车 |  
67 -| contactFactory | 5.0 | 联系工厂 |  
68 -| purchase | 10.0 | 购买 |  
69 -  
70 -### 3. 可配置参数  
71 -所有参数集中在 `config/offline_config.py`,便于调整优化。  
72 -  
73 -## 文件清单  
74 -  
75 -### 核心代码  
76 -  
77 -```  
78 -/home/tw/recommendation/  
79 -├── db_service.py # 数据库连接服务  
80 -├── requirements.txt # Python依赖包  
81 -└── offline_tasks/  
82 - ├── config/  
83 - │ └── offline_config.py # 配置文件  
84 - ├── scripts/  
85 - │ ├── i2i_swing.py # Swing算法  
86 - │ ├── i2i_session_w2v.py # Session W2V算法  
87 - │ ├── i2i_deepwalk.py # DeepWalk算法  
88 - │ ├── interest_aggregation.py # 兴趣点聚合  
89 - │ └── load_index_to_redis.py # 加载索引到Redis  
90 - ├── run_all.py # 统一调度脚本  
91 - ├── test_connection.py # 连接测试脚本  
92 - ├── example_query_redis.py # Redis查询示例  
93 - ├── README.md # 详细文档  
94 - ├── QUICKSTART.md # 快速启动指南  
95 - └── PROJECT_SUMMARY.md # 本文档  
96 -```  
97 -  
98 -### 输出目录  
99 -  
100 -```  
101 -offline_tasks/  
102 -├── output/ # 索引输出目录  
103 -│ ├── i2i_swing_YYYYMMDD.txt  
104 -│ ├── i2i_session_w2v_YYYYMMDD.txt  
105 -│ ├── i2i_deepwalk_YYYYMMDD.txt  
106 -│ ├── session_w2v_model_YYYYMMDD.model # W2V模型  
107 -│ ├── deepwalk_model_YYYYMMDD.model # DeepWalk模型  
108 -│ ├── item_graph_YYYYMMDD.txt # 物品图结构  
109 -│ ├── interest_aggregation_hot_YYYYMMDD.txt  
110 -│ ├── interest_aggregation_cart_YYYYMMDD.txt  
111 -│ ├── interest_aggregation_new_YYYYMMDD.txt  
112 -│ └── interest_aggregation_global_YYYYMMDD.txt  
113 -└── logs/ # 日志目录  
114 - ├── run_all_YYYYMMDD.log  
115 - └── ...  
116 -```  
117 -  
118 -## 使用流程  
119 -  
120 -### 1. 环境准备  
121 -```bash  
122 -pip install -r requirements.txt  
123 -```  
124 -  
125 -### 2. 测试连接  
126 -```bash  
127 -cd offline_tasks  
128 -python test_connection.py  
129 -```  
130 -  
131 -### 3. 运行离线任务  
132 -```bash  
133 -python run_all.py --lookback_days 730 --top_n 50  
134 -```  
135 -  
136 -### 4. 加载索引到Redis  
137 -```bash  
138 -python scripts/load_index_to_redis.py --expire-days 7  
139 -```  
140 -  
141 -### 5. 查询示例  
142 -```bash  
143 -python example_query_redis.py  
144 -```  
145 -  
146 -## 数据格式  
147 -  
148 -### i2i索引格式  
149 -```  
150 -item_id \t item_name \t similar_item_id1:score1,similar_item_id2:score2,...  
151 -```  
152 -  
153 -示例:  
154 -```  
155 -123456 \t 商品A \t 234567:0.8523,345678:0.7842,456789:0.7234  
156 -```  
157 -  
158 -### 兴趣点聚合索引格式  
159 -```  
160 -dimension_key \t item_id1:score1,item_id2:score2,...  
161 -```  
162 -  
163 -示例:  
164 -```  
165 -platform:PC \t 12345:98.52,23456:87.34,34567:76.89  
166 -country:US \t 45678:156.23,56789:142.87,67890:128.45  
167 -platform_country:PC_US \t 78901:234.56,89012:198.76,90123:187.23  
168 -```  
169 -  
170 -## 在线推荐场景  
171 -  
172 -### 场景1:详情页 - 大家都在看  
173 -```  
174 -用户浏览商品ID: 123456  
175 -查询: i2i:swing:123456  
176 -返回: 该商品的相似商品列表  
177 -```  
178 -  
179 -### 场景2:首页 - 猜你喜欢  
180 -```  
181 -用户特征: PC端, 美国, 零售商  
182 -组合查询:  
183 -1. interest:hot:platform_country:PC_US  
184 -2. interest:cart:customer_type:retailer  
185 -3. 结合用户历史行为的i2i  
186 -```  
187 -  
188 -### 场景3:搜索结果页 - 供应商推荐  
189 -```  
190 -用户搜索: 二级分类100  
191 -查询: interest:global:category_level2:100  
192 -返回: 该分类下的热门商品  
193 -```  
194 -  
195 -## 性能指标  
196 -  
197 -### 数据量参考(730天数据)  
198 -- 用户行为记录:约100万-1000万条  
199 -- 商品数量:约10万-50万个  
200 -- 生成索引:约5万-20万条  
201 -  
202 -### 运行时间(参考值)  
203 -- Swing算法:2-4小时  
204 -- Session W2V:30-60分钟  
205 -- DeepWalk:1-2小时  
206 -- 兴趣点聚合:30-60分钟  
207 -- 总计:约5-8小时  
208 -  
209 -### 资源占用  
210 -- CPU:8-16核  
211 -- 内存:8-16GB  
212 -- 磁盘:输出文件约500MB-2GB  
213 -  
214 -## 优化建议  
215 -  
216 -### 1. 算法层面  
217 -- **Swing算法**:可以使用C++版本(已有实现),性能提升10倍  
218 -- **并行化**:将不同算法分配到不同机器并行运行  
219 -- **增量更新**:对于变化不大的索引,考虑增量更新  
220 -  
221 -### 2. 工程层面  
222 -- **分布式计算**:使用Spark/Flink处理大规模数据  
223 -- **缓存中间结果**:避免重复计算  
224 -- **数据采样**:调试阶段使用采样数据  
225 -  
226 -### 3. 业务层面  
227 -- **A/B测试**:对比不同算法的效果  
228 -- **融合策略**:组合多个算法的结果  
229 -- **实时更新**:结合实时计算补充离线索引  
230 -  
231 -## 后续扩展  
232 -  
233 -### 1. 新增算法  
234 -- ItemCF(物品协同过滤)  
235 -- Node2Vec(带权重的图游走)  
236 -- Graph Neural Network(图神经网络)  
237 -  
238 -### 2. 新增维度  
239 -- 价格区间  
240 -- 品牌  
241 -- 标签组合  
242 -- 用户画像更多维度  
243 -  
244 -### 3. 实时化  
245 -- 实时更新热门商品  
246 -- 实时更新新品列表  
247 -- 实时i2i相似度计算  
248 -  
249 -### 4. 个性化  
250 -- 结合用户画像的个性化排序  
251 -- 多目标优化(点击率、转化率、GMV)  
252 -- 强化学习排序  
253 -  
254 -## 维护说明  
255 -  
256 -### 定期检查  
257 -- 每周检查日志,确保任务正常运行  
258 -- 每月检查索引质量,调整参数  
259 -- 每季度评估算法效果,优化策略  
260 -  
261 -### 监控指标  
262 -- 任务执行成功率  
263 -- 索引生成数量  
264 -- Redis命中率  
265 -- 推荐点击率/转化率  
266 -  
267 -## 联系方式  
268 -  
269 -如有问题或建议,请联系推荐系统团队。  
270 -  
271 ----  
272 -  
273 -**文档版本**: v1.0  
274 -**最后更新**: 2025-10-16  
275 -**作者**: 推荐系统团队  
276 -  
offline_tasks/QUICKSTART_NEW.md deleted
@@ -1,321 +0,0 @@ @@ -1,321 +0,0 @@
1 -# 快速开始 - 新版本  
2 -  
3 -## 🚀 5分钟快速上手  
4 -  
5 -### 1. 安装依赖  
6 -  
7 -```bash  
8 -cd /home/tw/recommendation  
9 -pip install -r requirements.txt  
10 -```  
11 -  
12 -**新增依赖**: `elasticsearch>=8.0.0`  
13 -  
14 -### 2. 测试ES连接  
15 -  
16 -```bash  
17 -cd offline_tasks  
18 -python scripts/test_es_connection.py  
19 -```  
20 -  
21 -如果看到 ✓ 表示测试通过。  
22 -  
23 -### 3. 运行所有任务  
24 -  
25 -```bash  
26 -python run_all.py  
27 -```  
28 -  
29 -就这么简单!不需要任何参数。  
30 -  
31 -### 4. 加载到Redis  
32 -  
33 -```bash  
34 -python scripts/load_index_to_redis.py  
35 -```  
36 -  
37 -## 📋 运行单个任务  
38 -  
39 -### i2i相似索引  
40 -  
41 -```bash  
42 -# Swing算法  
43 -python scripts/i2i_swing.py --lookback_days 30 --top_n 50 --time_decay  
44 -  
45 -# Session W2V  
46 -python scripts/i2i_session_w2v.py --lookback_days 30 --top_n 50 --save_model  
47 -  
48 -# DeepWalk  
49 -python scripts/i2i_deepwalk.py --lookback_days 30 --top_n 50 --save_model  
50 -  
51 -# 内容相似(ES向量)- 无需参数!  
52 -python scripts/i2i_content_similar.py  
53 -```  
54 -  
55 -### 兴趣聚合  
56 -  
57 -```bash  
58 -python scripts/interest_aggregation.py --lookback_days 30 --top_n 1000  
59 -```  
60 -  
61 -## 🎯 主要变化  
62 -  
63 -### 简化!简化!简化!  
64 -  
65 -#### 之前 (v1.0)  
66 -```bash  
67 -python run_all.py \  
68 - --lookback_days 30 \  
69 - --top_n 50 \  
70 - --skip-interest \  
71 - --only-content \  
72 - --debug  
73 -```  
74 -  
75 -#### 现在 (v2.0)  
76 -```bash  
77 -python run_all.py  
78 -# 或  
79 -python run_all.py --debug # 启用debug模式  
80 -```  
81 -  
82 -### 内容相似索引  
83 -  
84 -#### 之前  
85 -- 1个索引: `i2i_content_hybrid_*.txt`  
86 -- 基于: 商品属性(分类、供应商等)  
87 -- 参数: `--method hybrid --top_n 50`  
88 -  
89 -#### 现在  
90 -- **2个索引**:  
91 - - `i2i_content_name_*.txt` (名称向量)  
92 - - `i2i_content_pic_*.txt` (图片向量)  
93 -- 基于: Elasticsearch深度学习向量  
94 -- 参数: **无需参数!**  
95 -  
96 -## 📊 输出文件  
97 -  
98 -### 文件位置  
99 -```  
100 -offline_tasks/output/  
101 -├── i2i_swing_20251017.txt # Swing相似索引  
102 -├── i2i_session_w2v_20251017.txt # Session W2V相似索引  
103 -├── i2i_deepwalk_20251017.txt # DeepWalk相似索引  
104 -├── i2i_content_name_20251017.txt # 名称向量相似索引 ⭐新  
105 -├── i2i_content_pic_20251017.txt # 图片向量相似索引 ⭐新  
106 -├── interest_aggregation_hot_20251017.txt # 热门商品  
107 -├── interest_aggregation_cart_20251017.txt # 加购商品  
108 -├── interest_aggregation_new_20251017.txt # 新品  
109 -└── interest_aggregation_global_20251017.txt # 全局热门  
110 -```  
111 -  
112 -### 文件格式  
113 -```  
114 -item_id \t item_name \t similar_id1:score1,similar_id2:score2,...  
115 -```  
116 -  
117 -## 🔍 查询示例  
118 -  
119 -### Python查询  
120 -  
121 -```python  
122 -import redis  
123 -import json  
124 -  
125 -# 连接Redis  
126 -r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)  
127 -  
128 -# 1. 获取Swing相似商品  
129 -similar = json.loads(r.get('item:similar:swing:123456'))  
130 -# 返回: [[234567, 0.8523], [345678, 0.7842], ...]  
131 -  
132 -# 2. 获取名称向量相似商品 ⭐新  
133 -similar = json.loads(r.get('item:similar:content_name:123456'))  
134 -# 返回: [[234567, 0.9234], [345678, 0.8756], ...]  
135 -  
136 -# 3. 获取图片向量相似商品 ⭐新  
137 -similar = json.loads(r.get('item:similar:content_pic:123456'))  
138 -# 返回: [[567890, 0.8123], [678901, 0.7856], ...]  
139 -  
140 -# 4. 获取热门商品  
141 -hot_items = json.loads(r.get('interest:hot:platform:PC'))  
142 -# 返回: [123456, 234567, 345678, ...]  
143 -```  
144 -  
145 -### Redis CLI查询  
146 -  
147 -```bash  
148 -# 连接Redis  
149 -redis-cli  
150 -  
151 -# 查看Swing相似商品  
152 -GET item:similar:swing:123456  
153 -  
154 -# 查看名称向量相似商品 ⭐新  
155 -GET item:similar:content_name:123456  
156 -  
157 -# 查看图片向量相似商品 ⭐新  
158 -GET item:similar:content_pic:123456  
159 -  
160 -# 查看热门商品  
161 -GET interest:hot:platform:PC  
162 -```  
163 -  
164 -## ⚙️ 配置说明  
165 -  
166 -### ES配置 (i2i_content_similar.py)  
167 -  
168 -```python  
169 -ES_CONFIG = {  
170 - 'host': 'http://localhost:9200',  
171 - 'index_name': 'spu',  
172 - 'username': 'essa',  
173 - 'password': '4hOaLaf41y2VuI8y'  
174 -}  
175 -```  
176 -  
177 -### 算法参数 (i2i_content_similar.py)  
178 -  
179 -```python  
180 -TOP_N = 50 # 每个商品返回50个相似商品  
181 -KNN_K = 100 # KNN查询返回100个候选  
182 -KNN_CANDIDATES = 200 # 候选池大小200  
183 -```  
184 -  
185 -### 全局配置 (offline_config.py)  
186 -  
187 -```python  
188 -DEFAULT_LOOKBACK_DAYS = 30 # 回看天数  
189 -DEFAULT_I2I_TOP_N = 50 # i2i Top N  
190 -DEFAULT_INTEREST_TOP_N = 1000 # 兴趣聚合 Top N  
191 -```  
192 -  
193 -## 🔧 故障排查  
194 -  
195 -### ES连接失败  
196 -  
197 -```bash  
198 -# 1. 检查ES是否运行  
199 -curl -u essa:4hOaLaf41y2VuI8y http://localhost:9200  
200 -  
201 -# 2. 运行测试脚本  
202 -python scripts/test_es_connection.py  
203 -  
204 -# 3. 检查配置  
205 -# 编辑 scripts/i2i_content_similar.py 中的 ES_CONFIG  
206 -```  
207 -  
208 -### 商品ID不存在  
209 -  
210 -测试脚本默认使用 `item_id = "3302275"`,如果不存在:  
211 -  
212 -```python  
213 -# 编辑 test_es_connection.py  
214 -test_item_id = "你的商品ID"  
215 -```  
216 -  
217 -### Redis连接失败  
218 -  
219 -```bash  
220 -# 检查Redis配置  
221 -cat offline_tasks/config/offline_config.py | grep REDIS  
222 -  
223 -# 测试Redis连接  
224 -redis-cli ping  
225 -```  
226 -  
227 -### 文件不存在  
228 -  
229 -```bash  
230 -# 检查output目录  
231 -ls -lh offline_tasks/output/  
232 -  
233 -# 查看最新生成的文件  
234 -ls -lht offline_tasks/output/ | head -10  
235 -```  
236 -  
237 -## 📚 详细文档  
238 -  
239 -- **ES向量相似度**: `scripts/ES_VECTOR_SIMILARITY.md`  
240 -- **更新说明**: `CONTENT_SIMILARITY_UPDATE.md`  
241 -- **变更总结**: `CHANGES_SUMMARY.md`  
242 -- **Redis规范**: `REDIS_DATA_SPEC.md`  
243 -  
244 -## 🎓 学习路径  
245 -  
246 -### 新用户  
247 -1. 阅读本文档 ✓  
248 -2. 运行 `test_es_connection.py`  
249 -3. 运行 `run_all.py`  
250 -4. 查看 `output/` 目录  
251 -5. 加载到Redis并查询  
252 -  
253 -### 进阶使用  
254 -1. 阅读 `ES_VECTOR_SIMILARITY.md`  
255 -2. 了解向量相似度原理  
256 -3. 优化ES查询性能  
257 -4. 自定义算法参数  
258 -  
259 -### 开发者  
260 -1. 阅读 `CONTENT_SIMILARITY_UPDATE.md`  
261 -2. 了解技术架构  
262 -3. 阅读源代码注释  
263 -4. 贡献代码改进  
264 -  
265 -## 🚨 注意事项  
266 -  
267 -### ⚠️ 破坏性变化  
268 -  
269 -1. **i2i_content_similar.py 参数全部改变**  
270 - - 旧: `--method`, `--top_n`, `--debug`  
271 - - 新: 无参数  
272 -  
273 -2. **Redis Key格式改变**  
274 - - 旧: `item:similar:content:{item_id}`  
275 - - 新: `item:similar:content_name:{item_id}` 和 `item:similar:content_pic:{item_id}`  
276 -  
277 -3. **输出文件改变**  
278 - - 旧: `i2i_content_hybrid_*.txt`  
279 - - 新: `i2i_content_name_*.txt` 和 `i2i_content_pic_*.txt`  
280 -  
281 -### ✅ 向后兼容  
282 -  
283 -- Swing、W2V、DeepWalk 算法不受影响  
284 -- 兴趣聚合不受影响  
285 -- Redis加载器向后兼容  
286 -- 其他i2i索引继续工作  
287 -  
288 -## 💡 最佳实践  
289 -  
290 -### 运行频率  
291 -- **行为相似** (Swing, W2V, DeepWalk): 每天  
292 -- **内容相似** (名称向量, 图片向量): 每周  
293 -- **兴趣聚合**: 每天  
294 -  
295 -### Redis TTL  
296 -- **行为相似**: 7天  
297 -- **内容相似**: 30天  
298 -- **兴趣聚合**: 3-7天  
299 -  
300 -### 性能优化  
301 -1. 使用 `--debug` 模式调试  
302 -2. 先用小数据集测试  
303 -3. 定期清理过期数据  
304 -4. 监控ES查询性能  
305 -  
306 -## 🎉 总结  
307 -  
308 -新版本大幅简化了使用,主要改进:  
309 -  
310 -1. ✅ **无需参数**: `run_all.py` 和 `i2i_content_similar.py` 无需参数  
311 -2. ✅ **更强大**: 基于深度学习向量,更准确  
312 -3. ✅ **多维度**: 名称 + 图片两个维度  
313 -4. ✅ **更快**: ES KNN查询性能优秀  
314 -5. ✅ **易维护**: 代码简洁,配置清晰  
315 -  
316 -开始使用新版本,享受更简单、更强大的推荐系统!  
317 -  
318 ----  
319 -  
320 -**问题反馈**: 如有问题请查看详细文档或联系开发团队  
321 -  
offline_tasks/QUICK_DEBUG_SUMMARY.md deleted
@@ -1,128 +0,0 @@ @@ -1,128 +0,0 @@
1 -# Debug功能快速总结  
2 -  
3 -## ✅ 已完成的工作  
4 -  
5 -### 1. 核心组件  
6 -  
7 -| 组件 | 状态 | 说明 |  
8 -|------|------|------|  
9 -| `debug_utils.py` | ✅ | Debug工具库(369行) |  
10 -| `offline_config.py` | ✅ | 新增DEBUG_CONFIG |  
11 -| `i2i_swing.py` | ✅ | 完整debug支持 |  
12 -| `run_all.py` | ✅ | 支持--debug参数传递 |  
13 -  
14 -### 2. Debug功能特性  
15 -  
16 -#### A. 详细日志输出  
17 -```python  
18 -# 自动记录:  
19 -- 算法参数  
20 -- 数据统计(行数、列数、类型、缺失值)  
21 -- 处理进度(每N条显示)  
22 -- 每个步骤的耗时  
23 -- 数据分布(行为类型、用户数、商品数)  
24 -- 中间结果采样  
25 -```  
26 -  
27 -#### B. 明文索引文件  
28 -```  
29 -原始: 12345\t香蕉干\t67890:0.8567,11223:0.7234  
30 -明文: [1] i2i:swing:12345(香蕉干)  
31 - 1. ID:67890(芒果干) - Score:0.8567  
32 - 2. ID:11223(菠萝干) - Score:0.7234  
33 -```  
34 -  
35 -#### C. 日志文件  
36 -```  
37 -offline_tasks/logs/debug/i2i_swing_20251016_193000.log  
38 -offline_tasks/output/debug/i2i_swing_20251016_readable.txt  
39 -```  
40 -  
41 -## 🚀 使用方法  
42 -  
43 -### 单个脚本  
44 -```bash  
45 -# i2i_swing.py 已支持debug  
46 -python3 scripts/i2i_swing.py --lookback_days 7 --top_n 10 --debug  
47 -```  
48 -  
49 -### 所有任务  
50 -```bash  
51 -# run_all.py 已支持debug参数传递  
52 -python3 run_all.py --lookback_days 7 --top_n 10 --debug  
53 -```  
54 -  
55 -## 📊 输出示例  
56 -  
57 -### 控制台输出  
58 -```  
59 -2025-10-16 19:30:00 - i2i_swing - DEBUG - ============================================================  
60 -2025-10-16 19:30:00 - i2i_swing - DEBUG - 算法参数:  
61 -2025-10-16 19:30:00 - i2i_swing - DEBUG - alpha: 0.5  
62 -2025-10-16 19:30:00 - i2i_swing - DEBUG - top_n: 10  
63 -2025-10-16 19:30:05 - i2i_swing - INFO - 获取到 15234 条记录  
64 -2025-10-16 19:30:05 - i2i_swing - DEBUG - 总行数: 15234  
65 -2025-10-16 19:30:05 - i2i_swing - DEBUG - 行为类型分布:  
66 -2025-10-16 19:30:05 - i2i_swing - DEBUG - addToCart: 8520 (55.93%)  
67 -2025-10-16 19:30:10 - i2i_swing - INFO - 总用户数: 3456, 总商品数: 2345  
68 -```  
69 -  
70 -### 明文文件示例  
71 -```  
72 -================================================================================  
73 -明文索引文件  
74 -生成时间: 2025-10-16 19:35:00  
75 -描述: Swing算法 i2i相似度推荐 (alpha=0.5, lookback_days=7)  
76 -总索引数: 2345  
77 -================================================================================  
78 -  
79 -[1] i2i:swing:12345(香蕉干)  
80 ---------------------------------------------------------------------------------  
81 - 1. ID:67890(芒果干) - Score:0.8567  
82 - 2. ID:11223(菠萝干) - Score:0.7234  
83 - 3. ID:44556(苹果干) - Score:0.6891  
84 -```  
85 -  
86 -## 🔧 Debug工具函数  
87 -  
88 -| 函数 | 功能 |  
89 -|------|------|  
90 -| `setup_debug_logger()` | 设置debug日志 |  
91 -| `log_dataframe_info()` | 记录DataFrame详情 |  
92 -| `log_dict_stats()` | 记录字典统计 |  
93 -| `save_readable_index()` | 保存明文索引 |  
94 -| `fetch_name_mappings()` | 获取ID到名称映射 |  
95 -| `log_algorithm_params()` | 记录算法参数 |  
96 -| `log_processing_step()` | 记录处理步骤 |  
97 -  
98 -## 📝 待完成  
99 -  
100 -需要为以下脚本添加debug支持(使用相同模式):  
101 -- [ ] i2i_session_w2v.py  
102 -- [ ] i2i_deepwalk.py  
103 -- [ ] i2i_content_similar.py  
104 -- [ ] interest_aggregation.py  
105 -  
106 -## 💡 快速测试  
107 -  
108 -```bash  
109 -# 1. 测试debug工具  
110 -cd /home/tw/recommendation/offline_tasks  
111 -python3 -c "from scripts.debug_utils import *; print('✓ Debug utils OK')"  
112 -  
113 -# 2. 测试i2i_swing debug模式  
114 -python3 scripts/i2i_swing.py --lookback_days 1 --top_n 5 --debug  
115 -  
116 -# 3. 查看输出  
117 -ls -lh logs/debug/  
118 -ls -lh output/debug/  
119 -```  
120 -  
121 -## 📖 完整文档  
122 -  
123 -详细使用指南:`DEBUG_GUIDE.md`  
124 -  
125 ----  
126 -  
127 -**状态**: 🚧 进行中 (i2i_swing.py完成,其他脚本待更新)  
128 -**下一步**: 批量更新其他4个脚本的debug支持  
offline_tasks/STRUCTURE.md deleted
@@ -1,303 +0,0 @@ @@ -1,303 +0,0 @@
1 -# 项目目录结构  
2 -  
3 -```  
4 -/home/tw/recommendation/  
5 -│  
6 -├── db_service.py # 数据库连接服务(共享模块)  
7 -├── requirements.txt # Python依赖包列表  
8 -│  
9 -├── offline_tasks/ # 【离线任务主目录】  
10 -│ │  
11 -│ ├── config/ # 配置目录  
12 -│ │ └── offline_config.py # 离线任务配置文件  
13 -│ │ - 数据库配置  
14 -│ │ - Redis配置  
15 -│ │ - 算法参数配置  
16 -│ │ - 时间配置  
17 -│ │  
18 -│ ├── scripts/ # 脚本目录  
19 -│ │ ├── i2i_swing.py # Swing算法实现  
20 -│ │ │ 输出: i2i_swing_YYYYMMDD.txt  
21 -│ │ │  
22 -│ │ ├── i2i_session_w2v.py # Session Word2Vec算法  
23 -│ │ │ 输出: i2i_session_w2v_YYYYMMDD.txt  
24 -│ │ │ session_w2v_model_YYYYMMDD.model  
25 -│ │ │  
26 -│ │ ├── i2i_deepwalk.py # DeepWalk算法  
27 -│ │ │ 输出: i2i_deepwalk_YYYYMMDD.txt  
28 -│ │ │ deepwalk_model_YYYYMMDD.model  
29 -│ │ │ item_graph_YYYYMMDD.txt  
30 -│ │ │  
31 -│ │ ├── interest_aggregation.py # 兴趣点聚合索引生成  
32 -│ │ │ 输出: interest_aggregation_hot_YYYYMMDD.txt  
33 -│ │ │ interest_aggregation_cart_YYYYMMDD.txt  
34 -│ │ │ interest_aggregation_new_YYYYMMDD.txt  
35 -│ │ │ interest_aggregation_global_YYYYMMDD.txt  
36 -│ │ │  
37 -│ │ └── load_index_to_redis.py # 索引加载到Redis  
38 -│ │  
39 -│ ├── output/ # 输出目录(自动创建)  
40 -│ │ ├── i2i_swing_*.txt # Swing算法输出  
41 -│ │ ├── i2i_session_w2v_*.txt # Session W2V输出  
42 -│ │ ├── i2i_deepwalk_*.txt # DeepWalk输出  
43 -│ │ ├── interest_aggregation_* # 兴趣点聚合输出  
44 -│ │ ├── *.model # 训练的模型文件  
45 -│ │ └── item_graph_*.txt # 物品图结构  
46 -│ │  
47 -│ ├── logs/ # 日志目录(自动创建)  
48 -│ │ ├── run_all_*.log # 总调度日志  
49 -│ │ ├── load_redis.log # Redis加载日志  
50 -│ │ └── cron.log # 定时任务日志  
51 -│ │  
52 -│ ├── run_all.py # 【主调度脚本】  
53 -│ │ 统一运行所有离线任务  
54 -│ │  
55 -│ ├── install.sh # 安装脚本  
56 -│ │ 自动安装依赖和初始化  
57 -│ │  
58 -│ ├── test_connection.py # 连接测试脚本  
59 -│ │ 测试数据库和Redis连接  
60 -│ │  
61 -│ ├── example_query_redis.py # Redis查询示例  
62 -│ │ 演示如何查询索引  
63 -│ │  
64 -│ ├── README.md # 详细文档  
65 -│ ├── QUICKSTART.md # 快速开始指南  
66 -│ ├── PROJECT_SUMMARY.md # 项目总结  
67 -│ └── STRUCTURE.md # 本文档  
68 -│  
69 -├── item_sim.py # 原有的物品相似度脚本(参考)  
70 -├── hot/ # 原有的热门商品模块(参考)  
71 -├── collaboration/ # 原有的协同过滤模块(参考)  
72 -└── graphembedding/ # 原有的图嵌入模块(参考)  
73 -```  
74 -  
75 -## 数据流向图  
76 -  
77 -```  
78 -┌─────────────────┐  
79 -│ 数据源 │  
80 -│ (SelectDB) │  
81 -└────────┬────────┘  
82 - │  
83 - │ SQL查询  
84 - │  
85 - ▼  
86 -┌─────────────────────────────────────────────────────────┐  
87 -│ 离线任务处理 │  
88 -│ │  
89 -│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │  
90 -│ │ Swing算法 │ │ Session W2V │ │ DeepWalk算法 │ │  
91 -│ │ │ │ │ │ │ │  
92 -│ │ 用户行为共现 │ │ 会话序列 │ │ 图随机游走 │ │  
93 -│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │  
94 -│ │ │ │ │  
95 -│ └─────────────────┴─────────────────┘ │  
96 -│ │ │  
97 -│ │ i2i相似度索引 │  
98 -│ ▼ │  
99 -│ ┌─────────────────┐ │  
100 -│ │ 输出文件(.txt) │ │  
101 -│ └─────────────────┘ │  
102 -│ │  
103 -│ ┌──────────────────────────────────────────────────┐ │  
104 -│ │ 兴趣点聚合 │ │  
105 -│ │ │ │  
106 -│ │ 按维度分组: 平台/国家/客户类型/分类 │ │  
107 -│ │ 按类型分组: 热门/加购/新品/全局 │ │  
108 -│ │ 时间衰减 + 行为权重 │ │  
109 -│ └────────────────────┬─────────────────────────────┘ │  
110 -│ │ │  
111 -│ │ 多维度索引 │  
112 -│ ▼ │  
113 -│ ┌─────────────────┐ │  
114 -│ │ 输出文件(.txt) │ │  
115 -│ └─────────────────┘ │  
116 -└─────────────────────────────────────────────────────────┘  
117 - │  
118 - │ 加载  
119 - ▼  
120 - ┌─────────────────┐  
121 - │ Redis │  
122 - │ (在线索引) │  
123 - └────────┬────────┘  
124 - │  
125 - │ 查询  
126 - ▼  
127 - ┌─────────────────┐  
128 - │ 在线推荐服务 │  
129 - │ │  
130 - │ - 详情页推荐 │  
131 - │ - 首页推荐 │  
132 - │ - 搜索推荐 │  
133 - └──────────────────┘  
134 -```  
135 -  
136 -## 核心模块说明  
137 -  
138 -### 1. 配置模块  
139 -**文件**: `config/offline_config.py`  
140 -  
141 -**职责**:  
142 -- 数据库连接配置  
143 -- Redis连接配置  
144 -- 算法超参数配置  
145 -- 行为权重配置  
146 -- 时间范围配置  
147 -  
148 -### 2. i2i相似度模块  
149 -  
150 -#### 2.1 Swing算法  
151 -**文件**: `scripts/i2i_swing.py`  
152 -  
153 -**输入**: 用户行为数据(user_id, item_id, event_type, create_time)  
154 -  
155 -**核心逻辑**:  
156 -```python  
157 -# 对于物品i和j,计算它们的Swing相似度  
158 -for user_u in common_users:  
159 - for user_v in common_users:  
160 - common_items = items_u ∩ items_v  
161 - sim(i, j) += 1 / (alpha + |common_items|)  
162 -```  
163 -  
164 -**输出**: `i2i_swing_YYYYMMDD.txt`  
165 -```  
166 -item_id \t item_name \t similar_item_id1:score1,similar_item_id2:score2,...  
167 -```  
168 -  
169 -#### 2.2 Session Word2Vec  
170 -**文件**: `scripts/i2i_session_w2v.py`  
171 -  
172 -**输入**: 用户会话序列  
173 -  
174 -**核心逻辑**:  
175 -1. 按时间间隔切分用户会话  
176 -2. 训练Word2Vec模型  
177 -3. 计算物品向量相似度  
178 -  
179 -**输出**:  
180 -- `i2i_session_w2v_YYYYMMDD.txt`  
181 -- `session_w2v_model_YYYYMMDD.model`  
182 -  
183 -#### 2.3 DeepWalk  
184 -**文件**: `scripts/i2i_deepwalk.py`  
185 -  
186 -**输入**: 用户-物品交互数据  
187 -  
188 -**核心逻辑**:  
189 -1. 构建物品共现图  
190 -2. 执行随机游走生成序列  
191 -3. 训练Word2Vec模型  
192 -4. 计算物品向量相似度  
193 -  
194 -**输出**:  
195 -- `i2i_deepwalk_YYYYMMDD.txt`  
196 -- `deepwalk_model_YYYYMMDD.model`  
197 -- `item_graph_YYYYMMDD.txt`  
198 -  
199 -### 3. 兴趣点聚合模块  
200 -**文件**: `scripts/interest_aggregation.py`  
201 -  
202 -**输入**: 用户行为数据 + 用户特征  
203 -  
204 -**核心逻辑**:  
205 -```python  
206 -# 按维度聚合  
207 -for each behavior:  
208 - weight = behavior_weight * time_weight  
209 - aggregations[dimension_key][item_id] += weight  
210 -  
211 -# 排序并输出top N  
212 -for dimension_key, items in aggregations:  
213 - output top_n items sorted by weight  
214 -```  
215 -  
216 -**维度组合**:  
217 -- 单维度: platform, country, customer_type, category_level2, category_level3  
218 -- 组合维度: platform_country, platform_customer, country_customer, platform_country_customer  
219 -  
220 -**列表类型**:  
221 -- hot: 最近180天高交互  
222 -- cart: 加购行为  
223 -- new: 新品(最近90天上架)  
224 -- global: 全局(所有数据)  
225 -  
226 -**输出**:  
227 -- `interest_aggregation_hot_YYYYMMDD.txt`  
228 -- `interest_aggregation_cart_YYYYMMDD.txt`  
229 -- `interest_aggregation_new_YYYYMMDD.txt`  
230 -- `interest_aggregation_global_YYYYMMDD.txt`  
231 -  
232 -### 4. Redis加载模块  
233 -**文件**: `scripts/load_index_to_redis.py`  
234 -  
235 -**职责**: 将生成的索引文件加载到Redis  
236 -  
237 -**Redis Key格式**:  
238 -- i2i索引: `i2i:{algorithm}:{item_id}`  
239 -- 兴趣点索引: `interest:{list_type}:{dimension_key}`  
240 -  
241 -**示例**:  
242 -```  
243 -i2i:swing:123456 -> "234567:0.8523,345678:0.7842,..."  
244 -interest:hot:platform:PC -> "12345:98.52,23456:87.34,..."  
245 -```  
246 -  
247 -### 5. 统一调度模块  
248 -**文件**: `run_all.py`  
249 -  
250 -**职责**: 按顺序运行所有离线任务  
251 -  
252 -**执行流程**:  
253 -1. 运行Swing算法  
254 -2. 运行Session W2V  
255 -3. 运行DeepWalk  
256 -4. 运行兴趣点聚合  
257 -5. 记录日志和统计  
258 -  
259 -## 使用场景映射  
260 -  
261 -| 业务场景 | 使用的索引 | Redis Key示例 |  
262 -|---------|-----------|--------------|  
263 -| 详情页 - 大家都在看 | i2i相似度 | `i2i:swing:{item_id}` |  
264 -| 首页 - 猜你喜欢 | 兴趣点聚合 | `interest:hot:platform_country:{platform}_{country}` |  
265 -| 搜索 - 相关推荐 | 兴趣点聚合 + i2i | `interest:global:category_level2:{cat_id}` |  
266 -| 购物车 - 可能喜欢 | 兴趣点聚合(cart) | `interest:cart:customer_type:{type}` |  
267 -| 新品推荐 | 兴趣点聚合(new) | `interest:new:platform:{platform}` |  
268 -  
269 -## 配置调优参数  
270 -  
271 -### 时间相关  
272 -- `LOOKBACK_DAYS`: 730 (2年)  
273 -- `RECENT_DAYS`: 180 (热门商品统计)  
274 -- `NEW_DAYS`: 90 (新品定义)  
275 -- `decay_factor`: 0.95 (时间衰减)  
276 -  
277 -### 算法相关  
278 -- Swing `alpha`: 0.5  
279 -- W2V `vector_size`: 128  
280 -- W2V `window_size`: 5  
281 -- DeepWalk `num_walks`: 10  
282 -- DeepWalk `walk_length`: 40  
283 -  
284 -### 输出相关  
285 -- i2i `top_n`: 50  
286 -- 兴趣点 `top_n`: 1000  
287 -  
288 -## 性能优化要点  
289 -  
290 -1. **Swing算法**: 使用C++版本可提升10倍性能  
291 -2. **并行化**: 将不同算法分配到不同机器  
292 -3. **增量更新**: 只更新变化的部分  
293 -4. **数据采样**: 调试时使用采样数据  
294 -5. **批量加载**: Redis使用pipeline批量加载  
295 -  
296 -## 监控指标  
297 -  
298 -- 任务执行时间  
299 -- 生成索引数量  
300 -- Redis内存占用  
301 -- 推荐点击率  
302 -- 推荐转化率  
303 -  
offline_tasks/UPDATE_CONFIG_GUIDE.md deleted
@@ -1,205 +0,0 @@ @@ -1,205 +0,0 @@
1 -# 配置参数调整指南  
2 -  
3 -## 📝 概述  
4 -  
5 -所有默认参数现在都集中在配置文件中,便于统一管理和调整。  
6 -  
7 -## 🎯 主要默认参数  
8 -  
9 -### 在 `config/offline_config.py` 中配置:  
10 -  
11 -```python  
12 -# 时间配置  
13 -DEFAULT_LOOKBACK_DAYS = 30 # 默认回看天数  
14 -DEFAULT_RECENT_DAYS = 7 # 默认最近天数  
15 -  
16 -# i2i算法参数  
17 -DEFAULT_I2I_TOP_N = 50 # 默认返回Top N个相似商品  
18 -  
19 -# 兴趣聚合参数  
20 -DEFAULT_INTEREST_TOP_N = 1000 # 默认每个key返回Top N个商品  
21 -```  
22 -  
23 -## 🔧 调试与生产切换  
24 -  
25 -### 调试阶段(当前配置)  
26 -  
27 -```python  
28 -DEFAULT_LOOKBACK_DAYS = 30 # 30天数据,快速验证  
29 -DEFAULT_RECENT_DAYS = 7 # 7天最近数据  
30 -DEFAULT_I2I_TOP_N = 50 # Top 50  
31 -DEFAULT_INTEREST_TOP_N = 1000 # Top 1000  
32 -```  
33 -  
34 -**预估运行时间**:30-60分钟  
35 -**内存占用**:2-4GB  
36 -  
37 -### 生产环境配置  
38 -  
39 -```python  
40 -DEFAULT_LOOKBACK_DAYS = 730 # 2年历史数据,更准确  
41 -DEFAULT_RECENT_DAYS = 180 # 半年最近数据  
42 -DEFAULT_I2I_TOP_N = 50 # Top 50  
43 -DEFAULT_INTEREST_TOP_N = 1000 # Top 1000  
44 -```  
45 -  
46 -**预估运行时间**:6-10小时  
47 -**内存占用**:8-16GB  
48 -  
49 -## 🚀 使用方式  
50 -  
51 -### 1. 使用默认配置运行  
52 -  
53 -```bash  
54 -# 使用配置文件中的默认值(当前为30天)  
55 -python3 run_all.py  
56 -```  
57 -  
58 -### 2. 临时覆盖默认值  
59 -  
60 -```bash  
61 -# 临时使用不同的参数,不修改配置文件  
62 -python3 run_all.py --lookback_days 7 --top_n 20  
63 -```  
64 -  
65 -### 3. 修改配置文件(推荐)  
66 -  
67 -编辑 `config/offline_config.py`:  
68 -  
69 -```python  
70 -# 调试完成后,改为生产配置  
71 -DEFAULT_LOOKBACK_DAYS = 730  
72 -DEFAULT_RECENT_DAYS = 180  
73 -```  
74 -  
75 -然后运行:  
76 -  
77 -```bash  
78 -python3 run_all.py  
79 -```  
80 -  
81 -## 📊 各脚本的默认参数  
82 -  
83 -所有脚本都会从配置文件读取默认值:  
84 -  
85 -| 脚本 | 参数 | 默认值 | 来源 |  
86 -|------|------|--------|------|  
87 -| `i2i_swing.py` | `--lookback_days` | 30 | `DEFAULT_LOOKBACK_DAYS` |  
88 -| `i2i_swing.py` | `--top_n` | 50 | `DEFAULT_I2I_TOP_N` |  
89 -| `i2i_session_w2v.py` | `--lookback_days` | 30 | `DEFAULT_LOOKBACK_DAYS` |  
90 -| `i2i_session_w2v.py` | `--top_n` | 50 | `DEFAULT_I2I_TOP_N` |  
91 -| `i2i_deepwalk.py` | `--lookback_days` | 30 | `DEFAULT_LOOKBACK_DAYS` |  
92 -| `i2i_deepwalk.py` | `--top_n` | 50 | `DEFAULT_I2I_TOP_N` |  
93 -| `i2i_content_similar.py` | `--top_n` | 50 | `DEFAULT_I2I_TOP_N` |  
94 -| `interest_aggregation.py` | `--lookback_days` | 30 | `DEFAULT_LOOKBACK_DAYS` |  
95 -| `interest_aggregation.py` | `--top_n` | 1000 | `DEFAULT_INTEREST_TOP_N` |  
96 -  
97 -## 💡 调试建议  
98 -  
99 -### 第一次运行(验证流程)  
100 -  
101 -```bash  
102 -# 使用最小数据量快速验证  
103 -python3 run_all.py --lookback_days 7 --top_n 10  
104 -```  
105 -  
106 -### 第二次运行(调试参数)  
107 -  
108 -```python  
109 -# 修改配置文件为30天  
110 -DEFAULT_LOOKBACK_DAYS = 30  
111 -```  
112 -  
113 -```bash  
114 -python3 run_all.py  
115 -```  
116 -  
117 -### 第三次运行(生产环境)  
118 -  
119 -```python  
120 -# 修改配置文件为730天  
121 -DEFAULT_LOOKBACK_DAYS = 730  
122 -DEFAULT_RECENT_DAYS = 180  
123 -```  
124 -  
125 -```bash  
126 -python3 run_all.py  
127 -```  
128 -  
129 -## 🔍 其他可调整的配置  
130 -  
131 -### i2i算法详细配置  
132 -  
133 -在 `offline_config.py` 的 `I2I_CONFIG` 中:  
134 -  
135 -```python  
136 -I2I_CONFIG = {  
137 - 'swing': {  
138 - 'alpha': 0.5, # swing算法的alpha参数  
139 - 'threshold1': 0.5, # 交互强度阈值1  
140 - 'threshold2': 0.5, # 交互强度阈值2  
141 - 'max_sim_list_len': 300, # 最大相似列表长度  
142 - 'top_n': 50, # 输出top N个相似商品  
143 - },  
144 - # ...其他算法配置  
145 -}  
146 -```  
147 -  
148 -### 兴趣聚合详细配置  
149 -  
150 -```python  
151 -INTEREST_AGGREGATION_CONFIG = {  
152 - 'top_n': 1000, # 每个key生成前N个商品  
153 - 'time_decay_factor': 0.95, # 时间衰减因子(每30天)  
154 - 'min_interaction_count': 2, # 最小交互次数  
155 -  
156 - 'behavior_weights': {  
157 - 'click': 1.0,  
158 - 'addToCart': 3.0,  
159 - 'addToPool': 2.0,  
160 - 'contactFactory': 5.0,  
161 - 'purchase': 10.0,  
162 - },  
163 -}  
164 -```  
165 -  
166 -## 📌 注意事项  
167 -  
168 -1. **调试优先**:先用小数据量(7-30天)验证流程  
169 -2. **逐步扩大**:确认无误后再增加到生产数据量  
170 -3. **监控资源**:注意内存和磁盘空间使用情况  
171 -4. **保存配置**:在配置文件中注释记录不同场景的参数值  
172 -  
173 -## 🎯 快速切换环境  
174 -  
175 -创建不同的配置副本:  
176 -  
177 -```bash  
178 -# 备份当前配置  
179 -cp config/offline_config.py config/offline_config_debug.py  
180 -cp config/offline_config.py config/offline_config_prod.py  
181 -  
182 -# 使用不同配置  
183 -cp config/offline_config_debug.py config/offline_config.py # 调试模式  
184 -cp config/offline_config_prod.py config/offline_config.py # 生产模式  
185 -```  
186 -  
187 -## ✅ 验证配置  
188 -  
189 -查看当前默认值:  
190 -  
191 -```bash  
192 -python3 -c "from config.offline_config import *; print(f'LOOKBACK_DAYS: {DEFAULT_LOOKBACK_DAYS}')"  
193 -```  
194 -  
195 -查看帮助信息:  
196 -  
197 -```bash  
198 -python3 run_all.py --help  
199 -```  
200 -  
201 ----  
202 -  
203 -**配置文件位置**: `config/offline_config.py`  
204 -**当前默认配置**: 30天调试模式  
205 -**建议**: 调试通过后修改为730天生产模式  
offline_tasks/config/offline_config.py
@@ -28,7 +28,7 @@ os.makedirs(LOG_DIR, exist_ok=True) @@ -28,7 +28,7 @@ os.makedirs(LOG_DIR, exist_ok=True)
28 # ============================================================================ 28 # ============================================================================
29 29
30 # 时间配置(建议先用小数值调试,确认无误后再改为大数值) 30 # 时间配置(建议先用小数值调试,确认无误后再改为大数值)
31 -DEFAULT_LOOKBACK_DAYS = 730 # 默认回看天数(调试用30天,生产可改为730天) 31 +DEFAULT_LOOKBACK_DAYS = 400 # 默认回看天数(调试用30天,生产可改为730天)
32 DEFAULT_RECENT_DAYS = 180 # 默认最近天数(调试用7天,生产可改为180天) 32 DEFAULT_RECENT_DAYS = 180 # 默认最近天数(调试用7天,生产可改为180天)
33 33
34 # i2i算法默认参数 34 # i2i算法默认参数
offline_tasks/COMPLETE_INDEX_LIST.md renamed to offline_tasks/doc/COMPLETE_INDEX_LIST.md
offline_tasks/DATABASE_SETUP.md renamed to offline_tasks/doc/DATABASE_SETUP.md
offline_tasks/DEBUG_GUIDE.md renamed to offline_tasks/doc/DEBUG_GUIDE.md
offline_tasks/OFFLINE_INDEX_SPEC.md renamed to offline_tasks/doc/OFFLINE_INDEX_SPEC.md
offline_tasks/doc/README.md 0 → 100644
@@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
  1 +# 推荐系统离线任务文档中心
  2 +
  3 +本目录包含推荐系统所有重要文档。
  4 +
  5 +## 📚 文档目录
  6 +
  7 +### 快速开始
  8 +
  9 +- **[从这里开始.md](./从这里开始.md)** - 新手入门指南,了解项目结构和基本概念
  10 +- **[快速开始.md](./快速开始.md)** - 快速运行离线任务的步骤
  11 +- **[Swing快速开始.md](../collaboration/Swing快速开始.md)** - C++ Swing算法快速使用指南
  12 +
  13 +### 使用指南
  14 +
  15 +- **[Swing算法使用指南.md](./Swing算法使用指南.md)** - 详细的Swing算法使用文档
  16 +- **[运行脚本指南.md](./运行脚本指南.md)** - 所有离线任务脚本的使用说明
  17 +- **[调试指南.md](./调试指南.md)** - Debug模式和日志使用说明
  18 +
  19 +### 数据规范
  20 +
  21 +- **[离线索引数据规范.md](./离线索引数据规范.md)** - 所有离线索引的格式和说明
  22 +- **[Redis数据规范.md](./Redis数据规范.md)** - Redis中数据的key格式和结构
  23 +- **[完整索引列表.md](./完整索引列表.md)** - 系统中所有索引的完整清单
  24 +
  25 +### 配置说明
  26 +
  27 +- **[数据库配置说明.md](./数据库配置说明.md)** - 数据库连接和表结构说明
  28 +- **配置文件**: `../config/offline_config.py` - 所有可配置参数
  29 +
  30 +### 实现总结
  31 +
  32 +- **[Swing实现总结.md](./Swing实现总结.md)** - C++ Swing集成实现的完整说明
  33 +
  34 +### 维护文档
  35 +
  36 +- **[故障排查指南.md](./故障排查指南.md)** - 常见问题和解决方案
  37 +- **[更新日志.md](./更新日志.md)** - 系统更新历史
  38 +
  39 +## 📂 相关文档
  40 +
  41 +### 其他模块文档
  42 +
  43 +- **Collaboration模块**: `../collaboration/README.md` - C++ 协同过滤算法
  44 +- **GraphEmbedding模块**:
  45 + - Session W2V: `../graphembedding/session_w2v/README.md`
  46 + - DeepWalk: `../graphembedding/deepwalk/README.md`
  47 +- **Hot模块**: `../hot/README.md` - 热门商品推荐
  48 +
  49 +### 项目README
  50 +
  51 +- **项目根目录**: `../../README.md` - 项目总览
  52 +- **离线任务**: `../README.md` - 离线任务模块说明
  53 +
  54 +## 🎯 文档使用建议
  55 +
  56 +### 新用户
  57 +
  58 +1. 先阅读 **[从这里开始.md](./从这里开始.md)** 了解整体架构
  59 +2. 然后看 **[快速开始.md](./快速开始.md)** 快速运行系统
  60 +3. 需要时查阅具体的使用指南和数据规范
  61 +
  62 +### 开发人员
  63 +
  64 +1. 查看 **[运行脚本指南.md](./运行脚本指南.md)** 了解所有脚本
  65 +2. 参考 **[调试指南.md](./调试指南.md)** 进行调试
  66 +3. 遵循 **数据规范** 文档进行开发
  67 +
  68 +### 运维人员
  69 +
  70 +1. 配置前先看 **[数据库配置说明.md](./数据库配置说明.md)**
  71 +2. 遇到问题查看 **[故障排查指南.md](./故障排查指南.md)**
  72 +3. 了解 **[Redis数据规范.md](./Redis数据规范.md)** 便于维护
  73 +
  74 +## 📝 文档更新
  75 +
  76 +所有文档由项目维护者更新。如有疑问或发现错误,请联系团队。
  77 +
  78 +**最后更新**: 2024-10-17
  79 +
offline_tasks/REDIS_DATA_SPEC.md renamed to offline_tasks/doc/REDIS_DATA_SPEC.md
offline_tasks/RUN_SCRIPT_GUIDE.md renamed to offline_tasks/doc/RUN_SCRIPT_GUIDE.md
offline_tasks/doc/Redis数据规范.md 0 → 100644
@@ -0,0 +1,306 @@ @@ -0,0 +1,306 @@
  1 +# Redis数据灌入规范
  2 +
  3 +## 📋 数据灌入概述
  4 +
  5 +将离线生成的推荐索引加载到Redis,供在线系统实时查询使用。
  6 +
  7 +## 🔑 Redis Key规范
  8 +
  9 +### 通用规则
  10 +```
  11 +{namespace}:{function}:{algorithm}:{identifier}
  12 +```
  13 +
  14 +- `namespace`: 业务命名空间(item, user, interest等)
  15 +- `function`: 功能类型(similar, feature, hot等)
  16 +- `algorithm`: 算法名称(swing, w2v, deepwalk等)
  17 +- `identifier`: 具体标识(item_id, dimension_key等)
  18 +
  19 +## 📊 数据灌入规范表
  20 +
  21 +| 模块名称 | 源数据地址 | 格式描述 | RedisKey模板 | RedisValue格式 | TTL |
  22 +|---------|-----------|---------|-------------|---------------|-----|
  23 +| **i2i_swing** | `output/i2i_swing_YYYYMMDD.txt` | `item_id\titem_name\tsimilar_id1:score1,...` | `item:similar:swing:{item_id}` | `[[similar_id1,score1],[similar_id2,score2],...]` | 7天 |
  24 +| **i2i_session_w2v** | `output/i2i_session_w2v_YYYYMMDD.txt` | `item_id\titem_name\tsimilar_id1:score1,...` | `item:similar:w2v:{item_id}` | `[[similar_id1,score1],[similar_id2,score2],...]` | 7天 |
  25 +| **i2i_deepwalk** | `output/i2i_deepwalk_YYYYMMDD.txt` | `item_id\titem_name\tsimilar_id1:score1,...` | `item:similar:deepwalk:{item_id}` | `[[similar_id1,score1],[similar_id2,score2],...]` | 7天 |
  26 +| **i2i_content_name** | `output/i2i_content_name_YYYYMMDD.txt` | `item_id\titem_name\tsimilar_id1:score1,...` | `item:similar:content_name:{item_id}` | `[[similar_id1,score1],[similar_id2,score2],...]` | 30天 |
  27 +| **i2i_content_pic** | `output/i2i_content_pic_YYYYMMDD.txt` | `item_id\titem_name\tsimilar_id1:score1,...` | `item:similar:content_pic:{item_id}` | `[[similar_id1,score1],[similar_id2,score2],...]` | 30天 |
  28 +| **interest_hot** | `output/interest_aggregation_hot_YYYYMMDD.txt` | `dimension_key\titem_id1,item_id2,...` | `interest:hot:{dimension_key}` | `[item_id1,item_id2,item_id3,...]` | 3天 |
  29 +| **interest_cart** | `output/interest_aggregation_cart_YYYYMMDD.txt` | `dimension_key\titem_id1,item_id2,...` | `interest:cart:{dimension_key}` | `[item_id1,item_id2,item_id3,...]` | 3天 |
  30 +| **interest_new** | `output/interest_aggregation_new_YYYYMMDD.txt` | `dimension_key\titem_id1,item_id2,...` | `interest:new:{dimension_key}` | `[item_id1,item_id2,item_id3,...]` | 3天 |
  31 +| **interest_global** | `output/interest_aggregation_global_YYYYMMDD.txt` | `dimension_key\titem_id1,item_id2,...` | `interest:global:{dimension_key}` | `[item_id1,item_id2,item_id3,...]` | 7天 |
  32 +
  33 +## 📝 详细说明
  34 +
  35 +### 1. i2i相似度索引
  36 +
  37 +#### 源数据格式
  38 +```
  39 +12345 香蕉干 67890:0.8567,11223:0.7234,44556:0.6891
  40 +```
  41 +
  42 +#### Redis存储
  43 +
  44 +**Key**: `item:similar:swing:12345`
  45 +
  46 +**Value** (JSON格式):
  47 +```json
  48 +[[67890, 0.8567], [11223, 0.7234], [44556, 0.6891]]
  49 +```
  50 +
  51 +**Value** (序列化后):
  52 +```python
  53 +import json
  54 +value = json.dumps([[67890, 0.8567], [11223, 0.7234], [44556, 0.6891]])
  55 +# 存储: "[[67890,0.8567],[11223,0.7234],[44556,0.6891]]"
  56 +```
  57 +
  58 +#### 查询示例
  59 +```python
  60 +import redis
  61 +import json
  62 +
  63 +r = redis.Redis(host='localhost', port=6379, db=0)
  64 +
  65 +# 获取商品12345的相似商品(Swing算法)
  66 +similar_items = json.loads(r.get('item:similar:swing:12345'))
  67 +# 返回: [[67890, 0.8567], [11223, 0.7234], [44556, 0.6891]]
  68 +
  69 +# 获取Top5相似商品
  70 +top_5 = similar_items[:5]
  71 +```
  72 +
  73 +### 2. 兴趣点聚合索引
  74 +
  75 +#### 源数据格式
  76 +```
  77 +platform:pc 12345,67890,11223,44556,22334
  78 +category_level2:200 67890,12345,22334,55667,11223
  79 +```
  80 +
  81 +#### Redis存储
  82 +
  83 +**Key**: `interest:hot:platform:pc`
  84 +
  85 +**Value** (JSON格式):
  86 +```json
  87 +[12345, 67890, 11223, 44556, 22334]
  88 +```
  89 +
  90 +**Value** (序列化后):
  91 +```python
  92 +import json
  93 +value = json.dumps([12345, 67890, 11223, 44556, 22334])
  94 +# 存储: "[12345,67890,11223,44556,22334]"
  95 +```
  96 +
  97 +#### 查询示例
  98 +```python
  99 +import redis
  100 +import json
  101 +
  102 +r = redis.Redis(host='localhost', port=6379, db=0)
  103 +
  104 +# 获取PC平台的热门商品
  105 +hot_items = json.loads(r.get('interest:hot:platform:pc'))
  106 +# 返回: [12345, 67890, 11223, 44556, 22334]
  107 +
  108 +# 获取Top10热门商品
  109 +top_10 = hot_items[:10]
  110 +```
  111 +
  112 +## 🔄 数据加载流程
  113 +
  114 +### 1. 加载i2i索引
  115 +
  116 +```python
  117 +def load_i2i_index(file_path, algorithm_name, redis_client, expire_seconds=604800):
  118 + """
  119 + 加载i2i相似度索引到Redis
  120 +
  121 + Args:
  122 + file_path: 索引文件路径
  123 + algorithm_name: 算法名称(swing, w2v, deepwalk, content)
  124 + redis_client: Redis客户端
  125 + expire_seconds: 过期时间(秒),默认7天
  126 + """
  127 + import json
  128 +
  129 + count = 0
  130 + with open(file_path, 'r', encoding='utf-8') as f:
  131 + for line in f:
  132 + parts = line.strip().split('\t')
  133 + if len(parts) < 3:
  134 + continue
  135 +
  136 + item_id = parts[0]
  137 + similar_str = parts[2] # similar_id1:score1,similar_id2:score2,...
  138 +
  139 + # 解析相似商品
  140 + similar_items = []
  141 + for pair in similar_str.split(','):
  142 + if ':' in pair:
  143 + sim_id, score = pair.split(':')
  144 + similar_items.append([int(sim_id), float(score)])
  145 +
  146 + # 存储到Redis
  147 + redis_key = f"item:similar:{algorithm_name}:{item_id}"
  148 + redis_value = json.dumps(similar_items)
  149 +
  150 + redis_client.set(redis_key, redis_value)
  151 + redis_client.expire(redis_key, expire_seconds)
  152 +
  153 + count += 1
  154 +
  155 + return count
  156 +```
  157 +
  158 +### 2. 加载兴趣聚合索引
  159 +
  160 +```python
  161 +def load_interest_index(file_path, list_type, redis_client, expire_seconds=259200):
  162 + """
  163 + 加载兴趣点聚合索引到Redis
  164 +
  165 + Args:
  166 + file_path: 索引文件路径
  167 + list_type: 列表类型(hot, cart, new, global)
  168 + redis_client: Redis客户端
  169 + expire_seconds: 过期时间(秒),默认3天
  170 + """
  171 + import json
  172 +
  173 + count = 0
  174 + with open(file_path, 'r', encoding='utf-8') as f:
  175 + for line in f:
  176 + parts = line.strip().split('\t')
  177 + if len(parts) != 2:
  178 + continue
  179 +
  180 + dimension_key = parts[0] # platform:pc
  181 + item_ids_str = parts[1] # 12345,67890,11223,...
  182 +
  183 + # 解析商品ID列表
  184 + item_ids = [int(item_id) for item_id in item_ids_str.split(',')]
  185 +
  186 + # 存储到Redis
  187 + redis_key = f"interest:{list_type}:{dimension_key}"
  188 + redis_value = json.dumps(item_ids)
  189 +
  190 + redis_client.set(redis_key, redis_value)
  191 + redis_client.expire(redis_key, expire_seconds)
  192 +
  193 + count += 1
  194 +
  195 + return count
  196 +```
  197 +
  198 +## 🚀 快速加载命令
  199 +
  200 +### 加载所有索引
  201 +```bash
  202 +cd /home/tw/recommendation/offline_tasks
  203 +
  204 +# 加载所有索引(使用今天的数据)
  205 +python3 scripts/load_index_to_redis.py --redis-host localhost --redis-port 6379
  206 +
  207 +# 加载指定日期的索引
  208 +python3 scripts/load_index_to_redis.py --date 20251016 --redis-host localhost
  209 +
  210 +# 只加载i2i索引
  211 +python3 scripts/load_index_to_redis.py --load-i2i --redis-host localhost
  212 +
  213 +# 只加载兴趣聚合索引
  214 +python3 scripts/load_index_to_redis.py --load-interest --redis-host localhost
  215 +```
  216 +
  217 +### 验证数据
  218 +```bash
  219 +# 连接Redis
  220 +redis-cli
  221 +
  222 +# 检查key数量
  223 +DBSIZE
  224 +
  225 +# 查看某个商品的相似推荐
  226 +GET item:similar:swing:12345
  227 +
  228 +# 查看平台热门商品
  229 +GET interest:hot:platform:pc
  230 +
  231 +# 查看所有i2i相关的key
  232 +KEYS item:similar:*
  233 +
  234 +# 查看所有interest相关的key
  235 +KEYS interest:*
  236 +
  237 +# 检查key的过期时间
  238 +TTL item:similar:swing:12345
  239 +```
  240 +
  241 +## 📊 数据统计
  242 +
  243 +### Redis内存占用估算
  244 +
  245 +| 索引类型 | Key数量 | 单条Value大小 | 总内存 |
  246 +|---------|--------|-------------|--------|
  247 +| i2i_swing | 50,000 | ~500B | ~25MB |
  248 +| i2i_w2v | 50,000 | ~500B | ~25MB |
  249 +| i2i_deepwalk | 50,000 | ~500B | ~25MB |
  250 +| i2i_content_name | 50,000 | ~500B | ~25MB |
  251 +| i2i_content_pic | 50,000 | ~500B | ~25MB |
  252 +| interest_hot | 10,000 | ~1KB | ~10MB |
  253 +| interest_cart | 10,000 | ~1KB | ~10MB |
  254 +| interest_new | 5,000 | ~1KB | ~5MB |
  255 +| interest_global | 10,000 | ~1KB | ~10MB |
  256 +| **总计** | **270,000** | - | **~160MB** |
  257 +
  258 +### 过期策略
  259 +
  260 +| 索引类型 | TTL | 原因 |
  261 +|---------|-----|------|
  262 +| i2i行为相似 | 7天 | 用户行为变化快,需要频繁更新 |
  263 +| i2i内容相似 | 30天 | 商品属性变化慢,可以保留更久 |
  264 +| 热门/加购 | 3天 | 热度变化快,需要及时更新 |
  265 +| 新品 | 3天 | 新品概念有时效性 |
  266 +| 全局热门 | 7天 | 相对稳定,可以保留更久 |
  267 +
  268 +## ⚠️ 注意事项
  269 +
  270 +1. **原子性**: 使用Pipeline批量写入,提高性能
  271 +2. **过期时间**: 合理设置TTL,避免过期数据
  272 +3. **内存管理**: 定期清理过期key,监控内存使用
  273 +4. **数据版本**: 使用日期标记,支持数据回滚
  274 +5. **容错处理**: 加载失败时不影响线上服务
  275 +6. **监控告警**: 监控加载成功率、Redis内存、查询延迟
  276 +
  277 +## 🔍 监控指标
  278 +
  279 +### 数据质量指标
  280 +```python
  281 +# 检查加载成功率
  282 +total_keys = redis_client.dbsize()
  283 +expected_keys = 245000
  284 +success_rate = total_keys / expected_keys * 100
  285 +
  286 +# 检查数据完整性
  287 +sample_keys = [
  288 + 'item:similar:swing:12345',
  289 + 'interest:hot:platform:pc'
  290 +]
  291 +for key in sample_keys:
  292 + if not redis_client.exists(key):
  293 + print(f"Missing key: {key}")
  294 +```
  295 +
  296 +### 性能指标
  297 +- 加载耗时: < 5分钟
  298 +- 内存占用: < 200MB
  299 +- 查询延迟: < 1ms
  300 +- 成功率: > 99%
  301 +
  302 +## 🔗 相关文档
  303 +
  304 +- **离线索引规范**: `OFFLINE_INDEX_SPEC.md`
  305 +- **API接口文档**: `RECOMMENDATION_API.md`
  306 +- **运维手册**: `OPERATIONS.md`
offline_tasks/SWING_USAGE.md renamed to offline_tasks/doc/SWING_USAGE.md
offline_tasks/doc/Swing实现总结.md 0 → 100644
@@ -0,0 +1,375 @@ @@ -0,0 +1,375 @@
  1 +# Swing算法实现总结
  2 +
  3 +## 完成的任务
  4 +
  5 +本次实现完成了以下功能:
  6 +
  7 +### 1. Session生成脚本 ✓
  8 +
  9 +**文件**: `offline_tasks/scripts/generate_session.py`
  10 +
  11 +**功能**:
  12 +- 从数据库提取用户行为数据
  13 +- 聚合用户session(按商品维度累加权重)
  14 +- 支持两种输出格式:
  15 + - 标准格式:`uid \t {"item_id":score,...}`
  16 + - C++格式:`{"item_id":score,...}` (每行一个用户)
  17 +
  18 +**主要参数**:
  19 +- `--lookback_days`: 回看天数(默认730天)
  20 +- `--format`: 输出格式(standard/cpp/both)
  21 +- `--output`: 输出文件路径
  22 +- `--debug`: 启用debug模式
  23 +
  24 +**使用示例**:
  25 +```bash
  26 +cd /home/tw/recommendation/offline_tasks
  27 +python3 scripts/generate_session.py --lookback_days 730 --format both
  28 +```
  29 +
  30 +### 2. Swing运行脚本 ✓
  31 +
  32 +**文件**: `collaboration/run.sh`
  33 +
  34 +**改进内容**:
  35 +- ✓ 适配新的数据路径(`../offline_tasks/output/`)
  36 +- ✓ 自动检测session文件格式(带uid或纯json)
  37 +- ✓ 增加配置区域,便于修改参数
  38 +- ✓ 添加错误检查和友好的输出信息
  39 +- ✓ 自动调用debug脚本生成可读文件
  40 +- ✓ 支持自定义Python环境
  41 +
  42 +**配置项**:
  43 +```bash
  44 +SESSION_DATA_DIR="../offline_tasks/output" # session文件目录
  45 +ALPHA=0.7 # Swing alpha参数
  46 +THRESHOLD1=1 # 交互强度阈值1
  47 +THRESHOLD2=3 # 交互强度阈值2
  48 +THREAD_NUM=4 # 线程数
  49 +SHOW_PROGRESS=1 # 显示进度
  50 +PYTHON_CMD="python3" # Python命令
  51 +```
  52 +
  53 +**执行流程**:
  54 +1. 编译C++程序
  55 +2. 查找session文件
  56 +3. 运行Swing算法(多线程)
  57 +4. 合并结果
  58 +5. 生成可读版本(自动调用debug脚本)
  59 +
  60 +### 3. Debug脚本 ✓
  61 +
  62 +**文件**: `offline_tasks/scripts/add_names_to_swing.py`
  63 +
  64 +**功能**:
  65 +- 读取Swing算法输出结果
  66 +- 从数据库获取商品名称映射
  67 +- 生成可读版本:`item_id:name \t similar_id1:name1:score1,...`
  68 +
  69 +**使用示例**:
  70 +```bash
  71 +cd /home/tw/recommendation/offline_tasks
  72 +python3 scripts/add_names_to_swing.py \
  73 + ../collaboration/output/swing_similar.txt \
  74 + ../collaboration/output/swing_similar_readable.txt \
  75 + --debug
  76 +```
  77 +
  78 +### 4. 使用文档 ✓
  79 +
  80 +**文件**:
  81 +- `offline_tasks/SWING_USAGE.md` - 完整使用指南
  82 +- `collaboration/QUICKSTART.md` - 快速开始指南
  83 +
  84 +**包含内容**:
  85 +- 详细的使用步骤
  86 +- 参数说明和调优建议
  87 +- 故障排查指南
  88 +- 性能优化建议
  89 +- 完整示例
  90 +
  91 +## 数据流程
  92 +
  93 +```
  94 +┌─────────────────────────────────────────────────────────────┐
  95 +│ 步骤1: 生成Session文件 │
  96 +│ generate_session.py │
  97 +│ ↓ │
  98 +│ 数据库 → 用户行为数据 → 聚合权重 → session.txt.YYYYMMDD │
  99 +└─────────────────────────────────────────────────────────────┘
  100 + ↓
  101 +┌─────────────────────────────────────────────────────────────┐
  102 +│ 步骤2: 运行Swing算法 │
  103 +│ collaboration/run.sh │
  104 +│ ↓ │
  105 +│ session文件 → C++ Swing → sim_matrx.* → swing_similar.txt │
  106 +└─────────────────────────────────────────────────────────────┘
  107 + ↓
  108 +┌─────────────────────────────────────────────────────────────┐
  109 +│ 步骤3: 生成Debug文件 │
  110 +│ add_names_to_swing.py (自动调用) │
  111 +│ ↓ │
  112 +│ swing_similar.txt → 添加商品名 → swing_similar_readable.txt│
  113 +└─────────────────────────────────────────────────────────────┘
  114 +```
  115 +
  116 +## 文件格式说明
  117 +
  118 +### Session文件格式
  119 +
  120 +**标准格式** (`session.txt.YYYYMMDD`):
  121 +```
  122 +user_id1 {"123":10.0,"456":5.0,"789":3.0}
  123 +user_id2 {"123":8.0,"999":12.0}
  124 +```
  125 +
  126 +**C++格式** (`session.txt.YYYYMMDD.cpp`):
  127 +```
  128 +{"123":10.0,"456":5.0,"789":3.0}
  129 +{"123":8.0,"999":12.0}
  130 +```
  131 +
  132 +### Swing结果格式
  133 +
  134 +**原始格式** (`swing_similar.txt`):
  135 +```
  136 +12345 67890:0.8523,23456:0.7234,34567:0.6891
  137 +```
  138 +
  139 +**可读格式** (`swing_similar_readable.txt`):
  140 +```
  141 +12345:iPhone 15 Pro 67890:iPhone 15:0.8523,23456:iPhone 14 Pro:0.7234
  142 +```
  143 +
  144 +## 行为权重配置
  145 +
  146 +当前配置(在`generate_session.py`中):
  147 +
  148 +| 行为类型 | 权重 | 说明 |
  149 +|---------|------|------|
  150 +| purchase | 10.0 | 购买行为(最强信号) |
  151 +| contactFactory | 5.0 | 联系厂家 |
  152 +| addToCart | 3.0 | 加入购物车 |
  153 +| addToPool | 2.0 | 加入询价池 |
  154 +
  155 +## 快速开始
  156 +
  157 +```bash
  158 +# 1. 生成session文件(730天数据)
  159 +cd /home/tw/recommendation/offline_tasks
  160 +python3 scripts/generate_session.py --lookback_days 730
  161 +
  162 +# 2. 运行Swing算法
  163 +cd /home/tw/recommendation/collaboration
  164 +bash run.sh
  165 +
  166 +# 3. 查看结果
  167 +cat output/swing_similar_readable.txt | head -20
  168 +```
  169 +
  170 +## 项目结构
  171 +
  172 +```
  173 +recommendation/
  174 +├── offline_tasks/
  175 +│ ├── scripts/
  176 +│ │ ├── generate_session.py # 新增:生成session
  177 +│ │ ├── add_names_to_swing.py # 新增:添加商品名
  178 +│ │ ├── i2i_swing.py # 已有:Python版Swing
  179 +│ │ └── debug_utils.py # 已有:Debug工具
  180 +│ ├── config/
  181 +│ │ └── offline_config.py # 配置文件
  182 +│ ├── output/
  183 +│ │ ├── session.txt.YYYYMMDD # 生成的session文件
  184 +│ │ └── session.txt.YYYYMMDD.cpp # C++格式session
  185 +│ ├── SWING_USAGE.md # 新增:详细使用文档
  186 +│ └── ...
  187 +├── collaboration/
  188 +│ ├── run.sh # 修改:适配新数据格式
  189 +│ ├── QUICKSTART.md # 新增:快速开始
  190 +│ ├── src/
  191 +│ │ ├── swing.cc # C++ Swing实现
  192 +│ │ ├── swing_symmetric.cc # 对称Swing
  193 +│ │ ├── icf_simple.cc # 简单协同过滤
  194 +│ │ └── ucf.py # 用户协同
  195 +│ ├── bin/ # 编译后的可执行文件
  196 +│ ├── output_YYYYMMDD/ # 输出目录
  197 +│ │ ├── sim_matrx.* # 多线程输出
  198 +│ │ ├── swing_similar.txt # 合并结果
  199 +│ │ └── swing_similar_readable.txt # 可读结果
  200 +│ └── output -> output_YYYYMMDD # 软链接
  201 +└── SWING_IMPLEMENTATION_SUMMARY.md # 本文档
  202 +```
  203 +
  204 +## 参数调优建议
  205 +
  206 +### 针对B2B低频场景
  207 +
  208 +```bash
  209 +# Session生成
  210 +--lookback_days 730 # 2年数据(B2B交互频次低)
  211 +
  212 +# Swing算法
  213 +ALPHA=0.5-0.7 # 关注用户共同行为的多样性
  214 +THRESHOLD1=1 # 低阈值,保留更多数据
  215 +THRESHOLD2=3 # 中等阈值,过滤噪音
  216 +THREAD_NUM=4-8 # 根据服务器配置
  217 +```
  218 +
  219 +### 针对大数据量场景
  220 +
  221 +```bash
  222 +# 增加线程数
  223 +THREAD_NUM=8
  224 +
  225 +# 修改C++代码参数
  226 +max_sim_list_len=300 # 相似列表长度
  227 +max_session_list_len=100 # session截断长度
  228 +```
  229 +
  230 +## 与现有系统集成
  231 +
  232 +### 1. 定时任务
  233 +
  234 +```bash
  235 +# 每天凌晨2点运行
  236 +0 2 * * * cd /home/tw/recommendation/offline_tasks && \
  237 + python3 scripts/generate_session.py && \
  238 + cd ../collaboration && bash run.sh
  239 +```
  240 +
  241 +### 2. 结果导入Redis
  242 +
  243 +可使用现有的 `load_index_to_redis.py` 脚本导入结果。
  244 +
  245 +### 3. 与Python版Swing对比
  246 +
  247 +- **C++版本**(本次实现):性能更好,适合大数据量
  248 +- **Python版本**(`i2i_swing.py`):易于调试,支持时间衰减
  249 +
  250 +可以运行两个版本对比效果:
  251 +```bash
  252 +# Python版本
  253 +python3 offline_tasks/scripts/i2i_swing.py --debug
  254 +
  255 +# C++版本
  256 +cd collaboration && bash run.sh
  257 +```
  258 +
  259 +## 测试验证
  260 +
  261 +### 1. 小数据量测试
  262 +
  263 +```bash
  264 +# 生成小范围数据(30天)
  265 +python3 scripts/generate_session.py --lookback_days 30
  266 +
  267 +# 运行Swing
  268 +cd ../collaboration
  269 +bash run.sh
  270 +```
  271 +
  272 +### 2. 查看结果质量
  273 +
  274 +```bash
  275 +# 查看可读版本前100行
  276 +head -100 output/swing_similar_readable.txt
  277 +
  278 +# 检查相似度分布
  279 +cat output/swing_similar.txt | awk -F'\t' '{print NF-1}' | sort -n | uniq -c
  280 +```
  281 +
  282 +### 3. 性能测试
  283 +
  284 +```bash
  285 +# 记录运行时间
  286 +time bash run.sh
  287 +```
  288 +
  289 +## 故障排查
  290 +
  291 +### 常见问题
  292 +
  293 +1. **Session文件不存在**
  294 + - 先运行 `generate_session.py`
  295 +
  296 +2. **编译失败**
  297 + - 检查g++版本:`g++ --version`
  298 + - 手动编译:`cd collaboration && make`
  299 +
  300 +3. **数据库连接失败**
  301 + - 检查配置:`offline_tasks/config/offline_config.py`
  302 + - 测试连接:`python3 offline_tasks/test_connection.py`
  303 +
  304 +4. **结果为空**
  305 + - 降低threshold参数
  306 + - 增加lookback_days
  307 + - 检查数据量:`wc -l output/session.txt.*`
  308 +
  309 +详细故障排查参见:`offline_tasks/SWING_USAGE.md`
  310 +
  311 +## 后续优化方向
  312 +
  313 +1. **性能优化**
  314 + - 支持分布式计算
  315 + - 增量更新机制
  316 + - 结果缓存
  317 +
  318 +2. **功能增强**
  319 + - 支持多种相似度算法
  320 + - 在线实时更新
  321 + - A/B测试框架
  322 +
  323 +3. **可观测性**
  324 + - 添加监控指标
  325 + - 结果质量评估
  326 + - 自动报警
  327 +
  328 +## 相关文档
  329 +
  330 +- **详细使用指南**: `offline_tasks/SWING_USAGE.md`
  331 +- **快速开始**: `collaboration/QUICKSTART.md`
  332 +- **配置说明**: `offline_tasks/config/offline_config.py`
  333 +- **Debug工具**: `offline_tasks/scripts/debug_utils.py`
  334 +- **Swing算法原理**: `collaboration/README.md`
  335 +
  336 +## 维护说明
  337 +
  338 +### 代码维护
  339 +
  340 +- **Session生成**: `offline_tasks/scripts/generate_session.py`
  341 +- **Swing执行**: `collaboration/run.sh`
  342 +- **Debug脚本**: `offline_tasks/scripts/add_names_to_swing.py`
  343 +
  344 +### 配置维护
  345 +
  346 +- **数据库配置**: `offline_tasks/config/offline_config.py`
  347 +- **行为权重**: `generate_session.py` 中的 `behavior_weights`
  348 +- **Swing参数**: `collaboration/run.sh` 中的配置区域
  349 +
  350 +### 日志查看
  351 +
  352 +```bash
  353 +# Session生成日志
  354 +ls offline_tasks/logs/debug/generate_session_*.log
  355 +
  356 +# Swing运行日志
  357 +ls collaboration/logs/
  358 +```
  359 +
  360 +## 总结
  361 +
  362 +本次实现完成了一套完整的C++ Swing算法工作流:
  363 +
  364 +1. ✓ **前置任务**:Session文件生成(`generate_session.py`)
  365 +2. ✓ **核心算法**:C++ Swing执行(改进的`run.sh`)
  366 +3. ✓ **后处理**:Debug文件生成(`add_names_to_swing.py`)
  367 +4. ✓ **文档完善**:详细使用指南和快速开始
  368 +
  369 +所有脚本都支持debug模式,便于调试和监控。整体流程自动化程度高,只需一条命令即可完成全流程。
  370 +
  371 +---
  372 +
  373 +**实现时间**: 2024-10-17
  374 +**状态**: ✅ 已完成
  375 +
offline_tasks/doc/Swing算法使用指南.md 0 → 100644
@@ -0,0 +1,322 @@ @@ -0,0 +1,322 @@
  1 +# Swing算法使用指南
  2 +
  3 +本文档介绍如何使用C++版本的Swing算法进行物品相似度计算。
  4 +
  5 +## 目录结构
  6 +
  7 +```
  8 +recommendation/
  9 +├── offline_tasks/
  10 +│ ├── scripts/
  11 +│ │ ├── generate_session.py # 生成用户session文件
  12 +│ │ └── add_names_to_swing.py # 给结果添加商品名称
  13 +│ └── output/
  14 +│ └── session.txt.YYYYMMDD # 生成的session文件
  15 +└── collaboration/
  16 + ├── run.sh # Swing算法执行脚本
  17 + ├── src/
  18 + │ ├── swing.cc # Swing算法实现
  19 + │ └── ucf.py # 用户协同过滤
  20 + └── output_YYYYMMDD/
  21 + ├── swing_similar.txt # Swing结果(ID格式)
  22 + └── swing_similar_readable.txt # Swing结果(带商品名)
  23 +```
  24 +
  25 +## 使用流程
  26 +
  27 +### 步骤1: 生成Session文件
  28 +
  29 +首先需要从数据库提取用户行为数据,生成session文件。
  30 +
  31 +```bash
  32 +cd /home/tw/recommendation/offline_tasks
  33 +
  34 +# 基本用法(使用默认参数:730天数据)
  35 +python3 scripts/generate_session.py
  36 +
  37 +# 指定回看天数
  38 +python3 scripts/generate_session.py --lookback_days 365
  39 +
  40 +# 启用debug模式查看详细信息
  41 +python3 scripts/generate_session.py --lookback_days 730 --debug
  42 +
  43 +# 指定输出文件路径
  44 +python3 scripts/generate_session.py --output output/session.txt.20241017
  45 +
  46 +# 选择输出格式
  47 +python3 scripts/generate_session.py --format both # 同时生成两种格式(默认)
  48 +python3 scripts/generate_session.py --format standard # uid \t json 格式
  49 +python3 scripts/generate_session.py --format cpp # 纯json格式(.cpp后缀)
  50 +```
  51 +
  52 +**输出文件格式:**
  53 +
  54 +- `session.txt.YYYYMMDD` - 标准格式(包含uid):
  55 + ```
  56 + uid1 \t {"item_id1":10.0,"item_id2":5.0,"item_id3":3.0}
  57 + uid2 \t {"item_id4":15.0,"item_id5":8.0}
  58 + ```
  59 +
  60 +- `session.txt.YYYYMMDD.cpp` - C++格式(纯json):
  61 + ```
  62 + {"item_id1":10.0,"item_id2":5.0,"item_id3":3.0}
  63 + {"item_id4":15.0,"item_id5":8.0}
  64 + ```
  65 +
  66 +**行为权重配置:**
  67 +- `purchase`: 10.0(购买)
  68 +- `contactFactory`: 5.0(联系厂家)
  69 +- `addToCart`: 3.0(加入购物车)
  70 +- `addToPool`: 2.0(加入询价池)
  71 +
  72 +### 步骤2: 运行Swing算法
  73 +
  74 +session文件生成后,运行C++版本的Swing算法。
  75 +
  76 +```bash
  77 +cd /home/tw/recommendation/collaboration
  78 +
  79 +# 直接运行(使用默认配置)
  80 +bash run.sh
  81 +
  82 +# 或者给脚本添加执行权限后运行
  83 +chmod +x run.sh
  84 +./run.sh
  85 +```
  86 +
  87 +**配置说明(修改run.sh中的参数):**
  88 +
  89 +```bash
  90 +# 数据路径配置
  91 +SESSION_DATA_DIR="../offline_tasks/output" # session文件目录
  92 +
  93 +# Swing算法参数
  94 +ALPHA=0.7 # Swing算法的alpha参数(越小越关注用户共同行为)
  95 +THRESHOLD1=1 # 交互强度阈值1(用于筛选用户行为)
  96 +THRESHOLD2=3 # 交互强度阈值2(用于计算相似度)
  97 +THREAD_NUM=4 # 线程数(根据CPU核心数调整)
  98 +SHOW_PROGRESS=1 # 是否显示进度 (0/1)
  99 +
  100 +# Python环境
  101 +PYTHON_CMD="python3" # 如需使用特定Python环境,修改此处
  102 +```
  103 +
  104 +**脚本执行流程:**
  105 +
  106 +1. 编译C++程序(swing, icf_simple, swing_symmetric)
  107 +2. 查找当天日期的session文件
  108 +3. 运行Swing算法计算物品相似度
  109 +4. 合并多线程输出结果
  110 +5. 自动调用debug脚本生成可读版本
  111 +
  112 +### 步骤3: 查看结果
  113 +
  114 +运行完成后,结果文件位于 `collaboration/output_YYYYMMDD/` 目录:
  115 +
  116 +**1. swing_similar.txt** - 原始结果(ID格式)
  117 +```
  118 +12345 \t 67890:0.8523,23456:0.7234,34567:0.6891
  119 +```
  120 +格式:`item_id \t similar_item_id1:score1,similar_item_id2:score2,...`
  121 +
  122 +**2. swing_similar_readable.txt** - 可读结果(带商品名)
  123 +```
  124 +12345:iPhone 15 Pro \t 67890:iPhone 15:0.8523,23456:iPhone 14 Pro:0.7234
  125 +```
  126 +格式:`item_id:item_name \t similar_item_id1:name1:score1,similar_item_id2:name2:score2,...`
  127 +
  128 +### 步骤4: 单独生成Debug文件(可选)
  129 +
  130 +如果需要为其他文件生成可读版本:
  131 +
  132 +```bash
  133 +cd /home/tw/recommendation/offline_tasks
  134 +
  135 +# 基本用法
  136 +python3 scripts/add_names_to_swing.py collaboration/output/swing_similar.txt
  137 +
  138 +# 指定输出文件
  139 +python3 scripts/add_names_to_swing.py \
  140 + collaboration/output/swing_similar.txt \
  141 + collaboration/output/my_readable.txt
  142 +
  143 +# 启用debug模式
  144 +python3 scripts/add_names_to_swing.py \
  145 + collaboration/output/swing_similar.txt \
  146 + --debug
  147 +```
  148 +
  149 +## 参数调优建议
  150 +
  151 +### Swing算法参数
  152 +
  153 +1. **alpha (0.5-1.0)**
  154 + - 越小:越关注用户共同行为的多样性
  155 + - 越大:越容忽略用户重叠度
  156 + - 建议:0.5-0.7(B2B场景)
  157 +
  158 +2. **threshold1 (1-5)**
  159 + - 用于筛选用户的有效行为
  160 + - 建议:1-3(低频场景可用1)
  161 +
  162 +3. **threshold2 (1-10)**
  163 + - 用于计算相似度的行为强度阈值
  164 + - 建议:3-5(需要较强的交互信号)
  165 +
  166 +4. **thread_num (1-20)**
  167 + - 根据CPU核心数设置
  168 + - 建议:4-8(普通服务器)
  169 +
  170 +### 数据范围参数
  171 +
  172 +1. **lookback_days**
  173 + - B2B低频场景:建议730天(2年)
  174 + - B2C高频场景:建议30-90天
  175 + - 数据量大时可适当减少
  176 +
  177 +## 完整示例
  178 +
  179 +```bash
  180 +# 1. 生成session文件(730天数据)
  181 +cd /home/tw/recommendation/offline_tasks
  182 +python3 scripts/generate_session.py --lookback_days 730 --debug
  183 +
  184 +# 2. 检查生成的文件
  185 +ls -lh output/session.txt.*
  186 +# 应该看到:
  187 +# session.txt.20241017
  188 +# session.txt.20241017.cpp
  189 +
  190 +# 3. 运行Swing算法
  191 +cd /home/tw/recommendation/collaboration
  192 +bash run.sh
  193 +
  194 +# 4. 查看结果
  195 +ls -lh output/swing_similar*
  196 +cat output/swing_similar_readable.txt | head -20
  197 +```
  198 +
  199 +## 故障排查
  200 +
  201 +### 问题1: Session文件不存在
  202 +
  203 +```
  204 +错误: Session文件不存在: ../offline_tasks/output/session.txt.20241017.cpp
  205 +```
  206 +
  207 +**解决方法:**
  208 +```bash
  209 +cd /home/tw/recommendation/offline_tasks
  210 +python3 scripts/generate_session.py
  211 +```
  212 +
  213 +### 问题2: 编译失败
  214 +
  215 +```
  216 +编译失败,退出
  217 +```
  218 +
  219 +**解决方法:**
  220 +```bash
  221 +cd /home/tw/recommendation/collaboration
  222 +# 检查编译器
  223 +g++ --version
  224 +
  225 +# 手动编译
  226 +make clean
  227 +make
  228 +
  229 +# 检查依赖
  230 +ls include/
  231 +ls utils/
  232 +```
  233 +
  234 +### 问题3: 数据库连接失败
  235 +
  236 +```
  237 +获取数据失败: Connection refused
  238 +```
  239 +
  240 +**解决方法:**
  241 +- 检查数据库配置:`offline_tasks/config/offline_config.py`
  242 +- 测试连接:`python3 offline_tasks/test_connection.py`
  243 +- 确认网络和防火墙设置
  244 +
  245 +### 问题4: 结果为空
  246 +
  247 +**可能原因:**
  248 +- threshold1/threshold2设置过高,过滤掉了所有数据
  249 +- 数据量太少,用户和商品交集不足
  250 +
  251 +**解决方法:**
  252 +- 降低threshold参数(如threshold1=0.5, threshold2=1)
  253 +- 增加lookback_days
  254 +- 检查数据量:`wc -l output/session.txt.*`
  255 +
  256 +## 性能优化
  257 +
  258 +### 大数据量场景
  259 +
  260 +如果数据量很大(>100万用户,>10万商品):
  261 +
  262 +1. **增加线程数**
  263 + ```bash
  264 + THREAD_NUM=8 # 或更多
  265 + ```
  266 +
  267 +2. **分批处理**
  268 + - 可以将session文件按用户分片
  269 + - 分别运行Swing算法
  270 + - 最后合并结果
  271 +
  272 +3. **调整max_session_list_len**
  273 + - 修改 `src/swing.cc` 中的 `max_session_list_len`
  274 + - 限制每个用户的最大行为数
  275 +
  276 +### 内存优化
  277 +
  278 +如果遇到内存不足:
  279 +
  280 +1. 减少 `max_sim_list_len`(默认300)
  281 +2. 减少 `max_session_list_len`(默认100)
  282 +3. 分批处理数据
  283 +
  284 +## 集成到定时任务
  285 +
  286 +```bash
  287 +# 添加到crontab
  288 +crontab -e
  289 +
  290 +# 每天凌晨2点运行
  291 +0 2 * * * cd /home/tw/recommendation/offline_tasks && python3 scripts/generate_session.py && cd ../collaboration && bash run.sh >> logs/swing_$(date +\%Y\%m\%d).log 2>&1
  292 +```
  293 +
  294 +## 相关文档
  295 +
  296 +- [Swing算法原理](./collaboration/README.md)
  297 +- [离线任务配置](./offline_tasks/config/offline_config.py)
  298 +- [Debug工具使用](./offline_tasks/scripts/debug_utils.py)
  299 +
  300 +## 常见问题
  301 +
  302 +**Q: session文件格式选择哪个?**
  303 +A: run.sh会自动检测格式。建议使用 `--format both` 生成两种格式。
  304 +
  305 +**Q: Swing算法运行多久?**
  306 +A: 取决于数据量和线程数。通常:
  307 +- 1万商品:1-5分钟
  308 +- 10万商品:10-30分钟
  309 +- 数据量大时建议使用多线程
  310 +
  311 +**Q: 如何调整相似商品数量?**
  312 +A: 修改 `src/swing.cc` 中的 `max_sim_list_len` 参数(默认300)。
  313 +
  314 +**Q: 能否使用Python版本的Swing?**
  315 +A: 可以,使用 `offline_tasks/scripts/i2i_swing.py`。但C++版本性能更好。
  316 +
  317 +## 联系支持
  318 +
  319 +如有问题,请参考:
  320 +- 项目README: `/home/tw/recommendation/README.md`
  321 +- 故障排查: `/home/tw/recommendation/offline_tasks/TROUBLESHOOTING.md`
  322 +
offline_tasks/TROUBLESHOOTING.md renamed to offline_tasks/doc/TROUBLESHOOTING.md
offline_tasks/START_HERE.md renamed to offline_tasks/doc/从这里开始.md
offline_tasks/doc/完整索引列表.md 0 → 100644
@@ -0,0 +1,350 @@ @@ -0,0 +1,350 @@
  1 +# 完整索引清单
  2 +
  3 +## 📋 所有可用的推荐索引
  4 +
  5 +### 1. i2i 相似度索引
  6 +
  7 +#### 1.1 行为相似索引(3种)
  8 +
  9 +**Swing算法**:
  10 +```
  11 +i2i:swing:{item_id}
  12 +```
  13 +示例:`i2i:swing:12345`
  14 +
  15 +**Session Word2Vec**:
  16 +```
  17 +i2i:session_w2v:{item_id}
  18 +```
  19 +示例:`i2i:session_w2v:12345`
  20 +
  21 +**DeepWalk**:
  22 +```
  23 +i2i:deepwalk:{item_id}
  24 +```
  25 +示例:`i2i:deepwalk:12345`
  26 +
  27 +#### 1.2 内容相似索引(3种方法)
  28 +
  29 +**混合方法(推荐)**:
  30 +```
  31 +i2i:content_hybrid:{item_id}
  32 +```
  33 +示例:`i2i:content_hybrid:12345`
  34 +
  35 +**TF-IDF方法**:
  36 +```
  37 +i2i:content_tfidf:{item_id}
  38 +```
  39 +示例:`i2i:content_tfidf:12345`
  40 +
  41 +**分类方法**:
  42 +```
  43 +i2i:content_category:{item_id}
  44 +```
  45 +示例:`i2i:content_category:12345`
  46 +
  47 +---
  48 +
  49 +### 2. 兴趣点聚合索引
  50 +
  51 +格式:`interest:{list_type}:{dimension}:{value}`
  52 +
  53 +#### 2.1 列表类型(list_type)
  54 +
  55 +- `hot` - 热门商品
  56 +- `cart` - 加购商品
  57 +- `new` - 新品
  58 +- `global` - 全局(所有数据)
  59 +
  60 +#### 2.2 单维度索引
  61 +
  62 +##### 业务平台(platform)
  63 +```
  64 +interest:hot:platform:pc
  65 +interest:hot:platform:mobile
  66 +interest:cart:platform:pc
  67 +interest:new:platform:mobile
  68 +interest:global:platform:pc
  69 +```
  70 +
  71 +##### 客户端平台(client_platform)
  72 +```
  73 +interest:hot:client_platform:web
  74 +interest:hot:client_platform:app
  75 +interest:cart:client_platform:web
  76 +interest:new:client_platform:app
  77 +interest:global:client_platform:web
  78 +```
  79 +
  80 +##### 供应商(supplier)
  81 +```
  82 +interest:hot:supplier:10001
  83 +interest:hot:supplier:10002
  84 +interest:cart:supplier:10001
  85 +interest:new:supplier:10002
  86 +interest:global:supplier:10001
  87 +```
  88 +
  89 +##### 一级分类(category_level1)
  90 +```
  91 +interest:hot:category_level1:100
  92 +interest:cart:category_level1:100
  93 +interest:new:category_level1:100
  94 +interest:global:category_level1:100
  95 +```
  96 +
  97 +##### 二级分类(category_level2)
  98 +```
  99 +interest:hot:category_level2:200
  100 +interest:cart:category_level2:200
  101 +interest:new:category_level2:200
  102 +interest:global:category_level2:200
  103 +```
  104 +
  105 +##### 三级分类(category_level3)
  106 +```
  107 +interest:hot:category_level3:300
  108 +interest:cart:category_level3:300
  109 +interest:new:category_level3:300
  110 +interest:global:category_level3:300
  111 +```
  112 +
  113 +##### 四级分类(category_level4)
  114 +```
  115 +interest:hot:category_level4:400
  116 +interest:cart:category_level4:400
  117 +interest:new:category_level4:400
  118 +interest:global:category_level4:400
  119 +```
  120 +
  121 +#### 2.3 组合维度索引
  122 +
  123 +##### 平台 + 客户端
  124 +```
  125 +interest:hot:platform_client:pc_web
  126 +interest:hot:platform_client:pc_app
  127 +interest:hot:platform_client:mobile_web
  128 +interest:hot:platform_client:mobile_app
  129 +```
  130 +
  131 +##### 平台 + 二级分类
  132 +```
  133 +interest:hot:platform_category2:pc_200
  134 +interest:hot:platform_category2:mobile_200
  135 +interest:cart:platform_category2:pc_200
  136 +interest:new:platform_category2:mobile_200
  137 +```
  138 +
  139 +##### 平台 + 三级分类
  140 +```
  141 +interest:hot:platform_category3:pc_300
  142 +interest:hot:platform_category3:mobile_300
  143 +interest:cart:platform_category3:pc_300
  144 +interest:new:platform_category3:mobile_300
  145 +```
  146 +
  147 +##### 客户端平台 + 二级分类
  148 +```
  149 +interest:hot:client_category2:web_200
  150 +interest:hot:client_category2:app_200
  151 +interest:cart:client_category2:web_200
  152 +interest:new:client_category2:app_200
  153 +```
  154 +
  155 +---
  156 +
  157 +## 🎯 按业务场景的索引使用
  158 +
  159 +### 场景1: 首页个性化推荐
  160 +
  161 +**方案A: 基于平台**
  162 +```python
  163 +key = f"interest:hot:platform:{user_platform}"
  164 +# 示例:interest:hot:platform:pc
  165 +```
  166 +
  167 +**方案B: 基于分类偏好**
  168 +```python
  169 +key = f"interest:hot:category_level2:{user_favorite_category}"
  170 +# 示例:interest:hot:category_level2:200
  171 +```
  172 +
  173 +**方案C: 基于平台+分类**
  174 +```python
  175 +key = f"interest:hot:platform_category2:{user_platform}_{category_id}"
  176 +# 示例:interest:hot:platform_category2:pc_200
  177 +```
  178 +
  179 +### 场景2: 详情页相关推荐
  180 +
  181 +**方案A: 行为相似**
  182 +```python
  183 +key = f"i2i:swing:{current_item_id}"
  184 +# 示例:i2i:swing:12345
  185 +```
  186 +
  187 +**方案B: 内容相似**
  188 +```python
  189 +key = f"i2i:content_hybrid:{current_item_id}"
  190 +# 示例:i2i:content_hybrid:12345
  191 +```
  192 +
  193 +**方案C: 融合推荐**
  194 +```python
  195 +behavior_similar = redis.get(f"i2i:swing:{item_id}")
  196 +content_similar = redis.get(f"i2i:content_hybrid:{item_id}")
  197 +# 融合两种结果
  198 +```
  199 +
  200 +### 场景3: 分类页推荐
  201 +
  202 +**方案A: 该分类热门**
  203 +```python
  204 +key = f"interest:hot:category_level2:{category_id}"
  205 +# 示例:interest:hot:category_level2:200
  206 +```
  207 +
  208 +**方案B: 该分类新品**
  209 +```python
  210 +key = f"interest:new:category_level2:{category_id}"
  211 +# 示例:interest:new:category_level2:200
  212 +```
  213 +
  214 +**方案C: 该分类+平台**
  215 +```python
  216 +key = f"interest:hot:platform_category2:{platform}_{category_id}"
  217 +# 示例:interest:hot:platform_category2:pc_200
  218 +```
  219 +
  220 +### 场景4: 供应商店铺页
  221 +
  222 +**方案A: 供应商热门商品**
  223 +```python
  224 +key = f"interest:hot:supplier:{supplier_id}"
  225 +# 示例:interest:hot:supplier:10001
  226 +```
  227 +
  228 +**方案B: 供应商新品**
  229 +```python
  230 +key = f"interest:new:supplier:{supplier_id}"
  231 +# 示例:interest:new:supplier:10001
  232 +```
  233 +
  234 +### 场景5: 搜索结果页推荐
  235 +
  236 +**方案A: 全局热门**
  237 +```python
  238 +key = "interest:global:platform:pc"
  239 +```
  240 +
  241 +**方案B: 分类相关**
  242 +```python
  243 +key = f"interest:global:category_level2:{search_category}"
  244 +# 示例:interest:global:category_level2:200
  245 +```
  246 +
  247 +---
  248 +
  249 +## 📊 索引数量统计
  250 +
  251 +### i2i索引
  252 +- 行为相似:3种算法 × 商品数量
  253 +- 内容相似:3种方法 × 商品数量
  254 +- **总计**:6 × 商品数量
  255 +
  256 +### 兴趣点聚合索引
  257 +
  258 +**单维度**:
  259 +- platform: 2-10个
  260 +- client_platform: 2-5个
  261 +- supplier: 100-1000个
  262 +- category_level1: 10-50个
  263 +- category_level2: 50-200个
  264 +- category_level3: 200-1000个
  265 +- category_level4: 1000-5000个
  266 +
  267 +**组合维度**:
  268 +- platform_client: 4-50个
  269 +- platform_category2: 100-2000个
  270 +- platform_category3: 400-10000个
  271 +- client_category2: 100-1000个
  272 +
  273 +**列表类型**:每个维度 × 4种类型(hot/cart/new/global)
  274 +
  275 +**预估总数**:10000-50000条索引
  276 +
  277 +---
  278 +
  279 +## 🔍 查询示例代码
  280 +
  281 +### Python示例
  282 +
  283 +```python
  284 +import redis
  285 +
  286 +# 连接Redis
  287 +r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
  288 +
  289 +# 1. 查询商品的相似商品
  290 +item_id = "12345"
  291 +similar_items = r.get(f"i2i:swing:{item_id}")
  292 +if similar_items:
  293 + items = similar_items.split(',')
  294 + for item in items[:5]: # 取前5个
  295 + item_id, score = item.split(':')
  296 + print(f"商品ID: {item_id}, 相似度: {score}")
  297 +
  298 +# 2. 查询分类热门商品
  299 +category_id = "200"
  300 +hot_items = r.get(f"interest:hot:category_level2:{category_id}")
  301 +if hot_items:
  302 + items = hot_items.split(',')
  303 + for item in items[:10]: # 取前10个
  304 + item_id, score = item.split(':')
  305 + print(f"商品ID: {item_id}, 得分: {score}")
  306 +
  307 +# 3. 查询平台+分类组合
  308 +platform = "pc"
  309 +category_id = "200"
  310 +key = f"interest:hot:platform_category2:{platform}_{category_id}"
  311 +items = r.get(key)
  312 +```
  313 +
  314 +### Redis命令行示例
  315 +
  316 +```bash
  317 +# 查询商品相似度
  318 +redis-cli GET "i2i:swing:12345"
  319 +
  320 +# 查询分类热门
  321 +redis-cli GET "interest:hot:category_level2:200"
  322 +
  323 +# 查询供应商商品
  324 +redis-cli GET "interest:hot:supplier:10001"
  325 +
  326 +# 模糊查询所有热门索引
  327 +redis-cli KEYS "interest:hot:*"
  328 +
  329 +# 查看某个分类的所有类型
  330 +redis-cli KEYS "interest:*:category_level2:200"
  331 +```
  332 +
  333 +---
  334 +
  335 +## 📝 注意事项
  336 +
  337 +1. **索引命名规范**:严格遵循 `type:subtype:dimension:value` 格式
  338 +2. **值的格式**:`item_id1:score1,item_id2:score2,...`
  339 +3. **过期时间**:建议设置7天过期
  340 +4. **更新频率**:建议每天更新一次
  341 +5. **查询优先级**:
  342 + - 优先使用细粒度索引(如四级分类)
  343 + - 粗粒度索引作为后备(如一级分类)
  344 + - 融合多个索引结果
  345 +
  346 +---
  347 +
  348 +**版本**: v1.1
  349 +**生成日期**: 2025-10-16
  350 +**索引总数**: 约10000-50000条
offline_tasks/QUICKSTART.md renamed to offline_tasks/doc/快速开始.md
offline_tasks/doc/故障排查指南.md 0 → 100644
@@ -0,0 +1,217 @@ @@ -0,0 +1,217 @@
  1 +# 故障排除指南
  2 +
  3 +## 常见问题及解决方案
  4 +
  5 +### 1. 数据库字段错误
  6 +
  7 +#### 问题:
  8 +```
  9 +pymysql.err.OperationalError: (1105, "errCode = 2, detailMessage = Unknown column 'xxx' in 'xxx'")
  10 +```
  11 +
  12 +#### 原因:
  13 +数据库表结构与代码中使用的字段名不匹配。
  14 +
  15 +#### 解决方案:
  16 +1. 查看 `DATABASE_SETUP.md` 了解如何配置字段
  17 +2. 修改对应脚本中的SQL查询,使用实际存在的字段名
  18 +3. 如果是分类字段不存在,这些字段是可选的,代码会自动跳过
  19 +
  20 +#### 已修复的字段:
  21 +- ✅ `category_level2_id` 和 `category_level3_id` 现在是可选的
  22 +- ✅ 基础功能不依赖分类字段
  23 +
  24 +---
  25 +
  26 +### 2. 连接超时
  27 +
  28 +#### 问题:
  29 +```
  30 +pymysql.err.OperationalError: (2003, "Can't connect to MySQL server...")
  31 +```
  32 +
  33 +#### 解决方案:
  34 +1. 检查数据库配置:`config/offline_config.py`
  35 +2. 确认网络连接和防火墙设置
  36 +3. 运行测试:`python3 test_connection.py`
  37 +
  38 +---
  39 +
  40 +### 3. 内存不足
  41 +
  42 +#### 问题:
  43 +程序运行时内存占用过高或被杀死。
  44 +
  45 +#### 解决方案:
  46 +1. 减少回溯天数:`--lookback_days 365`(从730改为365)
  47 +2. 减少输出数量:`--top_n 20`(从50改为20)
  48 +3. 先运行单个算法:
  49 + ```bash
  50 + python3 scripts/i2i_session_w2v.py # 内存占用较小
  51 + ```
  52 +4. 跳过Swing算法(内存占用最大):
  53 + ```bash
  54 + python3 run_all.py --skip-i2i
  55 + ```
  56 +
  57 +---
  58 +
  59 +### 4. 运行时间过长
  60 +
  61 +#### 解决方案:
  62 +1. 减少数据量:`--lookback_days 180`
  63 +2. 只运行特定算法:
  64 + ```bash
  65 + python3 run_all.py --only-w2v
  66 + ```
  67 +3. 考虑使用C++版本的Swing(性能提升10倍)
  68 +
  69 +---
  70 +
  71 +### 5. 依赖包安装失败
  72 +
  73 +#### 解决方案:
  74 +```bash
  75 +# 单独安装失败的包
  76 +pip3 install pandas sqlalchemy pymysql gensim numpy
  77 +
  78 +# 或使用国内镜像
  79 +pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
  80 +```
  81 +
  82 +---
  83 +
  84 +### 6. Redis连接失败
  85 +
  86 +#### 问题:
  87 +```
  88 +redis.exceptions.ConnectionError: Error connecting to Redis
  89 +```
  90 +
  91 +#### 解决方案:
  92 +1. Redis是可选的,只影响索引加载功能
  93 +2. 如果不需要Redis,可以跳过:
  94 + ```bash
  95 + python3 run_all.py # 只运行离线任务,不加载到Redis
  96 + ```
  97 +3. 如果需要Redis,确认Redis已安装并运行:
  98 + ```bash
  99 + redis-cli ping # 应该返回 PONG
  100 + ```
  101 +
  102 +---
  103 +
  104 +### 7. 输出文件为空
  105 +
  106 +#### 可能原因:
  107 +1. 数据量太少(没有满足最小阈值)
  108 +2. 时间范围内没有数据
  109 +3. SQL查询条件过于严格
  110 +
  111 +#### 解决方案:
  112 +1. 检查日志:`tail -f logs/run_all_*.log`
  113 +2. 调整参数:
  114 + - 增加时间范围:`--lookback_days 1000`
  115 + - 减少阈值:修改配置文件中的 `min_interaction_count`
  116 +3. 检查数据库中是否有数据:
  117 + ```python
  118 + # 运行简单查询测试
  119 + python3 test_connection.py
  120 + ```
  121 +
  122 +---
  123 +
  124 +### 8. 权限问题
  125 +
  126 +#### 问题:
  127 +```
  128 +PermissionError: [Errno 13] Permission denied
  129 +```
  130 +
  131 +#### 解决方案:
  132 +```bash
  133 +# 给脚本添加执行权限
  134 +chmod +x install.sh run_all.py
  135 +
  136 +# 确保有写入权限
  137 +chmod 755 output/ logs/
  138 +```
  139 +
  140 +---
  141 +
  142 +### 9. Python版本问题
  143 +
  144 +#### 要求:
  145 +Python 3.7+
  146 +
  147 +#### 检查版本:
  148 +```bash
  149 +python3 --version
  150 +```
  151 +
  152 +#### 如果版本过低,需要升级Python
  153 +
  154 +---
  155 +
  156 +### 10. 编码问题
  157 +
  158 +#### 问题:
  159 +```
  160 +UnicodeDecodeError: 'utf-8' codec can't decode byte...
  161 +```
  162 +
  163 +#### 解决方案:
  164 +确保所有文件使用UTF-8编码,特别是配置文件和输出文件。
  165 +
  166 +---
  167 +
  168 +## 调试技巧
  169 +
  170 +### 1. 查看详细日志
  171 +```bash
  172 +tail -f logs/run_all_*.log
  173 +```
  174 +
  175 +### 2. 运行单个任务(便于调试)
  176 +```bash
  177 +python3 scripts/i2i_swing.py --lookback_days 30 --top_n 10
  178 +```
  179 +
  180 +### 3. 使用较小的数据量测试
  181 +```bash
  182 +python3 run_all.py --lookback_days 30 --top_n 10
  183 +```
  184 +
  185 +### 4. 检查中间结果
  186 +```bash
  187 +ls -lh output/
  188 +head -n 20 output/i2i_swing_*.txt
  189 +```
  190 +
  191 +---
  192 +
  193 +## 获取支持
  194 +
  195 +如果以上方法都无法解决问题:
  196 +
  197 +1. **查看文档**:
  198 + - `README.md` - 详细说明
  199 + - `DATABASE_SETUP.md` - 数据库配置
  200 + - `QUICKSTART.md` - 快速开始
  201 +
  202 +2. **查看日志**:
  203 + - `logs/` 目录下的所有日志文件
  204 +
  205 +3. **简化测试**:
  206 + - 先运行 `test_connection.py`
  207 + - 再运行单个脚本
  208 + - 使用小数据量测试
  209 +
  210 +4. **记录错误信息**:
  211 + - 完整的错误堆栈
  212 + - 使用的命令
  213 + - 配置文件内容
  214 +
  215 +---
  216 +
  217 +**提示**:大部分问题都与数据库字段名不匹配有关,请优先查看 `DATABASE_SETUP.md`。
offline_tasks/doc/数据库配置说明.md 0 → 100644
@@ -0,0 +1,179 @@ @@ -0,0 +1,179 @@
  1 +# 数据库字段配置说明
  2 +
  3 +## 问题说明
  4 +
  5 +如果运行时遇到类似 `Unknown column 'xxx'` 的错误,说明数据库表结构与代码中使用的字段名不匹配。
  6 +
  7 +## 已适配的基础字段
  8 +
  9 +当前代码已经适配了以下基础字段(参考 `item_sim.py`):
  10 +
  11 +### sensors_events 表
  12 +- `anonymous_id` - 用户ID
  13 +- `item_id` - 商品ID
  14 +- `event` - 事件类型
  15 +- `create_time` - 创建时间
  16 +- `platform` - 平台(可选)
  17 +- `country` - 国家(可选)
  18 +- `customer_type` - 客户类型(可选)
  19 +
  20 +### prd_goods_sku 表
  21 +- `id` - 商品ID
  22 +- `name` - 商品名称
  23 +- `create_time` - 创建时间(用于判断新品)
  24 +
  25 +## 可选字段配置
  26 +
  27 +如果您的数据库表包含以下字段,可以在SQL查询中添加它们以支持更多维度:
  28 +
  29 +### 分类字段(可选)
  30 +- `category_level1_id` - 一级分类ID
  31 +- `category_level2_id` - 二级分类ID
  32 +- `category_level3_id` - 三级分类ID
  33 +
  34 +## 如何添加分类字段支持
  35 +
  36 +如果您的数据库有分类字段,可以按以下步骤启用:
  37 +
  38 +### 步骤1: 修改 SQL 查询
  39 +
  40 +编辑 `scripts/interest_aggregation.py`,找到 SQL 查询部分,添加分类字段:
  41 +
  42 +```python
  43 +sql_query = f"""
  44 +SELECT
  45 + se.anonymous_id AS user_id,
  46 + se.item_id,
  47 + se.event AS event_type,
  48 + se.create_time,
  49 + pgs.name AS item_name,
  50 + pgs.create_time AS item_create_time,
  51 + pgs.category_level2_id, # 添加这一行
  52 + pgs.category_level3_id, # 添加这一行
  53 + se.platform,
  54 + se.country,
  55 + se.customer_type
  56 +FROM
  57 + sensors_events se
  58 +LEFT JOIN prd_goods_sku pgs ON se.item_id = pgs.id
  59 +...
  60 +"""
  61 +```
  62 +
  63 +### 步骤2: 修改聚合逻辑
  64 +
  65 +在 `aggregate_by_dimensions` 函数中,字段检查已经做好了,如果字段存在会自动使用:
  66 +
  67 +```python
  68 +# 维度4: 二级分类 (category_level2) - 如果字段存在
  69 +if 'category_level2_id' in row and pd.notna(row.get('category_level2_id')):
  70 + key = f"category_level2:{row['category_level2_id']}"
  71 + aggregations[key][item_id] += weight
  72 +```
  73 +
  74 +这段代码会自动检测字段是否存在,如果存在就使用,不存在就跳过。
  75 +
  76 +## 查看实际表结构
  77 +
  78 +运行以下命令查看您的数据库表结构:
  79 +
  80 +```python
  81 +# 创建一个简单的脚本查看表结构
  82 +import pandas as pd
  83 +from db_service import create_db_connection
  84 +from offline_tasks.config.offline_config import DB_CONFIG
  85 +
  86 +engine = create_db_connection(
  87 + DB_CONFIG['host'],
  88 + DB_CONFIG['port'],
  89 + DB_CONFIG['database'],
  90 + DB_CONFIG['username'],
  91 + DB_CONFIG['password']
  92 +)
  93 +
  94 +# 查看 prd_goods_sku 表结构
  95 +df = pd.read_sql("SELECT * FROM prd_goods_sku LIMIT 1", engine)
  96 +print("prd_goods_sku 字段列表:")
  97 +for col in df.columns:
  98 + print(f" - {col}")
  99 +
  100 +# 查看 sensors_events 表结构
  101 +df = pd.read_sql("SELECT * FROM sensors_events LIMIT 1", engine)
  102 +print("\nsensors_events 字段列表:")
  103 +for col in df.columns:
  104 + print(f" - {col}")
  105 +```
  106 +
  107 +## 常见字段名映射
  108 +
  109 +如果您的数据库使用不同的字段名,需要在SQL查询中做映射:
  110 +
  111 +| 代码中的字段 | 可能的实际字段名 | 修改方式 |
  112 +|-------------|----------------|---------|
  113 +| `category_level2_id` | `cat2_id`, `category2`, `second_category` | `pgs.cat2_id AS category_level2_id` |
  114 +| `category_level3_id` | `cat3_id`, `category3`, `third_category` | `pgs.cat3_id AS category_level3_id` |
  115 +| `anonymous_id` | `user_id`, `uid`, `visitor_id` | `se.user_id AS anonymous_id` |
  116 +| `customer_type` | `client_type`, `buyer_type` | `se.client_type AS customer_type` |
  117 +
  118 +## 完整示例
  119 +
  120 +假设您的表结构是:
  121 +- `prd_goods_sku` 有字段:`id`, `title`, `cat2`, `cat3`, `add_time`
  122 +- `sensors_events` 有字段:`uid`, `goods_id`, `action`, `time`
  123 +
  124 +则需要修改SQL为:
  125 +
  126 +```python
  127 +sql_query = f"""
  128 +SELECT
  129 + se.uid AS user_id,
  130 + se.goods_id AS item_id,
  131 + se.action AS event_type,
  132 + se.time AS create_time,
  133 + pgs.title AS item_name,
  134 + pgs.add_time AS item_create_time,
  135 + pgs.cat2 AS category_level2_id,
  136 + pgs.cat3 AS category_level3_id
  137 +FROM
  138 + sensors_events se
  139 +LEFT JOIN prd_goods_sku pgs ON se.goods_id = pgs.id
  140 +...
  141 +"""
  142 +```
  143 +
  144 +## 最小化配置
  145 +
  146 +如果只想先测试基本功能,可以只使用最基础的字段:
  147 +
  148 +### i2i 算法只需要:
  149 +- `anonymous_id` / `user_id`
  150 +- `item_id`
  151 +- `event` / `event_type`
  152 +- `create_time`
  153 +- `name` (商品名称)
  154 +
  155 +### 兴趣点聚合至少需要:
  156 +- 以上i2i的字段
  157 +- 至少一个维度字段(如 `platform` 或 `country`)
  158 +
  159 +## 测试连接
  160 +
  161 +修改后,运行测试脚本验证:
  162 +
  163 +```bash
  164 +cd /home/tw/recommendation/offline_tasks
  165 +python3 test_connection.py
  166 +```
  167 +
  168 +## 获取帮助
  169 +
  170 +如果仍有问题,请:
  171 +1. 查看日志文件:`logs/run_all_*.log`
  172 +2. 运行单个脚本测试,便于调试
  173 +3. 使用 `--help` 参数查看命令行选项
  174 +
  175 +```bash
  176 +python3 scripts/i2i_swing.py --help
  177 +python3 scripts/interest_aggregation.py --help
  178 +```
  179 +
offline_tasks/CHANGELOG.md renamed to offline_tasks/doc/更新日志.md
offline_tasks/doc/离线索引数据规范.md 0 → 100644
@@ -0,0 +1,197 @@ @@ -0,0 +1,197 @@
  1 +# 离线索引产出规范
  2 +
  3 +## 📋 索引任务列表
  4 +
  5 +| 模块名称 | 任务命令 | 调度频次 | 输出数据 | 格式和示例 |
  6 +|---------|---------|---------|---------|-----------|
  7 +| **i2i_swing** | `python3 scripts/i2i_swing.py` | 每天 | `output/i2i_swing_YYYYMMDD.txt` | `item_id \t item_name \t similar_id1:score1,similar_id2:score2,...` |
  8 +| **i2i_session_w2v** | `python3 scripts/i2i_session_w2v.py` | 每天 | `output/i2i_session_w2v_YYYYMMDD.txt` | `item_id \t item_name \t similar_id1:score1,similar_id2:score2,...` |
  9 +| **i2i_deepwalk** | `python3 scripts/i2i_deepwalk.py` | 每天 | `output/i2i_deepwalk_YYYYMMDD.txt` | `item_id \t item_name \t similar_id1:score1,similar_id2:score2,...` |
  10 +| **i2i_content** | `python3 scripts/i2i_content_similar.py` | 每周 | `output/i2i_content_hybrid_YYYYMMDD.txt` | `item_id \t item_name \t similar_id1:score1,similar_id2:score2,...` |
  11 +| **interest_hot** | `python3 scripts/interest_aggregation.py` | 每天 | `output/interest_aggregation_hot_YYYYMMDD.txt` | `dimension_key \t item_id1,item_id2,item_id3,...` |
  12 +| **interest_cart** | `python3 scripts/interest_aggregation.py` | 每天 | `output/interest_aggregation_cart_YYYYMMDD.txt` | `dimension_key \t item_id1,item_id2,item_id3,...` |
  13 +| **interest_new** | `python3 scripts/interest_aggregation.py` | 每天 | `output/interest_aggregation_new_YYYYMMDD.txt` | `dimension_key \t item_id1,item_id2,item_id3,...` |
  14 +| **interest_global** | `python3 scripts/interest_aggregation.py` | 每天 | `output/interest_aggregation_global_YYYYMMDD.txt` | `dimension_key \t item_id1,item_id2,item_id3,...` |
  15 +
  16 +## 📊 详细格式说明
  17 +
  18 +### 1. i2i相似度索引
  19 +
  20 +#### 输出格式
  21 +```
  22 +item_id \t item_name \t similar_id1:score1,similar_id2:score2,...
  23 +```
  24 +
  25 +#### 示例
  26 +```
  27 +12345 香蕉干 67890:0.8567,11223:0.7234,44556:0.6891
  28 +67890 芒果干 12345:0.8567,22334:0.7123,55667:0.6543
  29 +```
  30 +
  31 +#### 字段说明
  32 +- `item_id`: 商品SKU ID
  33 +- `item_name`: 商品名称
  34 +- `similar_id`: 相似商品ID
  35 +- `score`: 相似度分数(0-1之间,越大越相似)
  36 +
  37 +#### 算法差异
  38 +| 算法 | 特点 | 适用场景 |
  39 +|------|------|---------|
  40 +| **Swing** | 基于用户共同行为,发现购买关联 | 详情页"大家都在看" |
  41 +| **Session W2V** | 基于会话序列,捕捉浏览顺序 | 详情页"看了又看" |
  42 +| **DeepWalk** | 基于图结构,发现深层关系 | 详情页"相关推荐" |
  43 +| **Content** | 基于商品属性,类目相似 | 冷启动商品推荐 |
  44 +
  45 +### 2. 兴趣点聚合索引
  46 +
  47 +#### 输出格式
  48 +```
  49 +dimension_key \t item_id1,item_id2,item_id3,...
  50 +```
  51 +
  52 +#### 示例
  53 +```
  54 +platform:pc 12345,67890,11223,44556,22334
  55 +category_level2:200 67890,12345,22334,55667,11223
  56 +platform_category2:pc_200 12345,67890,22334,11223,55667
  57 +supplier:10001 12345,44556,22334,67890,11223
  58 +```
  59 +
  60 +#### 维度说明
  61 +
  62 +**单维度(7个)**
  63 +- `platform:{platform_id}` - 业务平台(pc, h5, app等)
  64 +- `client_platform:{client}` - 客户端平台(iOS, Android, Web等)
  65 +- `supplier:{supplier_id}` - 供应商
  66 +- `category_level1:{cat_id}` - 一级分类
  67 +- `category_level2:{cat_id}` - 二级分类
  68 +- `category_level3:{cat_id}` - 三级分类
  69 +- `category_level4:{cat_id}` - 四级分类
  70 +
  71 +**组合维度(4个)**
  72 +- `platform_client:{platform}_{client}` - 平台+客户端
  73 +- `platform_category2:{platform}_{cat_id}` - 平台+二级分类
  74 +- `platform_category3:{platform}_{cat_id}` - 平台+三级分类
  75 +- `client_category2:{client}_{cat_id}` - 客户端+二级分类
  76 +
  77 +#### 列表类型说明
  78 +
  79 +| 类型 | 文件名 | 计算逻辑 | 适用场景 |
  80 +|------|--------|---------|---------|
  81 +| **hot** | `interest_aggregation_hot_YYYYMMDD.txt` | 最近N天的高频交互商品 | 首页"热门推荐" |
  82 +| **cart** | `interest_aggregation_cart_YYYYMMDD.txt` | 高加购率商品 | 首页"热门加购" |
  83 +| **new** | `interest_aggregation_new_YYYYMMDD.txt` | 最近上架的新品 | 首页"新品推荐" |
  84 +| **global** | `interest_aggregation_global_YYYYMMDD.txt` | 全局热门商品 | 首页"猜你喜欢" |
  85 +
  86 +## 🔄 调度建议
  87 +
  88 +### 每日调度(数据量大,变化快)
  89 +```bash
  90 +# 每天凌晨3点执行
  91 +0 3 * * * cd /home/tw/recommendation/offline_tasks && python3 run_all.py --lookback_days 730 --top_n 50
  92 +```
  93 +
  94 +### 每周调度(数据量小,变化慢)
  95 +```bash
  96 +# 每周日凌晨4点执行
  97 +0 4 * * 0 cd /home/tw/recommendation/offline_tasks && python3 scripts/i2i_content_similar.py --top_n 50
  98 +```
  99 +
  100 +## 📁 文件命名规范
  101 +
  102 +### 标准格式
  103 +```
  104 +{algorithm_name}_{date}.txt
  105 +```
  106 +
  107 +### 示例
  108 +```
  109 +i2i_swing_20251016.txt
  110 +i2i_session_w2v_20251016.txt
  111 +interest_aggregation_hot_20251016.txt
  112 +```
  113 +
  114 +### Debug文件(开发调试用)
  115 +```
  116 +output/debug/{algorithm_name}_{date}_readable.txt
  117 +logs/debug/{algorithm_name}_{date}_{time}.log
  118 +```
  119 +
  120 +## 📈 数据量估算
  121 +
  122 +| 索引类型 | 索引数量 | 单条大小 | 总大小 | 更新频率 |
  123 +|---------|---------|---------|--------|---------|
  124 +| i2i_swing | ~50,000 | ~500B | ~25MB | 每天 |
  125 +| i2i_session_w2v | ~50,000 | ~500B | ~25MB | 每天 |
  126 +| i2i_deepwalk | ~50,000 | ~500B | ~25MB | 每天 |
  127 +| i2i_content | ~50,000 | ~500B | ~25MB | 每周 |
  128 +| interest_hot | ~10,000 | ~1KB | ~10MB | 每天 |
  129 +| interest_cart | ~10,000 | ~1KB | ~10MB | 每天 |
  130 +| interest_new | ~5,000 | ~1KB | ~5MB | 每天 |
  131 +| interest_global | ~10,000 | ~1KB | ~10MB | 每天 |
  132 +| **总计** | **~245,000** | - | **~135MB** | - |
  133 +
  134 +## 🎯 质量检查
  135 +
  136 +### 数据完整性检查
  137 +```bash
  138 +# 检查文件是否生成
  139 +ls -lh output/*_$(date +%Y%m%d).txt
  140 +
  141 +# 检查行数
  142 +wc -l output/*_$(date +%Y%m%d).txt
  143 +
  144 +# 检查格式
  145 +head -5 output/i2i_swing_$(date +%Y%m%d).txt
  146 +```
  147 +
  148 +### 数据质量指标
  149 +
  150 +**i2i索引质量**
  151 +- 覆盖率:有推荐的商品数 / 总商品数 > 80%
  152 +- 推荐数量:每个商品推荐10-50个相似商品
  153 +- 分数范围:相似度分数在0.01-1.0之间
  154 +
  155 +**兴趣聚合质量**
  156 +- 覆盖率:有数据的维度数 / 总维度数 > 60%
  157 +- 推荐数量:每个维度推荐50-1000个商品
  158 +- 商品去重:同一商品在列表中只出现一次
  159 +
  160 +## 🔍 查询示例
  161 +
  162 +### 查看特定商品的相似推荐
  163 +```bash
  164 +# 查看商品12345的相似商品
  165 +grep "^12345\t" output/i2i_swing_20251016.txt
  166 +```
  167 +
  168 +### 查看特定维度的热门商品
  169 +```bash
  170 +# 查看PC平台的热门商品
  171 +grep "^platform:pc\t" output/interest_aggregation_hot_20251016.txt
  172 +```
  173 +
  174 +### 统计索引数量
  175 +```bash
  176 +# 统计各类型索引数量
  177 +for file in output/*_20251016.txt; do
  178 + echo "$file: $(wc -l < $file) 条"
  179 +done
  180 +```
  181 +
  182 +## ⚠️ 注意事项
  183 +
  184 +1. **文件编码**: 所有文件使用UTF-8编码
  185 +2. **分隔符**: 使用Tab(\t)分隔字段
  186 +3. **商品ID**: 使用数字类型,不带引号
  187 +4. **分数精度**: 相似度分数保留4位小数
  188 +5. **排序规则**: 相似商品按分数降序排列
  189 +6. **去重**: 确保推荐列表中没有重复商品
  190 +7. **有效性**: 推荐的商品必须是在售状态
  191 +
  192 +## 🔗 相关文档
  193 +
  194 +- **Redis数据规范**: `REDIS_DATA_SPEC.md`
  195 +- **API接口文档**: `RECOMMENDATION_API.md`
  196 +- **Debug指南**: `DEBUG_GUIDE.md`
  197 +- **配置说明**: `UPDATE_CONFIG_GUIDE.md`
offline_tasks/doc/系统改进总结-20241017.md 0 → 100644
@@ -0,0 +1,366 @@ @@ -0,0 +1,366 @@
  1 +# 推荐系统离线任务改进总结
  2 +
  3 +**日期**: 2024-10-17
  4 +**改进内容**: 前置任务优化、文档整理、算法增强
  5 +
  6 +---
  7 +
  8 +## ✅ 完成的改进
  9 +
  10 +### 1. 前置任务:商品属性获取
  11 +
  12 +**问题**: 多个脚本都需要获取ID->名称映射,导致重复查询数据库,效率低下。
  13 +
  14 +**解决方案**:
  15 +- ✅ 创建 `fetch_item_attributes.py` 作为前置任务
  16 +- ✅ 一次性从数据库获取所有ID->名称映射
  17 +- ✅ 保存到本地JSON文件 (`item_attributes_mappings.json`)
  18 +- ✅ 后续任务直接加载本地文件,避免重复查询
  19 +
  20 +**新增文件**:
  21 +```
  22 +offline_tasks/scripts/fetch_item_attributes.py
  23 +offline_tasks/output/item_attributes_mappings.json
  24 +offline_tasks/output/item_attributes_stats.txt
  25 +```
  26 +
  27 +**修改文件**:
  28 +```
  29 +offline_tasks/scripts/debug_utils.py
  30 + - 新增 load_name_mappings_from_file() 函数
  31 + - fetch_name_mappings() 标记为已弃用
  32 +
  33 +offline_tasks/scripts/add_names_to_swing.py
  34 + - 改用 load_name_mappings_from_file()
  35 + - 移除数据库连接代码
  36 +
  37 +offline_tasks/scripts/i2i_swing.py
  38 + - 改用 load_name_mappings_from_file()
  39 + - Debug模式加载本地映射
  40 +
  41 +offline_tasks/run_all.py
  42 + - 添加前置任务1: fetch_item_attributes
  43 + - 添加前置任务2: generate_session
  44 + - 调整任务执行顺序
  45 +```
  46 +
  47 +**效果**:
  48 +- ⚡ 大幅减少数据库查询次数
  49 +- 🚀 提升整体任务执行速度
  50 +- 💾 统一的映射数据源,避免不一致
  51 +
  52 +---
  53 +
  54 +### 2. Session文件生成前置化
  55 +
  56 +**改进**: 将session文件生成作为独立的前置任务
  57 +
  58 +**新增任务流程**:
  59 +```
  60 +run_all.py 执行顺序:
  61 +1. fetch_item_attributes.py → 获取商品属性
  62 +2. generate_session.py → 生成用户session文件
  63 +3. i2i_swing.py → Swing算法
  64 +4. i2i_session_w2v.py → Session W2V
  65 +5. i2i_deepwalk.py → DeepWalk
  66 +6. i2i_content_similar.py → 内容相似度
  67 +7. interest_aggregation.py → 兴趣聚合
  68 +```
  69 +
  70 +**好处**:
  71 +- 📦 Session文件可复用于多个任务
  72 +- 🔄 C++版Swing算法可直接使用session文件
  73 +- 🎯 数据准备与算法执行解耦
  74 +
  75 +---
  76 +
  77 +### 3. Swing算法增强:支持日期维度
  78 +
  79 +**功能**: i2i_swing.py 现在支持 uid+日期 作为额外的session维度
  80 +
  81 +**实现方式**:
  82 +```python
  83 +# 数据duplicate:
  84 +# 1. 原始数据:uid -> items
  85 +# 2. 日期数据:uid_YYYYMMDD -> items
  86 +# 3. 合并后输入Swing算法
  87 +
  88 +# 新增参数
  89 +--use_daily_session # 启用日期维度(默认开启)
  90 +--no_daily_session # 禁用日期维度
  91 +```
  92 +
  93 +**示例**:
  94 +```bash
  95 +# 使用日期维度(默认)
  96 +python3 scripts/i2i_swing.py --lookback_days 730 --debug
  97 +
  98 +# 禁用日期维度
  99 +python3 scripts/i2i_swing.py --lookback_days 730 --no_daily_session
  100 +```
  101 +
  102 +**效果**:
  103 +- 📈 同时考虑用户整体行为和单日行为
  104 +- 🎯 更精准的物品相似度计算
  105 +- 🔍 捕获用户短期和长期兴趣
  106 +
  107 +**原理**:
  108 +```
  109 +原始数据:
  110 + user_A -> [item1, item2, item3] (跨多天的行为)
  111 +
  112 +Duplicate后:
  113 + user_A -> [item1, item2, item3] # 原始session
  114 + user_A_20241015 -> [item1] # 10月15日session
  115 + user_A_20241016 -> [item2, item3] # 10月16日session
  116 +
  117 +算法同时考虑:
  118 +- 用户整体偏好(跨时间)
  119 +- 用户单日集中行为(同一天购买的商品更相关)
  120 +```
  121 +
  122 +---
  123 +
  124 +### 4. 文档整理与规范化
  125 +
  126 +**问题**: 文档散乱,临时记录太多,命名不规范。
  127 +
  128 +**解决方案**:
  129 +
  130 +#### 4.1 创建统一文档中心
  131 +```
  132 +offline_tasks/doc/
  133 +├── README.md # 文档索引
  134 +├── 从这里开始.md
  135 +├── 快速开始.md
  136 +├── Swing算法使用指南.md
  137 +├── 运行脚本指南.md
  138 +├── 调试指南.md
  139 +├── 离线索引数据规范.md
  140 +├── Redis数据规范.md
  141 +├── 完整索引列表.md
  142 +├── 数据库配置说明.md
  143 +├── 故障排查指南.md
  144 +├── 更新日志.md
  145 +└── Swing实现总结.md
  146 +```
  147 +
  148 +#### 4.2 删除临时文档
  149 +```
  150 +已删除的临时文档(offline_tasks/):
  151 +- MEMORY_MONITORING_UPDATE.md
  152 +- LATEST_UPDATES.md
  153 +- CONTENT_SIMILARITY_UPDATE.md
  154 +- QUICKSTART_NEW.md
  155 +- CHANGES_SUMMARY.md
  156 +- B2B_LOW_FREQUENCY_OPTIMIZATION.md
  157 +- FIX_NAME_MAPPING.md
  158 +- QUICK_DEBUG_SUMMARY.md
  159 +- UPDATE_CONFIG_GUIDE.md
  160 +- FINAL_UPDATE.md
  161 +- FINAL_SUMMARY.md
  162 +- CURRENT_STATUS.md
  163 +- DELIVERY.md
  164 +- PROJECT_SUMMARY.md
  165 +- STRUCTURE.md
  166 +- FIELD_MAPPING.md
  167 +
  168 +已删除的临时文档(根目录):
  169 +- DEBUG_IMPLEMENTATION_SUMMARY.md
  170 +- CONFIG_CHANGES_SUMMARY.md
  171 +- OFFLINE_TASKS_SUMMARY.md
  172 +- OFFLINE_TASKS_README.md
  173 +- tables_structure.md
  174 +```
  175 +
  176 +#### 4.3 文档命名规范
  177 +- ✅ 所有重要文档使用中文名
  178 +- ✅ 统一放在 `doc/` 目录
  179 +- ✅ 创建 `doc/README.md` 索引
  180 +- ✅ collaboration目录下的文档同步规范
  181 +
  182 +---
  183 +
  184 +## 📊 改进效果对比
  185 +
  186 +### 数据库查询优化
  187 +
  188 +**改进前**:
  189 +```
  190 +每次运行任务:
  191 + 1. i2i_swing.py → 查询商品名称
  192 + 2. add_names_to_swing → 查询商品名称
  193 + 3. 其他debug任务 → 重复查询
  194 +
  195 +总查询次数: 5-10次(取决于任务数)
  196 +```
  197 +
  198 +**改进后**:
  199 +```
  200 +每次运行任务:
  201 + 1. fetch_item_attributes.py → 查询1次,保存文件
  202 + 2. 所有后续任务 → 加载本地文件
  203 +
  204 +总查询次数: 1次
  205 +```
  206 +
  207 +**性能提升**: 减少 80-90% 的数据库查询
  208 +
  209 +### Session文件生成
  210 +
  211 +**改进前**:
  212 +```
  213 +- i2i_swing.py 内部查询数据库
  214 +- C++ Swing需要手动准备数据
  215 +```
  216 +
  217 +**改进后**:
  218 +```
  219 +- generate_session.py 统一生成
  220 +- 支持两种格式(标准/C++)
  221 +- 所有算法可复用
  222 +```
  223 +
  224 +### 文档管理
  225 +
  226 +**改进前**:
  227 +- 30+ 散乱的Markdown文件
  228 +- 无明确分类和索引
  229 +- 大量临时记录
  230 +
  231 +**改进后**:
  232 +- 13个核心文档
  233 +- 统一在 doc/ 目录
  234 +- 清晰的索引和分类
  235 +
  236 +---
  237 +
  238 +## 🚀 使用指南
  239 +
  240 +### 运行完整流程
  241 +
  242 +```bash
  243 +cd /home/tw/recommendation/offline_tasks
  244 +
  245 +# 方式1: 运行全部任务(推荐)
  246 +python3 run_all.py --debug
  247 +
  248 +# 方式2: 分步运行
  249 +# 步骤1: 获取商品属性
  250 +python3 scripts/fetch_item_attributes.py
  251 +
  252 +# 步骤2: 生成session文件
  253 +python3 scripts/generate_session.py --lookback_days 730
  254 +
  255 +# 步骤3: 运行Swing算法(启用日期维度)
  256 +python3 scripts/i2i_swing.py --lookback_days 730 --use_daily_session --debug
  257 +```
  258 +
  259 +### C++ Swing算法
  260 +
  261 +```bash
  262 +cd /home/tw/recommendation/collaboration
  263 +
  264 +# session文件自动生成后,运行Swing
  265 +bash run.sh
  266 +```
  267 +
  268 +### 查看文档
  269 +
  270 +```bash
  271 +cd /home/tw/recommendation/offline_tasks/doc
  272 +
  273 +# 查看文档索引
  274 +cat README.md
  275 +
  276 +# 快速开始
  277 +cat 快速开始.md
  278 +
  279 +# 详细使用指南
  280 +cat Swing算法使用指南.md
  281 +```
  282 +
  283 +---
  284 +
  285 +## 📁 文件结构
  286 +
  287 +```
  288 +recommendation/
  289 +├── offline_tasks/
  290 +│ ├── scripts/
  291 +│ │ ├── fetch_item_attributes.py # 新增:前置任务
  292 +│ │ ├── generate_session.py # 已有:session生成
  293 +│ │ ├── add_names_to_swing.py # 修改:使用本地映射
  294 +│ │ ├── i2i_swing.py # 修改:支持日期维度
  295 +│ │ └── debug_utils.py # 修改:添加加载函数
  296 +│ ├── doc/ # 新增:文档中心
  297 +│ │ ├── README.md
  298 +│ │ ├── 快速开始.md
  299 +│ │ ├── Swing算法使用指南.md
  300 +│ │ └── ...
  301 +│ ├── output/
  302 +│ │ ├── item_attributes_mappings.json # 新增:映射文件
  303 +│ │ ├── item_attributes_stats.txt # 新增:统计信息
  304 +│ │ └── session.txt.YYYYMMDD # session文件
  305 +│ ├── run_all.py # 修改:添加前置任务
  306 +│ └── README.md
  307 +└── collaboration/
  308 + ├── run.sh # 已修改:适配session
  309 + ├── Swing快速开始.md # 重命名
  310 + └── ...
  311 +```
  312 +
  313 +---
  314 +
  315 +## 🎯 核心改进点总结
  316 +
  317 +1. **✅ 性能优化**: 减少80-90%的数据库查询
  318 +2. **✅ 架构优化**: 前置任务解耦,数据准备与算法分离
  319 +3. **✅ 功能增强**: Swing算法支持日期维度
  320 +4. **✅ 文档规范**: 统一管理,中文命名,清晰索引
  321 +5. **✅ 代码质量**: 无Linter错误,统一编码规范
  322 +
  323 +---
  324 +
  325 +## 📝 后续建议
  326 +
  327 +### 短期优化
  328 +
  329 +1. **监控与告警**
  330 + - 添加任务执行时间监控
  331 + - 映射文件过期检测
  332 + - 自动重新获取机制
  333 +
  334 +2. **性能优化**
  335 + - Session文件增量更新
  336 + - 映射文件分批加载
  337 + - 并行任务执行
  338 +
  339 +### 长期规划
  340 +
  341 +1. **分布式支持**
  342 + - 多机协同计算
  343 + - 数据分片处理
  344 +
  345 +2. **实时更新**
  346 + - 在线学习机制
  347 + - 增量索引更新
  348 +
  349 +3. **A/B测试框架**
  350 + - 多版本算法对比
  351 + - 效果评估系统
  352 +
  353 +---
  354 +
  355 +## 📞 相关文档
  356 +
  357 +- **快速开始**: [doc/快速开始.md](./快速开始.md)
  358 +- **详细指南**: [doc/Swing算法使用指南.md](./Swing算法使用指南.md)
  359 +- **故障排查**: [doc/故障排查指南.md](./故障排查指南.md)
  360 +- **文档索引**: [doc/README.md](./README.md)
  361 +
  362 +---
  363 +
  364 +**改进完成时间**: 2024-10-17
  365 +**状态**: ✅ 已完成并测试通过
  366 +
offline_tasks/doc/调试指南.md 0 → 100644
@@ -0,0 +1,332 @@ @@ -0,0 +1,332 @@
  1 +# Debug模式使用指南
  2 +
  3 +## 🐛 Debug功能概述
  4 +
  5 +Debug模式为所有离线任务提供:
  6 +1. **详细的DEBUG级别日志** - 显示数据流向、统计信息、处理进度
  7 +2. **明文索引文件** - ID后面带上对应的名称,方便检查效果
  8 +3. **数据采样展示** - 关键步骤的示例数据
  9 +4. **性能统计** - 每个步骤的耗时和资源使用
  10 +
  11 +## 🚀 快速开始
  12 +
  13 +### 1. 运行单个脚本(Debug模式)
  14 +
  15 +```bash
  16 +cd /home/tw/recommendation/offline_tasks
  17 +
  18 +# Swing算法 - Debug模式
  19 +python3 scripts/i2i_swing.py --lookback_days 7 --top_n 10 --debug
  20 +
  21 +# 兴趣聚合 - Debug模式
  22 +python3 scripts/interest_aggregation.py --lookback_days 7 --top_n 100 --debug
  23 +
  24 +# 内容相似 - Debug模式
  25 +python3 scripts/i2i_content_similar.py --top_n 10 --debug
  26 +```
  27 +
  28 +### 2. 运行所有任务(Debug模式)
  29 +
  30 +```bash
  31 +# 使用debug参数运行所有任务
  32 +python3 run_all.py --lookback_days 7 --top_n 10 --debug
  33 +```
  34 +
  35 +## 📊 Debug输出说明
  36 +
  37 +### A. 日志输出
  38 +
  39 +Debug模式下,日志会输出到两个地方:
  40 +1. **控制台** - 实时查看进度
  41 +2. **Debug日志文件** - 完整保存
  42 +
  43 +日志文件位置:
  44 +```
  45 +offline_tasks/logs/debug/i2i_swing_20251016_193000.log
  46 +offline_tasks/logs/debug/interest_aggregation_20251016_193500.log
  47 +...
  48 +```
  49 +
  50 +### B. 日志内容示例
  51 +
  52 +```
  53 +2025-10-16 19:30:00 - i2i_swing - DEBUG - ============================================================
  54 +2025-10-16 19:30:00 - i2i_swing - DEBUG - 算法参数:
  55 +2025-10-16 19:30:00 - i2i_swing - DEBUG - ============================================================
  56 +2025-10-16 19:30:00 - i2i_swing - DEBUG - alpha: 0.5
  57 +2025-10-16 19:30:00 - i2i_swing - DEBUG - top_n: 10
  58 +2025-10-16 19:30:00 - i2i_swing - DEBUG - lookback_days: 7
  59 +2025-10-16 19:30:00 - i2i_swing - DEBUG - debug: True
  60 +2025-10-16 19:30:00 - i2i_swing - DEBUG - ============================================================
  61 +
  62 +2025-10-16 19:30:05 - i2i_swing - INFO - 获取到 15234 条记录
  63 +
  64 +2025-10-16 19:30:05 - i2i_swing - DEBUG - ============================================================
  65 +2025-10-16 19:30:05 - i2i_swing - DEBUG - 用户行为数据 信息:
  66 +2025-10-16 19:30:05 - i2i_swing - DEBUG - ============================================================
  67 +2025-10-16 19:30:05 - i2i_swing - DEBUG - 总行数: 15234
  68 +2025-10-16 19:30:05 - i2i_swing - DEBUG - 总列数: 5
  69 +2025-10-16 19:30:05 - i2i_swing - DEBUG - 列名: ['user_id', 'item_id', 'event_type', 'create_time', 'item_name']
  70 +2025-10-16 19:30:05 - i2i_swing - DEBUG -
  71 +2025-10-16 19:30:05 - i2i_swing - DEBUG - 数据类型:
  72 +2025-10-16 19:30:05 - i2i_swing - DEBUG - user_id: object
  73 +2025-10-16 19:30:05 - i2i_swing - DEBUG - item_id: int64
  74 +2025-10-16 19:30:05 - i2i_swing - DEBUG - event_type: object
  75 +2025-10-16 19:30:05 - i2i_swing - DEBUG - create_time: datetime64[ns]
  76 +2025-10-16 19:30:05 - i2i_swing - DEBUG - item_name: object
  77 +
  78 +2025-10-16 19:30:05 - i2i_swing - DEBUG - 行为类型分布:
  79 +2025-10-16 19:30:05 - i2i_swing - DEBUG - addToCart: 8520 (55.93%)
  80 +2025-10-16 19:30:05 - i2i_swing - DEBUG - contactFactory: 3456 (22.68%)
  81 +2025-10-16 19:30:05 - i2i_swing - DEBUG - purchase: 2134 (14.01%)
  82 +2025-10-16 19:30:05 - i2i_swing - DEBUG - addToPool: 1124 (7.38%)
  83 +
  84 +2025-10-16 19:30:10 - i2i_swing - INFO - 总用户数: 3456, 总商品数: 2345
  85 +2025-10-16 19:30:15 - i2i_swing - DEBUG - 已处理 50/2345 个商品 (2.1%)
  86 +2025-10-16 19:30:20 - i2i_swing - DEBUG - 已处理 100/2345 个商品 (4.3%)
  87 +...
  88 +```
  89 +
  90 +### C. 明文索引文件
  91 +
  92 +Debug模式下,每个索引文件都会生成对应的明文文件:
  93 +
  94 +**原始索引文件** (`output/i2i_swing_20251016.txt`):
  95 +```
  96 +12345 香蕉干 67890:0.8567,11223:0.7234,44556:0.6891
  97 +67890 芒果干 12345:0.8567,22334:0.7123,55667:0.6543
  98 +```
  99 +
  100 +**明文索引文件** (`output/debug/i2i_swing_20251016_readable.txt`):
  101 +```
  102 +================================================================================
  103 +明文索引文件
  104 +生成时间: 2025-10-16 19:35:00
  105 +描述: Swing算法 i2i相似度推荐 (alpha=0.5, lookback_days=7)
  106 +总索引数: 2345
  107 +================================================================================
  108 +
  109 +[1] i2i:swing:12345(香蕉干)
  110 +--------------------------------------------------------------------------------
  111 + 1. ID:67890(芒果干) - Score:0.8567
  112 + 2. ID:11223(菠萝干) - Score:0.7234
  113 + 3. ID:44556(苹果干) - Score:0.6891
  114 + 4. ID:22334(木瓜干) - Score:0.6234
  115 + 5. ID:55667(草莓干) - Score:0.5891
  116 +
  117 +[2] i2i:swing:67890(芒果干)
  118 +--------------------------------------------------------------------------------
  119 + 1. ID:12345(香蕉干) - Score:0.8567
  120 + 2. ID:22334(木瓜干) - Score:0.7123
  121 + 3. ID:55667(草莓干) - Score:0.6543
  122 + 4. ID:11223(菠萝干) - Score:0.6234
  123 + 5. ID:44556(苹果干) - Score:0.5891
  124 +
  125 +...
  126 +
  127 +================================================================================
  128 +已输出 50/2345 个索引
  129 +================================================================================
  130 +```
  131 +
  132 +## 📁 文件结构
  133 +
  134 +Debug模式下的文件组织:
  135 +
  136 +```
  137 +offline_tasks/
  138 +├── output/
  139 +│ ├── i2i_swing_20251016.txt # 原始索引文件
  140 +│ ├── interest_aggregation_hot_20251016.txt
  141 +│ └── debug/ # Debug明文文件目录
  142 +│ ├── i2i_swing_20251016_readable.txt # 明文索引
  143 +│ ├── interest_aggregation_hot_20251016_readable.txt
  144 +│ └── ...
  145 +└── logs/
  146 + ├── run_all_20251016.log # 主日志
  147 + └── debug/ # Debug详细日志目录
  148 + ├── i2i_swing_20251016_193000.log
  149 + ├── interest_aggregation_20251016_193500.log
  150 + └── ...
  151 +```
  152 +
  153 +## 🔍 使用场景
  154 +
  155 +### 场景1:调试数据流程
  156 +
  157 +```bash
  158 +# 使用小数据量+debug模式快速验证
  159 +python3 scripts/i2i_swing.py --lookback_days 1 --top_n 5 --debug
  160 +
  161 +# 查看日志,检查:
  162 +# - 数据加载是否正确
  163 +# - 行为类型分布是否合理
  164 +# - 用户/商品数量是否符合预期
  165 +```
  166 +
  167 +### 场景2:检查推荐效果
  168 +
  169 +```bash
  170 +# 生成明文索引文件
  171 +python3 scripts/i2i_swing.py --lookback_days 7 --top_n 20 --debug
  172 +
  173 +# 打开明文文件查看:
  174 +cat output/debug/i2i_swing_20251016_readable.txt | less
  175 +
  176 +# 检查推荐是否合理,例如:
  177 +# - 香蕉干 -> 芒果干、菠萝干 ✓ 合理
  178 +# - 电脑 -> 香蕉干 ✗ 不合理,需要调整参数
  179 +```
  180 +
  181 +### 场景3:性能调优
  182 +
  183 +```bash
  184 +# Debug模式查看各步骤耗时
  185 +python3 scripts/i2i_swing.py --debug 2>&1 | grep "耗时"
  186 +
  187 +# 输出示例:
  188 +# 步骤1耗时: 2.34秒
  189 +# 步骤2耗时: 15.67秒 <- 瓶颈在这里
  190 +# 步骤3耗时: 1.23秒
  191 +# 总耗时: 19.24秒
  192 +```
  193 +
  194 +### 场景4:参数调整
  195 +
  196 +```bash
  197 +# 测试不同alpha值的效果
  198 +python3 scripts/i2i_swing.py --alpha 0.3 --debug > alpha_0.3.log 2>&1
  199 +python3 scripts/i2i_swing.py --alpha 0.5 --debug > alpha_0.5.log 2>&1
  200 +python3 scripts/i2i_swing.py --alpha 0.7 --debug > alpha_0.7.log 2>&1
  201 +
  202 +# 对比明文文件,选择最佳参数
  203 +diff output/debug/i2i_swing_*_readable.txt
  204 +```
  205 +
  206 +## 💡 最佳实践
  207 +
  208 +### 1. 开发调试阶段
  209 +
  210 +```bash
  211 +# 使用小数据量 + Debug模式
  212 +python3 run_all.py --lookback_days 3 --top_n 10 --debug
  213 +```
  214 +
  215 +- ✅ 快速验证流程
  216 +- ✅ 详细日志便于排错
  217 +- ✅ 明文文件检查效果
  218 +
  219 +### 2. 参数调优阶段
  220 +
  221 +```bash
  222 +# 中等数据量 + Debug模式
  223 +python3 scripts/i2i_swing.py --lookback_days 30 --top_n 50 --debug
  224 +```
  225 +
  226 +- ✅ 查看数据分布
  227 +- ✅ 评估推荐质量
  228 +- ✅ 调整算法参数
  229 +
  230 +### 3. 生产运行阶段
  231 +
  232 +```bash
  233 +# 大数据量 + 正常模式(不加--debug)
  234 +python3 run_all.py --lookback_days 730 --top_n 50
  235 +```
  236 +
  237 +- ✅ 高效运行
  238 +- ✅ 只输出必要日志
  239 +- ✅ 节省磁盘空间
  240 +
  241 +## 🛠️ Debug工具
  242 +
  243 +### 查看实时日志
  244 +
  245 +```bash
  246 +# 实时查看debug日志
  247 +tail -f logs/debug/i2i_swing_*.log
  248 +
  249 +# 只看DEBUG级别
  250 +tail -f logs/debug/i2i_swing_*.log | grep "DEBUG"
  251 +
  252 +# 只看错误
  253 +tail -f logs/debug/i2i_swing_*.log | grep "ERROR"
  254 +```
  255 +
  256 +### 统计分析
  257 +
  258 +```bash
  259 +# 统计处理的数据量
  260 +grep "总行数" logs/debug/*.log
  261 +
  262 +# 统计生成的索引数
  263 +grep "总索引数" output/debug/*_readable.txt
  264 +
  265 +# 查看性能统计
  266 +grep "耗时" logs/debug/*.log
  267 +```
  268 +
  269 +### 快速检查
  270 +
  271 +```bash
  272 +# 检查前10个推荐
  273 +head -50 output/debug/i2i_swing_*_readable.txt
  274 +
  275 +# 搜索特定商品的推荐
  276 +grep "香蕉干" output/debug/i2i_swing_*_readable.txt -A 10
  277 +
  278 +# 统计推荐数量分布
  279 +grep "Score:" output/debug/i2i_swing_*_readable.txt | wc -l
  280 +```
  281 +
  282 +## ⚠️ 注意事项
  283 +
  284 +1. **磁盘空间**
  285 + - Debug日志和明文文件会占用较多空间
  286 + - 建议定期清理:`rm -rf logs/debug/* output/debug/*`
  287 +
  288 +2. **运行时间**
  289 + - Debug模式会增加10-20%的运行时间
  290 + - 生产环境建议关闭debug
  291 +
  292 +3. **敏感信息**
  293 + - 明文文件包含商品名称等信息
  294 + - 注意数据安全和隐私保护
  295 +
  296 +4. **文件编码**
  297 + - 明文文件使用UTF-8编码
  298 + - 确保查看工具支持中文显示
  299 +
  300 +## 📖 相关命令
  301 +
  302 +```bash
  303 +# 查看帮助
  304 +python3 scripts/i2i_swing.py --help
  305 +python3 run_all.py --help
  306 +
  307 +# 验证配置
  308 +python3 -c "from config.offline_config import DEBUG_CONFIG; print(DEBUG_CONFIG)"
  309 +
  310 +# 测试debug工具
  311 +python3 -c "from scripts.debug_utils import *; print('Debug utils loaded OK')"
  312 +```
  313 +
  314 +## ✅ 验证Debug功能
  315 +
  316 +```bash
  317 +# 快速测试
  318 +cd /home/tw/recommendation/offline_tasks
  319 +python3 scripts/i2i_swing.py --lookback_days 1 --top_n 5 --debug
  320 +
  321 +# 应该看到:
  322 +# ✓ DEBUG级别日志输出
  323 +# ✓ 创建debug日志文件
  324 +# ✓ 生成明文索引文件
  325 +# ✓ 显示数据统计信息
  326 +```
  327 +
  328 +---
  329 +
  330 +**Debug模式**: 开发和调试的利器
  331 +**正常模式**: 生产环境的选择
  332 +**灵活切换**: 一个参数的事情
offline_tasks/doc/运行脚本指南.md 0 → 100644
@@ -0,0 +1,304 @@ @@ -0,0 +1,304 @@
  1 +# run.sh 运行脚本使用指南
  2 +
  3 +## 概述
  4 +
  5 +`run.sh` 是一个自动化运行脚本,集成了内存监控功能,确保离线任务安全高效运行。
  6 +
  7 +## 主要特性
  8 +
  9 +### 1. 内存监控
  10 +- **警告阈值**: 25GB - 打印警告日志
  11 +- **强制终止阈值**: 30GB - 自动kill进程
  12 +- **检查频率**: 每10秒检查一次
  13 +- **日志文件**: `logs/memory_monitor.log`
  14 +
  15 +### 2. 任务流程
  16 +1. 清理旧进程和输出
  17 +2. 运行调试模式(小数据量测试)
  18 +3. 运行生产模式(大数据量)
  19 +4. 加载索引到Redis
  20 +
  21 +### 3. 错误处理
  22 +- 任何步骤失败会立即退出
  23 +- 显示详细的退出码
  24 +- 保存完整日志
  25 +
  26 +## 使用方法
  27 +
  28 +### 基本运行
  29 +```bash
  30 +cd /home/tw/recommendation/offline_tasks
  31 +./run.sh
  32 +```
  33 +
  34 +### 查看实时输出
  35 +```bash
  36 +./run.sh | tee logs/run_$(date +%Y%m%d_%H%M%S).log
  37 +```
  38 +
  39 +### 后台运行
  40 +```bash
  41 +nohup ./run.sh > logs/run_$(date +%Y%m%d_%H%M%S).log 2>&1 &
  42 +```
  43 +
  44 +## 内存监控说明
  45 +
  46 +### 监控逻辑
  47 +
  48 +```bash
  49 +check_memory() {
  50 + local pid=$1
  51 + local threshold_warn=25 # 25GB警告
  52 + local threshold_kill=30 # 30GB强制kill
  53 +
  54 + while 进程运行中; do
  55 + 获取内存使用
  56 +
  57 + if 内存 >= 30GB:
  58 + 打印错误日志
  59 + 强制终止进程
  60 + break
  61 + elif 内存 >= 25GB:
  62 + 打印警告日志
  63 +
  64 + sleep 10秒
  65 + done
  66 +}
  67 +```
  68 +
  69 +### 日志格式
  70 +
  71 +**警告日志**:
  72 +```
  73 +[2025-10-17 14:30:25] ⚠️ 内存警告!当前使用: 26.45GB (>= 25GB), PID=12345
  74 +```
  75 +
  76 +**强制终止日志**:
  77 +```
  78 +[2025-10-17 14:35:30] ❌ 内存超限!当前使用: 31.20GB (>= 30GB), 强制终止进程 PID=12345
  79 +```
  80 +
  81 +### 查看监控日志
  82 +```bash
  83 +# 实时查看
  84 +tail -f logs/memory_monitor.log
  85 +
  86 +# 查看历史
  87 +cat logs/memory_monitor.log
  88 +```
  89 +
  90 +## 运行流程
  91 +
  92 +### 步骤1: 调试模式
  93 +```bash
  94 +python3 run_all.py --debug
  95 +```
  96 +- 使用默认参数(见 `offline_config.py`)
  97 +- 输出保存到 `output_debug/`
  98 +- 启动内存监控
  99 +
  100 +### 步骤2: 生产模式
  101 +```bash
  102 +python3 run_all.py --debug
  103 +```
  104 +- 生成完整索引
  105 +- 输出保存到 `output/`
  106 +- 启动内存监控
  107 +
  108 +### 步骤3: 加载Redis
  109 +```bash
  110 +python3 scripts/load_index_to_redis.py --redis-host localhost
  111 +```
  112 +- 加载所有生成的索引
  113 +- 包括新增的内容相似索引
  114 +
  115 +## 输出示例
  116 +
  117 +```
  118 +======================================================================
  119 +开始运行离线任务 - 2025-10-17 14:00:00
  120 +内存监控: 警告阈值=25GB, 强制终止阈值=30GB
  121 +======================================================================
  122 +
  123 +>>> 步骤1: 调试模式运行(小数据量)
  124 +调试任务 PID: 12345
  125 +✓ 调试模式完成
  126 +
  127 +>>> 步骤2: 生产模式运行(大数据量)
  128 +生产任务 PID: 12346
  129 +[2025-10-17 14:30:25] ⚠️ 内存警告!当前使用: 26.45GB (>= 25GB), PID=12346
  130 +✓ 生产模式完成
  131 +
  132 +>>> 步骤3: 加载到Redis
  133 +✓ Redis加载完成
  134 +
  135 +======================================================================
  136 +所有任务完成 - 2025-10-17 16:30:00
  137 +======================================================================
  138 +```
  139 +
  140 +## 自定义配置
  141 +
  142 +### 修改内存阈值
  143 +
  144 +编辑 `run.sh` 中的以下行:
  145 +```bash
  146 +local threshold_warn=25 # 修改警告阈值
  147 +local threshold_kill=30 # 修改强制kill阈值
  148 +```
  149 +
  150 +### 修改检查频率
  151 +
  152 +编辑 `run.sh` 中的以下行:
  153 +```bash
  154 +sleep 10 # 修改为其他秒数
  155 +```
  156 +
  157 +### 跳过调试模式
  158 +
  159 +注释掉步骤1相关代码:
  160 +```bash
  161 +# # 3. 调试模式运行(小数据量)
  162 +# echo ""
  163 +# echo ">>> 步骤1: 调试模式运行(小数据量)"
  164 +# python3 run_all.py --debug &
  165 +# ...
  166 +```
  167 +
  168 +### 修改Redis配置
  169 +
  170 +修改步骤3的参数:
  171 +```bash
  172 +python3 scripts/load_index_to_redis.py \
  173 + --redis-host your-redis-host \
  174 + --redis-port 6379 \
  175 + --redis-db 0
  176 +```
  177 +
  178 +## 故障排查
  179 +
  180 +### 内存持续超限
  181 +
  182 +**原因**:
  183 +- 数据量太大
  184 +- 内存泄漏
  185 +- 并发任务过多
  186 +
  187 +**解决方案**:
  188 +1. 增加内存阈值(临时方案)
  189 +2. 优化代码减少内存占用
  190 +3. 分批处理数据
  191 +4. 使用增量更新
  192 +
  193 +### 进程被意外终止
  194 +
  195 +**检查日志**:
  196 +```bash
  197 +# 查看监控日志
  198 +cat logs/memory_monitor.log
  199 +
  200 +# 查看任务日志
  201 +ls -lht logs/
  202 +cat logs/run_all_*.log
  203 +```
  204 +
  205 +### 任务失败
  206 +
  207 +**查看退出码**:
  208 +- 0: 成功
  209 +- 1: 一般错误
  210 +- 137: 被kill信号终止(可能是内存超限)
  211 +- 其他: 查看具体错误信息
  212 +
  213 +## 监控建议
  214 +
  215 +### 1. 添加系统监控
  216 +```bash
  217 +# 安装监控工具
  218 +apt install htop iotop
  219 +
  220 +# 实时监控
  221 +htop -p $(pgrep -f run_all.py)
  222 +```
  223 +
  224 +### 2. 设置告警
  225 +```bash
  226 +# 配置邮件告警
  227 +if [ $PROD_EXIT_CODE -ne 0 ]; then
  228 + echo "任务失败" | mail -s "离线任务告警" admin@example.com
  229 +fi
  230 +```
  231 +
  232 +### 3. 定时任务
  233 +```bash
  234 +# 添加到crontab
  235 +0 2 * * * /home/tw/recommendation/offline_tasks/run.sh >> /var/log/offline_tasks.log 2>&1
  236 +```
  237 +
  238 +## 性能优化
  239 +
  240 +### 内存优化建议
  241 +
  242 +1. **分批处理**
  243 + ```python
  244 + # 在代码中使用batch处理
  245 + batch_size = 1000
  246 + for i in range(0, len(items), batch_size):
  247 + batch = items[i:i+batch_size]
  248 + process(batch)
  249 + ```
  250 +
  251 +2. **及时释放**
  252 + ```python
  253 + import gc
  254 + del large_object
  255 + gc.collect()
  256 + ```
  257 +
  258 +3. **使用生成器**
  259 + ```python
  260 + def process_items():
  261 + for item in items:
  262 + yield process(item)
  263 + ```
  264 +
  265 +## 日志管理
  266 +
  267 +### 日志文件
  268 +- `logs/memory_monitor.log` - 内存监控日志
  269 +- `logs/run_all_YYYYMMDD.log` - 任务运行日志
  270 +- `output/` - 生成的索引文件
  271 +- `output_debug/` - 调试模式输出
  272 +
  273 +### 清理旧日志
  274 +```bash
  275 +# 保留最近7天
  276 +find logs/ -name "*.log" -mtime +7 -delete
  277 +
  278 +# 压缩旧日志
  279 +find logs/ -name "*.log" -mtime +3 -exec gzip {} \;
  280 +```
  281 +
  282 +## 安全注意事项
  283 +
  284 +1. **权限**: 确保脚本有执行权限 `chmod +x run.sh`
  285 +2. **路径**: 使用绝对路径避免混淆
  286 +3. **清理**: 脚本会清理旧进程,确保没有重要进程被误杀
  287 +4. **备份**: 脚本会删除output目录,请提前备份重要数据
  288 +
  289 +## 总结
  290 +
  291 +`run.sh` 提供了:
  292 +- ✅ 自动化运行流程
  293 +- ✅ 内存监控保护
  294 +- ✅ 详细日志记录
  295 +- ✅ 错误处理机制
  296 +- ✅ 进度显示
  297 +
  298 +建议在生产环境使用前先在测试环境验证。
  299 +
  300 +---
  301 +
  302 +**更新时间**: 2025-10-17
  303 +**版本**: v2.0
  304 +
offline_tasks/run.sh
@@ -29,12 +29,6 @@ check_memory() { @@ -29,12 +29,6 @@ check_memory() {
29 done 29 done
30 } 30 }
31 31
32 -# # 查看配置指南  
33 -# cat UPDATE_CONFIG_GUIDE.md  
34 -  
35 -# 2. 测试连接  
36 -# python3 test_connection.py  
37 -  
38 # 清理旧进程 32 # 清理旧进程
39 ps -ef|grep run_all.py | awk '{print $2}' | xargs kill -9 2>/dev/null 33 ps -ef|grep run_all.py | awk '{print $2}' | xargs kill -9 2>/dev/null
40 ps -ef|grep recommendation | awk '{print $2}' | xargs kill -9 2>/dev/null 34 ps -ef|grep recommendation | awk '{print $2}' | xargs kill -9 2>/dev/null
@@ -50,7 +44,8 @@ echo &quot;======================================================================&quot; @@ -50,7 +44,8 @@ echo &quot;======================================================================&quot;
50 44
51 echo "" 45 echo ""
52 echo ">>> run_all.py" 46 echo ">>> run_all.py"
53 -python3 run_all.py --debug 47 +# python3 run_all.py --lookback_days 400 --top_n 50 --debug &
  48 +python3 run_all.py --debug &
54 PID_PROD=$! 49 PID_PROD=$!
55 echo "生产任务 PID: $PID_PROD" 50 echo "生产任务 PID: $PID_PROD"
56 51
offline_tasks/run_all.py
@@ -95,6 +95,35 @@ def main(): @@ -95,6 +95,35 @@ def main():
95 success_count = 0 95 success_count = 0
96 total_count = 0 96 total_count = 0
97 97
  98 + # 前置任务1: 获取item基础属性
  99 + logger.info("\n" + "="*80)
  100 + logger.info("前置任务1: 获取商品基础属性(ID->名称映射)")
  101 + logger.info("="*80)
  102 + total_count += 1
  103 + script_args = []
  104 + if args.debug:
  105 + script_args.append('--debug')
  106 + if run_script('fetch_item_attributes.py', script_args):
  107 + success_count += 1
  108 + else:
  109 + logger.error("获取商品属性失败,后续任务可能无法生成可读文件")
  110 +
  111 + # 前置任务2: 生成session文件
  112 + logger.info("\n" + "="*80)
  113 + logger.info("前置任务2: 生成用户行为Session文件")
  114 + logger.info("="*80)
  115 + total_count += 1
  116 + script_args = [
  117 + '--lookback_days', str(DEFAULT_LOOKBACK_DAYS),
  118 + '--format', 'both'
  119 + ]
  120 + if args.debug:
  121 + script_args.append('--debug')
  122 + if run_script('generate_session.py', script_args):
  123 + success_count += 1
  124 + else:
  125 + logger.error("生成session文件失败")
  126 +
98 # i2i 行为相似任务 127 # i2i 行为相似任务
99 logger.info("\n" + "="*80) 128 logger.info("\n" + "="*80)
100 logger.info("Task 1: Running Swing algorithm for i2i similarity") 129 logger.info("Task 1: Running Swing algorithm for i2i similarity")
offline_tasks/scripts/add_names_to_swing.py
@@ -9,9 +9,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath( @@ -9,9 +9,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(
9 9
10 import argparse 10 import argparse
11 from datetime import datetime 11 from datetime import datetime
12 -from db_service import create_db_connection  
13 -from offline_tasks.config.offline_config import DB_CONFIG  
14 -from offline_tasks.scripts.debug_utils import setup_debug_logger, fetch_name_mappings 12 +from offline_tasks.scripts.debug_utils import setup_debug_logger, load_name_mappings_from_file
15 13
16 14
17 def add_names_to_swing_result(input_file, output_file, name_mappings, logger=None, debug=False): 15 def add_names_to_swing_result(input_file, output_file, name_mappings, logger=None, debug=False):
@@ -110,20 +108,16 @@ def main(): @@ -110,20 +108,16 @@ def main():
110 logger.error(f"输入文件不存在: {args.input_file}") 108 logger.error(f"输入文件不存在: {args.input_file}")
111 return 109 return
112 110
113 - # 创建数据库连接  
114 - logger.info("连接数据库...")  
115 - engine = create_db_connection(  
116 - DB_CONFIG['host'],  
117 - DB_CONFIG['port'],  
118 - DB_CONFIG['database'],  
119 - DB_CONFIG['username'],  
120 - DB_CONFIG['password']  
121 - ) 111 + # 从本地文件加载名称映射
  112 + logger.info("加载ID到名称的映射...")
  113 + name_mappings = load_name_mappings_from_file(debug=args.debug)
  114 +
  115 + if not name_mappings or not name_mappings.get('item'):
  116 + logger.error("映射文件为空或加载失败")
  117 + logger.error("请先运行: python3 scripts/fetch_item_attributes.py")
  118 + return
122 119
123 - # 获取名称映射  
124 - logger.info("获取ID到名称的映射...")  
125 - name_mappings = fetch_name_mappings(engine, debug=args.debug)  
126 - logger.info(f"获取到 {len(name_mappings['item'])} 个商品名称") 120 + logger.info(f"加载了 {len(name_mappings['item'])} 个商品名称")
127 121
128 # 处理文件 122 # 处理文件
129 add_names_to_swing_result( 123 add_names_to_swing_result(
offline_tasks/scripts/debug_utils.py
@@ -255,9 +255,60 @@ def format_key_with_name(key, name_mappings): @@ -255,9 +255,60 @@ def format_key_with_name(key, name_mappings):
255 return ':'.join(formatted_parts) 255 return ':'.join(formatted_parts)
256 256
257 257
  258 +def load_name_mappings_from_file(mappings_file=None, debug=False):
  259 + """
  260 + 从本地文件加载ID到名称的映射(推荐使用)
  261 + 避免重复查询数据库,提高性能
  262 +
  263 + Args:
  264 + mappings_file: 映射文件路径(如果为None,使用默认路径)
  265 + debug: 是否输出debug信息
  266 +
  267 + Returns:
  268 + name_mappings字典
  269 + """
  270 + if mappings_file is None:
  271 + # 默认路径
  272 + base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  273 + mappings_file = os.path.join(base_dir, 'output', 'item_attributes_mappings.json')
  274 +
  275 + if not os.path.exists(mappings_file):
  276 + if debug:
  277 + print(f"✗ 映射文件不存在: {mappings_file}")
  278 + print(f" 请先运行 fetch_item_attributes.py 生成映射文件")
  279 + return {
  280 + 'item': {},
  281 + 'category': {},
  282 + 'platform': {},
  283 + 'supplier': {},
  284 + 'client_platform': {}
  285 + }
  286 +
  287 + try:
  288 + with open(mappings_file, 'r', encoding='utf-8') as f:
  289 + mappings = json.load(f)
  290 +
  291 + if debug:
  292 + print(f"✓ 从文件加载映射: {mappings_file}")
  293 + for key, value in mappings.items():
  294 + print(f" {key}: {len(value)} 个映射")
  295 +
  296 + return mappings
  297 + except Exception as e:
  298 + if debug:
  299 + print(f"✗ 加载映射文件失败: {e}")
  300 + return {
  301 + 'item': {},
  302 + 'category': {},
  303 + 'platform': {},
  304 + 'supplier': {},
  305 + 'client_platform': {}
  306 + }
  307 +
  308 +
258 def fetch_name_mappings(engine, debug=False): 309 def fetch_name_mappings(engine, debug=False):
259 """ 310 """
260 - 从数据库获取ID到名称的映射 311 + 从数据库获取ID到名称的映射(已弃用,建议使用load_name_mappings_from_file)
261 312
262 Args: 313 Args:
263 engine: 数据库连接 314 engine: 数据库连接
@@ -268,6 +319,10 @@ def fetch_name_mappings(engine, debug=False): @@ -268,6 +319,10 @@ def fetch_name_mappings(engine, debug=False):
268 """ 319 """
269 import pandas as pd 320 import pandas as pd
270 321
  322 + if debug:
  323 + print("⚠️ 警告: 使用fetch_name_mappings直接查询数据库")
  324 + print(" 建议使用load_name_mappings_from_file加载本地映射文件")
  325 +
271 mappings = { 326 mappings = {
272 'item': {}, 327 'item': {},
273 'category': {}, 328 'category': {},
offline_tasks/scripts/fetch_item_attributes.py 0 → 100644
@@ -0,0 +1,179 @@ @@ -0,0 +1,179 @@
  1 +"""
  2 +获取商品基础属性(前置任务)
  3 +从数据库获取ID->名称的映射,保存到本地文件供其他任务使用
  4 +避免每个任务重复查询数据库
  5 +"""
  6 +import sys
  7 +import os
  8 +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
  9 +
  10 +import pandas as pd
  11 +import json
  12 +import argparse
  13 +from datetime import datetime
  14 +from db_service import create_db_connection
  15 +from offline_tasks.config.offline_config import DB_CONFIG, OUTPUT_DIR
  16 +from offline_tasks.scripts.debug_utils import setup_debug_logger
  17 +
  18 +
  19 +def fetch_and_save_mappings(engine, output_dir, logger=None, debug=False):
  20 + """
  21 + 从数据库获取各种ID->名称映射并保存
  22 +
  23 + Args:
  24 + engine: 数据库连接
  25 + output_dir: 输出目录
  26 + logger: 日志记录器
  27 + debug: 是否开启debug模式
  28 +
  29 + Returns:
  30 + mappings字典和输出文件路径
  31 + """
  32 + if logger:
  33 + logger.info("开始获取ID到名称的映射...")
  34 +
  35 + mappings = {
  36 + 'item': {},
  37 + 'category': {},
  38 + 'platform': {},
  39 + 'supplier': {},
  40 + 'client_platform': {}
  41 + }
  42 +
  43 + stats = {}
  44 +
  45 + # 1. 获取商品名称
  46 + try:
  47 + if logger:
  48 + logger.info("获取商品名称...")
  49 + query = "SELECT id, name FROM prd_goods_sku WHERE status IN (2,4,5) LIMIT 5000000"
  50 + df = pd.read_sql(query, engine)
  51 + mappings['item'] = dict(zip(df['id'].astype(str), df['name']))
  52 + stats['item'] = len(mappings['item'])
  53 + if logger:
  54 + logger.info(f"✓ 获取到 {stats['item']} 个商品名称")
  55 + except Exception as e:
  56 + if logger:
  57 + logger.error(f"✗ 获取商品名称失败: {e}")
  58 + stats['item'] = 0
  59 +
  60 + # 2. 获取分类名称
  61 + try:
  62 + if logger:
  63 + logger.info("获取分类名称...")
  64 + query = "SELECT id, name FROM prd_category LIMIT 100000"
  65 + df = pd.read_sql(query, engine)
  66 + mappings['category'] = dict(zip(df['id'].astype(str), df['name']))
  67 + stats['category'] = len(mappings['category'])
  68 + if logger:
  69 + logger.info(f"✓ 获取到 {stats['category']} 个分类名称")
  70 + except Exception as e:
  71 + if logger:
  72 + logger.error(f"✗ 获取分类名称失败: {e}")
  73 + stats['category'] = 0
  74 +
  75 + # 3. 获取供应商名称
  76 + try:
  77 + if logger:
  78 + logger.info("获取供应商名称...")
  79 + query = "SELECT id, name FROM sup_supplier LIMIT 100000"
  80 + df = pd.read_sql(query, engine)
  81 + mappings['supplier'] = dict(zip(df['id'].astype(str), df['name']))
  82 + stats['supplier'] = len(mappings['supplier'])
  83 + if logger:
  84 + logger.info(f"✓ 获取到 {stats['supplier']} 个供应商名称")
  85 + except Exception as e:
  86 + if logger:
  87 + logger.error(f"✗ 获取供应商名称失败: {e}")
  88 + stats['supplier'] = 0
  89 +
  90 + # 4. 平台名称(硬编码)
  91 + mappings['platform'] = {
  92 + 'pc': 'PC端',
  93 + 'h5': 'H5移动端',
  94 + 'app': 'APP',
  95 + 'miniprogram': '小程序',
  96 + 'wechat': '微信'
  97 + }
  98 + stats['platform'] = len(mappings['platform'])
  99 +
  100 + # 5. 客户端平台(硬编码)
  101 + mappings['client_platform'] = {
  102 + 'iOS': 'iOS',
  103 + 'Android': 'Android',
  104 + 'Web': 'Web',
  105 + 'H5': 'H5'
  106 + }
  107 + stats['client_platform'] = len(mappings['client_platform'])
  108 +
  109 + # 保存到文件
  110 + os.makedirs(output_dir, exist_ok=True)
  111 + output_file = os.path.join(output_dir, 'item_attributes_mappings.json')
  112 +
  113 + if logger:
  114 + logger.info(f"保存映射到: {output_file}")
  115 +
  116 + with open(output_file, 'w', encoding='utf-8') as f:
  117 + json.dump(mappings, f, ensure_ascii=False, indent=2)
  118 +
  119 + # 保存统计信息
  120 + stats_file = os.path.join(output_dir, 'item_attributes_stats.txt')
  121 + with open(stats_file, 'w', encoding='utf-8') as f:
  122 + f.write(f"商品属性映射统计信息\n")
  123 + f.write(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
  124 + f.write(f"=" * 60 + "\n")
  125 + for key, count in stats.items():
  126 + f.write(f"{key}: {count}\n")
  127 + f.write(f"=" * 60 + "\n")
  128 + f.write(f"总计: {sum(stats.values())}\n")
  129 +
  130 + if logger:
  131 + logger.info(f"统计信息已保存到: {stats_file}")
  132 + logger.info(f"总计获取 {sum(stats.values())} 个映射")
  133 +
  134 + return mappings, output_file
  135 +
  136 +
  137 +def main():
  138 + parser = argparse.ArgumentParser(description='Fetch item attributes and save mappings')
  139 + parser.add_argument('--output_dir', type=str, default=OUTPUT_DIR,
  140 + help='Output directory for mappings file')
  141 + parser.add_argument('--debug', action='store_true',
  142 + help='Enable debug mode with detailed logging')
  143 +
  144 + args = parser.parse_args()
  145 +
  146 + # 设置日志
  147 + logger = setup_debug_logger('fetch_item_attributes', debug=args.debug)
  148 +
  149 + logger.info("="*60)
  150 + logger.info("商品属性获取任务(前置任务)")
  151 + logger.info("="*60)
  152 +
  153 + # 创建数据库连接
  154 + logger.info("连接数据库...")
  155 + engine = create_db_connection(
  156 + DB_CONFIG['host'],
  157 + DB_CONFIG['port'],
  158 + DB_CONFIG['database'],
  159 + DB_CONFIG['username'],
  160 + DB_CONFIG['password']
  161 + )
  162 +
  163 + # 获取并保存映射
  164 + mappings, output_file = fetch_and_save_mappings(
  165 + engine,
  166 + args.output_dir,
  167 + logger=logger,
  168 + debug=args.debug
  169 + )
  170 +
  171 + logger.info("="*60)
  172 + logger.info("✓ 商品属性获取完成!")
  173 + logger.info(f"映射文件: {output_file}")
  174 + logger.info("="*60)
  175 +
  176 +
  177 +if __name__ == '__main__':
  178 + main()
  179 +
offline_tasks/scripts/i2i_swing.py
@@ -20,7 +20,7 @@ from offline_tasks.config.offline_config import ( @@ -20,7 +20,7 @@ from offline_tasks.config.offline_config import (
20 ) 20 )
21 from offline_tasks.scripts.debug_utils import ( 21 from offline_tasks.scripts.debug_utils import (
22 setup_debug_logger, log_dataframe_info, log_dict_stats, 22 setup_debug_logger, log_dataframe_info, log_dict_stats,
23 - save_readable_index, fetch_name_mappings, log_algorithm_params, 23 + save_readable_index, load_name_mappings_from_file, log_algorithm_params,
24 log_processing_step 24 log_processing_step
25 ) 25 )
26 26
@@ -51,7 +51,7 @@ def calculate_time_weight(event_time, reference_time, decay_factor=0.95, days_un @@ -51,7 +51,7 @@ def calculate_time_weight(event_time, reference_time, decay_factor=0.95, days_un
51 return weight 51 return weight
52 52
53 53
54 -def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, logger=None, debug=False): 54 +def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, use_daily_session=True, logger=None, debug=False):
55 """ 55 """
56 Swing算法实现 56 Swing算法实现
57 57
@@ -60,6 +60,7 @@ def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, logger=No @@ -60,6 +60,7 @@ def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, logger=No
60 alpha: Swing算法的alpha参数 60 alpha: Swing算法的alpha参数
61 time_decay: 是否使用时间衰减 61 time_decay: 是否使用时间衰减
62 decay_factor: 时间衰减因子 62 decay_factor: 时间衰减因子
  63 + use_daily_session: 是否同时使用uid+日期作为session维度
63 logger: 日志记录器 64 logger: 日志记录器
64 debug: 是否开启debug模式 65 debug: 是否开启debug模式
65 66
@@ -68,7 +69,7 @@ def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, logger=No @@ -68,7 +69,7 @@ def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, logger=No
68 """ 69 """
69 start_time = datetime.now() 70 start_time = datetime.now()
70 if logger: 71 if logger:
71 - logger.debug(f"开始Swing算法计算,参数: alpha={alpha}, time_decay={time_decay}") 72 + logger.debug(f"开始Swing算法计算,参数: alpha={alpha}, time_decay={time_decay}, use_daily_session={use_daily_session}")
72 73
73 # 如果使用时间衰减,计算时间权重 74 # 如果使用时间衰减,计算时间权重
74 reference_time = datetime.now() 75 reference_time = datetime.now()
@@ -82,6 +83,27 @@ def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, logger=No @@ -82,6 +83,27 @@ def swing_algorithm(df, alpha=0.5, time_decay=True, decay_factor=0.95, logger=No
82 if logger and debug: 83 if logger and debug:
83 logger.debug(f"时间权重统计: min={df['time_weight'].min():.4f}, max={df['time_weight'].max():.4f}, avg={df['time_weight'].mean():.4f}") 84 logger.debug(f"时间权重统计: min={df['time_weight'].min():.4f}, max={df['time_weight'].max():.4f}, avg={df['time_weight'].mean():.4f}")
84 85
  86 + # 如果启用daily_session,duplicate数据:添加uid+date作为新的uid
  87 + if use_daily_session and 'create_time' in df.columns:
  88 + if logger:
  89 + logger.info("启用日期维度:duplicate数据,添加uid+日期作为新的session")
  90 +
  91 + # 创建原始数据副本
  92 + df_original = df.copy()
  93 +
  94 + # 创建uid+date版本
  95 + df_daily = df.copy()
  96 + df_daily['date'] = pd.to_datetime(df_daily['create_time']).dt.strftime('%Y%m%d')
  97 + df_daily['user_id'] = df_daily['user_id'].astype(str) + '_' + df_daily['date']
  98 +
  99 + # 合并两份数据
  100 + df = pd.concat([df_original, df_daily], ignore_index=True)
  101 +
  102 + if logger:
  103 + logger.info(f"原始数据: {len(df_original)} 条")
  104 + logger.info(f"日期维度数据: {len(df_daily)} 条")
  105 + logger.info(f"合并后总数据: {len(df)} 条")
  106 +
85 # 构建用户-物品倒排索引 107 # 构建用户-物品倒排索引
86 if logger: 108 if logger:
87 log_processing_step(logger, "步骤1: 构建用户-物品倒排索引") 109 log_processing_step(logger, "步骤1: 构建用户-物品倒排索引")
@@ -201,6 +223,10 @@ def main(): @@ -201,6 +223,10 @@ def main():
201 help='Use time decay for behavior weights (default: False for B2B low-frequency scenarios)') 223 help='Use time decay for behavior weights (default: False for B2B low-frequency scenarios)')
202 parser.add_argument('--decay_factor', type=float, default=0.95, 224 parser.add_argument('--decay_factor', type=float, default=0.95,
203 help='Time decay factor') 225 help='Time decay factor')
  226 + parser.add_argument('--use_daily_session', action='store_true', default=True,
  227 + help='Use uid+date as additional session dimension (default: True)')
  228 + parser.add_argument('--no_daily_session', action='store_false', dest='use_daily_session',
  229 + help='Disable uid+date session dimension')
204 parser.add_argument('--output', type=str, default=None, 230 parser.add_argument('--output', type=str, default=None,
205 help='Output file path') 231 help='Output file path')
206 parser.add_argument('--debug', action='store_true', 232 parser.add_argument('--debug', action='store_true',
@@ -218,6 +244,7 @@ def main(): @@ -218,6 +244,7 @@ def main():
218 'lookback_days': args.lookback_days, 244 'lookback_days': args.lookback_days,
219 'time_decay': args.time_decay, 245 'time_decay': args.time_decay,
220 'decay_factor': args.decay_factor, 246 'decay_factor': args.decay_factor,
  247 + 'use_daily_session': args.use_daily_session,
221 'debug': args.debug 248 'debug': args.debug
222 }) 249 })
223 250
@@ -299,6 +326,7 @@ def main(): @@ -299,6 +326,7 @@ def main():
299 alpha=args.alpha, 326 alpha=args.alpha,
300 time_decay=args.time_decay, 327 time_decay=args.time_decay,
301 decay_factor=args.decay_factor, 328 decay_factor=args.decay_factor,
  329 + use_daily_session=args.use_daily_session,
302 logger=logger, 330 logger=logger,
303 debug=args.debug 331 debug=args.debug
304 ) 332 )
@@ -333,9 +361,9 @@ def main(): @@ -333,9 +361,9 @@ def main():
333 if args.debug: 361 if args.debug:
334 logger.info("Debug模式:生成明文索引文件...") 362 logger.info("Debug模式:生成明文索引文件...")
335 try: 363 try:
336 - # 获取名称映射  
337 - logger.debug("获取ID到名称的映射...")  
338 - name_mappings = fetch_name_mappings(engine, debug=True) 364 + # 从本地文件加载名称映射
  365 + logger.debug("加载ID到名称的映射...")
  366 + name_mappings = load_name_mappings_from_file(debug=True)
339 367
340 # 准备索引数据(合并已有的item_name_map) 368 # 准备索引数据(合并已有的item_name_map)
341 # item_name_map的key已经是str类型,可以直接更新 369 # item_name_map的key已经是str类型,可以直接更新