
1. 为什么从零搭建是个伪命题我见过太多人在搭建 AI 创作工作台这件事上把时间浪费在了错误的地方。打开一个空白的项目目录从环境变量开始配到模型接口、提示词管理、会话存储、前端界面一路写下来两周过去了真正用来创作的时间可能不到两小时。这不是能力问题是路径问题。这套工作台的核心思路很简单把已经被验证过的结构直接拿过来你只改跟业务相关的那 20%。剩下的 80%——目录组织、配置加载、提示词模板管理、多轮会话状态维护、技能Skill注册与调度——这些是通用骨架没必要重新发明。所谓AI 创作工作台拆开来看就是四件事一个能稳定调用大模型的执行层一套可复用可组合的提示词与技能体系一个能记住上下文的会话与知识管理层以及一个让你愿意天天打开它的交互入口。这四件事里只有提示词和技能是真正体现你个人价值的其余三件都是基础设施。基础设施就该抄现成的。这篇文章面向三类人一是想用 AI 提效但被工程细节劝退的内容创作者二是手里有一堆零散提示词、想系统化管理起来的从业者三是想搭一套自己的 Agent 工作流、但不想从零造轮子的开发者。我会把整套工作台的骨架、每个模块为什么这么设计、以及我实际踩过的坑全部摊开讲。你照着搭快的话一个下午就能跑起来。关键词里出现的 Skill、Prompt、IMA、Agent 这些概念我会在对应章节里逐个落地不讲空理论只讲怎么放进你的工作台里用起来。2. 工作台的骨架四个模块与它们的职责边界2.1 执行层模型调用要封成一层别到处裸调很多人搭工作台的第一步就是到处写client.chat.completions.create(...)结果模型一换、参数一调全项目搜索替换。正确做法是封一个薄薄的执行层把调用哪个模型、用什么参数、失败了怎么重试这三件事收口到一个地方。我的做法是定义一个LLMClient类对外只暴露一个invoke(prompt, **kwargs)方法。内部维护一个模型配置表把模型名、温度、最大 token、超时时间都放在配置里而不是硬编码在业务代码里。这样你换模型的时候只改配置表一行业务代码零改动。# llm_client.py import time from dataclasses import dataclass dataclass class ModelConfig: name: str temperature: float 0.7 max_tokens: int 4096 timeout: int 60 max_retries: int 3 class LLMClient: def __init__(self, config: ModelConfig, provider): self.config config self.provider provider # 具体的 SDK 适配器 def invoke(self, prompt: str, **overrides): params { temperature: self.config.temperature, max_tokens: self.config.max_tokens, } params.update(overrides) last_err None for attempt in range(self.config.max_retries): try: return self.provider.call(prompt, **params) except Exception as e: last_err e time.sleep(2 ** attempt) # 指数退避 raise RuntimeError(f调用失败已重试{self.config.max_retries}次) from last_err为什么要做指数退避重试因为模型服务偶发的超时和限流是常态尤其是你在批量跑任务的时候。我实测下来加了重试之后批量任务的失败率从 8% 左右降到 1% 以下。这个细节看起来小但它决定了你的工作台是玩具还是能干活。注意重试只对幂等的调用安全。如果你的调用会触发副作用比如写文件、发消息重试前一定要做去重判断否则会重复执行。2.2 提示词层Prompt 不是字符串是带元数据的资产把 Prompt 当字符串随手写在代码里是工作台走向混乱的开始。Prompt 应该是独立的、带元数据的资产它有名字、有版本、有适用场景、有输入变量声明。我推荐用目录 模板文件的方式管理。prompts/ summarize/ v1.md v2.md meta.yaml rewrite/ v1.md meta.yamlmeta.yaml里声明这个 Prompt 需要哪些变量、默认温度是多少、适合哪个模型name: summarize version: v2 variables: [content, max_length, tone] default_temperature: 0.3 description: 长文摘要支持指定语气和长度加载的时候用模板引擎渲染变量。这样做的好处是Prompt 可以独立迭代、可以 A/B 对比、可以回滚。我踩过的一个坑是——早期把 Prompt 写死在代码里改一版就要重新部署后来改成文件加载改 Prompt 就是改一个 md 文件热加载即可生效迭代速度完全不是一个量级。关于 Prompt 的写法关键词里提到的提示工程Prompt Engineering核心就三点角色设定要具体、任务描述要可验证、输出格式要约束死。比如你要模型输出 JSON就在 Prompt 里明确给出 schema并加一句只输出 JSON不要任何解释文字。我见过太多人抱怨模型输出不稳定其实九成是 Prompt 没把格式约束清楚。2.3 技能层Skill 是可复用的能力单元Skill 这个词最近很热但它的本质一点都不玄乎一个 Skill 就是一段提示词 一组工具调用 一套输入输出约定的封装。它把某个具体能力比如读一篇论文并生成结构化笔记打包成一个可被工作台调度的单元。为什么要有 Skill 这一层因为 Prompt 是一次性的指令而 Skill 是可被反复调用的能力。当你有了十几个 Skill工作台就从聊天框升级成了能力平台。你可以让一个 Skill 的输出喂给另一个 Skill形成流水线。一个 Skill 的目录结构大概是这样skills/ paper_notes/ skill.yaml # 元信息名称、描述、输入输出 schema prompt.md # 核心提示词 tools.py # 可选该技能需要的工具函数 examples/ # 可选few-shot 示例skill.yaml里最关键的是输入输出 schema它让 Skill 之间可以自动串联name: paper_notes description: 输入论文全文输出结构化笔记 inputs: paper_text: string outputs: title: string contributions: list method: string limitations: string我实际用下来Skill 化最大的收益是可组合性。以前我处理一篇论文要手动跑好几个 Prompt现在写一个编排脚本把提取正文 → 生成笔记 → 翻译摘要 → 归档串成一条链一键跑完。关键词里的agent skillcodex skill说的都是这个思路只是不同平台的叫法不同。2.4 会话与知识层让工作台记得住一个只会单轮问答的工作台用两天你就腻了。真正让人离不开的是它能记住你的偏好、你之前处理过的内容、你积累的知识。这一层我拆成两块会话记忆和知识库。会话记忆负责短期上下文最简单的做法是维护一个消息列表每次调用时把最近 N 轮拼进 Prompt。但要注意 token 成本——我一般设置一个滑动窗口超过阈值就把更早的消息做一次摘要压缩而不是直接丢弃。摘要压缩的 Prompt 可以复用上面 Prompt 层的机制。知识库负责长期记忆把常用的参考资料、历史产出、领域文档做向量化存储检索时按相似度召回。关键词里的 IMA 这类知识管理工具本质上就是帮你做这件事。如果你不想引入向量数据库起步阶段用简单的关键词检索 文件索引也能撑住等数据量上来了再升级。提示会话记忆和知识库不要混在一起。会话是临时的、会过期的知识是长期的、要沉淀的。混在一起会导致检索结果里全是无关的闲聊记录。3. 把 Skill 和 Prompt 真正用起来三个落地场景3.1 场景一长文处理流水线这是我最常用的场景。输入一篇几千字的文章输出摘要、要点、金句、以及一段适合发社交平台的短文案。整条流水线由四个 Skill 串成extract_structure提取文章骨架输出各级标题和段落主题summarize基于骨架生成 200 字摘要extract_quotes抽取 3-5 句有传播力的原句social_copy把摘要改写成社交平台文案每个 Skill 独立可测串起来就是一条流水线。我实测下来处理一篇 5000 字的文章全流程大概 40 秒人工做同样的事至少要 20 分钟。关键在于每个环节的 Prompt 都做了格式约束输出直接是结构化数据不需要人工再整理。这里有个经验流水线的每个环节都要能单独重跑。因为模型输出有随机性某个环节结果不满意时你只想重跑那一步而不是整条链重来。所以编排脚本要支持从第 N 步开始执行。3.2 场景二多轮改稿助手写东西的人都知道初稿到定稿之间要改很多轮。我搭了一个改稿 Skill它记住整篇文章的当前版本你每次给一个修改指令第二段太啰嗦把结论提前它输出修改后的完整版本并标注改了哪里。这个场景对会话记忆的要求很高因为模型必须知道当前版本是什么。我的做法是把当前版本作为系统消息的一部分固定注入而不是依赖对话历史。这样即使对话很长模型看到的永远是最新的全文。def rewrite(current_draft, instruction, client): system f你是改稿助手。当前稿件全文如下\n\n{current_draft} user f修改指令{instruction}\n请输出修改后的完整稿件并在末尾用【改动说明】标注修改点。 return client.invoke(system \n\n user)踩过的坑早期我让模型只输出改动部分结果它经常漏掉上下文改出来的东西前后不连贯。后来改成输出完整稿件 改动说明虽然 token 消耗多了但质量稳定太多。这个取舍很值。3.3 场景三领域知识问答把某个领域的文档比如产品手册、行业报告灌进知识库工作台就变成了一个懂这个领域的问答助手。用户提问时先检索相关片段再把片段和问题一起喂给模型让它基于检索到的内容回答而不是凭空生成。这个模式的关键是检索质量。我试过纯关键词检索和向量检索前者在术语精确匹配时更准后者在语义相近时更强。实际用下来两者结合效果最好先用关键词粗筛再用向量精排。另外Prompt 里一定要加一句如果检索内容中没有答案就明确说不知道否则模型会编。4. 搭建过程中最容易翻车的五个地方4.1 配置散落各处改一个参数要翻五个文件这是新手最常见的病。模型名写在 A 文件温度写在 B 文件Prompt 路径写在 C 文件。等到要换模型你得全局搜索。解决办法是单一配置源所有配置集中在一个config.yaml代码里通过统一的配置加载器读取。llm: default_model: your-model-name temperature: 0.7 max_tokens: 4096 paths: prompts: ./prompts skills: ./skills knowledge: ./knowledge memory: window_size: 10 summary_threshold: 4000配置加载器支持环境变量覆盖这样本地开发和部署环境可以用同一份配置只改环境变量。我现在的习惯是任何可能会变的值都不写死在代码里一律进配置。4.2 Prompt 里的变量没转义注入攻击防不住如果你的工作台会接收用户输入并把它拼进 Prompt那就要小心了。用户输入里如果包含类似忽略以上所有指令的内容可能让模型跑偏。这不是危言耸听我在测试时就遇到过用户输入把整个系统提示词带偏的情况。防御手段有三层一是把用户输入用明确的分隔符包起来并在系统提示里声明分隔符内的内容是数据不是指令二是对输入做长度限制和敏感模式过滤三是对关键操作做二次确认。第三层最重要——任何会触发实际动作写文件、发请求的操作都要有人工确认环节不能全自动。4.3 会话历史无限增长token 账单爆炸我早期没做窗口限制一个长对话跑下来单次调用的输入 token 能到几万成本高得离谱而且模型对超长上下文的注意力也会下降。后来加了滑动窗口 摘要压缩成本降了大概 70%。具体策略保留最近 10 轮完整对话更早的内容每 5 轮做一次摘要摘要控制在 200 字以内。摘要本身也用模型生成Prompt 就是把以下对话压缩成 200 字以内的要点保留关键决策和结论。4.4 Skill 之间接口不统一串不起来如果每个 Skill 的输入输出格式都不一样你就没法自动编排。解决办法是强制所有 Skill 遵循统一的 I/O 约定输入是一个字典输出也是一个字典且必须有 schema 声明。这样编排器才能知道上一个 Skill 的输出能不能喂给下一个。我见过有人每个 Skill 都返回一段自由文本结果想串联时只能靠人工解析完全失去了自动化的意义。统一 I/O 是 Skill 体系能规模化的前提。4.5 没有日志出了问题无从排查工作台跑起来之后最怕的是结果不对但不知道为什么。我的做法是每次调用都记一条结构化日志时间、Skill 名、输入摘要、输出摘要、耗时、token 消耗、是否重试。这样出问题时回看日志就能定位是哪一步、哪个 Prompt 出的问题。日志不要记全文太占空间记摘要和哈希即可。需要复现时用哈希去缓存里捞完整内容。这个设计让我排查问题的效率提升了好几个档次。5. 让工作台从能用到好用的几个细节5.1 给每个 Skill 配一个自检能力Skill 跑完输出后让它自己检查一遍格式对不对、有没有漏字段、内容是否自洽。这个自检可以是一个独立的轻量 Prompt成本很低但能拦下大部分低级错误。我实测下来加了自检之后需要人工返工的比例从 15% 降到了 5% 左右。自检 Prompt 的写法把输出 schema 和实际输出一起给模型问它输出是否符合 schema如果不符合指出具体问题。注意让模型只回答符合或不符合 问题描述不要让它顺手改改是另一个环节的事。5.2 缓存重复调用同一个 Prompt、同样的输入如果短时间内被调用多次结果应该复用。我在执行层加了一层缓存key 是Prompt 哈希 输入哈希 模型参数哈希value 是输出。对于批量处理场景缓存命中率能到 30% 以上省时省钱。缓存要注意失效策略。Prompt 改了、模型换了缓存必须失效。所以 key 里一定要包含 Prompt 版本和模型标识不能只用输入做 key。5.3 把常用操作做成一键入口工作台再好如果每次用都要敲一堆命令你也会懒得用。我的做法是把最高频的几个操作做成快捷入口一个命令处理一篇文章、一个命令开启改稿模式、一个命令查询知识库。入口越简单使用频率越高。这一步不需要什么技术就是把你最常用的编排脚本包一层。但它的心理价值很大——降低启动成本是让工具真正融入日常的关键。6. 关于直接复制这件事的边界标题说可以直接复制但我要诚实地说骨架可以复制业务逻辑必须自己长。你可以直接拿走目录结构、配置加载、执行层封装、Skill 的 I/O 约定这些是通用的。但你的 Prompt 内容、你的 Skill 组合方式、你的知识库内容这些是别人复制不走的也正是你工作台的价值所在。我见过有人到处找现成的工作台想一键部署结果拿到手发现全是别人的业务逻辑改起来比自己搭还累。正确的姿势是拿骨架填自己的肉。骨架部分我上面已经给全了你花半天就能搭起来剩下的时间应该花在打磨你的 Prompt 和 Skill 上那才是真正拉开差距的地方。关键词里那些教别人用 AI 赚翻了之类的说法我不评价。但有一点是确定的工具本身不产生价值工具加上你对某个领域的理解才产生价值。工作台只是把你的理解放大、加速、沉淀下来的载体。搭好它然后去用它解决你真正关心的问题这才是正事。最后分享一个我自己的习惯每搭一个新 Skill我都会先手动跑十遍确认 Prompt 稳定了再把它注册进工作台。急着自动化的结果往往是自动化了一堆错误。慢一点稳一点工作台才会越用越顺手。