news 2026/9/18 12:46:16

跑开源 Skill 洗 AI 味,TaoToken 发 Key 到 Base URL

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跑开源 Skill 洗 AI 味,TaoToken 发 Key 到 Base URL

1. 从一个每天要跑几百次的脚本说起

把一篇稿子里的机器腔删干净,最费时间的从来不是写,而是逐句检查:有没有"首先/其次/最后"的三段式,有没有"在当今这个快速发展的时代"这种开场,有没有硬凑的排比和破折号,有没有把一句话拆成三行来装节奏。42.2K Star 的那个开源 Skill 之所以火,就是因为它把这套判断标准固化下来了——一份禁用词表、一份句式模板库、一份自检清单,再加一段"改完再读一遍"的提示词。手动用一两次很爽,但要按天处理几十上百篇稿子,就必须把它塞进自动化脚本里。

我最初的版本很粗糙:把 Skill 里的提示词硬编码在 Python 文件里,密钥写在.env里直接用官方地址。跑了两天,问题集中暴露:批量并发一上来就限流,单条超时后整个批次卡住,模型偶尔换了输出格式导致后面的解析全崩,最要命的是换台机器就得重新配一遍。后来我把模型出口统一收拢到 TaoToken:到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=skill_intro 取一个 Key,Base URL 固定成https://taotoken.net/api,脚本里只读环境变量,不落地任何明文凭证。这篇文章就把这套链路从头到尾拆开,包括可复现的命令、调用日志怎么记、以及批量去 AI 味的结果怎么验。

需要先说明一点:下面所有命令和请求都由你在本地终端执行,我不建议把这类批处理脚本挂到任何直连内部系统的 Agent 上去跑,文本改写这种活儿只需要一个稳定的模型出口就够了。

2. 先把 Key 和 Base URL 落到环境变量

不管后面用 Python 脚本、Claude Code 还是 Codex,第一步都一样:让凭证只存在于环境变量里。脚本里出现sk-开头的字符串,迟早会被提交到仓库里。

到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=apikey_env 拿到 Key 之后,本地这么写:

# ~/.taotoken_env.sh —— 只在本机 source,不要提交到仓库 export TAOTOKEN_BASE_URL="https://taotoken.net/api" export TAOTOKEN_API_KEY="YOUR_API_KEY" export TAOTOKEN_MODEL="YOU_MODEL_ID" # 模型 ID 以控制台模型列表为准 # 用法:source ~/.taotoken_env.sh

先把连通性跑通,再写业务逻辑。用 curl 打一发最小请求,确认路径拼接、鉴权和模型名三件事都没有问题:

# 最小连通性测试:只发一条消息,确认 200 与返回结构 curl -sS -w '\nHTTP_STATUS:%{http_code}\n' \ "$TAOTOKEN_BASE_URL/v1/chat/completions" \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"model\": \"$TAOTOKEN_MODEL\", \"messages\": [ {\"role\": \"system\", \"content\": \"你是一名中文编辑,只做去机器腔改写。\"}, {\"role\": \"user\", \"content\": \"在当今这个快速发展的时代,我们首先要做的是明确目标,其次要拆解路径,最后要落地执行。\"} ], \"temperature\": 0.3 }"

跑通之后你大概率会看到两个现象,这也是后面脚本必须处理的:

第一,HTTP_STATUS是 200,但返回体里的choices[0].message.content可能带着模型自己的解释,比如"以下是改写结果:"。去 AI 味的输出要求"只给正文",就得在提示词里把这条约束写死,并且在脚本里做一次前缀剥离。

第二,temperature别开太高。去 AI 味本质上是"收敛"任务,不是创作任务。0.2 到 0.4 之间比较稳,再高就会出现为了"不像 AI"而故意写错别字、故意断句的过度表演。

3. 把 Skill 的提示词固化成可重跑的批处理脚本

Skill 的价值在于规则,工程化的价值在于规则可以被版本化、被复用、被验证。我把它拆成三个文件:rules/system.txt放角色与硬约束,rules/banned.txt放禁用词表,rules/checklist.txt放自检清单。脚本每次运行都重新读,改规则不需要改代码。

