AI Proxy - API代理管理面板

{{ healthOk ? '服务运行中' : '服务未连接' }} {{ healthModels.length }} 个模型 | {{ healthProviders.length }} 个供应商
热重载已开启:修改配置后自动生效,无需重启服务。也可以直接编辑 config.yaml 文件。
{{ p.name }}
全部
{{ providerTabName(t) }} ×
+
供应商 {{ effectiveSearchQuery ? matchedProviderCount : config.providers.length }}
📊 性能看板 导出配置 导入配置 + 添加供应商 🔁 批量替换上游模型
全部 已启用 已禁用 有视觉 有重复模型
🔽 全部展开 🔼 全部收起
找到 {{ effectiveSearchQuery ? matchedProviderCount : providerTotal }} 个供应商(已加载 {{ config.providers.length }})
#{{ p._origIdx + 1 }} {{ p.name }} 识图✓ 识图✗ {{ imageEditShapeBadge(p) }} 合并system✓ 消息限制✓ Anthropic格式
{{ p.base_url }}
API Keys: ({{ getProviderApiKeys(p).length }}个) 模板:
{{ isProviderExpanded(p) ? '▾' : '▸' }} {{ (p.models || []).length }} 个模型 大供应商 ({{ (p.models || []).length }}行)
→ ● {{ modelHealthStyle(modelHealthInfo(p, m)).text }} {{ modelTestResults[testKey(p._origIdx, findModelOrigIdx(p, m), m.name)].ok ? '✓' : '✗' }} {{ modelTestResults[testKey(p._origIdx, findModelOrigIdx(p, m), m.name)].time }}s 外部识图 自定义文件服务 自定义载荷 Responses直连 系统提示: {{ m.system_prompt }}
模板: {{ getModelEffectiveTemplate(m, p) }} ←供应商←全局
当前供应商 ({{ p.name }})
{{ pp.name }}
暂无模型,点击"添加模型"添加
该供应商下无匹配模型
共 {{ p.models.length }} 个模型
⟳ 加载中...
已显示 {{ Math.min(searchRenderLimit, filteredProvidersAll.length) }} / {{ filteredProvidersAll.length }} 个匹配供应商,滚动或点击加载更多 ▾
滚动加载更多(已加载 {{ config.providers.length }} / {{ providerTotal }})
已加载全部 {{ config.providers.length }} 个供应商
✓ 代理会转换:外部Anthropic请求 → OpenAI格式转发 → Anthropic格式返回 ✓ 上游支持Anthropic格式时选择,代理直接转发不做转换
预览: {{ providerForm.base_url.replace(/\/+$/, '') }}{{ providerForm._append_chat ? (providerForm.api_format === 'anthropic' ? '/messages' : '/chat/completions') : '' }} 追加 {{ providerForm.api_format === 'anthropic' ? '/messages' : '/chat/completions' }}
🔗 会话头自动注入:该上游要求请求携带 x-opencode-session,中转已自动处理,无需配置——客户端传了会话头则透传;没传则按 key+IP+首条消息派生稳定 ID(同会话多轮同 ID,防上游风控)
#{{ euIdx + 1 }} 删除
+ 添加测试地址 或选常用尾缀(基于主地址自动拼接): 添加
用于在线测试时切换不同端点(如生图、视频地址)。主地址始终为默认。
共 {{ providerForm.api_keys.length }} 个 · 启用 {{ providerForm.api_keys.filter(k=>k.enabled!==false).length }} · 禁用 {{ providerForm.api_keys.filter(k=>k.enabled===false).length }} 全开 全关
# Key 权重 开关 操作
{{ providerForm.api_keys.length ? '无匹配的 key,换个关键词试试' : '暂无 key,点下方"添加Key"或"批量导入"' }}
+ 添加Key ⇪ 批量导入 列表内部滚动 · 复制按钮复制该 key
数字越大越优先 同优先级内分配比例 关闭后该供应商不会被调用
生效载荷:
支持图片输入(PDF扫描件转图片)
需要合并多条system消息(讯飞等)
消息限制错误码:
图生图方式: 这家供应商做图生图时该往哪个口发。默认自动判断;单个模型可在「编辑模型」里覆盖
逗号分隔,用于识别消息过多错误并触发自动压缩重试
{{ providerSaveError }}
把某个失效的上游模型(供应商卡片里 对外模型名 → 上游模型名 箭头右边那一栏)一次换成新的, 跨所有供应商生效。只改这一个字段:权重 / 参数 / 系统提示词 / 模板全部保留。
原上游模型
替换为
仅替换启用中的模型 (已禁用的行仍会列出,但默认不动)
{{ replacePreviewHint || '选择「原上游模型」后,这里会列出将被改动的地方(可逐行取消勾选)' }}
把 {{ replaceCheckedIds.length }} 处模型的「上游模型」从 {{ replaceConfirmInfo.from }} 换成 {{ replaceConfirmInfo.to }}:
{{ replaceConfirmInfo.byProvider }}
⚠ 会直接写入数据库(不重启即生效)
⚠ 各行的权重 / 参数 / 系统提示词 / 模板保持不动
⚠ 本次改动会记进「操作日志」可按时间回查,不可一键撤销
每行一个 key,空行忽略;已存在的 key 自动去重跳过。导入后为启用+权重1,可在列表里再调。
{{ providerBatchPreview }}
{{ fetchingModels ? '查询中…' : '获取模型列表' }}
{{ fetchModelsError }}
{{ fetchModelsNote }}
{{ keyLabelShort(k) }}
关闭后该模型不会被调用 数字越大越优先,留空继承供应商 同优先级内分配比例,留空继承供应商 开启后,图片将通过外部API解析为文本再发给模型 开启后,文档将通过自定义文件处理服务处理后再发给模型
选择「Responses 原生直连」时,请求自动转成 Responses 格式发给上游(适合 muse-spark 等只支持 Responses 的模型)。 支持文本 / 工具调用(tools→Responses tools 自动转换);图片会转成 input_image(是否可用取决于上游是否支持视觉)。
选择「Messages 原生直连」时,请求自动转成 Anthropic 格式发给上游,鉴权头自动用 x-api-key + anthropic-version (适合只提供 /v1/messages 的供应商,如 opencode zen 的 /zen/go/v1/messages); 支持文本 / 图片 / 工具调用与工具结果(tools→input_schema、tool_calls→tool_use、role:tool→tool_result 自动转换), 流式同样支持(含思考内容转发)。 ⚠️ 思考量大的模型需给足 max_output_tokens(建议 ≥2048),否则正文会被思考占满。
⚠️ 当前生效模板({{ modelForm.template || '继承的模板' }})配置了 defaults.stream:false, 会强制上游走非流式请求(对生图模型等流式不稳定的上游更稳)。
✅ 客户端不受影响:客户端要求流式时,中转会自动把上游的非流式结果翻译成流式(SSE)返回,客户端照常收到流式;客户端要非流式则直接返回非流式。
{{ modelForm.template ? '当前模板载荷:' : '继承上级载荷:' }} {{ param }}={{ getModelEffectiveParamValue(param) }}
可直接编辑载荷参数:
图生图方式: 留空 = 跟供应商一样 / 自动判断。供应商做图生图只给一个生图端口、没有 edits 端口时,选「共用一个端口」
{{ getModelEffectivePreview() }}
{{ modelSaveError }}
{{ upstreamModels.length }} 个模型 | 来自 {{ (upstreamKeySummary||{}).keys_ok || 0 }} / {{ (upstreamKeySummary||{}).keys_total || 0 }} 个 Key ({{ upstreamKeySummary.keys_failed }} 个 Key 取不到) · {{ upstreamKeySummary.models_unique }} 个模型仅 1 个 Key 提供 {{ (upstreamKeySummary||{}).elapsed_ms || 0 }}ms
按模型看 按 Key 看
Key: {{ keyLabelShort(k) }} 清空筛选
只看单 Key 独占 {{ pickerView === 'model' ? ('共 ' + filteredUpstreamModels.length + ' / ' + upstreamModels.length + ' 个') : (filteredPickerKeys.length + ' 个 Key') }}
{{ upstreamModels.length === 0 ? '暂无模型,请先点击"获取模型列表"' : '无匹配结果' }}
{{ gName }} ({{ group.length }}) {{ expandedGroups[gName] ? '收起 ▲' : '展开 ▼' }}
✓ {{ m }}
每个 Key 各自能看到的模型(点 Key 行展开/收起) 全部展开 全部收起
无匹配的 Key
{{ k.label }} {{ k.enabled ? '启用' : '禁用' }} {{ k.count }} 个模型 独占 {{ pickerKeyOnlyModels(k).length }} ✕ {{ k.error }} {{ pickerKeyExpanded[k.index] ? '收起 ▲' : '展开 ▼' }}
{{ m }}★
{{ !k.ok ? '(取不到模型,见上方报错)' : (modelPickerSearch ? '(该 Key 下无匹配搜索的模型)' : '(该 Key 返回 0 个模型)') }}
📁
点击选择 JSON 配置文件
支持 .json 格式
{{ importFileName }}
包含 {{ importProvidersCount }} 个供应商
导入模式
合并 已存在的按名称更新,新的追加
覆盖 已存在的按名称整体替换,新的追加
全部替换 清空现有配置,全部用导入数据替代
当前供应商数: {{ config.providers.length }}
导入供应商数: {{ importProvidersCount }}
⚠️ 将清空所有现有供应商配置
保存配置
基础设置
外部服务
高级设置

