@9000ai/cli 0.6.5 → 0.7.0

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.
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerContentCommands(parent: Command): void;
@@ -0,0 +1,66 @@
1
+ import { request, printJson, pollUntilDone } from "../client.js";
2
+ import { loadJsonFile } from "../utils/format.js";
3
+ export function registerContentCommands(parent) {
4
+ const cmd = parent.command("content").description("LLM content processing (analyze, rewrite, summarize)");
5
+ cmd
6
+ .command("analyze")
7
+ .description("Submit batch LLM processing tasks")
8
+ .option("--preset <name>", "Built-in preset: analyze, summarize, rewrite")
9
+ .option("--system-prompt <prompt>", "Custom system prompt (alternative to --preset)")
10
+ .option("--texts-file <path>", "JSON file: [{\"id\": \"...\", \"text\": \"...\"}]")
11
+ .option("--model <model>", "Override LLM model")
12
+ .option("--group-label <label>", "Batch group label")
13
+ .option("--webhook <url>", "Webhook for completion callback")
14
+ .option("--wait", "Poll until all tasks complete")
15
+ .option("--fields <list>", "Comma-separated fields to extract")
16
+ .option("--compact", "One JSON object per line")
17
+ .action(async (opts) => {
18
+ if (!opts.textsFile) {
19
+ console.error("Error: --texts-file is required");
20
+ process.exit(1);
21
+ }
22
+ if (!opts.preset && !opts.systemPrompt) {
23
+ console.error("Error: must provide --preset or --system-prompt");
24
+ process.exit(1);
25
+ }
26
+ const textsData = loadJsonFile(opts.textsFile);
27
+ const texts = Array.isArray(textsData) ? textsData : textsData.texts;
28
+ const payload = { texts };
29
+ if (opts.preset)
30
+ payload.preset = opts.preset;
31
+ if (opts.systemPrompt)
32
+ payload.system_prompt = opts.systemPrompt;
33
+ if (opts.model)
34
+ payload.model = opts.model;
35
+ if (opts.groupLabel)
36
+ payload.group_label = opts.groupLabel;
37
+ if (opts.webhook)
38
+ payload.webhook = opts.webhook;
39
+ const data = await request({
40
+ method: "POST",
41
+ path: "/api/v1/content/batch-analyze",
42
+ payload,
43
+ });
44
+ const resp = data;
45
+ const inner = resp.data;
46
+ const batchId = inner?.batch_id;
47
+ if (!opts.wait || !batchId) {
48
+ printJson(data, { fields: opts.fields, compact: opts.compact });
49
+ return;
50
+ }
51
+ console.error(`Batch submitted → ${batchId}, waiting...`);
52
+ await pollUntilDone(`/api/v1/tasks/batch/${batchId}`);
53
+ const resultData = await request({
54
+ method: "GET",
55
+ path: `/api/v1/tasks/batch/${batchId}`,
56
+ });
57
+ printJson(resultData, { fields: opts.fields, compact: opts.compact });
58
+ });
59
+ cmd
60
+ .command("presets")
61
+ .description("List available LLM presets")
62
+ .action(async () => {
63
+ const data = await request({ method: "GET", path: "/api/v1/content/presets" });
64
+ printJson(data);
65
+ });
66
+ }
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, copyFileSync, readFileSync, readdirSync, statSyn
2
2
  import { join, relative } from "path";
3
3
  import { resolveSkillsPath } from "../config.js";
4
4
  /** User data directories — never overwrite even with --force */
5
- const USER_DATA_DIRS = ["profile", "claims", "inbox", "projects", "benchmarks"];
5
+ const USER_DATA_DIRS = ["profile", "claims", "inbox", "projects", "benchmarks", "assets", "workflows"];
6
6
  function filesEqual(a, b) {
7
7
  try {
8
8
  return readFileSync(a).equals(readFileSync(b));
@@ -114,7 +114,7 @@ export function registerInitCommand(program) {
114
114
  }
115
115
  else if (isUpdate) {
116
116
  console.log(`\nWhat's new: 9000ai skill load 9000AI-hub to see latest capabilities.`);
117
- console.log(`Your data (profile/, claims/, inbox/, projects/) was not modified.`);
117
+ console.log(`Your data (profile/, claims/, assets/, workflows/, inbox/, projects/) was not modified.`);
118
118
  }
119
119
  });
120
120
  }
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import { registerFeedbackCommands } from "./commands/feedback.js";
10
10
  import { registerSkillCommands } from "./commands/skill.js";
11
11
  import { registerInitCommand } from "./commands/init.js";
12
12
  import { registerUpdateCommand } from "./commands/update.js";
13
+ import { registerContentCommands } from "./commands/content.js";
13
14
  const program = new Command();
14
15
  program
15
16
  .name("9000ai")
@@ -25,6 +26,7 @@ registerFeedbackCommands(program);
25
26
  registerSkillCommands(program);
26
27
  registerInitCommand(program);
27
28
  registerUpdateCommand(program);
