feat(cloud-agent): 单步输出上限与秒级墙钟,超时/空输出可自恢复
画布 Agent 一轮要跑很多步模型调用,此前只有"按任务类型的分钟级超时":某一步卡住只能等 整轮判死;更根本的是每一步请求根本不带输出上限,不写 max_tokens 时上游按剩余上下文放行, 思考模型可以把单步拖到几分钟,且偶发把整个输出预算花在推理上、正文与工具调用皆空。 - 新增运行时策略 task.agentStepTimeoutSeconds 与 task.agentStepMaxOutputTokens:秒级墙钟 与单步输出上限,都支持环境变量给部署级默认值、管理端热更新;旧配置 JSON 缺字段按默认值 回填,无需数据迁移。 - 单步墙钟到点中止这一步时不再把整轮判死:以可识别标记记为该步失败,运行期关掉上游思考 重试同一步一次(model_failure_recovered / step_timeout_retried),重试仍超时才以可读原因 (model_step_timeout)结束本轮。 - 空输出催办用尽后新增一级升级:关思考 + 放大输出预算重试同一步 (model_failure_recovered / empty_output_escalated),而不是直接判死。放大档在原值上翻倍 并以 131072 封顶,策略值为 0 时用 32768 兜底,让重试仍然有界。 - 输出上限真正下发到上游:textOptions.maxOutputTokens 成为任务信封字段,Agent 的两条请求 路径(内置协议与声明式协议)组装请求体时写入 max_tokens / max_output_tokens,与既有的 input.MaxOutputTokens 取较小值,避免策略上限超过模型声明的物理上限。 - task_worker:执行时限改用带画布 Agent 分支的 taskExecutionTimeout;执行时限到点本身不再 被当成"租约丢失",否则任务会停在 running 等租约过期后被反复重跑(实测一次调用被重跑成 三次上游请求)。续租仍用上游已合入的"不继承父 context 取消"的独立 context。
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { App, Button, Form, InputNumber, Skeleton } from "antd";
|
||||
import { AlertTriangle, Database, Gauge, Infinity as InfinityIcon, Network, RefreshCw, RotateCcw, Save, ShieldCheck, TimerReset } from "lucide-react";
|
||||
import { AlertTriangle, Bot, Database, Gauge, Infinity as InfinityIcon, Network, RefreshCw, RotateCcw, Save, ShieldCheck, TimerReset } from "lucide-react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
|
||||
import { useBlocker } from "react-router";
|
||||
|
||||
@@ -51,6 +51,27 @@ const timeoutFields: PolicyField[] = [
|
||||
{ group: "task", name: "defaultTimeoutMinutes", label: "默认任务超时", extra: "未匹配专用类型时使用的最长执行时间。", unit: "分钟", max: 9_999 },
|
||||
];
|
||||
|
||||
const agentFields: PolicyField[] = [
|
||||
{
|
||||
group: "task",
|
||||
name: "agentStepMaxOutputTokens",
|
||||
label: "单步输出上限",
|
||||
extra: "画布 Agent 每次模型调用的输出上限,含思考、正文与工具调用参数。0 表示不限制,此时只有单步超时兜底;抬高可以避免长思考模型被截断后返回空内容。",
|
||||
unit: "token",
|
||||
min: 0,
|
||||
max: 131_072,
|
||||
},
|
||||
{
|
||||
group: "task",
|
||||
name: "agentStepTimeoutSeconds",
|
||||
label: "单步超时",
|
||||
extra: "画布 Agent 单步模型调用的最长等待时间,到点会中止这一步并自动关思考重试一次。0 表示沿用“文本任务超时”,不再单独计时。",
|
||||
unit: "秒",
|
||||
min: 0,
|
||||
max: 3_600,
|
||||
},
|
||||
];
|
||||
|
||||
const rateFields: PolicyField[] = [
|
||||
{ group: "request", name: "taskCreatePerMinute", label: "任务创建", extra: "每账号每分钟允许创建的任务数。", unit: "次/分钟", max: 999_999 },
|
||||
{ group: "request", name: "resourceUploadPerMinute", label: "资源上传", extra: "每账号每分钟上传资源的次数。", unit: "次/分钟", max: 999_999 },
|
||||
@@ -88,6 +109,15 @@ const policySections: PolicySectionDefinition[] = [
|
||||
status: <AdminStatusBadge label="保存后热更新" tone="info" />,
|
||||
},
|
||||
{ id: "policy-timeout", icon: <TimerReset className="size-4" aria-hidden="true" />, title: "任务超时", shortTitle: "任务超时", description: "不同生成类型的最长执行时间。", fields: timeoutFields },
|
||||
{
|
||||
id: "policy-agent",
|
||||
icon: <Bot className="size-4" aria-hidden="true" />,
|
||||
title: "画布 Agent 单步",
|
||||
shortTitle: "Agent 单步",
|
||||
description: "画布 Agent 每一步模型调用的输出上限与等待时限;两者一起决定单步最坏耗时。",
|
||||
fields: agentFields,
|
||||
status: <AdminStatusBadge label="保存后热更新" tone="info" />,
|
||||
},
|
||||
{ id: "policy-rate", icon: <ShieldCheck className="size-4" aria-hidden="true" />, title: "业务频控", shortTitle: "业务频控", description: "账号与 IP 维度的固定窗口请求限制。", fields: rateFields },
|
||||
{ id: "policy-relay", icon: <Network className="size-4" aria-hidden="true" />, title: "渠道中转与熔断", shortTitle: "中转与熔断", description: "请求体、响应体、并发、超时和上游故障保护。", fields: relayFields },
|
||||
];
|
||||
|
||||
@@ -333,6 +333,10 @@ export type RuntimeTaskPolicy = {
|
||||
videoTimeoutMinutes: number;
|
||||
storyboardTimeoutMinutes: number;
|
||||
defaultTimeoutMinutes: number;
|
||||
/** 画布 Agent 单步模型调用的输出上限(思考 + 正文 + 工具参数);0 表示不限制。 */
|
||||
agentStepMaxOutputTokens: number;
|
||||
/** 画布 Agent 单步模型调用的秒级墙钟;0 表示沿用文本任务超时。 */
|
||||
agentStepTimeoutSeconds: number;
|
||||
};
|
||||
|
||||
export type RuntimeRequestPolicy = {
|
||||
|
||||
Reference in New Issue
Block a user