跳到主内容
快讯直播
AI智模界
教程

豆包工作接入Kimi与DeepSeek:多模型切换与分流

这篇能做出什么

做完之后,你会有一个不绑死在任何一家模型上的工作台:

  • 同一个入口,能在豆包、Kimi、DeepSeek 之间切换,换模型不用换工具、不用重新贴一遍上下文;
  • 一张写死的「任务—模型」分工表,常见任务默认走指定模型,遇到特殊任务临时改一行配置就能改道;
  • 一层几十行的统一调用代码,三家模型走同一套参数,谁家接口出问题可以自动降级到另一家;
  • 一份调用日志,记录每次用了哪个模型、花了多少 token、耗时多久,一周后你能拿着数据回答「这个任务到底该用谁」。

举个具体场景:你上午要读一份 60 页的合同并出摘要,中午要把会议录音整理成纪要,下午要写一段数据清洗脚本。这三件事的最优解大概率不是同一个模型。有工作台的做法是:合同走长上下文能力强的模型,纪要走中文表达顺手的模型,脚本走代码能力强的模型——你只切换一个任务标签,背后自动改道。

关于「豆包工作」本身:这类成品工作台产品通常在设置里提供「自定义模型 / 接入第三方 API」的入口,具体位置、支持的字段、能配几个模型,以官方页面当前版本为准,产品改版后界面会变。所以本文的做法分两层——能配的地方直接配,配不了的部分用一个本地脚本兜底,两层互不冲突。

前置条件清单

动手前先把这些准备好,缺一项后面就会卡住:

1. 三个平台的账号:豆包(火山方舟开放平台)、Kimi(Moonshot 开放平台)、DeepSeek 开放平台。按各家要求完成实名或企业认证。

2. 三个 API Key:每家控制台里都能创建,创建后只显示一次,记得当场保存。

3. Python 环境:Python 3 即可,不需要特殊版本。

4. 一个能装包的终端:pip install openai python-dotenv。三家平台都提供 OpenAI 兼容接口,所以一个 SDK 通吃。

5. 三份配置信息:每家的 base_url(接口地址)、model(模型名)。这两项在各家控制台的「API 文档 / 接入指南」页能找到,具体取值以官方文档当前版本为准,模型名会随平台迭代新增和下线。

6. 十到二十条你自己的真实任务:用来校准分工表。没有这个,分工表只能照抄别人的经验,大概率不准。

7. 额度与账单提醒:三家控制台都有额度设置或用量告警,开通时顺手设一下,别等月底。

步骤一:把授权做成「可撤销」的

这一步最容易被跳过,但它是整个工作台的地基。三条纪律:

一、一家一个 Key,命名带用途。 创建时备注「个人工作台-2024xx」这种信息,别叫 test。将来要吊销时你知道吊销的是哪一个。

二、Key 只进环境变量,不进代码。 新建项目目录,写一个 .env:

```bash

.env —— 这个文件永远不进 git

DOUBAO_API_KEY=你的豆包key

DOUBAO_BASE_URL=控制台给的兼容地址

DOUBAO_MODEL=控制台给的模型名

KIMI_API_KEY=你的Kimi key

KIMI_BASE_URL=控制台给的兼容地址

KIMI_MODEL=控制台给的模型名

DEEPSEEK_API_KEY=你的DeepSeek key

DEEPSEEK_BASE_URL=控制台给的兼容地址

DEEPSEEK_MODEL=控制台给的模型名

```

配套的 .gitignore:

```bash

.gitignore

.env

*.log

logs/

__pycache__/

```

三、权限最小化 + 额度封顶。 能只开推理权限就别开管理权限;能设月度上限就设。API Key 泄露最常见的路径不是被黑,是自己 push 到了公开仓库。

步骤二:先跑通三条通路,别急着写路由

新手常犯的错是一上来就写路由和分流,结果报错时不知道是路由写错了还是 Key 配错了。先做最笨的事:一个模型一个模型地单独跑通。

```python

smoke_test.py

import os

from dotenv import load_dotenv

from openai import OpenAI

load_dotenv()

def ping(prefix: str):

key = os.getenv(f"{prefix}_API_KEY")

base = os.getenv(f"{prefix}_BASE_URL")

model = os.getenv(f"{prefix}_MODEL")

client = OpenAI(api_key=key, base_url=base)

resp = client.chat.completions.create(

model=model,

messages=[{"role": "user", "content": "用一句话说明你是什么模型"}],

max_tokens=100,

)

print(f"[{prefix}] OK -> {resp.choices[0].message.content}")

for p in ["DOUBAO", "KIMI", "DEEPSEEK"]:

try:

ping(p)

except Exception as e:

print(f"[{p}] FAILED -> {type(e).__name__}: {e}")

```

