你會不會常常遇到這種情況?電腦裡堆滿了 PDF、Word 檔、筆記,但每次要找一個關鍵資料,就得一個一個資料夾慢慢翻,有時候甚至忘記檔案叫什麼名字,只能憑印象亂猜。
更慘的是,如果你今天在飛機上、地鐵裡,或者去露營、出國沒有網路,那些雲端搜尋工具像是 Google Drive 或 Notion 的 AI 功能,通通不能用。你只能對著離線的檔案乾瞪眼。
今天這篇文章,就是要教你一套「在地端跑的 AI 搜尋引擎」。我們會用到一個超級輕量的模型叫做 Ternlight,它的大小只有 7MB,比一張手機照片還小。你可以把它放在你的電腦裡,不用連上網路,就能用 AI 的語意理解能力,快速找到你需要的檔案。
這不是科幻電影,而是你今晚就能學會的技能。準備好了嗎?我們開始吧。
為什麼你需要一個「離線 AI 搜尋」?
你可能會想:「我用 Windows 的搜尋功能不就好了嗎?」傳統的檔案搜尋(比如按 Ctrl+F 或 Windows 搜尋列)是「關鍵字比對」。意思是,它只會找檔案名稱或是檔案裡面有出現你打的那些字的文件。
但問題是,人類的記憶不是這樣運作的。舉個例子:你記得你幾個月前寫過一份關於「客戶滿意度調查」的報告,但你忘記檔案名稱了,而且檔案裡面寫的是「NPS 分數分析」或是「顧客回饋總結」。你用「客戶滿意度」去搜尋,傳統搜尋可能就找不到,因為它沒有「理解」NPS 就是客戶滿意度的一種衡量方式。
這就是「語意搜尋」的強項。AI 模型會把文字轉換成數學上的「向量」,然後根據意思的接近程度來找資料。所以即使你用的詞彙和檔案裡的字不完全一樣,AI 也能幫你找到。
另一個更重要的原因是 隱私。把公司機密文件或個人日記丟到 ChatGPT 或 Google 的雲端去搜尋,其實就是把資料交給別人。用 Ternlight 這種本地模型,所有計算都在你的電腦上完成,檔案永遠不會離開你的硬碟。這對於注重隱私的香港和台灣朋友來說,是非常實用的選擇。
第一步:認識 Ternlight —— 7MB 的超級小幫手
Ternlight 是一個「嵌入模型」(Embedding Model)。嵌入模型的工作就是把文字變成一串數字(向量),讓電腦能夠理解文字之間的「距離」。意思相近的句子,它們的向量距離就會很近;意思無關的句子,距離就會很遠。
一般的大型嵌入模型(像是 OpenAI 的 text-embedding-3-small)雖然很強,但它們需要網路,而且體積很大。Ternlight 的厲害之處在於它只有 7MB,而且可以在瀏覽器裡用 WebAssembly(WASM)跑起來,速度非常快。它雖然小,但在語意搜尋的表現上,對於個人文件管理來說已經非常夠用。
我們要做的步驟如下:
- 準備你的文件資料夾:把你想搜尋的所有文件(.txt, .md, .pdf 等)放在一個資料夾裡。
- 安裝一個本機工具:我們會用一個叫做
local-ai-search的開源工具(或是類似的 Python 腳本),它會幫我們呼叫 Ternlight 模型來處理檔案。 - 建立索引:工具會掃描你資料夾裡的所有文件,把每一份文件都餵給 Ternlight,產生一個對應的「向量」。這個過程叫做「索引」。
- 開始搜尋:當你想找東西時,只要輸入一句話,工具就會把你的問題也轉成向量,然後比對所有文件向量的距離,找出最相關的幾份文件。
聽起來很複雜?別擔心,我們一步一步來。
第二步:實戰教學 —— 用 Python 建立你的離線搜尋引擎
以下步驟需要你有一點點使用命令列(Terminal)的基礎,但就算你是新手,只要跟著複製貼上,也能成功。
前置準備: 你的電腦需要安裝 Python(3.8 以上版本)。如果不確定,可以打開終端機輸入 python --version 來檢查。
1. 安裝需要的套件
打開你的終端機(Windows 是命令提示字元或 PowerShell,Mac 是終端機),輸入以下指令安裝必要的 Python 函式庫:
pip install sentence-transformers chromadb
sentence-transformers:這是一個可以載入各種嵌入模型的套件,我們會用它來載入 Ternlight。chromadb:這是一個輕量級的向量資料庫,可以幫助我們快速儲存和搜尋向量。
2. 下載 Ternlight 模型
Ternlight 在 HuggingFace 上有一個套件。我們可以直接用程式碼下載。建立一個新的 Python 檔案,叫做 build_index.py,然後貼上以下程式碼:
# build_index.py
import os
from sentence_transformers import SentenceTransformer
import chromadb
from chromadb.utils import embedding_functions
# 1. 設定你的文件資料夾路徑(改成你自己的)
DOCUMENTS_FOLDER = "./my_documents" # 例如:C:\Users\你的名字\Documents
# 2. 載入 Ternlight 模型
# 模型名稱是 "ternlight/ternlight-embedding-v1" (這是範例名稱,實際名稱請查 HuggingFace)
# 但因為 Ternlight 只有 7MB,我們用 sentence-transformers 載入一個很小的模型
# 這裡我們用 'all-MiniLM-L6-v2' 作為替代,它只有 22MB,但效果很好。
# 如果你想用更小的,可以試試 'paraphrase-albert-small-v2' (約 43MB)
print("正在載入嵌入模型...")
model = SentenceTransformer('all-MiniLM-L6-v2')
print("模型載入完成!")
# 3. 建立 ChromaDB 客戶端(資料會存在本機硬碟)
client = chromadb.PersistentClient(path="./vector_db")
collection = client.get_or_create_collection(name="my_files")
# 4. 掃描資料夾內的所有 .txt 檔案
print(f"正在掃描資料夾:{DOCUMENTS_FOLDER}")
documents = []
ids = []
file_paths = []
for filename in os.listdir(DOCUMENTS_FOLDER):
if filename.endswith(".txt"): # 你也可以改成 .md 或 .pdf(需要另外安裝套件)
file_path = os.path.join(DOCUMENTS_FOLDER, filename)
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
documents.append(content)
# 用檔案名稱當作 ID,避免重複
ids.append(filename)
file_paths.append(file_path)
print(f" 已讀取:{filename}")
if not documents:
print("沒有找到任何 .txt 檔案,請確認資料夾路徑。")
exit()
# 5. 將文件轉換成向量並存入 ChromaDB
print("正在建立索引...(這可能需要幾秒鐘)")
embeddings = model.encode(documents).tolist()
collection.add(
embeddings=embeddings,
documents=documents,
ids=ids,
metadatas=[{"source": fp} for fp in file_paths]
)
print("索引建立完成!總共建立了", len(documents), "份文件的索引。")
重要提醒:上面的程式碼中,我使用了 all-MiniLM-L6-v2 這個模型,因為它非常成熟且穩定。如果你想換成真正的 Ternlight,可以去 HuggingFace 搜尋 Ternlight,然後把 model 的名稱改成你下載的模型名稱。但對於初學者來說,all-MiniLM-L6-v2 已經非常夠用,而且速度很快。
3. 執行搜尋
建立另一個 Python 檔案,叫做 search.py:
# search.py
from sentence_transformers import SentenceTransformer
import chromadb
# 載入同樣的模型
model = SentenceTransformer('all-MiniLM-L6-v2')
# 連接到同一個向量資料庫
client = chromadb.PersistentClient(path="./vector_db")
collection = client.get_collection(name="my_files")
# 輸入你想搜尋的內容
query = input("請輸入你的搜尋問題:")
# 將問題轉成向量
query_embedding = model.encode([query]).tolist()
# 在資料庫中搜尋最相似的 3 份文件
results = collection.query(
query_embeddings=query_embedding,
n_results=3
)
print("\n🔍 搜尋結果:")
for i, (doc, metadata, distance) in enumerate(zip(results['documents'][0], results['metadatas'][0], results['distances'][0])):
# distance 越小表示越相關
print(f"\n第 {i+1} 名(相關度分數:{1 - distance:.2f})")
print(f"來源檔案:{metadata['source']}")
# 只顯示前 200 個字
print(f"內容摘要:{doc[:200]}...")
4. 測試看看
在你的 my_documents 資料夾裡放幾個 .txt 檔案。例如:
iphone_review.txt:裡面寫「這支手機的電池續航力很棒,拍照效果也很好。」laptop_review.txt:裡面寫「這台筆電的處理器很快,但重量有點重。」
然後執行 python search.py,輸入:「哪個產品的電池比較好?」
你會發現,即使你沒有提到「iPhone」,AI 也能根據「電池」這個概念,正確地找出 iphone_review.txt。
讓搜尋更強大的進階技巧
以上的基礎版本已經很實用了,但我們還可以讓它更強。
1. 支援 PDF 和 Word 檔案
要搜尋 PDF 或 Word 文件,你需要安裝額外的套件來讀取它們的內容。
pip install PyPDF2 python-docx
然後在 build_index.py 的掃描檔案部分,加入對 .pdf 和 .docx 的支援:
import PyPDF2
from docx import Document
# ... 前面的程式碼 ...
for filename in os.listdir(DOCUMENTS_FOLDER):
file_path = os.path.join(DOCUMENTS_FOLDER, filename)
content = ""
if filename.endswith(".txt"):
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
elif filename.endswith(".pdf"):
with open(file_path, 'rb') as f:
reader = PyPDF2.PdfReader(f)
for page in reader.pages:
content += page.extract_text()
elif filename.endswith(".docx"):
doc = Document(file_path)
content = "\n".join([p.text for p in doc.paragraphs])
if content:
documents.append(content)
ids.append(filename)
file_paths.append(file_path)
print(f" 已讀取:{filename}")
2. 建立自動排程更新
如果你每天都會新增文件,可以設定一個排程,讓系統自動重新建立索引。在 Mac/Linux 上可以用 cron,在 Windows 上可以用「工作排程器」。你只需要定時執行 python build_index.py 就可以了。
3. 製作一個簡單的網頁介面
如果你不喜歡用命令列,可以把 search.py 改寫成一個 Flask 或 Streamlit 的網頁應用。這樣你就可以在瀏覽器裡,用一個漂亮的搜尋框來找檔案了。
總結與 FAQ
今天你學到了一項超實用的技能:用一個不到 50MB 的 AI 模型,在你的電腦上建立一個離線的語意搜尋引擎。這不僅保護了你的隱私,也讓你在沒有網路的時候,依然能夠快速找到需要的資訊。
這個技術的應用場景非常廣:
- 學生:搜尋筆記和參考文獻。
- 上班族:快速找到合約、報告和會議記錄。
- 創作者:管理靈感筆記和草稿。
- 任何注重隱私的人:不想把個人資料上傳到雲端。
不要害怕嘗試,先從幾個 .txt 檔案開始,感受一下語意搜尋的威力。一旦你習慣了這種搜尋方式,你就再也回不去傳統的 Ctrl+F 了。
延伸閱讀
常見問題
Q: Ternlight 模型要到哪裡下載?我找不到 HuggingFace 上的正確名稱。
A: 目前 Ternlight 在 HuggingFace 上的正式套件名稱還在開發中。如果你無法找到,強烈建議使用 all-MiniLM-L6-v2 作為替代。它的大小約 22MB,比 Ternlight 稍大,但效果非常穩定,社群支援也最完善。對於個人文件搜尋來說,這個模型的表現已經綽綽有餘。
Q: 我建立索引後,新增了文件,需要重新執行 build_index.py 嗎?
A: 是的,目前這個基礎版本每次都會重新掃描所有檔案並重建索引。如果你的檔案數量很多(超過幾千份),建議可以研究 ChromaDB 的增量更新功能,或是用 collection.add() 只加入新的檔案,不要每次都重建。
Q: 搜尋中文的效果好嗎?
A: 如果你使用 all-MiniLM-L6-v2,它對中文的理解力還算不錯,但當然沒有專門的中文模型(例如 shibing624/text2vec-base-chinese)那麼好。如果你主要是搜尋中文文件,可以把模型換成中文專用模型,程式碼完全一樣,只需修改第一行的 model = SentenceTransformer('shibing624/text2vec-base-chinese') 即可。
Q: 這個方法可以搜尋圖片或音檔嗎? A: 這個教學專注在文字搜尋。要搜尋圖片,你需要使用多模態模型(例如 CLIP),它能同時把圖片和文字轉成向量。這個概念是一樣的,但需要的模型會大很多(通常幾百 MB 到幾 GB)。如果這是你的需求,可以留言告訴我們,我們可以再寫一篇進階教學。
Q: 我的文件有幾千份,這個方法會不會很慢?
A: 對於幾千份文件,all-MiniLM-L6-v2 的建立索引時間大約是幾分鐘。搜尋時間幾乎是即時的(小於 0.1 秒)。如果你的文件超過十萬份,建議使用更專業的向量資料庫(如 Qdrant 或 Milvus),但對於一般個人使用,ChromaDB 已經非常夠用。