切换前后
以下是典型的 OpenAI Python 客户端示例:
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
r = client.chat.completions.create(
model="your-current-model",
messages=[{"role": "user", "content": "Draft a tense dialogue between two rivals."}],
)
指向无审查替代方案的相同客户端:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.chatgptunfiltered.com/v1",
api_key=os.environ["UNFILTERED_API_KEY"],
)
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Draft a tense dialogue between two rivals."}],
)
构造函数中修改了两行,调用中的模型字符串也发生了更改。消息格式、响应对象以及你读取 r.choices[0].message.content 的方式保持不变。替代方案是由独立提供商运行的不同模型。它不是 ChatGPT,也不是来自 OpenAI 或其他任何人的官方 API。
仅使用环境变量进行切换
官方 Python 和 Node SDK 的最新版本在创建不带参数的客户端时,会读取 OPENAI_BASE_URL 和 OPENAI_API_KEY。这意味着应用代码可以保持不变:
export OPENAI_BASE_URL="https://api.chatgptunfiltered.com/v1"
export OPENAI_API_KEY="YOUR_KEY"
python app.py
你仍需确保代码传递了 model="uncensored"。如果模型名称在多处被硬编码,请先将其提取到一个配置值中。这个小型重构使得未来任何方向的切换成本同样低廉。
Node 中同样适用此方法:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.chatgptunfiltered.com/v1",
apiKey: process.env.UNFILTERED_API_KEY,
});
const r = await client.chat.completions.create({
model: "uncensored",
messages: [{ role: "user", content: "Give me five villain names." }],
});
console.log(r.choices[0].message.content);框架和 Responses 格式
封装 OpenAI 客户端的库通常会暴露 Base URL 设置。在 LangChain 的 OpenAI 聊天包装器中,它看起来像这样:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.chatgptunfiltered.com/v1",
api_key="YOUR_KEY",
)
print(llm.invoke("Name three moods for a chase scene.").content)
如果你使用较新的 Responses 格式,POST /v1/responses 和 POST /v1/chat/completions 都受支持。GET /v1/models 列出了该模型,这是检查你的密钥和 URL 是否正确的一种快速方法。
预期差异
| 区域 | 你会注意到的差异 |
|---|---|
| 回答意愿 | 针对合法成人用途,它不会拒绝内容。带过滤的模型会拒绝的提示词通常也会得到回答。 |
| 措辞和风格 | 不同的模型,不同的风格。语气、长度和格式习惯将与你之前的模型不匹配。 |
| 模型选择 | 一个模型,ID 为 uncensored。无需选择层级。 |
| 范围 | 仅支持文本:不支持图像、音频或视频生成,不支持嵌入,不支持微调。 |
| 上下文 | 100,000 token,包括提示词和补全。max_tokens 是可选的。 |
| 限制 | 完整密钥:8 个并发请求,每分钟 300 次。试用密钥:2 个并发请求,每分钟 60 次。请求体最大 8 MB。 |
| 错误 | HTTP 429 且代码为 rate_limited 或 concurrency;临时过载返回 429 并带有 Retry-After: 5。 |
支持流式输出、函数调用和 JSON 模式,也支持 temperature、top_p、stop、seed 和惩罚参数。响应头包括 X-Request-Id、X-Balance-USD、X-RateLimit-Limit-Requests 和 X-RateLimit-Limit-Concurrency。文档 包含详细信息。
还有两个差异值得注意。首先,不同的模型计算 token 的方式可能不同,因此相同文本的计数可能与旧提供商报告的不同;请使用响应中的使用量数据,而不是你自己的估算。其次,依赖于厂商托管工具的功能(如内置网页搜索或厂商端的文件存储)不是此服务的一部分。函数调用是指:你定义函数,你的代码执行它们。
针对你自己提示词的对比脚本
与其目测少量输出,不如在循环中将你的提示词集通过新接口运行,并保存所有需要审查的内容。
import csv, json
with open("prompts.json", encoding="utf-8") as f:
prompts = json.load(f) # a list of strings
with open("results.csv", "w", newline="", encoding="utf-8") as out:
w = csv.writer(out)
w.writerow(["prompt", "reply", "in_tokens", "out_tokens"])
for p in prompts:
r = client.chat.completions.create(
model="uncensored",
temperature=0.7,
messages=[{"role": "user", "content": p}],
)
w.writerow([p, r.choices[0].message.content, r.usage.prompt_tokens, r.usage.completion_tokens])
打开 CSV 文件,逐列审查。Token 列为你提供相同流量的成本预测:将总和乘以每 1M token $0.15 和 $0.50。试用密钥允许每分钟 60 次请求和同时 2 个请求,因此如果保持循环顺序,几百个提示词集将在几分钟内完成。
简短的迁移清单
- 获取密钥。 在 API 密钥页面,使用 Google 或邮箱注册并领取 $0.50 免费试用额度。有效期 7 天,无需绑定银行卡。
- 将模型名称和 URL 放入配置。 一个地方,从环境变量读取。
- 重新运行你的测试提示词。 使用 20 到 50 个真实示例,包括之前被模型拒绝的示例,并查看结果。
- 调整系统提示词。 删除仅用于说服被过滤模型回答的文本。保留描述角色、受众和格式的内容。
- 添加 429 处理程序。 等待 5 秒并重试。将并发限制设置为与你的密钥限额匹配。
- 查看使用情况。 在实际流量运行时,通过响应中的
X-Balance-USD监控余额。
一个涵盖步骤 5 的重试辅助函数:
import time
from openai import RateLimitError
def create_with_retry(**kwargs):
for _ in range(4):
try:
return client.chat.completions.create(**kwargs)
except RateLimitError:
time.sleep(5)
raise RuntimeError("rate limited after 4 tries")
保留旧模型的已保存输出几周。如果用户在切换后抱怨某些内容感觉不对劲,你可以将其与旧模型会产生的输出进行比较,并查看差异是来自提示词、模型还是输入。
无风险推出
不要一次性切换所有模型。将提供商选择放在配置后面,以便你可以移动一定比例的流量并在几秒钟内回滚。
import os, random
from openai import OpenAI
old = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
new = OpenAI(base_url="https://api.chatgptunfiltered.com/v1", api_key=os.environ["UNFILTERED_API_KEY"])
SHARE = float(os.environ.get("NEW_SHARE", "0.05"))
def pick():
if random.random() < SHARE:
return new, "uncensored"
return old, os.environ["OLD_MODEL"]
从 5% 开始,观察几天的错误率、429 计数和用户反馈,然后增加。将 NEW_SHARE 设置为 0 以回滚。按用户或功能进行选择比按请求进行选择更好,因为在对话必须保持在同一模型上时,中途切换模型会改变语气。
成本是多少,何时保持现状
价格为每 1M 输入 token $0.15,每 1M 输出 token $0.50,从预付额度中扣除。一次请求输入 1,500 个 token,输出 400 个,成本为 1,500 x $0.15 / 1M = $0.000225,加上 400 x $0.50 / 1M = $0.0002,总计 $0.000425,或每 1,000 次请求 $0.425。对于其他供应商,请查看其当前定价页面;费率会变化,凭记忆进行的比较很快就会过时。充值为整额,从 $20 到 $500,以加密货币支付,从 $50 起有奖金。详情见 定价。
如果你需要图像或嵌入功能,如果你的受众需要严格的内容审核,或者如果特定供应商的模型是硬性要求,那么继续使用你当前的供应商是正确的选择。要了解此类模型的背景,请阅读 了解无审查 ChatGPT 模型。硬性限制永不改变:禁止涉及未成年人的性内容。
同时运行两个提供商也是可以的。许多团队将普通请求路由到一个模型,而将频繁被拒绝的请求路由到另一个模型。由于两者都使用相同的格式,这种路由只需几行代码和一个何时使用哪个模型的规则。
