跳转到正文
返回门户

LFModel ​

全局变量:LFModel · 启用方式:// @require model

调用PluginX AI 网关。所有调用固定归属当前应用(计入其预算),经扩展后台携带PluginX登录态,不能指定其它应用身份。

本地开发中的项目

还没有上架的本地项目不设预算,消耗合并计入账号的「本地开发」:getBudget() 返回不限额,getUsage() 返回所有本地项目的合计,getBudgetUrl() 打开积分详情页。上架为应用后才按应用单独计算预算与消耗。

方法 ​

ts
LFModel.listModels({ force?, page?, pageSize?, q?, ids? }?): Promise<{ models, page, pageSize, total, count, hasMore, ... }>

列出当前账号可用的模型

ts
LFModel.getModel(modelId): Promise<ModelDescriptor>

读取单个模型的描述信息

ts
LFModel.chat(payload): Promise<ChatCompletionsResponse>

对话补全(非流式),OpenAI 风格 payload

ts
LFModel.chatStream(payload): AsyncIterable<StreamChunk>

流式对话,异步迭代 { kind: "delta", data } 分片

ts
LFModel.image(payload): Promise<ImageGenerationsResponse>

图片生成

ts
LFModel.getBalance(): Promise<BalanceInfo>

查询账户余额

ts
LFModel.getBudget(): Promise<BudgetInfo>

查询当前应用的预算配置

ts
LFModel.getSpendable(): Promise<SpendableInfo>

一次拿到可消费积分快照:min(账户余额, 应用预算剩余) + 余额不足/预算耗尽判定

ts
LFModel.getUsage(options?): Promise<UsageInfo>

查询用量统计(range: 1d / 7d / 30d / all)

ts
LFModel.getPlansUrl(): Promise<string>

官网订阅套餐页深链(本期积分用完时引导用户订阅或升级)

ts
LFModel.getBudgetUrl(): Promise<string>

官网本应用预算面板深链(预算耗尽时引导用户提额)

参数详解 ​

chat(payload) / chatStream(payload) ​

payload 是 OpenAI Chat Completions 风格的请求体,未知字段透传给上游;app_scope 由后台强制注入为当前应用,自己传的会被剥离:

字段类型必填说明
modelstring是模型 id,取自 listModels() 返回的 models[].id
messagesChatMessage[]是每条 { role: 'system' / 'user' / 'assistant' / 'tool', content };多模态 content 支持 [{ type: 'text', text }, { type: 'image_url', image_url: { url } }]
tools / tool_choiceOpenAITool[] / 'auto' 等否函数调用声明与选择策略,原样转发
temperature / top_p / max_tokensnumber否采样与长度控制,原样转发;上游模型明确拒收某个采样参数时(如部分新版 Claude 只接受默认 temperature),网关会去掉该参数自动重发。思考型模型会把一部分 max_tokens 花在推理上,请留足余量,否则正文可能被 finish_reason: 'length' 截断
reasoning_effort'low' / 'medium' / 'high' / 'xhigh'否统一的思考强度档位(也接受 camelCase reasoningEffort;另接受 max,none / minimal 按 low 处理,其它值静默忽略)。对所有模型都用这一组值,不要传厂商私有参数(thinking、enable_thinking、thinking_budget 等,thinking / reasoning 字段会被网关剔除)。网关按上游协议映射:OpenAI 兼容上游透传 low/medium/high,xhigh / max 收敛为 high;GLM 映射为 low/high/max(medium→high、xhigh→max);Anthropic 新模型(Claude 5 系列、Opus 4.5+、Sonnet 4.6+)透传为 effort(支持全部五档,带 tools 同样生效,并去掉 temperature / top_p / top_k);老模型换算为 thinking 预算,请求带 tools 或 max_tokens 放不下 1024 的最低思考预算时不开启 thinking,开启时会去掉 temperature;Gemini 换算为 thinkingBudget。不支持推理的模型会剔除该字段。不传则用上游默认档
response_format{ type, json_schema? }否type 为 'text' / 'json_object' / 'json_schema';json_schema 时需附 { name, schema, strict? }
stop / n / seed / frequency_penalty / presence_penalty—否原样转发(多数上游 n 上限为 1)
streamboolean否chat() 强制为 false;要流式请用 chatStream()