# rules/system.txt(节选,按你自己的 Skill 规则改写) 你是中文文本编辑,任务是把机器腔文本改写成自然的人类表达。 硬约束: 1. 只输出改写后的正文,不要任何前言、解释、总结、markdown 标题。 2. 保留原文事实、数字、专有名词,不得新增或删除信息点。 3. 禁止使用以下句式:首先/其次/最后、总的来说、综上所述、值得注意的是、在当今这个快速发展的时代。 4. 禁止三段式排比凑字数;句子长度要有明显长短交错。 5. 不使用破折号制造停顿感,不用"不是……而是……"的模板句。 6. 如果原文本身就是自然表达,原样返回,不要为了改而改。
# batch_deai.py —— 批处理入口,逐条调用 + 重试 + 落日志 import json import os import pathlib import random import time import urllib.error import urllib.request BASE_URL = os.environ["TAOTOKEN_BASE_URL"].rstrip("/") API_KEY = os.environ["TAOTOKEN_API_KEY"] MODEL = os.environ["TAOTOKEN_MODEL"] IN_DIR = pathlib.Path("inbox") OUT_DIR = pathlib.Path("outbox") LOG_PATH = pathlib.Path("logs/deai.jsonl") OUT_DIR.mkdir(exist_ok=True) LOG_PATH.parent.mkdir(parents=True, exist_ok=True) RULES = pathlib.Path("rules/system.txt").read_text(encoding="utf-8") BANNED = [w.strip() for w in pathlib.Path("rules/banned.txt").read_text( encoding="utf-8").splitlines() if w.strip()] def call_model(text: str, timeout: int = 90) -> dict: payload = { "model": MODEL, "temperature": 0.3, "messages": [ {"role": "system", "content": RULES}, {"role": "user", "content": text}, ], } req = urllib.request.Request( f"{BASE_URL}/v1/chat/completions", data=json.dumps(payload, ensure_ascii=False).encode("utf-8"), headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, method="POST", ) with urllib.request.urlopen(req, timeout=timeout) as resp: return json.loads(resp.read().decode("utf-8")) def strip_preamble(s: str) -> str: """模型偶尔会带一句前言,这里做最小化剥离""" for prefix in ("以下是改写结果:", "改写后:", "输出:"): if s.startswith(prefix): return s[len(prefix):].lstrip() return s.strip() def deai_one(path: pathlib.Path) -> dict: raw = path.read_text(encoding="utf-8").strip() started = time.time() last_err = None for attempt in range(4): try: body = call_model(raw) content = strip_preamble(body["choices"][0]["message"]["content"]) usage = body.get("usage", {}) return { "file": path.name, "status": "ok", "attempt": attempt + 1, "latency_ms": int((time.time() - started) * 1000), "tokens": usage, "hits": [w for w in BANNED if w in content], "out_len": len(content), "content": content, } except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e: last_err = repr(e) # 指数退避 + 抖动,避免整批同时重试把并发顶穿 time.sleep(min(2 ** attempt, 8) + random.random()) return {"file": path.name, "status": "failed", "error": last_err} def main() -> None: files = sorted(p for p in IN_DIR.iterdir() if p.suffix in (".txt", ".md")) with LOG_PATH.open("a", encoding="utf-8") as logf: for path in files: result = deai_one(path) if result["status"] == "ok": (OUT_DIR / path.name).write_text(result["content"], encoding="utf-8") logf.write(json.dumps(result, ensure_ascii=False) + "\n") logf.flush() # 边跑边落盘,中断也不丢日志 print(result["file"], result["status"], result.get("latency_ms", "-")) if __name__ == "__main__": main()

几个刻意的设计,跑过批量任务的人应该会有共鸣:

日志用 JSONL 追加写并flush(),中途 Ctrl+C 也不会丢已完成的记录,重跑时可以按文件名去重;重试带抖动的指数退避,比固定间隔重试的存活率高很多;hits字段直接记录改写结果里还残留了几个禁用词,这就是后面验收的依据。

4. Claude Code 侧配置:settings.json 与 ANTHROPIC_*

如果你习惯在 Claude Code 里先手工调规则、确认提示词稳定了再丢给批处理脚本,那就把模型出口也指到同一条链路上。改~/.claude/settings.json

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "YOU_MODEL_ID" } }

这里的变量名是 Claude Code 认的ANTHROPIC_*三件套,不要把它抄到 Codex 的配置里去——两者读的键完全不同,混用只会得到 401 或者"模型不存在"。配置来源和可用模型可以在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=client_config 对照着看,两边保持一致,脚本和交互式工具才能共用同一个 Key。

