跳到主要内容

合议模型

合议模型让调用方只使用一个模型别名,由 AISIX 请求多个合议成员生成候选响应,再请求评审模型合成最终答案。调用方发送一个请求,并在所请求的别名下收到一个答案。分发与合成都在网关内部完成。

在 AISIX 中,合议模型是一种模型别名,AISIX 通过调用多个直连模型来解析它,与路由组和语义路由器类似。它不直接指向某个上游模型,而是通过 ensemble 配置告诉 AISIX:调用哪些直连模型作为合议成员,以及用哪个直连模型作为评审模型。

合议模型包含两部分:

  • 合议成员并发调用,各自生成独立的候选响应。
  • 评审模型接收成功的合议成员响应,合成返回给调用方的单一响应。

合议成员和评审模型都必须引用已存在的直连模型别名。服务提供方凭证、服务提供方模型名称、健康行为、冷却行为以及模型级限流,都在这些直连模型上配置。

适用场景与取舍

合议模型用额外的模型调用换取更强的答案合成能力。当答案质量或一致性比极致的延迟、成本更重要时,它最为有用。

当单个模型的答案本身不够可靠时,可以使用合议模型:

  • 降低单模型的波动和盲区。相互印证的独立答案更可能正确,评审模型会化解矛盾、舍弃缺乏依据的说法。
  • 对高难度的推理或研究类提示词做交叉验证。不同模型可能沿不同路径得出答案,另一个候选响应往往能暴露其中的错误。
  • 单一服务提供方下的自合议。合议成员可以是同一个直连模型的多次重复,各次使用不同的 temperatureseed,这样只有一个服务提供方密钥的团队,无需引入新厂商也能获得答案多样性。

合议模型会向每个合议成员各发一个请求,再调用评审模型,因此并不适合所有场景。以下情况请改用其他模型类型:

  • 对延迟敏感、以流式优先的链路。首个 Token 到达时间天然偏高,原因见流式与调用方响应一节。
  • 使用工具或函数调用的请求。这类请求不受支持,受支持的请求形态见安全护栏与请求约束
  • 高流量、对成本敏感的流量,此时质量提升不足以抵消额外开销。
  • Chat Completions 以外的端点。合议模型仅支持聊天。

这些情况请改用直连模型或多目标模型。多目标模型每次请求只选一个目标,而合议模型会调用全部合议成员,并综合它们的输出。

请求流程

合议请求从一个模型别名进入。AISIX 把请求并发分发给配置的合议成员,将成功的成员响应交给评审模型,最终只返回评审模型合成的答案。

对于每个聊天请求,AISIX 会执行以下阶段:

  1. 分发给合议成员。AISIX 把提示词并发分发给每个合议成员,并套用各成员各自的 temperatureseed 覆盖值。
  2. 收集成功响应。AISIX 保留成功的答案;一旦成功的成员数量满足 min_responses,即进入下一步,否则请求按失败处理中的行为处理。
  3. 合成最终答案。AISIX 用原始请求和已收集的答案构造合成提示词,再以固定的低 temperature 调用评审模型。评审模型的输出在合议模型别名下返回给调用方。

只要仍满足 min_responses,个别缓慢或失败的合议成员不会导致整个请求失败。评审模型调用在遇到瞬时故障(超时、传输错误或上游 5xx)时会重试一次。

成本与延迟

合议模型的成本更高,通常也比直连模型或多目标模型更慢,因为每个请求可能触发多次上游调用。

成本是各子调用之和:

ensemble cost ≈ sum(panel member costs) + judge cost

三个合议成员加一个评审模型,会把提示词处理四次,评审模型还要额外处理所有成员答案。面向调用方的 usage 反映的正是这一真实成本,见用量核算

延迟主要由最慢的合议成员加上评审模型决定:

ensemble latency ≈ max(panel member latency) + judge latency

由于评审模型必须等合议成员返回后才能开始,首个 Token 到达时间天然偏高——在合成开始前没有任何 Token 可供流式输出。

提示

