Select Page
Google Labs 最新 Mixboard:用 AI 把靈感拼貼秒變高質感簡報

Google Labs 最新 Mixboard:用 AI 把靈感拼貼秒變高質感簡報

最近 Google Labs 再次投下震撼彈——推出全新的視覺協作工具 Google Mixboard。這款被科技界譽為「進階版的 AI Pinterest」的創作平台,不只提供一張能無限延伸的靈感畫布,讓使用者自由拼貼、蒐集、創作,更強大的是它整合了 Google 最新影像模型 Gemini Nano Banana Pro,讓「圖片與文字的轉化能力」大幅進化。

Mixboard 不只是找圖工具,它是一款真正能把雜亂靈感整合成專業產出的 AI 創作平台。從蒐集參考、生成圖像、到一鍵變成簡報,你的創作流程從此不再分散於各個應用工具,全部在 Mixboard 一站式完成。


🌈 AI 靈感畫布:願景、概念、素材一次整合

Mixboard 的核心概念是一張能無限延伸的 Infinite Canvas(無限畫布)。你可以:

  • 任意拖放圖片與文字
  • 建立 Moodboard / 風格版
  • 生成 AI 圖像
  • 標記重點、串連思考流程
  • 與團隊同步協作

它的使用體驗與 Pinterest 的收藏便利性類似,但功能延伸到即時生成、編輯與視覺敘事,因此被形容為「AI 時代的 Pinterest 2.0」。

對設計師、行銷人、PM、內容創作者而言,這款工具能大幅提升發想到產出的速度與品質


Nano Banana Pro 模型強化「圖文轉化」:簡報不再需要手動排版

Mixboard 最大亮點,就是 Google Labs 全新的 Gemini Nano Banana Pro 影像模型。

它最令人驚豔的能力是:

一鍵把零散靈感 → 自動變成專業簡報

只要選擇畫布內容並下指令,Mixboard 能:

  • 自動辨識素材意圖
  • 依據內容自動重構敘事結構
  • 自動生成排版精美的投影片
  • 產出高解析度圖片與文字
  • 保留原本的風格、色調、敘事邏輯

無論你是做品牌提案、產品靈感收集、UI 改版構思、或社群 campaign 規劃,原本需要花上數小時整理的簡報,都只要 一鍵轉換 就能完成。


🧩 Mixboard 解決了哪些過往創作痛點?

1. 靈感雜亂、難以整理

貼在 Notion?存到 Pinterest?散落在相簿?
Mixboard 用單一畫布把所有靈感視覺化。

2. 簡報排版耗時

你只需要負責「想法」,簡報排版由 AI 完成。

3. 多工具切換降低效率

找圖 → 裁圖 → 設計 → 編排 → 簡報,全部一站式完成,大幅縮短製作流程。

4. 團隊協作斷層

Mixboard 支援分享與多人編輯,視覺溝通更直觀。


🚀 更適合哪些族群使用?

  • 品牌行銷團隊
  • 社群小編、內容創作者
  • 新創團隊 Pitch Deck 製作者
  • 設計師、UI/UX 規劃者
  • 教育工作者、講師
  • 想快速整理靈感的人

如果你常常在 Canva、Keynote、Notion、Pinterest 之間切換,Mixboard 將會是你最強的替代方案。


🔗 更多資訊

官方網站:
https://labs.google.com/mixboard/welcome

AI 提示架構:角色+任務+背景+格式提示詞設計技巧|為什麼 21 字以上比 9 字有效?

你常常只給 AI 九個字,卻期望它做出奇蹟嗎?根據 Google 官方統計資訊,只有當提示詞達到 21 個字以上,AI 才有機會輸出高品質答案。Google 在提示工程白皮書中也強調,好的提示詞結構比簡單請求更能引導大模型解出我們要的內容。

在這篇文章,我要分享給你一個 Google 推薦的「萬用公式」提示架構:角色 + 任務 + 背景 + 格式,輔以動詞導向的敘述方式,讓你的 AI 提示更加有力、精準。


✅ Google 萬用提示公式:角色、任務、背景、格式

