企业级AI中台架构设计:模型管理、服务编排与权限控制实战
2026/9/8 2:21:37 网站建设 项目流程

上个月帮一家企业做架构评审,我打开他们的“AI中台”目录时愣了一下:同一个BERT模型被复制成了七八份,命名靠日期后缀,有的在finetune之前,有的在finetune之后;更离谱的是,只要拿到内网IP和端口,任何服务都能直接调推理接口,完全没有鉴权。这不是个例,很多号称AI中台的项目,本质上只是把训练脚本和模型文件挪到了一块共享盘上。

这篇内容想聊的是,企业级AI中台架构设计里最容易被忽略、也最影响成败的三件事:模型管理、服务编排、权限控制。我会从架构设计角度拆开讲清楚每部分到底要解决什么问题,为什么必须这么做,以及在SpringBoot这类技术栈里落地时常见的坑。适合正在做中台建设的架构师、平台组工程师,以及打算引入AI能力但不想把业务代码搞成一团乱麻的技术负责人。

1. 大中台不是大杂烩:先划清AI中台的职能边界

1.1 中台与业务系统的三层关系

很多团队一提中台,就恨不得把能复用的东西全塞进去,最后中台变成了一个巨大的业务系统,改哪里都牵扯不清。AI中台首先要解决的是“边界”问题。

我习惯把系统分成三层:基础设施层、中台平台层、业务应用层。基础设施层提供GPU算力、存储、网络;中台平台层负责把模型变成可复用、可治理、可观测的服务;业务应用层则面向最终用户,实现具体的交互和业务逻辑。

AI中台应该收敛的是“模型全生命周期管理、服务化封装、服务编排、统一权限控制、监控审计”这些能力。它不应该替业务团队实现具体的规则逻辑,也不应该直接面向C端用户。把这个边界画清楚,后面所有的架构决策都会简单很多。

1.2 四个必须收敛的公共能力

我梳理过多个中台项目,能称得上“中台”的,至少要在平台层收敛四件事:

  • 模型注册与版本管理:所有模型必须在一个地方登记,有唯一标识、状态、版本、元数据。
  • 模型推理服务化:把模型包装成标准接口,调用方不关心模型是TensorFlow、PyTorch还是ONNX。
  • 服务编排与组合:多个模型服务可以按业务场景编排成一个流程,而不是让业务系统自己串。
  • 统一认证与权限控制:不管是人还是系统,调模型必须有身份、有授权、有审计。

这四件事缺了任何一件,中台都会退化成“共享盘”。

1.3 需要留在业务侧的边界

同样重要的是明确什么不能收进中台。业务特征极强的数据处理、业务规则、前端流程、会话状态管理,这些都应该留在业务应用层。

举个例子,知识库问答里的“文档解析规则”和“答案后处理”往往和业务强相关,如果你强行把它们下沉到中台,中台就得不断适配各种业务方的奇葩需求,最终变成开发瓶颈。我见过一个失败案例,中台团队花了两个月做了个通用文档解析器,结果上线后每个业务方都要加自己的解析规则,代码里全是if分支,远比让各业务方自己用解析SDK更糟糕。

核心原则:中台管模型,不管业务;管服务编排,不管界面流程;管权限模型,不替业务定义角色。

2. 模型管理:版本、血缘、评估和生命周期,缺一个后面都会还债

2.1 模型注册中心设计:一份元数据描述一个模型

模型管理的第一步,不是建文件夹,而是建注册中心。注册中心里每个模型都应该有唯一ID,关联一组不可变版本,版本下面再挂一份完整元数据。

一个最小可用的模型元数据大概长这样:

{ "model_id": "text-cls-bert", "model_name": "文本分类-BERT", "owner": "alg-platform", "versions": [ { "version": "1.3.0", "framework": "pytorch", "format": "torchscript", "artifact_path": "s3://models/text-cls-bert/1.3.0/model.pt", "sha256": "9f2c92...", "status": "prod", "input_schema": {"text": "string", "max_len": 128}, "output_schema": {"label": "int", "probability": "float"}, "train_metrics": {"acc": 0.967, "f1": 0.963}, "code_version": "release/2024.11.15", "deploy_time": "2024-11-16T10:00:00Z" } ] }

