AI 大模型平台

AI 大模型平台

image

一、项目定位

这是一个面向企业内部业务的多模型统一接入平台。

平台向上提供统一的聊天、图片生成和后台调试能力,向下接入多个模型供应商,并在中间完成:

  • 统一请求协议;
  • 模型与供应商路由;
  • Prompt、知识库和业务配置组装;
  • 流式与非流式响应适配;
  • API Token 与后台 SSO 鉴权;
  • RPM、TPM 限流;
  • Token、模型和知识库成本计算;
  • 调用日志、余额扣减和额度同步;
  • Token 级用量事件上报,以及面向外部分析服务的可观测数据沉淀。

平台的核心目标可以概括为:

让业务系统只面对一个稳定的 AI 服务入口,把不同模型供应商的协议差异和治理逻辑收敛到平台内部。

平台同时保留两类数据出口:一类服务于平台自身的配置、调用日志、余额和额度管理;另一类将标准化的 Token 用量、费用和调用质量事件异步提交给外部用量与可观测服务,由外部服务消费 Kafka 消息并写入 ClickHouse,支撑跨业务分析、报表和观测查询。

二、为什么需要统一接入

平台接入的模型能力并不来自单一厂商,覆盖 Qwen、DeepSeek、豆包/火山引擎、OpenAI 兼容接口、GPT-5.4、Gemini、Claude、华为云以及内部模型等多类模型和服务来源。

这些模型在以下方面存在差异:

  • 请求地址和认证方式不同;
  • 模型名称和供应商标识不一定一致;
  • 深度思考参数命名不同;
  • 流式输出和增量输出规则不同;
  • Token usage 返回结构存在差异;
  • 部分模型支持的请求模式不同;
  • 不同模型的输入、输出和缓存价格不同。

如果由每个业务系统直接对接模型供应商,业务系统就会逐渐承担大量供应商判断、参数转换和异常处理。平台将这些共性问题集中处理,业务系统只需要按照统一接口提交请求。

三、总体架构

平台整体可以按七个层次理解:

  1. 接入层:处理 HTTP 路由、请求协议、响应类型和后台调试入口。
  2. 安全与治理层:处理 API Token、后台 SSO、服务状态、余额和限流。
  3. 应用编排层:处理业务配置、Prompt、知识库、模型选择和请求生命周期。
  4. 底层传输层:处理 HTTP JSON、SSE、连接管理、超时、取消、事件分帧和完整响应聚合。
  5. 模型适配层:处理供应商路由、参数转换、供应商响应和 usage 归一化。
  6. 基础设施层:提供 Redis、MySQL、配置中心、服务注册、监控和告警。
  7. 外部用量与可观测服务:接收平台上报的标准化用量事件,通过 Kafka 解耦接入与消费,再将数据写入 ClickHouse。
flowchart LR subgraph Platform["多模型统一接入平台"] direction TB subgraph Access["接入层"] ChatAPI["chat/completions"] ImageAPI["图片生成接口"] AdminAPI["后台管理与调试接口"] end subgraph Security["安全与治理层"] Auth["鉴权与身份上下文"] Validate["业务、模型、版本校验"] Limit["RPM / TPM 限流"] Balance["余额与服务状态检查"] end subgraph Application["应用编排层"] Relay["聊天请求编排"] Chat["后台会话与配置保存"] ImageRelay["图片请求编排"] Prompt["Prompt 与业务变量"] Wiki["知识库检索与结果注入"] Usage["usage、费用与用量事件"] end subgraph Transport["底层传输层"] ChatHTTP["聊天 HTTP<br/>非流式 JSON"] ChatSSE["聊天 SSE<br/>流式事件"] ImageHTTP["图片 HTTP<br/>请求 / 响应"] Conn["连接管理<br/>超时 / 取消 / 重试边界"] end subgraph Adapter["模型适配层"] ChatRoute["聊天模型路由"] ImageRoute["图片模型路由"] Normalize["参数与响应归一化<br/>usage / 图片结果"] Providers["供应商适配组件<br/>Qwen / DeepSeek / Doubao / OpenAI<br/>GPT / Gemini / Claude / Huawei"] end subgraph Infra["平台基础设施"] Redis["Redis / Lua / 分布式锁"] DB["MySQL / 持久化存储"] Config["Apollo / Eureka / 应用配置"] Monitor["监控与飞书告警"] end ChatAPI --> Auth ImageAPI --> Auth AdminAPI --> Auth Auth --> Validate --> Limit --> Balance Balance --> Relay Balance --> Chat Balance --> ImageRelay Relay --> Prompt Relay --> Wiki Relay --> ChatRoute Chat --> ChatRoute ImageRelay --> ImageRoute ChatRoute --> ChatHTTP ChatRoute --> ChatSSE ImageRoute --> ImageHTTP ChatHTTP --> Conn ChatSSE --> Conn ImageHTTP --> Conn Conn --> Providers --> Normalize Relay --> Usage Chat --> Usage ImageRelay --> Usage Limit --> Redis Usage --> Redis Usage --> DB Validate --> DB Application -.-> Config Usage -.-> Monitor end subgraph External["外部用量与可观测服务"] UsageTopic["Kafka 用量事件主题"] UsageConsumer["用量消费与分析服务"] ClickHouse["ClickHouse<br/>Token / 费用 / 延迟 / 错误"] UsageTopic --> UsageConsumer --> ClickHouse end Usage -. "异步上报标准化用量事件" .-> UsageTopic