組成部分目的範例
角色設定 AI 扮演的身份或專業領域「請你扮演一位專業的旅遊部落客…」
任務定義主要目標與行動「…撰寫一份為期三天的行程…」
背景加入情境、限制條件、目標對象「…針對要去東京的小資旅行。」
格式指定輸出的結構與型式「…請用簡單的條列式清單呈現。」

用這樣的架構引導 AI,能讓提示詞具體、有結構,減少 AI 的猜測空間。


🛠 用詞與語法技巧 TIPS(提升提示效能的小技巧)

  • 盡量用動詞開頭:給 AI「做什麼」比「什麼是」更有力。例如用「撰寫」「列出」「翻譯」「審校」等動詞開頭。
  • 避免模糊語詞:少用「很棒」「不錯」這類曖昧形容詞,改用具體指標(如「300 字」「三段落」「條列式」)。
  • 提供範例或模板:在提示中給一個輸出範例讓 AI 參考,降低偏差。
  • 讓 AI 回問你需要什麼:可以讓 AI 主動反問「你要什麼風格/語氣/受眾?」來細化需求。

🧩 實例演練:讓 AI 幫妳寫提示詞

下面示範一個互動流程:

你對 AI 說:
「請你扮演行銷顧問,幫我寫一個 Facebook 廣告文案。針對 25–35 歲上班族,宣傳一款健康能量飲品,格式為標題 + 兩段銷售文案 + 行動呼籲。」

AI 回覆後你可以加一句:

「請問你要什麼風格?正式、活潑、針對女性或男性?」

AI 反問後,你回答語氣與受眾,它就能生成更貼合你需求的文案。

這樣的對話式提示設計也比一次寫好全部提示更靈活有彈性。


💡 為什麼 21 字以上比 9 字好?

  • 模型理解上下文有門檻:過短提示缺乏足夠上下文,AI 容易「自由發揮」,未必對應你真正需求。
  • 更精準引導模型工作:加入角色、任務、背景與格式,能讓 AI 經過「角色思考」後才動手回答。
  • 提示後段不易被截斷:雖然 AI 提示有長度限制,在合理長度內放些條件比過短更能保留關鍵訊息。

小結與建議

  • 使用 角色 + 任務 + 背景 + 格式 為提示骨架
  • 用動詞為主語,引導 AI 行動
  • 鼓勵 AI 反問細節,加強精準度
  • 避免過於簡短的提示詞,適度增加字數與條件

只要掌握這套公式與技巧,你的 AI 提示力可能真的能提升 80% 或以上。試著用它設計你的下個提示詞吧!

https://gemini.google.com

Google Stitch 教學:如何用 AI 從文字與圖片提示快速生成前端 UI + 程式碼

Google Stitch 教學:如何用 AI 從文字與圖片提示快速生成前端 UI + 程式碼

Google I/O 2025 上,Google 推出了名為 Stitch 的全新 AI 工具,目標是用文字或圖片提示(prompt / image prompt)快速生成網頁與 App 的 UI 設計與前端程式碼。Stitch 結合 Gemini 2.5 Pro 與 Flash 模型,並支持 Figma 匯出與 IDE 編輯,雖不是要取代專業設計工具如 Figma,但它能大幅簡化設計初期流程,是設計師與前端開發者的新利器。以下詳細介紹功能、優勢與使用心得。

google stitch

功能特色與技術細節

  1. 從文字或圖片提示產生 UI + 前端程式碼
    • 用戶可以用簡單的中英文描述(這真的是google模型的好處),例如「建立一個深色主題的行動 app 登入頁面,有按鈕和表單欄位」來生成設計。
    • 或者上傳草圖、線框圖(wireframe)或其他 UI 的範例圖片來作為參考。Stitch 會根據這些提示產生對應設計。
  2. 整合 Gemini 2.5 Pro/Flash 模型 + 主題與設計流程工具
    • Stitch 是由 Google Labs 實驗性專案(experimental tool)之一,背後運行的是 Gemini 2.5 Pro 模型,這使得生成的 UI 設計在色彩、佈局與細節上更乾淨與現代感。
    • 提供主題(theme)選擇、樣式(style)調整等交互功能;可視化設計流程內建 Canvas,可以看到完整頁面流程與介面切換模式。
  3. 輸出與匯出支持:HTML/CSS/Figma 等
    • Stitch 可以匯出為 HTML / CSS 程式碼,讓開發者能夠「拿來就用」於前端專案當中。
    • 同時有「Paste to Figma」或「Copy to Figma」功能,可將設計匯入 Figma 進行進一步編輯。

