大模型接入的认证与计费:多模型供应商的统一网关设计
大模型接入的认证与计费多模型供应商的统一网关设计一、三个团队各用各的 API Key月底账单混乱财务说分不清谁花了多少钱多模型供应商共存的企业场景下OpenAI Claude 自建 vLLM接入层需要解决两个关键问题。第一个是认证授权——不同供应商的认证方式不同OpenAI 用 API Key、Claude 用 API Key Organization ID、vLLM 可能用 JWT 或无认证。第二个是计费分摊——谁调用了多少 Token、花了多少钱需要精确到团队/项目/用户的维度。统一网关API Gateway 模型封装了上游多供应商的差异对下游暴露一个统一接口。下游调用方只需要关心用哪个模型不需要知道这个模型走 OpenAI 还是 vLLM。认证、鉴权、限流、计费全部在网关层统一处理和业务代码解耦。二、底层机制与原理剖析统一网关的四个核心模块认证模块发放统一的 API Key。每个团队/项目有自己的 API Key在数据库中记录 Key → Team 的映射关系。接收请求时解析 API Key挂载team_id到请求上下文中。后端根据team_id做限流和计费。模型路由根据model参数决定转发到哪个上游。路由表在配置中心维护——新增供应商或模型只需要改路由表不需要改代码。路由逻辑可以按团队做特殊化——Team A 的gpt-4走 OpenAITeam B 的同模型走 Azure。计费模块不管上游供应商是 OpenAI按 token 收费还是自建 vLLM按 GPU 时间计费在网关层统一折算为内部计费单位。从 API 响应中提取usage.total_tokens记录到数据库。支持按团队/模型/时间维度的聚合查询。格式适配器不同供应商的 API 格式不完全相同。OpenAI 用messages数组Anthropic 用messagessystem字段。网关层负责做格式转换——下游只需要用统一格式如 OpenAI 格式上游差异由适配器处理。三、生产级代码实现# unified-llm-gateway.py 统一 LLM API 网关 功能 1. 统一认证API Key → 团队/用户 2. 模型路由model → provider 3. 请求格式适配统一格式 ↔ 各供应商格式 4. 计费记录token 用量统计 import hashlib import hmac import time import json import logging from typing import Optional, Dict, Any, List from dataclasses import dataclass from enum import Enum from urllib.request import Request, urlopen from urllib.error import HTTPError import redis logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) # --------------------------------------------------------------------------- # 数据模型 # --------------------------------------------------------------------------- dataclass class ApiKeyInfo: API Key 对应的元信息 team_id: str user_id: str tier: str # free / pro / enterprise rate_limit_qpm: int # 每分钟请求数限制 daily_token_budget: int # 每日 Token 预算 dataclass class ProviderRoute: 供应商路由配置 provider: str # openai / anthropic / vllm base_url: str # API 基础 URL api_key: str # 该供应商的 API Key model_mapping: dict # 统一 model 名 → 供应商 model 名 default_headers: dict # 额外的请求头 # --------------------------------------------------------------------------- # 网关核心 # --------------------------------------------------------------------------- class LLMGateway: LLM 统一网关 请求流程 1. 认证解析 API Key → 确定 team/user 2. 限流检查 team/user 是否超出配额 3. 路由根据 model 查找上游供应商 4. 适配格式转换 5. 转发发送到上游 6. 计费记录 token 用量 def __init__(self, redis_client: redis.Redis None): self.redis redis_client # API Key 存储生产环境放数据库 self.api_keys: Dict[str, ApiKeyInfo] {} # 供应商路由表从配置中心加载 self.providers: Dict[str, ProviderRoute] { openai: ProviderRoute( provideropenai, base_urlhttps://api.openai.com/v1, api_keysk-xxx, # 实际从 secrets manager 读取 model_mapping{gpt-4: gpt-4-turbo, gpt-3.5: gpt-3.5-turbo}, default_headers{OpenAI-Organization: org-xxx}, ), anthropic: ProviderRoute( provideranthropic, base_urlhttps://api.anthropic.com/v1, api_keysk-ant-xxx, model_mapping{claude-3: claude-3-opus-20240229}, default_headers{anthropic-version: 2023-06-01}, ), vllm: ProviderRoute( providervllm, base_urlhttp://vllm-service.ai-inference.svc:8000/v1, api_key, # 内部服务可能不需要 API Key model_mapping{llama-3: meta-llama/Meta-Llama-3-70B-Instruct}, default_headers{}, ), } # 模型 → 供应商映射 self.model_routes { gpt-4: openai, gpt-3.5-turbo: openai, claude-3-opus: anthropic, claude-3-sonnet: anthropic, llama-3-70b: vllm, } def register_api_key(self, api_key: str, info: ApiKeyInfo): 注册 API Key self.api_keys[api_key] info def handle_chat_completion(self, api_key: str, model: str, messages: list, **kwargs) - Dict[str, Any]: 处理 chat completion 请求核心入口 # 1. 认证 key_info self.api_keys.get(api_key) if not key_info: return {error: Invalid API key, status: 401} # 2. 限流检查 if not self._check_rate_limit(key_info): return {error: Rate limit exceeded, status: 429} # 3. 路由查找 provider_name self.model_routes.get(model) if not provider_name: return {error: fUnknown model: {model}, status: 400} provider self.providers.get(provider_name) if not provider: return {error: fProvider not configured: {provider_name}, status: 500} # 4. 请求格式适配 adapted_request self._adapt_request(provider, model, messages, **kwargs) # 5. 转发到上游供应商 upstream_url f{provider.base_url}/chat/completions response self._forward_request( upstream_url, adapted_request, provider ) if isinstance(response, dict) and error in response: return response # 6. 计费记录 usage response.get(usage, {}) self._record_billing( team_idkey_info.team_id, user_idkey_info.user_id, modelmodel, providerprovider_name, prompt_tokensusage.get(prompt_tokens, 0), completion_tokensusage.get(completion_tokens, 0), ) # 7. 响应格式统一 return self._adapt_response(response, provider) def _adapt_request(self, provider: ProviderRoute, model: str, messages: list, **kwargs) - dict: 请求格式适配统一格式 → 供应商格式 # 映射 model 名 mapped_model provider.model_mapping.get(model, model) if provider.provider anthropic: # Anthropic 格式system 从 messages 中提取 system_msg filtered_messages [] for msg in messages: if msg.get(role) system: system_msg msg.get(content, ) else: filtered_messages.append(msg) return { model: mapped_model, messages: filtered_messages, system: system_msg, max_tokens: kwargs.get(max_tokens, 1024), temperature: kwargs.get(temperature, 0.7), } # OpenAI 兼容格式vLLM 也兼容 return { model: mapped_model, messages: messages, max_tokens: kwargs.get(max_tokens, 1024), temperature: kwargs.get(temperature, 0.7), stream: kwargs.get(stream, False), } def _adapt_response(self, response: dict, provider: ProviderRoute) - dict: 响应格式适配供应商格式 → 统一格式 # 统一包装为 OpenAI 兼容格式 return { id: response.get(id, ), object: chat.completion, created: response.get(created, int(time.time())), model: response.get(model, ), choices: response.get(choices, []), usage: response.get(usage, {}), provider: provider.provider, # 额外字段标记来源 } def _forward_request(self, url: str, body: dict, provider: ProviderRoute) - dict: 转发请求到上游供应商 headers { Content-Type: application/json, Authorization: fBearer {provider.api_key}, **provider.default_headers, } data json.dumps(body).encode(utf-8) try: req Request(url, datadata, headersheaders, methodPOST) with urlopen(req, timeout60) as resp: resp_body resp.read().decode(utf-8) return json.loads(resp_body) except HTTPError as e: error_body e.read().decode(utf-8) if e.fp else logger.error(Upstream error: %s %s, e.code, error_body) return { error: fUpstream error ({e.code}), detail: error_body, status: e.code, } def _check_rate_limit(self, key_info: ApiKeyInfo) - bool: 检查请求频率限制 if not self.redis: return True # 每分钟请求数限制 rl_key fratelimit:{key_info.team_id}:qpm current self.redis.incr(rl_key) if current 1: self.redis.expire(rl_key, 60) # 1 分钟窗口 return current key_info.rate_limit_qpm def _record_billing(self, team_id: str, user_id: str, model: str, provider: str, prompt_tokens: int, completion_tokens: int): 记录计费信息 # Token 成本映射示例——实际从配置读取 cost_per_1k { (gpt-4, openai): 0.03, (gpt-3.5-turbo, openai): 0.002, (claude-3-opus, anthropic): 0.015, (llama-3-70b, vllm): 0, # 自建模型按 GPU 时间计费 } total_tokens prompt_tokens completion_tokens unit_cost cost_per_1k.get((model, provider), 0.001) estimated_cost total_tokens * unit_cost / 1000 # 写入计费日志实际应写入数据库 logger.info( Billing: team%s user%s model%s provider%s tokens%d (prompt%d, completion%d) cost$%.4f, team_id, user_id, model, provider, total_tokens, prompt_tokens, completion_tokens, estimated_cost, ) # 在 Redis 中记录每日累计用于日报表 if self.redis: date_key time.strftime(%Y%m%d) bill_key fbilling:{date_key}:{team_id} self.redis.hincrby(bill_key, total_tokens, total_tokens) self.redis.hincrbyfloat(bill_key, total_cost, estimated_cost) self.redis.expire(bill_key, 86400 * 30) # 保留 30 天 # --------------------------------------------------------------------------- # 使用示例 # --------------------------------------------------------------------------- if __name__ __main__: gateway LLMGateway() # 注册 API Key gateway.register_api_key(sk-team-a-xxx, ApiKeyInfo( team_idteam-a, user_idservice-account, tierenterprise, rate_limit_qpm1000, daily_token_budget10_000_000, )) # 发起请求 response gateway.handle_chat_completion( api_keysk-team-a-xxx, modelgpt-4, messages[ {role: system, content: 你是一个有用的助手}, {role: user, content: 什么是 Kubernetes}, ], max_tokens500, ) print(json.dumps(response, indent2, ensure_asciiFalse))四、边界分析与架构权衡网关单点问题网关成为所有 LLM 请求的唯一入口如果网关挂了所有 LLM 调用不可用解决方案多副本部署K8s Deployment replicas3 负载均衡。网关自身应该是无状态的状态放 Redis/DB认证转发 vs 认证终结网关可以把下游 API Key 换成上游 API Key 后转发认证中转——下游不需要知道上游的 API Key也可以把下游的 API Key 直接透传给上游认证透传——如果上下游 Key 一致推荐中转模式——上游 API Key 只在网关持有下游泄漏自己的 Key 不会泄漏上游 Key流式响应的处理ChatGPT 的 SSEServer-Sent Events流式响应在网关层需要特殊处理——不能等上游完全返回再转给下游网关需要支持 SSE 代理——上游 SSE 事件逐个转发同时累计 token 用于计费五、总结LLM 统一网关的核心价值是封装上游多供应商差异认证方式、API 格式、计费模型对下游暴露统一接口。四个模块各司其职认证鉴权API Key → team/user、模型路由model → provider URL、格式适配统一格式 ↔ 各供应商格式、计费记录token 用量 → 成本分摊。关键设计决策认证走中转模式上游 Key 只在网关持有、计费层记录到数据库支持按团队/模型的成本分析、网关自身无状态状态放 Redis。