29
+ registerContentCommands(program);
28
30
  program.parseAsync(process.argv).catch((err) => {
29
31
  console.error(err);
30
32
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@9000ai/cli",
3
- "version": "0.6.5",
3
+ "version": "0.7.0",
4
4
  "description": "9000AI Toolbox CLI — unified command-line interface for 9000AI platform",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,6 +57,10 @@ output-format: routing-only
57
57
  - 命令: `9000ai transcribe`
58
58
  - 场景: 批量视频转文字、查看转写结果
59
59
 
60
+ ### 内容处理
61
+ - 命令: `9000ai content`
62
+ - 场景: 批量文案拆解、改写、摘要,或自定义 prompt 处理
63
+
60
64
  ### 反馈提交
61
65
  - 命令: `9000ai feedback`
62
66
  - 场景: 提交反馈、查看记录。接口报错或用户不满时主动提议反馈
@@ -69,6 +73,7 @@ output-format: routing-only
69
73
  | 查热榜 / 搜抖音 / 找选题 | `9000ai search` |
70
74
  | 看某人主页 / 监控抖音号 | `9000ai monitor` |
71
75
  | 视频转文字 / 转写 | `9000ai transcribe` |
76
+ | 拆解这篇文案 / 分析内容 / 改写 / 摘要 | `9000ai content` |
72
77
  | 反馈 / 建议 / 报 bug | `9000ai feedback` |
73
78
 
74
79
  ## 首次使用流程
@@ -117,7 +122,8 @@ output-format: routing-only
117
122
  > 画像建好了。你的工作空间包含:
118
123
  > - `profile/` — 你的画像(刚填好的)
119
124
  > - `claims/` — 主张库,所有内容围绕主张展开
120
- > - `benchmarks/` — 对标文案库,转写和拆解的素材存这里,通过 index.json 索引
125
+ > - `assets/` — 内容弹药库,所有素材统一存放,AI 通过三层检索找素材
126
+ > - `workflows/` — 工作流,会在使用中不断进化
121
127
  > - `inbox/` — 素材投喂入口
122
128
  > - `projects/` — 选题项目
123
129
  >
@@ -11,9 +11,10 @@
11
11
  | 目录 | 用途 | 你的权限 |
12
12
  |------|------|---------|
13
13
  | profile/ | 了解用户是谁——身份、风格、领域 | 只读(用户维护) |
14
+ | claims/ | 主张库——主张定义、角度、产出记录 | 读写(匹配、回写角度和产出) |
15
+ | assets/ | 内容弹药库——所有素材统一存放 | 读写(入库、更新索引、标记使用) |
16
+ | workflows/ | 工作流——会在使用中不断进化 | 读写(追加已验证规则) |
14
17
  | inbox/ | 接收用户投喂的语料——会议记录、视频链接、文章、随笔 | 读取 + 处理后归档 |
15
- | claims/ | 主张库——核心资产,所有内容围绕主张展开 | 读写(提取、匹配、回写) |
16
- | benchmarks/ | 对标文案库——转写、拆解的素材,通过 index.json 索引 | 读写(存素材 + 维护索引) |
17
18
  | projects/ | 选题项目——一个选题一个项目 | 读写 |
18
19
 
19
20
  ## 3. 可用工具能力
@@ -25,25 +26,136 @@
25
26
  | 对标账号监控 | 监控指定博主的内容更新 | `9000ai monitor` |
26
27
  | 视频转文字 | 批量将视频转为文字稿 | `9000ai transcribe` |
27
28
 
28
- ## 3.1 benchmarks 对标文案库规则
29
+ ## 4. 内容弹药库(assets/)
29
30
 
30
- `benchmarks/` 通过 `index.json` 索引。**必须遵守以下规则:**
31
+ 弹药库是整个系统的核心。所有素材——对标博主的文案、拆解出来的案例、你自己的金句——全部存在这里。
31
32
 
32
- **存入素材时:**
33
- 1. 按主题建子目录(如 `AI就业/`、`知识付费/`)
34
- 2. 文件名格式:`作者_标题.md`
35
- 3. **必须同步更新 `benchmarks/index.json`**,追加条目,id 递增
33
+ ### 4.1 三层检索
36
34
 
37
- **检索素材时:**
38
- 1. 先读 `benchmarks/index.json`,按 tags 或 topic 匹配
39
- 2. 只读匹配到的具体文件,不全量扫描目录
40
- 3. 做选题前主动检查有没有相关对标素材
35
+ AI 找素材不能一次性读全量,必须分层:
41
36
 
42
- ## 4. inbox 处理规则
37
+ **第一层:仓库总览 `assets/catalog.json`**
38
+
39
+ AI 第一个读的文件。记录有哪些主题、每个主题多少素材、什么标签、关联哪些主张。
40
+
41
+ ```json
42
+ [
43
+ {
44
+ "topic": "知识付费",
45
+ "count": 326,
46
+ "claim_ids": ["cl001"],
47
+ "top_tags": ["割韭菜", "教育", "焦虑", "课程"],
48
+ "top_ips": ["栋哥", "曲曲大女人"]
49
+ },
50
+ {
51
+ "topic": "_自己的",
52
+ "count": 89,
53
+ "claim_ids": ["cl001", "cl002", "cl003"],
54
+ "top_tags": ["金句", "开头", "亲身经历"],
55
+ "top_ips": []
56
+ }
57
+ ]
58
+ ```
59
+
60
+ **第二层:主题索引 `assets/_index/{主题}.jsonl`**
61
+
62
+ 每个主题一个索引文件,每行一条素材摘要。AI 按标签过滤,筛出十几条相关的。
63
+
64
+ ```jsonl
65
+ {"id":"a001","type":"transcription","title":"栋哥讲知识付费真相","tags":["知识付费","割韭菜","教育"],"source_ip":"栋哥","claim_ids":["cl001"],"hook":"知识付费就是当代最大的骗局","structure":"递进","date":"2026-04-04","reuse_count":2,"file":"知识付费/栋哥_知识付费真相.md"}
66
+ ```
67
+
68
+ **第三层:具体文件 `assets/{主题}/{文件}`**
69
+
70
+ 只有被第二层命中了才读。转写原文、拆解报告、自己的片段都在这里。
71
+
72
+ ### 4.2 检索规则
73
+
74
+ 1. **必须从第一层开始**,不允许跳过总览直接扫索引
75
+ 2. 读 catalog.json → 判断该读哪几个主题的索引 → 读对应 _index/*.jsonl → 按标签筛 → 只读命中的具体文件
76
+ 3. `_自己的` 主题里的素材优先级高于对标素材——用户自己验证过的表述优先复用
77
+ 4. 每次使用某条素材后,更新该条记录的 `reuse_count`,避免过度复用同一个案例
78
+
79
+ ### 4.3 素材入库规则
80
+
81
+ 素材进来时,AI 做三件事:
82
+ 1. 具体文件存到 `assets/{主题}/`,文件名格式:`{作者}_{标题}.md`
83
+ 2. 在 `assets/_index/{主题}.jsonl` 追加一行索引记录
84
+ 3. 更新 `assets/catalog.json` 里对应主题的 count 和 top_tags
85
+
86
+ 新主题第一次出现时,自动建文件夹和索引文件,同时在 catalog.json 追加条目。
87
+
88
+ 还没想好放哪个主题的素材,先存到 `_待分类/`。
89
+
90
+ ### 4.4 拆解报告
91
+
92
+ 对标文案转写后,如果经过后端拆解,拆解报告存在原文旁边:
93
+
94
+ ```
95
+ assets/知识付费/
96
+ ├── 栋哥_知识付费真相.md ← 转写原文
97
+ └── 栋哥_知识付费真相.analysis.json ← 拆解报告
98
+ ```
99
+
100
+ 拆解报告包含:开头钩子、核心观点、案例素材、金句、结构模式、转化钩子。AI 做选题时可以直接读拆解报告,不需要重新分析原文。
101
+
102
+ ### 4.5 `_自己的` 目录
103
+
104
+ 用户自己产出的好内容——录过的文案、想到的金句、亲身经历——存在这里。
105
+
106
+ ```
107
+ assets/_自己的/
108
+ ├── 片段/
109
+ │ ├── 知识付费就是欺诈_完整文案.md
110
+ │ └── 劳动仲裁_口述观点.md
111
+ └── ...
112
+ ```
113
+
114
+ 这里的素材和对标素材走同样的索引机制,但 `source_ip` 标记为用户自己(从 profile/identity.md 读名字),AI 检索时可以区分"我自己说过的"和"别人说的"。
115
+
116
+ ## 5. 工作流进化(workflows/)
117
+
118
+ 工作流文件定义内容生产的步骤。关键特性:**工作流不是写死的,在使用中不断固化标准。**
119
+
120
+ ### 5.1 进化机制
121
+
122
+ 用户每次纠正 AI 的判断,AI 把验证过的标准追加到对应工作流文件的"已验证规则"区域。
123
+
124
+ 例子:
125
+
126
+ ```markdown
127
+ ## 已验证规则
128
+
129
+ - 案例筛选:点赞 ≥ 500,时长 > 60s 的要点赞 ≥ 1000
130
+ - 角度偏好:优先选有冲突感的,不要中性表述
131
+ - 开头风格:直接亮观点,不铺垫
132
+ - 补素材:弹药库里相关案例 < 3 条时自动搜索补充,不用问
133
+ ```
134
+
135
+ ### 5.2 规则追加原则
136
+
137
+ 1. **只记真正的规律**,单次偶发纠正不写入
138
+ 2. **记标准不记操作**,写"点赞 ≥ 500"而不是"上次你删了那条 200 赞的"
139
+ 3. **记原因**,不只是结论,要写为什么——方便判断边界情况
140
+ 4. **用户确认后才追加**,AI 先提议,用户同意了再写入
141
+
142
+ ### 5.3 工作流与主张的关系
143
+
144
+ 工作流是通用的流程模板,主张是个人化的内容资产。工作流里不硬编码具体主张,而是引用 claims/claims.json。这样同一套工作流可以服务不同主张。
145
+
146
+ ## 6. 对标 IP 管理
147
+
148
+ 不新建文件,复用 monitor 的 creator 列表。
149
+
150
+ - 用户说"盯住这几个 IP" → 调 `9000ai monitor create-creator` 添加监控
151
+ - 对标 IP 的内容转写后入库时,`source_ip` 字段自动标记博主名
152
+ - 做选题时可以按 `source_ip` 检索某个博主的所有素材
153
+
154
+ ## 7. inbox 处理规则
43
155
 
44
156
  当用户往 inbox/ 丢入新文件时:
45
157
 
46
- ### 4.1 判断文件类型
158
+ ### 7.1 判断文件类型
47
159
 
48
160
  | 类型 | 特征 |
49
161
  |------|------|
@@ -53,20 +165,20 @@
53
165
  | 观点 / 随笔 | .txt / .md,短篇,非结构化 |
54
166
  | 热点事件描述 | 含事件名称、时间、平台来源 |
55
167
 
56
- ### 4.2 内容分类分发
168
+ ### 7.2 内容分类分发
57
169
 
58
170
  inbox 里的内容不全是案例素材,提取前先判断类型,分发到正确的位置:
59
171
 
60
172
  | 内容类型 | 判断特征 | 去哪 |
61
173
  |---------|---------|------|
62
- | 主张相关的案例、观点、热点事件 | 可以服务于某个主张,适合对外输出 | `claims/cases.jsonl` |
174
+ | 对标文案、案例、观点、热点事件 | 可以作为内容素材 | `assets/` 对应主题 |
175
+ | 用户自己的好内容 | 第一人称表述、自己的经历 | `assets/_自己的/` |
63
176
  | 个人身份、背景、目标受众 | 关于"你是谁"的信息 | 提示用户更新 `profile/identity.md` |
64
177
  | 用户自己的表达风格、语气偏好 | 用户描述自己说话方式的信息 | 提示用户更新 `profile/voice.md` |
65
178
  | 关注领域、赛道、不碰的方向 | 关于"你做什么内容"的信息 | 提示用户更新 `profile/topics.md` |
66
179
  | 产品细节、交付形式、定价、卖点 | 关于"你卖什么"的信息 | 提示用户更新 `profile/product.md` |
67
- | 技术实现、系统设计、内部流程 | 关于"你怎么做"的内部信息 | 提示用户更新 `profile/product.md` |
68
180
 
69
- **原则**:没有内容会被丢弃,只是放对位置。profile 类内容不入案例库,cases.jsonl 只存适合对外创作的素材。
181
+ **原则**:没有内容会被丢弃,只是放对位置。profile 类内容不入弹药库。
70
182
 
71
183
  #### profile/voice.md 写入规则
72
184
 
@@ -84,8 +196,8 @@ inbox 里的内容不全是案例素材,提取前先判断类型,分发到
84
196
 
85
197
  | 情况 | 处理 |
86
198
  |------|------|
87
- | 提到对标博主(曲曲、良策文化等) | 存 `cases.jsonl` 作为选题参考,不碰 voice.md |
88
- | 投喂的是别人的文案(用于分析) | 只提取案例素材,不碰 voice.md |
199
+ | 提到对标博主(曲曲、良策文化等) | 存 assets/ 作为素材,不碰 voice.md |
200
+ | 投喂的是别人的文案(用于分析) | 只入弹药库,不碰 voice.md |
89
201
  | 会议里描述第三方账号的风格 | 忽略风格部分,不碰 voice.md |
90
202
  | 用户说"我想学 XX 的风格" | 见下方特殊情况处理 |
91
203
 
@@ -107,47 +219,46 @@ inbox 里的内容不全是案例素材,提取前先判断类型,分发到
107
219
  > 「你是想把 XX 加为风格模仿对象(写入 voice.md),还是只是选题对标?」
108
220
 
109
221
  - 选风格模仿 → 写入 voice.md 的"参考博主风格"字段,并标注"待学习"
110
- - 选选题对标 → 存 cases.jsonl,不碰 voice.md
222
+ - 选选题对标 → 存 assets/,不碰 voice.md
111
223
 
112
- ### 4.3 并行调度 subagent
224
+ ### 7.3 并行调度 subagent
113
225
 
114
- - **提取 subagent**:从语料中提取主张相关的案例、观点、事件(经过 4.2 分类判断后)→ 写入 cases.jsonl
226
+ - **入库 subagent**:将素材分类后存入 assets/ 对应主题,更新索引
115
227
  - **转写 subagent**:如果有视频链接 → 调用视频转文字能力
116
228
  - **搜索 subagent**:如果需要佐证或补充素材 → 调用关键词搜索能力
117
229
  - **profile subagent**:如果语料中有用户个人信息 → 提醒用户更新 profile/
118
230
 
119
- ### 4.4 处理完成后
231
+ ### 7.4 处理完成后
120
232
 
121
233
  1. 将原始文件从 inbox/ 移入 inbox/processed/
122
- 2. 向用户汇报:提取了什么、写入了哪些文件、匹配了哪些主张
234
+ 2. 向用户汇报:提取了什么、存入了哪些主题、关联了哪些主张
123
235
 
124
- ## 5. 匹配流程
236
+ ## 8. 匹配流程
125
237
 
126
238
  ```
127
239
  输入(热点/案例/事件)
128
240
  → AI 提取关键词
129
- 遍历 claims/angles.jsonl,按 tags 字段匹配
130
- 命中已有角度:
131
- 推荐该角度 + cases.jsonl 拉历史案例
132
- 未命中:
133
- 读取 claims.json 中对应主张的 description
134
- 基于主张现推 2-3 个新角度
135
- 用户选定后新角度写回 angles.jsonl
136
- → 用户录制完成后 → 记录到 outputs.jsonl
241
+ assets/catalog.json 定位相关主题
242
+ 读对应 _index/*.jsonl 按标签匹配
243
+ 命中已有素材 推荐角度 + 拉历史案例
244
+ 未命中 → 读 claims/claims.json 中对应主张
245
+ 基于主张现推 2-3 个新角度
246
+ 用户选定后 → 新角度写回 claims/angles.jsonl
247
+ 用户录制完成后 记录到 claims/outputs.jsonl
137
248
  ```
138
249
 
139
- ## 6. subagent 调度规则
250
+ ## 9. subagent 调度规则
140
251
 
141
252
  - 独立任务应并行执行,不串行等待
142
253
  - 每个 subagent 只做一件事,做完汇报
143
254
  - subagent 不直接修改 claims/ 数据,汇报给主 agent,由主 agent 统一写入
144
255
  - 大量数据不塞上下文,用文件路径传递
145
256
 
146
- ## 7. 自我进化准则
257
+ ## 10. 自我进化准则
147
258
 
148
259
  这个系统应该越用越好用、越用越个性化。用户每一次纠正都是信号,不能丢掉。
149
260
 
150
- ### 7.1 用户纠正时的行为链
261
+ ### 10.1 用户纠正时的行为链
151
262
 
152
263
  当用户纠正 agent 的判断、输出或行为时,按以下顺序处理:
153
264
 
@@ -164,7 +275,8 @@ inbox 里的内容不全是案例素材,提取前先判断类型,分发到
164
275
  | 纠正性质 | 处理方式 |
165
276
  |---------|---------|
166
277
  | 用户画像不准(AI 不了解用户) | 询问用户是否更新对应 profile/ 文件 |
167
- | 工作流判断错误(系统级问题) | 提议提交 feedback-9000AI |
278
+ | 工作流判断错误(可固化的标准) | 提议追加到对应 workflows/ 文件的"已验证规则" |
279
+ | 工作流系统级问题 | 提议提交 feedback |
168
280
  | 单次误操作(偶发,不代表规律) | 当场纠正,不更新任何文件 |
169
281
 
170
282
  **第三步:更新 profile(如适用)**
@@ -179,18 +291,19 @@ inbox 里的内容不全是案例素材,提取前先判断类型,分发到
179
291
 
180
292
  如果纠正属于工作流或系统级问题,主动提议:
181
293
 
182
- > 「这个问题可能不只影响你,要不要提交一条 feedback 让团队知道?团队可以帮你做工程化落地,我可以帮你整理。」
294
+ > 「这个问题可能不只影响你,要不要提交一条 feedback 让团队知道?」
183
295
 
184
- ### 7.2 主动提议更新 profile 的时机
296
+ ### 10.2 主动提议更新的时机
185
297
 
186
- 不只是纠正时,以下情况也应主动询问是否更新画像:
298
+ 不只是纠正时,以下情况也应主动询问:
187
299
 
188
- - inbox 处理中发现了用户的第一人称风格自描述(见 4.2)
300
+ - inbox 处理中发现了用户的第一人称风格自描述(见 7.2)
189
301
  - 用户在对话中透露了新的业务信息、受众变化、领域调整
190
- - 用户多次对同一类输出表示满意(正向信号,可提炼为风格规律)
302
+ - 用户多次对同一类输出表示满意(正向信号,可提炼为工作流规则)
303
+ - 用户反复做同样的手动操作(可以固化为工作流步骤)
191
304
 
192
- ### 7.3 不该做的事
305
+ ### 10.3 不该做的事
193
306
 
194
307
  - 不要在用户没确认的情况下自动更新任何 profile 文件
195
- - 不要把单次纠正当成规律写入画像
196
- - 不要每次都问"要不要更新 profile",只在真正有信息量的时候问
308
+ - 不要把单次纠正当成规律写入工作流
309
+ - 不要每次都问"要不要更新",只在真正有信息量的时候问
@@ -0,0 +1,56 @@
1
+ # 内容弹药库
2
+
3
+ 所有内容素材统一存放在这里。按主题分文件夹,AI 通过三层检索找素材。
4
+
5
+ ## 目录结构
6
+
7
+ ```
8
+ assets/
9
+ ├── catalog.json ← 仓库总览(AI 第一个读的文件)
10
+ ├── _index/ ← 每个主题的素材索引
11
+ │ ├── 知识付费.jsonl
12
+ │ ├── AI就业.jsonl
13
+ │ └── _自己的.jsonl
14
+ ├── 知识付费/ ← 按主题存素材
15
+ │ ├── 栋哥_知识付费真相.md
16
+ │ └── 栋哥_知识付费真相.analysis.json
17
+ ├── _自己的/ ← 你自己的好内容
18
+ │ └── 片段/
19
+ ├── _待分类/ ← 还没归类的素材
20
+ └── README.md
21
+ ```
22
+
23
+ ## AI 怎么找素材
24
+
25
+ 1. 读 catalog.json → 判断该看哪几个主题
26
+ 2. 读 _index/{主题}.jsonl → 按标签筛出相关条目
27
+ 3. 只读命中的具体文件
28
+
29
+ **不允许跳过第一层直接扫全部索引。**
30
+
31
+ ## 素材入库
32
+
33
+ 每次存入新素材:
34
+ 1. 文件存到 `assets/{主题}/`,文件名:`{作者}_{标题}.md`
35
+ 2. `_index/{主题}.jsonl` 追加一行
36
+ 3. `catalog.json` 更新对应主题的 count 和 top_tags
37
+
38
+ ## 索引记录格式
39
+
40
+ ```jsonl
41
+ {"id":"a001","type":"transcription","title":"标题","tags":["标签1","标签2"],"source_ip":"作者","claim_ids":["cl001"],"hook":"开头第一句","structure":"递进","date":"2026-04-04","reuse_count":0,"file":"主题/作者_标题.md"}
42
+ ```
43
+
44
+ | 字段 | 说明 |
45
+ |------|------|
46
+ | id | 递增编号 a001, a002... |
47
+ | type | transcription(转写) / analysis(拆解) / quote(金句) / experience(亲身经历) / fragment(片段) |
48
+ | title | 素材标题 |
49
+ | tags | 关键词标签(行业+情绪+场景+人物) |
50
+ | source_ip | 来源博主名,自己的内容标记用户名 |
51
+ | claim_ids | 关联的主张 ID 列表,未关联时为 [] |
52
+ | hook | 开头钩子(第一句话),可选 |
53
+ | structure | 结构模式(递进/多角度/对比),可选 |
54
+ | date | 入库日期 |
55
+ | reuse_count | 被引用次数,初始 0 |
56
+ | file | 相对路径 |
@@ -49,7 +49,7 @@
49
49
  ### cases.jsonl(每行一条 JSON)
50
50
 
51
51
  ```json
52
- {"id":"c001","claim_id":"cl001","angle_id":null,"type":"event","title":"标题","summary":"摘要","source":"来源","direction":"negative","date":"2026-03-28"}
52
+ {"id":"c001","claim_id":"cl001","angle_id":null,"type":"phenomenon","title":"标题","summary":"摘要","source":"来源","source_ip":"博主名","tags":["标签1","标签2"],"direction":"positive","date":"2026-03-28","reuse_count":0}
53
53
  ```
54
54
 
55
55
  | 字段 | 类型 | 必填 | 说明 |
@@ -57,12 +57,15 @@
57
57
  | id | string | 是 | 格式 c{NNN} |
58
58
  | claim_id | string | 是 | 关联的主张 ID |
59
59
  | angle_id | string\|null | 否 | 关联角度 ID,初期可为 null |
60
- | type | string | 是 | event / opinion / story |
60
+ | type | string | 是 | event(热点事件) / phenomenon(社会现象) / history(历史事件) / business(商业案例) / opinion(观点金句) / story(个人故事) |
61
61
  | title | string | 是 | 标题 |
62
62
  | summary | string | 是 | 摘要 |
63
63
  | source | string | 否 | 来源(平台@账号) |
64
+ | source_ip | string | 否 | 来源 IP 名称(如"栋哥"、"曲曲大女人"),用于按对标 IP 检索 |
65
+ | tags | string[] | 是 | 关键词标签(行业+情绪+场景),用于检索匹配 |
64
66
  | direction | string | 是 | positive(证实)/ negative(证伪) |
65
67
  | date | string | 否 | 日期 |
68
+ | reuse_count | int | 是 | 被引用次数,初始 0,每次成文引用 +1,避免过度复用 |
66
69
 
67
70
  ### outputs.jsonl(每行一条 JSON)
68
71
 
@@ -6,9 +6,14 @@
6
6
  ./
7
7
  ├── agents/content-agent.md # AI 助手的角色定义
8
8
  ├── profile/ # 你的画像(身份、风格、领域、产品)
9
+ ├── claims/ # 主张库(主张定义、角度、产出记录)
10
+ ├── assets/ # 内容弹药库(所有素材统一存放)
11
+ │ ├── catalog.json 仓库总览
12
+ │ ├── _index/ 每个主题的素材索引
13
+ │ ├── _自己的/ 你自己的好内容
14
+ │ └── _待分类/ 还没归类的素材
15
+ ├── workflows/ # 工作流(会在使用中不断进化)
9
16
  ├── inbox/ # 素材投喂入口
10
- ├── claims/ # 主张库(你的核心资产)
11
- ├── benchmarks/ # 对标文案库(转写、拆解的素材)
12
17
  ├── projects/ # 选题项目
13
18
  └── guide.md # 就是这份指南
14
19
  ```
@@ -18,18 +23,17 @@
18
23
  ## 全流程概览
19
24
 
20
25
  ```
21
- 发现热点 → 匹配主张 → 找角度 → 补素材转写视频存入文案库 → 产出内容
22
- ↑ ↑ ↑
23
- 热榜/搜索 claims.json angles cases 视频转文字 benchmarks/
26
+ 发现热点 → 匹配主张 → 找角度 → 从弹药库找素材不够就搜+转写+入库 → 产出内容
27
+ ↑ ↑ ↑
28
+ 热榜/搜索 claims.json angles assets/ 自动补充 outputs
24
29
  ```
25
30
 
26
31
  1. **发现**:用热榜或搜索找到值得追的热点
27
32
  2. **匹配**:看这个热点能挂到你的哪个主张上
28
33
  3. **切角度**:从角度库找已有角度,或基于主张推新角度
29
- 4. **补素材**:从案例库拉历史素材,或搜索新素材
30
- 5. **转写**:对标视频转成文字稿,分析学习
31
- 6. **入库**:转写和拆解的文案存到 `benchmarks/主题/`,自动更新索引
32
- 7. **产出**:录制/撰写内容,记录到 outputs.jsonl
34
+ 4. **找素材**:AI 从弹药库按标签检索相关案例和对标文案
35
+ 5. **补素材**:弹药库里不够就自动搜索、转写、拆解、入库
36
+ 6. **产出**:组合成文,记录到 outputs.jsonl
33
37
 
34
38
  ---
35
39
 
@@ -76,13 +80,18 @@
76
80
 
77
81
  ---
78
82
 
79
- ## 第三步:积累对标文案
83
+ ## 第三步:积累内容弹药
80
84
 
81
- `benchmarks/` 是你的对标文案库。搜索或监控发现好内容后,转写 → 拆解 → 存到这里。
85
+ `assets/` 是你的内容弹药库。所有素材——对标博主的文案、你自己的金句、搜索到的案例——全部存在这里。
82
86
 
83
- AI 通过 `benchmarks/index.json` 索引快速检索,不需要全量扫描。每次存入新素材时 AI 自动更新索引。
87
+ AI 通过三层检索找素材:
88
+ 1. 先看 `catalog.json`(仓库总览)判断翻哪个主题
89
+ 2. 再看 `_index/{主题}.jsonl` 按标签筛出相关条目
90
+ 3. 只读命中的具体文件
84
91
 
85
- 详见 `benchmarks/README.md`。
92
+ 你自己的好内容存在 `assets/_自己的/`,AI 取用时会优先用你验证过的素材。
93
+
94
+ 详见 `assets/README.md`。
86
95
 
87
96
  ---
88
97
 
@@ -104,29 +113,24 @@ AI 通过 `benchmarks/index.json` 索引快速检索,不需要全量扫描。
104
113
  9000ai search keyword "知识付费" --sort 0 --time 7
105
114
  ```
106
115
 
107
- 结果自动存到 `output/` 目录
108
-
109
116
  ### 对标监控 — 盯住你的对标账号
110
117
 
111
118
  ```bash
112
119
  # 查看已有监控目标
113
120
  9000ai monitor list-creators
114
121
 
122
+ # 直接看某人主页视频
123
+ 9000ai monitor fetch --sec-user <sec_user_id> --fields desc,likes,shares,create_time
124
+
115
125
  # 提交监控任务
116
126
  9000ai monitor submit --json-file <配置文件>
117
-
118
- # 查看执行历史
119
- 9000ai monitor list-runs
120
127
  ```
121
128
 
122
129
  ### 视频转文字
123
130
 
124
131
  ```bash
125
- # 提交转写任务
126
- 9000ai transcribe submit --json-file <视频列表>
127
-
128
- # 查看任务状态
129
- 9000ai task status --task-id <id>
132
+ # 按 video_id 转写(推荐)
133
+ 9000ai transcribe submit --video-ids <id1,id2,...>
130
134
 
131
135
  # 获取转写结果
132
136
  9000ai transcribe text --task-id <id>
@@ -147,36 +151,45 @@ AI 通过 `benchmarks/index.json` 索引快速检索,不需要全量扫描。
147
151
 
148
152
  1. `9000ai search hot` 拉热榜
149
153
  2. 看到热点,问 agent:「这个热点能挂到我的哪个主张上?」
150
- 3. Agent 提取关键词匹配 angles.jsonl 的 tags
151
- 4. 命中角度推荐角度 + 拉历史案例
152
- 5. 没命中 → 基于主张推 2-3 个新角度,你选一个,写回 angles.jsonl
154
+ 3. Agent 匹配主张从弹药库检索相关素材 推荐角度
155
+ 4. 素材不够自动搜索补充 转写 → 入库
156
+ 5. 组合成文
153
157
  6. 录制完成 → 记录到 outputs.jsonl
154
158
 
155
159
  ### 场景 B:投喂素材,积累弹药
156
160
 
157
161
  1. 把会议记录、文章、视频链接丢进 `inbox/`
158
162
  2. 告诉 agent:「处理 inbox」
159
- 3. Agent 自动提取案例和观点写入 `claims/cases.jsonl`
163
+ 3. Agent 自动分类素材存入 assets/ 对应主题 → 更新索引
160
164
  4. 原始文件归档到 `inbox/processed/`
161
165
 
162
166
  ### 场景 C:围绕主题做批量选题调研
163
167
 
164
168
  1. `9000ai search keyword "关键词"` 搜索目标内容
165
- 2. 结果落到 output 文件
166
- 3. 挑出值得学的视频 `9000ai transcribe submit` 转文字稿
167
- 4. 转写结果存到 `benchmarks/主题/`,AI 自动更新索引
168
- 5. 分析文字稿提取案例写入 cases.jsonl
169
- 6. 基于积累的案例和对标文案 → 规划一周选题
169
+ 2. 挑出值得学的视频 `9000ai transcribe submit` 转文字稿
170
+ 3. 转写结果存到 `assets/{主题}/`,拆解报告存旁边
171
+ 4. AI 自动更新索引,素材进入弹药库
172
+ 5. 基于积累的弹药规划一周选题
170
173
 
171
174
  ### 场景 D:对标监控 + 持续素材积累
172
175
 
173
176
  1. `9000ai monitor create-creator` 添加对标账号
174
177
  2. 定期监控,获取最新内容
175
- 3. 值得学的视频 → 转写 → 存到 `benchmarks/` → 提取角度和案例
178
+ 3. 值得学的视频 → 转写 → 拆解 → 存到 `assets/` → 案例入库
176
179
  4. 找对标做了但你没做的角度 → 新选题
177
180
 
178
181
  ---
179
182
 
183
+ ## 工作流进化
184
+
185
+ `workflows/` 目录下的工作流文件会在使用中不断进化。你每次纠正 AI 的判断,AI 会把验证过的标准追加进去。
186
+
187
+ 比如你说"点赞低于500的案例不要",AI 就把这条规则追加到对应工作流里。下次自动按这个标准筛,不再问你。
188
+
189
+ 用得越多,规则越多,AI 越来越不需要问你。
190
+
191
+ ---
192
+
180
193
  ## 常见问题
181
194
 
182
195
  **怎么重新初始化?**
@@ -195,3 +208,6 @@ AI 通过 `benchmarks/index.json` 索引快速检索,不需要全量扫描。
195
208
 
196
209
  **inbox 里的文件处理完去哪了?**
197
210
  归档到 `inbox/processed/`,不会被删除。
211
+
212
+ **弹药库素材怎么找?**
213
+ 不需要手动找。告诉 AI 你要做什么,AI 会自动从 assets/ 检索。你也可以按主题文件夹自己翻。
@@ -0,0 +1,26 @@
1
+ # 工作流
2
+
3
+ 这里存放内容生产的工作流定义。
4
+
5
+ ## 核心特性
6
+
7
+ 工作流不是写死的。你和 AI 一起用的过程中,AI 会把验证过的标准追加到对应工作流文件里。用得越多,AI 自主空间越大,需要问你的越少。
8
+
9
+ ## 每个工作流文件的结构
10
+
11
+ ```markdown
12
+ # 工作流名称
13
+
14
+ ## 步骤
15
+ (具体步骤)
16
+
17
+ ## 已验证规则
18
+ (在使用中逐步积累,AI 追加,用户确认)
19
+ ```
20
+
21
+ ## 规则追加原则
22
+
23
+ - 只记真正的规律,单次偶发纠正不写入
24
+ - 记标准不记操作
25
+ - 记原因,方便判断边界情况
26
+ - 用户确认后才追加
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: content-processing
3
+ description: 当用户要批量拆解文案、改写文案、提取摘要、或用自定义 prompt 批量处理文本时使用。后台异步执行,提交后通过 task status 回查结果。
4
+ triggers:
5
+ - 文案拆解
6
+ - 文案改写
7
+ - 文案分析
8
+ - 批量拆解
9
+ - 批量改写
10
+ - 内容摘要
11
+ - 批量处理文案
12
+ role: operator
13
+ scope: execution
14
+ output-format: task-oriented
15
+ ---
16
+
17
+ # 内容处理 Skill
18
+
19
+ 批量 LLM 文案处理:拆解、改写、摘要,或自定义 prompt。
20
+
21
+ ## 适用范围
22
+
23
+ - 批量文案拆解(提取 hook、论点、金句、节奏等)
24
+ - 批量文案改写
25
+ - 批量提取摘要
26
+ - 自定义 prompt 批量处理任意文本
27
+
28
+ ## 内置 Preset
29
+
30
+ | Preset | 说明 |
31
+ |--------|------|
32
+ | `analyze` | 结构化拆解:hook/主题/论点/金句/CTA/节奏 |
33
+ | `summarize` | 100 字以内核心摘要 |
34
+ | `rewrite` | 保留观点换表达 |
35
+
36
+ 查看可用 preset:
37
+
38
+ ```bash
39
+ 9000ai content presets
40
+ ```
41
+
42
+ ## 工作方式
43
+
44
+ 内容处理是异步任务:
45
+ 1. 准备文本文件(JSON 格式)
46
+ 2. 提交批量任务
47
+ 3. 拿到 batch_id
48
+ 4. 回查结果
49
+
50
+ ## 文本文件格式
51
+
52
+ ```json
53
+ [
54
+ {"id": "bm001", "text": "文案内容..."},
55
+ {"id": "bm002", "text": "另一段文案..."}
56
+ ]
57
+ ```
58
+
59
+ `id` 用于标识每段文案,建议用有意义的名称(如视频 ID、标题缩写等)。
60
+
61
+ ## 命令
62
+
63
+ ```bash
64
+ # 用内置 preset 拆解
65
+ 9000ai content analyze --preset analyze --texts-file texts.json --group-label "AI就业-拆解"
66
+
67
+ # 用内置 preset 改写
68
+ 9000ai content analyze --preset rewrite --texts-file texts.json
69
+
70
+ # 用自定义 prompt
71
+ 9000ai content analyze --system-prompt "请提取文案中的数据和论据" --texts-file texts.json
72
+
73
+ # 提交并等待结果
74
+ 9000ai content analyze --preset analyze --texts-file texts.json --wait
75
+
76
+ # 查询结果
77
+ 9000ai task status --batch-id <batch_id>
78
+ 9000ai task results --task-id <task_id> --fields output
79
+ ```
80
+
81
+ ## 典型串联流程
82
+
83
+ 监控 → 转写 → 拆解:
84
+
85
+ ```bash
86
+ # 1. 转写视频
87
+ 9000ai transcribe submit --video-ids <id1>,<id2> --group-label "竞品分析"
88
+
89
+ # 2. 提取文案到本地
90
+ 9000ai transcribe text --task-id <task_id1> --dir "竞品分析"
91
+ 9000ai transcribe text --task-id <task_id2> --dir "竞品分析"
92
+
93
+ # 3. 准备 texts.json(从转写文案组装)
94
+ # 4. 批量拆解
95
+ 9000ai content analyze --preset analyze --texts-file texts.json --group-label "竞品分析-拆解" --wait
96
+ ```
97
+
98
+ ## 性能准则(必须遵守)
99
+
100
+ ### 数据精简
101
+
102
+ 查询结果时用 `--fields` 只取需要的字段。
103
+
104
+ ```bash
105
+ # 只取 LLM 输出
106
+ 9000ai task results --task-id <id> --fields output
107
+ ```
108
+
109
+ ### 并行执行
110
+
111
+ 独立操作必须并行,不要串行等待。
112
+
113
+ ### 不暴露中间过程
114
+
115
+ 拿到结果后直接呈现分析结论,不要展示原始 JSON。
116
+
117
+ ## 参考
118
+
119
+ 接口细节见 `references/endpoints.md`。
@@ -0,0 +1,72 @@
1
+ # Content Processing API Endpoints
2
+
3
+ ## POST /api/v1/content/batch-analyze
4
+
5
+ 批量提交 LLM 处理任务。
6
+
7
+ **Request:**
8
+
9
+ ```json
10
+ {
11
+ "preset": "analyze",
12
+ "texts": [
13
+ {"id": "bm001", "text": "文案内容..."},
14
+ {"id": "bm002", "text": "另一段..."}
15
+ ],
16
+ "model": "gemini-2.5-pro",
17
+ "group_label": "AI就业-拆解",
18
+ "webhook": "https://..."
19
+ }
20
+ ```
21
+
22
+ | 字段 | 必填 | 说明 |
23
+ |------|------|------|
24
+ | preset | 二选一 | 内置模板名:analyze / summarize / rewrite |
25
+ | system_prompt | 二选一 | 自定义 system prompt |
26
+ | texts | 是 | 文本列表,每项含 id 和 text |
27
+ | model | 否 | 覆盖默认模型 |
28
+ | group_label | 否 | 分组标签 |
29
+ | webhook | 否 | 回调地址 |
30
+
31
+ **Response:**
32
+
33
+ ```json
34
+ {
35
+ "code": 0,
36
+ "data": {
37
+ "batch_id": "uuid",
38
+ "total_tasks": 2,
39
+ "tasks": [
40
+ {"task_id": "uuid", "third_party_task_id": "bm001", "status": "pending"},
41
+ {"task_id": "uuid", "third_party_task_id": "bm002", "status": "pending"}
42
+ ]
43
+ },
44
+ "message": "已提交 2 个 LLM 任务"
45
+ }
46
+ ```
47
+
48
+ ## GET /api/v1/content/presets
49
+
50
+ 列出可用的内置 preset。
51
+
52
+ **Response:**
53
+
54
+ ```json
55
+ {
56
+ "code": 0,
57
+ "data": {
58
+ "presets": ["analyze", "rewrite", "summarize"]
59
+ }
60
+ }
61
+ ```
62
+
63
+ ## 结果查询
64
+
65
+ 使用通用任务接口:
66
+
67
+ ```
68
+ GET /api/v1/tasks/{task_id}
69
+ GET /api/v1/tasks/batch/{batch_id}
70
+ ```
71
+
72
+ 每个 task 的 `output` 字段包含 LLM 返回的处理结果。
@@ -19,39 +19,33 @@ output-format: file-oriented
19
19
 
20
20
  # 抖音选题发现 Skill
21
21
 
22
- 这个 skill 对应一个能力:`douyin_topic_discovery`。
22
+ 这个 skill 对应一个能力:`douyin_topic_discovery`。用于拉取抖音热点榜和按关键词搜索视频。
23
23
 
24
- ## 先看变量名
25
-
26
- 不要去别的文档里猜变量名。这个 skill 固定只认中台统一变量:
24
+ ## 命令
27
25
 
28
- ```text
29
- 9000AI_BASE_URL
30
- 9000AI_API_KEY
31
- ```
26
+ ```bash
27
+ # 热榜
28
+ 9000ai search hot --type society --count 20
29
+ 9000ai search hot --type all --count 20
32
30
 
33
- 请求头里的 key 名固定是:
31
+ # 关键词搜索(异步,返回 batch_id)
32
+ 9000ai search keyword “AI创业” “副业” --sort 0 --time 7 --min-likes 200
34
33
 
35
- ```text
36
- X-API-Key
37
- ```
34
+ # 搜索并等待结果
35
+ 9000ai search keyword “知识付费” --wait --fields desc,author_name,likes
38
36
 
39
- 读取优先级固定是:
37
+ # 查询批次结果
38
+ 9000ai search batch-result --batch-id <batch_id> --fields desc,author_name,likes
40
39
 
41
- ```text
42
- 1. 命令行参数
43
- 2. 9000AI_BASE_URL / 9000AI_API_KEY
44
- 3. douyin-topic-discovery-9000AI/local/config.json
40
+ # 查看结果文件
41
+ 9000ai search list-output
42
+ 9000ai search show-result --input latest_search --row 3
43
+ 9000ai search export-media --input latest_search --row 3
45
44
  ```
46
45
 
47
- 本地配置文件的字段名固定是:
46
+ 搜索结果数量:每个关键词默认 30 条,后端自动翻页聚合。
48
47
 
49
- ```json
50
- {
51
- "base_url": "http://127.0.0.1:8025",
52
- "api_key": "sk-xxx"
53
- }
54
- ```
48
+ 常用榜单类型:`hot`(综合)、`society`(社会)、`entertainment`(娱乐)、`seeding`(种草)、`city`(城市)、`challenge`(挑战)
55
49
 
56
50
  ## 批量选题调研
57
51
 
@@ -61,104 +55,24 @@ X-API-Key
61
55
 
62
56
  按该文档的阶段逐步执行,不要跳步。
63
57
 
64
- ## 当前范围
65
-
66
- 用于:
67
- - 获取抖音热点榜
68
- - 按关键词搜索抖音搜索流
69
- - 把结果落到 `output/` 目录
70
- - 让后续脚本按文件继续消费
71
- - 批量选题调研(按工作流文档执行)
72
-
73
- 不负责:
74
- - 自动生成推荐结论
75
-
76
- ## 工作方式
77
-
78
- 标准动作是:
79
- 1. 调热榜或搜索流 API
80
- 2. 把结果写到 `douyin-topic-discovery-9000AI/output/`
81
- 3. 对话里只展示摘要和少量关键字段
82
-
83
- `search` 现在是真异步:
84
- 1. 先提交 `batch`
85
- 2. 立即返回 `batch_id`
86
- 3. 需要结果时,再用 `batch-result` 查询
87
- 4. 查询到结果后,再落 `latest_search.json/tsv`
88
-
89
- ## 配置
90
-
91
- 优先推荐直接配中台统一环境变量:
92
-
93
- ```powershell
94
- $env:9000AI_BASE_URL = "http://127.0.0.1:8025"
95
- $env:9000AI_API_KEY = "sk-xxx"
96
- ```
97
-
98
- 或者通过 CLI 写入配置:
99
-
100
- ```bash
101
- 9000ai config set --base-url http://127.0.0.1:8025 --api-key <key>
102
- ```
103
-
104
58
  ## 输出目录
105
59
 
106
- 固定输出到:
107
-
108
- ```text
109
- output/
110
- ```
111
-
112
- 常用文件:
113
- - `latest_hot.json`
114
- - `latest_hot.tsv`
115
- - `latest_search.json`
116
- - `latest_search.tsv`
117
-
118
- ## 命令
119
-
120
- 查看帮助:
121
-
122
- ```bash
123
- 9000ai search --help
124
- ```
125
-
126
- 常用命令:
127
-
128
- ```bash
129
- 9000ai config set --base-url http://127.0.0.1:8025 --api-key <key>
130
- 9000ai auth whoami
131
- 9000ai auth capabilities
132
- 9000ai search hot --type society --count 20
133
- 9000ai search keyword "AI创业" "副业" --sort 0 --time 7 --content-type 1 --filter-duration 0 --min-likes 200 --min-comments 20
134
- 9000ai search batch-result --batch-id <batch_id>
135
- 9000ai search list-output
136
- 9000ai search show-result --input latest_search --row 3
137
- 9000ai search export-media --input latest_search --row 3
138
- ```
139
-
140
- 搜索结果数量规则:
141
- - `search` 每个关键词默认抓取 `30` 条
142
- - 后端会基于 `search_general_v3` 自动翻页聚合,不需要额外传分页参数
60
+ 结果自动落盘到 `output/`:
61
+ - `latest_hot.json` / `latest_hot.tsv`
62
+ - `latest_search.json` / `latest_search.tsv`
143
63
 
144
64
  ## 性能准则(必须遵守)
145
65
 
146
66
  ### 数据精简
147
67
 
148
- 搜索结果和任务结果都支持 `--fields`、`--compact` 和 `--format csv`。**默认必须用 `--fields` 只取需要的字段,禁止全量读取。**
68
+ **默认必须用 `--fields` 只取需要的字段,禁止全量读取。**
149
69
 
150
70
  ```bash
151
- # 错误 — 返回全量 JSON,浪费上下文
71
+ # 错误 — 全量返回
152
72
  9000ai search batch-result --batch-id <id>
153
73
 
154
- # 正确 — 只取选题需要的字段
74
+ # 正确 — 只取需要的字段
155
75
  9000ai search batch-result --batch-id <id> --fields desc,author_name,likes,duration
156
-
157
- # CSV 格式 — 省 token,适合列表数据
158
- 9000ai search keyword "美食探店" --wait --format csv --fields desc,author_name,author_sec_uid,likes
159
-
160
- # 更紧凑 — 每条一行 JSON
161
- 9000ai search batch-result --batch-id <id> --fields desc,author_name,likes --compact
162
76
  ```
163
77
 
164
78
  常用字段组合:
@@ -168,24 +82,14 @@ output/
168
82
 
169
83
  ### 并行执行
170
84
 
171
- 独立操作必须并行,不要串行等待。
172
-
173
- 可以并行:
174
- - 多个 `batch-result` 查询(不同 batch_id)
175
- - 写输出文件 + 查询下一批结果
176
- - 多关键词搜索提交后,同时查询各自的 batch_id
177
-
178
- 不能并行:
179
- - 提交搜索 → 等 batch_id 返回 → 查询结果(有依赖)
180
-
181
- ### 减少中间文件
85
+ 独立操作必须并行。多个 batch_id 的结果查询、多关键词搜索提交后同时查询。
182
86
 
183
- 简单的热榜或搜索请求直接用命令行参数,不要写 JSON 文件。
87
+ 不能并行:提交搜索 等 batch_id → 查结果(有依赖)。
184
88
 
185
89
  ### 不暴露中间过程
186
90
 
187
- 拿到搜索结果后直接输出摘要或执行下一步,不要把原始 JSON 全量展示给用户。
91
+ 拿到结果后直接输出摘要或执行下一步,不要把原始 JSON 全量展示给用户。
188
92
 
189
- ## 一句话总结
93
+ ## 参考
190
94
 
191
- 这是一个”热榜 + search_general_v3 搜索流”的抖音选题发现 skill。
95
+ 接口细节和字段说明见 `references/endpoints.md`。