三个都打印 OK,再往下走。任何一个报错,先看后面的「常见坑与排错」,不要继续往下叠代码。

步骤三:写一层统一调用

三家的参数名基本一致(model / messages / temperature / max_tokens),但返回结构和错误码不完全一样。包一层,把差异挡在外面:

```python

workbench.py

import os, time, json

from datetime import datetime

from dotenv import load_dotenv

from openai import OpenAI

load_dotenv()

PROVIDERS = {

"doubao": {"key": "DOUBAO", "style": "中文写作、纪要润色、生态内文档联动"},

"kimi": {"key": "KIMI", "style": "长文档通读、多文件对照"},

"deepseek": {"key": "DEEPSEEK", "style": "代码、结构化抽取、批量处理"},

}

def _client(name: str):

prefix = PROVIDERS[name]["key"]

return OpenAI(

api_key=os.getenv(f"{prefix}_API_KEY"),

base_url=os.getenv(f"{prefix}_BASE_URL"),

), os.getenv(f"{prefix}_MODEL")

def call(name: str, messages: list, temperature: float = 0.3, max_tokens: int = 2000) -> dict:

client, model = _client(name)

t0 = time.time()

resp = client.chat.completions.create(

model=model,

messages=messages,

temperature=temperature,

max_tokens=max_tokens,

)

text = resp.choices[0].message.content

usage = resp.usage.model_dump() if resp.usage else {}

return {

"model_name": name,

"text": text,

"latency_s": round(time.time() - t0, 2),

"prompt_tokens": usage.get("prompt_tokens"),

"completion_tokens": usage.get("completion_tokens"),

}

```

注意 temperature 和 max_tokens 各家默认值和取值范围有差异,部分模型对某些参数不敏感甚至忽略。如果你发现调了没反应,去查该模型的参数说明,别怀疑代码。

步骤四:定分工表(这是全篇最值钱的一步)

不要把分工表当成「谁更强」的排行榜,它是你自己任务分布的映射。按任务类型分,不按模型分:

任务类型标签默认模型判断依据
长文档通读、多文件对照long_docKimiAI 词典:上下文窗口">上下文窗口大,塞整份材料不用切
代码生成、脚本、正则codeDeepSeek代码场景表现稳定
结构化抽取(表格、字段)extractDeepSeek输出格式较可控,适合批处理
中文写作、纪要润色writing豆包中文表达自然,和日常办公场景贴合
会议纪要、内部问答meeting豆包同上,且能和其他办公工具联动
需要先想再答的推理题reasoningDeepSeek挑带推理模式的模型
拿不准的杂活default豆包日常主入口

三条使用心得:

1. 按「输入长度」分流比按「任务名」分流更靠谱。 一句话的活儿谁都行;超过两三万字的材料,先看谁吃得下,再看谁答得好。

2. 批量任务先小样本试。 要处理 500 条数据,先跑 20 条看抽取准确率,别一次性把额度打光。

3. 同一个 prompt 换模型,效果可能差一截。 换模型时提示词要跟着调,尤其是输出格式要求。别用一套提示词打三家。

步骤五:加路由,带手动开关和自动降级

```python

router.py

from workbench import call

ROUTES = {

"long_doc": "kimi",

"code": "deepseek",

"extract": "deepseek",

"reasoning": "deepseek",

"writing": "doubao",

"meeting": "doubao",

"default": "doubao",

}

降级顺序:主模型失败时依次尝试

FALLBACK = ["doubao", "kimi", "deepseek"]

def route(task_type: str, messages: list, override: str | None = None) -> dict:

primary = override or ROUTES.get(task_type, ROUTES["default"])

order = [primary] + [m for m in FALLBACK if m != primary]

last_err = None

for name in order:

try:

result = call(name, messages)

result["task_type"] = task_type

result["fallback_used"] = (name != primary)

return result

except Exception as e:

last_err = e

print(f"[warn] {name} 调用失败,尝试下一个:{type(e).__name__}")

raise RuntimeError(f"全部模型调用失败:{last_err}")

```

override 这个参数就是「自由切换」的入口。命令行里加个 --model kimi,或者在工作台设置里改一个默认值,就能覆盖分工表。默认走规则,特殊任务手动改道,这个组合比纯自动更实用——自动路由猜错的成本,比手动点一下高。

配一个最小命令行入口:

