知更 Knower 文档
欢迎阅读知更 Knower 的完整技术文档。本文档涵盖系统架构、算法原理、数据结构和全部 API 接口。
知更 Knower 是面向个人视频创作者(B站/抖音/小红书)的本地 AI 桌面工作流客户端。帮助从选题到发布,生成多平台发布物料(脚本、标题、标签、封面文案、字幕稿等)。
核心特性
- 多平台物料生成 — 粘贴脚本,自动生成 B站、YouTube、抖音、小红书的发布物料
- 本地数据爬取 — 支持 B站、抖音、小红书、微博的数据采集
- 数据 100% 本地 — SQLite 存储,数据从未离开你的电脑
- 自带 API Key — 你自己的 AI 服务密钥,我们不接触
- AI Agent 工作流 — ReAct 循环 + 有状态条件路由 + 流式输出
- 双协议 LLM — 同时支持 Anthropic (Claude) 和 OpenAI 标准 API
- 选题评价算法 — 5 维度 12 指标量化评估选题爆款潜力
- 多账号隔离 — 支持多创作者账号切换,数据互不干扰
安装
环境要求
- 操作系统:Windows 10+(macOS 版本开发中)
- Node.js:18+(推荐 20 LTS)
- Python:3.10+(仅爬虫模块需要)
从源码构建
git clone https://github.com/user/knower.git
cd knower
npm install
npm run dev
Vite HMR + Electron 热重载将自动启动。
构建发布版本
npm run build # tsc 类型检查 + Vite 打包 + electron-builder 打包
npm run preview # 预览前端产物
爬虫模块初始化(可选)
cd knower-agent/crawler
setup_env.bat # 创建 venv + 安装依赖 + 安装 Playwright
快速上手
安装完成后,按以下步骤开始使用:
- 启动应用后,进入 设置 页面
- 选择 LLM 提供商(Anthropic 或 OpenAI-compatible),填入 API Key 和模型名
- 进入 创作台,输入你的创作想法
- AI Agent 会自动执行工具调用,生成多平台物料
创作台
创作台是知更的核心界面,提供 AI 对话式创作体验。底层运行的是一个 ReAct (Reason + Act) Agent,最大迭代 10 轮,支持工具调用和流式输出。
Agent 执行流程
使用方式
在聊天输入框中输入你的创作需求,Agent 会自动决定执行哪些工具:
// 示例:生成多平台物料
用户: 帮我根据这个脚本生成 B站和小红书的发布物料
Agent 执行流程:
1. 解析用户意图 → 确定需要 analyze_script + expand_script
2. 调用 analyze_script 分析脚本内容
3. 调用 expand_script 生成多平台物料
4. 调用 save_result 保存到数据库
5. 返回最终回复
输出物料类型
| 物料类型 | 说明 |
|---|---|
| B站标题 | 优化后的视频标题(10-30 字,含数字/问句/情感词) |
| B站标签 | 相关话题标签,支持热度排序 |
| 小红书标题 | 小红书风格标题(emoji + 关键词优化) |
| 封面文案 | 封面图文字建议(大字报风格 / 信息卡片) |
| 拍摄清单 | 分镜拍摄建议(景别 + 时长 + 画面描述) |
| 字幕稿 | 带时间戳的口播字幕 |
灵感库
灵感库用于管理和浏览 AI 生成的选题建议。基于爬取的平台数据和你的历史表现,AI 会为你推荐个性化选题。选题经过病毒性评分算法量化评估(详见 选题评价算法)。
选题生成流程
数据分析
数据分析页面展示爬取到的各平台数据,帮助你了解爆款规律。
- 概览卡片 — 各平台关键指标一览(总视频数、总播放量、平均互动率)
- 趋势图表 — 内容表现趋势可视化(按日/周聚合)
- 爆款分析 — AI 分析高互动内容的共性(标题模式、发布时间、分类分布)
爬虫模块
MediaCrawler 多平台爬虫已集成到 knower-agent/crawler/,支持 B站、抖音、小红书、微博四个平台。通过 Node.js 子进程桥接 Python 进程。
架构
Node.js 封装
// lib/crawler.js — 子进程调用
const { spawn } = require('child_process')
async function runCrawler(platform, keyword, options = {}) {
const args = [
'main.py',
'--platform', platform,
'--keyword', keyword,
'--max-notes', String(options.maxNotes || 10),
]
return new Promise((resolve, reject) => {
const proc = spawn('python', args, {
cwd: path.join(__dirname, '..', 'crawler'),
})
let stdout = ''
proc.stdout.on('data', d => { stdout += d })
proc.on('close', code => {
if (code !== 0) return reject(new Error(`Exit ${code}`))
try {
resolve(JSON.parse(stdout))
} catch {
reject(new Error('Failed to parse crawler output'))
}
})
})
}
Electron IPC 调用
// 渲染进程调用
const result = await window.electronAPI.runCrawler('bili', '关键词', {
maxNotes: 10,
specifiedId: '可选:指定UP主ID',
})
注意事项
- 首次运行需扫码登录,登录状态保存在
mediasrc/login_state/ - 建议
ENABLE_CDP_MODE = False(除非有远程调试 Chrome) .gitignore已排除.venv/、data/、登录状态等
Agent 引擎概述
知更的 AI Agent 是一个基于 ReAct (Reason + Act) 范式的有状态工作流引擎。核心组件位于 knower-agent/agent/。
组件架构
ReAct 主循环"] STATE["state.js
状态机"] ROUTER["router.js
条件路由"] PROC["processor.js
结果处理"] TOOLS["tools/
8 个工具"] CACHE["cache.js
提示词缓存"] end subgraph "LLM 层" ANTH["anthropic.js
Anthropic SDK"] OAI["openai-compat.js
OpenAI 兼容"] end subgraph "数据层" DB["db/index.js
SQLite WASM"] MEM["memories
Agent 记忆"] end CORE --> STATE CORE --> ROUTER CORE --> PROC CORE --> TOOLS CORE --> CACHE CORE --> ANTH CORE --> OAI TOOLS --> DB PROC --> MEM
核心配置常量
const MAX_ITERATIONS = 10 // 最大 ReAct 循环次数
const TOOL_TIMEOUT = {
default: 30000, // 一般工具 30s 超时
crawl_data: 120000, // 爬虫工具 120s 超时
crawl_data_batch: 120000,
}
const MAX_RETRIES = 2 // 工具执行最大重试次数
ReAct 循环(深入)
ReAct 循环是 Agent 的核心执行逻辑,位于 agent/core.js。
+ 上下文] PROMPT --> LLM[调用 LLM
chat / stream] LLM --> STOP{stopReason?} STOP -->|"tool_use"| ROUTE{Router 判断} ROUTE -->|"工具兼容"| EXEC[执行工具
executeToolWithRetry] ROUTE -->|"工具不兼容"| WARN[记录警告
继续执行] WARN --> EXEC EXEC --> RESULT{执行成功?} RESULT -->|"成功"| PROC[processToolResult
更新 State] RESULT -->|"可重试错误"| RETRY[指数退避重试
1s, 2s, ...] RETRY --> EXEC RESULT -->|"不可重试"| ERR[记录错误
更新 State] PROC --> ITER{迭代次数未达上限?} ERR --> ITER ITER -->|"是"| PROMPT ITER -->|"否"| FORCED[强制结束
返回当前结果] STOP -->|"end_turn"| CHECK{State 检查} CHECK -->|"需要自动操作"| AUTO[auto_analyze /
auto_generate / auto_save] AUTO --> PROMPT CHECK -->|"任务完成"| DONE([返回回复]) CHECK -->|"idle 无操作"| DONE FORCED --> DONE
executeToolWithRetry 算法
async function executeToolWithRetry(tool, input, maxRetries = 2) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const result = await tool.execute(input)
if (result.error && isRetryableError(result.error)) {
await sleep(1000 * (attempt + 1)) // 指数退避
continue
}
return result
} catch (err) {
if (isRetryableError(err.message) && attempt < maxRetries) {
await sleep(1000 * (attempt + 1))
continue
}
}
}
return { error: '工具执行失败', retryable: false }
}
// 可重试错误模式
const retryablePatterns = [
'timeout', 'ETIMEDOUT', 'ECONNRESET', 'ECONNREFUSED',
'rate limit', '429', '503', '502',
'network', 'fetch failed',
]
有限状态机
Agent 使用有限状态机(FSM)管理工作流状态,位于 agent/state.js。状态转换遵循严格的合法转换表。
合法转换表(VALID_TRANSITIONS)
const transitions = {
idle: ['crawling', 'analyzing', 'querying', 'suggesting'],
crawling: ['analyzing', 'idle', 'done'],
analyzing: ['generating', 'idle', 'done'],
generating:['saving', 'idle', 'done'],
saving: ['idle', 'done'],
querying: ['idle', 'done'],
suggesting:['idle', 'done'],
done: ['idle'],
}
State 数据结构
class AgentState {
phase: 'idle' | 'crawling' | 'analyzing' | 'generating' | 'saving' | 'querying' | 'suggesting' | 'done'
script: string | null // 用户输入的脚本
analysis: object | null // 分析结果
materials: object | null // 生成的物料
crawlData: array | null // 爬取结果
crawlStats: object | null // 爬取统计
topicSuggestions: array | null // 选题建议
errors: string[] // 错误列表
warnings: string[] // 警告列表
userPreferences: object // 用户偏好(来自 memories)
toolHistory: array // 已执行工具历史
metadata: {
startTime: number, // 开始时间戳
toolCallCount: number, // 工具调用次数
iterationCount: number, // ReAct 迭代次数
platforms: string[], // 相关平台
targetPlatforms: string[], // 目标平台
}
}
getNextAction 决策逻辑
当 LLM 返回 end_turn(无工具调用)时,Router 根据当前 State 决定下一步:
- idle + 有 script 但无 analysis → 自动触发
auto_analyze - analyzing + analysis 已就绪 → 自动触发
auto_generate - generating + materials 已就绪 → 自动触发
auto_save - 其他情况 → 返回
continue,等待下一轮
工具系统
Agent 可调用 8 个工具,每个工具有独立的输入模式(input_schema)、执行逻辑和超时设置。工具定义位于 agent/tools/。
工具清单
| 工具名 | 文件 | 超时 | 功能 |
|---|---|---|---|
analyze_script | analyze_script.js | 30s | 分析用户输入的脚本/想法,提取关键信息 |
expand_script | expand_script.js | 30s | 基于分析结果生成多平台发布物料 |
crawl_data | crawl_data.js | 120s | 调用 MediaCrawler 爬取单平台数据 |
crawl_data_batch | crawl_data_batch.js | 120s | 批量爬取多平台数据 |
query_data | query_data.js | 30s | 查询本地数据库中的历史数据 |
save_result | save_result.js | 30s | 将生成结果保存到数据库 |
request_user_input | request_user_input.js | 30s | 向用户请求额外信息 |
suggest_topics | suggest_topics.js | 30s | 基于数据生成选题建议 |
工具-阶段兼容矩阵
Router 在执行工具前会检查工具与当前 State 阶段的兼容性:
| 阶段 | 可用工具 |
|---|---|
idle | crawl_data, crawl_data_batch, query_data, suggest_topics, request_user_input, analyze_script |
crawling | crawl_data, crawl_data_batch, query_data |
analyzing | analyze_script, request_user_input |
generating | expand_script |
saving | save_result |
querying | query_data |
suggesting | suggest_topics |
done | (无可用工具) |
工具调用序列图
LLM 客户端(双协议架构)
系统同时支持 Anthropic 原生 API 和 OpenAI-compatible API,两个客户端实现统一接口。
统一接口规范
// 两个客户端都实现相同接口
interface LLMClient {
chat({ system, messages, tools, maxTokens, temperature }): Promise<{
content: ContentBlock[], // Anthropic-style content blocks
stopReason: 'tool_use' | 'end_turn',
usage: { input_tokens, output_tokens }
}>
async *stream({ system, messages, tools, maxTokens, temperature, signal }): AsyncGenerator<
| { type: 'text', text: string }
| { type: 'final', content: ContentBlock[], stopReason, toolUseInputs, hasToolUse, usage }
>
}
Anthropic 客户端
| 配置项 | 说明 | 示例 |
|---|---|---|
provider | 固定为 anthropic | anthropic |
apiKey | Anthropic API Key | sk-ant-api03-xxx |
baseUrl | API 端点(可选) | https://api.anthropic.com |
model | Claude 模型名 | claude-sonnet-4-20250514 |
API 端点: POST /v1/messages
认证头: x-api-key: {apiKey}
流式协议: Server-Sent Events (SSE),事件类型包括 content_block_start、content_block_delta、content_block_stop
OpenAI-Compatible 客户端
| 配置项 | 说明 | 示例 |
|---|---|---|
provider | 非 anthropic 的任意值 | openai / deepseek / qwen |
apiKey | 对应服务的 API Key | sk-xxx |
baseUrl | API 端点 | https://api.openai.com/v1 |
model | 模型名 | gpt-4o / deepseek-chat |
API 端点: POST /v1/chat/completions
认证头: Authorization: Bearer {apiKey}
流式协议: SSE,标准 OpenAI 格式(data: {choices: [{delta: {...}}]})
格式转换层
OpenAI 客户端内部进行 Anthropic ↔ OpenAI 格式转换:
- 工具定义: Anthropic
input_schema→ OpenAIfunction.parameters - 消息格式: Anthropic
tool_resultblocks → OpenAIrole: 'tool'messages - 工具调用: Anthropic
tool_useblocks → OpenAItool_calls数组 - 输出归一化: OpenAI
tool_calls→ Anthropic-styletool_usecontent blocks
LLM 流式状态机
API 配置
在设置页面配置 LLM 服务。支持 Anthropic (Claude) 和 OpenAI-compatible 两种协议。
配置项说明
| 配置项 | 说明 | Anthropic 示例 | OpenAI 示例 |
|---|---|---|---|
provider | LLM 提供商 | anthropic | openai / deepseek |
apiKey | API Key | sk-ant-api03-xxx | sk-xxx |
baseUrl | API 端点 | https://api.anthropic.com | https://api.openai.com/v1 |
model | 模型名 | claude-sonnet-4-20250514 | gpt-4o |
x-api-key 认证头,OpenAI 使用 Bearer token。系统根据 provider 字段自动选择正确的客户端和认证方式。electron-store 中,不经过任何第三方服务器。平台参数
| 平台 | platform 值 | 说明 | 特殊参数 |
|---|---|---|---|
| B站 | bili | Bilibili 视频平台 | specifiedId(指定视频ID), creatorId(指定UP主ID) |
| 抖音 | dy | 需要 Node.js(JS 签名) | - |
| 小红书 | xhs | 图文/视频笔记 | - |
| 微博 | wb | 微博内容 | - |
数据库
使用 sql.js(WebAssembly 版 SQLite)本地数据库 knower.db。支持防抖写入(2s 延迟)和进程退出时强制刷盘。
写入策略
// 防抖写入:2s 内多次修改只写一次
let _dirty = false
let _saveTimer = null
function saveDb() {
_dirty = true
if (_saveTimer) return
_saveTimer = setTimeout(() => {
if (!_dirty || !db) return
_dirty = false
const data = db.export() // 导出为 Uint8Array
const buffer = Buffer.from(data)
fs.writeFileSync(DB_PATH, buffer)
}, 2000)
}
// 进程退出时强制刷盘
process.on('exit', flushDb)
process.on('SIGINT', () => { flushDb(); process.exit() })
process.on('SIGTERM', () => { flushDb(); process.exit() })
数据库模块导出 42+ 个函数,覆盖所有表的 CRUD 操作。
数据库 Schema
完整 Schema 包含 10 张表,支持多账号数据隔离。
accounts — 多创作者账号管理
CREATE TABLE IF NOT EXISTS accounts (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
platform TEXT NOT NULL,
uid TEXT DEFAULT '',
avatar_url TEXT DEFAULT '',
description TEXT DEFAULT '',
is_active INTEGER DEFAULT 0,
user_id TEXT NOT NULL DEFAULT 'default',
created_at DATETIME DEFAULT (datetime('now','localtime')),
updated_at DATETIME DEFAULT (datetime('now','localtime'))
)
scripts — 脚本存储
CREATE TABLE IF NOT EXISTS scripts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL,
analysis TEXT,
result TEXT,
account_id TEXT NOT NULL DEFAULT 'default',
created_at DATETIME DEFAULT (datetime('now','localtime'))
)
conversations — 对话记录
CREATE TABLE IF NOT EXISTS conversations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL DEFAULT '新对话',
is_pinned INTEGER DEFAULT 0,
account_id TEXT NOT NULL DEFAULT 'default',
created_at DATETIME DEFAULT (datetime('now','localtime')),
updated_at DATETIME DEFAULT (datetime('now','localtime'))
)
messages — 消息
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
conversation_id INTEGER NOT NULL,
role TEXT NOT NULL, -- 'user' | 'assistant' | 'system'
content TEXT NOT NULL,
created_at DATETIME DEFAULT (datetime('now','localtime')),
FOREIGN KEY (conversation_id) REFERENCES conversations(id)
)
memories — Agent 记忆
CREATE TABLE IF NOT EXISTS memories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id TEXT NOT NULL DEFAULT 'default',
type TEXT NOT NULL, -- 'style' | 'preference' | 'topic'
key TEXT NOT NULL,
value TEXT NOT NULL,
evidence TEXT,
weight REAL NOT NULL DEFAULT 0.5,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
)
crawl_tasks — 爬取任务
CREATE TABLE IF NOT EXISTS crawl_tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
platform TEXT NOT NULL,
keywords TEXT,
crawler_type TEXT DEFAULT 'search',
status TEXT DEFAULT 'pending', -- 'pending' | 'running' | 'done' | 'error'
result_json TEXT,
account_id TEXT NOT NULL DEFAULT 'default',
created_at DATETIME DEFAULT (datetime('now','localtime')),
completed_at DATETIME
)
crawl_content — 爬取内容数据
CREATE TABLE IF NOT EXISTS crawl_content (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id INTEGER,
platform TEXT NOT NULL,
content_type TEXT,
content_id TEXT,
title TEXT,
"desc" TEXT,
author_name TEXT,
author_id TEXT,
like_count INTEGER DEFAULT 0,
comment_count INTEGER DEFAULT 0,
share_count INTEGER DEFAULT 0,
play_count INTEGER DEFAULT 0,
created_at TEXT,
raw_json TEXT,
category TEXT DEFAULT '未分类',
source_uid TEXT DEFAULT '',
source_name TEXT DEFAULT '',
fetched_at DATETIME DEFAULT (datetime('now','localtime')),
FOREIGN KEY (task_id) REFERENCES crawl_tasks(id),
UNIQUE(platform, content_id)
)
topic_suggestions — 选题建议
CREATE TABLE IF NOT EXISTS topic_suggestions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id TEXT NOT NULL DEFAULT 'default',
title TEXT NOT NULL,
description TEXT,
score REAL DEFAULT 0,
reasoning TEXT,
source TEXT DEFAULT 'ai',
status TEXT DEFAULT 'pending', -- 'pending' | 'approved' | 'rejected'
created_at DATETIME DEFAULT (datetime('now','localtime'))
)
content_notes — 创作者笔记
CREATE TABLE IF NOT EXISTS content_notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id TEXT NOT NULL DEFAULT 'default',
title TEXT,
content TEXT NOT NULL,
tags TEXT,
created_at DATETIME DEFAULT (datetime('now','localtime')),
updated_at DATETIME DEFAULT (datetime('now','localtime'))
)
content_library — 内容素材库
CREATE TABLE IF NOT EXISTS content_library (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id TEXT NOT NULL DEFAULT 'default',
type TEXT NOT NULL, -- 'reference' | 'template' | 'asset'
title TEXT,
content TEXT NOT NULL,
metadata TEXT,
created_at DATETIME DEFAULT (datetime('now','localtime'))
)
IPC 通道全表
渲染进程通过 contextBridge 与主进程通信,安全配置:contextIsolation: true,nodeIntegration: false。所有 handler 使用 ipcMain.handle / ipcRenderer.invoke 模式。
设置存储
| 通道 | 方向 | 参数 | 返回 | 说明 |
|---|---|---|---|---|
store:get | R→M | key: string | any | 读取 electron-store |
store:set | R→M | key: string, value: any | void | 写入 electron-store |
对话管理
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
conversation:list | R→M | accountId?: string | Conversation[] |
conversation:create | R→M | title: string, accountId | { id: number } |
conversation:rename | R→M | id: number, title: string | void |
conversation:delete | R→M | id: number | void |
conversation:togglePin | R→M | id: number | void |
消息管理
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
messages:get | R→M | conversationId: number | Message[] |
messages:add | R→M | conversationId, role, content | { id: number } |
脚本管理
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
script:save | R→M | content, analysis, result, accountId | { id: number } |
script:list | R→M | accountId?: string | Script[] |
爬虫
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
crawler:run | R→M | platform, keyword, options | CrawlResult |
账号管理
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
account:list | R→M | - | Account[] |
account:create | R→M | name, platform, uid? | Account |
account:switch | R→M | accountId: string | void |
account:delete | R→M | accountId: string | void |
数据查询
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
data:crawlContent | R→M | accountId? | CrawlContent[] |
data:crawlTasks | R→M | accountId? | CrawlTask[] |
data:stats | R→M | accountId? | Stats |
选题管理
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
topic:list | R→M | accountId? | TopicSuggestion[] |
topic:create | R→M | title, description, score, accountId | TopicSuggestion |
topic:updateStatus | R→M | id, status | void |
topic:delete | R→M | id | void |
笔记与素材
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
note:list | R→M | accountId? | Note[] |
note:create | R→M | title, content, tags, accountId | Note |
note:update | R→M | id, title?, content?, tags? | void |
note:delete | R→M | id | void |
library:list | R→M | accountId? | LibraryItem[] |
library:create | R→M | type, title, content, metadata?, accountId | LibraryItem |
library:delete | R→M | id | void |
记忆系统
| 通道 | 方向 | 参数 | 返回 |
|---|---|---|---|
memory:list | R→M | accountId?, type? | Memory[] |
memory:upsert | R→M | type, key, value, evidence?, weight?, accountId | Memory |
memory:delete | R→M | id | void |
窗口控制
| 通道 | 方向 | 说明 |
|---|---|---|
window:minimize | R→M | 最小化窗口 |
window:maximize | R→M | 最大化/还原窗口 |
window:close | R→M | 关闭窗口 |
事件流(M→R)
| 事件 | 方向 | 说明 |
|---|---|---|
agent:progress | M→R | Agent 执行进度(阶段、工具名、进度百分比) |
agent:stream | M→R | LLM 流式输出文本块 |
agent:tool-call | M→R | 工具调用开始/完成/错误 |
topic:toChat | M→R | 从灵感库发送选题到创作台 |
技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| Electron | 33 | 桌面应用框架 |
| React | 18 | UI 渲染(Hooks API) |
| TypeScript | 5.6 | 类型安全(strict mode) |
| Vite | 6 | 构建工具 + HMR |
| vite-plugin-electron | - | Electron 主进程/preload 分离构建 |
| Tailwind CSS | 3.4 | 样式系统(暗色主题) |
| sql.js | - | WASM 版 SQLite(本地数据库) |
| @anthropic-ai/sdk | - | Anthropic Claude API 客户端 |
| gsap | - | 动画库(页面过渡、折叠动画) |
| @phosphor-icons/react | - | 图标库 |
| MediaCrawler | - | 多平台数据爬取(Python) |
项目结构
knower/
├── electron/
│ ├── main.ts # 主进程:窗口创建(~48个IPC handler)
│ └── preload.ts # contextBridge暴露~50个方法
├── src/
│ ├── App.tsx # 页面路由 (useState<Page>)
│ ├── components/
│ │ ├── ChatView.tsx # 创作台(Agent流式输出)
│ │ ├── Sidebar.tsx # 侧边栏(导航+对话历史)
│ │ ├── AccountSwitcher.tsx # 多账号切换
│ │ ├── MaterialCards.tsx # 物料卡片展示
│ │ ├── SettingsView.tsx # API配置页
│ │ ├── TopicsView.tsx # 灵感库
│ │ └── DataView.tsx # 数据分析
│ ├── contexts/
│ │ ├── ToastContext.tsx # 全局Toast
│ │ ├── PlatformContext.tsx # 平台信息
│ │ └── AccountContext.tsx # 账号状态
│ ├── lib/
│ │ └── gsap.ts # 页面过渡动画
│ ├── types/
│ │ └── electron.ts # IPC类型定义
│ └── index.css # Tailwind组件样式
├── knower-agent/
│ ├── agent/
│ │ ├── core.js # ReAct主循环(MAX_ITERATIONS=10)
│ │ ├── state.js # 有限状态机(8状态)
│ │ ├── router.js # 条件路由+工具兼容检查
│ │ ├── processor.js # 工具结果处理+上下文构建
│ │ ├── cache.js # 系统提示词缓存
│ │ └── tools/ # 8个工具实现
│ │ ├── analyze_script.js
│ │ ├── expand_script.js
│ │ ├── crawl_data.js
│ │ ├── crawl_data_batch.js
│ │ ├── query_data.js
│ │ ├── save_result.js
│ │ ├── request_user_input.js
│ │ └── suggest_topics.js
│ ├── llm/
│ │ ├── index.js # LLM客户端工厂
│ │ ├── anthropic.js # Anthropic SDK封装
│ │ └── openai-compat.js # OpenAI兼容(格式转换层)
│ ├── virality-score/
│ │ ├── index.js # 统一入口
│ │ ├── metrics.js # 12个指标计算
│ │ ├── normalizer.js # 4种归一化器(fit-transform)
│ │ └── scorer.js # 维度融合+置信度+解读
│ ├── db/
│ │ └── index.js # SQLite WASM(10表,42+函数)
│ ├── lib/
│ │ └── crawler.js # Python子进程桥接
│ └── crawler/ # MediaCrawler Python模块
├── tailwind.config.js # 颜色和字体定义
├── vite.config.ts # Vite + electron构建配置
└── tsconfig.json
系统架构图
(contextBridge)"] end subgraph "Electron 主进程" MT["main.ts"] HANDLERS["~48 IPC Handlers"] WIN["BrowserWindow
frame:false, vibrancy"] end subgraph "Agent Core (Node.js)" REACT["ReAct 循环
core.js"] STATE["状态机
state.js"] ROUTER["路由器
router.js"] TOOLS["8 个工具
tools/"] end subgraph "LLM 层" ANTH["Anthropic
Claude API"] OAI["OpenAI-compat
GPT/DeepSeek/..."] end subgraph "数据层" DB["SQLite WASM
knower.db
10表, 42+函数"] MEM["Agent 记忆
memories表"] end subgraph "外部服务" CRAWL["MediaCrawler
Python 子进程"] BILI["B站 API"] DY["抖音 API"] XHS["小红书 API"] WB["微博 API"] end UI <-->|"IPC"| IPC IPC <-->|"ipcMain.handle"| HANDLERS MT --> WIN HANDLERS --> REACT REACT --> STATE REACT --> ROUTER REACT --> TOOLS REACT --> ANTH REACT --> OAI TOOLS --> DB TOOLS --> CRAWL CRAWL --> BILI CRAWL --> DY CRAWL --> XHS CRAWL --> WB ROUTER --> MEM
分支约定
| 分支 | 用途 |
|---|---|
main | 稳定版本 |
dev | 开发分支 |
feat/xxx | 功能分支 |
提交规范
提交格式:type(scope): 描述
| type | 说明 | 示例 |
|---|---|---|
feat | 新功能 | feat(chat): 接入 streaming API |
fix | 修复 | fix(settings): 修复 API key 保存 |
refactor | 重构 | refactor(agent): 有状态条件路由替代 while 循环 |
style | 样式 | style: 调整侧边栏间距 |
docs | 文档 | docs: 更新 API 配置说明 |
chore | 杂项 | chore: 升级 Electron 版本 |
贡献指南
欢迎贡献代码!请遵循以下步骤:
- Fork 仓库并创建功能分支
feat/your-feature - 按照提交规范进行开发
- 确保
npm run build通过 - 提交 Pull Request 到
dev分支
许可证
知更 Knower 采用 MIT License 开源协议发布。
你可以自由地使用、修改和分发本软件,但需保留原始版权声明和许可证。