全局模板

未选择时:透传客户端标准参数,未传的用下方「全局默认参数」兜底
当前生效载荷:

全局默认参数

模型未选择模板时,以下参数作为兜底注入上游请求:客户端显式传的参数优先,客户端没传才用这里的默认值。已选择模板的模型走模板自身的 forward_params,不受这里影响。

调试日志

开启后将完整请求/响应报文写入 logs/debug.log

外部访问配置

外部访问此代理服务时需要携带的API Key,留空则不验证

Image API(/v1/images/generations + /v1/images/edits)

Cherry Studio 图片生成、图片编辑功能使用这两个端点。
处理逻辑:优先用 image 格式请求上游,上游不支持时自动降级为 chat 格式请求。

推荐开启,兼容所有上游供应商

自动路由:chat 端口 → image 端口

客户端通过 chat 端口请求生图模型(如 gpt-image-2-pro)时,命中下方关键词的模型
自动优先用 image 格式请求上游,上游不支持时降级为普通 chat 请求。
✅ 流式自动适配:image 格式上游是一次性返回(无流式),客户端要求流式时中转自动把结果 翻译成 SSE 流式返回,客户端照常收到流式;要非流式则直接返回非流式。无需配 no-stream 模板。

关闭后关键词配置保留但不生效 模型名包含 上游模型 id 包含 任一满足即触发
{{ kw }} ×

