feat: add AI model health ban exclusion
This commit is contained in:
parent
15a08e6d65
commit
c7966298dc
@ -869,6 +869,7 @@ type AiModel = {
|
|||||||
fallbackModelId1?: string;
|
fallbackModelId1?: string;
|
||||||
fallbackModelId2?: string;
|
fallbackModelId2?: string;
|
||||||
excludeFromFailover?: boolean;
|
excludeFromFailover?: boolean;
|
||||||
|
excludeFromHealthBan?: boolean;
|
||||||
healthStatus?: "healthy" | "degraded" | "auto_disabled";
|
healthStatus?: "healthy" | "degraded" | "auto_disabled";
|
||||||
healthConsecutiveFailures?: number;
|
healthConsecutiveFailures?: number;
|
||||||
healthLastEventType?: string | null;
|
healthLastEventType?: string | null;
|
||||||
@ -3608,6 +3609,7 @@ export function AdminSettingsClient() {
|
|||||||
fallbackModelId1: "", // 备用模型 ID 1
|
fallbackModelId1: "", // 备用模型 ID 1
|
||||||
fallbackModelId2: "", // 备用模型 ID 2
|
fallbackModelId2: "", // 备用模型 ID 2
|
||||||
excludeFromFailover: false,
|
excludeFromFailover: false,
|
||||||
|
excludeFromHealthBan: false,
|
||||||
capabilities: {} as Record<string, unknown>,
|
capabilities: {} as Record<string, unknown>,
|
||||||
// 🆕 图片生成模型特性配置
|
// 🆕 图片生成模型特性配置
|
||||||
imageGenConfig: createDefaultImageGenConfig(),
|
imageGenConfig: createDefaultImageGenConfig(),
|
||||||
@ -6892,6 +6894,7 @@ export function AdminSettingsClient() {
|
|||||||
fallbackModelId1: "",
|
fallbackModelId1: "",
|
||||||
fallbackModelId2: "",
|
fallbackModelId2: "",
|
||||||
excludeFromFailover: false,
|
excludeFromFailover: false,
|
||||||
|
excludeFromHealthBan: false,
|
||||||
capabilities: {},
|
capabilities: {},
|
||||||
imageGenConfig: createDefaultImageGenConfig(),
|
imageGenConfig: createDefaultImageGenConfig(),
|
||||||
});
|
});
|
||||||
@ -14978,6 +14981,10 @@ export function AdminSettingsClient() {
|
|||||||
多模态模型(Agent 识图与分析使用同一模型)
|
多模态模型(Agent 识图与分析使用同一模型)
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="space-y-3 rounded-md border p-3">
|
||||||
|
<div className="text-sm font-medium">
|
||||||
|
故障保护策略
|
||||||
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Switch
|
<Switch
|
||||||
checked={modelForm.excludeFromFailover || false}
|
checked={modelForm.excludeFromFailover || false}
|
||||||
@ -14989,9 +14996,30 @@ export function AdminSettingsClient() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Label>
|
<Label>
|
||||||
禁止参与故障迁移(不作为其他模型的自动备用模型)
|
不参与故障迁移候选池
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
开启后,该模型不会作为其他模型请求失败时的自动备用模型。
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Switch
|
||||||
|
checked={modelForm.excludeFromHealthBan || false}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
setModelForm({
|
||||||
|
...modelForm,
|
||||||
|
excludeFromHealthBan: checked,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Label>
|
||||||
|
不参与故障封禁池
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
开启后,健康检查仍会记录故障日志,但不会因为连续失败自动禁用该模型。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* 🆕 图片生成模型特性配置 */}
|
{/* 🆕 图片生成模型特性配置 */}
|
||||||
{(isImageProviderForModelConfig ||
|
{(isImageProviderForModelConfig ||
|
||||||
@ -15911,7 +15939,12 @@ export function AdminSettingsClient() {
|
|||||||
)}
|
)}
|
||||||
{(model as any).excludeFromFailover && (
|
{(model as any).excludeFromFailover && (
|
||||||
<span className="text-xs bg-rose-100 text-rose-700 px-2 py-0.5 rounded">
|
<span className="text-xs bg-rose-100 text-rose-700 px-2 py-0.5 rounded">
|
||||||
不参与故障迁移
|
不参与迁移池
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{(model as any).excludeFromHealthBan && (
|
||||||
|
<span className="text-xs bg-stone-100 text-stone-700 px-2 py-0.5 rounded">
|
||||||
|
不参与封禁池
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{healthStatus === "auto_disabled" && (
|
{healthStatus === "auto_disabled" && (
|
||||||
@ -16033,6 +16066,8 @@ export function AdminSettingsClient() {
|
|||||||
(model as any).fallbackModelId2 || "",
|
(model as any).fallbackModelId2 || "",
|
||||||
excludeFromFailover:
|
excludeFromFailover:
|
||||||
(model as any).excludeFromFailover || false,
|
(model as any).excludeFromFailover || false,
|
||||||
|
excludeFromHealthBan:
|
||||||
|
(model as any).excludeFromHealthBan || false,
|
||||||
capabilities:
|
capabilities:
|
||||||
(model as any).capabilities &&
|
(model as any).capabilities &&
|
||||||
typeof (model as any).capabilities === "object" &&
|
typeof (model as any).capabilities === "object" &&
|
||||||
|
|||||||
@ -82,6 +82,7 @@ const createModelSchema = z.object({
|
|||||||
fallbackModelId1: z.string().max(128).optional(),
|
fallbackModelId1: z.string().max(128).optional(),
|
||||||
fallbackModelId2: z.string().max(128).optional(),
|
fallbackModelId2: z.string().max(128).optional(),
|
||||||
excludeFromFailover: z.boolean().optional(),
|
excludeFromFailover: z.boolean().optional(),
|
||||||
|
excludeFromHealthBan: z.boolean().optional(),
|
||||||
isAgentModel: z.boolean().optional(),
|
isAgentModel: z.boolean().optional(),
|
||||||
agentCodingModelId: z.string().max(128).optional(),
|
agentCodingModelId: z.string().max(128).optional(),
|
||||||
isMultimodal: z.boolean().optional(),
|
isMultimodal: z.boolean().optional(),
|
||||||
@ -106,6 +107,7 @@ const updateModelSchema = z.object({
|
|||||||
fallbackModelId1: z.string().max(128).optional(),
|
fallbackModelId1: z.string().max(128).optional(),
|
||||||
fallbackModelId2: z.string().max(128).optional(),
|
fallbackModelId2: z.string().max(128).optional(),
|
||||||
excludeFromFailover: z.boolean().optional(),
|
excludeFromFailover: z.boolean().optional(),
|
||||||
|
excludeFromHealthBan: z.boolean().optional(),
|
||||||
isAgentModel: z.boolean().optional(),
|
isAgentModel: z.boolean().optional(),
|
||||||
agentCodingModelId: z.string().max(128).optional(),
|
agentCodingModelId: z.string().max(128).optional(),
|
||||||
isMultimodal: z.boolean().optional(),
|
isMultimodal: z.boolean().optional(),
|
||||||
|
|||||||
@ -211,6 +211,7 @@ export async function reviveAiModelsFromCooldown(params?: { modelId?: string })
|
|||||||
const conditions = [
|
const conditions = [
|
||||||
eq(aiModel.isEnabled, false),
|
eq(aiModel.isEnabled, false),
|
||||||
eq(aiModel.excludeFromFailover, false),
|
eq(aiModel.excludeFromFailover, false),
|
||||||
|
eq(aiModel.excludeFromHealthBan, false),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (params?.modelId) {
|
if (params?.modelId) {
|
||||||
@ -392,6 +393,7 @@ export async function recordAiModelHealthFailure(params: {
|
|||||||
displayName: aiModel.displayName,
|
displayName: aiModel.displayName,
|
||||||
isEnabled: aiModel.isEnabled,
|
isEnabled: aiModel.isEnabled,
|
||||||
excludeFromFailover: aiModel.excludeFromFailover,
|
excludeFromFailover: aiModel.excludeFromFailover,
|
||||||
|
excludeFromHealthBan: aiModel.excludeFromHealthBan,
|
||||||
healthStatus: aiModel.healthStatus,
|
healthStatus: aiModel.healthStatus,
|
||||||
healthConsecutiveFailures: aiModel.healthConsecutiveFailures,
|
healthConsecutiveFailures: aiModel.healthConsecutiveFailures,
|
||||||
healthRecoverySuccessStreak: aiModel.healthRecoverySuccessStreak,
|
healthRecoverySuccessStreak: aiModel.healthRecoverySuccessStreak,
|
||||||
@ -414,6 +416,7 @@ export async function recordAiModelHealthFailure(params: {
|
|||||||
const shouldAutoDisable =
|
const shouldAutoDisable =
|
||||||
classification.counted &&
|
classification.counted &&
|
||||||
!existing.excludeFromFailover &&
|
!existing.excludeFromFailover &&
|
||||||
|
!existing.excludeFromHealthBan &&
|
||||||
((isObservation && existing.isEnabled) ||
|
((isObservation && existing.isEnabled) ||
|
||||||
(existing.healthStatus !== "auto_disabled" &&
|
(existing.healthStatus !== "auto_disabled" &&
|
||||||
nextConsecutiveFailures >= AUTO_DISABLE_FAILURE_THRESHOLD));
|
nextConsecutiveFailures >= AUTO_DISABLE_FAILURE_THRESHOLD));
|
||||||
|
|||||||
@ -106,6 +106,10 @@ const runMigrate = async () => {
|
|||||||
ALTER TABLE "AiModel"
|
ALTER TABLE "AiModel"
|
||||||
ADD COLUMN IF NOT EXISTS "excludeFromFailover" boolean NOT NULL DEFAULT false;
|
ADD COLUMN IF NOT EXISTS "excludeFromFailover" boolean NOT NULL DEFAULT false;
|
||||||
`);
|
`);
|
||||||
|
await db.execute(sql`
|
||||||
|
ALTER TABLE "AiModel"
|
||||||
|
ADD COLUMN IF NOT EXISTS "excludeFromHealthBan" boolean NOT NULL DEFAULT false;
|
||||||
|
`);
|
||||||
await db.execute(sql`
|
await db.execute(sql`
|
||||||
ALTER TABLE "AiModel"
|
ALTER TABLE "AiModel"
|
||||||
ADD COLUMN IF NOT EXISTS "isDefaultTextEditModel" boolean NOT NULL DEFAULT false;
|
ADD COLUMN IF NOT EXISTS "isDefaultTextEditModel" boolean NOT NULL DEFAULT false;
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "AiModel"
|
||||||
|
ADD COLUMN IF NOT EXISTS "excludeFromHealthBan" boolean NOT NULL DEFAULT false;
|
||||||
@ -484,6 +484,13 @@
|
|||||||
"when": 1779267679691,
|
"when": 1779267679691,
|
||||||
"tag": "0082_add_client_performance_events",
|
"tag": "0082_add_client_performance_events",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 69,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1779849000000,
|
||||||
|
"tag": "0083_add_ai_model_health_ban_exclusion",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4068,6 +4068,7 @@ export async function createAiModel({
|
|||||||
fallbackModelId1,
|
fallbackModelId1,
|
||||||
fallbackModelId2,
|
fallbackModelId2,
|
||||||
excludeFromFailover,
|
excludeFromFailover,
|
||||||
|
excludeFromHealthBan,
|
||||||
imageGenConfig,
|
imageGenConfig,
|
||||||
capabilities,
|
capabilities,
|
||||||
isAgentModel,
|
isAgentModel,
|
||||||
@ -4089,6 +4090,7 @@ export async function createAiModel({
|
|||||||
fallbackModelId1?: string;
|
fallbackModelId1?: string;
|
||||||
fallbackModelId2?: string;
|
fallbackModelId2?: string;
|
||||||
excludeFromFailover?: boolean;
|
excludeFromFailover?: boolean;
|
||||||
|
excludeFromHealthBan?: boolean;
|
||||||
imageGenConfig?: ImageGenConfig;
|
imageGenConfig?: ImageGenConfig;
|
||||||
capabilities?: Record<string, unknown> | null;
|
capabilities?: Record<string, unknown> | null;
|
||||||
isAgentModel?: boolean;
|
isAgentModel?: boolean;
|
||||||
@ -4139,6 +4141,7 @@ export async function createAiModel({
|
|||||||
fallbackModelId1: fallbackModelId1 || null,
|
fallbackModelId1: fallbackModelId1 || null,
|
||||||
fallbackModelId2: fallbackModelId2 || null,
|
fallbackModelId2: fallbackModelId2 || null,
|
||||||
excludeFromFailover: excludeFromFailover ?? false,
|
excludeFromFailover: excludeFromFailover ?? false,
|
||||||
|
excludeFromHealthBan: excludeFromHealthBan ?? false,
|
||||||
imageGenConfig: imageGenConfig || null,
|
imageGenConfig: imageGenConfig || null,
|
||||||
defaultParams,
|
defaultParams,
|
||||||
capabilities:
|
capabilities:
|
||||||
@ -4172,6 +4175,7 @@ export async function updateAiModel({
|
|||||||
fallbackModelId1,
|
fallbackModelId1,
|
||||||
fallbackModelId2,
|
fallbackModelId2,
|
||||||
excludeFromFailover,
|
excludeFromFailover,
|
||||||
|
excludeFromHealthBan,
|
||||||
imageGenConfig,
|
imageGenConfig,
|
||||||
capabilities,
|
capabilities,
|
||||||
isAgentModel,
|
isAgentModel,
|
||||||
@ -4194,6 +4198,7 @@ export async function updateAiModel({
|
|||||||
fallbackModelId1?: string;
|
fallbackModelId1?: string;
|
||||||
fallbackModelId2?: string;
|
fallbackModelId2?: string;
|
||||||
excludeFromFailover?: boolean;
|
excludeFromFailover?: boolean;
|
||||||
|
excludeFromHealthBan?: boolean;
|
||||||
imageGenConfig?: ImageGenConfig;
|
imageGenConfig?: ImageGenConfig;
|
||||||
capabilities?: Record<string, unknown> | null;
|
capabilities?: Record<string, unknown> | null;
|
||||||
isAgentModel?: boolean;
|
isAgentModel?: boolean;
|
||||||
@ -4261,6 +4266,21 @@ export async function updateAiModel({
|
|||||||
if (fallbackModelId1 !== undefined) updateData.fallbackModelId1 = fallbackModelId1 || null;
|
if (fallbackModelId1 !== undefined) updateData.fallbackModelId1 = fallbackModelId1 || null;
|
||||||
if (fallbackModelId2 !== undefined) updateData.fallbackModelId2 = fallbackModelId2 || null;
|
if (fallbackModelId2 !== undefined) updateData.fallbackModelId2 = fallbackModelId2 || null;
|
||||||
if (excludeFromFailover !== undefined) updateData.excludeFromFailover = excludeFromFailover;
|
if (excludeFromFailover !== undefined) updateData.excludeFromFailover = excludeFromFailover;
|
||||||
|
if (excludeFromHealthBan !== undefined) {
|
||||||
|
updateData.excludeFromHealthBan = excludeFromHealthBan;
|
||||||
|
if (excludeFromHealthBan) {
|
||||||
|
updateData.healthStatus = "healthy";
|
||||||
|
updateData.healthConsecutiveFailures = 0;
|
||||||
|
updateData.healthLastEventType = null;
|
||||||
|
updateData.healthLastError = null;
|
||||||
|
updateData.healthLastFailureAt = null;
|
||||||
|
updateData.healthAutoDisabledAt = null;
|
||||||
|
updateData.healthAutoDisabledReason = null;
|
||||||
|
updateData.healthRecoverySuccessStreak = 0;
|
||||||
|
updateData.healthObservationStartedAt = null;
|
||||||
|
updateData.healthUpdatedAt = new Date();
|
||||||
|
}
|
||||||
|
}
|
||||||
// 🆕 图片生成配置
|
// 🆕 图片生成配置
|
||||||
if (imageGenConfig !== undefined) updateData.imageGenConfig = imageGenConfig || null;
|
if (imageGenConfig !== undefined) updateData.imageGenConfig = imageGenConfig || null;
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -335,6 +335,7 @@ export const aiModel = pgTable("AiModel", {
|
|||||||
fallbackModelId1: varchar("fallbackModelId1", { length: 128 }), // 备用模型 ID 1
|
fallbackModelId1: varchar("fallbackModelId1", { length: 128 }), // 备用模型 ID 1
|
||||||
fallbackModelId2: varchar("fallbackModelId2", { length: 128 }), // 备用模型 ID 2
|
fallbackModelId2: varchar("fallbackModelId2", { length: 128 }), // 备用模型 ID 2
|
||||||
excludeFromFailover: boolean("excludeFromFailover").notNull().default(false), // 不参与故障迁移
|
excludeFromFailover: boolean("excludeFromFailover").notNull().default(false), // 不参与故障迁移
|
||||||
|
excludeFromHealthBan: boolean("excludeFromHealthBan").notNull().default(false), // 不参与故障自动封禁池
|
||||||
healthStatus: varchar("healthStatus", {
|
healthStatus: varchar("healthStatus", {
|
||||||
enum: ["healthy", "degraded", "auto_disabled"],
|
enum: ["healthy", "degraded", "auto_disabled"],
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user