Stitch 的定位與比較優勢

  • 輔助工具,而非全面取代設計平台:Stitch 的設計是為了縮短「從構思到原型 UI +程式碼」之間的落差,而不是完全取代專業設計師在 Figma、Sketch、Adobe XD 等工具中的工作。設計師仍可用這些工具做精細調整。
  • 速度與效率:使用 Stitch 生成 UI 設計/前端程式碼所需時間比從零開始設計加寫碼快很多,對於初期原型與快速驗證需求特別有用。
  • 可訪問性:Stitch 在 Google Labs 平台上可用,用戶界面相對友好,降低新手與非設計背景者的進入門檻。

限制與要注意的地方

  • 雖然 Stitch 支持匯出至 Figma,但某些情況(如從上傳圖片/草圖的模式)之下,Figma 匯出功能尚未全功能完善。
  • 設計細節(例如文字對齊、某些複雜元件組件化)有時候不完美,需要人工修正。
  • 現階段仍為實驗性/預覽模式(experimental / Labs),可能在某些瀏覽器支援或功能穩定性上有差異。

使用流程簡易指南

  1. 前往 Stitch 官方網站(stitch.withgoogle.com)並登入 Google 帳號。
  2. 選擇撰寫 prompt 或上傳參考圖片/草圖/線框圖。描述顏色、風格、佈局等細節。
  3. 等待 Stitch 生成 UI 設計與初步程式碼(HTML/CSS)。
  4. 若要匯出至 Figma,可使用「Copy to Figma / Paste to Figma」功能以便進一步編輯。
  5. 若為開發者,可直接取出 HTML/CSS 並嵌入 IDE 或網頁專案中。

Google Stitch 的收費/使用限額情況

從目前公開資訊來看,Google Stitch 屬於 Google Labs 的實驗性工具(beta 或公測階段),目前是免費使用,但有一些使用次數與模式上的限額/差異。下面是具體情況:

模式免費與否每月生成次數限額
Standard Mode(Flash 模式)免費每帳號每月約 350 次生成 │ 適合一般快速原型與草圖生成,可匯出 Figma 或 Code。
Experimental Mode(實驗/Pro 模式)免費每帳號每月約 50 次生成 │ 使用更強的 Gemini 2.5 Pro 模型;目前部分功能(如匯出 Figma)或效能有些限制。

參考資料

Flowith:免費無需邀請碼的最強 AI 自動化工具

Flowith:免費無需邀請碼的最強 AI 自動化工具

Flowith 最近正迅速崛起,成為超越 Manus 的最強 AI 自動化工具。​它不僅免費且無需邀請碼,還具備強大的 ORACLE 模式、自主知識花園創建等功能,為用戶提供無與倫比的 AI 互動體驗。​

Flowith 的主要特色

1. 免費使用,無需邀請碼

與其他需要邀請碼的 AI 工具不同,Flowith 完全免費,任何人都可以立即註冊並使用,無需等待或邀請碼。​

2. ORACLE 模式:自動化完成文件、簡報製作

Flowith 的 ORACLE 模式是一項突破性的功能,允許數十個甚至數百個 AI 代理同時為您工作,無需手動搭建工作流。​這使得複雜的數據收集和分析任務變得輕而易舉,並能自動生成文件和簡報等。 ​

3. 知識花園:創建並變現知識庫

Flowith 的「知識花園」功能讓您可以將自己的知識資源組織成系統化的知識庫,並可選擇對外分享或收費,實現知識變現。 ​

4. 邀請鏈接:獲得額外免費對話次數

透過邀請朋友加入 Flowith,您可以獲得額外的 500 次免費對話次數,提升使用體驗。​

邀請碼如下:

https://flowith.io/invitation?code=WPS1WR