相关新闻

AI数字内容生产系统:30天打造多平台高效创作流水线

AI数字内容生产系统:30天打造多平台高效创作流水线

1. 项目背景与核心价值去年夏天,我和团队用30天时间完成了一个疯狂的实验:用AI工具搭建完整的数字内容生产系统。这个系统覆盖了公众号运营、小说创作、小红书种草和视频号制作四大场景,实测下来单日最高产出达到47篇原创内容,小红…

2026/7/24 14:09:54 阅读更多 →
OpenClaw 切换 Kimi 系列模型,Moonshot 账号充值与密钥创建(含安装包)

OpenClaw 切换 Kimi 系列模型,Moonshot 账号充值与密钥创建(含安装包)

OpenClaw v2.7.9 接入 Kimi 大模型完整配置教程 接入前必备条件 本地设备完成 OpenClaw v2.7.9 部署,客户端能够正常打开运行;OpenClaw 页面顶部 Gateway 服务保持在线标识;设备网络环境稳定,可正常访问 Moonshot 开放平台&…

2026/7/24 14:09:54 阅读更多 →
8款AI工具助力本科生高效完成毕业论文写作

8款AI工具助力本科生高效完成毕业论文写作

1. 本科生毕业论文写作痛点与AI工具的价值 作为一名经历过本科论文写作的过来人,我深刻理解这个过程中的各种困扰。文献综述找不到方向、数据分析无从下手、格式调整耗时费力...这些问题往往让同学们在毕业季焦头烂额。而如今AI工具的快速发展,确实为我们…