四、技术分层设计

4.1 接入层

接入层只负责协议边界和请求进入,不承担具体的供应商调用逻辑。

平台对外提供几类统一入口:

入口类型 作用
聊天入口 接收统一聊天请求,支持流式和非流式返回
兼容入口 兼容 OpenAI 风格的调用协议
图片入口 接收图片生成和图片编辑请求
后台调试入口 支持模型调试、历史管理和配置保存

接入层的职责是完成请求解析、响应类型选择、HTTP JSON 或 SSE 响应封装、图片结果返回和异常边界处理,然后把请求交给后续的治理与编排流程。

4.2 对外 Chat Completions 接口

平台对外的核心聊天入口是:

POST /v{version}/chat/completions

它采用接近 OpenAI Chat Completions 的调用方式,业务系统可以使用统一的消息结构提交请求,不需要直接适配每一家模型供应商。

一次调用通常包含以下信息:

  • model:业务希望使用的模型标识;
  • messages:系统、用户、助手等多轮消息;
  • stream:是否采用流式返回;
  • temperature、top_p、max_tokens 等通用参数;
  • 深度思考、思考预算等能力参数;
  • 业务变量、知识库和 Prompt 选择信息。

平台不会简单地把请求原样转发出去,而是会在统一入口完成一次完整的请求组装:

  1. 识别调用方和业务服务;
  2. 根据版本和服务配置确定生效配置;
  3. 查询当前绑定的模型、Prompt、知识库和限流策略;
  4. 将请求参数与平台配置合并;
  5. 根据供应商和模型能力转换专属参数;
  6. 选择对应的模型适配组件;
  7. 以统一格式返回结果和 usage 信息。

4.3 Chat Completions 的版本与兼容

接口中的版本号主要用于兼容不同阶段的请求和响应约定。平台可以在统一入口下保留不同版本的返回包装,同时让底层模型调用、计费和治理逻辑保持一致。

为了降低接入成本,平台还提供兼容模式,使已经按照 OpenAI 风格开发的业务系统可以较少改造地接入平台。业务方主要关注:

  • 请求地址;
  • API Token;
  • 模型名称;
  • 消息列表;
  • 是否流式;
  • 需要覆盖的通用参数。

供应商 endpoint、API Key、深度思考字段、流式事件结构和实际计费规则由平台内部处理。

4.4 底层传输层:HTTP、SSE 与图片传输

底层传输层位于请求编排和供应商适配之间,负责把统一模型请求转换为具体的网络交互。它需要同时承接两类聊天传输方式和一类图片传输方式:

场景 对外返回 下游交互 传输层重点
聊天非流式 HTTP JSON 完整响应 HTTP 请求、等待完整响应 响应聚合、状态码、超时、错误体和 usage 解析
聊天流式 SSE 增量事件 HTTP 长连接或 SSE 增量响应 事件分帧、增量转换、heartbeat、断连、取消和结束事件
图片生成/编辑 HTTP JSON 图片结果 HTTP JSON 请求/响应 图片参数、输入图片、结果 URL 或图片数据、尺寸与图片数量

这里需要区分两个方向的协议:

  • 平台对外协议:聊天非流式返回 JSON,聊天流式返回 SSE,图片返回图片结果 JSON;
  • 平台对下游协议:由供应商适配层和传输层共同决定,可能是普通 HTTP JSON,也可能是供应商自定义的 SSE 或任务式图片接口。

传输层不负责决定使用哪一家模型,也不负责价格规则。它重点管理连接生命周期和数据边界:

  • 连接建立、读取、写入和超时;
  • HTTP 状态码、响应头和错误体;
  • SSE 字节流的事件分帧与结束标记;
  • 客户端断连后的取消传播;
  • 下游异常、响应截断和重试边界;
  • 完整响应与流式响应最终都汇总为统一结果,交给 usage、计费、日志和可观测链路。
