@tapdb/tapdb-data-analysis 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ name: tapdb-data-analysis
|
|
|
3
3
|
description: >
|
|
4
4
|
TapDB 游戏数据分析技能。用于查询和分析 TapDB 中的游戏运营数据,包括活跃(DAU/WAU/MAU)、
|
|
5
5
|
留存(1日留存-180日留存)、付费(收入/ARPU/ARPPU)、来源(新增/转化)、用户价值(LTV)、版本分布、
|
|
6
|
-
|
|
6
|
+
玩家行为、广告变现等指标。
|
|
7
7
|
当用户需要查询游戏数据、分析运营指标、对比项目表现、检测数据异常、生成数据报告时使用此技能。
|
|
8
8
|
触发关键词:TapDB、DAU、MAU、留存、付费、收入、ARPU、LTV、活跃、新增、来源、玩家行为、
|
|
9
9
|
版本分布、鲸鱼用户、广告变现、游戏数据分析。
|
|
@@ -11,18 +11,18 @@ description: >
|
|
|
11
11
|
|
|
12
12
|
# TapDB 数据分析
|
|
13
13
|
|
|
14
|
-
> Skill 版本:v0.1.
|
|
14
|
+
> Skill 版本:v0.1.27
|
|
15
15
|
|
|
16
|
-
通过 Python 脚本调用 TapDB
|
|
16
|
+
通过 Python 脚本调用 TapDB 运营数据查询接口,获取游戏指标数据并分析。
|
|
17
17
|
|
|
18
18
|
## 环境要求
|
|
19
19
|
|
|
20
|
-
- 查询脚本: `<SKILL_DIR>/scripts/tapdb_query.py
|
|
21
|
-
- Python 3(优先用 `python3
|
|
20
|
+
- 查询脚本: `<SKILL_DIR>/scripts/tapdb_query.py`
|
|
21
|
+
- Python 3(优先用 `python3`;否则用 `python`)
|
|
22
22
|
- npm(用于 Skill 更新检查)
|
|
23
23
|
- 认证密钥 `TAPDB_MCP_KEY_CN` / `TAPDB_MCP_KEY_SG`
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## 运行前检查(每次讨论一个新话题或新一轮数据查询时使用)
|
|
26
26
|
|
|
27
27
|
### 1. Skill 更新
|
|
28
28
|
|
|
@@ -30,25 +30,13 @@ description: >
|
|
|
30
30
|
npm view @tapdb/tapdb-data-analysis version --registry https://registry.npmjs.org/
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
与本文件顶部 `Skill 版本`
|
|
33
|
+
与本文件顶部 `Skill 版本` 对比,不同则更新本 Skill
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
cd /tmp && \
|
|
37
|
-
npm pack @tapdb/tapdb-data-analysis@latest --registry https://registry.npmjs.org/ && \
|
|
38
|
-
tar -xzf tapdb-tapdb-data-analysis-*.tgz && \
|
|
39
|
-
cp -r package/tapdb-data-analysis/* <SKILL_DIR>/ && \
|
|
40
|
-
rm -rf package tapdb-tapdb-data-analysis-*.tgz
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
更新后**重新读取** `<SKILL_DIR>/SKILL.md`,以新版本为准。告知用户"TapDB 数据分析 Skill 已更新到 vX.X.X"。详情:https://www.npmjs.com/package/@tapdb/tapdb-data-analysis
|
|
35
|
+
更新后**重新读取** `<SKILL_DIR>/SKILL.md`,以新版本为准。告知用户"TapDB 数据分析 Skill 已更新到 vX.X.X",并给出更新内容。
|
|
44
36
|
|
|
45
37
|
### 2. 环境变量
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
[ -z "$TAPDB_MCP_KEY_CN" ] && echo "❌ CN 未设置" || echo "✅ CN 已配置"
|
|
49
|
-
[ -z "$TAPDB_MCP_KEY_SG" ] && echo "❌ SG 未设置" || echo "✅ SG 已配置"
|
|
50
|
-
```
|
|
51
|
-
|
|
39
|
+
检查 `TAPDB_MCP_KEY_CN` 和 `TAPDB_MCP_KEY_SG` 环境变量是否存在。
|
|
52
40
|
缺少则**停止操作**,引导配置:秘钥在 **TapDB 页面右上角 → 账号设置 → 秘钥管理**。国内 CN/海外 SG 各需独立秘钥。用户提供后按步骤 3 写入 shell 配置文件并验证。
|
|
53
41
|
|
|
54
42
|
### 3. 持久化检查
|
|
@@ -57,15 +45,14 @@ rm -rf package tapdb-tapdb-data-analysis-*.tgz
|
|
|
57
45
|
|
|
58
46
|
## 工作流程
|
|
59
47
|
|
|
60
|
-
1. **确认项目**: `list_projects` 获取项目列表(含 `id/name/appid/sticky/remark
|
|
48
|
+
1. **确认项目**: `list_projects` 获取项目列表(含 `id/name/appid/sticky/remark`,若返回列表过长则先保存到本地再查找,避免截断导致找不到需要的项目)
|
|
61
49
|
- 在 `name` 和 `remark` 中检索匹配,任一命中即为候选
|
|
62
50
|
- 多候选时优先 `sticky: true`;仍有多个则对每个做轻量探测(如 7 天 DAU):仅一个有数据→直接用;多个有数据→列出让用户选;全零→同样列出让用户选
|
|
63
51
|
2. **识别场景**: 按「场景路由」判断分析路径
|
|
64
52
|
3. **查看能力**: `describe <接口名>` 确认支持的指标/分组/过滤
|
|
65
53
|
4. **调用脚本**: 查询数据
|
|
66
|
-
5.
|
|
67
|
-
6.
|
|
68
|
-
7. **输出报告**: 按 `references/output_rules.md` 生成结论优先、可追溯的结构化报告
|
|
54
|
+
5. **分析**: 读 `references/metrics_glossary.md`(指标定义)、`references/analysis_guide.md`(方法论)
|
|
55
|
+
6. **输出报告**: 按 `references/output_rules.md` 生成结论优先、可追溯的结构化报告
|
|
69
56
|
|
|
70
57
|
## 场景路由
|
|
71
58
|
|
|
@@ -132,6 +119,13 @@ python3 <SKILL_DIR>/scripts/tapdb_query.py describe active # 查看接口
|
|
|
132
119
|
| `--no-truncate` | 不截断输出 | |
|
|
133
120
|
| `-r` | 区域 cn/sg | `-r sg` |
|
|
134
121
|
|
|
122
|
+
### 时间范围硬规则(必须遵守)
|
|
123
|
+
|
|
124
|
+
- ✅ 连续时间范围直接查询
|
|
125
|
+
- ✅ TapDB 单次查询最长 **180 天**(包含起止日)
|
|
126
|
+
- ❌ 不要把时间范围按周拆分成多次查询(需要周粒度:用 `--group-unit week` **一次性**范围查询)
|
|
127
|
+
- ⚠️ 仅当用户明确要求“按日趋势/按天对比/定位异常日期”时才按天拆分;否则保持一次范围查询
|
|
128
|
+
|
|
135
129
|
### 查询示例
|
|
136
130
|
|
|
137
131
|
```bash
|
|
@@ -169,13 +163,11 @@ python3 <SKILL_DIR>/scripts/tapdb_query.py raw /op/active '{"project_id":2588,"s
|
|
|
169
163
|
|
|
170
164
|
| 场景 | 阈值 | 方式 |
|
|
171
165
|
|------|------|------|
|
|
172
|
-
| 时间序列 | > 30 行 | 首
|
|
166
|
+
| 时间序列 | > 30 行 | 首15 + 尾15 |
|
|
173
167
|
| 分组维度 | > 20 行 | 前20 |
|
|
174
168
|
| 鲸鱼用户 | > 20 条 | 前20 |
|
|
175
|
-
| 留存列 DR1-DR180 | 自动 | 仅 DR1/3/7/14/30/60/90 |
|
|
176
|
-
| LTV 列 1-60_LTV | 自动 | 仅 LTV1/3/7/14/30/60/90 |
|
|
177
169
|
|
|
178
|
-
- 不加 `--all-retention` 通常仅返回 `DR1-DR30 + DR60/90/120/150/180`;加上后会额外补齐 `DR31-DR59`(及对应 `_newDevice/_rate`
|
|
170
|
+
- 不加 `--all-retention` 通常仅返回 `DR1-DR30 + DR60/90/120/150/180`;加上后会额外补齐 `DR31-DR59`(及对应 `_newDevice/_rate` 列)。
|
|
179
171
|
|
|
180
172
|
- 分析时利用 `_truncation.summary` 统计量,不要仅基于可见行下结论
|
|
181
173
|
- 多次查询:每次先提取关键数值再下一个查询,不累积原始数据
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
import argparse
|
|
13
13
|
import json
|
|
14
14
|
import os
|
|
15
|
-
import re
|
|
16
15
|
import sys
|
|
17
16
|
import urllib.request
|
|
18
17
|
import urllib.error
|
|
@@ -74,18 +73,14 @@ def output(data):
|
|
|
74
73
|
|
|
75
74
|
# ── 数据截断 ────────────────────────────────────────────────
|
|
76
75
|
|
|
77
|
-
_RE_DR = re.compile(r'^DR(\d+)')
|
|
78
|
-
_RE_N_LTV = re.compile(r'^(\d+)_LTV$')
|
|
79
|
-
_RETENTION_KEEP = {1, 3, 7, 14, 30, 60, 90}
|
|
80
|
-
_LTV_KEEP = {1, 3, 7, 14, 30, 60, 90}
|
|
81
76
|
_TIME_FIELDS = frozenset(("date", "time", "activation_time", "start_time",
|
|
82
77
|
"date_", "time_", "activation_time_", "start_time_"))
|
|
83
78
|
|
|
84
79
|
_MAX_TIME_ROWS = 30
|
|
85
80
|
_MAX_GROUP_ROWS = 20
|
|
86
81
|
_MAX_WHALE_ROWS = 20
|
|
87
|
-
_HEAD =
|
|
88
|
-
_TAIL =
|
|
82
|
+
_HEAD = 15
|
|
83
|
+
_TAIL = 15
|
|
89
84
|
|
|
90
85
|
|
|
91
86
|
def _numeric_summary(rows, limit=6):
|
|
@@ -102,33 +97,6 @@ def _numeric_summary(rows, limit=6):
|
|
|
102
97
|
return out
|
|
103
98
|
|
|
104
99
|
|
|
105
|
-
def _slim_columns(rows, cmd_type):
|
|
106
|
-
"""Drop intermediate DR/LTV columns, keep key day columns only."""
|
|
107
|
-
if not rows or not isinstance(rows[0], dict):
|
|
108
|
-
return rows, None
|
|
109
|
-
sample = rows[0]
|
|
110
|
-
if cmd_type == "retention":
|
|
111
|
-
regex, keep_set, label = _RE_DR, _RETENTION_KEEP, "DR"
|
|
112
|
-
elif cmd_type == "user_value":
|
|
113
|
-
regex, keep_set, label = _RE_N_LTV, _LTV_KEEP, "LTV"
|
|
114
|
-
else:
|
|
115
|
-
return rows, None
|
|
116
|
-
|
|
117
|
-
matched = {}
|
|
118
|
-
for k in sample:
|
|
119
|
-
m = regex.match(k)
|
|
120
|
-
if m:
|
|
121
|
-
matched[k] = int(m.group(1))
|
|
122
|
-
kept_count = sum(1 for d in matched.values() if d in keep_set)
|
|
123
|
-
if len(matched) <= kept_count + 2:
|
|
124
|
-
return rows, None
|
|
125
|
-
keep_keys = {k for k in sample if k not in matched or matched.get(k) in keep_set}
|
|
126
|
-
removed = len(matched) - kept_count
|
|
127
|
-
rows = [{k: v for k, v in r.items() if k in keep_keys} for r in rows]
|
|
128
|
-
days = "/".join(str(d) for d in sorted(keep_set))
|
|
129
|
-
return rows, f"kept {label}{days}, removed {removed} other {label} columns"
|
|
130
|
-
|
|
131
|
-
|
|
132
100
|
def _slim_rows(rows, cmd_type):
|
|
133
101
|
"""Truncate row count; time-series keeps head+tail, others keep head."""
|
|
134
102
|
if not rows:
|
|
@@ -218,9 +186,6 @@ def truncate_response(resp, cmd_type=None):
|
|
|
218
186
|
return resp
|
|
219
187
|
|
|
220
188
|
info = {}
|
|
221
|
-
rows, col_msg = _slim_columns(rows, cmd_type)
|
|
222
|
-
if col_msg:
|
|
223
|
-
info["columns"] = col_msg
|
|
224
189
|
rows, row_info = _slim_rows(rows, cmd_type)
|
|
225
190
|
if row_info:
|
|
226
191
|
info.update(row_info)
|