mcpField
A
ai-model-web

ai-model-web

github.com/tencentcloudbase开发1.2k46 次安装1 天前更新
代码仓库

关于 ai-model-web

用于通过 `@cloudbase/js-sdk` 在浏览器 Web 应用中调用 AI 模型的 CloudBase 技能,要求在编写 SDK 代码前检查资源资格和模型组状态。

主要功能

  1. 01浏览器端模型调用
  2. 02文本响应流式输出
  3. 03Token 资源包资格检查
  4. 04模型组与目录检查
  5. 05托管及自定义模型组

适用场景

  1. 01在 Web 应用中添加文本生成
  2. 02在前端流式呈现模型输出
  3. 03集成前检查环境调用资格
  4. 04为应用启用模型

MCP 相关

该技能通过 CloudBase MCP 工具查询环境、检查 Token 资源包资格,并在 SDK 调用前发现或配置模型组。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tencentcloudbase/cloudbase-ai-toolkit --skill ai-model-web

安装后在 Claude Code 中输入/ai-model-web确认已加载。

详细介绍

同级技能(仅本地)

同级 CloudBase 技能与此技能一同提供。请使用 ../auth-tool-cloudbase/SKILL.md 这类本地相对路径。

如果此环境中缺少引用的同级技能文件,请让用户安装完整的 CloudBase 插件(或缺少的技能)。不要通过 HTTP 将远程技能或协议 Markdown 获取到 Agent 上下文中。

何时使用此技能

通过 @cloudbase/js-sdk 在浏览器/Web 应用中调用 AI 模型时,请使用此技能。

🧭 Web 默认使用运行时平面。 只要用户的请求围绕页面、Web 应用、前端、React/Vue/Next/Nuxt、仪表盘 UI 或“为我的 H5 添加 AI”展开,此技能就是默认路由目标。不要先提议使用 Node.js / 云函数 / CloudRun 代理;@cloudbase/js-sdk 可以直接从浏览器调用模型。只有在用户明确要求进行后端/服务端调用、图像生成,或场景确实需要服务端密钥或长时间运行的工作时,才切换到 ai-model-nodejs。此决策与用户选择的具体模型无关——模型名称(deepseek-*、glm-*、hunyuan-*、kimi-* 等)只影响 model 字段,不影响路由平面。

在以下情况使用:

  • 将 AI 文本生成集成到前端 Web 应用
  • 流式传输 AI 回复,改善用户体验
  • 从浏览器调用 Hunyuan / DeepSeek / GLM / Kimi / MiniMax 模型

以下情况不要使用:

  • Node.js 后端或云函数 → 使用 ai-model-nodejs 技能
  • 微信小程序 → 使用 ai-model-wechat 技能
  • 图像生成 → 使用 ai-model-nodejs 技能(仅限 Node SDK)
  • 不支持 CloudBase SDK 的运行时(原生应用、Python、Go 等)→ 使用 http-api-cloudbase 技能(该技能现已包含用于直接 HTTP 调用的 ai_model OpenAPI 规范;不要构建自定义 HTTP 代理)

⛔ 停止 — ai.createModel(...) 参数不是厂商/模型名称

请在编写任何 createModel(...) 代码行之前阅读此内容。Agent 为此 SDK 生成代码时,最常见的错误就是臆造参数。合法形式恰好有三种,其他任何形式都是错误。

