Menu

自洽性提示(Self-Consistency):多数投票

自洽性提示是把同一个推理问题问好几次,让每次运行各自推理,然后保留出现次数最多的答案。本文介绍它的原理、如何手动使用,以及如何用代码实现。

下面的每条提示词都可以编辑:改好后,在 ChatGPT、Claude 或其他 AI 应用中打开。

自洽性提示的意思是,把同一个推理问题问模型好几次,然后保留出现次数最多的答案。每次运行都会写出自己的推理过程,就像思维链提示那样;又因为模型在选词时带有一定的随机性,每次运行走的路径都不同。正确的路径往往会得出同一个答案,而错误则往往分散在各种不同的错误答案上。多数投票利用的正是这种差别。

这项技巧出自 Wang 等人 2022 年的论文《Self-Consistency Improves Chain of Thought Reasoning in Language Models》。论文比较了“采样多条推理路径再投票”和“只取一个贪心解码的答案”,发现投票提高了算术和常识推理基准测试上的准确率。

下面展示了同一个提示词的三次运行。每个标签页是一次运行及其回复。其中两次数对了,另一次犯了一个很容易犯的错误。

把 1 到 100 的所有整数都写出来,数字 7 一共出现多少次?一步一步想清楚,然后在最后一行以“Answer: N”的形式给出最终答案。
Try it
Example replyReplies vary between models and runs.

按数位来数 7。

  • 个位: 7、17、27、37、47、57、67、77、87、97。共 10 个 7。
  • 十位: 70 到 79。又是 10 个 7。
  • 百位: 只有 100 是三位数,而它不含 7。

77 在两组里都出现了,这是对的,因为它包含两个 7。

Answer: 20

第 2 次运行回答的其实是一个略有不同的问题:有多少个数含有 7,而不是数字 7 出现了多少次。它的推理读起来和另外两次一样有把握,单看它,你没有任何理由怀疑。三次运行的投票结果是 20、19、20,多数答案正是正确答案。

自洽性提示的原理

  1. 写一个带固定答案行的思维链提示词。 要求先写推理、最后给最终答案,并且答案采用一种你能找到的形式,比如“Answer: N”。没有固定的答案行,你就得读完每次运行的内容才能找到答案。
  2. 开启随机性,采样多次运行。 每次运行都需要有走不同路径的自由。在 API 中,把温度设为大于 0 就能做到。温度为 0 时,大多数运行会重复同样的推理,而把同一个错误重复五次并不能算作证据。
  3. 从每次运行中提取最终答案。 这一步忽略推理过程。两次运行通过不同的路线都得出 20,就算两票投给 20。
  4. 取最常见的答案。 计数之前先统一格式,让“20”“20.”和“二十”算作同一个答案。

答案的一致程度本身就是有用的信息。如果五次运行全部一致,随机失误的可能性就很小。如果投票分成三派,说明这个问题对模型来说很难,这时就该自己检查答案,或者改写提示词。论文还报告说,样本之间一致程度越高的问题,答对的可能性也越大。

手动使用自洽性提示

任何聊天应用都能用这个技巧。发送提示词,记下最后一行,然后再得到一次独立的运行:点击重新生成,或者把同一个提示词粘贴到新的对话里。重复这个过程,直到你得到三个或五个答案。

不要在同一个对话里用“你确定吗?”或“再试一次”来重新提问。模型能看到它上一次的回复,所以新的答案并不独立:它要么倾向于重复第一个答案,要么只因为你似乎有所怀疑就改掉答案。这两种都不算投票。

下面这个提示词已经为投票做好了准备。填入你自己的问题和答案格式,然后运行几次。

为投票准备好的提示词
Fill in
Parts
一家商店的笔 3 支一包,每包 2 元。小美买了 12 支笔,付了一张 10 元的纸币。她能找回多少钱?
一步一步想清楚。然后在最后一行单独给出最终答案,形式为“Answer: 以元为单位的金额”。
Try it
Example replyReplies vary between models and runs.

12 支笔是 12 ÷ 3 = 4 包。

4 包的价格是 4 × 2 元 = 8 元。

从 10 元中找零:10 元减 8 元 = 2 元。

Answer: 2 元

正是格式这一部分让投票成为可能。把它关掉,每次运行给出答案的措辞往往各不相同,而且常常夹在正文中间,一次简单的计数就变成了仔细的阅读。

