拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

10 大关键技术,助你快速落地 AI 门户

10 大关键技术,助你快速落地 AI 门户

“Don’t find fault. Find a remedy.” — Henry Ford

把成熟的 AI 网关搬进新环境时,你真正需要带走的不是脚本,而是状态机与数据边界。

我在笔记本里记过一个关于基础设施的规律:现代航天飞机火箭推进器的宽度,其实是由两匹马的屁股宽度决定的。因为当年英国和美国的铁轨宽度就是照着两匹马的宽度设计的。一旦某种基础设施嵌入了系统,只要没产生直观的毁灭性危害,它的形状就会被后人盲目沿用。

今天,当你被管理层叫去“给咱们也搞一套类似 ChatGPT 的门户”时,最危险的做法就是打开某个成熟团队的代码库,顺手把prd-auea-opui-rg-01这样的资源名和 Bicep/Terraform 脚本全盘复制。这就是在把别人的“马屁股”原封不动地搬进你的机房。成熟架构的背后是特定区域、已有网络拓扑、合规审计要求以及按团队结算财务等一系列隐性约束。你的环境只要有一条不同,抄来的脚本在what-if里看着是一片绿,在第一周的值班里就会变成一片红。

读完这篇,你将能画出一个严密的三环境发版状态机,并带着一份明确的“抄 / 改编 / 扔掉”清单走进架构评审会,而不是带着一张脆弱的资源名对照表。

你可能会在别人的部署脚本里看到一段看似粗糙的sleep 90,并以为这只是等网络就绪的野路子。实际上,那是为了在更新有状态容器前,强制停用当前修订版本,留出 60 秒优雅退出和 30 秒缓冲——这是有状态控制面禁止双活的物理约束,绝不是一个供你随意优化的魔术数字。

1. 发版状态机:比资源名更值得抄

在很多仓库的CONTRIBUTING.md里,有一句极易被跳过的话:Pull Request不会修改 sandbox、dev 或 prod 环境。what-if只显示差异。

优秀的 AI 网关(如基于 LiteLLM 构建的控制面)会把这句话严格写进代码里:

