合议模型
合议模型让调用方只使用一个模型别名,由 AISIX 请求多个合议成员生成候选响应,再请求评审模型合成最终答案。调用方发送一个请求,并在所请求的别名下收到一个答案。分发与合成都在网关内部完成。
在 AISIX 中,合议模型是一种模型别名,AISIX 通过调用多个直连模型来解析它,与路由组和语义路由器类似。它不直接指向某个上游模型,而是通过 ensemble 配置告诉 AISIX:调用哪些直连模型作为合议成员,以及用哪个直连模型作为评审模型。
合议模型包含两部分:
- 合议成员并发调用,各自生成独立的候选响应。
- 评审模型接收成功的合议成员响应,合成返回给调用方的单一响应。
合议成员和评审模型都必须引用已存在的直连模型别名。服务提供方凭证、服务提供方模型名称、健康行为、冷却行为以及模型级限流,都在这些直连模型上配置。
适用场景与取舍
合议模型用额外的模型调用换取更强的答案合成能力。当答案质量或一致性比极致的延迟、成本更重要时,它最为有用。
当单个模型的答案本身不够可靠时,可以使用合议模型:
- 降低单模型的波动和盲区。相互印证的独立答案更可能正确,评审模型会化解矛盾、舍弃缺乏依据的说法。
- 对高难度的推理或研究类提示词做交叉验证。不同模型可能沿不同路径得出答案,另一个候选响 应往往能暴露其中的错误。
- 单一服务提供方下的自合议。合议成员可以是同一个直连模型的多次重复,各次使用不同的
temperature和seed,这样只有一个服务提供方密钥的团队,无需引入新厂商也能获得答案多样性。
合议模型会向每个合议成员各发一个请求,再调用评审模型,因此并不适合所有场景。以下情况请改用其他模型类型:
- 对延迟敏感、以流式优先的链路。首个 Token 到达时间天然偏高,原因见流式与调用方响应一节。
- 使用工具或函数调用的请求。这类请求不受支持,受支持的请求形态见安全护栏与请求约束。
- 高流量、对成本敏感的流量,此时质量提升不足以抵消额外开销。
- Chat Completions 以外的端点。合议模型仅支持聊天。
这些情况请改用直连模型或多目标模型。多目标模型每次请求只选一个目标,而合议模型会调用全部合议成员,并综合它们的输出。
请求流程
合议请求从一个模型别名进入。AISIX 把请求并发分发给配置的合议成员,将成功的成员响应交给评审模型,最终只返回评审模型合成的答案。
对于每个聊天请求,AISIX 会执行以下阶段:
- 分发给合议成员。AISIX 把提示词并发分发给每个合议成员,并套用各成员各自的
temperature和seed覆盖值。 - 收集成功响应。AISIX 保留成功的答案;一旦成功的成员数量满足
min_responses,即进入下一步,否则请求按失败处理中的行为处理。 - 合成最终答案。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 引用一个直连模型,并可为该成员单独覆盖采样参数:
| 字段 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
model | string | 是 | 接收一次合议调用的直连模型 display_name。 |
temperature | number | 否 | 该成员调用使用的采样 temperature,会覆盖请求中的 temperature;省略则沿用请求值。 |
seed | integer | 否 | 该成员调用使用的采样 seed;需要可复现的变化时,与 temperature 搭配使用。 |
weight | integer | 否 | 为未来的投票策略预留,目前忽略,可省略。 |
同一个 display_name 可以出现多次——自合议正是这样表达的。
评审模型(judge)
把合议成员的答案合成为一个响应的模型。
| 字段 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
model | string | 是 | 合成合议成员响应的直连模型 display_name。 |
synthesis_prompt | string | 否 | 自定义合成模板;一旦设置,必须包含 {original_request} 和 {labeled_candidates}。省略则使用默认模板。模板的用法见评审合成一节。 |
评审模型始终以固定的低 temperature 运行以保证合成稳定,该值不可配置。
最少成功响应数(min_responses)
min_responses 设置评审模型运行前所需的最少成功合议成员响应数。
- 省略时,AISIX 要求最多两个成功的合议 成员响应,并以合议成员数量为上限。大于成员数量的值会被截断为成员数量,有效值始终至少为
1,因此单成员的自合议只需一个响应。 - 若成功的合议成员少于
min_responses,请求会失败,而不会基于过少的依据勉强合成。
单次调用超时(timeout_ms)
timeout_ms 为每个合议成员调用和评审模型调用设置一个可选的单次上游超时,单位毫秒。它叠加在每个被引用模型自身的超时之上。取 0 或不设置,表示没有合议级别的单次调用超时。
调优
通过调整合议成员数量、各成员采样参数、最少成功响应数以及单次调用超时来调优合议模型。
| 目标 | 调整方式 |
|---|---|
| 提升答案多样性 | 使用不同的成员模型,或把各成员的 temperature 拉开差距,例如 0.5、0.7、0.9。 |
| 结果可复现 | 为每个成员设置 seed,并搭配选定的 temperature。 |
| 单一服务提供方下的多样性 | 用不同的 temperature 和 seed,把同一个 model 重复两到三次。 |
| 容忍成员失败 | 多加一两个合议成员,并让 min_responses 低于成员数量,这样个别成员失败不至于让请求失败。 |
| 限制尾延迟 | 把 timeout_ms 设为可接受的单次调用上限;缓慢的成员会被丢弃,只要仍满足 min_responses,流程就继续。 |
| 降低成本 | 缩减合议成员、选更便宜的评审模型。合成质量更多取决于评审模型的推理能力,而非其规模。 |
评审合成
评审模型会把原始请求和成功的合议成员答案作为一条消息接收。候选答案以中性标签标注(Answer 1、Answer 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_tokens、completion_tokens | 该子调用自身的 Token 计数。 |
一个三成员的合议模型会产生四个用量事件——三个合议成员事件加一个评审模型事件——此外还有返回给客户端的合计。用这些事件可以看出哪个成员慢、哪个成员贵。遥测细节见指标与日志和可观测性导出器。
限流
限流作用于两个层面:
- 请求级限流,例如调用方 API 密钥、团队和成员级限流,在面向调用方的合议模型别名上一次性预留。一个合议请求算作一个请求。
- 模型级限流作用于每个被引用的合议成员和评审模型。超出自身模型限流的合议成员会成为失败的子调用,并在计算
min_responses时被丢弃,只要其他成员作答足够,请求仍然成功;超出自身模型限流的评审模型则会以429让请求失败。
请把模型级限流设在底层直连模型上,而不是合议模型别名上。限流配置见限流。
安全护栏与请求约束
配置在合议模型别名上的安全护栏链,作用于合成后的答案,也就是评审模型的输出,而不是每个合议成员的响应。面向调用方的响应反映的是调用方最终收到的答案。安全护栏配置见安全护栏。
合议模型还有以下请求形态约束:
- 仅支持聊天。合议模型只在
/v1/chat/completions上受支持;其他任何端点都会以400拒绝合议模型,并指明该模型及仅支持聊天的约束。 - 不支持工具。携带非空
tools数组,或携带强制调用的tool_choice的请求会被以400拒绝——把一次强制的工具调用广播给多个合议成员,会产生调用方无法调和的相互冲突的工具调用。空的tools: [],或取值为none、auto的tool_choice,视为没有工具并被接受。 - 仅限直连模型。合议成员和评审模型必须引用同一环境中的直连模型。合议模型不能嵌套,不能使用路由或合议目标,且与直连上游字段互斥。
- 由配置驱动。没有按请求覆盖合议成员的方式,调用方只能通过模型名称选择合议模型。
失败处理
| 条件 | 行为 | 客户端状态码 |
|---|---|---|
一个或多个合议成员缓慢或失败,但仍满足 min_responses | 合成基于已到达的答案继续,失败的成员被丢弃。 | 200 |
成功的合议成员响应少于 min_responses | 请求失败——AISIX 拒绝基于过少的依据勉强合成。 | 502 |
| 某个合议成员超出自身模型限流 | 视为失败的子调用,在计算 min_responses 时被丢弃。 | 其他成员作答足够则 200,否则 502 |
| 评审模型调用在唯一一次重试后仍失败 | 请求失败。评审模型的配置或凭证错误(4xx)会被保留,上游 5xx 归并为 502。 | 4xx / 502 |
| 评审模型超出自身模型限流 | 请求失败。 | 429 |
| 请求包含工具,或指向非聊天端点 | 在分发之前即被拒绝。 | 400 |
托管控制面
在 AISIX 托管控制面中,请从控制台的 Models 页面创建和编辑合议模型,而不是使用 Admin API。表单提供合议成员选择器、评审模型选择器,以及各成员采样、最少成功响应数和超时的控制项;合议成员选择器允许同一个模型被多次选中,以支持自合议。
控制面会把配置投射到环境的数据面,数据面运行与此处描述相同的逻辑。按子调用的用量会出现在用量报告中。