2026/7/24 14:09:54 阅读更多 →

最新新闻

BQ25886电源管理芯片:NVDC架构与DPM技术深度解析与实战

BQ25886电源管理芯片:NVDC架构与DPM技术深度解析与实战

1. 项目概述:为什么我们需要更聪明的电源管理芯片?做硬件开发,尤其是便携式设备,电源管理设计绝对是绕不开的“硬骨头”。我见过太多项目,功能做得天花乱坠,最后却栽在续航短、充电慢、发热大或者系统不稳定…

2026/7/24 14:19:59 阅读更多 →
CC3235MODx外设与安全实战:从JTAG、ADC到Wi-Fi与TLS的物联网设计精要

CC3235MODx外设与安全实战:从JTAG、ADC到Wi-Fi与TLS的物联网设计精要

1. 项目概述:从芯片手册到实战,拆解CC3235MODx的通信与安全基石 在物联网和嵌入式开发领域,选型一颗合适的MCU,远不止是看主频和内存。真正决定项目成败的,往往是那些“不起眼”的外设接口和深植于芯片内部的安全机制。…

2026/7/24 14:19:59 阅读更多 →
TDA4VM外设信号深度解析:CPTS、PRU_ICSSG与MCASP硬件设计与软件配置实战

TDA4VM外设信号深度解析:CPTS、PRU_ICSSG与MCASP硬件设计与软件配置实战