如何使用 Flowith

  1. 註冊帳號:​訪問 Flowith 官方網站,點擊「註冊」並填寫相關資訊。​
  2. 探索 ORACLE 模式:​在主介面中,選擇 ORACLE 模式,輸入您的需求,系統將自動規劃並執行相關任務。 ​https://doc.flowith.io
  3. 建立知識花園:​上傳您的資料或文件,Flowith 會自動將其拆分為知識種子,幫助您構建個人知識庫。 ​

參考資料

DeepSeek R1 伺服器繁忙?硅基流動推出高效 API 解決方案

DeepSeek R1 伺服器繁忙?硅基流動推出高效 API 解決方案

硅基流動(SiliconFlow)是一家致力於加速通用人工智慧(AGI)普惠化的公司,主要可以讓生成式人工智慧惠及開發者和終端使用者使用,最近,硅基流動與華為雲合作,推出了基於昇騰雲的 DeepSeek R1 和 V3 推理服務,為使用者提供高效、穩定的 AI 模型推理體驗。

DeepSeek R1 與硅基流動的合作

DeepSeek R1 是一款由強化學習驅動的推理模型,旨在解決模型生成內容的重複性和可讀性問題。在強化學習之前,DeepSeek R1 引入了冷啟動數據,進一步優化推理效能。然而,近期由於 DeepSeek 官方伺服器頻繁出現繁忙狀態,許多使用者在使用時受到限制。

為了解決這一問題,硅基流動與華為雲合作,將 DeepSeek R1 部署在基於昇騰的計算平台上,提供更 穩定、高速DeepSeek R1 API 服務,讓使用者可以在更低的成本下獲得優質的 AI 推理服務。

如何使用 DeepSeek R1 API

使用者可以透過 註冊硅基流動平台,取得 API 金鑰,並將 DeepSeek R1 模型整合到各種應用之中。硅基流動提供了詳細的 技術文件與教學,幫助開發者快速上手,充分發揮 DeepSeek R1 的強大功能。

硅基流動透過與華為雲的合作,成功解決了 DeepSeek R1 在使用過程中的伺服器繁忙問題,為開發者和終端使用者提供了一個 高效、穩定的 AI 模型推理平台。這不僅展現了 硅基流動的技術優勢,也體現了其在推動 AGI 普惠化 方面的努力。

API使用

GraphRAG 使用本地端的 Ollama

GraphRAG圖像檢索增強生成(Graph Retrieval-Augmented Generation,GraphRAG)超好用,但也超級貴,超級花錢,想要省錢的話,就要用本地端的服務如(Ollama),要用的話,可以按照下面的步驟處理,前提是你已經可以使用 OpenAI 版本的 GraphRAG 了,本篇是要把 OpenAI 改成 Ollama

講在前面

要先設定好 GraphRAG

下載以及安裝好 Ollama

安裝 ollama 的 Python 套件

pip install ollama

修改原先的 setting.yaml 檔案

把舊的 yaml 檔案改成 ollama 的設定檔,新的設定檔案如下

encoding_model: cl100k_base
skip_workflows: []
llm:
  api_key: ${GRAPHRAG_API_KEY}
  type: openai_chat # or azure_openai_chat
  # model: gpt-4o-mini
  model_supports_json: true # recommended if this is available for your model.
  # max_tokens: 4000
  # request_timeout: 180.0
  # api_base: https://<instance>.openai.azure.com
  # api_version: 2024-02-15-preview
  # organization: <organization_id>
  # deployment_name: <azure_model_deployment_name>
  # tokens_per_minute: 150_000 # set a leaky bucket throttle
  # requests_per_minute: 10_000 # set a leaky bucket throttle
  # max_retries: 10
  # max_retry_wait: 10.0
  # sleep_on_rate_limit_recommendation: true # whether to sleep when azure suggests wait-times
  # concurrent_requests: 25 # the number of parallel inflight requests that may be made

  # ollama api_base
  api_base: http://localhost:11434/v1
  model: llama3

parallelization:
  stagger: 0.3
  # num_threads: 50 # the number of threads to use for parallel processing

async_mode: threaded # or asyncio

