通知用户模型下载情况

发布时间:2025 年 10 月 1 日

在使用任何内置 AI API 之前,必须从网络下载底层模型和任何自定义项(例如微调),提取压缩数据,最后将其加载到内存中。本指南记录了一些最佳实践,可帮助您在用户等待下载时改善用户体验。

监控和分享下载进度

每个内置 AI API 都有一个 create() 函数来启动会话。create() 函数具有 monitor 选项,因此您可以访问下载进度并将其分享给用户。

虽然内置 AI API 是为客户端 AI 而构建的,可在浏览器和用户设备上处理数据,但有些应用允许在服务器上处理数据。您在模型下载进度中如何称呼用户取决于以下问题:数据处理是否必须仅在本地运行?如果值为 true,则表示您的应用仅为客户端应用。 如果不是,您的应用可以使用混合实现

仅限客户端

在某些情况下,需要进行客户端数据处理。例如,如果某医疗保健应用允许患者询问有关其个人信息的问题,那么该应用可能希望这些信息在用户设备上保持私密状态。用户必须等到模型和所有自定义设置下载完毕并准备就绪后,才能使用任何数据处理功能。

在这种情况下,如果模型尚不可用,您应向用户显示下载进度信息。

<style>
  progress[hidden] ~ label {
    display: none;
  }
</style>

<button type="button">Create LanguageModel session</button>
<progress hidden id="progress" value="0"></progress>
<label for="progress">Model download progress</label>

在下载内置模型期间,应用尚无法使用。

现在,为了让此功能正常运行,我们需要编写一些 JavaScript 代码。该代码首先将进度界面重置为初始状态(进度隐藏且为零),检查是否完全支持该 API,然后检查该 API 的可用性

  • API 为 'unavailable':您的应用无法在此设备上以客户端方式使用。提醒用户相应功能不可用。
  • API 为 'available':该 API 可立即使用,无需显示进度界面。
  • API 为 'downloadable''downloading':下载完成后即可使用 API。显示进度指示器,并在每次触发 downloadprogress 事件时更新该指示器。下载完成后,显示不确定状态,向用户表明浏览器正在提取模型并将其加载到内存中。
const createButton = document.querySelector('.create');
const promptButton = document.querySelector('.prompt');
const progress = document.querySelector('progress');
const output = document.querySelector('output');

let sessionCreationTriggered = false;
let session = null;

const createSession = async (options = {}) => {
  if (sessionCreationTriggered) {
    return;
  }

  progress.hidden = true;
  progress.value = 0;

  try {
    if (!('LanguageModel' in self)) {
      throw new Error('LanguageModel is not supported.');
    }

    const availability = await LanguageModel.availability();
    if (availability === 'unavailable') {
      throw new Error('LanguageModel is not available.');
    }

    let modelNewlyDownloaded = false;
    if (availability !== 'available') {
      modelNewlyDownloaded = true;
      progress.hidden = false;
    }
    console.log(`LanguageModel is ${availability}.`);
    sessionCreationTriggered = true;

    const llmSession = await LanguageModel.create({
      monitor(m) {
        m.addEventListener('downloadprogress', (e) => {
          progress.value = e.loaded;
          if (modelNewlyDownloaded && e.loaded === 1) {
            // The model was newly downloaded and needs to be extracted
            // and loaded into memory, so show the undetermined state.
            progress.removeAttribute('value');
          }
        });
      },
      ...options,
    });

    sessionCreationTriggered = false;
    return llmSession;
  } catch (error) {
    throw error;
  } finally {
    progress.hidden = true;
    progress.value = 0;
  }
};

createButton.addEventListener('click', async () => {
  try {
    localSession = await createSession({
      expectedInputs: [{ type: 'text', languages: ['en'] }],
      expectedOutputs: [{ type: 'text', languages: ['en'] }],
    });
    promptButton.disabled = false;
  } catch (error) {
    output.textContent = error.message;
  }
});

promptButton.addEventListener('click', async () => {
  output.innerHTML = '';
  try {
    const stream = localSession.promptStreaming('Write me a poem');
    for await (const chunk of stream) {
      output.append(chunk);
    }
  } catch (err) {
    output.textContent = err.message;
  }
});

如果用户在模型正积极下载到浏览器时进入应用,进度界面会根据仍缺失的数据指示浏览器在下载过程中的位置。

不妨观看演示,了解此流程的实际应用。如果内置 AI API(在本例中为 Prompt API)不可用,则无法使用该应用。如果仍需下载内置 AI 模型,系统会向用户显示进度指示器。您可以在 GitHub 上查看源代码

混合实现

如果您偏好使用客户端 AI,但可以暂时将数据发送到云端,则可以设置混合实现。这意味着,用户可以立即体验相关功能,同时并行下载本地模型。下载模型后,动态切换到本地会话。

您可以针对混合使用任何服务器端实现,但最好在云端和本地都坚持使用相同的模型系列,以确保获得可比较的结果质量。 Gemini API 和 Web 应用使用入门重点介绍了 Gemini API 的各种方法。

在下载内置模型期间,应用会回退到云模型,并且已可使用。

演示展示了此流程的实际效果。如果内置 AI API 不可用,演示会回退到云端中的 Gemini API。如果仍需下载内置模型,系统会向用户显示进度指示器,并且应用会在下载完成之前使用云端 Gemini API。查看 GitHub 上的完整源代码

总结

您的应用属于哪个类别?您是否需要 100% 的客户端处理,还是可以使用混合方法?回答完此问题后,下一步是实现最适合您的模型下载策略。

请务必确保用户始终知道他们何时以及是否可以使用应用客户端,方法是按照本指南中的说明向他们显示模型下载进度。

请注意,这不仅仅是一次性挑战:如果浏览器因存储压力而清除模型,或者当有新模型版本可用时,浏览器需要再次下载模型。无论您采用客户端方法还是混合方法,都可以确保为用户打造尽可能出色的体验,并让浏览器处理其余事宜。