chat() 返回标准 OpenAI 响应:choices[0].message.content 是文本(模型走工具调用时可能为 null),message.tool_calls[] 每项 { id, type: 'function', function: { name, arguments } }(arguments 是 JSON 字符串),思考型模型附 message.reasoning_content。计费规范字段是 usage.cost_points、usage.cost_unit === 'points' 与 lingfeng_billing.charge_points(1 CNY = 200 points);旧 CNY/cents 字段仅 deprecated compatibility,无币种 charge_cents 可能是 USD,不能当 CNY 积分。

chatStream() 返回异步迭代器,每个元素二选一:{ kind: 'delta', data }(data 是已解析的 OpenAI 流式 chunk 对象而不是字符串,增量文本在 data.choices[0].delta.content,可能为空;可含 usage.cost_points)或 { kind: 'billing', billing }(最后一条计费事件,规范字段 billing.charge_points)。break 跳出循环会自动中止上游请求。出错时由 for await 循环抛出 LFModelError(见下方错误类型)。

image(payload) ​

字段类型必填说明
modelstring是图片模型 id(kind === 'image')
promptstring是文本提示词
sizestring否如 '1024x1024',须在 model.supported_sizes 内
response_format'url' / 'b64_json'否须在 model.capabilities.supported_response_formats 内
n / quality / style / image / mode—否生成数量(部分上游会拼成一张网格图,要 K 张独立图请分次调用)/ 质量 / 风格 / 图生图参考图 / 生成模式

返回 { created, data: [{ url?, b64_json?, revised_prompt? }], usage?, lingfeng_billing };图片同样以 usage.cost_points / lingfeng_billing.charge_points 为规范计费字段。

listModels 分页与筛选 / 其它查询方法返回结构 ​

listModels() 的模型目录与 IDE agent 窗口的模型选择器同源:优先取服务端运营配置的精选目录(可见范围与顺序都由服务端决定,对话模型排在最前),运营未配置时回落到全量目录并按 page / pageSize 分页。所以你在 agent 模型选择器里看到的模型,就是应用能查到的模型——不要硬编码模型 id。注意精选目录约束的是发现:chat() / image() 直接打推理端点,传入精选之外的 id 是否可用由服务端网关决定。

方法关键返回字段
listModels({ force?, page?, pageSize?, q?, ids? })page 默认 1,pageSize 默认 40;q 搜索,ids 精确筛选 id。返回 models[]、page、pageSize、total、count、hasMore;每个查询/分页独立内存缓存,同查询并发请求自动合并,force: true 强制刷新该项。另含定价参数 priceWindowK / priceMarkupRatio。模型字段包括 id、name / display_name、context_length、kind('chat' / 'image')、capabilities、pricing_cny_per_1m、isFree。不支持按 kind 过滤,对话与图片模型混在同一列表里,请自行 models.filter((m) => m.kind === 'chat')
getModel(modelId)按 id 读取单个模型(与 listModels 共用缓存),找不到时抛 MODEL_NOT_FOUND。未配置精选目录时用精确 ids 查询,不拉取整页目录;配置了精选目录时在精选列表里查找,所以只能查到精选内的模型——精选之外的 id 即使 chat() 能用,getModel() 也会抛 MODEL_NOT_FOUND
getBalance()balance_points(规范余额积分);balance_cents / balance_micro 等旧字段仅 deprecated compatibility。钱包是用户级的,与应用无关
getBudget()规范字段 budget_points(null=不限)、spent_points、remaining_points;旧 budget_cents / spent_cents / spent_micro / remaining_cents 仅 deprecated compatibility;固定查询当前应用
getSpendable()规范字段:spendable_points(min(账户余额, 应用预算剩余))、balance_points,预算有限时还有 budget_remaining_points;另含 exhausted / exhausted_reason / limiting_factor。spendable_cents / spendable_micro 仅 deprecated compatibility
getUsage({ range? })range 取 '1d' / '7d'(默认)/ '30d' / 'all';total.charge_points 与 by_model[].charge_points 是规范积分聚合,旧 charge_cents / charge_micro 仅 deprecated compatibility