1. 项目概述与核心价值在嵌入式系统,尤其是像德州仪器TDA4VM这类高性能异构SoC的设计与开发中,硬件工程师和底层驱动开发者面临的最大挑战之一,就是如何从海量的数据手册引脚表中,快速、准确地理解每个外设接口的真正含义、连接方…

2026/7/24 14:19:59 阅读更多 →
MSP430FR5969 LaunchPad引脚映射与BoosterPack兼容性实战指南

MSP430FR5969 LaunchPad引脚映射与BoosterPack兼容性实战指南

1. 项目概述与核心价值 如果你手头有一块TI的MSP430FR5969 LaunchPad开发板,并且正琢磨着怎么给它接上各种传感器、显示屏或者通信模块,那么你大概率绕不开两个关键词:引脚映射和BoosterPack。这听起来像是硬件工程师的专属领域,但…

2026/7/24 14:19:59 阅读更多 →
Open-ultra智能路由代理:实现多LLM模型的动态选择与自我优化

Open-ultra智能路由代理:实现多LLM模型的动态选择与自我优化

如果你正在构建基于大语言模型的应用,可能已经遇到了一个典型困境:随着业务增长,你需要接入多个不同的LLM服务——可能是OpenAI GPT-4用于复杂推理,Claude用于长文本分析,本地部署的Llama用于成本敏感场景。但直接硬编…

2026/7/24 14:19:59 阅读更多 →
大模型长文本处理中的注意力稀释与优化策略

大模型长文本处理中的注意力稀释与优化策略

1. 大模型推理中的"偷工减料"现象解析 最近在使用大语言模型(LLM)进行长文本处理时,我发现一个有趣的现象:当上下文长度超过一定阈值后,模型似乎会"偷工减料",对输入信息的处理变得不那…

2026/7/24 14:18:58 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