Files
geo/docs/superpowers/specs/2026-04-16-kol-feature-design.md
T

857 lines
26 KiB
Markdown
Raw Normal View History

# KOL 功能设计文档(v3 — 第一方 KOL 方案,不依赖 share codes
> 本文档替代此前所有基于 `prompt_share_profiles` / `prompt_share_codes` 的 KOL 方案描述。
> `share_code_id` 仍然保留在 `article_templates` 现有表结构中作为历史遗留字段,但 **KOL 功能不再依赖它**。
2026-04-16 22:08:50 +08:00
## 概述
为 GEO 平台新增第一方 KOL 功能模块。KOL 是一种面向租户端产品能力的创作者身份:KOL 在自己的租户内编写、发布和运营精调 prompt 包,其他租户可以在市场中浏览并申请订阅;订阅成功后,订阅租户获得对对应 KOL prompt 的使用权,并通过专用 KOL 生成链路产出文章。
本方案的核心目标:
- **去旧方案依赖**:不再复用 `prompt_share_profiles``prompt_share_codes``share_code_id`
- **生成链路独立**:KOL 文章走独立的 `source_type='kol'` / `task_type='kol'`
- **权限边界清晰**:KOL 工作台属于租户端产品能力,审批与风控属于平台端能力
- **历史可追溯**Prompt 发布版本、变量 schema、使用快照、任务和文章链路完整可追踪
2026-04-16 22:08:50 +08:00
### 核心概念
- **KOL Profile**KOL 创作者身份,绑定一个 `user_id + tenant_id`
- **KOL Package**KOL 发布的一组 prompt 的业务包
- **KOL Prompt**:包内单个 prompt 的逻辑实体
- **KOL Prompt Revision**prompt 的不可变发布/草稿修订
- **KOL Subscription**:订阅租户对某个 package 的订阅关系
- **KOL Subscription Prompt Access**:订阅生效后,租户对包内某个 prompt 的访问授权
- **KOL Usage Log**:每次生成请求的审计与结算基础记录
### 设计原则
1. **KOL 是第一方模型,不是旧分享模型的变体**
2. **KOL 原始 prompt 不写入 `article_templates`**
3. **KOL 生成只走专用 API 与专用 worker 分支**
4. **V1 不接入通用模板选择器,避免绕过订阅鉴权**
5. **租户端能力留在 `tenant-api`,平台审批留在 `platform-api`**
2026-04-16 22:08:50 +08:00
---
## 1. 架构定位
2026-04-16 22:08:50 +08:00
### 1.1 边界划分
| 能力 | 归属 | 说明 |
|------|------|------|
| 市场浏览、包详情、申请订阅 | `tenant-api` | 面向租户端用户的产品能力 |
| KOL 工作台、Prompt 编辑、KOL 看板 | `tenant-api` | KOL 在自己租户内使用 |
| 订阅审批、KOL Profile 开通/冻结 | `platform-api` | 平台运营能力 |
| 文章生成执行 | `worker-generate` | 复用既有队列、额度、任务状态框架 |
### 1.2 与现有系统的关系
| 现有模块 | 复用方式 |
|---------|---------|
| `articles` | 复用,新增 `source_type='kol'``kol_prompt_id` |
| `generation_tasks` | 复用,新增 `task_type='kol'` |
| `article_versions` | 复用,生成成功后正常写入 |
| `quota_reservations` / `tenant_quota_ledgers` | 复用,遵守既有事务边界 |
| `task_records + SSE` | 复用,前端感知生成进度 |
| `template_assist_tasks` | 不复用,新建 `kol_assist_tasks` |
| `article_templates` | 不作为 KOL 原始 prompt 存储;`share_code_id` 对 KOL 无意义 |
### 1.3 V1 显式不做
- 不复活旧的 share code 导入/物化方案
- 不把 KOL prompt 接入通用 `/articles/template` 生成链路
- 不把 KOL prompt 存成订阅方的 `article_templates`
- 不做在线支付、分账、提现
- 不做 KOL 多租户归属切换
2026-04-16 22:08:50 +08:00
---
## 2. 数据模型
2026-04-16 22:08:50 +08:00
### 2.1 新增表
2026-04-16 22:08:50 +08:00
#### kol_profiles — KOL 创作者身份
2026-04-16 22:08:50 +08:00
```sql
CREATE TABLE kol_profiles (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
user_id BIGINT NOT NULL REFERENCES users(id),
display_name VARCHAR(100) NOT NULL,
bio TEXT,
avatar_url TEXT,
market_enabled BOOLEAN NOT NULL DEFAULT FALSE,
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active / suspended / closed
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
2026-04-16 22:08:50 +08:00
);
CREATE UNIQUE INDEX uk_kol_profile_user_active
ON kol_profiles(user_id)
WHERE deleted_at IS NULL;
CREATE INDEX idx_kol_profile_tenant
ON kol_profiles(tenant_id)
WHERE deleted_at IS NULL;
2026-04-16 22:08:50 +08:00
```
设计要点:
- 一个用户在 V1 仅允许有一个 active KOL Profile
- `tenant_id` 是 KOL 的归属租户,也是 AI 辅助费用归属租户
- KOL Profile 不是 `platform_role`,也不是 `tenant_role`,而是第一方业务身份
#### kol_packages — KOL 订阅包
2026-04-16 22:08:50 +08:00
```sql
CREATE TABLE kol_packages (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
kol_profile_id BIGINT NOT NULL REFERENCES kol_profiles(id),
name VARCHAR(200) NOT NULL,
description TEXT,
cover_url TEXT,
industry VARCHAR(100),
tags JSONB NOT NULL DEFAULT '[]',
price_note VARCHAR(200),
status VARCHAR(20) NOT NULL DEFAULT 'draft', -- draft / published / archived
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
2026-04-16 22:08:50 +08:00
);
CREATE INDEX idx_kol_package_profile
ON kol_packages(kol_profile_id, created_at DESC)
WHERE deleted_at IS NULL;
CREATE INDEX idx_kol_package_status
ON kol_packages(status, created_at DESC)
WHERE deleted_at IS NULL;
2026-04-16 22:08:50 +08:00
```
设计要点:
- `tenant_id` 是创作者租户,不是订阅租户
- 包可以是全局可见资源,但 ownership 仍然属于创作者租户
- 市场只展示 `status='published'``kol_profiles.market_enabled=true`
- 市场列表/详情是**跨租户查询**`/api/tenant/kol/marketplace/*` 是已知 tenant-scope 豁免点,实施时不能复用默认“按当前 tenant_id 过滤”的仓储查询
- 实施建议:优先在 service 层做跨租户聚合查询;若落在 tenant 仓储 SQL,则需为该查询显式标注 tenant-scope exemption,并同步调整 `check_tenant_scope.sh` 的豁免策略
#### kol_prompts — KOL Prompt 逻辑主表
```sql
CREATE TABLE kol_prompts (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
package_id BIGINT NOT NULL REFERENCES kol_packages(id),
name VARCHAR(200) NOT NULL,
platform_hint VARCHAR(100),
status VARCHAR(20) NOT NULL DEFAULT 'draft', -- draft / active / archived
sort_order INT NOT NULL DEFAULT 0,
published_revision_no INT,
draft_revision_no INT,
created_by BIGINT NOT NULL REFERENCES users(id),
updated_by BIGINT NOT NULL REFERENCES users(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_kol_prompt_package
ON kol_prompts(package_id, sort_order, created_at)
WHERE deleted_at IS NULL;
CREATE INDEX idx_kol_prompt_tenant_status
ON kol_prompts(tenant_id, status, created_at DESC)
WHERE deleted_at IS NULL;
```
设计要点:
- `kol_prompts` 是逻辑实体,不直接存放 prompt 原文
- 当前可用版本通过 `published_revision_no` 指向
- KOL 编辑时创建新 revision;发布时切换 `published_revision_no`
#### kol_prompt_revisions — KOL Prompt 不可变修订
```sql
CREATE TABLE kol_prompt_revisions (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
prompt_id BIGINT NOT NULL REFERENCES kol_prompts(id),
revision_no INT NOT NULL,
prompt_asset_key TEXT NOT NULL, -- 受保护资产 key
schema_json JSONB NOT NULL DEFAULT '{}',
card_config_json JSONB NOT NULL DEFAULT '{}',
created_by BIGINT NOT NULL REFERENCES users(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (prompt_id, revision_no)
);
CREATE INDEX idx_kol_prompt_revision_prompt
ON kol_prompt_revisions(prompt_id, revision_no DESC);
```
设计要点:
- 原始 prompt 正文只存受保护资产,不回传前端
- `schema_json``card_config_json` 与 prompt 正文一起冻结在 revision 中
- 历史生成任务通过 `prompt_id + revision_no` 可精确回放
2026-04-16 22:08:50 +08:00
#### kol_subscriptions — 租户级订阅关系
2026-04-16 22:08:50 +08:00
```sql
CREATE TABLE kol_subscriptions (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id), -- 订阅方租户
package_id BIGINT NOT NULL REFERENCES kol_packages(id),
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending / active / expired / revoked
approved_by BIGINT REFERENCES users(id),
start_at TIMESTAMPTZ,
end_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
2026-04-16 22:08:50 +08:00
);
CREATE UNIQUE INDEX uk_kol_subscription_active
ON kol_subscriptions(tenant_id, package_id)
WHERE status IN ('pending', 'active');
CREATE INDEX idx_kol_subscription_package
ON kol_subscriptions(package_id, status, created_at DESC);
```
设计要点:
- 订阅主体是 tenant,不是单个 user
- 审批与撤销都以 tenant 为单位
- 结算、看板、风控也以 tenant 为统计口径
#### kol_subscription_prompts — 订阅生效后的 prompt 访问授权
```sql
CREATE TABLE kol_subscription_prompts (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
subscription_id BIGINT NOT NULL REFERENCES kol_subscriptions(id),
package_id BIGINT NOT NULL REFERENCES kol_packages(id),
prompt_id BIGINT NOT NULL REFERENCES kol_prompts(id),
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active / revoked
granted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
revoked_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX uk_kol_subscription_prompt
ON kol_subscription_prompts(subscription_id, prompt_id);
CREATE INDEX idx_kol_subscription_prompt_tenant
ON kol_subscription_prompts(tenant_id, status, created_at DESC);
2026-04-16 22:08:50 +08:00
```
设计要点:
- 这是新的“订阅后可用 prompt”映射表,用来替代旧的 share code / 物化模板模型
- 订阅审批通过时,为当前包内所有 active prompt 创建 access row
- 包后续新增 prompt 时,为所有 active 订阅补齐 access row
- 撤订或 prompt 下架时,access row 置为 revoked
#### kol_usage_logs — 使用与审计记录
2026-04-16 22:08:50 +08:00
```sql
CREATE TABLE kol_usage_logs (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
subscription_id BIGINT REFERENCES kol_subscriptions(id),
subscription_prompt_id BIGINT REFERENCES kol_subscription_prompts(id),
package_id BIGINT NOT NULL REFERENCES kol_packages(id),
prompt_id BIGINT NOT NULL REFERENCES kol_prompts(id),
prompt_revision_no INT NOT NULL,
article_id BIGINT REFERENCES articles(id),
generation_task_id BIGINT REFERENCES generation_tasks(id),
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending / completed / failed
variables_snapshot JSONB,
schema_snapshot JSONB,
rendered_prompt_hash VARCHAR(64),
error_message TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
finished_at TIMESTAMPTZ
2026-04-16 22:08:50 +08:00
);
CREATE INDEX idx_kol_usage_package
ON kol_usage_logs(package_id, created_at DESC);
CREATE INDEX idx_kol_usage_tenant
ON kol_usage_logs(tenant_id, created_at DESC);
CREATE INDEX idx_kol_usage_prompt
ON kol_usage_logs(prompt_id, created_at DESC);
2026-04-16 22:08:50 +08:00
```
设计要点:
- `status` 明确进入表结构,解决 pending/completed/failed 口径不一致问题
- `prompt_revision_no + schema_snapshot + variables_snapshot + rendered_prompt_hash` 组成完整审计快照
-`generation_task_id``article_id` 关联后可闭合结算与故障追踪链
#### kol_assist_tasks — KOL AI 辅助任务
```sql
CREATE TABLE kol_assist_tasks (
id VARCHAR(64) PRIMARY KEY,
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
kol_profile_id BIGINT NOT NULL REFERENCES kol_profiles(id),
prompt_id BIGINT REFERENCES kol_prompts(id),
operator_id BIGINT NOT NULL REFERENCES users(id),
task_type VARCHAR(50) NOT NULL, -- ai_generate / ai_optimize
status VARCHAR(20) NOT NULL DEFAULT 'queued',
request_json JSONB NOT NULL DEFAULT '{}'::jsonb,
result_json JSONB,
error_message TEXT,
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_kol_assist_tenant_profile
ON kol_assist_tasks(tenant_id, kol_profile_id, created_at DESC);
CREATE INDEX idx_kol_assist_status
ON kol_assist_tasks(status, created_at DESC);
```
设计要点:
- `kol_assist_tasks.tenant_id` 是**计费租户**,必须始终写入 `kol_profiles.tenant_id`
- 实施时禁止直接使用当前请求的 `actor.TenantID` 作为兜底来源;即使 V1 中两者相同,也要先解析 profile 后再写任务记录
- 这样后续即使支持 KOL 多租户归属切换,历史费用归属也不会歧义
2026-04-16 22:08:50 +08:00
### 2.2 现有表变更
2026-04-16 22:08:50 +08:00
#### articles 表
2026-04-16 22:08:50 +08:00
新增字段:
- `kol_prompt_id BIGINT REFERENCES kol_prompts(id)`
新增 `source_type` 值:
- `kol`
说明:
- KOL 文章不依赖 `template_id`
- `template_id` 对 KOL 文章保持 `NULL`
2026-04-16 22:08:50 +08:00
#### generation_tasks 表
新增 `task_type` 值:
- `kol`
2026-04-16 22:08:50 +08:00
`input_params_json` 示例:
2026-04-16 22:08:50 +08:00
```json
{
"subscription_prompt_id": 901,
"prompt_id": 42,
"prompt_revision_no": 7,
2026-04-16 22:08:50 +08:00
"variables": {
"var_a1b2c3": "宜家家居",
"var_d4e5f6": "家具"
},
"schema_snapshot": {
"variables": []
},
"rendered_prompt_hash": "a1b2c3d4..."
2026-04-16 22:08:50 +08:00
}
```
#### article_templates 表
无 KOL 专属新增值。
说明:
- KOL 原始 prompt 不写入 `article_templates`
- 旧字段 `share_code_id` 继续保留,但 KOL 不使用
2026-04-16 22:08:50 +08:00
---
## 3. Prompt 变量与版本模型
### 3.1 schema_json 格式
```json
{
"variables": [
{
"id": "var_a1b2c3",
"key": "公司名称",
"label": "公司名称",
"type": "input",
"required": true,
"placeholder": "请输入您的公司名"
},
{
"id": "var_d4e5f6",
"key": "行业",
"label": "行业",
"type": "select",
"options": ["家具", "建材", "家电"],
"required": true
}
]
}
```
设计要点:
- 每个变量有不可变 `id`
- Prompt 正文内部只引用 `{{id}}`
- 前端展示 `label`,提交时按 `id -> value` 映射
- 修改 `key/label` 不会破坏既有 prompt 引用
### 3.2 修订规则
- 每次保存草稿,创建新的 `kol_prompt_revisions.revision_no`
- `kol_prompts.draft_revision_no` 指向最新草稿
- 点击发布时,把 `published_revision_no` 切到当前草稿修订
- `status='active'` 的 prompt 必须有 `published_revision_no`
### 3.3 历史复现
历史生成记录依赖以下字段重建:
2026-04-16 22:08:50 +08:00
- `prompt_id`
- `prompt_revision_no`
- `schema_snapshot`
- `variables_snapshot`
- `rendered_prompt_hash`
因此即使 KOL 后续继续编辑 prompt,历史记录仍可审计、对账和回放。
2026-04-16 22:08:50 +08:00
---
## 4. 页面结构与路由
### 4.1 侧边栏导航
2026-04-16 22:08:50 +08:00
```
现有导航:
Workspace
文章创作: 模版生成 | 自定义生成 | 自由创作 | 发布管理
品牌管理: 品牌库
品牌追踪: 追踪详情
内容管理: 知识库 | 图片库
新增:
KOL 市场: 模版市场 ← 所有用户可见
KOL 工作台: 提示词管理 | 数据看板 ← 仅 active kol_profile 可见
2026-04-16 22:08:50 +08:00
```
### 4.2 新增路由
2026-04-16 22:08:50 +08:00
| 路由 | 组件 | 角色 | 说明 |
|------|------|------|------|
| `/kol/marketplace` | `KolMarketplaceView` | 所有用户 | 浏览 KOL 包 |
| `/kol/packages/:id` | `KolPackageDetailView` | 所有用户 | 包详情与订阅 |
| `/kol/generate/:subscriptionPromptId` | `KolGenerateView` | 已订阅租户 | 动态表单生成 |
| `/kol/manage` | `KolManageView` | 仅 KOL | 包与 prompt 管理 |
| `/kol/dashboard` | `KolDashboardView` | 仅 KOL | KOL 数据看板 |
2026-04-16 22:08:50 +08:00
### 4.3 用户入口
2026-04-16 22:08:50 +08:00
1. 侧边栏「模版市场」进入市场浏览与订阅
2. Workspace 新增「KOL Prompt 卡片区」,展示当前租户可用的 `kol_subscription_prompts`
3. **V1 不把 KOL prompt 放入通用模板选择器**
2026-04-16 22:08:50 +08:00
---
## 5. API 设计
2026-04-16 22:08:50 +08:00
### 5.1 市场与订阅(tenant API
2026-04-16 22:08:50 +08:00
```text
GET /api/tenant/kol/marketplace/packages
GET /api/tenant/kol/marketplace/packages/:id
POST /api/tenant/kol/marketplace/packages/:id/subscribe
GET /api/tenant/kol/subscriptions
GET /api/tenant/kol/subscription-prompts
GET /api/tenant/kol/subscription-prompts/:id
```
2026-04-16 22:08:50 +08:00
说明:
2026-04-16 22:08:50 +08:00
- `/marketplace/*` 返回全局已发布包
- `/subscriptions``/subscription-prompts` 只返回当前租户数据
- `/api/tenant/kol/marketplace/*` 属于 tenant-api 中少数跨租户读场景;实施时需显式声明 tenant-scope exemption
### 5.2 KOL 生成(tenant API
```text
GET /api/tenant/kol/subscription-prompts/:id/schema
POST /api/tenant/kol/subscription-prompts/:id/generate
```
2026-04-16 22:08:50 +08:00
说明:
2026-04-16 22:08:50 +08:00
- `:id``kol_subscription_prompts.id`
- 后端根据 access row 反查 package、prompt、published revision
- 生成请求只接受变量值,不接受 prompt 原文
### 5.3 KOL 工作台(tenant API
```text
GET /api/tenant/kol/manage/profile
GET /api/tenant/kol/manage/packages
POST /api/tenant/kol/manage/packages
PUT /api/tenant/kol/manage/packages/:id
DELETE /api/tenant/kol/manage/packages/:id
PUT /api/tenant/kol/manage/packages/:id/publish
PUT /api/tenant/kol/manage/packages/:id/archive
GET /api/tenant/kol/manage/packages/:id/prompts
POST /api/tenant/kol/manage/packages/:id/prompts
PUT /api/tenant/kol/manage/prompts/:id
DELETE /api/tenant/kol/manage/prompts/:id
POST /api/tenant/kol/manage/prompts/:id/publish
POST /api/tenant/kol/manage/assist/generate
POST /api/tenant/kol/manage/assist/optimize
```
说明:
- 工作台不走 `/api/platform/kol/*`
- 只有 `kol_profiles.tenant_id = actor.TenantID AND user_id = actor.UserID` 的用户可操作
### 5.4 KOL 看板(tenant API
```text
GET /api/tenant/kol/dashboard/overview
GET /api/tenant/kol/dashboard/packages
GET /api/tenant/kol/dashboard/trend
```
### 5.5 平台管理员操作(platform API
```text
POST /api/platform/admin/kol/profiles
PUT /api/platform/admin/kol/profiles/:id/suspend
PUT /api/platform/admin/kol/profiles/:id/activate
PUT /api/platform/admin/kol/subscriptions/:id/approve
POST /api/platform/admin/kol/subscriptions
PUT /api/platform/admin/kol/subscriptions/:id/revoke
```
---
## 6. 订阅与授权生命周期
### 6.1 申请订阅
1. 用户在市场页点击「申请订阅」
2. 创建 `kol_subscriptions(status='pending')`
3. 等待平台管理员审批
### 6.2 审批通过
1. 平台管理员把订阅改为 `active`
2. 在同一事务或紧随其后的授权任务中,为该 package 当前所有 active prompt 创建 `kol_subscription_prompts`
3. Workspace 的 KOL 卡片区开始展示这些 prompt
### 6.3 包后续新增 prompt
1. KOL 在已发布包下新建并发布 prompt
2. 系统为所有 active 订阅补写 `kol_subscription_prompts`
3. 新 prompt 自动出现在订阅租户的 KOL 卡片区
实现建议:
- 订阅审批时可同步插入 access rows
- “已发布包新增 prompt” 建议走异步任务,避免大批量订阅阻塞发布请求
- 异步分发复用现有 `task_records` 可观测能力
### 6.4 订阅过期处理
V1 口径:
- **不做自动过期任务**
- `kol_subscriptions.end_at` 仅在读时与生成鉴权时实时校验
-`end_at < now()` 时,即使 `status` 仍为 `active`,生成接口也必须拒绝访问
- 列表页、看板统计口径应把“`status='active'` 且当前时间仍在有效期内”视为有效订阅
- 后续如需引入 scheduler,再补“批量把过期订阅改为 `expired` + 回收 access rows”的异步清理任务
### 6.5 撤销订阅
1. 平台管理员把订阅改为 `revoked`
2. 把该订阅下所有 `kol_subscription_prompts` 置为 `revoked`
3. Workspace KOL 卡片区不再展示
4. 生成接口返回 403
### 6.6 Prompt 下架
1. KOL 把 prompt 标记为 `archived`
2. 对应的 `kol_subscription_prompts` 置为 `revoked`
3. 已生成文章保留,后续新生成禁止
2026-04-16 22:08:50 +08:00
---
## 7. 生成链路
2026-04-16 22:08:50 +08:00
严格遵循现有架构中的事务、额度、幂等和 worker 回写规则。
### 7.1 提交前校验
2026-04-16 22:08:50 +08:00
生成前必须逐项校验:
2026-04-16 22:08:50 +08:00
1. `kol_subscription_prompts.id` 存在且 `status='active'`
2. access row 的 `tenant_id = 当前租户`
3. 对应 `kol_subscriptions.status='active'`
4. 订阅在有效期内
5. `kol_packages.status='published'`
6. `kol_prompts.status='active'`
7. `kol_prompts.published_revision_no IS NOT NULL`
2026-04-16 22:08:50 +08:00
### 7.2 提交路径(单 PostgreSQL 事务)
2026-04-16 22:08:50 +08:00
1. 读取 `kol_prompts.published_revision_no`
2. 读取对应 `kol_prompt_revisions`
3. 渲染变量并计算 `rendered_prompt_hash`
4. 单事务内执行:
- 额度预扣与 reservation 创建
- 创建 `articles(source_type='kol', kol_prompt_id=...)`
- 创建 `generation_tasks(task_type='kol', request_hash=rendered_prompt_hash)`
- 创建 `kol_usage_logs(status='pending')`
- 创建 `task_records`
5. 事务提交后发送队列消息
2026-04-16 22:08:50 +08:00
### 7.3 Worker 执行路径
2026-04-16 22:08:50 +08:00
Worker 处理 `task_type='kol'` 时:
2026-04-16 22:08:50 +08:00
1.`generation_tasks.input_params_json` 读取 `prompt_id + prompt_revision_no`
2. 加载对应 revision 的受保护 prompt 资产
3. 组装模型请求
4. 生成文章内容
2026-04-16 22:08:50 +08:00
### 7.4 成功路径(单 PostgreSQL 事务)
2026-04-16 22:08:50 +08:00
- 写入 `article_versions`
- 更新 `articles.generate_status='completed'`
- 确认额度消耗
- 更新 `kol_usage_logs.status='completed'`
- 回写 `article_id``finished_at`
2026-04-16 22:08:50 +08:00
### 7.5 失败路径(单 PostgreSQL 事务)
- 更新 `generation_tasks.status='failed'`
- 释放或退还额度
- 更新 `kol_usage_logs.status='failed'`
- 写入 `error_message``finished_at`
### 7.6 幂等键
幂等规则:
- `tenant_id + source_type('kol') + request_hash(rendered_prompt_hash) + schedule_slot(null)`
说明:
- 与现有生成体系一致
- KOL 不做定时调度,因此 `schedule_slot = null`
2026-04-16 22:08:50 +08:00
---
## 8. KOL Prompt 编辑器
### 8.1 包管理
- 仅展示当前 KOL 在当前租户下创建的包
- 支持创建、编辑、发布、归档
- 已发布包允许继续新增 prompt
### 8.2 Prompt 编辑器
2026-04-16 22:08:50 +08:00
三栏布局:
2026-04-16 22:08:50 +08:00
- 左栏:变量组件面板
- 中栏:Prompt 编辑区 + AI 辅助
- 右栏:变量配置面板
2026-04-16 22:08:50 +08:00
### 8.3 编辑规则
2026-04-16 22:08:50 +08:00
1. 拖拽变量组件到编辑区
2. 系统生成不可变 `var_xxx` 变量 ID
3. 编辑器显示 `{{公司名称}}`
4. 底层正文始终写成 `{{var_xxx}}`
5. 保存草稿时创建新 revision
6. 发布时切换 `published_revision_no`
2026-04-16 22:08:50 +08:00
### 8.4 AI 辅助
2026-04-16 22:08:50 +08:00
- AI 生成:根据场景描述生成 prompt 草稿
- AI 优化:对当前草稿 revision 进行优化建议
- 异步任务写入 `kol_assist_tasks`
- 费用记到 `kol_profiles.tenant_id`
2026-04-16 22:08:50 +08:00
### 8.5 Prompt 内容保护
2026-04-16 22:08:50 +08:00
- 正文存入受保护资产,前端不回传
- 普通用户只获取 `schema_json`
- 订阅租户无法查看原始 prompt 正文
2026-04-16 22:08:50 +08:00
---
## 9. 数据看板
2026-04-16 22:08:50 +08:00
### 9.1 指标
2026-04-16 22:08:50 +08:00
- 总订阅租户数
- 本月新增订阅
- 总使用次数
- 本月使用次数
- 失败次数与失败率
2026-04-16 22:08:50 +08:00
### 9.2 维度
2026-04-16 22:08:50 +08:00
- 按包:订阅租户数、使用次数、失败率
- 按 prompt:使用排行、失败排行
- 按时间:订阅趋势、使用趋势
2026-04-16 22:08:50 +08:00
### 9.3 数据来源
2026-04-16 22:08:50 +08:00
- 订阅:`kol_subscriptions`
- 授权:`kol_subscription_prompts`
- 使用:`kol_usage_logs`
2026-04-16 22:08:50 +08:00
---
## 10. Workspace 与文章集成
2026-04-16 22:08:50 +08:00
### 10.1 Workspace
新增接口:
2026-04-16 22:08:50 +08:00
```text
GET /api/tenant/workspace/kol-cards
```
返回当前租户可用的 KOL prompt 卡片:
2026-04-16 22:08:50 +08:00
- 包名
- Prompt 名称
- KOL 显示名
- 平台标识
- `subscription_prompt_id`
2026-04-16 22:08:50 +08:00
### 10.2 文章列表
2026-04-16 22:08:50 +08:00
文章列表对 `source_type='kol'` 展示:
2026-04-16 22:08:50 +08:00
- 来源标签:`KOL 生成`
- 关联 prompt 名称
- 关联 package 名称
2026-04-16 22:08:50 +08:00
### 10.3 明确不做的集成
2026-04-16 22:08:50 +08:00
- V1 不把 KOL prompt 混入 `template-cards`
- V1 不接入 `/api/tenant/templates/*`
- V1 不接入通用模板向导页面
这样可以避免普通模板链路绕过 KOL 的订阅鉴权和 usage 埋点。
2026-04-16 22:08:50 +08:00
---
## 11. 权限与鉴权
2026-04-16 22:08:50 +08:00
### 11.1 KOL 身份
2026-04-16 22:08:50 +08:00
满足以下条件才视为 KOL
- `kol_profiles.user_id = actor.UserID`
- `kol_profiles.tenant_id = actor.TenantID`
- `kol_profiles.status = 'active'`
说明:
- `status='active'` 决定能否进入 KOL 工作台
- `market_enabled=true` 只决定是否能在市场中对外展示
### 11.2 接口鉴权
| 路径前缀 | 鉴权方式 | 说明 |
|---------|---------|------|
| `/api/tenant/kol/marketplace/*` | 标准 tenant 身份 | 市场浏览与订阅 |
| `/api/tenant/kol/subscription-prompts/*` | tenant + access row | 生成 |
| `/api/tenant/kol/manage/*` | tenant + active kol_profile | 工作台 |
| `/api/tenant/kol/dashboard/*` | tenant + active kol_profile | 看板 |
| `/api/platform/admin/kol/*` | `platform_role` | 平台运营 |
### 11.3 审计
高风险操作必须写审计日志:
- KOL Profile 开通、冻结、恢复
- 订阅审批、撤销
- Prompt 发布、归档
- KOL 包发布、归档
---
## 12. i18n
新增 `kol` 命名空间:
```text
kol.marketplace.title
kol.marketplace.filter.*
kol.package.subscribe
kol.package.pending
kol.package.subscribed
kol.generate.title
kol.generate.submit
kol.manage.title
kol.manage.createPackage
kol.manage.editor.*
kol.dashboard.title
kol.dashboard.totalSubs
kol.dashboard.monthSubs
kol.dashboard.totalUsage
kol.dashboard.monthUsage
kol.dashboard.failRate
nav.kolMarketplace
nav.kolManage
nav.kolDashboard
status.sourceType.kol
2026-04-16 22:08:50 +08:00
```
---
## 13. 第一版范围
2026-04-16 22:08:50 +08:00
### 第一版做
- `kol_profiles`
- `kol_packages`
- `kol_prompts + kol_prompt_revisions`
- `kol_subscriptions + kol_subscription_prompts`
- KOL 市场浏览与申请订阅
- KOL 工作台与三栏编辑器
- AI 辅助生成/优化
- KOL 专用生成链路
- `kol_usage_logs` 审计与看板
- Workspace KOL 卡片区
2026-04-16 22:08:50 +08:00
### 第一版不做
- 旧 share code 兼容层
- 通用模板选择器集成
- 在线支付
- 收益分账/提现
- KOL 自助入驻
- KOL 多租户迁移
2026-04-16 22:08:50 +08:00
- Prompt A/B 测试
- 订阅评价/评分系统
---
## 14. 关键决策总结
1. KOL 改为新的第一方模型,不再挂在旧分享能力上
2. KOL 原始 prompt 不写入 `article_templates`
3. 订阅后不再物化模板,改为 `kol_subscription_prompts` 授权映射
4. KOL 生成走独立 `source_type='kol'` / `task_type='kol'`
5. V1 不进入通用模板链路,先确保权限、审计、结算口径闭合