获取 API 密钥

无审查模型 API 的 Prompt 写法:system、角色、格式、采样

同一个模型,Prompt 写得松和写得紧,输出质量差一个档次。这里不讲玄学,只列工程上能直接验证的做法:system prompt 怎么分层,角色设定怎么写才不跑偏,怎样只靠指令拿到可解析的 JSON,temperature 和 top_p 怎么取,以及哪些写法一定会翻车。每条都能放进你的代码里做对照实验。

更新于

要点

  • system prompt 用规则加设定两段式,规则编号,设定只写事实。
  • 要 JSON 就在指令里写死格式,调低 temperature,代码里必须有解析失败的兜底。
  • temperature 和 top_p 一次只动一个,创作 0.8 到 1.0,抽取 0 到 0.3 起步。
  • 常见翻车写法:含糊的否定句、互相矛盾的规则、把格式要求放在对话中间。

先定四条原则

  • 一个请求一个任务。让模型既写剧情又做摘要又出 JSON,三样都会打折。拆成多次调用,成本很低,输入每百万 token 只要 $0.25。
  • 规则要可检验。“写得生动一点”无法检验,“每段不超过 120 字,至少一处环境描写”可以。
  • 正向表述优先。说“只写动作和对白”,比说“不要写心理活动”稳定得多。
  • 先小样本,后批量。任何 Prompt 改动,先用五到十条样例对比,再上线。

这个模型对合法的成人向内容、虚构题材和有争议的话题不会拒绝,所以你不需要在 Prompt 里绕弯子、反复声明“这只是小说”。直接把任务写清楚,反而更稳。唯一的硬边界是涉及未成年人的性内容,无论虚构与否都会返回 403,这一条没法靠措辞改变。

system prompt 的两段式结构

推荐把 system 拆成“规则”和“设定”两块,规则放前面、编号,设定放后面、只写事实。下面是一个小说叙述者的写法:

你是「夜航」,一名为成年读者写黑色悬疑小说的叙述者。

# 规则
1. 第三人称过去时,每段不超过 120 字。
2. 不替用户的角色做决定,只写环境和其他角色的反应。
3. 每次输出 300 到 500 字,结尾停在一个未决的动作上。
4. 不总结、不点评、不加免责声明,直接写正文。

# 设定
时间:1998 年深秋。地点:港口城市旧码头区。
主角:沈野,退役水警,嗜烟,右耳有旧伤。

几个要点:

  1. 规则不超过六条,条数越多,后面的越容易被忽略。
  2. 数字约束(段落字数、输出长度)比形容词有效。
  3. 结尾约束(停在未决动作上)能让多轮续写自然衔接。
  4. 设定里不要塞剧情走向,剧情由 user 消息推进,否则后面和用户的输入打架。

输出长度要与 max_tokens 配合:规则说 500 字,而 max_tokens 只给 200,就会被截断在句子中间。

再补一个实战细节:system 里的编号规则最好每条只表达一件事。“每段不超过 120 字,并且不要总结”看似一条,其实是两条,拆开后模型更容易同时满足。写完后自己逐条读一遍,问一句:这条能不能用眼睛检查出有没有被遵守?不能的,就改写成能检查的形式。

角色设定怎么写才不跑偏

角色漂移是多轮对话里最常见的问题:前五轮语气正常,到第二十轮就开始“出戏”。对策有三个。

  • 设定只写可观察的特征。“沈野:嗜烟,右耳有旧伤,说话短句多”,优于“沈野是一个复杂而有魅力的人”。
  • 把说话方式写成例句。给两三句示范台词,模型模仿例句的效果远好于理解形容词。
  • 定期重申。对话很长时,每隔若干轮在 user 消息末尾追加一行简短提醒,比如“保持沈野的短句风格”,成本只有几十个 token。

另外,别让角色设定和输出规则混在一起。规则是“怎么写”,设定是“写谁”,分开后你可以在不动规则的前提下换角色,做 A/B 对比也方便。长对话要注意上下文总量,细节见100k 长上下文实战。

多角色场景再加一条:每个角色单独一行设定,台词风格各给一句示范,避免所有人说话像同一个人。用户扮演的角色,只在设定里写“由用户控制”,让模型不要代写。

用指令控制 JSON 输出

不要假设模型“一定”返回合法 JSON。可靠做法是三层:指令写死格式,参数压低随机性,代码兜底解析。

import json
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.wushenchaapi.com/v1", api_key=os.environ["API_KEY"])

