用 Python 与 GPT-4 Turbo 搭建自动化写作流:TaoToken 统一 API 配置实操
1. 内容团队批量产稿的真实卡点如果你在内容团队待过大概率见过这样的场景三个人一天憋出五篇稿选题会开两小时提纲改三版初稿写完还要润色最后排版发布。真正花在写上的时间可能不到三分之一剩下的全耗在流程切换和重复劳动上。我试过把这套流程拆开看发现它其实高度结构化选题、提纲、初稿、润色每一步的输入输出都能定义清楚。这意味着它天然适合用脚本串起来。Python 负责调度GPT-4 Turbo 负责生成中间用统一的 API 网关管理 Key 和模型路由整条流水线就能跑起来。这篇文章要解决的就是这件事用 Python 脚本调用 GPT-4 Turbo搭一条从选题到成稿的自动化写作流水线。适合谁内容团队的技术负责人、想给自己减负的独立创作者、以及需要批量产出技术文档或营销文案的工程同学。核心检索词就三个Python 自动化写作、GPT-4 Turbo API 调用、统一 Key 接入。先说清楚一个前提GPT-4 Turbo 的上下文窗口是 128K tokens能一次性吃下约 300 页英文或更长的中文文档。这个特性对写作流很关键——你可以在一次请求里塞进参考资料、历史风格样本、格式约束模型不用失忆。但代价是 token 消耗所以脚本里必须做截断和分块控制否则账单会教你做人。另一个前提是成本结构。GPT-4 Turbo 的输入和输出是分开计费的输出通常更贵。这意味着你的 Prompt 设计要尽量把约束前置减少模型自由发挥的空间尤其是技术文档这类要求事实准确的场景Temperature 压到 0.1 到 0.3别让它编。整条流水线的设计思路是每一步都是一个独立的函数输入是上一步的输出中间通过统一的 API 客户端调用模型。这样你既能单独调试某一步也能把整条链串起来批量跑。下面从环境准备开始一步步搭。2. TaoToken 统一 API 前置配置在写 Python 代码之前得先把 API 接入这层搞定。直接用各家厂商的原生 SDK 也能跑但内容团队通常不止用一个模型——选题可能用便宜的初稿用 GPT-4 Turbo润色可能换 Claude。如果每个模型都维护一套 Key 和 Base URL脚本会变得很难看。TaoToken 在这里的角色是统一入口一个 Key一个 Base URL通过 model 参数切换模型。对写作流水线来说这意味着你可以在 config.toml 里定义选题用哪个模型、初稿用哪个模型代码层不用改。先拿 Key。访问 API Keys 管理页https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 登录后创建一个新 Key复制保存。注意这个 Key 只在创建时完整显示一次丢了就得重建。拿到 Key 之后Base URL 统一用https://taotoken.net/api 。这个地址不加任何 UTM 参数直接写进配置。模型 ID 方面GPT-4 Turbo 对应的标识符你可以在模型对话页确认https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 页面上会列出当前可用的模型和对应的 ID 字符串。如果你用的是 Claude Code 这类工具做辅助开发接入文档在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有 Base URL、Key、Model ID 三件套的完整说明。Cline MCP 或 Codex 的 auth.json 配置也遵循同样的三件套逻辑后面排障章节会展开。环境变量建议这样设别把 Key 硬编码进脚本export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/apiWindows 下用set或 PowerShell 的$env:语法。设完之后echo $TAOTOKEN_API_KEY验证一下能读到。Python 依赖只需要两个openai官方库和tomliPython 3.11 以下读 TOML 用。安装pip install openai tomliPython 3.11 及以上自带tomllib不用额外装。版本确认一下python --version pip show openaiopenai 库建议 1.0 以上旧版 0.x 的调用方式和现在差别很大网上很多示例代码是旧版的直接抄会报错。这一点后面排障会细说。3. 可复制配置config.toml 与 settings.json 骨架配置层是整个流水线的地基。我习惯把模型参数、Prompt 模板、输出路径都抽到配置文件里代码只负责读配置和执行。这样换模型、调 Temperature、改字数限制都不用动 Python。先看config.toml骨架。这个文件放在项目根目录和脚本同级[api] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY timeout 120 max_retries 3 [models] topic gpt-4-turbo outline gpt-4-turbo draft gpt-4-turbo polish gpt-4-turbo [params.topic] temperature 0.8 max_tokens 500 [params.outline] temperature 0.5 max_tokens 1500 [params.draft] temperature 0.3 max_tokens 4000 [params.polish] temperature 0.2 max_tokens 4000 [output] dir ./output encoding utf-8这里的设计逻辑选题阶段需要发散Temperature 给到 0.8提纲需要结构清晰降到 0.5初稿要求事实准确0.3润色只改表达不改事实0.2。max_tokens 逐级放大因为初稿和润色要处理完整长文。再看settings.json。这个文件主要给需要 JSON 配置的工具链用比如 Cline MCP 或某些 IDE 插件。如果你只用 Python 脚本config.toml 就够了但如果团队里有人用编辑器插件辅助settings.json 能保证两边参数一致{ taotoken: { baseUrl: https://taotoken.net/api, apiKeyEnv: TAOTOKEN_API_KEY, defaultModel: gpt-4-turbo, models: { topic: gpt-4-turbo, outline: gpt-4-turbo, draft: gpt-4-turbo, polish: gpt-4-turbo }, timeout: 120, maxRetries: 3 }, output: { dir: ./output, encoding: utf-8 } }注意baseUrl和apiKeyEnv这两个字段任何工具接入都是这三件套Base URL、Key或 Key 的环境变量名、Model ID。Cline MCP 的配置里也是这三个只是字段名可能叫baseURL、apiKey、model。Codex 的auth.json同理结构不同但信息一致。Prompt 模板我单独放一个prompts.py不塞进配置文件因为模板里有大量中文和格式化字符串放 TOML 里转义很麻烦TOPIC_PROMPT 你是一位资深内容策划。 任务围绕主题「{seed}」生成 {count} 个差异化选题。 要求 1. 每个选题包含标题和一句话说明。 2. 标题不超过 25 字说明不超过 50 字。 3. 选题之间角度不重复。 输出格式编号列表每条一行标题下一行缩进写说明。 OUTLINE_PROMPT 你是一位技术专栏编辑。 选题{topic} 目标读者{audience} 任务为该选题生成一份三级提纲。 要求 1. 一级标题 4 到 6 个。 2. 每个一级标题下至少 2 个二级要点。 3. 提纲要覆盖背景、核心步骤、常见问题、总结。 输出格式Markdown 无序列表。 DRAFT_PROMPT 你是一位技术写作专家。 选题{topic} 提纲 {outline} 目标读者{audience} 约束 1. 字数控制在 {word_count} 字左右。 2. 至少包含一个可运行的代码示例。 3. 语气客观避免夸张形容词。 4. 段落之间用空行分隔。 输出纯 Markdown 正文不要加一级标题。 POLISH_PROMPT 你是一位资深文字编辑。 任务对以下初稿进行润色。 要求 1. 不改变事实和代码。 2. 修正语病和冗余表达。 3. 保持原有 Markdown 结构。 4. 只输出润色后的正文。 初稿 {draft} 这套模板的关键在于约束前置。模型对格式要求的遵循度和约束出现的顺序强相关。把字数、格式、禁用项写在任务描述之后、输出要求之前比写在最后效果好。配置和模板都就位后目录结构大概是这样writing-pipeline/ ├── config.toml ├── settings.json ├── prompts.py ├── pipeline.py └── output/output目录提前建好脚本不会自动创建。这一步别偷懒后面跑批量任务时路径不存在会直接抛异常。4. 端到端生成与验证请求配置齐了现在写主脚本pipeline.py。核心是一个统一的客户端初始化函数加四个步骤函数最后串成一条链。先看客户端初始化。这里用 openai 库但把 base_url 指向 TaoTokenimport os import json import tomllib from pathlib import Path from openai import OpenAI from prompts import TOPIC_PROMPT, OUTLINE_PROMPT, DRAFT_PROMPT, POLISH_PROMPT def load_config(pathconfig.toml): with open(path, rb) as f: return tomllib.load(f) def build_client(cfg): api_key os.environ.get(cfg[api][api_key_env]) if not api_key: raise RuntimeError(f环境变量 {cfg[api][api_key_env]} 未设置) return OpenAI( api_keyapi_key, base_urlcfg[api][base_url], timeoutcfg[api][timeout], max_retriescfg[api][max_retries], )base_url从配置读指向https://taotoken.net/api。max_retries设 3网络抖动时自动重试不用自己写循环。然后是通用的调用函数四个步骤共用def call_model(client, cfg, step, prompt): model cfg[models][step] params cfg[params][step] response client.chat.completions.create( modelmodel, messages[ {role: system, content: 你是一个严格遵循指令的写作助手。}, {role: user, content: prompt}, ], temperatureparams[temperature], max_tokensparams[max_tokens], ) return response.choices[0].message.content注意response.choices[0].message.content这个取值路径。openai 1.x 版本里 choices 是列表取第一个元素的 message.content。如果你看到报错说ChatCompletion object has no attribute choices或者reading choices八成是库版本不对或者返回结构变了排障章节细说。四个步骤函数def gen_topics(client, cfg, seed, count5): prompt TOPIC_PROMPT.format(seedseed, countcount) return call_model(client, cfg, topic, prompt) def gen_outline(client, cfg, topic, audience): prompt OUTLINE_PROMPT.format(topictopic, audienceaudience) return call_model(client, cfg, outline, prompt) def gen_draft(client, cfg, topic, outline, audience, word_count): prompt DRAFT_PROMPT.format( topictopic, outlineoutline, audienceaudience, word_countword_count ) return call_model(client, cfg, draft, prompt) def polish(client, cfg, draft): prompt POLISH_PROMPT.format(draftdraft) return call_model(client, cfg, polish, prompt)主流程串起来def run_pipeline(seed, audience, word_count): cfg load_config() client build_client(cfg) out_dir Path(cfg[output][dir]) out_dir.mkdir(exist_okTrue) topics gen_topics(client, cfg, seed) print( 选题 ) print(topics) first_topic topics.strip().split(\n)[0] outline gen_outline(client, cfg, first_topic, audience) print( 提纲 ) print(outline) draft gen_draft(client, cfg, first_topic, outline, audience, word_count) print( 初稿 ) print(draft[:200], ...) final polish(client, cfg, draft) out_file out_dir / article.md out_file.write_text(final, encodingcfg[output][encoding]) print(f 成稿已写入 {out_file} ) if __name__ __main__: run_pipeline( seedPython 自动化写作, audience内容团队技术负责人, word_count1500, )跑之前先做一次最小验证别直接上完整流水线。单独测一次 API 连通性from openai import OpenAI import os client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlhttps://taotoken.net/api, ) resp client.chat.completions.create( modelgpt-4-turbo, messages[{role: user, content: 回复两个字通了}], max_tokens10, ) print(resp.choices[0].message.content)如果这一步返回通了说明 Base URL、Key、Model ID 三件套都对。如果报 401是 Key 问题报 model not found是 Model ID 写错报连接超时检查网络和 base_url 拼写。验证通过后跑完整流程python pipeline.py正常输出会依次打印选题、提纲、初稿前 200 字最后提示成稿写入./output/article.md。打开文件检查一下润色后的正文应该是完整 Markdown没有多余的一级标题代码块保留。实测下来一次完整流程选题 5 个 提纲 1500 字初稿 润色大概消耗 6000 到 8000 tokens其中初稿和润色占大头。如果批量跑 50 篇token 量会到 30 万到 40 万成本要提前算。批量场景下把run_pipeline包一层循环每篇之间加time.sleep(2)避免请求过于密集。输出文件名用选题的哈希或序号区分别都叫article.md互相覆盖。5. 常见报错排查对照这一节按真实报错来。跑流水线时最容易撞上的就那么几个逐个拆。401 Unauthorized / invalid api key最常见。原因通常是环境变量没设、设了但没生效、或者 Key 复制时带了空格。先验证echo [$TAOTOKEN_API_KEY]方括号是为了看清首尾有没有空格。如果为空说明当前 shell 没读到检查是写进了.bashrc还是只在某个终端会话里 export 过。如果 Key 本身没问题但还是 401去 API Keys 页面确认这个 Key 没被删除或禁用。local proxy failed / connection error这个报错说明请求根本没发出去卡在本地网络层。检查base_url是不是写成了https://taotoken.net/api/末尾多斜杠有时会导致路径拼接异常或者环境里有残留的代理配置干扰。openai 库会读HTTP_PROXY和HTTPS_PROXY环境变量如果这两个变量指向一个不可用的地址就会报 local proxy failed。清掉unset HTTP_PROXY unset HTTPS_PROXY然后重跑验证脚本。Error reading choices / ChatCompletion object has no attribute choices这个报错指向库版本或返回结构。先确认 openai 版本pip show openai | grep Version如果是 0.x升级到 1.xpip install --upgrade openai升级后旧代码的openai.ChatCompletion.create要改成client.chat.completions.create这是 1.x 的破坏性变更。另外如果返回体里没有 choices可能是请求被网关拦截返回了错误 JSON打印完整 response 看看print(resp.model_dump())OAuth / authentication 相关报错如果你在用 Cline MCP 或 Codex 这类工具报 OAuth 错误通常不是 Key 的问题而是工具的认证流程没走完。这类工具接入 TaoToken 时配置里要写全三件套Base URL 填https://taotoken.net/apiKey 填你的 Key 或 Key 的环境变量名Model ID 填gpt-4-turbo。Codex 的auth.json结构大致是{ baseURL: https://taotoken.net/api, apiKey: sk-你的Key, model: gpt-4-turbo }字段名以工具文档为准但信息就这三样。少任何一个都会报认证失败。Cline MCP 的配置在设置面板里填同样是这三项。max_tokens 超限 / 输出被截断如果初稿写到一半断了检查max_tokens是不是设小了。GPT-4 Turbo 的输出上限和输入共享上下文窗口128K 是总量。如果你塞了大量参考资料进 Prompt留给输出的空间就少了。解决办法是把参考资料做摘要后再注入或者分块生成再拼接。Temperature 设了但输出还是很随机检查配置读取路径。cfg[params][step][temperature]如果 step 名字拼错会 KeyError 而不是静默失败。但如果你的代码用了.get()带默认值拼错就会悄悄用默认值。打印一下实际读到的参数print(cfg[params][draft])确认 temperature 和 max_tokens 是你设的值。中文乱码写文件时没指定 encoding。write_text默认用系统编码Windows 下可能是 GBK。显式传encodingutf-8config.toml 里的output.encoding就是干这个的。这几个报错覆盖了 90% 的初次接入问题。遇到没列出来的先打印完整异常堆栈和 response 对象大部分问题看堆栈就能定位。6. 把流水线接进团队工作流脚本能跑通只是第一步。真正让内容团队用起来还得解决几个工程问题。第一是并发控制。批量跑 50 篇时串行太慢全并发又容易触发限流。用concurrent.futures.ThreadPoolExecutor控制并发数在 3 到 5 之间每个任务内部做重试。openai 库的max_retries已经处理了单请求重试但并发层面的退避要自己加。第二是结果校验。模型输出不一定符合格式要求尤其是提纲和初稿。在写入文件前加一层校验提纲检查是否包含至少 4 个一级标题初稿检查字数是否在目标值的 80% 到 120% 之间。不达标的重跑该步骤最多重试 2 次。第三是人工介入点。自动化写作不是完全替代人而是把人从机械劳动里解放出来。我的做法是在初稿和润色之间留一个 review 环节脚本生成初稿后暂停人工确认事实和方向没问题再触发润色。这样既保证了效率又避免了模型幻觉直接进入成稿。第四是 Prompt 版本管理。prompts.py里的模板会随着使用不断调整建议用 git 管理每次改动记录原因。团队协作时Prompt 的变更和代码变更一样需要 review。如果你需要长期跑这套流水线或者想把它扩展成 Agent 形态比如自动抓取热点、自动配图、自动发布可以了解一下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 里面有面向长期编码和 Agent 场景的接入方案。最后说一个实际踩过的坑别把生产环境的 Key 写进脚本或提交到 git。用环境变量用.env文件加.gitignore或者用密钥管理服务。Key 泄露的代价比省下的那点配置时间大得多。整条流水线到这里就完整了。从 config.toml 定义参数到 Python 脚本调度再到端到端验证和排障每一步都能单独调试也能串起来批量跑。你可以先从单篇跑通开始确认输出质量符合预期后再逐步放大批量规模。