flowchart TB Request["统一模型请求"] --> Choice{"传输模式"} Choice -->|"聊天 stream=false"| ChatHTTP["聊天 HTTP 非流式"] ChatHTTP --> FullRequest["HTTP 请求"] FullRequest --> FullResponse["完整 JSON 响应"] FullResponse --> ChatResult["统一聊天结果"] Choice -->|"聊天 stream=true"| ChatSSE["聊天 SSE 流式"] ChatSSE --> StreamRequest["HTTP 长连接请求"] StreamRequest --> Decode["SSE 解码与事件分帧"] Decode --> Delta["增量内容转换"] Delta --> SSEOutput["向业务方持续返回 SSE"] Decode --> StreamEnd["结束事件与最终 usage"] StreamEnd --> ChatResult Choice -->|"图片生成 / 编辑"| ImageHTTP["图片 HTTP 请求 / 响应"] ImageHTTP --> ImageRequest["JSON 与图片输入"] ImageRequest --> ImageResponse["图片结果 JSON"] ImageResponse --> ImageResult["统一图片结果"] ChatResult --> Final["usage / 费用 / 日志 / 用量事件"] ImageResult --> Final Conn["连接管理<br/>超时 / 取消 / 错误边界"] -.-> ChatHTTP Conn -.-> ChatSSE Conn -.-> ImageHTTP

聊天非流式和流式请求最终会汇聚到同一条 usage 与治理链路;图片请求则使用独立的图片结果归一化和图片计费逻辑,不进入聊天 SSE 事件链路。

4.5 安全与身份层

平台存在两种主要身份体系。

对外 API 调用:

  1. 通过 API Token 识别调用方;
  2. 查询调用方对应的业务服务;
  3. 校验业务服务状态和调用权限;
  4. 建立本次请求的业务身份;
  5. 将身份信息传递给配置、限流、扣费和日志流程。

后台管理与调试:

  1. 通过企业统一身份体系完成 SSO 认证;
  2. 校验后台用户身份和操作权限;
  3. 建立当前调试人员的身份上下文;
  4. 将用户身份传递给调试、会话和配置保存流程。

这样可以将身份认证与业务处理分离,后续流程只需要使用已经确认的调用方或后台用户身份。

sequenceDiagram autonumber participant C as 调用方 participant I as 身份认证层 participant Auth as Token / SSO 校验 participant DB as 业务服务配置 participant R as 统一入口 participant S as 请求编排层 C->>I: 提交请求 alt 对外 API I->>I: 读取 API Token I->>Auth: 识别调用方 Auth->>DB: 查询业务服务与状态 DB-->>Auth: 返回业务身份 else 后台管理 I->>I: 读取 SSO Token I->>Auth: 校验后台用户 Auth-->>I: 返回用户身份 end I->>I: 写入请求上下文 I->>R: 建立身份上下文 R->>S: 进入请求编排 S-->>C: 返回统一响应或 SSE

4.6 应用编排层

应用编排层是主聊天链路的核心。它不直接实现某一家厂商的 HTTP 协议,而是负责组织一次请求的完整生命周期:

  • 根据 Token 和版本读取业务配置;
  • 校验服务是否上线;
  • 检查 RPM、TPM 和余额;
  • 合并请求参数与已保存配置;
  • 处理 Prompt、业务变量和多 Prompt;
  • 根据配置调用知识库;
  • 计算并设置厂商相关的基础参数;
  • 选择底层模型适配组件;
  • 根据 stream 和模型类型选择聊天 HTTP、聊天 SSE 或图片 HTTP 传输;
  • 处理流式或非流式返回;
  • 触发费用计算;
  • 保存调用日志并同步额度;
  • 生成包含 Token、费用、延迟、状态和错误信息的标准化用量事件,并异步上报给外部用量与可观测服务。

后台链路负责会话历史、后台调试和模型配置保存。图片链路独立编排,再通过图片模型路由选择供应来源。

4.7 模型抽象与供应商适配层

平台提供统一的模型抽象:

  • 统一消息结构;
  • 文本、图片和多图片 Prompt;
  • 通用模型参数;
  • 模型连接配置;
  • 统一响应对象;
  • 流式响应监听;
  • 图片输入与图片结果结构。

模型适配层负责供应商路由、参数转换、响应解析和 usage 协作;底层传输层负责 HTTP、SSE 以及连接生命周期。费用计算和用量事件生成使用统一的结果,不要求业务侧感知每个供应商的返回差异。

每个供应商适配器只关注自身协议:

  • Qwen;
  • DeepSeek;
  • 豆包/火山引擎;
  • OpenAI/GPT;
  • Gemini;
  • Claude;
  • 华为云;
  • 内部模型。

上层只依赖统一的模型调用能力,供应商差异集中在适配层内部。

五、数据与持久化设计

平台的数据设计围绕“配置可复用、调用可追踪、费用可结算、用量可观测”展开。平台本地持久化配置、调用日志和额度等业务事实;Token 用量、费用、延迟和错误等分析型数据,则通过标准化事件提交给外部用量与可观测服务,由该服务写入 ClickHouse。

