关于 ai-model-web
面向使用 CloudBase 的 Web 开发者,指导通过 @cloudbase/js-sdk 在浏览器中调用 AI 模型并流式呈现结果。它还规定了调用前的资源包资格和模型组就绪检查。
主要功能
- 01从浏览器调用 AI 模型
- 02流式生成文本响应
- 03检查 Token Credits 资格
- 04核验并启用模型组与模型
适用场景
- 01为 Web 应用添加文本生成
- 02在页面中流式显示模型输出
- 03调用 Hunyuan、DeepSeek 或 GLM
MCP 相关
该技能要求生成 SDK 代码前使用 MCP 工具检查环境、Token Credits 资源包和模型组状态;必要时通过工具启用模型。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tencentcloudbase/ skills --skill ai-model-web安装后在 Claude Code 中输入/ai-model-web确认已加载。
附带文件LICENSE.md
详细介绍
同级技能(仅限本地)
同级 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_modelOpenAPI 规范;不要构建自定义 HTTP 代理)
⛔ 停止 — ai.createModel(...) 参数不是供应商/模型名称
编写任何 createModel(...) 代码行之前,请先阅读此内容。Agent 为此 SDK 生成代码时,最常见的错误就是臆造该参数。合法形式恰好有四种,其他任何形式都是错误。
✅ 合法的 ai.createModel(...) 参数 | 使用时机 |
|---|---|
"cloudbase" | 新项目使用的主要托管组(由 TokenHub 支持,包含多个供应商的模型池)。供应商和具体模型应填写在 generateText / streamText 的 model 字段中,例如 { model: "deepseek-v4-flash" }。默认不会启用任何模型——请务必先检查 DescribeAIModels;如果目标模型不存在,请先使用 UpdateAIModel 启用该模型,再调用 SDK。 |
"hunyuan-v3" | 即将退役的旧版套餐组。 仅提供 hy3,平台不会再向其中添加新模型。现有代码仍可正常运行——新代码应使用 cloudbase + { model: "hy3" }。 |
"hunyuan-exp" | 仅当 DescribeAIModels 明确返回此环境的旧版内置组时使用。其原始默认模型 hunyuan-2.0-instruct-20251111 已下线(2026-05-31)——切勿使用此 ID。 |
"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: [...]
});
决策流程(用户指定具体模型时)
- 用户说“使用 DeepSeek v3.2”/“使用 hunyuan instruct”/“使用 Kimi k2.6”/“使用 GLM-5”/……
createModel("cloudbase")保持不变。- 将模型 ID 填入
model字段:{ model: "deepseek-v3.2" }、{ model: "hy3" }、{ model: "kimi-k2.6" }、{ model: "glm-5" }、…… - 切勿假设模型已启用。 编写 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[] 中。
-
列出当前环境中已配置的分组:
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。 -
切勿假设模型已启用。 检查
cloudbase分组的AIModelGroups[?].Models[].Model。如果目标模型缺失(或者用户未指定模型时,你打算默认使用的模型,例如deepseek-v4-flash),请跳转到第 4 步并启用它——暂时不要调用createModel("cloudbase")。如果cloudbase分组本身不存在或其Status=2,也请跳转到第 4 步。 -
用户请求的模型属于托管目录(例如
deepseek-v3.2、hy3、glm-5、kimi-k2.6、……):检查该Model是否已在cloudbase分组的Models[]中。如果不在,请跳转到第 4 步。不要猜测准确的模型 ID——请先通过DescribeManagedAIModelList(第 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 }) -
请求的模型不在托管目录中(未被
DescribeManagedAIModelList找到)→ 跳转到下一节,自定义接入(托管目录之外的模型)。
所有 Action 均使用
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)- 由 Tencent Cloud TokenHub 提供支持,这是一个统一的托管池,涵盖多个供应商——Hunyuan(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、……)、Zhipu 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-v3" — 旧版计划组(正在退役)
- 仅包含
hy3;该组不会新增模型,正逐步淘汰。迁移目标为cloudbase+{ model: "hy3" } - 现有代码仍可使用——不要将
createModel("hunyuan-v3")“修正”为createModel("hy3");hy3是模型 ID,不是 GroupName - 主要与小程序成长计划环境有关(参见
ai-model-wechat)
3. "hunyuan-exp" — 较旧的内置旧版模型组(为兼容性保留)
- 除非环境明确仍返回该组,否则不要在 Web 中使用(此类流程请切换到
ai-model-wechat技能) - 其原始默认模型
hunyuan-2.0-instruct-20251111已于 2026-05-31 下线——绝不要指定该模型 ID。该组目前仍提供的模型,必须通过DescribeAIModels({ GroupName: "hunyuan-exp" }).Models[]获取
4. 用户自定义 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时请改用驼峰命名。
安装
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;
}
最佳实践
- 首先执行两步预检——① 资格检查(通过
DescribeEnvPostpayPackage检查 Token Credits 资源包)+ ② 分组就绪情况检查(通过DescribeAIModels检查已启用的模型,通过DescribeManagedAIModelList获取权威的受支持模型目录;如果缺少目标模型,则使用包含完整替换内容的Models[]和Status: 1调用UpdateAIModel)。跳过预检会直接导致运行时出现“找不到模型”/“模型未启用”错误。 - 切勿假定任何模型已启用——无论是
deepseek-v4-flash、hunyuan-*,还是其他模型。务必先通过DescribeAIModels验证;如果缺少目标模型,请在DescribeManagedAIModelList中查找准确的Model字符串(不要猜拼写或自行编造供应商前缀),然后调用UpdateAIModel启用该模型。 createModel只接受四种值——"cloudbase"(主托管分组)、"hunyuan-v3"(旧版计划分组,仅限hy3,正在淘汰)、"hunyuan-exp"(较早的内置分组),或通过CreateAIModel注册的用户自定义 GroupName(必须以custom-开头,例如custom-kimi、custom-openai-compat)。切勿使用createModel("deepseek")/createModel("kimi")/createModel("custom")进行猜测。- 不要编造 SDK 方法名或参数。 本 SKILL.md 是
@cloudbase/js-sdkAI 接口的权威参考——编写代码前,请在此处(或下文的“类型定义”部分)查阅方法签名。如果此处没有记录某个方法或字段,请停下来询问,或通过 MCP 工具检查实时契约。不要猜测。 - 启用新的托管模型前先展示价格——
DescribeManagedAIModelList会返回ModelSpec(上下文长度、最大输入/输出 Token 数)和ModelChargingInfo(输入/输出/缓存价格、计费单位)。调用UpdateAIModel前,请向用户展示价格。 - 长回复使用流式传输——提升用户感知到的响应速度和交互体验。
- 妥善处理错误——使用 try/catch 包装 AI 调用。
- 妥善保管
accessKey——使用可公开的密钥,切勿使用秘密密钥。 - 尽早初始化——在应用入口处设置 SDK,确保路由前身份验证和 AI 均已就绪。
- AI 功能不要使用匿名身份验证——新环境默认禁用匿名登录,且匿名用户没有 AI 模型权限。调用任何 AI API 前,必须要求用户完成已验证的登录(手机号、电子邮件、用户名和密码、微信或自定义方式)。将供应商配置交由
auth-tool-cloudbase技能处理,将浏览器登录流程交由auth-web-cloudbase技能处理;AI 模型技能会检查auth.getSession()并验证loginType,再决定是否允许调用。 - 区分“预检失败”和“模型调用失败”——前者表示用户需要购买资源包或调用
UpdateAIModel;后者表示提示词/参数/网络问题。针对这两种情况向用户提供不同的指导。 - TypeScript:不要使用
any来掩盖 SDK 类型错误。 SDK 自带类型定义;如果出现错误,请使用unknown和类型保护进行收窄,为实际使用的数据结构编写精确的interface,或在本地.d.ts中扩展类型。切勿使用: any、as any、@ts-ignore或@ts-nocheck。请参阅web-development技能中的 Engineering 宪章。 - 声称完成前先自行验证。 运行
tsc --noEmit和项目构建,然后用agent-browser打开页面并实际触发 AI 调用。确认:(a) 文本流已显示在 UI 中;(b) 没有新增控制台错误;(c)result.usage非零。没有证据就说“应该可以运行”是不可接受的——请遵循web-development/browser-testing.md。