跳转到正文
返回门户

接入 AI 模型 ​

目标:用 LFModel 调用PluginX AI 网关,做一个点击按钮流式输出 AI 总结的小应用。

main.js

js
// ==UserScript==
// @name AI Page Summary
// @description 一键让 AI 总结当前页面标题
// @match https://example.com/*
// @require dom
// @require model
// ==/UserScript==

LFDOM.ready(() => {
  const panel = LFDOM.createFloatingRoot({ id: "ai-summary" });
  panel.innerHTML =
    "<button id='lf-sum'>AI Summary</button><div id='lf-out' style='max-width:280px'></div>";

  panel.querySelector("#lf-sum").addEventListener("click", async () => {
    const out = panel.querySelector("#lf-out");
    out.textContent = "";
    try {
      const { models } = await LFModel.listModels();
      const chatModel = models.find((m) => m.kind === "chat");
      for await (const chunk of LFModel.chatStream({
        model: chatModel.id,
        messages: [{ role: "user", content: `用一句话总结这个页面标题: ${document.title}` }],
      })) {
        if (chunk.kind === "delta") out.textContent += chunk.data.choices?.[0]?.delta?.content ?? "";
      }
    } catch (error) {
      out.textContent = `调用失败: ${error.errorCode || error.message}`;
    }
  });
});

关键点 ​

  • listModels() 返回当前账号可用的模型列表,对话模型和图片模型混在一起,按 kind === "chat" 挑选,不要硬编码模型 ID
  • chat() 总是一次性返回完整结果(传 stream: true 也会被改成 false),要逐字输出必须用 chatStream()
  • chatStream() 返回异步迭代器,chunk.kind === "delta" 的分片里 chunk.data 是 OpenAI 流式 chunk 对象,增量文本在 chunk.data.choices[0].delta.content
  • 出错时循环抛 LFModelError,按 errorCode 分支(如 INSUFFICIENT_BALANCE、APP_BUDGET_EXHAUSTED)
  • 调用会计入当前应用预算;cost_points / charge_points 是规范积分字段(1 CNY = 200 points)。用 getBudget() / getUsage() 查询额度与消耗
  • 模型调用经扩展后台携带PluginX登录态,无法指定其它应用的身份