feat(composite): enforce reasoning effort policy

This commit is contained in:
Heatherm Huang
2026-08-01 21:15:44 +08:00
parent b74024c786
commit d60f4e442b
16 changed files with 250 additions and 48 deletions
@@ -850,7 +850,7 @@ export default {
rpmLimitHint: 'Max requests per minute for each user in this group; 0 = unlimited. Once set, it takes over per-user rate limiting in this group (overrides the user-level rpm_limit fallback).',
maxReasoningEffort: 'Max reasoning effort',
maxReasoningEffortUnlimited: 'Unlimited (follow request)',
maxReasoningEffortHint: 'Limits explicit OpenAI reasoning effort requests only. Higher values are capped; omitted effort stays omitted. The ceiling takes precedence over reasoning effort mappings.',
maxReasoningEffortHint: 'Limits explicit OpenAI reasoning effort requests only. For Composite groups, it applies only to requests resolved to OpenAI. Higher values are capped; omitted effort stays omitted. The ceiling takes precedence over reasoning effort mappings.',
reasoningEffortMappings: 'Reasoning effort mappings',
addReasoningEffortMapping: 'Add mapping',
removeReasoningEffortMapping: 'Remove mapping',
@@ -832,7 +832,7 @@ export default {
rpmLimitHint: '每用户在本分组每分钟最大请求数,0 = 不限制;一旦设置即接管该用户的限流(覆盖用户级 rpm_limit)',
maxReasoningEffort: '推理强度上限',
maxReasoningEffortUnlimited: '不限制(跟随请求)',
maxReasoningEffortHint: '仅限制客户端主动请求的 OpenAI reasoning effort;超过上限时自动降档,不会为缺省请求主动开启推理。上限优先级高于推理强度映射。',
maxReasoningEffortHint: '仅限制客户端主动请求的 OpenAI reasoning effort;Composite 分组仅对解析到 OpenAI 的请求生效。超过上限时自动降档,不会为缺省请求主动开启推理。上限优先级高于推理强度映射。',
reasoningEffortMappings: '推理强度映射',
addReasoningEffortMapping: '添加映射',
removeReasoningEffortMapping: '删除映射',
+5 -4
View File
@@ -610,7 +610,7 @@
<p class="input-hint">{{ t("admin.groups.form.rpmLimitHint") }}</p>
</div>
<ReasoningEffortPolicyFields
v-if="createForm.platform === 'openai'"
v-if="supportsReasoningEffortPolicyPlatform(createForm.platform)"
ref="createReasoningEffortPolicyRef"
id-prefix="create-group-reasoning"
:platform="createForm.platform"
@@ -2163,7 +2163,7 @@
<p class="input-hint">{{ t("admin.groups.form.rpmLimitHint") }}</p>
</div>
<ReasoningEffortPolicyFields
v-if="editForm.platform === 'openai'"
v-if="supportsReasoningEffortPolicyPlatform(editForm.platform)"
ref="editReasoningEffortPolicyRef"
id-prefix="edit-group-reasoning"
:platform="editForm.platform"
@@ -4099,6 +4099,7 @@ import {
normalizeReasoningEffortForPlatform,
reasoningEffortMappingsToAPI,
reasoningEffortMappingsToRows,
supportsReasoningEffortPolicyPlatform,
type ReasoningEffortMappingRow,
} from "./groupsReasoningEffort";
import {
@@ -5465,7 +5466,7 @@ const handleCreateGroup = async () => {
return;
}
if (
createForm.platform === "openai" &&
supportsReasoningEffortPolicyPlatform(createForm.platform) &&
createReasoningEffortPolicyRef.value &&
!createReasoningEffortPolicyRef.value.validate()
) {
@@ -5672,7 +5673,7 @@ const handleUpdateGroup = async () => {
return;
}
if (
editForm.platform === "openai" &&
supportsReasoningEffortPolicyPlatform(editForm.platform) &&
editReasoningEffortPolicyRef.value &&
!editReasoningEffortPolicyRef.value.validate()
) {
@@ -6,21 +6,28 @@ import {
reasoningEffortMappingsToAPI,
reasoningEffortMappingsToRows,
reasoningEffortOptionsForPlatform,
supportsReasoningEffortPolicyPlatform,
validateReasoningEffortMappings,
} from "../groupsReasoningEffort";
describe("groupsReasoningEffort", () => {
it("provides fixed OpenAI choices without none", () => {
expect(
reasoningEffortOptionsForPlatform("openai").map((option) => option.value),
).toEqual([
it("provides fixed OpenAI choices to OpenAI and Composite groups", () => {
const expected = [
"minimal",
"low",
"medium",
"high",
"xhigh",
"max",
]);
];
for (const platform of ["openai", "composite"] as const) {
expect(
reasoningEffortOptionsForPlatform(platform).map(
(option) => option.value,
),
).toEqual(expected);
expect(supportsReasoningEffortPolicyPlatform(platform)).toBe(true);
}
for (const platform of [
"anthropic",
"gemini",
@@ -28,6 +35,7 @@ describe("groupsReasoningEffort", () => {
"grok",
] as const) {
expect(reasoningEffortOptionsForPlatform(platform)).toEqual([]);
expect(supportsReasoningEffortPolicyPlatform(platform)).toBe(false);
}
});
@@ -48,6 +56,9 @@ describe("groupsReasoningEffort", () => {
it("clears values unsupported by OpenAI or used on another platform", () => {
expect(normalizeReasoningEffortForPlatform("openai", " MAX ")).toBe("max");
expect(normalizeReasoningEffortForPlatform("composite", " MAX ")).toBe(
"max",
);
expect(normalizeReasoningEffortForPlatform("grok", "max")).toBe("");
expect(normalizeReasoningEffortForPlatform("openai", "none")).toBe("");
});
@@ -12,7 +12,15 @@ const openAIReasoningEffortValues = [
const reasoningEffortValuesForPlatform = (
platform: GroupPlatform,
): readonly string[] =>
platform === "openai" ? openAIReasoningEffortValues : [];
supportsReasoningEffortPolicyPlatform(platform)
? openAIReasoningEffortValues
: [];
export function supportsReasoningEffortPolicyPlatform(
platform: GroupPlatform,
): boolean {
return platform === "openai" || platform === "composite";
}
export function reasoningEffortOptionsForPlatform(platform: GroupPlatform) {
return reasoningEffortValuesForPlatform(platform).map((value) => ({