我特别要强调code_versionartifact_path这两个字段。模型文件必须和训练/推理代码版本关联起来,不然回滚模型时很可能发生“模型是旧的、代码是新的”这种错位问题。后面专门讲这个坑。

2.2 版本管理与灰度发布:同一个模型名背后是多个版本

模型版本管理不能靠模型文件名带_v2_final来维护。要用不可变地址指向模型文件,每次发布一个模型版本,就生成一个不可变的存储路径和哈希值。这样任何环境都能精确知道跑的是哪一版模型。

有了版本之后,灰度发布就成了必须能力。新模型先在staging环境验证,再以金丝雀方式切5%流量,确认指标没有回退后逐步扩大。模型注册中心里的状态机至少要有:dev、staging、prod、deprecated、archive。生产环境的服务只能引用status=prod的版本,从机制上避免乱发布。

我当时给团队定的规则是:模型版本一经发布就不可变,想修改指标记录或元数据,必须发新版本。虽然一开始大家嫌麻烦,但三个月后做线上问题回溯时会感谢这个决定。

2.3 数据血缘与评估记录:模型不是调完参就完事了

只记录acc和f1远远不够。企业级模型管理还要记录“这个模型是用哪份数据集训练出来的”“训练集和测试集如何划分”“评估集有哪些badcase”。这就是模型血缘。

有了血缘,才能回答三个实际问题:线上效果变差是数据变了、模型过期了、还是上游特征变了?这个模型能不能安全回滚?某个用户投诉问题是否在测试集覆盖范围内?

我在模型注册中心里保留一份评估报告,内容包括训练样本数、样本时间窗口、分布变化、各分位的预测置信度、典型badcase。数据量不大,但价值极高。有一次业务方说模型“变笨了”,我们通过血缘发现训练集里缺少最近一个月的增量数据,问题在数据管道而非模型本身,几分钟就定位了。

2.4 多环境管理:开发环境、预发、生产环境的模型隔离

模型和代码一样需要环境隔离。如果开发环境的模型和生产环境共用一套存储,那测试时一个误操作就会影响线上服务。

建议按环境做命名空间隔离:

环境模型注册表推理服务数据库
devdev-registrydev-inferencedev-meta
stagingstaging-registrystaging-inferencestaging-meta
prodprod-registryprod-inferenceprod-meta

每个环境的模型状态机独立,模型从dev晋升到staging再到prod,需要走审批流。审批流一方面是为了安全,另一方面是强制记录“谁在什么时候把哪个版本提升到了生产”,这本身也是审计需求。

3. 服务编排:从“接口直连”走向“可编排、可观测、可治理”

3.1 为什么单模型接口不够用,还需要编排层

实际业务很少只调用一个模型。以智能客服为例,一次请求往往要经历:问题分类、情感识别、知识库检索、答案排序、大模型生成,每一步可能调不同的模型服务。如果没有编排层,这些调用顺序就被硬编码在业务代码里,改一个环节就要重新发布业务系统,而且看不到整个请求在哪个环节变慢。

编排层的本质是把这个“调用链”从业务代码里抽出来,变成一份可配置的DAG(有向无环图)。它至少要做四件事:

  • 按依赖关系并发或串行调用模型服务;
  • 对每个节点设置超时、重试、熔断;
  • 在节点之间做数据格式转换和上下文传递;
  • 记录每个节点的调用耗时和结果,供监控分析。

3.2 同步编排与异步任务编排的选型

AI服务分两类场景:在线推理和离线批量计算。它们的编排方式完全不同。

在线推理场景,用户请求必须实时返回,编排引擎要极快,且不能因为单个模型超时拖垮整个请求。适合用轻量级DAG引擎,甚至直接在网关层做同步编排。异步任务场景,比如批量文档向量化、定时模型评测,允许几分钟甚至几小时的任务,适合用消息队列加任务调度引擎。