5.1 核心数据域

数据域 主要内容 作用
业务服务 服务身份、状态、额度、告警阈值、管理员 识别调用方并承载资源与费用归属
服务版本配置 服务与模型的关联、版本、上线状态、RPM、TPM 决定某个业务版本实际使用什么能力
模型目录 模型名称、供应商、模型类型、模型代码、能力标识 为路由、参数兼容和价格计算提供依据
助手与 Prompt 配置 系统 Prompt、通用参数、深度思考设置、知识库设置 形成一次调用的默认配置
多 Prompt 配置 Prompt 版本、匹配条件、业务变量 支持同一个服务按业务条件选择不同 Prompt
知识库配置 知识库、检索策略、重排策略和关联关系 决定是否执行检索增强
会话与消息 调试主题、历史消息、模型关联、配置关联 支持后台调试和会话历史
调用日志 请求状态、输入输出 Token、缓存 Token、费用、耗时、错误 支撑计费、监控、问题定位和运营分析
额度与充值 剩余额度、已使用额度、充值记录、余额阈值 支撑业务服务的资金和资源管理
用量事件 请求标识、业务服务、供应商、模型、Token、费用、延迟、状态、错误 上报外部用量与可观测服务,支撑统计分析和报表

5.2 配置关系

一次对外调用并不是直接查询一个模型名称,而是沿着业务服务的配置关系找到最终能力:

flowchart LR A["调用方"] --> B["业务服务"] B --> C["生效版本"] C --> D["模型目录"] C --> E["Prompt 与通用参数"] E --> F["知识库与业务变量"] D --> G["供应商适配"] E --> G F --> G G --> H["模型调用"] H --> I["usage 解析与费用计算"] I --> J["本地调用日志与额度"] I --> K["标准化用量事件"] K --> L["外部用量与可观测服务"] L --> M["ClickHouse 分析存储"]

这种关系把“谁在调用”“调用哪个版本”“使用什么模型”“采用什么 Prompt”和“产生多少费用”串联起来。平台本地数据用于请求治理和额度控制,外部分析数据用于跨业务的 Token 用量、费用、延迟、错误率和供应商质量分析。

5.3 MySQL 与 Redis 的职责

MySQL 负责持久化事实:

  • 业务服务和服务版本;
  • 模型目录和供应商配置;
  • Prompt、知识库和业务变量;
  • 会话、消息和调试配置;
  • 调用日志、Token 和费用;
  • 额度、充值和告警相关数据。

Redis 负责高频运行状态:

  • RPM 滑动窗口;
  • TPM Token 桶;
  • 分布式锁;
  • 待同步额度标记;
  • 告警冷却和短期缓存。

可以将两者理解为:

  • MySQL 保存可以长期查询和审计的业务事实;
  • Redis 保存需要高频读写、原子控制和跨实例共享的运行状态。
  • ClickHouse 保存外部用量与可观测服务消费后的分析型数据,不参与平台请求入口的同步鉴权、限流和余额判断。

5.4 额度数据的落账过程

模型调用完成后,平台先根据真实 usage 计算费用并写入调用记录,再由额度同步流程聚合同一业务的待同步费用,更新业务服务的剩余额度和已使用额度。

这种设计将模型响应链路与数据库额度更新拆开:

flowchart TB A["模型返回 usage"] --> B["计算 Token 与费用"] B --> C["写入调用日志"] C --> D["Redis 记录待同步状态"] D --> E["额度同步任务"] E --> F["聚合业务费用"] F --> G["更新持久化额度"] G --> H["标记日志已完成同步"] G --> I["触发余额告警"]

这样既能保留每次调用的明细,又能减少高频请求对持久化存储的直接更新压力。

5.5 Token 用量与可观测数据链路

平台在一次模型调用结束后,会基于供应商返回的 usage 形成标准化用量事件。事件既服务于费用分析,也服务于模型调用的可观测性,典型字段包括:

  • 请求标识、链路标识和业务服务标识;
  • 模型、供应商、版本和调用模式;
  • 输入 Token、输出 Token、缓存 Token、思考 Token;
  • Prompt 费用、Completion 费用、缓存费用和总费用;
  • 首 Token 延迟、总耗时、状态码和错误类型;
  • 是否流式、是否命中知识库、请求时间和结果状态。

这条链路由两个服务边界组成:

  1. 当前平台负责 usage 解析、费用计算、事件标准化和 Kafka 上报,同时继续完成本地调用日志与额度同步。
  2. 外部用量与可观测服务负责消费 Kafka 事件,并将数据写入 ClickHouse,提供 Token 用量统计、费用趋势、模型调用质量、供应商对比和运营报表。