✅ 合法的 ai.createModel(...) 参数使用时机
"cloudbase"新项目使用的主要托管组(由 TokenHub 提供支持的多厂商模型池)。厂商和具体模型应放入 generateText / streamText 的 model 字段,例如 { model: "deepseek-v4-flash" }。默认不会启用任何模型 — 调用 SDK 前务必先检查 DescribeAIModels;如果缺少目标模型,则先使用 UpdateAIModel 启用它。
"hunyuan-exp"仅当 DescribeAIModels 明确为当前环境返回此旧版内置组时使用(主要用于小程序成长计划 — 请参阅 ai-model-wechat)。
"custom-<your-name>"通过 CreateAIModel 接入的用户自定义 GroupName。必须以 custom- 开头(例如 custom-kimi、custom-openai-compat)。
❌ 不要编写以下任何内容 — 它们全都不正确
ai.createModel("deepseek")                 // wrong — that's a vendor, not a GroupName
ai.createModel("deepseek-v4-flash")        // wrong — that's a model name, goes in the `model` field
ai.createModel("hunyuan")                  // wrong — vendor family, not a GroupName
ai.createModel("hunyuan-2.0-instruct-20251111")  // wrong — model name
ai.createModel("glm") / ai.createModel("kimi") / ai.createModel("minimax")  // wrong — vendor names
ai.createModel("openai") / ai.createModel("moonshot")  // wrong — vendor names
ai.createModel("custom")                   // wrong — placeholder; use your real custom-<name>
ai.createModel(modelName)                  // wrong — do not reuse the variable that holds the model id
✅ 正确模式 — GroupName 和 Model 是两个不同的字段
const model = ai.createModel("cloudbase");          // ← GroupName
await model.generateText({
  model: "deepseek-v4-flash",                       // ← concrete model id
  messages: [...]
});
决策流程(用户指定具体模型时)
  1. 用户说“使用 DeepSeek v3.2”/“使用 hunyuan instruct”/“使用 Kimi k2.6”/“使用 GLM-5”/……
  2. createModel("cloudbase") 保持不变。
  3. 将模型 ID 填入 model 字段:{ model: "deepseek-v3.2" }、{ model: "hunyuan-2.0-instruct-20251111" }、{ model: "kimi-k2.6" }、{ model: "glm-5" },……
  4. 切勿假设模型已启用。 编写 SDK 调用前,请确认模型已包含在 DescribeAIModels({ GroupName: "cloudbase" }).Models[] 中。如果缺少该模型,请调用 DescribeManagedAIModelList 确认平台支持的确切 Model 名称(区分大小写,不要猜测拼写),然后通过 UpdateAIModel 将其启用,并设置 Status: 1(请记住,Models 会整体替换,因此要重新传入所有已启用的模型以及新模型)。

