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   -# 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   -# 离线任务更新总结
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   -# 内容相似索引更新说明
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   -# 当前状态说明
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   -# 推荐系统离线任务 - 交付文档
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   -# 数据库字段映射说明
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   -# 内容相似索引重构 - 最终总结
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   -# 最终更新说明
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   -# 商品名称映射问题修复
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   -# 最新更新 (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   -# 内存监控功能更新
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   -# 推荐系统离线任务 - 项目总结
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   -# 快速开始 - 新版本
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   -# 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   -# 项目目录结构
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   -# 配置参数调整指南
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 28 # ============================================================================
29 29  
30 30 # 时间配置(建议先用小数值调试,确认无误后再改为大数值)
31   -DEFAULT_LOOKBACK_DAYS = 730 # 默认回看天数(调试用30天,生产可改为730天)
  31 +DEFAULT_LOOKBACK_DAYS = 400 # 默认回看天数(调试用30天,生产可改为730天)
32 32 DEFAULT_RECENT_DAYS = 180 # 默认最近天数(调试用7天,生产可改为180天)
33 33  
34 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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 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 33 ps -ef|grep run_all.py | awk '{print $2}' | xargs kill -9 2>/dev/null
40 34 ps -ef|grep recommendation | awk '{print $2}' | xargs kill -9 2>/dev/null
... ... @@ -50,7 +44,8 @@ echo &quot;======================================================================&quot;
50 44  
51 45 echo ""
52 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 49 PID_PROD=$!
55 50 echo "生产任务 PID: $PID_PROD"
56 51  
... ...
offline_tasks/run_all.py
... ... @@ -95,6 +95,35 @@ def main():
95 95 success_count = 0
96 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 127 # i2i 行为相似任务
99 128 logger.info("\n" + "="*80)
100 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  
10 10 import argparse
11 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 15 def add_names_to_swing_result(input_file, output_file, name_mappings, logger=None, debug=False):
... ... @@ -110,20 +108,16 @@ def main():
110 108 logger.error(f"输入文件不存在: {args.input_file}")
111 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 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 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 309 def fetch_name_mappings(engine, debug=False):
259 310 """
260   - 从数据库获取ID到名称的映射
  311 + 从数据库获取ID到名称的映射(已弃用,建议使用load_name_mappings_from_file)
261 312  
262 313 Args:
263 314 engine: 数据库连接
... ... @@ -268,6 +319,10 @@ def fetch_name_mappings(engine, debug=False):
268 319 """
269 320 import pandas as pd
270 321  
  322 + if debug:
  323 + print("⚠️ 警告: 使用fetch_name_mappings直接查询数据库")
  324 + print(" 建议使用load_name_mappings_from_file加载本地映射文件")
  325 +
271 326 mappings = {
272 327 'item': {},
273 328 'category': {},
... ...
offline_tasks/scripts/fetch_item_attributes.py 0 → 100644
... ... @@ -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 20 )
21 21 from offline_tasks.scripts.debug_utils import (
22 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 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 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 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 60 alpha: Swing算法的alpha参数
61 61 time_decay: 是否使用时间衰减
62 62 decay_factor: 时间衰减因子
  63 + use_daily_session: 是否同时使用uid+日期作为session维度
63 64 logger: 日志记录器
64 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 69 """
69 70 start_time = datetime.now()
70 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 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 83 if logger and debug:
83 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 108 if logger:
87 109 log_processing_step(logger, "步骤1: 构建用户-物品倒排索引")
... ... @@ -201,6 +223,10 @@ def main():
201 223 help='Use time decay for behavior weights (default: False for B2B low-frequency scenarios)')
202 224 parser.add_argument('--decay_factor', type=float, default=0.95,
203 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 230 parser.add_argument('--output', type=str, default=None,
205 231 help='Output file path')
206 232 parser.add_argument('--debug', action='store_true',
... ... @@ -218,6 +244,7 @@ def main():
218 244 'lookback_days': args.lookback_days,
219 245 'time_decay': args.time_decay,
220 246 'decay_factor': args.decay_factor,
  247 + 'use_daily_session': args.use_daily_session,
221 248 'debug': args.debug
222 249 })
223 250  
... ... @@ -299,6 +326,7 @@ def main():
299 326 alpha=args.alpha,
300 327 time_decay=args.time_decay,
301 328 decay_factor=args.decay_factor,
  329 + use_daily_session=args.use_daily_session,
302 330 logger=logger,
303 331 debug=args.debug
304 332 )
... ... @@ -333,9 +361,9 @@ def main():
333 361 if args.debug:
334 362 logger.info("Debug模式:生成明文索引文件...")
335 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 368 # 准备索引数据(合并已有的item_name_map)
341 369 # item_name_map的key已经是str类型,可以直接更新
... ...