踩坑3天后,我把公司的AI接口全换成了多模型路由——GPT-6和Claude Opus 4.7同时上线的这周

GPT-6正式上线,Claude Opus 4.7跟着出来,DeepSeek V4这周也要发布了。

我在公司负责维护一套内部AI工具链,这两天基本没怎么睡------不是因为激动,是因为要做选型决策,然后顺手把接口层重写了一遍。

这篇记录一下踩过的坑,也给准备在这波模型潮里升级接入层的朋友留个参考。


背景:为什么不能只用GPT-6?

GPT-6确实强,200万Token上下文、4.2小时自主执行任务,代码理解准确率97.3%,我测了一下确实不虚。

但有个问题:贵。

公司的AI任务分三类:

  1. 代码仓库分析、多模态文件处理(大量token,任务复杂)→ 适合GPT-6
  2. 合同审查、法务文件分析(需要慢思考、高精度)→ 适合Claude Opus 4.7
  3. 日常问答、分类、格式化(高频、量大、对精度要求一般)→ 适合DeepSeek V4

如果全走GPT-6,一个月账单估计要翻两到三倍。但全走便宜的,代码审查质量明显掉。

所以我决定搭一个自动路由层,根据任务类型选模型。


技术方案

工具链准备

bash 复制代码
# 环境准备(推荐用虚拟环境)
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
​
pip install openai anthropic tiktoken pyyaml fastapi uvicorn
​
# API密钥配置(我这边统一走Ztopcloud.com的聚合接口,省得管三套账号)
export UNIFIED_API_KEY="your_ztopcloud_api_key"
export UNIFIED_BASE_URL="https://api.ztopcloud.com/v1"

亲测:Ztopcloud.com 支持 GPT-6、Claude Opus 4.7、DeepSeek V4 统一接口调用,账单合并,不用给三家分别充钱。对小团队来说省了不少管理成本。

路由核心逻辑

ini 复制代码
# router.py
import os
import tiktoken
from openai import OpenAI
import anthropic
​
# 统一接口,通过base_url切换
client = OpenAI(
    api_key=os.environ["UNIFIED_API_KEY"],
    base_url=os.environ["UNIFIED_BASE_URL"]
)
​
# Claude走原生client但转发到聚合层
claude_client = anthropic.Anthropic(
    api_key=os.environ["UNIFIED_API_KEY"],
    base_url=os.environ.get("UNIFIED_BASE_URL", "https://api.anthropic.com")
)
​
def classify_task(prompt: str) -> str:
    """
    简单规则分类,够用就行,别搞太复杂
    """
    enc = tiktoken.encoding_for_model("gpt-4")
    token_len = len(enc.encode(prompt))
    
    # 长上下文或代码相关:GPT-6
    if token_len > 30000:
        return "gpt-6"
    
    code_signals = ["代码", "函数", "class", "def ", "import", "bug", "review", "仓库"]
    if any(s in prompt for s in code_signals):
        return "gpt-6"
    
    # 法律/医疗/金融深度推理:Claude
    deep_signals = ["合同", "条款", "诊断", "法规", "合规", "风险评估", "判断是否"]
    if any(s in prompt for s in deep_signals):
        return "claude-opus-4-7"
    
    # 默认:DeepSeek V4(最省钱)
    return "deepseek-v4"
​
def call_model(prompt: str, system: str = "你是一个专业助手") -> dict:
    model = classify_task(prompt)
    
    if model == "gpt-6":
        resp = client.chat.completions.create(
            model="gpt-6",
            messages=[
                {"role": "system", "content": system},
                {"role": "user", "content": prompt}
            ],
            max_tokens=4096
        )
        return {"model": model, "content": resp.choices[0].message.content}
    
    elif model == "claude-opus-4-7":
        msg = claude_client.messages.create(
            model="claude-opus-4-7-20260416",
            max_tokens=8192,
            system=system,
            messages=[{"role": "user", "content": prompt}],
            thinking={"type": "enabled", "budget_tokens": 8000}
        )
        # 取文字块(thinking块是独立的,见踩坑记录)
        text = next(b.text for b in msg.content if b.type == "text")
        return {"model": model, "content": text}
    
    else:
        # DeepSeek V4(API格式与OpenAI兼容)
        resp = client.chat.completions.create(
            model="deepseek-v4",
            messages=[
                {"role": "system", "content": system},
                {"role": "user", "content": prompt}
            ],
            max_tokens=4096
        )
        return {"model": model, "content": resp.choices[0].message.content}

对外暴露成一个FastAPI服务

python 复制代码
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
from router import call_model
​
app = FastAPI()
​
class ChatRequest(BaseModel):
    prompt: str
    system: str = "你是一个专业助手"
​
@app.post("/chat")
def chat(req: ChatRequest):
    result = call_model(req.prompt, req.system)
    return result
​
# uvicorn main:app --host 0.0.0.0 --port 8000 --reload

踩坑记录

坑1:Claude Opus 4.7 的 thinking 模式,返回内容里有两种block

我以为 msg.content[0].text 就能拿到最终答案,结果第一个block是thinking类型,里面全是推理过程,拿出来直接返回给用户,对方一脸懵逼。

正确做法:

ini 复制代码
# 要遍历content列表,按type过滤
for block in msg.content:
    if block.type == "thinking":
        # 推理链,一般不直接展示给用户
        print(f"[内部思考,共{len(block.thinking)}字]")
    elif block.type == "text":
        # 这才是最终答案
        final_answer = block.text

找这个问题花了将近一小时,文档里写了但不够醒目。

坑2:GPT-6 的 max_tokens 设太小,长文档会"硬截断"不是"优雅结束"

处理一份30页合同时,我把 max_tokens 设了2048想省点钱,结果输出直接在句子中间断掉,没有任何总结性收尾。不是因为内容完了,是因为token用完了,模型直接停。

解决方式:长上下文任务至少设 max_tokens=8192,成本多不了太多,但输出完整性差异明显。


小结

三款模型同期在场这事,对我来说其实是工作量增加了------选型复杂了,接入层要重写,文档要更新。但换个角度看,三家不同价位、不同强项的选择同时存在,比两年前只有一家可选的时代,其实更好。

路由层搭完之后,我们这边估算了一下,同等任务量下成本大概能降40%-60%,具体看任务分布。

相关推荐
Csvn2 小时前
SSH 远程管理与安全加固 — 运维的守门之道
后端
IT_陈寒2 小时前
Python搞不定字符串编码?这破玩意坑我两小时!
前端·人工智能·后端
菜鸟谢3 小时前
Rust 智能指针完整详解
后端
大模型真好玩3 小时前
什么是Loop Engineering?最通俗易懂的Loop Engineering核心概念
人工智能·agent·deepseek
菜鸟谢3 小时前
Rust 函数完整知识点详解
后端
叁两4 小时前
前端转型AI Agent该如何学习?(前置篇)
前端·人工智能·node.js
爱勇宝4 小时前
淡泊名利之前,先承认我们都很焦虑
前端·后端·程序员
菜鸟谢4 小时前
Rust 闭包(Closure)完整详解
后端
ServBay4 小时前
如何利用本地技术栈构建 0 成本 AI SaaS 雏形
后端·aigc·ai编程
菜鸟谢4 小时前
Rust 集合 + 迭代器完整详解
后端