```python

cli.py

import argparse, sys

from router import route

p = argparse.ArgumentParser()

p.add_argument("--task", default="default")

p.add_argument("--model", default=None, help="手动指定模型,覆盖分工表")

p.add_argument("--file", default=None, help="从文件读入提示词")

a = p.parse_args()

prompt = open(a.file, encoding="utf-8").read() if a.file else sys.stdin.read()

res = route(a.task, [{"role": "user", "content": prompt}], override=a.model)

print(res["text"])

print(f"\n--- {res['model_name']} | {res['latency_s']}s | "

f"in={res['prompt_tokens']} out={res['completion_tokens']}", file=sys.stderr)

```

用法:

```bash

echo "把这堆会议记录整理成带负责人和截止日的纪要:..." | python cli.py --task meeting

cat 合同.txt | python cli.py --task long_doc

python cli.py --task code --model doubao --file prompt.txt # 手动改道

```

步骤六:留痕,不然分工表永远校准不了

每次调用追加一行 JSON 到日志文件:

```python

logger.py

import json, os

from datetime import datetime

def log(res: dict, note: str = ""):

os.makedirs("logs", exist_ok=True)

path = f"logs/{datetime.now():%Y-%m}.jsonl"

row = {

"ts": datetime.now().isoformat(timespec="seconds"),

"task": res.get("task_type"),

"model": res["model_name"],

"fallback": res.get("fallback_used", False),

"latency_s": res["latency_s"],

"in": res["prompt_tokens"],

"out": res["completion_tokens"],

"note": note,

}

with open(path, "a", encoding="utf-8") as f:

f.write(json.dumps(row, ensure_ascii=False) + "\n")

```

一周后看三个数:哪类任务的返工率高(你手动改了结果的次数)、哪类任务的耗时集中、哪个模型被降级次数多。返工率高的任务,就换模型试;降级多的模型,去看是不是额度或者限速的问题。

常见坑与排错

401 / 403

Key 错、Key 被吊销、Key 没有该模型的调用权限。先确认 .env 里没有多余空格和引号,再回控制台看这个 Key 是否还活着。

404 model not found

模型名写错,或者豆包这类平台需要用「推理接入点 ID」而不是模型名。两者都去控制台复制粘贴,别手打。模型名随平台迭代会变,以官方文档当前版本为准。

400 上下文超长

输入加输出超过窗口上限。解决办法是切分:按章节、按段落拆,每段单独摘要后再做二次汇总。别指望「超一点没关系」。

429 限流

批量任务必须加重试和退避。简单做法:

```python

import time

def with_retry(fn, times=3):

for i in range(times):

try:

return fn()

except Exception as e:

if "429" in str(e) and i < times - 1:

time.sleep(2 ** i * 2)

continue

raise

```

JSON 解析失败

让模型输出 JSON 时,把字段名和类型写进提示词,并且代码里做兜底:先尝试 json.loads,失败就用正则抠出第一个 {...} 再解析。三家模型对格式的严格遵守程度不一样,兜底不能省。

费用悄悄失控

常见原因有三个:把整份长文档反复贴进上下文(每次都重新计费)、循环里没设退出条件、批量任务没做小样本验证。养成习惯:批量前先跑 20 条,估算总消耗再放开。

Key 提交到 git

如果已经 push 了,第一件事是去控制台吊销重建,不是删 commit。历史记录里的 Key 依然有效。

同一份提示词换个模型就不好使

这不是模型的问题,是提示词过拟合了。把「必须输出三段」「不要用markdown」这类硬性要求保留,把具体的措辞示例按模型微调。

下一步建议

1. 建一个 20 条的小评测集。 把你最常做的任务各挑几条,固定输入,记录三家模型的输出和你的人工评分。以后换模型、平台升级,跑一遍就知道要不要调整分工表。

2. 加上缓存。 同样的输入算过就别再算,尤其是长文档摘要这类贵操作。用输入内容的哈希做键,存到本地 sqlite 或者文件里都行。

3. 把降级链写进规则里。 现在是无脑轮询下一个,可以改成「只降级到同类能力的模型」,避免代码任务被降级到一个不擅长代码的模型,结果更差。

4. 脱敏前置。 如果会处理客户名单、合同金额这类内容,在 call() 之前加一层正则替换,把身份证、手机号、金额替换成占位符,回来再还原。

5. 接进日常入口。 成品工作台里能配自定义模型的地方直接配;配不了的,把 cli.py 包成一个快捷命令或者本地小界面,跟工作台放同一个屏幕。工具换了,习惯不用换。

这套东西的价值不在于「用了三个模型」,而在于你随时可以换掉其中任何一个。哪家涨价、哪家限流、哪家出了更强的版本,你改一行配置就行,工作流不动。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。