on:pull_request:{paths:[src/litellm/**,...]}push:{paths:[src/litellm/**,...]}sandbox:# 仅 PRoperation:whatIf|create# PR 上永远只是 whatIfdev:operation:whatIf|createdev-test:# 仅合入后执行playwright against the new LiteLLM URLprod:needs:dev-testif:push&&mainenvironment:prod# 必须有人工审批闸门

本地验证和云端验证使用的绝不是同一把尺子。make validate比对的是配置快照;make *-what-if问的是云环境会不会发生实质变更;而make local仅仅证明本地的 docker compose 还能跑通。把快照当部署,或把 what-if 当测试,都是在用错尺子。

模型上架同样是一个状态机。新增模型应该通过脚本生成配置,让 sandbox 先看见,non-prod 接着看见,prod 批准后才全员可用。千万不要开启网关的“通配符发现(wildcard discovery)”功能。如果开启,云控制台里的一次误操作,会立刻变成生产环境不受控的模型列表。这是产品安全决策,不是配置文件的口味问题。

📌本节要点:what-if 是意见,create 是事实。中间那道人工闸门,是你愿意为事实支付的保险金。

2. 身份、密钥与那把不能丢的盐

把带有硬编码 Secret 的脚本抄进你的仓库,就像是埋下了一颗定时炸弹。一旦代码被推送到远程,历史记录里的明文就会成为严重的安全漏洞。

身份管理必须彻底依赖 OIDC 和托管身份(Managed Identity)。GitHub 只持有 OIDC 和 Environment secret;容器启动时从 Key Vault 拉取凭证。每个应用应该有自己独立的 User-assigned MI。

这里有一个云服务商的不对称现实:Azure 模型可以走托管身份,从而消灭静态 key;但在当前设计下,AWS Bedrock 仍然需要 access key。搬到新环境时,你必须先问安全团队能否接受“半边没有长期密钥”。如果不能接受,你要么在 Bedrock 前加一层自建的凭证代理,要么就先别上 Claude。

在这个体系里,最关键的配置是盐(Salt)。网关使用LITELLM_SALT_KEY加密库存里的虚拟 key。如果 master key 丢了,你还能紧急签发;如果 salt 丢了,历史 key 就变成了一堆彻底解不开的字节。

🩸血泪提醒:备份 salt 的流程必须是两人、离线、定期演练。不要把它和普通的WEBUI_SECRET_KEY混在一起只写一句“记得放进 KV”。密钥轮换是日常运维,盐的保管是业务连续性,两件事绝对不能放在同一张 runbook 的同一行。

3. 数据驻留与灾备:证明你没有去错地方

如果架构评审会被“我们所有数据都加密了”这句话结束,那说明你们根本没有触及核心。

把数据落点写成一张表,才是对合规的交代:

数据类型存储位置生命周期谁能访问
聊天正文 / 历史业务 Postgres直到用户删除或清理 Job 触发(如 90 天闲置)应用 + 合法 break-glass
RAG 向量同一套 Postgres 的 pgvector同上同上
Prompt 全文(遥测)Log Analytics约 60 天表级 RBAC,禁止工作区全局权限
用量元数据(Token/金额)网关 Postgres长期财务/平台团队
会话状态Redis活着的会话非归档,丢弃无妨

灾难恢复(Disaster Recovery)脚本协调的是文件共享快照 + Postgres PITR(时间点恢复)。如果你的环境只有磁盘备份而没有文件快照,一旦发生回滚,RAG 就会面临“库在、文件不在”的幽灵状态。演练时要故意恢复到“库和文件时间点不一致”的状态,观察应用是否能正确报错。

另外,分清break-glass(破窗机制,用于合法接触用户数据)和 ops(常规运维,用于回滚、扩容)。Break-glass 必须两人授权、限时(默认 ≤ 2 小时)、优先只读,并在工单里写明法律依据。当关闭STORE_PROMPTS_IN_SPEND_LOGS时,去用量表找聊天正文会空手而归,操作者必须事先知道去业务库查还是去日志区查。

备份证明你能回到过去。驻留证明你没有去错地方。审计证明你知道谁去过。三件不是一件。

4. 另一所学校的第一周:抄、改编、扔掉

把别人的架构拆成三堆。只搬第一堆,也能开工;如果把第三堆当圣经,你会在命名规范上耗掉整整一个月。

抄(不可妥协的约束)

  • 控制面与 UI 必须分目录、分 workflow、分数据库。
  • 三环境隔离,生产环境强制人工审批;PR 默认只跑 what-if。
  • 使用 GitHub OIDC,坚决不用长期密码。
  • 用户身份通过 Header 传递进代理,预算绑定在“人”上,而不是绑定在“那个聊天容器”上。
  • 禁止控制面双写,保证单活会话。

改编(适应你的“世”)

  • 区域与网络:前人的 VNet 是既有资产,你可能需要从零画图或接入现有的零信任网络。网络配置代码是文档,不是让你直接apply的。
  • 计算底座:Serverless 容器可以换成 AKS / ECS,只要保住内部 DNS、托管身份和等价的 drain 机制。
  • 告警路由:接收人应该写在环境参数里,而不是硬编码某个英雄工程师的手机号。人员变动应该是提 PR,而不是在微信群里吼一声。

扔掉(别人的历史包袱)

  • prd-auea-opui-*这套晦涩的命名。建立你们自己的{env}-{region}-{workload}词典。
  • 把 syslog relay、SearXNG 搜索、动态会话等当成 MVP 的一部分。核心数据流跑通前,这些高级功能都应该处于关闭状态。
  • 在生产环境打开STORE_PROMPTS_IN_SPEND_LOGS=true只为了“调试方便”。这等同于把全文日志从 60 天的合规策略,直接扩成了数据库的长期存档。

5. 约束的保质期

任何架构决策都是当时当地合规、财务和技术妥协的产物。代码只是结果,背后的约束才是原因。

当系统规模极小,纯粹用于个人技术验证时,抄代码的收益大于理解约束的成本。但只要系统开始承载真实用户、涉及合规数据,盲目照搬就是灾难。

举一反三:在复用任何基础设施代码前,问自己一个问题——“这行配置是在解决什么我并没有面临的问题?”

架构的落地不是去比对别人家“马屁股”的宽度,而是去理解为什么当年要用两匹马。

现在,打开你的架构图,你的三个环境的GitHub Environment 名是什么?谁拥有 prod 的批准权?如果你连人名都写不出,先别写哪怕一行部署代码。

返回列表