在 kira-cms 中新增 Memory Admin 自定义视图,让运营人员可以按用户查看、搜索、新增、编辑和删除记忆。实现方式参考现有的 Delete Account 视图(Server Component + Client Form),通过调用 kira-memory 的 Admin API 完成所有操作。
核心能力
| 功能 | 说明 |
|---|
| 用户搜索 | 按 userId / email / nickname 搜索用户,展示其记忆概览 |
| Profile 查看 | 展示用户的 Compact Memory 画像(style / workflow / instructions / context) |
| Profile 编辑 | 运营人员可手动修正用户画像内容 |
| 记忆列表 | 分页展示用户所有 Vector Memory(情景记忆),支持按类型筛选 |
| 记忆详情 | 查看单条记忆的完整内容、元数据、权重信息 |
| 新增记忆 | 手动为用户添加记忆(自动生成 embedding) |
| 编辑记忆 | 修改记忆内容(自动重新 embedding) |
| 删除记忆 | 硬删除单条记忆 |
| 批量删除 | 勾选多条记忆批量删除 |
| 清空记忆 | 一键清空用户所有记忆 + 重置 profile(高危操作,需二次确认) |
CMS 不直接访问 LanceDB 或 Supabase memory schema,所有操作通过 kira-memory 的 Admin API 进行,保持职责单一。
kira-memory Admin API
所有 Admin API 路由前缀为 /admin,通过内网调用,需要 CMS 层面的管理员鉴权(CMS 登录态 → 请求携带 admin token)。
GET /admin/users
搜索有记忆数据的用户列表。
// Request
GET /admin/users?q=john&page=1&limit=20
// Response
{
users: Array<{
entity_id: string,
entity_type: 'user' | 'group',
memory_count: number, // 记忆总数
profile_updated_at: string, // 画像最后更新时间
has_profile: boolean,
}>,
total: number,
page: number,
limit: number,
}
实现:查询 Supabase memory.profiles 表,联合 LanceDB 统计 memory_count。q 参数先去 Supabase auth.users / user_profiles 做模糊匹配拿到 userId 列表,再关联 memory 数据。
GET /admin/users/:entity_id/profile
获取用户 Compact Memory 画像。
// Response
{
entity_id: string,
entity_type: 'user' | 'group',
style: string | null,
workflow: string | null,
instructions: string | null,
context: string | null,
stats: object,
updated_at: string,
}
PUT /admin/users/:entity_id/profile
手动编辑用户画像。
// Request
{
style?: string,
workflow?: string,
instructions?: string,
context?: string,
}
// Response
{ success: true, updated_at: string }
编辑后同步刷新 Dragonfly 缓存。
GET /admin/users/:entity_id/memories
分页获取用户的所有情景记忆。
// Request
GET /admin/users/:entity_id/memories?page=1&limit=20&type=preference&sort=created_at&order=desc
// Query Params
{
page?: number, // 默认 1
limit?: number, // 默认 20,最大 100
type?: string, // 可选过滤:preference | workflow | instruction | episodic
sort?: string, // 排序字段:created_at | importance | decay_weight | access_count
order?: 'asc' | 'desc', // 默认 desc
}
// Response
{
memories: Array<{
id: string,
content: string,
type: 'preference' | 'workflow' | 'instruction' | 'episodic',
source: 'behavior' | 'conversation' | 'explicit',
importance: number,
access_count: number,
decay_weight: number,
metadata: {
thread_id?: string,
tool_name?: string,
model?: string,
prompt?: string,
satisfaction?: string,
},
created_at: string,
last_accessed_at: string | null,
consolidated_at: string | null,
}>,
total: number,
page: number,
limit: number,
}
返回结果不包含 embedding 向量(512 维 Float32Array 太大),仅在详情接口中按需返回。
GET /admin/memories/:id
获取单条记忆详情(含 embedding 元信息)。
// Response
{
id: string,
entity_id: string,
entity_type: 'user' | 'group',
content: string,
embedding_preview: number[], // 前 8 维,用于调试展示
embedding_norm: number, // 向量范数
type: string,
source: string,
importance: number,
access_count: number,
decay_weight: number,
metadata: object,
created_at: string,
last_accessed_at: string | null,
consolidated_at: string | null,
}
POST /admin/users/:entity_id/memories
运营手动为用户新增记忆。
// Request
{
content: string, // 记忆内容(自然语言)
type: 'preference' | 'workflow' | 'instruction' | 'episodic',
importance?: number, // 0-1,默认 0.8
metadata?: {
note?: string, // 运营备注(标记为人工添加)
},
}
// Response
{ id: string, deduplicated: boolean }
自动生成 embedding,写入前执行去重检查(与 /memory/add 逻辑一致)。source 自动标记为 explicit,metadata 中附加 { admin: true, operator: "cms_user_id" } 以区分运营手动添加和 Agent 添加。
PUT /admin/memories/:id
编辑记忆内容。
// Request
{
content?: string, // 修改后内容(触发重新 embedding)
type?: string, // 修改分类
importance?: number, // 修改重要性
}
// Response
{ success: true }
DELETE /admin/memories/:id
硬删除单条记忆。
// Response
{ success: true }
POST /admin/users/:entity_id/memories/batch-delete
批量删除记忆。
// Request
{ ids: string[] }
// Response
{ deleted: number }
DELETE /admin/users/:entity_id/memories
清空用户所有记忆并重置 profile。高危操作,需要请求头携带确认标记。
// Request Header
X-Confirm-Dangerous: "RESET_ALL_MEMORIES"
// Response
{
memories_deleted: number,
profile_reset: true,
}
清空后同步刷新 Dragonfly 缓存。操作记录写入 Supabase 审计日志。
CMS 视图设计
文件结构
参考 Delete Account 视图的实现模式:
kira-cms/src/
components/
NavLinks.tsx # 新增 "User Memory" 导航链接
views/
MemoryAdmin.tsx # Server Component:页面入口
MemoryAdminPanel.tsx # Client Component:主面板
MemoryUserSearch.tsx # Client Component:用户搜索
MemoryProfileCard.tsx # Client Component:画像卡片(可编辑)
MemoryTable.tsx # Client Component:记忆列表表格
MemoryDetailModal.tsx # Client Component:记忆详情/编辑弹窗
页面布局
┌────────────────────────────────────────────────────────────┐
│ User Memory Management │
├────────────────────────────────────────────────────────────┤
│ 🔍 搜索用户: [userId / email / nickname ] [Search] │
├────────────────────────────────────────────────────────────┤
│ │
│ ┌─ User Profile (Compact Memory) ──────────────────────┐ │
│ │ Style: 偏好复古暖色调,vintage 使用率 80%... │ │
│ │ Workflow: 典型流程:滤镜→微调→裁剪→导出... │ │
│ │ Instructions: 导出时保持原始分辨率... │ │
│ │ Context: 常拍人像 │ │
│ │ Stats: sessions: 142 | edits/session: 3.2 │ │
│ │ [Edit Profile] │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌─ Vector Memories ─────────────────────────────────────┐ │
│ │ Filter: [All Types ▼] Sort: [Created ▼] [+ Add] │ │
│ │ ┌─────────────────────────────────────────────────────│ │
│ │ │ ☐ │ Type │ Content │ Imp. │ Decay │ │ │
│ │ ├───┼────────────┼──────────────────┼──────┼───────│ │ │
│ │ │ ☐ │ preference │ 喜欢暖色调滤镜... │ 0.9 │ 0.82 │ │ │
│ │ │ ☐ │ workflow │ 先裁剪再调色... │ 0.7 │ 0.65 │ │ │
│ │ │ ☐ │ instruction│ 所有图加水印... │ 1.0 │ 0.91 │ │ │
│ │ │ ☐ │ episodic │ 2月15日日落照... │ 0.6 │ 0.33 │ │ │
│ │ └─────────────────────────────────────────────────────│ │
│ │ [Delete Selected] Page 1/5 [< Prev] [Next >]│ │
│ │ │ │
│ │ ⚠️ [Clear All Memories] (需二次确认) │ │
│ └───────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
交互细节
| 操作 | 行为 |
|---|
| 搜索用户 | 输入后 debounce 300ms,调用 GET /admin/users?q=xxx,下拉展示匹配结果 |
| 选择用户 | 并行加载 profile 和 memories 列表 |
| Edit Profile | 点击后 profile 区域切换为可编辑文本框,保存调用 PUT /admin/users/:id/profile |
| + Add | 打开弹窗,填写 content / type / importance,提交调用 POST /admin/users/:id/memories |
| 点击行 | 打开详情弹窗,展示完整记忆信息,可编辑 content / type / importance |
| Delete Selected | 调用 POST /admin/users/:id/memories/batch-delete,需确认 |
| Clear All | 二次确认弹窗(输入 “RESET” 确认),调用 DELETE /admin/users/:id/memories |
Lark 通知
高危操作触发 Lark webhook 通知(复用现有 lib/lark.ts):
通知内容包含操作人、目标用户、删除数量、时间戳。
- CMS 层面:复用 Payload CMS 的管理员登录态,只有登录的管理员才能访问 Memory Admin 视图
- kira-memory 层面:Admin API 通过
X-Admin-Token 头部鉴权(共享密钥,环境变量 MEMORY_ADMIN_TOKEN),拒绝非授权请求
- 审计:所有写操作(增 / 改 / 删)记录操作人 ID、目标用户、操作类型、时间戳到 Supabase 审计表
审计日志
所有 Admin API 的写操作记录到 memory.admin_audit_log 表:
CREATE TABLE memory.admin_audit_log (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
operator_id TEXT NOT NULL, -- CMS 管理员 ID
action TEXT NOT NULL, -- create_memory | update_memory | delete_memory | batch_delete | reset_all | update_profile
target_entity TEXT NOT NULL, -- 目标用户/群 entity_id
detail JSONB DEFAULT '{}', -- 操作详情(如删除的 memory_id 列表、修改前后内容)
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_admin_audit_entity ON memory.admin_audit_log (target_entity, created_at DESC);
CREATE INDEX idx_admin_audit_operator ON memory.admin_audit_log (operator_id, created_at DESC);
与现有 API 的关系
| 接口 | 调用方 | 说明 |
|---|
POST /inject | kira-be Agent | 每轮对话前注入记忆上下文 |
POST /memory/add | kira-be Agent | Agent 显式存储记忆 |
POST /memory/search | kira-be Agent | Agent 主动查询 |
PUT /memory/:id | kira-be Agent | Agent 更新记忆 |
DELETE /memory/:id | kira-be Agent | Agent 删除记忆 |
/admin/* | kira-cms | 运营后台管理记忆(本文档) |
Agent API 和 Admin API 职责分离:
- Agent API 面向 AI,鉴权走 Supabase JWT,操作范围限于当前用户
- Admin API 面向运营,鉴权走 Admin Token,可操作任意用户