Kafka 和 ClickHouse 属于外部用量与可观测服务的链路,不进入当前平台的同步请求路径。模型响应不需要等待 ClickHouse 写入完成,外部服务的消费延迟也不会直接阻塞 chat/completions 的响应。

flowchart LR A["模型调用结束"] --> B["解析 usage"] B --> C["费用计算"] C --> D["生成标准化用量事件"] D --> E["Kafka"] E --> F["外部用量与可观测服务"] F --> G["ClickHouse"] G --> H["Token 用量统计"] G --> I["费用分析与报表"] G --> J["延迟、错误与供应商质量分析"] C --> K["本地调用日志"] C --> L["本地额度同步"]

从架构职责上看,本地调用日志和外部分析数据承担不同目标:

数据出口 主要目标 典型用途
平台本地日志与额度 请求治理、余额控制和单次调用追踪 余额检查、额度同步、问题定位
Kafka 用量事件 跨服务传递标准化事实 解耦模型调用与分析消费
ClickHouse 分析数据 高并发明细查询和聚合分析 Token 统计、费用报表、延迟分析、错误分析、供应商对比

事件上报需要围绕事件唯一标识、消费幂等、失败重试、积压监控和异常补偿建立运行保障。具体重试次数、死信策略和对账周期由外部用量与可观测服务负责配置。

六、多模型、多供应商接入

6.1 路由优先级

平台的聊天模型路由采用“供应商标识优先、模型名称兜底”的策略。

当请求带有明确的 brand 时,优先按供应商路由。例如:

  • brand=doubao 路由到豆包适配组件;
  • brand=huawei 路由到华为适配组件;
  • brand=shihuo 路由到内部模型适配组件;
  • brand=minimax 根据部署关系路由到对应适配组件。

当没有明确的供应商标识时,再根据模型名称选择适配组件,例如:

  • qwen*、qvq*、glm*、minimax*;
  • deepseek*;
  • ep-*;
  • gemini*;
  • claude*;
  • gpt-5.4*。

OpenAI 兼容接口还会根据 GPT 模型系列选择不同的 endpoint 和 API Key 配置。

flowchart LR A["统一业务请求"] --> B{"是否存在供应商标识"} B -->|"是"| C["按供应商标识路由"] B -->|"否"| D["按模型名称兜底路由"] C --> E["Qwen / DeepSeek / Doubao"] C --> F["Huawei / Shihuo / 其他"] D --> G["Gemini / Claude / GPT"] D --> H["Qwen / DeepSeek / ep-*"] E --> I["供应商适配器"] F --> I G --> I H --> I I --> J["统一响应"]

6.2 供应商能力兼容

业务侧表达的是统一能力,适配层再转换为供应商参数。

平台已覆盖的典型差异包括:

能力 供应商差异 平台处理
深度思考 有的使用 enable_thinking,有的使用 thinking.type 统一 deep 意图,按品牌生成请求字段
思考预算 Qwen、DeepSeek 等模型支持思考预算 从统一请求读取 thinking_budget,传给对应适配组件
流式输出 不同供应商的 SSE 字段和结束事件不同 由适配组件解析后向上层输出统一流式结果
增量输出 部分模型需要额外打开 incremental_output 在供应商专属参数中转换
usage 信息 流式 usage 位置和字段可能不同 由适配组件汇总为统一 usage
非流式限制 部分模型对 stream=false 或字段组合有特殊限制 在基础参数配置和供应商适配组件中处理

例如,统一的深度思考开关可能转换为:

flowchart LR A["业务请求<br/>开启深度思考"] --> B["统一请求模型"] B --> C["供应商参数归一化"] C --> D["Qwen / DeepSeek<br/>enable_thinking<br/>incremental_output<br/>stream"] C --> E["Doubao / Huawei<br/>thinking.type=enabled"] C --> F["其他供应商<br/>专属字段与限制"] D --> G["供应商请求体"] E --> G F --> G G --> H["模型调用"] H --> I["统一响应 + usage"]

这里的关键不是把每个厂商的字段暴露给业务方,而是保留供应商专属参数对象,同时在公共请求层完成能力归一化。

6.3 图片模型的独立路由

文本聊天和图片生成没有共用同一套调用协议:

  • 聊天使用独立的聊天模型路由;
  • 聊天非流式使用完整 HTTP JSON 响应,流式使用 SSE 增量事件;
  • 图片使用独立的图片模型路由和图片 HTTP 传输;
  • 图片请求可以携带文本 Prompt、单张或多张输入图片,返回图片结果 JSON;
  • 图片结果需要单独解析生成数量、输入图片数量、尺寸和结果状态;
  • 图片费用由独立的图片计费逻辑处理;
  • 图生或图编辑模型不进入后台 Chat 对话链路。