场景特征推荐手段关键指标
在线推理低延迟、高并发、请求有终态同步DAG引擎 / API网关编排TP95延迟、成功率
离线任务长时间、批量、可中断消息队列 + 分布式任务调度吞吐、失败重试

很多人一开始就用重型工作流引擎跑在线推理,结果全链路多了几十毫秒开销,得不偿失。在线编排应该轻,离线编排可以重,这个千万别搞反。

3.3 服务网关的一等公民:限流、熔断、优先级

模型推理服务是昂贵的资源,尤其GPU。所以编排层前面必须有一层网关,能做限流、熔断、优先级调度。

限流不能只按全局QPS做,要按“模型 + 调用方 + 资源池”组合来做。举个例子:同一个文本分类模型,A业务是核心交易链路,B业务是内部测试,两者并发很高时,必须保证A业务的请求优先通过。实现上可以用令牌桶或漏桶算法,在网关层为每个调用方分配配额,同时设置最大并发数。

扩容跟不上流量突增时,快速失败比排队更有价值。我见过一个线上事故:模型服务已经跑满,网关还在继续往服务发请求,结果每个请求都超时重试,最终雪崩。正确做法是网关层设置并发信号量,超过阈值直接返回503,让上游业务走自己的降级逻辑,而不是无限堆积。

3.4 一个最小编排引擎的抽象设计

如果你不想一开始就引入重引擎,可以设计一个极简抽象:

graph: - id: intent_cls type: model model: text-cls-bert owner: alg-team timeout_ms: 300 retry: 1 - id: sentiment_cls type: model model: sentiment-roberta timeout_ms: 300 depends_on: intent_cls - id: kb_search type: model model: dense-retrieval timeout_ms: 800 depends_on: sentiment_cls - id: answer_gen type: deep_model model: llm-generator timeout_ms: 2000 depends_on: kb_search

执行器解析这份配置,依赖关系里depends_on为空或已完成,就放到线程池并发执行;每个节点有独立超时,超时后按策略返回缓存或空结果;最终把每个节点的结果聚合到一个上下文对象里。

不需要K8s、不需要微服务编排平台,一个常驻内存的有向无环图和优雅的超时控制就能解决80%的问题。系统复杂到需要水平扩展时,再考虑组件化也不迟。

4. 权限控制:把人、服务、数据三层权限建清楚,漏一层都出事

4.1 RBAC和ABAC不是二选一,中台场景建议先用RBAC再升级ABAC

AI中台的权限控制,比其他业务系统更需要“多维度”。因为调用方有两种:人,以及系统服务。不能只做人的登录权限,而忽略了服务之间的鉴权。

权限模型上,我建议大多数团队从RBAC(基于角色的访问控制)起步。先把用户、角色、权限三张表设计好,再把“模型操作权限”和“服务调用权限”抽象成权限点。到了需要根据部门、项目、数据密级、时间等因素动态决策的场景,再升级ABAC(基于属性的访问控制)。

RBAC的核心设计并不复杂,但有一个关键:权限点要足够细。比如:

  • 模型管理端:查看模型、申请发布、审核发布、模型下线;
  • 模型调用端:调用某模型、查看某模型Metrics、访问某知识库;
  • 数据端:查看某知识库文档、导出某数据集。

粒度粗了,权限控制等于摆设;粒度细了,用户角色配置成本又高。解决方法是预置“角色模板”,比如“算法工程师”“平台运维”“业务调用方”,模板里预置一组权限点,新用户加入时直接套模板。

4.2 用户权限:从登录到Token,SpringBoot能做什么

热词里有人问“SpringBoot到底如何实现权限控制”,这里给一条我已经验证过多次的实现路径。

如果用SpringBoot + Spring Security + JWT,最常见做法是:

  1. 用户登录成功后签发JWT,JWT里携带用户ID、角色列表,不要放敏感信息;
  2. 在Spring Security配置中增加自定义Filter,解析JWT并设置SecurityContext;
  3. 通过注解@PreAuthorize("hasAuthority('model:call:12345')")控制接口权限;
  4. 数据库使用用户表、角色表、权限表、用户角色关联表、角色权限关联表。