用代码实现自洽性提示

在代码中,这个循环很短:把同一个提示词运行 N 次,取出答案行,然后计数。这个版本使用 OpenAI Python SDK;任何能设置温度的 API 都可以用同样的方式实现。

import re
from collections import Counter
from openai import OpenAI

client = OpenAI()
MODEL = "your-model-id"  # e.g. from your provider's model list

PROMPT = (
    "How many times does the digit 7 appear when you write out all the whole "
    "numbers from 1 to 100? Think it through step by step, then give the final "
    'answer on the last line in the form "Answer: N".'
)

def final_answer(text):
    # Also matches "**Answer: 20**", since chat models often bold the last line.
    lines = re.findall(r"^\**Answer:\**\s*(.+)$", text, re.MULTILINE)
    return lines[-1].strip(" *.") if lines else None

answers = []
for _ in range(5):
    response = client.chat.completions.create(
        model=MODEL,
        temperature=0.8,
        messages=[{"role": "user", "content": PROMPT}],
    )
    answers.append(final_answer(response.choices[0].message.content))

votes = Counter(a for a in answers if a is not None)
if votes:
    best, count = votes.most_common(1)[0]
    print(f"{best} ({count} of {len(answers)} runs agree)")
else:
    print("No run gave an answer line.")

这些运行彼此独立,所以在生产环境中,你会并行发送它们,而不是一个接一个地发。有些推理模型只接受默认温度,如果你设置了温度就会返回错误;对于这类模型,不要传 temperature。它们的运行结果仍然会有差异,因为默认设置本身就会采样。

什么时候用,以及代价是什么

当以下三点都成立时,自洽性就值得一用:答案简短且可比较(一个数字、一个标签、一个选项),答错的代价高于多调用几次的成本,并且模型在这个任务上还不够可靠。数学应用题、边界情况棘手的分类任务以及选择题都很合适。

它消耗的 token 大约是单个答案的 N 倍,而且如果模型每次运行都抱有同样的错误认识,它就帮不上忙。如果五次运行都犯了同一个错误,投票结果就会全票一致,而且是错的。投票减少的是随机失误,而不是系统性错误,所以它不能代替时不时地拿已知结果来核对答案。

会在回答之前先在内部推理的模型,每次运行本来就会详细地把问题想一遍,这往往会缩小投票带来的收益。但在它们的运行结果不一致的难题上,投票仍然可能有回报。

自洽性只对完成的答案投票。思维树提示更进一步,在解题过程中就比较不完整的推理,保留有希望的分支,并在弱的分支得出答案之前就把它们舍弃。

常见问题

自洽性提示是什么?

自洽性提示是 Wang 等人(2022)提出的一种技巧。你在开启采样的情况下把同一个思维链提示词发送好几次,让每次运行沿着不同的路径推理,然后取出现次数最多的最终答案。它用多条推理链之间的投票,取代了对单独一条推理链的信任。

自洽性提示应该采样多少次?

日常使用中,运行三到五次就足以在投票中压过偶尔的失误,而奇数次可以避免两个答案打成平手。原论文对每个问题采样了多得多的路径,发现样本越多,准确率越高,但每次的提升越来越小。答错代价高时就多运行几次,在乎成本或速度时就少运行几次。

自洽性和思维链有什么区别?

思维链是一次运行,模型在给出答案之前先写出推理过程。自洽性建立在思维链之上:它把思维链运行好几次,再对最终答案投票。思维链改变的是提示词;自洽性改变的是你收集多少个答案,以及怎样从中选出一个。

自洽性适用于文章或开放式回答吗?

不能直接用,因为投票需要能比较是否相同的答案:一个数字、一个标签、一个选择题选项或一个简短的事实。对于开放式文本,常见的变通办法是生成几个版本,再让模型判断哪个与其他版本最一致,但这是一种判断,而不是计数。

可以在 ChatGPT 或 Claude 里使用自洽性提示吗?

可以,手动操作即可。在几个新对话中分别发送这个提示词,或者把回复重新生成几次,记下每次运行的最终答案。要用新对话或重新生成按钮,而不是在同一个对话里再问一遍,因为能看到自己上一个答案的模型往往会重复它。

Coddy 编程语言插图

和 Coddy 一起学编程

开始