这种拆分避免文本流式协议、文本完整响应和图片结果处理相互污染。对于部分供应商可能采用的异步图片任务接口,可以在图片传输层扩展“任务提交、状态查询和结果获取”,而不改变上层图片请求模型。

七、一次聊天请求的完整链路

sequenceDiagram autonumber participant C as 业务系统 participant A as 身份认证层 participant R as 统一聊天入口 participant S as 请求编排层 participant G as 配置与模型信息 participant L as Redis 限流 participant W as 知识库 participant F as 聊天模型路由 participant T as 底层传输层 participant P as 供应商适配组件 participant M as 模型供应商 participant B as 计费模块 participant D as 日志与额度 participant E as 用量事件生产 participant K as 外部 Kafka participant O as 外部用量与可观测服务 participant CH as ClickHouse C->>A: Authorization + 聊天请求 A->>R: 建立调用方身份 R->>S: 进入请求编排 S->>G: 查询业务版本、模型、Prompt、参数 S->>L: RPM / TPM 预检查 L-->>S: 允许或拒绝 S->>S: 合并请求参数与服务配置 opt 配置了知识库 S->>W: 检索相关内容 W-->>S: 返回内容与知识库费用 S->>S: 注入消息或系统 Prompt end S->>F: 根据供应商 / 模型选择适配组件 alt 非流式聊天 F->>T: 选择 HTTP JSON T->>P: 发送完整请求 P->>M: 调用模型供应商 M-->>P: 返回完整响应与 usage P-->>T: 统一完整结果 T-->>S: JSON 响应 S-->>C: JSON 返回 else 流式聊天 F->>T: 选择 SSE 传输 T->>P: 建立流式请求 P->>M: 调用模型供应商 M-->>P: 返回增量事件 P-->>T: 转换增量内容 T-->>S: SSE 增量结果 S-->>C: SSE 实时返回 M-->>P: 返回结束事件与 usage P-->>T: 汇总最终 usage end S->>B: 根据 usage 计算费用 B-->>S: prompt / completion / cache / wiki / total cost S->>D: 保存调用日志 D->>D: Redis 扣减记录与额度同步 S->>E: 生成 Token 用量与调用质量事件 E->>K: 异步提交用量事件 K-->>O: 消费用量事件 O->>CH: 写入分析型明细

请求编排中有一个重要顺序:

  1. 先完成身份、服务状态和配置校验;
  2. 再执行 RPM、TPM 和余额检查;
  3. 再组装 Prompt、知识库和最终请求;
  4. 调用模型并拿到真实 usage;
  5. 基于 usage 计算成本;
  6. 保存本地日志并进入额度同步流程;
  7. 异步生成用量事件,提交外部 Kafka,由外部用量与可观测服务写入 ClickHouse。

这样做可以让鉴权、限流、调用、扣费和用量观测各自承担清晰职责。外部用量数据的落库延迟不会改变模型响应的同步协议。

八、后台调试与配置保存

平台提供后台 Chat 调试入口,后台用户可以在真实的模型配置下进行对话验证。

后台调试链路支持:

  • 后台会话调试;
  • 流式结果展示;
  • 聊天历史查询;
  • 历史清除与复制;
  • Prompt、业务变量和知识库验证;
  • 深度思考参数验证;
  • 将调试结果保存为模型与业务配置。

配置保存不是简单覆盖一个字段。保存时会比较当前配置与已有配置,涉及:

  • 模型参数;
  • Prompt 模式;
  • 多 Prompt 配置;
  • 知识库配置;
  • 业务变量。

配置发生变化时创建新的设置并重新关联;未发生变化时继续复用已有设置,减少重复配置。

flowchart LR A["后台 SSO 鉴权"] --> B["Admin Chat 调试"] B --> C["模型 + Prompt + 知识库 + 业务变量"] C --> D["流式验证"] D --> E{"是否调整配置"} E -->|"是"| C E -->|"否"| F["比较已有配置"] F --> G{"配置是否变化"} G -->|"变化"| H["创建新配置版本并关联"] G -->|"未变化"| I["复用已有配置"] H --> J["业务接口调用"] I --> J

九、限流与余额控制

9.1 RPM 限流

平台使用 Redis Lua 脚本实现滑动窗口 RPM 限流:

  • 按业务 Token 生成限流 Key;
  • 清理窗口外的请求;
  • 原子增加当前请求;
  • 返回当前窗口请求数量;
  • 超过阈值时拒绝请求或进入告警模式。

9.2 TPM 限流

TPM 限流以请求预估 Token 和模型配置中的 TPM 为依据:

  • 请求进入时预估本次 Token 数;
  • Redis Lua 脚本尝试占用 Token 配额;
  • 调用完成后根据真实 usage 更新 Token 桶;
  • 通过 Redis 保证多实例之间的共享状态。

