我們推出了 NeoMME,這是一個包含 2.6 億和 8 億參數的多語言多模態編碼器系列。與許多生成式視覺語言模型不同,NeoMME 不使用獨立的預訓練視覺塔或因果語言模型。
單一雙向 Transformer 即可處理文字標記和原始圖像區塊,我們使用遮罩式離散擴散目標從頭開始訓練整個模型。我們針對視覺文件檢索對 NeoMME 進行了微調,採用了 ColPali 的頁面圖像方法。
NeoMME-Retriever 能在一次前向傳播中返回密集和後期互動嵌入。兩種模型尺寸在 ViDoRe v3 的 nDCG@10 和模型尺寸方面均位於 Pareto 前緣。
在 NVIDIA L40S GPU 上,以 2048×2048 的圖像輸入尺寸進行測試,2.6 億參數模型每秒可編碼約 51 頁,約是 ColModernVBERT 吞吐量的兩倍。分層標記池化和非對稱量化將後期互動索引儲存從每頁約 1.5 MB 減少到 6 kB(縮小 255 倍),同時保留了超過 95% 的基準 nDCG@10。
NeoMME 已在 Hugging Face Transformers 中提供,我們根據 Apache 2.0 許可證發布所有模型檢查點。
為何需要另一個多模態編碼器?
許多近期視覺文件檢索器都是從預訓練的生成式視覺語言模型改編而來。一個獨立預訓練的視覺編碼器產生視覺特徵,然後由一個投影器將其映射到語言模型的輸入空間。
接著,一個因果解碼器處理結合後的圖像和文字表示。然而,檢索、分類和標記任務並不需要自迴歸地生成文字,因此不需要因果解碼器,也無需承擔這種架構的參數和計算開銷。
ModernBERT 為雙向編碼器帶來了高效的架構和訓練改進。對於視覺文件檢索,ModernVBERT 應用了雙向 ModernBERT 風格的文字編碼器,但仍保留了獨立預訓練的 SigLIP2 視覺塔。
我們希望更進一步,設計並訓練一個多模態編碼器,而無需承擔視覺語言模型(VLM)的參數和計算開銷。NeoMME(發音為「nee-oh-me」)是一個多語言、多模態的基礎編碼器,它使用單一 Transformer 編碼器為輸入文字和/或圖像生成向量表示。它不基於任何現有的預訓練視覺塔、文字編碼器或文字解碼器。
與雙塔和 VLM 編碼器不同,NeoMME 在一個雙向 Transformer 中處理圖像區塊和文字標記,無需預訓練的視覺塔或預訓練的文字編碼器或解碼器。圖像和文字使用相同的計算路徑,因此 NeoMME 可以更容易地支援跨兩種模態的預訓練、微調、平行化和服務。
NeoMME 編碼器核心架構
一個 Transformer 處理圖像和文字
NeoMME 有兩種尺寸:2.6 億和 8 億參數。兩種變體共享相同的架構:
原生多模態輸入:文字輸入使用分解式標記嵌入,而圖像則被分割成 32×32 的非重疊網格區塊,並透過小型 MLP 進行投影。兩者都進入相同的 Transformer 編碼器。
動態圖像解析度:圖像保持其長寬比和尺寸。這使得模型可以在高解析度、資訊密集的文檔頁面上使用比內容較少的較小圖像更多的標記。
長雙向上下文:兩種模型都具有 16,384 個標記的上下文長度(足以容納兩張標準的 3840×2160 4K UHD 圖像)。大多數層使用對稱滑動窗口注意力,而每第六層和最後一層使用全域注意力。
現代編碼器堆疊:NeoMME 使用了最新的編碼器改進,例如分組查詢注意力、查詢鍵正規化、門控注意力、2D 旋轉位置嵌入和平方 ReLU MLP 等。
多語言文字:我們從頭開始訓練了一個 BPE 分詞器,其詞彙量為 13.1 萬個標記,訓練資料包括多語言文字、程式碼、數學和機器生成的圖像轉錄。
透過遮罩文字從圖像中學習
我們從頭開始將 NeoMME 預訓練為一個離散的遮罩擴散文字去噪器。對於每個純文字範例,我們以 0 到 1 之間的均勻採樣腐蝕率進行遮罩。每個符合條件的文字標記都以該速率獨立地被遮罩。
多模態範例使用 0.3 到 1 之間的腐蝕率。圖像區塊保持可見,而 NeoMME 則重建被遮罩的文字。在輕度遮罩下,模型通常可以僅從周圍文字中恢復缺失的單詞。例如,即使沒有圖像,「cat」也是「The [MASK] sat on the mat」的合理補全。
但高度遮罩會迫使模型學習圖像基礎的描述,而幾乎沒有來自未遮罩輸入文字標記的訊號。較高的文字腐蝕率消除了純語言捷徑,並鼓勵 NeoMME 使用可見的圖像證據。
預訓練混合了多語言文字、程式碼、數學、自然圖像和文件圖像。每個模型處理約 5,240 億個打包輸入標記,其中包括來自純文字範例的 2,900 億個標記。這個文字預算相對於 ModernBERT 的 2 兆訓練標記預算來說相對較小。因此,我們選擇 NorMuon 優化器來提高訓練期間的資料效率。
NeoMME-Retriever
為了對核心架構進行有意義的下游評估,我們使用 ColPali 引入的頁面圖像方法,對 NeoMME 進行了視覺文件檢索的微調。傳統的基於文字的檢索包括檢索文字區塊,而 NeoMME-Retriever 則對文件頁面截圖進行排序,並繞過了從 PDF 中提取文字所需的所有預處理 OCR 步驟。
將頁面視為圖像可以保留版面、圖表、表格、字體類型和大小以及其他即使是完美的 OCR 模型也無法捕捉的視覺線索。
用於密集和後期互動檢索的雙頭設計
NeoMME-Retriever 重複使用 NeoMME 核心架構,但在其之上增加了兩個共同訓練的檢索頭:
密集頭:將核心架構的隱藏狀態向量平均為一個正規化向量(平均池化)。密集嵌入是目前最常見的,它們緊湊且能與近似最近鄰(ANN)技術自然配合,實現快速檢索。
後期互動頭:將核心架構輸出隱藏狀態中的每個文字標記或圖像區塊投影到一個 128 維的正規化向量。與密集嵌入相比,更精細的粒度保留了單個查詢標記和圖像區域之間的局部匹配。
一次 NeoMME-Retriever 前向傳播會同時返回這兩種表示,無論您的使用案例和基礎設施如何,都能提供靈活性。我們通常建議使用後期互動嵌入,因為它們更強大,並且可以輕鬆與 NextPlaid 等開源函式庫一起使用。
然而,如果您擁有非常大的語料庫,您可以透過 NeoMME-Retriever 執行單次前向傳播以獲取密集嵌入,透過 ANN 索引檢索少量文件,然後使用後期互動對檢索到的候選文件進行重新排序。
緊湊模型尺寸下的競爭性檢索效能
我們報告了 ViDoRe v3 上的 nDCG@10 評分。NeoMME-Retriever-260M 達到 0.523,是所有評估模型中參數嚴格小於 8 億的模型中最高分。它與 ColQwen2.5 的 nDCG@10 僅相差 0.002,但使用的參數約少 14 倍。
NeoMME-Retriever-800M 達到 0.556,與尺寸相近的 Vultron Retriever Flash (0.8B) 的 nDCG@10 僅相差 0.009。兩種 NeoMME-Retriever 模型都位於模型尺寸的 Pareto 前緣。
ViDoRe v1 和 v2 使用 nDCG@5。在這兩個基準測試中,NeoMME-Retriever-260M 都優於 ColModernVBERT 和兩倍大的 ColSmol-500M。NeoMME-Retriever-800M 優於 ColPali v1.3,但使用的參數少了 3.6 倍。
使高解析度檢索在後期互動中變得實用
後期互動儲存空間與輸出嵌入中的向量數量呈線性關係。高解析度圖像包含更多區塊,因此會產生更大的嵌入。例如,一個 2048×2048 的方形頁面使用 NeoMME-Retriever 會產生包含 4,200 個向量的嵌入,約為 2.1 MB(float32 格式)。在 ViDoRe v3 基準測試中,測得的平均值約為每份文件 1.5 MB。
為了減少後期互動索引的儲存佔用空間,我們結合了兩種互補的壓縮方法:
分層標記池化:將給定多向量嵌入中相似的文件向量聚類,並用其平均值替換每個聚類,從而減少每頁儲存的向量數量。
非對稱量化:將文件嵌入量化為 int8 或二進制。由於查詢嵌入不被儲存,僅在運行時生成,因此它們可以保持更高的精度。
我們在 ViDoRe v3 上測試了這個設定。在池化因子為 10 且查詢和文件均為 int8 的情況下,儲存空間從每頁約 1.5 MB 減少到 39 kB,減少了 39 倍,同時保留了超過 99% 的基準 nDCG@10。更積極的配置使用池化因子 8、int8 查詢和二進制文件。該版本每頁使用 6 kB(縮小 255 倍),並保留了超過 95% 的原始檢索品質。
使用者可以根據儲存預算和所需的檢索品質,從這個前緣中選擇壓縮設定。
快速推論,降低多模態語料庫索引成本
在您可以搜尋語料庫之前,檢索模型必須將您的文件轉換為嵌入,這些嵌入將儲存在 Qdrant、Weaviate 或 Milvus 等向量資料庫中。更快的編碼速度可以加快索引的建立和新文件的添加,從而減少 GPU 運行時間和所需的計算成本。
因此,我們測量了 NeoMME-Retriever 與其他多模態文件檢索器的圖像編碼速度。我們使用了預處理的圖像張量,並針對每個模型和圖像尺寸單獨校準了批次大小。在一個 NVIDIA L40S 上,以 2048×2048 的輸入尺寸進行測試,NeoMME-Retriever-260M 每秒編碼約 51 頁,幾乎是 ColModernVBERT 每秒 26 頁的兩倍。
2.6 億和 8 億參數的 NeoMME-Retriever 模型在較小輸入圖像上的速度也比我們比較的其他模型更快。
親自試用 NeoMME-Retriever!
NeoMME-Retriever(2.6 億和 8 億參數)同時返回密集和多向量嵌入。下面的範例將展示如何使用它。