示例代码片段:

@Slf4j public class JwtAuthFilter extends OncePerRequestFilter { private final JwtTokenProvider tokenProvider; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = resolveToken(request); if (token != null && tokenProvider.validateToken(token)) { var authentication = tokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); } filterChain.doFilter(request, response); } }

然后在模型调用接口上做方法级控制:

@PreAuthorize("hasAuthority('model:invoke:' + #modelId)") @PostMapping("/models/{modelId}/invoke") public Result invoke(@PathVariable String modelId, @RequestBody InvokeRequest request) { return inferenceService.invoke(modelId, request); }

这个方案的关键不是代码,而是“权限模型必须来自数据库”,而不是埋在代码里。理想情况下,每次分配模型调用权限,都应该走管理端配置,而不是改代码发版。

4.3 服务间权限:mTLS与Token传递

服务之间互相调用时,用户的JWT不能直接透传给下游,因为下游只想知道“这次调用是否有权限”,而不需要知道用户的登录状态。更稳妥的方案是引入服务身份凭证。

常用方案有两个:

  • 每个服务申请独立的ClientId/Secret,调用时使用客户端凭证模式申请短时Token;
  • 更严格的环境使用mTLS,做服务间双向证书校验。

我更推荐组合使用:对外部用户的身份用用户Token,对内部服务调用用服务凭证,同时配合内部网关做二次校验。因为AI中台是一个高度敏感的服务集群,一旦某个内部服务被攻破,如果缺少服务鉴权,攻击者可以顺着网络横向调用所有模型。

4.4 数据行级权限:知识库如何控制权限到人

“知识库如何控制权限到人”是知识类业务最常见的需求。权限不只是“能访问哪个知识库”,还要精确到知识库里的某段文档、某个知识点对谁可见。

知识库检索链路通常分三步:文档解析、向量化、检索。权限控制最合理的位置在向量化阶段和检索阶段。

错误做法:只在应用层过滤答案。因为向量化是把整篇文档切块后存入向量库的,如果你不做权限控制,用户通过接口直接检索向量库,可能把本不该看到的文档块也能捞出来。

我建议采用方案B:给每个文档块打权限标签。

{ "doc_id": "doc-001", "chunk_id": "chunk-012", "content": "关于产品退款政策的内部说明……", "permission_tag": "perm:refund:internal", "tenant_id": "tenant-a" }

检索时,在向量数据库查询条件里强制加一个过滤条件:where permission_tag in (用户标签集合) and tenant_id = 用户租户ID

权限标签可以设计成从用户的部门和角色动态推导,比如“财务部员工”自动获得perm:finance:*,知识库创建时选择可见范围,文档块继承这个范围。这样设置一次,后续检索时始终强制过滤,性能影响也不大。另外不要直接把向量数据库地址暴露给前端,所有检索必须经过统一API服务,把用户权限上下文注入检索SQL。

4.5 审计日志与权限审批:每一次调用都要可溯

权限系统做到最后,拖垮进度的往往是审计。但审计必须做。

至少要为如下行为留下日志:

  • 登录、注销、刷新Token;
  • 模型发布、版本变更、下线;
  • 模型调用记录:谁调用、调哪个模型、输入是否可脱敏、返回码、耗时;
  • 知识库权限变更:谁给谁授予了哪个标签的访问权。

权限变更要走审批流,最好不要由管理员直接改库。后台接口、审批接口、日志接口分开,审计日志只追加不修改。平时用不上,一旦遇到客户数据投诉或内部违规事件,这套记录就是救命稻草。

5. 落地时最容易翻车的三个细节,提前避开

5.1 模型文件与代码版本不联动,导致回滚回错

这几乎是所有AI中台上线后必踩的坑。模型注册中心里只记录了模型文件,忽略了推理代码版本,当线上模型效果突然下降要回滚时,运维直接回滚到上一个模型文件,却发现推理代码已经变了,导致输入输出解析全部错位。