embeddings:
  ## parallelization: override the global parallelization settings for embeddings
  async_mode: threaded # or asyncio
  llm:
    api_key: ${GRAPHRAG_API_KEY}
    type: openai_embedding # or azure_openai_embedding
    # model: text-embedding-3-small
    
    # ollama
    model: nomic-embed-text 
    api_base: http://localhost:11434/api

    # api_base: https://<instance>.openai.azure.com
    # api_version: 2024-02-15-preview
    # organization: <organization_id>
    # deployment_name: <azure_model_deployment_name>
    # tokens_per_minute: 150_000 # set a leaky bucket throttle
    # requests_per_minute: 10_000 # set a leaky bucket throttle
    # max_retries: 10
    # max_retry_wait: 10.0
    # sleep_on_rate_limit_recommendation: true # whether to sleep when azure suggests wait-times
    # concurrent_requests: 25 # the number of parallel inflight requests that may be made
    # batch_size: 16 # the number of documents to send in a single request
    # batch_max_tokens: 8191 # the maximum number of tokens to send in a single request
    # target: required # or optional
  
chunks:
  size: 300
  overlap: 100
  group_by_columns: [id] # by default, we don't allow chunks to cross documents
    
input:
  type: file # or blob
  file_type: text # or csv
  base_dir: "input"
  file_encoding: utf-8
  file_pattern: ".*\\.txt$"

cache:
  type: file # or blob
  base_dir: "cache"
  # connection_string: <azure_blob_storage_connection_string>
  # container_name: <azure_blob_storage_container_name>

storage:
  type: file # or blob
  base_dir: "output/${timestamp}/artifacts"
  # connection_string: <azure_blob_storage_connection_string>
  # container_name: <azure_blob_storage_container_name>

reporting:
  type: file # or console, blob
  base_dir: "output/${timestamp}/reports"
  # connection_string: <azure_blob_storage_connection_string>
  # container_name: <azure_blob_storage_container_name>

entity_extraction:
  ## llm: override the global llm settings for this task
  ## parallelization: override the global parallelization settings for this task
  ## async_mode: override the global async_mode settings for this task
  prompt: "prompts/entity_extraction.txt"
  entity_types: [organization,person,geo,event]
  max_gleanings: 0

summarize_descriptions:
  ## llm: override the global llm settings for this task
  ## parallelization: override the global parallelization settings for this task
  ## async_mode: override the global async_mode settings for this task
  prompt: "prompts/summarize_descriptions.txt"
  max_length: 500

claim_extraction:
  ## llm: override the global llm settings for this task
  ## parallelization: override the global parallelization settings for this task
  ## async_mode: override the global async_mode settings for this task
  # enabled: true
  prompt: "prompts/claim_extraction.txt"
  description: "Any claims or facts that could be relevant to information discovery."
  max_gleanings: 0

community_report:
  ## llm: override the global llm settings for this task
  ## parallelization: override the global parallelization settings for this task
  ## async_mode: override the global async_mode settings for this task
  prompt: "prompts/community_report.txt"
  max_length: 2000
  max_input_length: 8000

cluster_graph:
  max_cluster_size: 10

embed_graph:
  enabled: true # if true, will generate node2vec embeddings for nodes
  # num_walks: 10
  # walk_length: 40
  # window_size: 2
  # iterations: 3
  # random_seed: 597832

umap:
  enabled: true # if true, will generate UMAP embeddings for nodes

snapshots:
  graphml: true
  raw_entities: true
  top_level_nodes: true

local_search:
  # text_unit_prop: 0.5
  # community_prop: 0.1
  # conversation_history_max_turns: 5
  # top_k_mapped_entities: 10
  # top_k_relationships: 10
  # max_tokens: 12000

global_search:
  # max_tokens: 12000
  # data_max_tokens: 12000
  # map_max_tokens: 1000
  # reduce_max_tokens: 2000
  # concurrency: 32

其中修改 llm 區塊

修改 model: llama3

加入 api_base: http://localhost:11434/v1

修改 embeddings 區塊

model: nomic-embed-text

api_base: http://localhost:11434/api

修改 GraphRAG 的程式碼

除了設定好 setting.yaml 以外,程式碼也要修改成可以支持 ollama 的程式碼,有兩處要改,可以用以下現成的程式碼

  1. C:\Users\xxx\anaconda3\envs\GraphRAG\Lib\site-packages\graphrag\llm\openai\openai_embeddings_llm.py