示例:勾选"模型名" + 关键词 image → gpt-image-2-pro 自动触发
勾选"上游模型 id" + 关键词 image → 上游模型 gpt-image-2 触发

图片识图配置

选择图片识别方式:OCR提取文字 或 视觉模型理解

OCR 文字提取 视觉模型识别

自定义文件处理服务

独立文件处理服务,用于处理 PDF 等文档(独立于 OCR/视觉模型)。
在模型编辑中开启「自定义文件处理」标志后生效,处理顺序:文件服务 → OCR/视觉识图。
⚡ 同步模式:将文本内容 POST 到指定 API,适合通用文本处理服务。
📄 MinerU 模式:自动上传 PDF 原文件到 MinerU API,异步解析后返回 Markdown。

开启后,标记了「自定义文件处理」的模型会先调用文件服务处理文档 关闭后,PDF 不走本地 PyMuPDF 提取/渲染,仅由外部文件服务或上游模型处理

上游屏蔽

关闭后非流式响应会删除 reasoning_content(模型思考内容),在线测试将看不到思考块

重试降级配置

同供应商所有 Key 会全部尝试;此值限制跨供应商降级的额外供应商数

错误处置策略

自定义某类上游错误判定为「重试(换Key/供应商)」或「直接报错(不再尝试)」。判定顺序:例外规则(自上而下、第一条命中生效)→ 内置判定(代码兜底)。编辑后点「保存规则」才生效