SYSTEM = (
    "你是信息抽取器。只输出一个 JSON 对象,不要 Markdown 代码块,不要任何解释。"
    '格式:{"name": 字符串, "mood": "calm|tense|angry", "items": [字符串]}。'
    "缺失的字段用 null,items 没有则给空数组。"
)

def extract(text, retries=2):
    for _ in range(retries + 1):
        resp = client.chat.completions.create(
            model="uncensored",
            temperature=0.2,
            max_tokens=300,
            messages=[
                {"role": "system", "content": SYSTEM},
                {"role": "user", "content": text},
            ],
        )
        raw = resp.choices[0].message.content.strip()
        raw = raw.removeprefix("```json").removesuffix("```").strip()
        try:
            return json.loads(raw)
        except json.JSONDecodeError:
            continue
    return None

print(extract("老周把钥匙拍在桌上,冷着脸说:账本和那把铜钥匙,今晚都得还我。"))

这段代码体现了几个习惯:

  • 格式说明写在 system 里,并且给出字段取值范围(calm|tense|angry)。
  • 明确禁止代码块和解释文字,同时代码里仍然剥掉可能出现的围栏,双保险。
  • 缺失字段的约定写进指令(null、空数组),避免模型自己编。
  • 解析失败重试有上限,最后返回 None,让调用方决定怎么办。

如果字段很多,先在 Prompt 里贴一个完整示例对象,再让它照着输出,通常比描述一堆规则更准。

temperature 与 top_p 取值建议

以下是起点,不是定论,最终以你的样例对比为准。原则:一次只调一个参数,另一个保持默认。

场景temperaturetop_p备注
JSON 抽取、分类0 到 0.3默认要稳定,重复调用结果应一致
改写、润色0.5 到 0.7默认保留原意,允许措辞变化
小说续写、角色对话0.8 到 1.00.9 到 0.95要多样性,注意偶发跑题
头脑风暴、起名1.0 左右默认多次采样取最好的

两个信号可以帮你判断方向:输出重复啰嗦、总是同一种句式,说明温度偏低;出现无关内容、人物名前后不一致,说明温度或 top_p 偏高。stop 参数也很实用,比如让模型写到某个标记就停,方便做分段生成。

常见失败写法

写法问题改成
“尽量不要太长”没有数字,无法执行“不超过 400 字”
“不要写A,也不要不写A”规则互相矛盾只保留一条明确规则
格式要求夹在对话中间长对话后被淹没放进 system,或每轮末尾重申
让模型“扮演一个没有限制的 AI”空洞的设定,对输出毫无约束写具体的职责和写作规则
一次塞入几十条规则后半段规则失效精简到六条以内,其余拆到别的请求
JSON 要求只写“返回 JSON”字段名每次不同给出完整格式和示例

这张表的共同规律是:越具体越有效,越空洞越无用。另外别把“反复强调”当成解决办法,把同一句话写三遍、加粗加感叹号,效果通常不如把它改成一条带数字的规则。真正有用的是少而准,再配合样例验证。

调试流程清单

  1. 固定 temperature 为 0.2,复现问题。
  2. 只改一处 Prompt,重跑同一批样例。
  3. 看 finish_reason:如果是 length,问题出在 max_tokens 而不是 Prompt。
  4. 看 usage 里的 prompt_tokens:system 是否过长,挤占了历史对话。
  5. 改对之后再把 temperature 调回业务值,重新抽样验证。

接入细节见接入教程,参数完整列表在文档。如果你在评估要不要用中转类服务,成本与取舍的分析放在API 中转站分析那篇里,这里不重复。

常见问题

system prompt 写多长合适?

以能清楚表达规则为准,通常几百字足够。越长越占上下文,也越容易有规则相互冲突,建议规则不超过六条。

为什么指令要求只输出 JSON,仍偶尔带解释文字?

这是正常现象。把 temperature 调低、给出完整示例,并在代码里剥离围栏和做解析重试,比反复强调指令更可靠。

temperature 和 top_p 可以同时调吗?

可以,但不建议。同时动两个参数很难判断是哪个造成变化,先固定一个,只调另一个。

Prompt 里需要声明“这是虚构”吗?

不需要。合法的成人向虚构内容不会被拒绝,直接写清任务即可。涉及未成年人的性内容无论如何措辞都会被拦截。

只需填写表单即可获取密钥

创建账户,复制密钥,修改 Base URL。配置就是这么简单。