9.3 余额检查

调用模型前会检查业务服务余额。余额不足时直接阻断请求,并可以触发余额告警。

余额检查和 RPM/TPM 限流是两个独立维度:

  • RPM / TPM 控制调用速率和资源峰值;
  • 余额控制业务服务是否具备继续调用的资金或额度。

十、计费、Token 用量与可观测性

10.1 费用组成

模型调用结束后,平台从供应商响应中提取 usage,并按照模型和品牌配置计算:

  • Prompt Token 费用;
  • Completion Token 费用;
  • 缓存命中 Token 费用;
  • 深度思考模式下的费用差异;
  • 知识库或重排产生的附加费用;
  • 最终总费用。

计费模块负责将费用写回统一响应的 usage 字段,平台本地调用日志保存对应的 Token 和费用信息,同时生成标准化用量事件,提交给外部用量与可观测服务。

flowchart TB A["供应商响应 usage"] --> B["提取 prompt_tokens"] A --> C["提取 completion_tokens"] A --> D["提取 cached_tokens"] A --> E["读取 deep / brand / model"] E --> F["价格规则计算"] B --> F C --> F D --> F F --> G["prompt_cost"] F --> H["completion_cost"] F --> I["cached_tokens_cost"] J["知识库费用"] --> K["total_cost"] G --> K H --> K I --> K F --> K K --> L["统一 usage"] L --> M["调用日志"]

10.2 额度同步

当前额度扣减采用“调用日志记录 + Redis 状态 + 定时同步数据库”的方式:

  1. 请求完成后,日志记录实际 Token 和 total cost;
  2. 日志进入待同步状态;
  3. Redis 记录待同步标记,减少重复触发;
  4. 额度同步模块聚合同一业务的未同步费用;
  5. 使用分布式锁避免多实例重复同步;
  6. 更新 MySQL 中的剩余额度和已使用额度;
  7. 将日志标记为已同步;
  8. 余额低于阈值时发送告警。

这个设计把高频调用路径和数据库额度更新解耦。调用链路优先完成模型响应和日志记录,额度同步通过批量聚合降低数据库更新压力。

sequenceDiagram autonumber participant P as 模型调用 participant B as 计费模块 participant L as 调用日志 participant R as Redis participant Q as 额度同步模块 participant DB as MySQL participant N as 告警服务 P-->>B: 返回 usage B->>B: 计算模型、Token、缓存和知识库费用 B-->>L: 写入 prompt / completion / total cost L->>R: 标记待同步 R-->>Q: 触发或等待同步任务 Q->>R: 获取分布式锁 Q->>L: 查询未同步日志 Q->>Q: 聚合同一业务费用 Q->>DB: 扣减 quota,增加 used_quota Q->>L: 标记日志已同步 Q->>N: 余额低于阈值时告警

10.3 外部用量上报与分析存储

本地额度同步解决的是平台内部的调用准入和余额管理;Token 级用量统计与跨业务可观测,则通过独立的数据链路完成。平台完成一次模型调用后,将调用结果整理为标准化事件,通过 Kafka 提交给外部用量与可观测服务。外部服务消费事件后写入 ClickHouse,形成面向分析的明细数据。

该链路覆盖的分析维度包括:

  • 按业务服务、版本、模型和供应商统计输入、输出、缓存和思考 Token;
  • 按时间窗口统计调用量、Token 量、费用和额度消耗趋势;
  • 观察首 Token 延迟、总耗时、流式完成率和异常率;
  • 对比不同供应商的成功率、响应时延和单位 Token 成本;
  • 支撑费用报表、用量排行、异常波动识别和对账分析。

平台侧与外部服务侧的职责边界如下:

sequenceDiagram autonumber participant P as 多模型统一接入平台 participant K as Kafka participant O as 外部用量与可观测服务 participant C as ClickHouse participant R as 统计与报表 P->>P: 解析 usage、计算费用、补充延迟与状态 P->>K: 发布标准化用量事件 K-->>O: 消费用量事件 O->>O: 校验、去重、补充分析维度 O->>C: 写入 Token / 费用 / 延迟 / 错误明细 R->>C: 查询聚合结果 C-->>R: 返回统计与报表数据

这条链路与模型响应保持异步关系:平台先完成统一响应、本地日志和额度处理,再将用量事件提交到 Kafka;外部服务负责消费和分析存储。为保证数据可用性,需要关注事件唯一标识、重复消费、消费积压、失败重试、异常补偿以及平台本地日志与 ClickHouse 数据的周期性对账。

十一、传输层与响应生命周期

平台的传输层需要同时保证三类请求的稳定性:

聊天非流式 HTTP:

  • 发送一次完整请求并等待供应商完整响应;
  • 校验 HTTP 状态码、响应体和错误信息;
  • 将完整 JSON 解析为统一聊天结果;
  • 记录总耗时、usage、费用和最终状态。