内置判定(代码兜底,自动生效,无需配置)—— 400 默认「直接报错」,仅以下情况自动走重试:
· type=server_error(风控/临时错误,换Key可能成功)
· invalid_request 且消息含「模型/供应商/账户/余额不足」等关键词(换供应商可能成功)
· unknown_error 且消息含「余额不足」等关键词
· 消息过多(context length超限) → 先自动压缩再重试
· 空消息且非 invalid_request(旧行为兜底,非标结构修复后已少见)
其他状态码:404/405/422 → 直接报错;其余(5xx/429/403/408/409…) → 自动重试。

例外规则匹配说明:状态码=精确;错误类型=包含;消息关键词=空格分隔,默认任一命中,勾选"全部命中"才要求全出现;上游报错原文=默认仅参考,勾选"参与匹配"才参与。所有填了的条件都满足才命中。规则命中即覆盖内置判定(优先级最高)。

+ 添加规则 保存规则 修改后需点「保存规则」或右上角「保存配置」才生效

模型维护屏蔽

某个模型算力不足/维护中时,命中下方规则的模型请求不请求上游,直接返回你配置的报错文案(如"grok-4.1系列当前按量维护,请选择grok-4.5/4.6使用")。判定顺序:规则自上而下、第一条命中生效。编辑后点「保存规则」才生效

+ 添加规则 保存规则 修改后需点「保存规则」或右上角「保存配置」才生效

智能冷却 Key自动冷却

上游返回 429(限流) / 401/403(认证) / 410(已下线) 时,自动将该 Key 冷却指定秒数,冷却期间不参与负载均衡。冷却中的 Key 在 Key健康页面有标注。

关闭后所有状态码都不触发冷却(当前已冷却的 key 立即恢复?不——仍等 TTL 到期,可用下方按钮一键清除)
429(限流) 401/403(认证) 410(已下线) 400(泛化拒绝)
限流 认证失败 / 余额不足 模型已下线 / 已废弃 只说「请求不合法」不说字段 → 该 key 收不了这类请求 🧹 一键清除全部冷却 清掉所有 key 的冷却状态,立即恢复参与负载均衡

错误提示自定义

自定义各类错误返回给客户端的提示信息,隐藏上游细节。对所有供应商全局生效

关键词替换规则

错误信息中出现以下关键词时自动替换,防止泄露上游供应商名称

→ ×
+ 添加替换规则

消息自动压缩

对话消息过多时自动压缩历史消息,避免上游API报错(如讯飞10163)

消息数超过此值时触发压缩 压缩时完整保留的最近消息数

流式占位帧(首字保活)

模型思考期间是否先发一个空壳帧占位。开启可防客户端「首字节超时」断连,但会让日志里的「首字」偏小、与真实等待对不上。

已开启:首字会偏小(防断连优先) 已关闭(推荐):首字 = 真实等待时间 静默超过此秒数才补一帧,仅在启用时生效
⚠️ 为什么默认关闭
2026-09-21/24 上线后,vip 站(58)日志里的「首字」掉到 0.3 秒,而真实上游要 8~9 秒;另一站(56)仍是 9 秒多 —— 两站数据对不上。
原因就是这帧空壳:它先到,日志按下「收到第一帧」记首字,于是记成 0.3 秒。改造前两站都是 9 秒多、完全一致。
关掉后首字回到真实口径,两站数据才可比。若以后真出现「客户端首字节超时」断连,把开关打开即可(无需改代码)。
模板管理