加入 ollama setting 區塊

# Copyright (c) 2024 Microsoft Corporation.
# Licensed under the MIT License

"""The EmbeddingsLLM class."""

from typing_extensions import Unpack

from graphrag.llm.base import BaseLLM
from graphrag.llm.types import (
    EmbeddingInput,
    EmbeddingOutput,
    LLMInput,
)
import ollama

from .openai_configuration import OpenAIConfiguration
from .types import OpenAIClientTypes


class OpenAIEmbeddingsLLM(BaseLLM[EmbeddingInput, EmbeddingOutput]):
    """A text-embedding generator LLM."""

    _client: OpenAIClientTypes
    _configuration: OpenAIConfiguration

    def __init__(self, client: OpenAIClientTypes, configuration: OpenAIConfiguration):
        self.client = client
        self.configuration = configuration

    async def _execute_llm(
        self, input: EmbeddingInput, **kwargs: Unpack[LLMInput]
    ) -> EmbeddingOutput | None:
        args = {
            "model": self.configuration.model,
            **(kwargs.get("model_parameters") or {}),
        }
        # openai setting
        # embedding = await self.client.embeddings.create(
        #    input=input,
        #    **args,
        #)
        #return [d.embedding for d in embedding.data]

        # ollama setting
        embedding_list=[]
        for inp in input:
            embedding = ollama.embeddings(model='qwen:7b', prompt=inp) #如果要改模型, 模型的名字要換掉
            embedding_list.append(embedding['embedding'])
        return embedding_list        
  1. C:\Users\xxx\anaconda3\envs\GraphRAG\Lib\site-packages\graphrag\query\llm\oai\embedding.py

加入 ollama setting 區塊,並且關閉 openai setting 區塊即可

# Copyright (c) 2024 Microsoft Corporation.
# Licensed under the MIT License

"""OpenAI Embedding model implementation."""

import asyncio
from collections.abc import Callable
from typing import Any

import numpy as np
import tiktoken
from tenacity import (
    AsyncRetrying,
    RetryError,
    Retrying,
    retry_if_exception_type,
    stop_after_attempt,
    wait_exponential_jitter,
)

from graphrag.query.llm.base import BaseTextEmbedding
from graphrag.query.llm.oai.base import OpenAILLMImpl
from graphrag.query.llm.oai.typing import (
    OPENAI_RETRY_ERROR_TYPES,
    OpenaiApiType,
)
from graphrag.query.llm.text_utils import chunk_text
from graphrag.query.progress import StatusReporter
import ollama