配完之后,建议在项目根目录放一个CLAUDE.md,把去 AI 味的规则写进去,这样交互式改写和脚本批处理用的是同一套约束:

# 文本改写约定 - 只输出正文,不输出前言、总结、markdown 标题 - 禁用:首先/其次/最后、综上所述、值得注意的是、在当今这个快速发展的时代 - 禁止三段式排比;句长必须长短交错 - 事实、数字、专有名词一律保留

5. Codex 与 CC Switch:config.toml 和三件套切换

Codex 走的是~/.codex/config.toml,键名和 Claude Code 完全不一样:

# ~/.codex/config.toml model = "YOU_MODEL_ID" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api/v1" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"

注意env_key写的是环境变量的名字,不是 Key 本身。先source ~/.taotoken_env.sh,再启动 Codex,它就会自己去读TAOTOKEN_API_KEY。如果你在这份文件里塞了ANTHROPIC_AUTH_TOKEN,Codex 不会报"配置错误",它会安静地用一个空的凭证去请求,然后给你一个看不懂的鉴权失败——这类问题排查起来最浪费时间。

同机同时装着 Claude Code 和 Codex 的话,用 CC Switch 管理切换最省事。它的核心就是"三件套":Base URL、API Key、默认模型。我一般建两个 profile:

profile: taotoken-claude base_url : https://taotoken.net/api api_key : YOUR_API_KEY model : YOU_MODEL_ID profile: taotoken-codex base_url : https://taotoken.net/api/v1 api_key : YOUR_API_KEY model : YOU_MODEL_ID

同一个 Key、同一个出口,两个 profile 的差别只在 Base URL 的路径尾部和写入的目标配置文件。这样切工具不会把配置文件互相覆盖,也不会出现"A 工具能用、B 工具 401"的鬼故事。

6. 用日志和指标证明"去 AI 味"真的生效了

改写类任务最容易自欺欺人的地方在于:读起来顺了,就以为成了。批处理跑完几百篇,你需要几个能算出来的数字。

下面这个小脚本读logs/deai.jsonl,输出一份验收报告:

# verify.py —— 从日志里算出去 AI 味效果指标 import json import pathlib import statistics rows = [json.loads(l) for l in pathlib.Path("logs/deai.jsonl").read_text( encoding="utf-8").splitlines() if l.strip()] ok = [r for r in rows if r.get("status") == "ok"] print(f"总数 {len(rows)},成功 {len(ok)},失败 {len(rows) - len(ok)}") if ok: lat = [r["latency_ms"] for r in ok] print(f"延迟 P50={statistics.median(lat):.0f}ms " f"P95={sorted(lat)[int(len(lat) * 0.95)]:.0f}ms") dirty = [r for r in ok if r["hits"]] print(f"改写后仍含禁用词的文件:{len(dirty)}") for r in dirty[:10]: print(" ", r["file"], r["hits"]) ratio = [len(r["content"]) / max(r["out_len"], 1) for r in ok] print(f"输出长度中位数:{statistics.median(r['out_len'] for r in ok):.0f} 字符")

验收标准我一般定三条:失败率低于 2%;改写后仍命中禁用词的文件数低于 5%;人工抽检 20 篇,事实和数字零丢失。三条里任何一条不达标,回去改rules/system.txt,而不是去调temperature——规则问题用参数是治不好的。

还有一件事值得单独做:把改写前后的文本做一次 diff 抽样,人工只看 diff 片段。全篇通读效率太低,只看改动位置,几分钟就能判断模型是在"改机器腔"还是在"重新创作"。

7. 排障清单:这几类报错基本都遇到过

把 Skill 接进脚本的过程里,报错来来回回就那么几类,按顺序排查能省很多时间。遇到拿不准的鉴权或路径问题,回 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=troubleshoot 核对 Key 状态和 Base URL 写法。

401 / 403:九成是环境变量没source,或者把 Key 写进了config.toml的值位置而不是env_key。先在同一个 shell 里echo ${TAOTOKEN_API_KEY:0:6}确认前缀存在,再启动工具。

404:路径拼接错了。Base URL 是https://taotoken.net/api,OpenAI 风格接口的完整路径是/v1/chat/completions;如果你在配置里已经写了/v1,代码里再拼一次就会变成/v1/v1/...。统一原则:Base URL 里不含/v1时由代码拼,含/v1时由客户端拼,二者只留一个。