聊天流式 SSE:

  • 建立长连接并持续读取供应商事件;
  • 处理字节读取、事件分帧、增量内容转换和下游 SSE 推送;
  • 处理 heartbeat、客户端断连、取消传播和超时清理;
  • 在结束事件或连接结束后汇总最终 usage,再进入计费和日志流程。

图片 HTTP:

  • 以图片生成或图片编辑请求为独立协议;
  • 传递文本 Prompt、输入图片、尺寸、数量和图片特有参数;
  • 解析图片 URL、图片数据、生成数量、输入图片数量和结果状态;
  • 按图片数量、尺寸或 Token 规则完成独立计费;
  • 当前以同步 HTTP 请求/响应为主,供应商若采用异步任务式生成,可扩展任务提交、状态查询和结果获取。
flowchart TB A["统一请求"] --> B{"请求类型 / stream"} B -->|"聊天 + stream=false"| C["HTTP 非流式"] C --> D["完整响应读取"] D --> E["JSON 结果归一化"] B -->|"聊天 + stream=true"| F["SSE 流式"] F --> G["字节读取"] G --> H["事件分帧"] H --> I["增量内容转换"] I --> J["SSE 推送"] H --> K["结束事件 / 最终 usage"] B -->|"图片生成 / 编辑"| L["图片 HTTP"] L --> M["图片请求与输入处理"] M --> N["图片结果 JSON"] N --> O["图片结果归一化"] E --> P["统一结果处理"] K --> P O --> P P --> Q["本地日志 / 额度 / 费用"] P --> R["标准化用量事件"] R --> S["Kafka"] S --> T["外部用量与可观测服务"] T --> U["ClickHouse"] V["连接管理<br/>超时 / 取消 / 错误边界"] -.-> C V -.-> F V -.-> L

三类传输在结果处理阶段重新汇合,但不共用响应协议:聊天 SSE 负责增量事件,聊天 HTTP 负责完整 JSON,图片 HTTP 负责图片结果。这样可以把连接生命周期问题与业务编排、供应商价格规则和图片结果计费分别管理。

十二、平台技术特点

12.1 多供应商适配集中化

供应商适配组件、专属参数和参数转换位于公共模型适配层,上层业务编排不需要维护大量厂商分支。

12.2 业务配置与模型调用解耦

模型、Prompt、业务变量、知识库和供应商信息以配置方式组合,后台调试可以直接沉淀为可复用配置。

12.3 鉴权与业务逻辑分离

API Token、后台 SSO 和请求上下文由认证模块处理,业务编排模块可以直接使用已验证的业务身份。

12.4 限流与扣费分离

Redis Lua 负责高频限流和扣减状态,计费服务负责价格计算,额度同步服务负责数据库落账。

12.5 Token 用量与请求链路解耦

平台在模型调用完成后生成标准化用量事件,通过 Kafka 异步交给外部用量与可观测服务;ClickHouse 面向 Token、费用、延迟和错误数据提供分析存储。模型响应链路不直接依赖分析库写入,便于独立扩展统计和报表能力。

12.6 多协议传输统一治理

平台将 HTTP 非流式、SSE 流式和图片 HTTP 都纳入统一传输层治理。上层只表达请求类型和流式意图,底层负责连接、超时、取消、响应解析和错误边界;供应商适配层负责不同厂商的参数与结果差异。

12.7 文本与图片链路边界清晰

聊天和图片生成分别拥有自己的请求协议、编排流程和供应商适配边界,便于独立演进。

十三、总结

这个项目的技术核心不是简单封装一个模型接口,而是建立了一套多模型统一接入和治理链路:

统一入口
  -> 身份认证
  -> 业务与模型配置
  -> RPM / TPM / 余额检查
  -> Prompt 与知识库组装
  -> 多供应商路由
  -> 底层传输层选择
  -> HTTP 非流式 / SSE 流式 / 图片 HTTP
  -> usage 解析
  -> 费用计算
  -> 本地日志保存
  -> 本地额度同步与告警
  -> Kafka 用量事件上报
  -> 外部用量与可观测服务消费
  -> ClickHouse 分析存储

通过分层和适配器设计,新增模型供应商时主要扩展适配组件、配置和参数转换,不需要修改所有业务调用方;通过统一的治理链路,平台可以同时管理模型接入、调用安全、资源限制、实际成本和 Token 级用量可观测。

十四、说明范围

本文聚焦平台的技术架构、模型接入方式和治理链路。具体模型的可用能力、价格、服务地址和运行指标会随供应商及部署配置变化,实际使用时需要以平台配置和运行环境为准。

posted @ 2026-09-07 14:38  alin_qu  阅读(42)  评论(0)    收藏  举报