戰(zhàn):740M多模態(tài)嵌入模型從原理到落地)
1. 為什么 740M 這個(gè)尺寸值得單獨(dú)聊一聊第一次看到 EmbeddingGemma 2 這個(gè)標(biāo)題的時(shí)候我下意識(shí)地先看了參數(shù)量——740M。這個(gè)數(shù)字在今天的模型圈子里其實(shí)挺微妙的往上比動(dòng)輒 7B、13B 的通用大模型一抓一大把往下比各種幾十 M 的輕量級(jí)編碼器也遍地都是。但 740M 恰好卡在一個(gè)非常實(shí)用的位置它既不至于大到讓消費(fèi)級(jí)設(shè)備喘不過(guò)氣又足夠撐起多模態(tài)嵌入這種對(duì)語(yǔ)義理解要求不低的活兒。我先把結(jié)論擺在這兒EmbeddingGemma 2 是一個(gè)把多模態(tài)嵌入和本地推理這兩件事同時(shí)做扎實(shí)的中等規(guī)模模型。所謂嵌入說(shuō)白了就是把文本、圖片這類非結(jié)構(gòu)化數(shù)據(jù)轉(zhuǎn)換成一串固定長(zhǎng)度的數(shù)字向量讓機(jī)器能用數(shù)學(xué)的方式去衡量這兩段內(nèi)容到底像不像。而多模態(tài)意味著它不只處理文字還能把圖片映射到同一個(gè)語(yǔ)義空間里——你可以用一句話去搜一張圖也可以用一張圖去找相似的圖甚至做跨模態(tài)的檢索和聚類。這個(gè)模型解決的核心問(wèn)題是讓原本必須依賴云端 API 才能完成的嵌入計(jì)算能夠搬到本地跑。對(duì)做檢索增強(qiáng)、語(yǔ)義搜索、推薦召回、去重聚類、內(nèi)容審核這類工作的開發(fā)者來(lái)說(shuō)這意味著三件事數(shù)據(jù)不出本地、調(diào)用沒有網(wǎng)絡(luò)延遲、長(zhǎng)期使用沒有按量計(jì)費(fèi)的成本壓力。適合誰(shuí)來(lái)參考我覺得三類人最該關(guān)注一是手里有隱私敏感數(shù)據(jù)、不方便上傳云端的團(tuán)隊(duì)二是想在邊緣設(shè)備或普通筆記本上跑語(yǔ)義檢索的個(gè)人開發(fā)者三是正在做 RAG 類應(yīng)用、被嵌入 API 的延遲和費(fèi)用卡住脖子的工程同學(xué)。接下來(lái)我會(huì)從整體設(shè)計(jì)思路、核心細(xì)節(jié)、實(shí)操落地、踩坑排查幾個(gè)角度把這個(gè)模型掰開揉碎講清楚。內(nèi)容里涉及的具體參數(shù)和步驟一部分來(lái)自公開資料的常見實(shí)踐一部分是我自己在類似規(guī)模模型上摸爬滾打總結(jié)出來(lái)的經(jīng)驗(yàn)我會(huì)明確區(qū)分哪些是通用做法、哪些是我的個(gè)人建議你按自己場(chǎng)景取用就行。2. 整體設(shè)計(jì)與思路拆解2.1 為什么是中等參數(shù) 多模態(tài) 本地這個(gè)組合要理解 EmbeddingGemma 2 的設(shè)計(jì)取舍得先明白嵌入模型和生成模型的目標(biāo)根本不一樣。生成模型追求的是能說(shuō)會(huì)道參數(shù)量越大、知識(shí)越廣越好而嵌入模型追求的是把語(yǔ)義壓縮得準(zhǔn)它只需要輸出一個(gè)向量讓語(yǔ)義相近的東西在向量空間里靠得近。這就決定了嵌入模型不需要堆到幾十 B 參數(shù)740M 這個(gè)量級(jí)在嵌入任務(wù)上已經(jīng)相當(dāng)充裕。那為什么還要做多模態(tài)因?yàn)楝F(xiàn)實(shí)里的數(shù)據(jù)從來(lái)不是純文本的。一個(gè)電商商品庫(kù)里有標(biāo)題、有詳情、有主圖一個(gè)知識(shí)庫(kù)里有文檔、有截圖、有表格圖片。如果文本和圖片各自用一套模型編碼那跨模態(tài)檢索就無(wú)從談起。EmbeddingGemma 2 把文本和圖像映射到同一個(gè)向量空間本質(zhì)上是讓貓這個(gè)詞的向量和一張貓的照片的向量距離足夠近這樣跨模態(tài)的相似度計(jì)算才成立。至于本地推理這是整個(gè)設(shè)計(jì)里最有現(xiàn)實(shí)意義的一環(huán)。云端嵌入 API 的問(wèn)題不在于貴而在于不可控網(wǎng)絡(luò)抖動(dòng)會(huì)讓檢索延遲忽高忽低服務(wù)方的限流會(huì)讓你在高峰期干瞪眼數(shù)據(jù)合規(guī)要求又可能直接禁止你把內(nèi)容傳出去。本地推理把這三座大山一次性搬走。740M 的規(guī)模用 FP16 存儲(chǔ)大概占 1.5GB 顯存量化到 INT8 能壓到 800MB 左右INT4 甚至能到 400MB 出頭——這個(gè)體量一張入門級(jí)顯卡、一臺(tái)帶核顯的輕薄本甚至一些性能好點(diǎn)的手機(jī)都能扛得住。2.2 嵌入模型和生成模型到底差在哪很多剛接觸的朋友會(huì)混淆這兩類模型我在這里用生活化的方式說(shuō)清楚。生成模型像一個(gè)博學(xué)的朋友你問(wèn)他問(wèn)題他組織語(yǔ)言回答你嵌入模型像一個(gè)圖書管理員你給他一本書他不復(fù)述內(nèi)容而是直接告訴你這本書該放在書架的哪個(gè)位置。EmbeddingGemma 2 干的就是圖書管理員的活而且這個(gè)管理員同時(shí)管著文字區(qū)和圖片區(qū)還用的是同一套坐標(biāo)系統(tǒng)。這個(gè)區(qū)別帶來(lái)幾個(gè)實(shí)際影響。第一嵌入模型的輸出是固定維度的向量不是可變長(zhǎng)度的文本所以它的下游用法是算余弦相似度、做近鄰搜索而不是直接讀它的輸出。第二嵌入模型對(duì)語(yǔ)義等價(jià)很敏感但對(duì)表達(dá)流暢不敏感所以它可以用更小的參數(shù)量達(dá)到很好的效果。第三多模態(tài)嵌入模型在訓(xùn)練時(shí)最關(guān)鍵的是對(duì)齊——讓配對(duì)的圖文在向量空間里靠近不配對(duì)的推遠(yuǎn)這個(gè)對(duì)齊質(zhì)量直接決定了跨模態(tài)檢索的上限。2.3 本地推理的三種典型部署形態(tài)我在實(shí)際項(xiàng)目里見過(guò)三種主流的本地部署方式各有適用場(chǎng)景這里做個(gè)對(duì)比方便你對(duì)號(hào)入座。部署形態(tài)典型硬件量化方式延遲表現(xiàn)適合場(chǎng)景純 CPU 推理普通筆記本、服務(wù)器 CPUINT8/INT4單條 50-200ms低頻檢索、離線批處理單卡 GPU入門獨(dú)顯、消費(fèi)級(jí)顯卡FP16/INT8單條 5-30ms在線檢索、實(shí)時(shí)推薦邊緣設(shè)備手機(jī)、開發(fā)板INT4/INT8單條 100-500ms端側(cè)隱私計(jì)算、離線應(yīng)用選哪種取決于你的 QPS 要求和硬件預(yù)算。如果只是做離線的內(nèi)容去重或者知識(shí)庫(kù)預(yù)處理純 CPU 加 INT8 量化完全夠用還省了顯卡錢。如果是在線服務(wù)哪怕 QPS 只有個(gè)位數(shù)也建議上 GPU因?yàn)?CPU 在高并發(fā)下延遲會(huì)迅速劣化。3. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)3.1 向量維度與歸一化兩個(gè)最容易被忽略的細(xì)節(jié)EmbeddingGemma 2 輸出的向量維度通常在幾百到上千之間具體以你拿到的版本為準(zhǔn)這個(gè)維度不是隨便定的。維度太低語(yǔ)義區(qū)分度不夠很多不相關(guān)的內(nèi)容會(huì)擠在一起維度太高存儲(chǔ)和計(jì)算成本飆升而且在高維空間里距離度量會(huì)變得不穩(wěn)定。中等維度是精度和成本的平衡點(diǎn)。比維度更容易被忽略的是歸一化。嵌入向量在做相似度計(jì)算前幾乎都要做 L2 歸一化也就是把向量長(zhǎng)度縮放到 1。為什么因?yàn)橛嘞蚁嗨贫缺举|(zhì)上只關(guān)心方向不關(guān)心長(zhǎng)度如果不歸一化一個(gè)內(nèi)容多的向量可能因?yàn)槟iL(zhǎng)大而在點(diǎn)積里占便宜導(dǎo)致檢索結(jié)果偏向長(zhǎng)文本。歸一化之后點(diǎn)積就等于余弦相似度計(jì)算也更快。我見過(guò)不少新手直接拿原始向量去算距離結(jié)果召回質(zhì)量莫名其妙地差排查半天才發(fā)現(xiàn)是漏了歸一化這一步。提示歸一化一定要在入庫(kù)前做一次查詢時(shí)也做一次保證兩邊在同一尺度上。如果用的是向量數(shù)據(jù)庫(kù)很多庫(kù)支持在寫入時(shí)自動(dòng)歸一化但查詢向量往往要你自己處理別想當(dāng)然。3.2 文本和圖像怎么進(jìn)同一個(gè)空間多模態(tài)嵌入最核心的機(jī)制是共享的向量空間。訓(xùn)練時(shí)模型會(huì)拿到大量的圖文配對(duì)數(shù)據(jù)然后通過(guò)對(duì)比學(xué)習(xí)的方式讓配對(duì)的圖文向量互相靠近不配對(duì)的互相遠(yuǎn)離。這個(gè)過(guò)程有點(diǎn)像教一個(gè)小孩認(rèn)字卡圖片和對(duì)應(yīng)的詞一起出現(xiàn)出現(xiàn)多了他看到圖就想到詞看到詞就想到圖。落到實(shí)操上你需要注意輸入預(yù)處理的一致性。文本側(cè)通常要做分詞、截?cái)嗟阶畲箝L(zhǎng)度圖像側(cè)要做縮放、歸一化到模型期望的尺寸和數(shù)值范圍。這兩側(cè)的預(yù)處理如果和模型訓(xùn)練時(shí)不一致嵌入質(zhì)量會(huì)明顯下降。比如模型訓(xùn)練時(shí)圖像是 224x224 輸入你喂 512x512 進(jìn)去雖然模型可能不報(bào)錯(cuò)但出來(lái)的向量分布會(huì)偏檢索效果打折。3.3 批處理與顯存占用的關(guān)系本地推理繞不開顯存管理。740M 參數(shù)在 FP16 下權(quán)重占約 1.5GB但這只是權(quán)重實(shí)際推理時(shí)還要算上激活值、中間張量和批處理帶來(lái)的額外占用。批大小batch size每翻一倍激活相關(guān)的顯存大致也翻倍。我一般建議從 batch size 8 或 16 起步觀察顯存占用再往上加。這里有個(gè)經(jīng)驗(yàn)公式可以參考顯存占用 ≈ 權(quán)重 batch_size × 單樣本激活開銷。單樣本激活開銷和序列長(zhǎng)度、圖像分辨率強(qiáng)相關(guān)。如果你處理的是長(zhǎng)文本或高分辨率圖單樣本開銷會(huì)明顯變大這時(shí)候要么減小 batch要么縮短輸入。別一上來(lái)就把 batch 拉到 64然后 OOM 了再回頭一點(diǎn)點(diǎn)試那樣很浪費(fèi)時(shí)間。3.4 量化省顯存和掉精度之間的取舍量化是本地部署的必修課。FP16 轉(zhuǎn) INT8顯存直接砍半速度通常還能提升精度損失一般在 1% 以內(nèi)性價(jià)比極高。INT4 更激進(jìn)顯存再砍一半但精度損失可能到 2%-5%具體取決于量化方法和校準(zhǔn)數(shù)據(jù)。我的建議是優(yōu)先 INT8除非硬件實(shí)在吃緊再考慮 INT4。量化還有個(gè)坑是哪些層可以量化。有些實(shí)現(xiàn)會(huì)對(duì)所有線性層做量化有些會(huì)保留嵌入層和輸出層為高精度。嵌入層恰恰是嵌入模型的核心如果把它也粗暴量化了向量質(zhì)量可能崩得厲害。選量化方案時(shí)務(wù)必確認(rèn)它是否保護(hù)了嵌入相關(guān)的層。4. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)4.1 環(huán)境準(zhǔn)備與依賴安裝先把環(huán)境搭起來(lái)。我以 Python 生態(tài)為例這是最通用的路徑。假設(shè)你已經(jīng)裝好了 Python 3.9 和 pip接下來(lái)裝核心依賴。pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install transformers sentence-transformers pillow numpy這里解釋一下每個(gè)包的作用。torch和torchvision是深度學(xué)習(xí)底座圖像處理也靠它transformers提供模型加載和推理接口sentence-transformers在嵌入任務(wù)上封裝得更好用做相似度計(jì)算很方便pillow處理圖像讀寫numpy做向量運(yùn)算。如果你的機(jī)器沒有 NVIDIA 顯卡把cu121換成 CPU 版本的索引即可功能一樣只是慢一些。注意torch 版本和 CUDA 驅(qū)動(dòng)版本要匹配。裝完跑一句torch.cuda.is_available()返回 True 才算 GPU 可用。返回 False 的話先別急著懷疑模型八成是驅(qū)動(dòng)或版本沒對(duì)上。4.2 模型加載與首次推理驗(yàn)證環(huán)境好了先做一次最小可運(yùn)行的驗(yàn)證確認(rèn)模型能加載、能出向量。import torch from transformers import AutoModel, AutoProcessor model_id your-local-path-or-repo-id device cuda if torch.cuda.is_available() else cpu model AutoModel.from_pretrained(model_id, trust_remote_codeTrue).to(device) processor AutoProcessor.from_pretrained(model_id, trust_remote_codeTrue) model.eval() texts [一只橘貓趴在窗臺(tái)上, 陽(yáng)光下的貓咪] inputs processor(texttexts, return_tensorspt, paddingTrue, truncationTrue).to(device) with torch.no_grad(): outputs model(**inputs) embeddings outputs.last_hidden_state.mean(dim1) embeddings torch.nn.functional.normalize(embeddings, p2, dim1) print(embeddings.shape)這段代碼里有兩個(gè)關(guān)鍵點(diǎn)值得說(shuō)。第一model.eval()一定要調(diào)它會(huì)關(guān)掉 dropout 等訓(xùn)練態(tài)行為保證推理結(jié)果穩(wěn)定可復(fù)現(xiàn)。第二池化方式我用的是對(duì)最后一層隱狀態(tài)做平均池化這是嵌入模型里很常見的做法但具體用哪種池化要以模型說(shuō)明為準(zhǔn)——有的模型用 CLS token有的用平均池化用錯(cuò)了向量質(zhì)量會(huì)差很多。如果你不確定先查模型卡或者兩種都試一下看哪種在下游任務(wù)上表現(xiàn)好。4.3 文本嵌入的完整流程把上面的驗(yàn)證擴(kuò)展成可復(fù)用的文本嵌入函數(shù)。def embed_texts(texts, batch_size16): all_embeddings [] for i in range(0, len(texts), batch_size): batch texts[i:i batch_size] inputs processor(textbatch, return_tensorspt, paddingTrue, truncationTrue, max_length512).to(device) with torch.no_grad(): outputs model(**inputs) emb outputs.last_hidden_state.mean(dim1) emb torch.nn.functional.normalize(emb, p2, dim1) all_embeddings.append(emb.cpu()) return torch.cat(all_embeddings, dim0)max_length512是個(gè)需要你根據(jù)業(yè)務(wù)調(diào)整的參數(shù)。文本越長(zhǎng)語(yǔ)義越完整但計(jì)算量也越大。對(duì)于標(biāo)題、短句這類場(chǎng)景128 就夠?qū)τ陂L(zhǎng)文檔512 甚至更長(zhǎng)才有意義。截?cái)嗖呗砸惨⒁饽J(rèn)是從尾部截?cái)嗳绻愕年P(guān)鍵信息在末尾得改成從頭部截?cái)嗷蛘咦龇侄吻度朐倬酆稀?.4 圖像嵌入與跨模態(tài)檢索圖像側(cè)的處理邏輯類似只是輸入換成圖片。from PIL import Image def embed_images(image_paths, batch_size8): all_embeddings [] for i in range(0, len(image_paths), batch_size): batch_paths image_paths[i:i batch_size] images [Image.open(p).convert(RGB) for p in batch_paths] inputs processor(imagesimages, return_tensorspt).to(device) with torch.no_grad(): outputs model(**inputs) emb outputs.last_hidden_state.mean(dim1) emb torch.nn.functional.normalize(emb, p2, dim1) all_embeddings.append(emb.cpu()) return torch.cat(all_embeddings, dim0)跨模態(tài)檢索的用法就很直觀了把文本向量和圖像向量都算出來(lái)然后算余弦相似度取 top-k。def cross_modal_search(query_text, image_embeddings, top_k5): query_emb embed_texts([query_text]) sims torch.matmul(query_emb, image_embeddings.T).squeeze(0) top_indices torch.topk(sims, top_k).indices return top_indices.tolist(), sims[top_indices].tolist()因?yàn)閮蛇叾甲隽藲w一化這里的矩陣乘法直接就是余弦相似度省去了逐條計(jì)算的麻煩。這也是為什么我一直強(qiáng)調(diào)歸一化——它讓后續(xù)計(jì)算變得極其簡(jiǎn)潔。4.5 接入向量數(shù)據(jù)庫(kù)做規(guī)?;瘷z索數(shù)據(jù)量小的時(shí)候暴力算相似度沒問(wèn)題一旦上了十萬(wàn)、百萬(wàn)級(jí)就必須上向量數(shù)據(jù)庫(kù)。常見的選型有 FAISS、Milvus、Qdrant 等。以 FAISS 為例它輕量、純本地、上手快很適合個(gè)人項(xiàng)目。import faiss import numpy as np dim embeddings.shape[1] index faiss.IndexFlatIP(dim) # 內(nèi)積索引配合歸一化向量等價(jià)于余弦相似度 index.add(embeddings.numpy().astype(float32)) query embed_texts([查詢內(nèi)容]).numpy().astype(float32) scores, indices index.search(query, k5) print(indices, scores)IndexFlatIP是精確檢索結(jié)果最準(zhǔn)但速度隨數(shù)據(jù)量線性下降。數(shù)據(jù)量超過(guò)百萬(wàn)后可以換成IndexIVFFlat這類近似索引用一點(diǎn)點(diǎn)召回率換大幅速度提升。這個(gè)取舍要看你業(yè)務(wù)對(duì)準(zhǔn)確率的容忍度。5. 常見問(wèn)題與排查技巧實(shí)錄5.1 檢索結(jié)果不相關(guān)先查這五個(gè)地方嵌入檢索效果差原因往往不在模型本身而在流程細(xì)節(jié)。我整理了一張排查表按優(yōu)先級(jí)從高到低排。排查項(xiàng)典型癥狀檢查方法修復(fù)方式歸一化缺失長(zhǎng)文本霸榜檢查向量模長(zhǎng)是否接近 1入庫(kù)和查詢都做 L2 歸一化池化方式錯(cuò)誤整體效果平庸對(duì)比 CLS 與平均池化按模型說(shuō)明選正確池化輸入預(yù)處理不一致圖文檢索尤其差核對(duì)圖像尺寸和數(shù)值范圍嚴(yán)格對(duì)齊訓(xùn)練時(shí)預(yù)處理截?cái)噙^(guò)長(zhǎng)/過(guò)短長(zhǎng)文檔召回差統(tǒng)計(jì)被截?cái)啾壤{(diào)整 max_length 或分段維度不匹配直接報(bào)錯(cuò)或亂序打印向量 shape統(tǒng)一所有向量的維度我踩過(guò)最深的坑是歸一化。當(dāng)時(shí)做商品去重發(fā)現(xiàn)長(zhǎng)標(biāo)題的商品總是被判定為相似排查了兩天才發(fā)現(xiàn)是入庫(kù)時(shí)忘了歸一化長(zhǎng)標(biāo)題向量模長(zhǎng)大點(diǎn)積自然占優(yōu)。加上歸一化后問(wèn)題立刻消失。這個(gè)教訓(xùn)讓我養(yǎng)成了一個(gè)習(xí)慣任何向量入庫(kù)前先打印一下模長(zhǎng)分布確認(rèn)都在 1 附近。5.2 顯存不夠用的幾種解法OOM 是本地推理的高頻問(wèn)題。按代價(jià)從低到高我一般這么處理先降 batch size這是最直接的再考慮縮短輸入長(zhǎng)度長(zhǎng)文本和超大圖是顯存殺手然后上量化INT8 通常能救急最后才是換硬件。很多時(shí)候降 batch 加 INT8 就能解決沒必要一上來(lái)就換卡。還有一個(gè)容易被忽略的點(diǎn)是內(nèi)存泄漏。如果你在循環(huán)里不斷創(chuàng)建 tensor 而不釋放顯存會(huì)緩慢增長(zhǎng)直到 OOM。用torch.no_grad()包住推理、及時(shí)把結(jié)果.cpu()挪走、避免在循環(huán)里保留計(jì)算圖這幾個(gè)習(xí)慣能規(guī)避大部分泄漏。5.3 推理速度慢的優(yōu)化路徑速度慢先定位瓶頸在哪。用time.time()在預(yù)處理、前向推理、后處理三段分別打點(diǎn)看哪段最耗時(shí)。常見情況是預(yù)處理反而成了瓶頸尤其是圖像解碼和縮放。這時(shí)候可以把圖像預(yù)處理放到多進(jìn)程里做和 GPU 推理流水線化整體吞吐能提升不少。另一個(gè)提速手段是批處理。GPU 在 batch 較大時(shí)利用率才高單條推理往往浪費(fèi)算力。把請(qǐng)求攢一攢再一起推吞吐能翻好幾倍。代價(jià)是單條延遲略微上升這個(gè)取舍要看你業(yè)務(wù)是重吞吐還是重延遲。5.4 量化后精度下降怎么辦量化掉精度是正常的但如果掉得離譜通常是量化方法或校準(zhǔn)數(shù)據(jù)的問(wèn)題。我的經(jīng)驗(yàn)是校準(zhǔn)數(shù)據(jù)要覆蓋你實(shí)際業(yè)務(wù)的分布別隨便拿幾百條通用文本去校準(zhǔn)。如果你的業(yè)務(wù)是電商就用商品標(biāo)題和圖片去校準(zhǔn)如果是法律文檔就用法律文本。校準(zhǔn)數(shù)據(jù)和真實(shí)分布越接近量化后的精度損失越小。如果 INT8 還是不滿意可以試試只量化部分層把嵌入層和輸出層保留為 FP16。這種混合精度方案在嵌入模型上往往比全量化效果好很多顯存占用介于兩者之間是個(gè)不錯(cuò)的折中。6. 我在這類模型上的一些實(shí)操心得做嵌入相關(guān)的項(xiàng)目久了會(huì)發(fā)現(xiàn)很多問(wèn)題不是模型能力不夠而是工程細(xì)節(jié)沒摳到位。我分享幾個(gè)自己反復(fù)驗(yàn)證過(guò)的經(jīng)驗(yàn)。第一先建立評(píng)估集再調(diào)優(yōu)。很多人一上來(lái)就換模型、調(diào)參數(shù)但沒有一個(gè)固定的評(píng)估集根本不知道改動(dòng)是變好還是變壞。我一般會(huì)準(zhǔn)備 50-100 條帶標(biāo)注的查詢-結(jié)果對(duì)每次改動(dòng)都跑一遍看召回率和 MRR 的變化。這個(gè)評(píng)估集不用大但一定要有代表性。第二向量維度不是越高越好。我做過(guò)一個(gè)實(shí)驗(yàn)把 768 維降到 256 維存儲(chǔ)省了三分之二檢索速度快了近一倍而召回率只掉了不到 2%。對(duì)于很多業(yè)務(wù)場(chǎng)景這個(gè)取舍非常劃算。降維可以用 PCA也可以用模型自帶的降維輸出具體看模型支持。第三多模態(tài)檢索里文本查詢的質(zhì)量比圖像查詢更關(guān)鍵。因?yàn)橛脩糨斎氲奈谋就茈S意而圖像本身信息量大。我一般會(huì)對(duì)查詢文本做一點(diǎn)輕量改寫或擴(kuò)展比如補(bǔ)全同義詞召回率能提升明顯。這個(gè)技巧在電商搜索里尤其管用。第四別忘了緩存。熱門查詢的嵌入結(jié)果完全可以緩存起來(lái)避免重復(fù)計(jì)算。一個(gè)簡(jiǎn)單的 LRU 緩存就能擋掉大量重復(fù)請(qǐng)求對(duì)降低延遲幫助很大。最后說(shuō)個(gè)關(guān)于本地推理的體會(huì)。本地跑嵌入模型最大的價(jià)值不是省錢而是讓你敢于做以前不敢做的事。以前用云端 API每調(diào)一次都心疼很多實(shí)驗(yàn)不敢放開做本地跑起來(lái)之后你可以隨便試、隨便調(diào)迭代速度完全不一樣。這種心理成本的降低往往比賬面上的費(fèi)用節(jié)省更有價(jià)值。740M 這個(gè)尺寸恰好讓這種自由變得觸手可及。