定义载荷参数规则,不同供应商/模型可选用不同模板。直接编辑 JSON,修改自动保存。

💡 独特配置:强制非流式
在模板 JSON 的 defaults 里加 "stream": false(如内置 no-stream 模板), 该模板下的模型会强制上游走非流式请求(保稳定)。
✅ 客户端自动适配流式:客户端要求流式时,中转自动把上游非流式结果翻译成 SSE 流式返回, 客户端照常收到流式,无感知。客户端要非流式则直接返回非流式。
适用场景:生图模型(如 gpt-image-2-pro / gemini-image)——上游走流式可能丢结果,强制非流式更稳,中转自动翻译流式客户端不感知。
未配 stream 的模板不受影响,仍按客户端请求的流式/非流式转发。
{{ t.name }} {{ t.description }} {{ t._expanded ? '收起' : '展开' }}
{{ param }}
删除 格式化 {{ t._jsonError }} 失焦自动同步
+ 添加模板
实时配置 JSON

修改即生效,保存后写入 config.yaml

{{ configPreview }}
清空 重试 停止
外部调用格式:模拟外部客户端调用代理的格式。OpenAI格式走 /v1/chat/completions,Anthropic格式走 /v1/messages
图片尺寸: 提示词含 "3:4" "16:9" 等比例(中英文冒号均可)或 "横屏/竖屏/方形" 时自动识别
{{ q }}
我: AI: 错误:
思考中...
文件 发送
X
📄 📄 {{ f.name }} ({{ (f.size / 1024).toFixed(0) }}KB) PDF 图片 文本 X

OpenAI 兼容格式调用

将以下配置填入任何支持 OpenAI 格式的程序中即可使用

{{ m.name }} ({{ m.provider }} → {{ m.model_id }})

base_url = "http://localhost:{{ config.server.port }}/v1"
api_key = "{{ config.server.external_key || '123' }}"
model = "{{ m.name }}"

Anthropic Messages API 格式调用

使用 Anthropic SDK 或兼容客户端调用 /v1/messages 端点

base_url = "http://localhost:{{ config.server.port }}"
api_key = "{{ config.server.external_key || '123' }}"
model = "模型名称(同上方)"

示例 (Python SDK):

import anthropic
client = anthropic.Anthropic(
  base_url="http://localhost:{{ config.server.port }}",
  api_key="{{ config.server.external_key || '123' }}"
)
response = client.messages.create(
  model="模型名称",
  max_tokens=1024,
  messages=[{"role": "user", "content": "你好"}]
)
💰 消耗额度 ¥{{ logsSummary.cost }} 🚀 RPM {{ logsSummary.rpm }} ⚡ TPM {{ (logsSummary.tpm || 0).toLocaleString() }} 范围内共 {{ logsSummary.total_requests.toLocaleString() }} 次调用 · 30秒自动刷新
显示第 {{ logsTotal === 0 ? 0 : (logsPage-1)*logsPageSize+1 }} - {{ Math.min(logsPage*logsPageSize, logsTotal) }} 条,共 {{ logsTotal }} 条 ⟳ 刷新中... ~ 今天 近7天 本周 近30天 本月 ⚡精确匹配模型 搜索 📊 性能 🔑 Key健康 重置 刷新
☰ 拖动排序 · 勾选显示(自动保存) 恢复默认
☰ {{ c.label }} 📌
共 {{ logsTotal }} 条 · 第 {{ logsPage }} 页 / 共 {{ logsTotalPages }} 页 上一页 下一页
请求统计 ⟳ 刷新中...
{{ statsLoading ? '刷新中...' : '刷新' }}
{{ requestStats.total || 0 }}
总请求数
{{ requestStats.success || 0 }}
成功
{{ requestStats.error || 0 }}
失败
{{ Object.keys(requestStats.by_ip || {}).length }}
独立IP数
{{ requestStats.unauthorized_total || 0 }}
⚠️ 未授权访问

