资讯动态

LiteLLM 对接 TaoToken,MaaS 中台能统一调 Nova/Claude

发布时间:2026/9/18 8:47:38 来源:尧图企业网站定制
1. MaaS 中台的模型矩阵比你想的更难管企业内部搭 MaaS 中台最麻烦的不是把自建 DeepSeek 跑起来而是同时接 Amazon Nova、Claude Sonnet 3.7 这类 SaaS 模型时每个模型都要单独维护一套 Base URL 和 API Key。业务部门每次切换模型代码里就要改一遍 endpoint、改一遍鉴权排障时根本分不清是模型参数问题还是密钥过期。TaoTokenhttps://taotoken.net/?utm_sourcetaotoken_aicg_blog_end提供了一条 OpenAI 兼容通道能让 Nova/Claude 也走同一个 LiteLLM 入口不需要为每个 SaaS 模型单独拉专线、单独找密钥。参考原方案中「LiteLLM Proxy 负责统一转发」的设计我保留了 Amazon SageMaker IC 部署 DeepSeek 的部分把 LiteLLM 作为 MaaS 中台的统一出口TaoToken 在其中只承担一件事让 Nova/Claude 这类原本分散在多个厂商控制台里的模型聚合到同一个 OpenAI 兼容上游。这样业务部门看到的模型列表是完整的自建 DeepSeek、Amazon Nova、Claude Sonnet 3.7 都在一个 model_list 里复制同一个 Key 就能调全部模型。1.1 原文里那套架构卡在哪原始方案的整体架构很清晰OpenAPI RESTful HTTP 作为客户端与 MaaS 中台之间的接口LiteLLM Proxy 负责把请求转发到 Amazon SageMaker IC 上的 DeepSeek、Amazon Bedrock 或第三方 LLM。这套架构解决了「自建模型 AWS 生态」的统一接入但有个隐含前提所有模型的 API 密钥、服务地址都要预先配好。Amazon Nova 要走 Bedrock 的鉴权链Claude Sonnet 3.7 要走 Anthropic 的接口两个模型两套 Key业务部门根本不可能为每个模型都开发一套适配器。这里就是 TaoToken 的接入点。它没有替代 LiteLLM 的调度能力也没有碰 SageMaker IC 的资源管理而是以「OpenAI 兼容上游」的身份出现在 model_list 里把 Nova/Claude 的鉴权和地址差异全部屏蔽掉。配置完之后上游是自建 DeepSeek 还是 SaaS 模型LiteLLM 侧看到的都是同一个 RESTful 接口规范。1.2 真正值得先做的技术铺垫在动 LiteLLM 配置之前有几个细节值得先确认。首先自建 DeepSeek 的推理端点必须先用 Amazon SageMaker IC 部署好拿到稳定的 endpoint_name 和 InferenceComponentName其次确定 LiteLLM Proxy 的部署位置它要么和 SageMaker 端点在同一个 VPC 内要么能通过公网访问到 SageMaker 端点最后TaoToken 的 Base URL 是 https://taotoken.net/api注意末尾不要加 /v1LiteLLM 在配置 OpenAI 兼容上游时会自动拼路径。接下来的章节会按原文的目录节奏展开先在 SageMaker IC 上把 DeepSeek 32B/1.5B 部署出来再装 LiteLLM Proxy然后在 model_list 里把 TaoToken 加进去最后用同一把 Key 做联调验证。流式输出的 chunk 截断问题放在最后一章单独说因为这是原文里踩过最深的坑。2. 先在 SageMaker IC 上把自建 DeepSeek 跑起来2.1 创建 SageMaker 端点SageMaker IC 是建立在实时推理端点之上的第一步是创建端点配置和端点本身。原文用 ml.g5.48xlarge 承载 8 卡 A10下面这段是创建端点配置和端点的基础代码EndpointConfigName 和 EndpointName 在后续创建 Inference Component 时都要复用。import boto3 import sagemaker role sagemaker.get_execution_role() sm_client boto3.client(service_namesagemaker) endpoint_config_name Sagemaker-inference-component-config endpoint_name Sagemaker-inference-component-mme sm_client.create_endpoint_config( EndpointConfigNameendpoint_config_name, ExecutionRoleArnrole, ProductionVariants[{ VariantName: AllTraffic, InstanceType: ml.g5.48xlarge, InitialInstanceCount: 1, RoutingConfig: { RoutingStrategy: LEAST_OUTSTANDING_REQUESTS } }] ) sm_client.create_endpoint( EndpointNameendpoint_name, EndpointConfigNameendpoint_config_name )关于实例类型要根据显存需求定32B 模型 FP16 精度需要 64G 以上显存单张 A10 只有 24G所以至少 4 卡。如果选 ml.g5.48xlarge总显存 192G可以同时放下 32B 的 4 卡副本和 1.5B 的 2 卡副本剩余资源还能再塞副本。这段在原文里讲得很细实际操作时最容易漏的是 RoutingStrategy建议保持 LEAST_OUTSTANDING_REQUESTS让多个 IC 副本之间的负载更均衡。2.2 准备 vllm LMI 镜像配置Amazon SageMaker IC 的镜像推荐使用 vllm LMI 推理镜像核心是 serving.properties 和 requirements.txt 两个文件。32B 模型用 4 卡张量并行gpu_memory_utilization 控制在 0.87max_model_len 设 10240。下面这份 serving.properties 可以直接用于 DeepSeek-R1-Distill-Qwen-32BenginePython option.trust_remote_codeTrue option.tensor_parallel_degree4 option.gpu_memory_utilization.87 option.max_model_len10240 option.model_iddeepseek-ai/DeepSeek-R1-Distill-Qwen-32B option.max_rolling_batch_size2 option.rolling_batchvllm option.enable_streamingtruerequirements.txt 里锁定版本vllm0.7.0。把这两个文件打包成 tar.gz 上传到 S3。这里有个容易踩的坑vllm 的 tensor_parallel_degree 不支持奇数如果后端模型是 7B 或 13B想用 3 卡并行会直接报错因为 transformer layer 无法均分到每个 GPU 上。我的建议是部署前先确认模型参数量再规划 GPU 卡数。mkdir mymodel mv serving.properties mymodel/ mv requirements.txt mymodel/ tar czvf mymodel.tar.gz mymodel/ rm -rf mymodel s3_code_prefix large-model-lmi/code bucket sess.default_bucket() code_artifact sess.upload_data(mymodel.tar.gz, bucket, s3_code_prefix)2.3 创建 Inference Component 部署多个 LLM端点就绪、镜像配置上传到 S3 之后就可以创建 Inference Component。32B 和 1.5B 的区别主要在两个地方NumberOfAcceleratorDevicesRequired 分别是 4 和 1CopyCount 分别是 1 和 2。MinMemoryRequiredInMb 必须给足vllm 默认会为 prefill 缓存预留显存32B 模型原文设置了 80096MB。container_config { Image: image_uri, ModelDataUrl: source_data, Environment: vllm_config } response sm_client.create_model( ModelNamemodel_name, ExecutionRoleArnrole, PrimaryContainercontainer_config ) sm_client.create_inference_component( InferenceComponentNameIC-deepseek-r1-distill-qwen-32b- time.strftime(%Y-%m-%d-%H-%M-%S, time.gmtime()), EndpointNameendpoint_name, VariantNameAllTraffic, Specification{ ModelName: model_name, ComputeResourceRequirements: { NumberOfAcceleratorDevicesRequired: 4, MinMemoryRequiredInMb: 80096 } }, RuntimeConfig{CopyCount: 1} )1.5B 模型部署时NumberOfAcceleratorDevicesRequired 改为 1MinMemoryRequiredInMb 改为 4096CopyCount 改为 2。这样两个副本由 SageMaker IC 自动做负载均衡流量打过来时不会只压在一张卡上。如果后续扩容可以调用 update_inference_component 把 CopyCount 从 2 调到 8但要注意副本数增加后实例也必须对应扩容否则 GPU 卡不够扩缩会失败。3. LiteLLM proxy 安装与第一个上游3.1 pip 安装与环境变量SageMaker IC 部署完成后开始装 LiteLLM Proxy。新版本必须显式安装 proxy 组件否则只装了核心库没有 litellm 命令行入口。pip install litellm[proxy]安装后设置日志级别。如果 LiteLLM 运行在 EC2 上且绑定了实例角色可以跳过 AWS 密钥配置否则要显式声明访问密钥和区域这里建议区域用 us-west-2与 SageMaker 端点保持一致。export LITELLM_LOGDEBUG export AWS_ACCESS_KEY_IDyour_aws_access_key_id export AWS_REGION_NAMEus-west-2 export AWS_SECRET_ACCESS_KEYyour_aws_secret_access_key3.2 config.yaml 声明 SageMaker 上游LiteLLM 支持命令行直接指定--model sagemaker/endpoint_name但用 YAML 配置更利于维护。原始方案里是这样配置的model_list 中声明 sagemaker_ds 这个模型名litellm_params 里指定 sagemaker 调用方式和 IC 组件的 model_id。这个 model_id 很关键它是「Inference Component 名称」不是 HuggingFace 的模型名。如果不加LiteLLM 不知道要路由到哪个副本。model_list: - model_name: sagemaker_ds litellm_params: model: sagemaker/sagemaker/Sagemaker-inference-component-mme aws_region_name: us-west-2 model_id: IC-deepseek-r1-distill-qwen-32b-2025-03-11-14-30-02 hf_model_name: deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B max_tokens: 1024保存为 config.yaml 后用nohup litellm --config ./config.yaml启动。启动后先确认 4000 端口监听正常再进入下一章把 TaoToken 作为第二个上游加进 model_list。4. 把 TaoToken 作为 Nova/Claude 的统一上游加进 model_list4.1 先去官网创建 API KeySaaS 模型接入的统一工作可以在 TaoToken 上完成。打开官网后注册账号进入控制台创建 API Key把生成的 Key 复制保存为 YOUR_API_KEY。这一步对应原方案中「到各 SaaS 平台申请密钥」的动作只不过现在不需要分别去 Bedrock 和 Anthropic 控制台两趟了TaoToken 把这层统一掉了。创建完 Key顺手看一下模型广场确认上面挂出的 Nova、Claude 模型 ID 列表后面配置 model_list 时要以广场当时的列表为准不要凭记忆填。4.2 config.yaml 里加 OpenAI 兼容上游回到之前那份 config.yaml在 model_list 中追加一项。LiteLLM 的openai/前缀表示走 OpenAI 兼容协议api_base 填 TaoToken 的 Base URLhttps://taotoken.net/api注意末尾不要加 /v1。api_key 填刚才创建的 YOUR_API_KEYmodel 字段填模型广场上对应的模型 ID。model_list: - model_name: sagemaker_ds litellm_params: model: sagemaker/sagemaker/Sagemaker-inference-component-mme aws_region_name: us-west-2 model_id: IC-deepseek-r1-distill-qwen-32b-2025-03-11-14-30-02 hf_model_name: deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B max_tokens: 1024 - model_name: taotoken_nova litellm_params: model: openai/你的模型广场ID api_key: YOUR_API_KEY api_base: https://taotoken.net/api - model_name: taotoken_claude litellm_params: model: openai/你的模型广场ID api_key: YOUR_API_KEY api_base: https://taotoken.net/api「你的模型广场ID」需要替换为 TaoToken 模型广场上实际展示的模型 ID比如 Claude Sonnet 3.7 对应哪个 ID、Nova 对应哪个 ID以官网列表为准。注意这里模型 URL 填接口地址和官网落地页不是同一个东西不要混。4.3 与原来 SageMaker 上游的差异对比新增的 TaoToken 上游和原有的 sagemaker_ds 上游最明显的差异是少了很多字段不需要 aws_region_name、不需要 model_id、不需要 hf_model_name。这是因为 TaoToken 已经把 Nova/Claude 的鉴权和路由在它那一层处理完了LiteLLM 只需要把它当作一个标准的 OpenAI 兼容服务来调用。这种设计有一个实际收益原有业务代码中调 LiteLLM 的 RESTful 接口完全不用改只是 model 参数从 sagemaker_ds 换成 taotoken_nova 或 taotoken_claude。对于已经在生产环境跑了很久的中台来说这比引入新的 SDK 或改调用链要平滑得多。5. 用同一个 Key 验证两个上游5.1 通过 curl 调 /chat/completions配置保存后重启 LiteLLM Proxy先拿 curl 做一轮最小验证。下面这段同时验证了自建 DeepSeek 和 TaoToken 两个上游LiteLLM 会根据请求中的 model 字段自动路由。curl http://your-litellm-host:4000/chat/completions \ -H Content-Type: application/json \ -d { model: taotoken_nova, messages: [ {role: system, content: You are a helpful assistant.}, {role: user, content: Hello, introduce yourself in one sentence.} ] }把 model 换成 sagemaker_ds 再发一次如果两个请求都正常返回说明 model_list 的路由没问题。这里值得留意的是request 里没有再传任何 TaoToken 的 Key因为 Key 已经写在 config.yaml 的 litellm_params 里了Token 消耗发生在 TaoToken 层计费也在那边看。5.2 用 OpenAI SDK 验证兼容性LiteLLM Proxy 的接口兼容 OpenAI 协议所以业务代码里可以继续用 openai SDK只需要把 base_url 指到 LiteLLM 的地址。import openai client openai.OpenAI( api_keydummy, base_urlhttp://your-litellm-host:4000 ) response client.chat.completions.create( modeltaotoken_nova, messages[{role: user, content: 用一句话解释什么是 MaaS}] ) print(response.choices[0].message.content)api_key 传 dummy 是因为真正的鉴权发生在 LiteLLM 的 litellm_params 里这份 Key 在 openai SDK 这边只是占位。base_url 指向 LiteLLM 的 4000 端口而不是直接指向 https://taotoken.net/api。这一点和 4.2 节要区分开config.yaml 里填的是上游地址业务代码里填的是 LiteLLM 的地址。5.3 用 litellm completion 直接调 model_id如果不走 HTTP 接口也可以用 litellm 的 Python SDK 直接验证这对排查「到底是上游问题还是 proxy 问题」很有帮助。from litellm import completion response completion( modelsagemaker/sagemaker/Sagemaker-inference-component-mme, model_idIC-deepseek-r1-distill-qwen-32b-2025-03-11-14-30-02, messages[{role: user, content: How to make cake?}], temperature0.2, max_tokens80, aws_access_key_id*****, aws_secret_access_key*********, aws_region_nameus-west-2, ) print(response[choices][0][message][content])如果这段能通说明 SageMaker IC 部署本身没问题再试completion(modelopenai/你的模型广场ID, api_keyYOUR_API_KEY, api_basehttps://taotoken.net/api, ...)能通则说明 TaoToken 上游配置没问题。两个单独都通只有走 LiteLLM 才报错问题就局限在 config.yaml 上。5.4 跑通之后去控制台对一下这次调用统一验证完成后打开 TaoToken 模型对话 页面用同一把 Key 再发一条测试消息确认模型 ID 和 Base URL 都没填错。如果后续要把这套能力长期跑在业务侧可以看看 Coding Plan 里的套餐是否够用Key 的创建和管理统一在 控制台 API Keys 页面操作。对账时以这里记录的用量为准不要凭 LiteLLM 测的数估算。6. 流式输出踩坑与排障6.1 SageMaker 的 chunk encoder 截断问题原文里最隐蔽的坑是流式输出时的 chunk 截断。SageMaker 的 chunk encoder 编码方式会在超过 chunk size 时把一个 token 单词切到不同的 chunk 中LiteLLM 的 CustomStreamWrapper 直接把 chunk 当独立 JSON 解析时就会报 UnicodeDecodeError。处理方式是在每次读取 chunk 后判断是否以换行符结尾如果不是就继续取下一个 chunk 拼上来。chunk next(self.completion_stream) if not chunk.endswith(\n): next_chunk next(self.completion_stream) chunk next_chunk data json.loads(chunk)同步读取逻辑处理完后还要改异步的__anext__方法。Cline、Continue 这类工具走的都是异步序列方法它们从 SageMaker 拉流式 chunk 时同样会被截断问题干扰。改法是把 accumulated_json 累积到一个缓冲区尝试json.loads解析解析成功就 yield 结果并清空缓冲区解析失败就继续拼接下一个 chunk。async for chunk in iterator: event_stream_buffer.add_data(chunk) for event in event_stream_buffer: try: message self._parse_message_from_event(event) if message: message ( litellm.CustomStreamWrapper._strip_sse_data_from_chunk(message) or ) message message.replace(\n\n, ) accumulated_json message data json.loads(accumulated_json) yield self._chunk_parser(data) accumulated_json except json.JSONDecodeError: continue6.2 TaoToken 上游的流式行为差异走 TaoToken 上游时流式输出流程简单很多因为它是标准的 OpenAI 兼容 SSE 格式每个 chunk 都是完整 JSON没有 SageMaker chunk encoder 截断的问题。config.yaml 里不需要为此打补丁业务代码里原来的 streamTrue 参数可以原样保留。curl http://your-litellm-host:4000/chat/completions \ -H Content-Type: application/json \ -d { model: taotoken_claude, messages: [ {role: user, content: I want to make coffee} ], stream: true }正常时返回的是连续的多行 SSE JSON每行以data:开头包含完整的 choices[0].delta.content 字段。如果翻页翻到一半卡住优先看 LiteLLM 日志里的响应码和耗时是来自 TaoToken 还是来自 SageMaker。6.3 401、404、多一个 /v1排障部分只列这次配置最常遇到的三个问题。第一个是 401 Unauthorized请求到达 TaoToken 但 Key 不对。检查 config.yaml 里 api_key 是否真的填了、有没有复制时缺字符以及 Key 是否在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 控制台创建过。第二个是 404 Not FoundLiteLLM 找不到 model 对应的上游。先看请求里的 model 名称是否和 model_list 里的 model_name 完全一致再看 model 字段里的 openai/ 前缀后面有没有拼错模型 ID。第三个是连不上上游api_base 填成了 https://taotoken.net/api/v1 或者填成了官网地址LiteLLM 会把 /v1 再拼一次导致路径错误。记住接口地址就是 https://taotoken.net/api不带 /v1官网地址只用于打开控制台和模型广场。这三个问题按「模型 ID → Key → Base URL」的顺序排查基本都能定位。原文那套流式补丁只保留在 SageMaker 上游侧TaoToken 侧不需要动代码这一点对后续维护来说很关键。最后补一句经验任何 MaaS 中台只要走上多个模型共存的路线先把 Key 管理和 Base URL 规范固定下来再谈功能扩展。用 LiteLLM 做出口、TaoToken 做 SaaS 模型兼容层是我目前试过改动最小、业务侧无感的一种组合。如果还拿不准模型 ID 和用量回到 TaoToken 模型广场核对一遍是最稳妥的做法。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价