getPlansUrl / getBudgetUrl 支付引导深链 ​

两个方法都返回官网深链字符串(由扩展后台按当前环境域名拼出,请勿硬编码 URL):getPlansUrl() 打开官网订阅套餐页,适合 INSUFFICIENT_BALANCE(本期积分用完)时引导用户订阅或升级——积分每 31 天随套餐重置,按需购买已下线;getBudgetUrl() 打开 AI 面板并自动弹出当前应用的预算面板,适合 APP_BUDGET_EXHAUSTED(账户还有积分、但本应用预算用完)时引导用户提高预算。在你的应用 UI 里渲染成可点击的链接或 window.open(url, '_blank') 按钮即可。

错误类型 ​

所有方法失败抛 LFModelError(可用 instanceof LFModel.LFModelError 判断):status(HTTP 状态码)、errorCode(稳定枚举:INSUFFICIENT_BALANCE 本期积分用完、APP_BUDGET_EXHAUSTED 应用预算耗尽、MODEL_REQUIRES_PAID_PLAN 模型仅限订阅用户、MODEL_NOT_FOUND、NO_AVAILABLE_PROVIDER、UPSTREAM_ERROR 等)、payload(上游原始错误体)。按 errorCode 分支处理,不要解析 message 文本;INSUFFICIENT_BALANCE 配合 getPlansUrl()、APP_BUDGET_EXHAUSTED 配合 getBudgetUrl() 给出一键跳转;MODEL_REQUIRES_PAID_PLAN 表示该模型仅限订阅用户,同样引导到 getPlansUrl() 或换用未加锁模型。

几个例外:

  • chatStream() 的错误只带 errorCode,status 恒为 0、payload 为 null;请只按 errorCode 分支。
  • 网络故障、扩展通信中断等没有到达网关的失败,errorCode 为空字符串、status 为 0。后台连接在没有错误信息的情况下断开时,chatStream() 的迭代会像正常结束一样停止,需要确认完整性时可检查是否收到了 billing 元素。
  • 运行环境没有消息通道(既未启用 USER_SCRIPT messaging,也不在终端 run 中)时抛普通 Error。

示例

js
// @require model

const { models } = await LFModel.listModels();
// 列表里同时有对话模型和图片模型,按 kind 挑选
const chatModel = models.find((m) => m.kind === "chat");

// 调用前检查可消费积分(= min(账户余额, 应用预算剩余)),并区分是哪一侧不够
const spendable = await LFModel.getSpendable();
if (spendable.exhausted) {
  const url = spendable.exhausted_reason === "APP_BUDGET_EXHAUSTED"
    ? await LFModel.getBudgetUrl()    // 预算用完 → 引导去官网提高本应用预算
    : await LFModel.getPlansUrl(); // 本期积分用完 → 引导去订阅/升级套餐
  window.open(url, "_blank");
} else {
  console.log(`当前可消费 ${spendable.spendable_points} 积分`);
}

// 非流式
const reply = await LFModel.chat({
  model: chatModel.id,
  messages: [{ role: "user", content: "你好" }],
});
console.log(reply.choices[0].message.content);

// 流式:delta 的 data 是 OpenAI chunk 对象,文本在 choices[0].delta.content
let text = "";
for await (const chunk of LFModel.chatStream({
  model: chatModel.id,
  messages: [{ role: "user", content: "讲个笑话" }],
})) {
  if (chunk.kind === "delta") text += chunk.data.choices?.[0]?.delta?.content ?? "";
}
console.log(text);