⚠️ 异常请求(未授权访问)这些IP尝试访问你的API但Key验证失败,可能是扫描/暴力破解

IP分布统计 点击IP可跳转到操作日志查看详情

模型分布统计 点击模型名可跳转到请求日志查看详情

共 {{ operationLogsTotal }} 条 ⟳ 刷新中... 全部 ⚠️ 异常 🔐 登录 ⚙️ 配置 🏢 供应商/模型 🚫 IP封禁
{{ operationLogsLoading ? '刷新中...' : '刷新' }}
系统资源概览 刷新
{{ sysStatsError }}
当前共 {{ (cardCleanType === 'request' ? sysStats.pg.request_logs?.rows : sysStats.pg.operation_logs?.rows)?.toLocaleString() || 0 }} 条 / {{ cardCleanType === 'request' ? sysStats.pg.request_logs?.size_human : sysStats.pg.operation_logs?.size_human }} · 最近数据完好保留,仅删超出保留期的
删 {{ cardCleanPct }}%
留 {{ 100 - cardCleanPct }}%
橙 = 将被清理 蓝 = 保留
将删除 {{ cardCleanPreview.cutoff }} 之前的:
⚠ 删除后不可恢复;供应商 / 模型 / 配置等数据完全不受影响。
统计窗口 ⟳ 刷新
统计窗口 ⟳ 刷新
该模型近{{ healthHours }}小时无请求记录(或日志无 key 信息)
{{ k.api_key }}
{{ k.total.toLocaleString() }}次 {{ gp.total ? (k.total/gp.total*100).toFixed(1) : 0 }}% {{ k.avg_ms > 0 ? (k.avg_ms/1000).toFixed(1)+'s' : '-' }} {{ k.success_rate }}% 样本少
横条=该Key请求占比 · 颜色=耗时档位 · 百分比=成功率
统计窗口 供应商 只看有问题的 只看冷却中 ↺ 重置筛选 ⟳ 刷新
{{ keysHealthWindowLabel }}无请求记录(或日志无 key 信息)
点击任意行可下钻查看该Key映射的模型表现与完整报错 · 成功率配色:🟢≥95% 🟡70~95% 🔴<70%
供应商 Key 总次 成功率 平均耗时 模型数 冷却 常见报错 处置
{{ r.provider }} {{ r.api_key }} {{ r.total.toLocaleString() }} {{ r.success_rate }}% {{ r.avg_ms > 0 ? (r.avg_ms/1000).toFixed(1)+'s' : '-' }} {{ r.model_count }} ⏳ {{ keyCooldownInfo(r).code }} · {{ keyCooldownInfo(r).remaining_secs }}s— {{ keyErrorsText(r) }} 详情 {{ keyIsDisabled(r) ? '启用' : '禁用' }}
{{ keysHealthDisabledExpanded ? '▼' : '▶' }} 📁 已禁用 {{ keysHealthDisabledRows.length }} 个 Key 成功率 {{ keysHealthDisabledSummary }} · 点击{{ keysHealthDisabledExpanded ? '收起' : '展开' }}
共 {{ keysHealthActiveRows.length + keysHealthDisabledRows.length }} 个 Key · 启用 {{ keysHealthActiveRows.length }} 个 · 禁用 {{ keysHealthDisabledRows.length }} 个 · 单击行=下钻详情
🏢 {{ keyDetailRow.provider }} {{ keyDetailRow.api_key }} 总 {{ keyDetailRow.total.toLocaleString() }} 次 成功率 {{ keyDetailRow.success_rate }}% 平均 {{ keyDetailRow.avg_ms>0 ? (keyDetailRow.avg_ms/1000).toFixed(1)+'s' : '-' }} ⏳ 冷却中 {{ keyCooldownInfo(keyDetailRow).code }} · 剩余 {{ keyCooldownInfo(keyDetailRow).remaining_secs }}s
① 映射模型表现(此Key在这些模型上的成功率)
模型 总次 成功率
{{ m.model }} {{ m.total.toLocaleString() }} {{ m.success_rate }}%
无模型明细
② 近期常见报错
×{{ e.count }} {{ e.message }}
该窗口内无错误记录
{{ keyIsDisabled(keyDetailRow) ? '🔄 启用此Key' : '🚫 禁用此Key' }} ❌ 只看此Key日志 🧊 手动冷却60s 🔥 解除冷却 {{ keyIsDisabled(keyDetailRow) ? '当前已禁用' : '当前启用中' }} · 禁用后跨所有模型全局生效 · 冷却 {{ keyCooldownInfo(keyDetailRow) ? keyCooldownInfo(keyDetailRow).cooldown_count : 0 }} 次 / 累计 {{ keyCooldownInfo(keyDetailRow) ? Math.round(keyCooldownInfo(keyDetailRow).total_cooldown_seconds/60) : 0 }} 分钟
📊 整体
近 {{ healthLoading ? '刷新中...' : '刷新' }}
📈 平均耗时趋势 (秒)
📊 可用率趋势 (成功率%)
⚡ 首Token延迟趋势 (秒, 需积累新日志)
🗂 异常桶 (近{{ healthHours }}小时÷6桶)
供应商性能对比 (近{{ healthHours }}小时, 点击行下钻该供应商)
🧮 模型×供应商性能矩阵 (行=模型点击下钻, 列=供应商点击表头下钻, 色块=平均耗时: 绿≤3s / 黄3-10s / 红>10s, 按请求数取Top30模型)
暂无数据(需先有请求日志积累,点上方刷新拉取)
模型 \ 供应商 {{ p }} 合计
{{ row.model }} {{ row.cells[p] && row.cells[p].total ? (row.cells[p].avg_ms > 0 ? (row.cells[p].avg_ms/1000).toFixed(1) + 's' : '-') : '·' }} {{ row.total }}次
请求数
{{ healthProviderDetail.total.toLocaleString() }}
成功率
{{ healthProviderDetail.success_rate }}%
平均耗时
{{ healthProviderDetail.avg_ms > 0 ? (healthProviderDetail.avg_ms/1000).toFixed(1) + 's' : '-' }}
单token耗时
{{ healthProviderDetail.ms_per_tok > 0 ? healthProviderDetail.ms_per_tok.toFixed(2) + 'ms' : '-' }}
首Token
{{ healthProviderDetail.avg_ftt_ms > 0 ? (healthProviderDetail.avg_ftt_ms/1000).toFixed(3) + 's' : '-' }}
状态
健康 波动 异常
该供应商下模型表现 (点击行下钻该模型)
📈 该模型近{{ healthHours }}小时趋势 (柱状=请求量按供应商堆叠, 柱顶=总请求数)
折线指标 显示数值
📊 各时间段 × 供应商表现 (单元格=成功率色块+平均耗时+请求数, 横向对比快慢, 纵向看稳定性; 点击单元格查该供应商日志)
时间段 {{ pv.name }}
{{ row.hour }}
{{ cell.rate }}% {{ (cell.avg_ms/1000).toFixed(1) }}s {{ cell.total }}次
-
成功率≥95% 70%-95% <70% 💡 点击任意单元格 → 直接跳该供应商+时段的请求日志
统计窗口 基于 request_logs 的 vision_time_ms(真实调用,缓存命中不计) ⟳ 刷新
时间段 × 模型 明细 (单元格=成功率底色+平均耗时+请求数,点单元格查日志)
时间段 {{ c }}
{{ row.hour }}
{{ row.cells[c].rate }}%
{{ (row.cells[c].avg_ms/1000).toFixed(1) }}s {{ row.cells[c].total }}次
-
暂无数据(需有带 vision_time_ms 的请求日志)
≥95% 70-95% <70% 耗时配色复用 timeCostStyle:绿≤10s / 浅绿10-25s / 黄25-50s / 红50-100s / 深红>100s
{{ errorDetailContent }}