我现在的强制要求是:模型版本与推理镜像标签必须原子发布。每次发模型版本时,同时打一个包含模型文件地址和推理代码版本的镜像标签。回滚时一起回滚,不允许只回滚模型文件。这是一个架构层面的约定,比任何文档都管用。

5.2 权限控制只做了接口层,没做数据层

很多团队给AI服务加了JWT校验,就认为权限安全了。实际上还要检查两件事:

第一,向量数据库、模型文件存储、消息队列,这些基础组件是否直接暴露给了业务方?如果是,那么业务方完全可以绕过中台API直接访问底层数据。结论是所有基础组件必须在内网隔离区,只有中台服务能访问。

第二,模型调用权限是否只控制了“能不能调接口”,而没有控制“能调哪些模型”?有些实现把所有模型放在同一个接口后面,服务端用模型ID做路由,但鉴权逻辑只检查接口权限,没检查模型ID权限,结果就是只要拿到接口访问权就能调用所有模型。必须用本文4.2节的方法级鉴权,把模型ID作为权限点才好。

5.3 流量突增时GPU排队导致超时雪崩

模型服务的容量规划经常被忽略。假设一个GPU实例一次只能处理1个请求,单次推理耗时100ms,那么单个实例的极限QPS只有10。如果你想要60QPS,就至少需要6个实例,而且还要留出30%~50%冗余,否则任何慢请求都会让排队时间急剧上升。

很多时候问题不在于并发不够,而在于网关没有做快速失败。我建议在线推理服务在网关层同时配置两个数字:最大并发数和最大排队时间。超过最大并发直接返回503,排队超过200ms也直接返回503。业务方看到503后可以走自己的降级逻辑,这比所有请求都慢到30秒要好得多。

以下是一份简单容量参考表(假设单请求平均100ms):

目标QPS单实例并发数所需实例数建议实例数(含50%冗余)
10112
60169
10011015

这个表格虽然简单,但在评审阶段能快速说服业务方给出真实容量预期,避免上线第一天就被流量冲垮。

6. 从0到1的落地路线:先解决最痛的点,再逐步扩展

6.1 阶段一:模型统一注册与网关鉴权

不要一上来就建设大而全的中台。第一阶段只做两件事:把已有模型全部纳入注册中心,并在所有推理服务前面加统一网关。

时间周期一到两周。网关负责鉴权、基础限流、日志。注册中心负责记录模型版本和元数据。这个阶段结束后,至少能回答“线上有哪些模型在跑、谁在调用、哪个版本、请求是否正常”这四个问题,中台已经比大多数共享盘方案强很多了。

6.2 阶段二:模型环境隔离与灰度发布

第二阶段解决“乱发布导致线上故障”的痛点。把开发、staging、生产环境彻底隔离,模型注册表加审批流和状态机,生产环境只允许已审批版本上线。

同时引入灰度发布能力:先切1%流量,观察半小时,再逐步扩展到5%、20%、100%。发现问题时使用一键回滚,同时回滚模型和推理代码镜像。

这一阶段大概是三到四周。做完后,模型上线才开始变得“可控”。

6.3 阶段三:编排层与数据权限

第三阶段再引入DAG编排引擎和知识库行级权限。这时候已经有清晰的模型目录和统一网关,编排引擎只需要对接标准模型接口即可,不会出现一边做编排一边还要处理各种模型协议差异的混乱局面。

知识库权限先聚焦一种权限模式,比如按租户或部门标签过滤。不要一上来就做ABAC,否则规则引擎光配置就要写几十页。

  1. 至于更高级的自动伸缩、成本分摊、模型自动评测,那是在跑通以上链路之后的事。地基越干净,上层功能越不容易翻车。

给正在建设AI中台的团队一句实在话:中台不是靠PPT建出来的,是靠一条一条权限策略、一个一个模型版本、一张一张链路图磨出来的。先把最痛的那颗钉子拔掉,后面的事会顺利得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询