1. 为什么我要自己搭一个 AI 小说写作工作台
写长篇最折磨人的地方,从来不是「写不出这一段」,而是写到三十万字的时候,你已经忘了第三章那个配角姓什么、第七章埋的伏笔到底指向谁。普通 AI 对话工具能帮你发散灵感,但项目一长,上下文就丢,人物关系开始漂移,大纲和正文各写各的。传统写作软件编辑功能很稳,可它不会主动去读你的设定集,也不会在你写崩的时候提醒你「这个角色上一卷已经死了」。
我试过把设定、大纲、正文全塞进一个超长对话里,结果就是模型开始胡编,把两个角色的名字混在一起。后来我意识到,这不是模型的问题,是工程问题:资料分散、设定遗忘、上下文失控、大纲与正文脱节。要解决它,得有一个本地优先的桌面工作台,把项目管理、资料维护、章节写作和 AI 协作放进同一个界面。
这就是 CharacterArc(弧光)的思路,一个基于 Electron + Vue 3 + TypeScript + SQLite 的开源 AI 小说创作桌面应用。它不追求「一键生成整本小说」,而是把 AI 当成一个能读项目资料、能调工具、能提修改方案的协作 Agent。本文会带你从零跑通它的项目结构、Agent 调用链配置,以及用 TaoToken 统一 Key 接入模型接口的完整步骤,最后验证章节生成闭环。适合有前端基础、想自己掌控写作数据、又不想被单一模型绑死的写作者和开发者。
2. TaoToken 统一 Key 接入:一个 Key 管多模型
CharacterArc 本身不内置收费模型,你需要自己配置 OpenAI 兼容接口或 Anthropic 接口。问题来了:写小说时你可能想用 DeepSeek 做大纲扩写,用 Claude 做文风润色,用通义做章节修复。如果每个模型都单独配一套 Key、一套 Base URL,标题栏切换起来会很乱,配置也容易写错。
TaoToken 在这里的作用就是统一入口。它提供 OpenAI 兼容协议和 Anthropic 协议两种接入方式,你只需要一个 Key,就能在 CharacterArc 里保存多套接口配置,按需切换模型。官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api (这个不加 UTM)。
具体怎么拿 Key:进入控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 创建一个新 Key。创建时建议按用途命名,比如characterarc-novel,方便后面在多个项目里区分。Key 只在创建时完整显示一次,复制后先存到本地密码管理器。
拿到 Key 之后,CharacterArc 的模型配置逻辑是这样的:它支持保存多套接口配置,每套配置包含协议类型、Base URL、API Key、模型 ID。对于 OpenAI 兼容协议,Base URL 填https://taotoken.net/api,模型 ID 填你实际要用的模型名,比如deepseek-chat、claude-sonnet-4-20250514这类。对于 Anthropic 协议,同样走 TaoToken 的 Anthropic 兼容入口,Base URL 保持一致,协议类型选 Anthropic。
这里有个容易踩的坑:很多人把 Base URL 写成https://taotoken.net/api/v1,结果请求 404。CharacterArc 的 OpenAI 兼容层会自动补/v1/chat/completions,所以你只需要填到/api这一层。如果你用的是其他客户端,比如 Cline 或 Claude Code,配置方式略有不同,但核心三件套不变:Base URL、Key、Model ID。
为什么推荐用统一 Key 而不是每个模型单独申请?一是省事,二是切换成本低。你在写大纲时用推理强的模型,写正文时换成文风好的模型,标题栏一点就切,不用重新填一遍配置。三是便于统计,所有调用都走同一个入口,用量和费用一目了然。对于长期维护多个小说项目的人来说,这种统一管理比散落各处的 Key 靠谱得多。
3. 可复制配置:项目结构、Agent 调用链与 settings 片段
先把项目拉下来。开发环境需要 Node.js 18+ 和 pnpm 10+:
git clone https://github.com/uu201/character-arc.git cd character-arc pnpm install pnpm run dev跑起来之后,你会看到项目中心、作品概览、Skill 管理、章节创作、封面工作台几个入口。整个应用的数据流是这样的:Vue 渲染进程通过 IPC 调用 Electron 主进程,主进程里跑 SQLite 持久化、AI 任务调度、Agent Loop、Skill 加载与匹配、项目知识检索,最后通过 OpenAI / Anthropic 传输层发出去。SQLite 和 AI 调用都放在主进程,渲染层只管界面和状态。
项目结构大致如下:
character-arc/ ├── src/ │ ├── main/ # Electron 主进程 │ │ ├── db/ # SQLite 封装与迁移 │ │ ├── agent/ # Agent Loop、工具调用、暂存区 │ │ ├── skills/ # Skill 加载与匹配 │ │ ├── ai/ # OpenAI / Anthropic 传输层 │ │ └── ipc/ # IPC 路由 │ ├── renderer/ # Vue 3 渲染层 │ │ ├── views/ # 项目中心、章节创作、Skill 管理 │ │ ├── stores/ # Pinia 状态 │ │ └── components/ # TipTap 编辑器、关系图谱 │ └── shared/ # 类型定义与常量 ├── electron.vite.config.ts └── package.jsonAgent 调用链是核心。一个典型的章节生成流程是:理解用户需求 → 检索相关项目资料 → 读取目标章节和大纲 → 加载匹配的写作 Skill → 生成修改方案 → 进入暂存区等待用户审阅 → 用户确认后写回项目。涉及章节和项目资料的修改不会直接落盘,Agent 先生成暂存变更或 Diff,你确认后才写回。这样既保留 Agent 的操作能力,又不会把最终决定权交给模型。
模型配置部分,CharacterArc 把接口配置存在本地。如果你要手动写一份配置做备份或迁移,可以参考这个 JSON 结构(路径对应应用内的模型配置存储):
{ "providers": [ { "id": "taotoken-openai", "name": "TaoToken OpenAI 兼容", "protocol": "openai", "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的TaoTokenKey", "models": [ { "id": "deepseek-chat", "label": "DeepSeek 大纲" }, { "id": "claude-sonnet-4-20250514", "label": "Claude 润色" } ] }, { "id": "taotoken-anthropic", "name": "TaoToken Anthropic", "protocol": "anthropic", "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的TaoTokenKey", "models": [ { "id": "claude-sonnet-4-20250514", "label": "Claude 章节修复" } ] } ], "activeProviderId": "taotoken-openai", "activeModelId": "deepseek-chat" }注意baseUrl只写到/api,不要带/v1。apiKey用你在控制台创建的那个。protocol字段决定走 OpenAI 兼容还是 Anthropic 兼容。保存后重启应用,标题栏就能看到当前模型,点一下可以快速切换。
如果你同时用 Cline 或 Claude Code 做辅助开发,它们的配置也是同一套三件套。Cline 的 MCP 配置里,Base URL 填https://taotoken.net/api,Key 填同一个,Model ID 按需选。Claude Code 的 settings 里,Anthropic 协议入口同样指向 TaoToken。这样你在写作工作台和编码工具之间,用的是同一个 Key,管理起来不分裂。
4. 验证请求:跑通章节生成闭环
配置好之后,别急着写正文,先做一次最小验证。打开一个测试项目,创建一卷大纲,再建一个章节,绑定到刚建的大纲节点。章节工作台是三栏结构:左边章节目录树,中间 TipTap 正文编辑器,右边 AI 助手。
在 AI 助手里输入一个明确指令,比如「根据当前章节绑定的大纲节点,生成 800 字初稿,保持第三人称限知视角」。Agent 会先检索项目里的角色、世界观、大纲、章节、剧情线、创作记忆和知识文档,然后加载匹配的写作 Skill,比如「章节生成与修复」。生成结果不会直接写进正文,而是进入暂存区,你可以看到 Diff 对比。
如果请求成功,你会在暂存区看到一段带修改标记的文本,确认后写回章节。如果失败,常见的是 401。401 基本就是 Key 错了或者没带上。检查apiKey字段是不是完整复制,有没有多余空格。另一个常见报错是local proxy failed,这通常出现在你本地开了某些网络工具,导致请求被拦截。CharacterArc 是直连https://taotoken.net/api的,不需要任何本地代理,把系统代理关掉再试。
还有一种报错是reading 'choices',这表示返回结构不是预期的 OpenAI 格式。原因多半是 Base URL 写成了 Anthropic 协议却选了 OpenAI 协议,或者模型 ID 填错。对照一下:OpenAI 兼容协议返回choices数组,Anthropic 协议返回content数组。CharacterArc 会根据协议类型解析,所以协议和 Base URL 必须匹配。
验证通过后,你可以走一遍完整写作流程:先在大纲页用 AI 扩写分卷剧情,再创建章节绑定大纲节点,然后在章节工作台让 Agent 生成初稿,手动修改后保存快照。TipTap 编辑器支持自动保存、搜索替换、字数目标、阅读模式、专注模式、手动快照、历史版本回滚,以及 TXT 和 DOCX 导出。写完之后,项目可以导出为.carc归档,包含项目信息、世界观、角色、关系、组织、大纲、章节、历史版本、知识文档、参考作品、AI 运行记录、助手会话和项目级 Skill。换设备时导入归档就能恢复。
如果你想让 Agent 参考某部作品的文风,可以在拆书与知识库导入参考作品,分析叙事结构、提取语言风格、生成风格指纹。生成章节时手动选择需要参考的作品,系统按需检索,不会把整部作品塞进上下文。这样既控制了 token 消耗,又让文风有依据。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
排错时先分清是配置问题还是网络问题。下面这几个是我实际遇到过的。
401 Unauthorized。最常见。原因:Key 复制不完整、Key 被删除、Key 前后有空格、或者用了错误的协议入口。解决:重新在 API Keys 页面生成一个,粘贴时注意不要带换行。如果用的是 Anthropic 协议,确认 Key 有对应权限。
local proxy failed。这个报错说明请求在本地就被拦了。CharacterArc 直连 TaoToken,不需要任何本地代理工具。检查系统代理设置,把 HTTP/HTTPS 代理关掉。如果你在公司网络里,可能有透明代理,换一个网络环境再试。
reading 'choices'。返回结构解析失败。OpenAI 兼容协议期望choices,Anthropic 协议期望content。如果你把 Anthropic 的 Base URL 配到了 OpenAI 协议下,就会报这个。检查protocol字段和baseUrl是否匹配。另外,模型 ID 如果填了一个不存在的名字,也可能返回非预期结构。
OAuth 相关报错。CharacterArc 本身不需要 OAuth 登录,它用的是 API Key。如果你在 Claude Code 或某些 CLI 工具里看到 OAuth 报错,那是那个工具自己的认证流程,和 CharacterArc 无关。在 CharacterArc 里,只要 Base URL、Key、Model ID 三件套正确,就能直接调用。
还有一个隐蔽的坑:模型返回的思考内容被写进正文。DeepSeek、MiniMax、通义、Kimi、GLM 这些推理模型会输出<think>或reasoning_content。CharacterArc 会尝试隔离这些内容,但如果你用的模型 ID 不在它的识别列表里,可能会漏掉。解决办法是在 Skill 里加一条清洗规则,或者在 Agent 配置里显式声明该模型为推理模型。
排查顺序建议:先看 Key 是否有效,再看 Base URL 是否只写到/api,再看协议和模型 ID 是否匹配,最后看网络环境。大部分问题出在前两步。
6. 把工作台用起来:从配置到长期写作
跑通闭环之后,真正有价值的是长期使用。CharacterArc 内置了 3 组共 28 个 Skill,覆盖长篇小说写作、短篇小说写作、章节生成与修复、人物设计、世界观构建、节奏与高潮设计、情绪曲线、爽点设计、题材分析、平台商业化、风格指纹提取、多种文风融合、中文文本润色、去除机械化表达、封面提示词生成、平台内容合规等场景。AI 助手会根据当前对话、作品题材和创作阶段自动匹配 Skill,你也可以给单独项目导入自己的 Skill 包,项目级 Skill 相互隔离。
对于多模型切换,我的习惯是:大纲和剧情线用推理强的模型,章节初稿用文风好的模型,润色和去机械化表达用中文能力强的模型。这些都在 TaoToken 统一 Key 下管理,标题栏一点就切。如果你长期做编码和 Agent 开发,也可以看看 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它和写作工作台用的是同一套接入逻辑。
模型对话入口在 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。如果你用 Claude Code 做辅助开发,Anthropic 入口的配置参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude-code-anthropic&utm_campaign=rewrite 。
最后说一个实用技巧:项目导出为.carc归档时,AI 运行记录和助手会话也会一起打包。这意味着你可以回溯某一段正文是哪次 Agent 调用生成的、当时用了哪个 Skill、参考了哪部作品。对于长篇创作来说,这种可追溯性比「一键生成」有用得多。写崩了能回滚,写好了能复用,设定不会丢,大纲和正文始终绑在一起。这才是工作台该有的样子。