阶段4(下):LangChain 1.x、提示词与注入防护、模型侧(路由/vLLM/LoRA)、AI 编程工具与验证、Dify/Coze 专题
This commit is contained in:
1 parent
caaec830b3
commit
7a32d2c9a6
38 files changed
+3059
-67
No files matched your search
@@ -0,0 +1,77 @@
|
||||
---
|
||||
id: ai.llm-serving.scenario.multi-provider-gateway
|
||||
title: 公司级大模型网关:多厂商路由、配额、敏感数据走内网模型
|
||||
type: scenario
|
||||
domain: ai
|
||||
stack: [llm-serving, fastapi, redis]
|
||||
tags: [模型网关, 多模型路由, 配额, 熔断, 降级, 敏感数据, 成本分摊]
|
||||
level: advanced
|
||||
prerequisites: [ai.llm-serving.routing-vllm-lora]
|
||||
est_hours: 3
|
||||
related: [ai.llm-serving.interview, python.fastapi.index, backend.redis.lock-ratelimit]
|
||||
week: [13, 14]
|
||||
---
|
||||
|
||||
# 公司级大模型网关:多厂商路由、配额、敏感数据走内网模型
|
||||
|
||||
## 业务背景与问题
|
||||
|
||||
公司有十几个业务在用大模型,各自申请厂商账号、各自写调用代码,出现:
|
||||
|
||||
1. 某个业务的密钥被写进了前端代码;
|
||||
2. 一次厂商故障,所有业务同时不可用;
|
||||
3. 月底账单超预算,不知道是哪个业务用的;
|
||||
4. HR 系统把员工身份证号发给了外部模型。
|
||||
|
||||
## 约束
|
||||
|
||||
- 业务方改造成本要低。
|
||||
- 敏感数据不能出内网。
|
||||
|
||||
## 方案设计
|
||||
|
||||
1. **统一网关**:提供 OpenAI 兼容接口,业务方只需要改 `base_url` 和使用网关分配的业务令牌;厂商密钥只存在网关。
|
||||
2. **路由策略**:业务方指定“逻辑模型名”(`chat-large`、`chat-small`、`chat-private`),网关映射到具体的厂商和模型,可以随时调整而不改业务代码。
|
||||
3. **可用性**:每个逻辑模型配置主备提供方;限流重试、超时切换、熔断;所有提供方都不可用时返回明确的错误码。
|
||||
4. **配额和成本**:Redis 记录每个业务每分钟请求数和每日 token 数,超限返回 429;调用台账按业务汇总成本,每天推送报表。
|
||||
5. **敏感数据**:`chat-private` 只路由到内网 vLLM;网关对发往外部的请求做敏感信息检测(身份证号、手机号等),命中时拒绝或脱敏,并告警。
|
||||
6. **可观测性**:记录每次调用的业务、逻辑模型、实际模型、token、耗时、是否降级;不默认记录完整内容(按需开启并脱敏)。
|
||||
|
||||
## 关键代码
|
||||
|
||||
网关入口(FastAPI,示意):
|
||||
|
||||
```python
|
||||
@app.post("/v1/chat/completions")
|
||||
async def chat(req: ChatRequest, app_id: str = Depends(auth_app)):
|
||||
await quota.check(app_id, tokens_estimate=estimate(req.messages)) # Redis 计数,超限 429
|
||||
route = ROUTES[req.model] # 逻辑模型名 -> 提供方列表
|
||||
if not route.private and contains_sensitive(req.messages):
|
||||
raise HTTPException(400, "请求包含敏感信息,请使用 chat-private 模型")
|
||||
result = await router.chat(route, req.messages, stream=req.stream)
|
||||
await ledger.record(app_id=app_id, logical=req.model, provider=result.provider,
|
||||
tokens_in=result.tokens_in, tokens_out=result.tokens_out, fallback=result.fallback)
|
||||
return result.response
|
||||
```
|
||||
|
||||
路由、熔断、降级的可运行示例:[examples/model-router](../examples/model-router/)。
|
||||
|
||||
## 取舍
|
||||
|
||||
| 选择 | 优点 | 缺点 |
|
||||
| --- | --- | --- |
|
||||
| **自建网关(本方案)** | 完全可控,能接入公司的鉴权和审计 | 要开发和维护 |
|
||||
| 开源网关(如 LiteLLM) | 功能现成 | 定制和二次开发有学习成本 |
|
||||
| 云厂商的模型网关服务 | 免运维 | 绑定云厂商;内网模型接入受限 |
|
||||
| 各业务自己调用 | 灵活 | 本场景中的所有问题 |
|
||||
|
||||
## 易错点
|
||||
|
||||
- 网关成为单点:多实例部署、无状态,配额放 Redis。
|
||||
- 流式响应经过网关时被缓冲(Nginx、中间件),首字延迟变长。
|
||||
- 敏感信息检测只用简单正则,误报漏报多:结合业务分级,最可靠的是让敏感业务只能用内网模型。
|
||||
- 降级到备用模型后,输出格式差异导致业务解析失败:备用模型也要在业务评测集上验证。
|
||||
|
||||
## 面试怎么讲
|
||||
|
||||
> “我们做了一个公司级的模型网关,提供 OpenAI 兼容接口,业务方只换 base_url 和令牌,厂商密钥只在网关里。业务用逻辑模型名,网关映射到具体厂商,主备切换、限流重试、熔断都在网关做。配额用 Redis 计数,台账按业务出成本报表。敏感业务只能用路由到内网 vLLM 的 private 模型,发往外部的请求做敏感信息检测。”
|
||||
Reference in new issue
Block a user