動態

詳情 返回 返回

Chrome 138 beta Summarizer API 嚐鮮 - 動態 詳情

前言

之前一直想把視頻AI總結的功能集成到Video Roll中,但是由於調用各廠商的AI接口基本上無法實現完全免費,即使免費額度也是有限制的,所以想免費提供給用户使用就捉襟見肘。另一種方式就是讓用户自己填各個廠商的key來做一箇中間件而已。於是覺得沒太大必要,一直擱置了這個功能。但是最近Chrome宣佈138版本將正式內置AI接口,比如Summarizer, Translater等。於是我趕緊下載Chrome 138 beta版本來進行測試,經測試效果還是非常不錯,它的模型是基於Gemini Nano,於是我將其立馬集成到了新版的Video Roll中,待Chrome 138正式發佈,即可上線。

注意:Chrome 138 beta第一次需要在chrome://flags來啓用Summarizer API

檢測API和下載

按照官方文檔的方式進行調用即可,這個過程中會有兩個比較重要的步驟,第一是檢測Summarizer API是否可用,如果可用,第一次可能需要下載模型,下載完成後才能調用後續的API。

關於API是否可用,官方給了基本配置,但目前經我的測試,實際使用很多不確定因素。比如頭天開啓後可以正常使用,第二天重啓電腦後就提示無法使用了,也不知道是電量不足還是其他原因。

  • Operating system: Windows 10 or 11; macOS 13+ (Ventura and onwards); or Linux. Chrome for Android, iOS, and ChromeOS are not yet supported by our APIs backed by Gemini Nano.
  • Storage: At least 22 GB on the volume that contains your Chrome profile.
  • GPU: Strictly more than 4 GB of VRAM.
  • Network: Unlimited data or an unmetered connection.
public async downloadModel(): Promise<void> {
    return new Promise(async (resolve, reject) => {
      if (this.isInitialized) {
        resolve();
      }

      try {
        if (!("Summarizer" in self)) {
          console.log("Summarizer API 不可用");
          reject(new Error("Summarizer API not loaded"));
        }

        const availability = await window.Summarizer.availability();

        console.log("--availability", availability);
        if (availability === "unavailable") {
          console.log("Summarizer API 不可用");
          reject(new Error("Summarizer API unavailable"));
          return;
        }

        const options: SummaryOptions = {
          sharedContext: "This is a YouTube video transcript summary.",
          type: "key-points",
          format: "markdown",
          length: "long",
        };

        if (availability === "available") {
          // The Summarizer API can be used immediately .
          this.summarizer = await window.Summarizer.create(options);
        } else {
          // The Summarizer API can be used after the model is downloaded.
          this.summarizer = await window.Summarizer.create(options);
          this.summarizer.addEventListener("downloadprogress", (e) => {
            console.log(`Downloaded ${e.loaded * 100}%`);
            const progress = e.total
              ? (e.loaded / e.total) * 100
              : e.loaded * 100;
            console.log(`Summarizer 模型下載進度: ${progress.toFixed(2)}%`);
          });
          await this.summarizer.ready;
        }

        this.isInitialized = true;
        console.log("Summarizer 服務初始化成功");
        resolve();
      } catch (error) {
        console.log("Summarizer 服務初始化失敗:", error);
        this.isInitialized = false;
        reject(
          error instanceof Error
            ? error
            : new Error("Failed to initialize summarizer")
        );
      }
    });
  }

調用總結

總結可以使用流式和批量兩種方式,為了更好的用户體驗,一般使用流式輸出

/**
   * Generate summary from text
   * @param {string} text - The text to summarize
   * @param {SummaryOptions} [options] - Summary options
   * @returns {Promise<string | null>} The generated summary or null if generation fails
   */
  public async generateSummary(
    text: string,
    tabId: number,
    options: Partial<SummaryOptions> = {}
  ): Promise<string | null> {
    if (!text?.trim()) {
      logDebug("文本為空,無法生成摘要");
      return null;
    }

    try {
      if (!this.isInitialized || !this.summarizer) {
        await this.initialize();
      }

      if (!this.summarizer) {
        throw new Error("Summarizer not initialized");
      }

      const summaryOptions: SummaryOptions = {
        context:
          options.context || "This is a YouTube video transcript section.",
        length: options.length || "long",
        format: "markdown",
        type: options.type || "key-points",
      };

      const result = await this.summarizer.summarizeStreaming(text, {
        context:
          "這是一個帶時間線的Youtube視頻字幕摘要, 請用中文生成摘要,並在摘要標註時間段",
      });

      // 創建解碼器
      const decoder = new TextDecoder();
      let summary = "";

      // 處理流式響應
      const reader = result.getReader();
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        summary += value;

        // 觸發進度更新事件
        sendRuntimeMessage(tabId, {
          type: ActionType.SUMMARIZING,
          tabId,
          payload: {
            text: summary,
            complete: false,
          },
        });
      }

      // 觸發進度更新事件
      sendRuntimeMessage(tabId, {
        type: ActionType.SUMMARIZE_DONE,
        tabId,
        payload: {
          text: summary,
          complete: true,
        },
      });
      return summary;
    } catch (error) {
      logDebug("生成摘要失敗:", error);
      return null;
    }
  }

限制

目前測試了輸入大概超過20000個字符串就會提示too large,模型無法輸出的情況。這也可能是由於客户端性能和模型的限制。

總結

總的來説客户端內置AI是一個巨大的進步,這讓前端工程師可以直接在客户端使用AI,也能通過完成一些簡單的任務。

user avatar toopoo 頭像 zaotalk 頭像 smalike 頭像 linlinma 頭像 jingdongkeji 頭像 qingzhan 頭像 kobe_fans_zxc 頭像 zourongle 頭像 linx 頭像 anchen_5c17815319fb5 頭像 huichangkudelingdai 頭像 u_17443142 頭像
點贊 168 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.