如果你准备输入 ai.createModel(,而括号内是供应商名称、模型名称或猜测值,请停下。它几乎肯定不属于上述三个合法值。


强制两步预检(编写任何 SDK 代码之前)

生成任何 AI 相关的 SDK 代码之前,请先执行两步预检:① 资格检查,② 分组就绪检查。直接输出 createModel(...),让用户自行排查运行时错误,代价要高得多。

第 0 步:获取环境 ID

调用 MCP 工具 queryEnv,设置 action=info,并从响应中读取 EnvId。后续每项检查和购买链接都使用此 EnvId。


预检 ① — 资格检查(Token Credits 资源包)

调用 MCP 工具:

callCloudApi(service="tcb", action="DescribeEnvPostpayPackage", params={ EnvId })

通过条件(必须全部满足):

  • envPostpayPackageInfoList 至少包含一个条目

  • 该条目的 postpayPackageId 以 pkg_tcb_tokencredits_ 开头

  • 该条目的 status 不在 [3, 4] 中(3 / 4 通常表示已过期 / 已停用;请以实时响应为准)

  • ❌ 未满足 → 停止编写代码,并向用户说明以下内容(将 {envId} 替换为实际 ID):

    当前环境没有启用中的 Token Credits 资源包。调用任何 AI API 前,请先购买资源包: https://buy.cloud.tencent.com/lowcode?buyType=resPack&envId={envId}&resourceType=token

    完成后请告知我,我会重新检查资源包状态。

  • ✅ 已满足 → 继续进行预检 ②。

根据约定,参数名使用 PascalCase。如果调用返回 InvalidParameter,请改用 camelCase(envId / envPostpayPackageInfoList),并以实时响应为准。对于小程序场景,还需额外检查增长计划分支——请切换到 ai-model-wechat 技能。


预检 ② — 分组就绪情况(DescribeAIModels → 必要时调用 UpdateAIModel)

仅满足资格条件还不够。**暂时不要调用 createModel("cloudbase")。**首先确认目标 GroupName 在环境中存在且 Status=1,并且目标 Model 已包含在其 Models[] 中。

  1. 列出当前环境中已配置的分组:

    callCloudApi(service="tcb", action="DescribeAIModels", params={ EnvId })
    

    返回 AIModelGroups: AIModelGroup[],其中每个 AIModelGroup 都包含 GroupName、Type(builtin / custom)、Models: [{ Model, EnableMCP, Tags }]、Status(1 = 开启 / 2 = 关闭)、BaseUrl、Secret、Remark。主要托管分组的 GroupName 是 cloudbase。

  2. **切勿假定某个模型已启用。**检查 cloudbase 分组中的 AIModelGroups[?].Models[].Model。如果缺少目标模型(或者用户未指定模型时,你打算默认使用的模型,例如 deepseek-v4-flash),请跳转到第 4 步并启用它——暂时不要调用 createModel("cloudbase")。如果 cloudbase 分组本身不存在或其 Status=2,也请跳转到第 4 步。

  3. 用户指定了属于托管目录的模型(例如 deepseek-v3.2、hunyuan-2.0-instruct-20251111、glm-5、kimi-k2.6 等):检查该 Model 是否已包含在 cloudbase 分组的 Models[] 中。如果没有,请跳转到第 4 步。不要猜测确切的模型 ID——请先通过 DescribeManagedAIModelList 确认规范写法(第 4 步会介绍)。

  4. 启用 / 添加托管模型(务必先检查权威目录和定价):

    callCloudApi(service="tcb", action="DescribeManagedAIModelList", params={ EnvId })
    

    返回 ManagedAIModelGroup[],其中每个分组都列出 GroupName(例如 cloudbase)、Remark 和 Models: [{ Model, EnableMCP, ModelSpec{ContextLength, MaxInputToken, MaxOutputToken}, ModelChargingInfo[{Type, InputPrice, OutputPrice, InputOutputUnit, CachePrice}] }]。**这是受支持模型名称和定价的唯一权威来源——不要凭记忆推断。调用 UpdateAIModel 时,请使用此处返回的确切 Model 字符串。**启用前也请向用户说明价格。

    然后启用(注意:Models 是全量替换——请始终连同已启用的模型一起重新传入新模型):

    callCloudApi(service="tcb", action="UpdateAIModel", params={
      EnvId,
      GroupName: "cloudbase",
      Models: [
        // resend every model that DescribeAIModels already showed as enabled
        { Model: "<already-enabled model, e.g. deepseek-v4-flash>" },
        // append the newly-requested one, using the exact spelling from DescribeManagedAIModelList
        { Model: "<target model>" }
      ],
      Status: 1
    })
    
  5. 请求的模型不在托管目录中(未通过 DescribeManagedAIModelList 找到)→ 跳转到下一节,自定义接入(托管目录之外的模型)。

所有 Actions 均使用 service=tcb、Version=2018-06-08。参数使用 PascalCase(EnvId / GroupName / Models / Status)。只有在调用返回 InvalidParameter 时,才回退为 camelCase。


可用的提供商和模型

ai.createModel(<GroupName>) 仅接受以下三种合法值:

1. "cloudbase" — 主要托管分组(推荐)
  • GroupName: "cloudbase"、Type: "builtin"、Remark: "腾讯云开发"(Tencent CloudBase)
  • 由腾讯云 TokenHub提供支持,这是一个统一托管池,涵盖多个供应商——混元(HY 2.0 Instruct、HY 2.0 Think、Hunyuan-role、Hy3 preview 等)、DeepSeek(DeepSeek-V4-Pro、DeepSeek-V4-Flash、Deepseek-v3.2、Deepseek-v3.1、Deepseek-r1-0528、Deepseek-v3-0324 等)、智谱 GLM(GLM-5、GLM-5-Turbo、GLM-5.1、GLM-5V-Turbo)、Kimi(K2.5、K2.6)、MiniMax(M2.5、M2.7)等。模型列表会持续更新——不要在应用代码中硬编码特定 SKU;请在运行时查询。
  • **默认情况下不会启用任何模型。**务必先调用 DescribeAIModels,查看环境中实际启用的模型;如果缺少目标模型,请调用 DescribeManagedAIModelList 获取权威目录和定价,然后调用 UpdateAIModel(Status: 1,Models 全量替换)启用模型,再调用 SDK。
  • 权威目录和定价:DescribeManagedAIModelList
  • 环境中已启用的模型集合:DescribeAIModels
2. "hunyuan-exp" — 为兼容性保留的旧版内置分组
  • 主要适用于小程序增长计划场景;Web 端不要使用,除非环境明确仍有该分组(此流程请改用 ai-model-wechat 技能)
  • 默认模型:hunyuan-2.0-instruct-20251111;其他 hunyuan SKU 必须在运行时通过 DescribeAIModels({ GroupName: "hunyuan-exp" }).Models[] 获取,不要硬编码其他 ID
3. 用户自定义 GroupName
  • 通过 CreateAIModel 接入(见下一节)。自定义 GroupName 必须以 custom- 开头(例如 custom-kimi、custom-moonshot、custom-openai-compat)。此命名约定可避免与平台未来可能引入的内置或供应商 GroupName(cloudbase、hunyuan-exp、deepseek、glm、kimi、minimax,等等)发生冲突
  • 示例:createModel("custom-kimi")、createModel("custom-openai-compat")

切勿使用 createModel("deepseek") 或 createModel("custom") 这样的猜测值,除非 DescribeAIModels 明确返回了完全相同的 GroupName(旧环境可能仍带有历史遗留的 deepseek / hunyuan-exp 内置分组;为兼容性仍允许使用,但新项目应始终通过 cloudbase 接入)。


自定义接入(托管目录之外的模型)

当用户想要调用非托管模型(自托管、企业内部模型、第三方 OpenAI 兼容端点,等等)时,不要阻止。请引导他们完成接入:

选项 1:控制台流程(推荐,由用户自行处理)

https://tcb.cloud.tencent.com/dev?envId={envId}#/ai

选项 2:以编程方式接入(CreateAIModel)
callCloudApi(service="tcb", action="CreateAIModel", params={
  EnvId: "<envId>",
  GroupName: "custom-<your-name>",  // MUST start with "custom-" (e.g. custom-kimi, custom-openai-compat); never start with "cloudbase"
  BaseUrl: "<OpenAI-compatible endpoint, e.g. https://api.moonshot.cn/v1>",
  Models: [
    { Model: "<model name, e.g. kimi-k2.5>", EnableMCP: true }
  ],
  Remark: "<optional remark>",
  Status: 1,
  Secret: { ApiKey: "<vendor api key supplied by the user>" }
})

接入后,使用 DescribeAIModels 确认分组已就绪,然后在代码中调用 ai.createModel("<the GroupName you just registered>")。使用 UpdateAIModel 添加或移除模型、轮换密钥,或更改 BaseUrl(请记住,Models 是完全替换)。使用 DeleteAIModel 删除自定义分组(内置分组无法删除)。

自定义模型的费用由第三方提供商收取,不会从 Token Credits 资源包中扣除。字段大小写遵循实时契约;遇到 InvalidParameter 时,请改用 camelCase。


安装

npm install @cloudbase/js-sdk

初始化

⚠️ 不要将匿名登录用作默认方式。 新环境默认禁用匿名登录,已有的不活跃环境也已自动禁用。即使手动启用了匿名登录,匿名用户默认也没有调用 AI 模型的权限。AI 模型技能不规定特定的登录界面——请将相关工作交由相应技能处理:

  • 启用 / 配置登录提供方(手机短信、电子邮件、微信开放平台、用户名+密码、OAuth 等)→ 遵循 auth-tool-cloudbase 技能(通过 callCloudApi 配置后端)。
  • 在浏览器中构建实际的登录流程(登录表单、回调、会话守卫)→ 遵循 auth-web-cloudbase 技能(使用 @cloudbase/js-sdk 认证 API,例如 signInWithPassword、signInWithPhone、getSession)。

AI 功能不要回退到 signInAnonymously()——匿名用户无法调用 AI 模型。仅在用户明确提出要求并接受这一取舍时,才将匿名登录用于非 AI 的只读演示。

import cloudbase from "@cloudbase/js-sdk";

const app = cloudbase.init({
  env: "<YOUR_ENV_ID>",
  accessKey: import.meta.env.VITE_PUBLISHABLE_KEY  // auto-provision via queryAppAuth / manageAppAuth, write to .env.local (see auth-web-cloudbase prerequisites)
});

const auth = app.auth;

// CRITICAL: Use auth.getSession() to check login — NOT the deprecated getLoginState().
// getLoginState() returns uid even without real login (just accessKey), causing false positives.
// getSession() returns data.session === undefined when no real login exists.
// Anonymous users are DENIED AI model permissions — calling AI without real login will fail.
const { data: sessionData } = await auth.getSession();
if (!sessionData?.session || sessionData.session.user?.is_anonymous) {
  // No real login or anonymous session — route to sign-in page
  window.location.href = "/login";
  return;
}

const ai = app.ai();

重要说明:

  • 使用顶层导入进行同步初始化
  • accessKey 会导致 getLoginState() 返回误导性的认证数据——已弃用的 getLoginState() 即使在未实际登录时也会返回带有 uid 的对象,这会导致简单的 !!loginState 检查失效。请改用 auth.getSession():在不存在实际登录时,它会返回 data.session === undefined,因此 !!data.session 是可靠的认证门控条件。
  • 使用 AI 功能前,用户必须通过已验证的登录方式(手机、电子邮件、微信、用户名+密码、自定义方式)完成认证。匿名用户没有 AI 模型权限。具体流程由 auth-web-cloudbase 技能负责。
  • 从 CloudBase 控制台获取 accessKey

generateText() — 非流式

前提条件: 已通过两步预检(资格检查 + 分组就绪检查),并已确认目标模型存在于 DescribeAIModels({ GroupName: "cloudbase" }).Models[] 中——如果模型不存在,则此时应已通过 UpdateAIModel 启用。以下示例仅以 deepseek-v4-flash 作说明;请替换为用户实际要求的模型。

const model = ai.createModel("cloudbase");

const result = await model.generateText({
  model: "deepseek-v4-flash",  // must already be enabled in this env (DescribeAIModels → UpdateAIModel)
  messages: [{ role: "user", content: "Give me a one-paragraph intro to Li Bai." }],
});

console.log(result.text);           // generated text string
console.log(result.usage);          // { prompt_tokens, completion_tokens, total_tokens }
console.log(result.messages);       // full message history
console.log(result.rawResponses);   // raw model responses

streamText() — 流式

前提条件: 已通过两步预检。

const model = ai.createModel("cloudbase");

const res = await model.streamText({
  model: "deepseek-v4-flash",
  messages: [{ role: "user", content: "Give me a one-paragraph intro to Li Bai." }],
});

// Option 1: iterate the text stream (recommended)
for await (let text of res.textStream) {
  console.log(text);  // incremental text chunks
}

// Option 2: iterate the data stream for full response chunks
for await (let data of res.dataStream) {
  console.log(data);  // full response chunk with metadata
}

// Option 3: access final results
const messages = await res.messages;  // full message history
const usage = await res.usage;        // token usage

错误处理模式

const model = ai.createModel("cloudbase");

try {
  const result = await model.generateText({
    model: "deepseek-v4-flash",
    messages: [{ role: "user", content: "Generate a concise onboarding checklist." }],
  });

  console.log(result.text);
} catch (error) {
  console.error("Failed to call CloudBase AI from Web", error);
}

类型定义

interface BaseChatModelInput {
  model: string;                        // required: model name
  messages: Array<ChatModelMessage>;    // required: message array
  temperature?: number;                 // optional: sampling temperature
  topP?: number;                        // optional: nucleus sampling
}

type ChatModelMessage =
  | { role: "user"; content: string }
  | { role: "system"; content: string }
  | { role: "assistant"; content: string };

interface GenerateTextResult {
  text: string;                         // generated text
  messages: Array<ChatModelMessage>;    // full message history
  usage: Usage;                         // token usage
  rawResponses: Array<unknown>;         // raw model responses
  error?: unknown;                      // error if any
}

interface StreamTextResult {
  textStream: AsyncIterable<string>;    // incremental text stream
  dataStream: AsyncIterable<DataChunk>; // full data stream
  messages: Promise<ChatModelMessage[]>;// final message history
  usage: Promise<Usage>;                // final token usage
  error?: unknown;                      // error if any
}

interface Usage {
  prompt_tokens: number;
  completion_tokens: number;
  total_tokens: number;
}

最佳实践

  1. 先执行两步预检 — ① 资格检查(通过 DescribeEnvPostpayPackage 检查 Token Credits 资源包)+ ② 分组就绪情况检查(通过 DescribeAIModels 检查已启用的模型,通过 DescribeManagedAIModelList 获取权威的受支持模型目录;如果缺少目标模型,则使用完整替换的 Models[] 和 Status: 1 调用 UpdateAIModel)。跳过预检会直接导致运行时出现“找不到模型”/“模型未启用”错误。
  2. 绝不要假设任何模型已启用 — 无论是 deepseek-v4-flash、hunyuan-*,还是其他模型。始终先通过 DescribeAIModels 确认;如果缺少目标模型,就在 DescribeManagedAIModelList 中查找准确的 Model 字符串(不要猜拼写或编造供应商前缀),然后调用 UpdateAIModel 启用它。
  3. createModel 只接受三种值 — "cloudbase"(主托管分组)、"hunyuan-exp"(旧版内置分组,适用于成长计划场景),或通过 CreateAIModel 注册的用户自定义 GroupName(必须以 custom- 开头,例如 custom-kimi、custom-openai-compat)。绝不要猜着使用 createModel("deepseek")/createModel("kimi")/createModel("custom")。
  4. 不要编造 SDK 方法名或参数。 此 SKILL.md 是 @cloudbase/js-sdk AI 接口的权威参考——编写代码前,请在此处(或下方的类型定义部分)查找方法签名。如果此处未记录某个方法或字段,请停下来询问,或通过 MCP 工具检查实时契约。不要猜测。
  5. 启用新的托管模型前,先展示价格 — DescribeManagedAIModelList 会返回 ModelSpec(上下文长度、最大输入/输出 Token 数)和 ModelChargingInfo(输入/输出/缓存价格、计费单位)。调用 UpdateAIModel 前,先向用户展示价格。
  6. 长响应使用流式传输 — 可提升用户感知到的响应速度和交互性。
  7. 妥善处理错误 — 使用 try/catch 包装 AI 调用。
  8. 妥善保管 accessKey — 使用可发布密钥,绝不要使用秘密密钥。
  9. 尽早初始化 — 在应用入口处设置 SDK,以便路由前就绪认证和 AI 功能。
  10. AI 功能不要使用匿名认证 — 新环境默认禁用匿名登录,且匿名用户没有 AI 模型权限。调用任何 AI API 前,必须先通过已验证的方式登录(手机号、电子邮件、用户名和密码、微信、自定义方式)。将提供商配置交给 auth-tool-cloudbase skill,将浏览器登录流程交给 auth-web-cloudbase skill;AI-model skill 会检查 auth.getSession() 并验证 loginType,再决定是否允许调用。
  11. 区分“预检失败”和“模型调用失败” — 前者表示用户需要购买资源包或调用 UpdateAIModel;后者则是提示词/参数/网络问题。针对两种情况向用户提供不同的指引。
  12. TypeScript:不要使用 any 来掩盖 SDK 的类型错误。 SDK 自带类型;如果出现错误,请用 unknown 配合类型保护进行缩窄,为实际使用的结构编写精确的 interface,或在本地 .d.ts 中扩展类型。绝不要使用 : any、as any、@ts-ignore 或 @ts-nocheck。请参阅 web-development skill 中的 Engineering constitution。
  13. 声称完成前先自行验证。 运行 tsc --noEmit 和项目构建,通过 agent-browser 打开页面并实际触发 AI 调用。确认:(a) 文本流到达 UI;(b) 控制台没有新增错误;(c) result.usage 非零。没有证据就说“应该可以运行”是不可接受的——请遵循 web-development/browser-testing.md。

评论

支持 Markdown