简书

OpenClaw + 147AI:把多模型调用从业务代码里抽离(简书笔记版)

这是一篇纯技术笔记:不做价格对比、不做平台推荐。只记录一件事——当你需要“能长期跑”的多模型流程时,怎么把接入复杂度从业务层搬走。


1)我遇到的真实问题:多模型项目最先烂掉的不是 Prompt

做 AI 功能时,大家最早关注的是 Prompt、效果、幻觉。
但如果项目要上线,最先把工程拖垮的往往是这些“水管活”:

  • SDK/协议差异:每家模型一套参数、返回结构、流式细节;AB 实验很快就变成“全局改接口”。
  • Key/鉴权散落:Key 分在多个服务、多个环境变量里,轮换和排错都费劲。
  • 运行时行为不一致:超时、错误码、重试、fallback、并发限制,每家都不一样,最后业务层塞满 if-else。

你以为在做“智能体”,结果写出来是一堆适配层。


2)一个更省心的思路:统一入口 + 可配置调度

我现在更倾向于把模型当成“可替换的基础设施”,像数据库连接一样对待:

  • 业务层只知道一个入口(例如 OpenAI 风格的 /v1)和一个 model 字符串
  • 模型选择、fallback、allowlist、失败策略放在配置/网关层

这篇文章用两个组件来落地这件事:

  • OpenClaw:负责流程编排与运行时治理(模型选择、fallback、工具等都更适合放配置里)
  • 147AI:提供 OpenAI 风格 /v1 入口作为示例网关

为了避免写成宣传,我只写两条能确认的技术事实:147AI 对外暴露的是 OpenAI 风格 /v1 路径(例如 /v1/chat/completions),并且未携带令牌时会返回 401 提示“未提供令牌”。除此之外(比如支持哪些模型、具体参数),请以你登录控制台后看到的列表为准。


3)把 147AI 接进 OpenClaw:自定义一个 Provider

OpenClaw 的配置文件默认在:

  • ~/.openclaw/openclaw.json(JSON5,支持注释与尾逗号)

你可以先跑一遍向导把环境搭起来:

openclaw onboard

接下来把 147AI 当作一个 OpenAI 风格 Provider(OpenClaw 的 openai-completions 协议)。下文里我用“网关域名”占位,避免正文出现过多外链文本:

// ~/.openclaw/openclaw.json(片段)
{
  models: {
    mode: "merge",
    providers: {
      api147: {
        baseUrl: "https://<你的网关域名>/v1",
        apiKey: "${API147_KEY}",
        api: "openai-completions",
        // 具体模型 id 以你在 147AI 控制台/文档里看到的为准
        models: [{ id: "your-model-id", name: "Primary" }],
      },
    },
  },

  agents: {
    defaults: {
      model: { primary: "api147/your-model-id" },
    },
  },
}

Key 用环境变量注入(示例):

export API147_KEY="你的令牌"

到这一步,你已经把“模型接入”从业务代码挪到了配置层:业务侧不需要知道你背后换了哪家模型,只需要 provider/model-id


4)最小验证:先确认鉴权和 /v1 入口通不通

最常见的“看似配好了但跑不通”,本质都是鉴权没带上。

你可以用 curl 先测一下(不带令牌会 401)。把 <你的网关域名> 替换成你实际使用的网关域名:

curl -i -X POST 'https://<你的网关域名>/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -d '{"model":"your-model-id","messages":[{"role":"user","content":"ping"}]}'

如果你用 OpenAI Python SDK 做连通性验证,一般是这样:

from openai import OpenAI

client = OpenAI(
    api_key="你的令牌",
    base_url="https://<你的网关域名>/v1",
)

resp = client.chat.completions.create(
    model="your-model-id",
    messages=[{"role": "user", "content": "ping"}],
)

print(resp.choices[0].message.content)

排错时我通常先盯四件事:

  • base_url 是否以 /v1 结尾
  • model 是否是你控制台里真实存在的 ID
  • 401 是否是“未提供令牌/令牌无效”(多数情况下就是这个)
  • 如果在 OpenClaw 里切模型没反应,先看 allowlist

5)一个容易踩的坑:allowlist 把你自己拦住了

OpenClaw 里如果设置了 agents.defaults.models,它会变成允许列表(allowlist)。
你在会话里用 /model 选择的模型不在列表里,就会出现 “Model is not allowed” 之类的提示。

处理方式也简单:

  • 不需要限制就去掉 allowlist
  • 需要限制就把 api147/your-model-id 明确加进去

这个问题在多模型场景非常常见:不是接口坏了,是配置把你挡住了。


6)多模态/视频这类请求,别按“文本请求”写

最后补一句经验:图片、音频、视频这些请求,工程形态更像“任务系统”,不是一次 HTTP 就完事的聊天接口。

如果你后面要接视频生成,建议直接按异步任务设计:

  • 任务创建返回 task_id
  • 轮询/回调查询状态
  • 失败可重试、可取消、可降级

把它当成“作业系统”会更稳。


7)收尾

这篇笔记想证明的只有一件事:多模型不是“多写几份 SDK 适配”,而是“统一入口 + 配置化调度”。
当你把入口收敛到 /v1,把策略搬到 OpenClaw 配置层,业务代码会干净很多,后续做成本控制、稳定性兜底也更顺手。

合集导航回到合集目录 →
上一章
掘金
下一章
虎扑
← 返回博客列表