class OpenAIEmbedding(BaseTextEmbedding, OpenAILLMImpl):
    """Wrapper for OpenAI Embedding models."""

    def __init__(
        self,
        api_key: str | None = None,
        azure_ad_token_provider: Callable | None = None,
        model: str = "text-embedding-3-small",
        deployment_name: str | None = None,
        api_base: str | None = None,
        api_version: str | None = None,
        api_type: OpenaiApiType = OpenaiApiType.OpenAI,
        organization: str | None = None,
        encoding_name: str = "cl100k_base",
        max_tokens: int = 8191,
        max_retries: int = 10,
        request_timeout: float = 180.0,
        retry_error_types: tuple[type[BaseException]] = OPENAI_RETRY_ERROR_TYPES,  # type: ignore
        reporter: StatusReporter | None = None,
    ):
        OpenAILLMImpl.__init__(
            self=self,
            api_key=api_key,
            azure_ad_token_provider=azure_ad_token_provider,
            deployment_name=deployment_name,
            api_base=api_base,
            api_version=api_version,
            api_type=api_type,  # type: ignore
            organization=organization,
            max_retries=max_retries,
            request_timeout=request_timeout,
            reporter=reporter,
        )

        self.model = model
        self.encoding_name = encoding_name
        self.max_tokens = max_tokens
        self.token_encoder = tiktoken.get_encoding(self.encoding_name)
        self.retry_error_types = retry_error_types

    def embed(self, text: str, **kwargs: Any) -> list[float]:
        """
        Embed text using OpenAI Embedding's sync function.

        For text longer than max_tokens, chunk texts into max_tokens, embed each chunk, then combine using weighted average.
        Please refer to: https://github.com/openai/openai-cookbook/blob/main/examples/Embedding_long_inputs.ipynb
        """
        token_chunks = chunk_text(
            text=text, token_encoder=self.token_encoder, max_tokens=self.max_tokens
        )
        chunk_embeddings = []
        chunk_lens = []
        for chunk in token_chunks:
            try:
                # openai setting
                #embedding, chunk_len = self._embed_with_retry(chunk, **kwargs)
                #chunk_embeddings.append(embedding)
                #chunk_lens.append(chunk_len)

                # ollama setting
                embedding = ollama.embeddings(model="nomic-embed-text", prompt=chunk)['embedding'] #如果要替換嵌入模型, 請修改此處的模型名稱
                chunk_lens.append(chunk)
                chunk_embeddings.append(embedding)
                chunk_lens.append(chunk_lens)                
            # TODO: catch a more specific exception
            except Exception as e:  # noqa BLE001
                self._reporter.error(
                    message="Error embedding chunk",
                    details={self.__class__.__name__: str(e)},
                )

                continue
        #chunk_embeddings = np.average(chunk_embeddings, axis=0, weights=chunk_lens)
        #chunk_embeddings = chunk_embeddings / np.linalg.norm(chunk_embeddings)
        return chunk_embeddings.tolist()

    async def aembed(self, text: str, **kwargs: Any) -> list[float]:
        """
        Embed text using OpenAI Embedding's async function.

        For text longer than max_tokens, chunk texts into max_tokens, embed each chunk, then combine using weighted average.
        """
        token_chunks = chunk_text(
            text=text, token_encoder=self.token_encoder, max_tokens=self.max_tokens
        )
        chunk_embeddings = []
        chunk_lens = []
        embedding_results = await asyncio.gather(*[
            self._aembed_with_retry(chunk, **kwargs) for chunk in token_chunks
        ])
        embedding_results = [result for result in embedding_results if result[0]]
        chunk_embeddings = [result[0] for result in embedding_results]
        chunk_lens = [result[1] for result in embedding_results]
        chunk_embeddings = np.average(chunk_embeddings, axis=0, weights=chunk_lens)  # type: ignore
        chunk_embeddings = chunk_embeddings / np.linalg.norm(chunk_embeddings)
        return chunk_embeddings.tolist()

    def _embed_with_retry(
        self, text: str | tuple, **kwargs: Any
    ) -> tuple[list[float], int]:
        try:
            retryer = Retrying(
                stop=stop_after_attempt(self.max_retries),
                wait=wait_exponential_jitter(max=10),
                reraise=True,
                retry=retry_if_exception_type(self.retry_error_types),
            )
            for attempt in retryer:
                with attempt:
                    embedding = (
                        self.sync_client.embeddings.create(  # type: ignore
                            input=text,
                            model=self.model,
                            **kwargs,  # type: ignore
                        )
                        .data[0]
                        .embedding
                        or []
                    )
                    return (embedding, len(text))
        except RetryError as e:
            self._reporter.error(
                message="Error at embed_with_retry()",
                details={self.__class__.__name__: str(e)},
            )
            return ([], 0)
        else:
            # TODO: why not just throw in this case?
            return ([], 0)

    async def _aembed_with_retry(
        self, text: str | tuple, **kwargs: Any
    ) -> tuple[list[float], int]:
        try:
            retryer = AsyncRetrying(
                stop=stop_after_attempt(self.max_retries),
                wait=wait_exponential_jitter(max=10),
                reraise=True,
                retry=retry_if_exception_type(self.retry_error_types),
            )
            async for attempt in retryer:
                with attempt:
                    embedding = (
                        await self.async_client.embeddings.create(  # type: ignore
                            input=text,
                            model=self.model,
                            **kwargs,  # type: ignore
                        )
                    ).data[0].embedding or []
                    return (embedding, len(text))
        except RetryError as e:
            self._reporter.error(
                message="Error at embed_with_retry()",
                details={self.__class__.__name__: str(e)},
            )
            return ([], 0)
        else:
            # TODO: why not just throw in this case?
            return ([], 0)

參考資料