保持合议成员数量较少(两到四个),选一个响应快的评审模型,并设置 timeout_ms,避免某个卡住的成员拖慢整个请求。

配置合议模型

合议模型引用已存在的直连模型,并定义 AISIX 如何把它们用作合议成员和评审模型。

创建模型

合议成员和评审模型通过 display_name 引用已存在的直连模型,因此要先创建这些直连模型。如果需要完整的模型创建流程,见模型别名

合议模型定义合议成员、评审模型、最少成功响应数以及单次调用超时:

{
"display_name": "research-ensemble",
"ensemble": {
"panel": [
{ "model": "gpt-4o-panel", "temperature": 0.7 },
{ "model": "claude-panel", "temperature": 0.7 },
{ "model": "gemini-panel", "temperature": 0.9 }
],
"judge": { "model": "gpt-4o-judge" },
"min_responses": 2,
"timeout_ms": 30000
}
}

合议模型存储并生效后,就能像调用其他模型一样,在 /v1/chat/completions 上调用 research-ensemble

curl -sS -X POST "http://127.0.0.1:3000/v1/chat/completions" \
-H "Authorization: Bearer YOUR_CALLER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "research-ensemble",
"messages": [
{
"role": "user",
"content": "In one sentence, what is an API gateway?"
}
]
}' \
| jq '{ model, choices: (.choices | length), total_tokens: .usage.total_tokens }'

返回结果展示了合议模型对外可观察的约定:

{
"model": "research-ensemble",
"choices": 1,
"total_tokens": 508
}

model 是合议模型别名,choices 是一个合成后的答案,total_tokens 是合议成员与评审模型的合计。

合议模型字段

参考以下字段说明来调优示例中的合议成员、评审模型、最少成功响应数和超时。完整 schema 见 Admin API 参考