429:并发开太高,或者单批文件太大。把并发降到 2 到 4,单条文本超过 4000 字就先切段再送。重试一定要带抖动,固定间隔的重试会在同一秒形成新的尖峰。

超时但服务端其实处理完了:改写任务重试是幂等的(同样的输入同样的规则,输出基本一致),所以超时直接重试没有副作用。但要在日志里把attempt记下来,重试率突然上升通常是网络或并发问题,不是模型问题。

返回内容被截断:输出长度上限没设够,或者输入太长导致模型把预算花在了前半段。批处理场景建议按段落切分,每段独立送,最后再拼回去,这样单条失败也不会毁掉整篇。

中文乱码:读写全部显式写encoding="utf-8",请求体用ensure_ascii=False编码。Windows 上默认编码不是 UTF-8,这一条踩过的人最多。

同一批文本两次结果差异很大:检查temperature和提示词是否完全一致。批处理脚本里凡是从外部读进来的规则文件,最好在日志里记一个内容哈希,出问题时能确认"规则真的没变"。

8. 把链路收拢成一条命令

工程化的终点是:换台机器,三条命令就能复现整套流程。

source ~/.taotoken_env.sh # 1. 注入 Base URL / Key / Model python batch_deai.py # 2. 批处理改写,日志落 logs/deai.jsonl python verify.py # 3. 出验收报告,看失败率与禁用词残留

规则改了怎么办?改rules/下的文本文件,重跑第二步。想换模型对比效果?改TAOTOKEN_MODEL,重跑,对比两份日志的延迟和禁用词命中率。整个过程不需要动代码,也不需要重新配置任何客户端。

回到最开始那个问题:42.2K Star 的开源 Skill 提供的是"怎么改"的规则,而批处理脚本要解决的是"稳定地改一万次"。两者的连接点其实很朴素——一个固定的 Base URL 和一个只存在于环境变量里的 Key,加上一份能追溯的调用日志。把这三样东西固定下来,去 AI 味这件事才从手工活变成了可复现的流水线。

接下来可以按这个顺序往下走:

  • 想先在网页里手工试几轮规则,看哪一种改写风格最贴合你的稿子,从模型对话入手:https://taotoken.net/models/detail/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat_skill
  • 如果你不只是跑批处理,还要在 Claude Code、Codex 里高频改写和调规则,可以看Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan_skill
  • 还没拿到 Key,或者想给脚本单独建一个便于轮换的 Key,直接去创建 Key:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=create_key_skill
  • Claude Code 的settings.jsonANTHROPIC_*变量写法,以官方文档为准,照着抄不会踩键名混用的坑:https://taotoken.net/doc/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude_code_doc

把 Key 拿到手之后,先跑第 2 节那条 curl,确认 200,再去写你的批处理循环。顺序反了的话,你会在 401 和 404 上浪费一整个下午。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 12:45:10

FP8加速Stable Diffusion 3.5:显存减半,吞吐量提升40%的实战指南

1. 为什么我盯上了FP8这个精度格式1.1 从一次显存告急说起Stable Diffusion 3.5发布那阵子,我第一时间就把权重拉下来跑了一圈。说实话,画质确实比SDXL上了一个台阶,尤其是多主体场景下的提示词跟随能力,还有画面里的文字渲染&…

作者头像 李华
网站建设 2026/9/18 12:43:50

拆解 system_prompts_leaks:系统提示词结构与提示词工程实践

系统提示词这东西,早几年是各家产品的"内部资产",普通开发者基本接触不到。直到有人把散落在各处、被公开披露过的 system prompts 整理成合集,也就是大家看到的这类 system_prompts_leaks 项目,情况才变了——它把一堆…

作者头像 李华
网站建设 2026/9/18 12:42:00

电话 AI 不冷场,qwen-audio-agent 的 LLM 请求指向 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 12:41:26

轻量级LSTM+Attention模型实现本地化学情诊断

简介:本资源是一份聚焦人工智能赋能教育实践的深度技术解析文档,面向教育技术研究者、一线教师及教育信息化从业者,系统解答AI如何提升教学设计效率与测评精准度两大核心问题。全文围绕教学设计自动化(AID)与教学自动测…

作者头像 李华
网站建设 2026/9/18 12:40:31

Credit_Auditor_Agent 要统一模型通道?TaoToken 这样填模型字段

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华