合议成员(panel

非空的合议成员列表。每个成员通过 display_name 引用一个直连模型,并可为该成员单独覆盖采样参数:

字段类型是否必填说明
modelstring接收一次合议调用的直连模型 display_name
temperaturenumber该成员调用使用的采样 temperature,会覆盖请求中的 temperature;省略则沿用请求值。
seedinteger该成员调用使用的采样 seed;需要可复现的变化时,与 temperature 搭配使用。
weightinteger为未来的投票策略预留,目前忽略,可省略。

同一个 display_name 可以出现多次——自合议正是这样表达的。

评审模型(judge

把合议成员的答案合成为一个响应的模型。

字段类型是否必填说明
modelstring合成合议成员响应的直连模型 display_name
synthesis_promptstring自定义合成模板;一旦设置,必须包含 {original_request}{labeled_candidates}。省略则使用默认模板。模板的用法见评审合成一节。

评审模型始终以固定的低 temperature 运行以保证合成稳定,该值不可配置。

最少成功响应数(min_responses

min_responses 设置评审模型运行前所需的最少成功合议成员响应数。

  • 省略时,AISIX 要求最多两个成功的合议成员响应,并以合议成员数量为上限。大于成员数量的值会被截断为成员数量,有效值始终至少为 1,因此单成员的自合议只需一个响应。
  • 若成功的合议成员少于 min_responses,请求会失败,而不会基于过少的依据勉强合成。

单次调用超时(timeout_ms

timeout_ms 为每个合议成员调用和评审模型调用设置一个可选的单次上游超时,单位毫秒。它叠加在每个被引用模型自身的超时之上。取 0 或不设置,表示没有合议级别的单次调用超时。

调优

通过调整合议成员数量、各成员采样参数、最少成功响应数以及单次调用超时来调优合议模型。

目标调整方式
提升答案多样性使用不同的成员模型,或把各成员的 temperature 拉开差距,例如 0.50.70.9
结果可复现为每个成员设置 seed,并搭配选定的 temperature
单一服务提供方下的多样性用不同的 temperatureseed,把同一个 model 重复两到三次。
容忍成员失败多加一两个合议成员,并让 min_responses 低于成员数量,这样个别成员失败不至于让请求失败。
限制尾延迟timeout_ms 设为可接受的单次调用上限;缓慢的成员会被丢弃,只要仍满足 min_responses,流程就继续。
降低成本缩减合议成员、选更便宜的评审模型。合成质量更多取决于评审模型的推理能力,而非其规模。

评审合成

评审模型会把原始请求和成功的合议成员答案作为一条消息接收。候选答案以中性标签标注(Answer 1Answer 2 等),不带合议成员的模型名称,这样运维方选用的服务提供方和模型就不会出现在合成后的响应里。

每个候选答案在送入评审模型前都会被限制长度,因此再大的合议也不会撑爆评审模型的上下文窗口——超长答案会被截断,而不是丢弃。

默认的合成指令要求评审模型:把候选答案当作证据、优先采纳共识、用推理化解矛盾、舍弃缺乏依据的说法,并只返回最终答案。响应沿用用户要求的语言和格式,且不会提及背后有多个模型参与。

自定义评审提示词

自定义合成提示词会替换默认指令,同样可以包含 {original_request}{labeled_candidates} 占位符。可以用它给评审模型下达领域特定的评判标准:

{
"display_name": "code-council",
"ensemble": {
"panel": [
{ "model": "model-a" },
{ "model": "model-b" }
],
"judge": {
"model": "model-a",
"synthesis_prompt": "You are a senior reviewer. From the candidate solutions, produce one correct, secure, idiomatic answer. Prefer code that compiles and handles edge cases. Output only the final code and a one-line rationale.\n\nRequest:\n{original_request}\n\nCandidates:\n{labeled_candidates}"
}
}
}

如果自定义合成提示词省略了 {original_request}{labeled_candidates},就收不到对应内容。当评审模型需要原始请求和候选答案时,请把这两个占位符都包含进去。

合议模式

创建出基本的合议模型后,可以按以下常见模式调整合议成员和评审模型的配置。

跨服务提供方合议

从不同服务提供方选取合议成员,并用一个推理能力强的模型作评审模型,以最大化独立性:

{
"panel": [
{ "model": "model-a" },
{ "model": "model-b" },
{ "model": "model-c" }
],
"judge": { "model": "model-b" },
"min_responses": 2
}

单一服务提供方的自合议

在不引入额外厂商的前提下,用不同 temperature 重复同一个模型,从单个模型获得答案多样性:

{
"panel": [
{ "model": "model-a", "temperature": 0.4, "seed": 1 },
{ "model": "model-a", "temperature": 0.7, "seed": 2 },
{ "model": "model-a", "temperature": 1.0, "seed": 3 }
],
"judge": { "model": "model-a" }
}

成本受限的合议

当你希望在成本不大幅增加的前提下获得适度质量提升时,可以用两个合议成员、一个更便宜的评审模型和一个较紧的超时:

{
"panel": [
{ "model": "model-a" },
{ "model": "model-b" }
],
"judge": { "model": "model-b" },
"min_responses": 1,
"timeout_ms": 20000
}

运行时行为

AISIX 接受合议请求后,调用方看到的仍是一个模型响应。与直连模型的差异体现在流式、用量核算、遥测、限流和失败处理上。

流式与调用方响应

合议模型接受 stream: true,但合议成员阶段不会流式传输。AISIX 先等到足够的成员响应,再只把评审模型的输出流式发给调用方。

在合议成员阶段,连接不发送任何字节,包括 keep-alive 帧。请把客户端读取超时设得足以容纳最慢的合议成员,再加上评审模型发出首个 Token 前的时间。评审模型开始流式输出后,AISIX 会发送 SSE keep-alive 帧来保持连接。通用的流式行为见流式传输

面向调用方的响应完整保留合议这层抽象。response.model 回显调用方请求的合议模型别名,响应不会暴露合议成员别名、评审模型或上游服务提供方的模型 ID。合议模型和直连模型一样,会出现在 GET /v1/models 列表中。

用量核算

响应的 usage 对象是每次合议成员调用加上评审模型调用的合计。它反映请求的真实成本,因此 prompt_tokens 可能远大于调用方实际发送的 Token 数:每个合议成员都要处理提示词,评审模型则同时处理提示词上下文和成员答案。

在流式请求中,只有当调用方设置了 stream_options.include_usage: true 时,这个合计才会在末尾的 usage 分片里返回;否则流式响应不带 usage,与直连模型完全一致。

子调用遥测

每个子调用都会发出自己的用量事件,因此可以按合议成员和评审模型分别归因成本与延迟。同一个请求的所有事件共享同一个 request ID。

字段取值
attempt_kind合议成员为 panel,评审模型调用为 judge
attempt_index该成员在合议中的槽位。评审模型最后运行,其 index 等于合议成员数量。
attempt_model该子调用的模型 display_name
prompt_tokenscompletion_tokens该子调用自身的 Token 计数。

一个三成员的合议模型会产生四个用量事件——三个合议成员事件加一个评审模型事件——此外还有返回给客户端的合计。用这些事件可以看出哪个成员慢、哪个成员贵。遥测细节见指标与日志可观测性导出器

限流

限流作用于两个层面:

  • 请求级限流,例如调用方 API 密钥、团队和成员级限流,在面向调用方的合议模型别名上一次性预留。一个合议请求算作一个请求。
  • 模型级限流作用于每个被引用的合议成员和评审模型。超出自身模型限流的合议成员会成为失败的子调用,并在计算 min_responses 时被丢弃,只要其他成员作答足够,请求仍然成功;超出自身模型限流的评审模型则会以 429 让请求失败。

请把模型级限流设在底层直连模型上,而不是合议模型别名上。限流配置见限流

安全护栏与请求约束

配置在合议模型别名上的安全护栏链,作用于合成后的答案,也就是评审模型的输出,而不是每个合议成员的响应。面向调用方的响应反映的是调用方最终收到的答案。安全护栏配置见安全护栏

合议模型还有以下请求形态约束:

  • 仅支持聊天。合议模型只在 /v1/chat/completions 上受支持;其他任何端点都会以 400 拒绝合议模型,并指明该模型及仅支持聊天的约束。
  • 不支持工具。携带非空 tools 数组,或携带强制调用的 tool_choice 的请求会被以 400 拒绝——把一次强制的工具调用广播给多个合议成员,会产生调用方无法调和的相互冲突的工具调用。空的 tools: [],或取值为 noneautotool_choice,视为没有工具并被接受。
  • 仅限直连模型。合议成员和评审模型必须引用同一环境中的直连模型。合议模型不能嵌套,不能使用路由或合议目标,且与直连上游字段互斥。
  • 由配置驱动。没有按请求覆盖合议成员的方式,调用方只能通过模型名称选择合议模型。

失败处理

条件行为客户端状态码
一个或多个合议成员缓慢或失败,但仍满足 min_responses合成基于已到达的答案继续,失败的成员被丢弃。200
成功的合议成员响应少于 min_responses请求失败——AISIX 拒绝基于过少的依据勉强合成。502
某个合议成员超出自身模型限流视为失败的子调用,在计算 min_responses 时被丢弃。其他成员作答足够则 200,否则 502
评审模型调用在唯一一次重试后仍失败请求失败。评审模型的配置或凭证错误(4xx)会被保留,上游 5xx 归并为 5024xx / 502
评审模型超出自身模型限流请求失败。429
请求包含工具,或指向非聊天端点在分发之前即被拒绝。400

托管控制面

在 AISIX 托管控制面中,请从控制台的 Models 页面创建和编辑合议模型,而不是使用 Admin API。表单提供合议成员选择器、评审模型选择器,以及各成员采样、最少成功响应数和超时的控制项;合议成员选择器允许同一个模型被多次选中,以支持自合议。

控制面会把配置投射到环境的数据面,数据面运行与此处描述相同的逻辑。按子调用的用量会出现在用量报告中。

下一步

继续阅读代理错误与重试了解面向调用方的失败,或在需要把合议子调用遥测导出到 AISIX 之外时,阅读可观测性导出器