建方案)
搜索引擎全文檢索后端前端CLI【免費(fèi)下載鏈接】histerYour own search engine項(xiàng)目地址https://gitcode.com/GitHub_Trending/hi/hister點(diǎn)擊查看免費(fèi)下載導(dǎo)讀hister 是一個(gè)自托管的個(gè)人搜索引擎Your own search engine它的語義搜索需要向量數(shù)據(jù)庫能力。為了讓 sqlite-vec 這一 SQLite 向量擴(kuò)展能夠跨平臺(tái)、零系統(tǒng)依賴地構(gòu)建進(jìn) Go 二進(jìn)制項(xiàng)目在server/vectorstore/sqlitevec/目錄下維護(hù)了一個(gè)自包含的本地捆綁包。本文以 server/vectorstore/sqlitevec/README.md 為骨架結(jié)合vec.go、update.sh、sqlite.go等源碼講解這一捆綁方案的設(shè)計(jì)動(dòng)機(jī)、CGO 細(xì)節(jié)、版本更新流程以及它如何支撐 hister 的 vec0 虛擬表向量檢索。為什么需要本地捆綁跨平臺(tái)構(gòu)建的痛點(diǎn)sqlite-vec 是 SQLite 的一個(gè) C 語言擴(kuò)展通過注冊vec0虛擬表來提供 KNNK 近鄰向量搜索能力。如果像普通擴(kuò)展那樣依賴系統(tǒng)安裝的共享庫.so/.dylib/.dllhister 的發(fā)布和部署就會(huì)面臨一系列問題用戶在 Alpine Linuxmusl libc、macOS、Windows 等環(huán)境上需要自行編譯或下載對應(yīng)平臺(tái)的擴(kuò)展文件擴(kuò)展與宿主 SQLite 的版本/編譯選項(xiàng)不匹配時(shí)可能加載失敗Docker 多架構(gòu)鏡像docker-bake.hcl支持多平臺(tái)構(gòu)建需要為每個(gè)平臺(tái)準(zhǔn)備擴(kuò)展維護(hù)成本極高。README 開門見山地給出了結(jié)論WARNING: This is required to be able to build sqlite-vec cross platform without dependencies也就是說這個(gè)包的存在不是可選項(xiàng)而是實(shí)現(xiàn)跨平臺(tái)構(gòu)建的前提。方案本身很簡單把 sqlite-vec 的 C 源碼sqlite-vec.c和頭文件sqlite-vec.h直接拷貝進(jìn)倉庫再補(bǔ)一個(gè)sqlite3.h頭文件然后通過 CGO 的CGO_CFLAGS指向 mattn/go-sqlite3 的包目錄。這樣整個(gè)構(gòu)建過程完全自包含不依賴任何系統(tǒng)庫。目錄結(jié)構(gòu)捆綁包的構(gòu)成整個(gè)捆綁包位于 server/vectorstore/sqlitevec/包含以下文件文件來源作用sqlite-vec.csqlite-vec v0.1.6上游 C 源碼vec0 虛擬表、vec_each表值函數(shù)及距離函數(shù)L2、cosine 等的完整實(shí)現(xiàn)sqlite-vec.hsqlite-vec v0.1.6上游頭文件聲明sqlite3_vec_init入口與版本宏SQLITE_VEC_VERSION v0.1.6sqlite3.hmattn/go-sqlite3 v1.14.42對應(yīng) SQLite 3.51.3編譯期所需的 SQLite API 聲明vec.go本倉庫Go 包入口包含 CGO 預(yù)處理指令與Auto()注冊函數(shù)update.sh本倉庫從上游自動(dòng)拉取并更新上述 C 文件的維護(hù)腳本其中sqlite3.h是關(guān)鍵的膠水。README 稱之為 one-liner sqlite3.h shim實(shí)際實(shí)現(xiàn)上見 update.sh是把 mattn/go-sqlite3 模塊緩存里的sqlite3-binding.h直接拷貝為sqlite3.h——因?yàn)?SQLite 的頭文件必須與編譯進(jìn)二進(jìn)制的那份 SQLite 實(shí)現(xiàn)來自 mattn/go-sqlite3嚴(yán)格一致否則擴(kuò)展調(diào)用 SQLite API 時(shí)可能因 ABI 不匹配而出錯(cuò)。捆綁這份頭文件使得構(gòu)建時(shí)無需在系統(tǒng)里額外安裝 SQLite 開發(fā)包。vec.goCGO 前奏與進(jìn)程級(jí)注冊Go 側(cè)的入口是 vec.go它的 CGO 預(yù)處理指令是整個(gè)捆綁方案的樞紐// #cgo CFLAGS: -DSQLITE_CORE // #cgo CFLAGS: -Du_int8_tuint8_t -Du_int16_tuint16_t -Du_int64_tuint64_t // #cgo linux LDFLAGS: -lm // #include sqlite-vec.h import C逐行拆解-DSQLITE_CORE告訴 sqlite-vec 以內(nèi)嵌核心模式編譯。sqlite-vec.h中據(jù)此選擇包含sqlite3.h而非加載器模式的sqlite3ext.h即擴(kuò)展直接靜態(tài)編譯進(jìn)宿主進(jìn)程而不是作為運(yùn)行時(shí)動(dòng)態(tài)加載的共享庫。-Du_int8_tuint8_t ...musl 兼容這是打包時(shí)專門為 Alpine Linux 等 musl libc 環(huán)境打的補(bǔ)丁。musl 不提供 POSIX 的u_int*_t別名而 sqlite-vec.c 的源碼用它來 typedef C99 的uint*_t類型這些宏讓 typedef 在 musl 上變成空操作在 glibc 上也無害類型本就兼容。沒有這三行hister 的 Docker 鏡像Alpine 基礎(chǔ)鏡像根本無法編譯通過。-lmLinux 下鏈接數(shù)學(xué)庫vec0 的距離計(jì)算需要sqrt等數(shù)學(xué)函數(shù)。包提供的唯一公開 API 是Auto()func Auto() { C.sqlite3_auto_extension((*[0]byte)(C.sqlite3_vec_init)) }它調(diào)用 SQLite 的sqlite3_auto_extension把sqlite3_vec_init注冊為自動(dòng)擴(kuò)展。這意味著進(jìn)程內(nèi)此后打開的每一個(gè) SQLite 連接都會(huì)自動(dòng)加載 sqlite-vec調(diào)用方無需在每個(gè)連接上手動(dòng)執(zhí)行SELECT load_extension(...)。這一設(shè)計(jì)配合了 hister 的數(shù)據(jù)庫訪問方式數(shù)據(jù)庫連接可能在不同模塊中創(chuàng)建Auto()在初始化時(shí)調(diào)用一次即可全局生效。真實(shí)調(diào)用鏈sqlite.go在 server/vectorstore/sqlite.go 中newSQLite()首先調(diào)用sqlitevec.Auto()然后打開主數(shù)據(jù)庫同目錄下的vectors.sqlite3向量庫并限制為單連接以避免 SQLite 鎖競爭func newSQLite(cfg *config.Config) (VectorStore, error) { sqlitevec.Auto() dbPath : cfg.FullPath(cfg.Server.Database) dir : filepath.Dir(dbPath) vecDBPath : filepath.Join(dir, vectors.sqlite3) db, err : sql.Open(sqlite3, vecDBPath) ... db.SetMaxOpenConns(1) ... }隨后Init()用SELECT vec_version()校驗(yàn)擴(kuò)展確實(shí)可用并創(chuàng)建基于 vec0 的embeddings虛擬表sqlite.go#L100-L110CREATE VIRTUAL TABLE embeddings USING vec0( user_id INTEGER PARTITION KEY, chunk_key TEXT PRIMARY KEY, embedding FLOAT[dimensions] distance_metriccosine )這里展示了 vec0 的三個(gè)特性PARTITION KEY按用戶分區(qū)KNN 查詢可限定分區(qū)、TEXT PRIMARY KEYvec0 內(nèi)部用 int64 rowid 存儲(chǔ)、以id text unique模擬文本主鍵見sqlite-vec.c中VEC0_SHADOW_ROWIDS_CREATE_PK_TEXT的注釋、以及distance_metriccosine余弦距離從默認(rèn)的 L2 遷移而來——sqlite.go的initEmbeddingsTable專門實(shí)現(xiàn)了舊 L2 表到 cosine 表的事務(wù)性數(shù)據(jù)遷移。FLOAT[n]的維度n來自配置項(xiàng)semantic_search.dimensions。查詢側(cè)sqlite.go#L254-L294使用 vec0 的 KNN 語法SELECT e.chunk_key, e.distance, ... FROM embeddings e LEFT JOIN chunk_meta m ON e.chunk_key m.chunk_key WHERE e.embedding MATCH ? AND e.k ? AND e.user_id ? ORDER BY e.distance其中MATCH傳入的是float32ToBlob序列化的小端序vec_f32二進(jìn)制向量sqlite.go#L310-L318k為返回候選數(shù)e.user_id分區(qū)條件讓 vec0 的vec0BestIndex在 chunk 層面提前過濾分區(qū)避免全庫掃描。結(jié)果中的distance換算為相似度1.0 - distance后再與semantic_search.similarity_threshold比較過濾隨后經(jīng) vectorstore.go 的候選放大topK * 4與文檔級(jí)去重每篇文檔最多保留 2 個(gè) chunk處理最終進(jìn)入索引器的語義重排。整套鏈路完全建立在Auto()注冊的捆綁擴(kuò)展之上。版本維護(hù)update.sh 與手工同步的代價(jià)捆綁方案的代價(jià)在 README 末尾被明確點(diǎn)出The downside is were copying upstream C files and need to update them manually when sqlite-vec releases.即上游發(fā)布新版本后必須手動(dòng)重新拉取 C 文件并同步版本號(hào)。為此項(xiàng)目提供了 update.sh支持兩種調(diào)用方式# 方式一通過 go generate 觸發(fā)版本號(hào)從 vec.go 注釋中自動(dòng)讀取 go generate ./server/vectorstore/sqlitevec/ # 方式二顯式指定版本 sh update.sh v0.1.6腳本執(zhí)行流程確定版本優(yōu)先用命令行參數(shù)未傳參時(shí)從vec.go中以// sqlite-vec source:開頭的注釋中解析版本號(hào)下載 C 源碼從 sqlite-vec-go-bindings 倉庫對應(yīng)版本的cgo目錄依次下載sqlite-vec.c和sqlite-vec.h依賴curl同步 sqlite3.h通過go list -m -json github.com/mattn/go-sqlite3定位模塊緩存目錄把其中的sqlite3-binding.h拷貝為sqlite3.h——保證頭文件始終與 go.mod 中鎖定的 mattn/go-sqlite3 版本當(dāng)前為 v1.14.42SQLite 3.51.3一致提示收尾提醒更新vec.go中的版本注釋。整個(gè)更新流程刻意手工化腳本只負(fù)責(zé)拉文件不自動(dòng)改代碼目的是讓版本變更成為一次可審查的顯式提交。當(dāng)前捆綁的版本在vec.go注釋與sqlite-vec.h的SQLITE_VEC_VERSION宏中均有記錄sqlite-vec v0.1.6。權(quán)衡總結(jié)何時(shí)該采用本地捆綁策略從 this 包的實(shí)現(xiàn)可以提煉出一套可復(fù)用的取舍邏輯維度本地捆綁本方案系統(tǒng)級(jí)依賴共享庫構(gòu)建復(fù)雜度高需處理 CGO、musl 兼容低安裝即用跨平臺(tái)可移植性強(qiáng)單二進(jìn)制自包含弱每平臺(tái)需準(zhǔn)備擴(kuò)展部署運(yùn)維無額外步驟需管理擴(kuò)展生命周期版本更新手動(dòng)同步上游 C 文件跟隨系統(tǒng)包管理器適用場景分發(fā)多平臺(tái) Docker 鏡像、追求零依賴已有系統(tǒng)包管理、單一可控環(huán)境hister 選擇前者換來的是docker-bake.hcl多平臺(tái)鏡像、Dockerfile 構(gòu)建、甚至靜態(tài)部署場景下的統(tǒng)一體驗(yàn)——用戶拿到一個(gè)二進(jìn)制就自帶完整的向量檢索能力這正是Your own search engine自托管理念在工程層面的體現(xiàn)。參考文件索引捆綁包說明server/vectorstore/sqlitevec/README.mdGo 入口與 CGO 指令server/vectorstore/sqlitevec/vec.go上游同步腳本server/vectorstore/sqlitevec/update.sh向量擴(kuò)展實(shí)現(xiàn)server/vectorstore/sqlitevec/sqlite-vec.cSQLite 頭文件 shimserver/vectorstore/sqlitevec/sqlite3.h向量庫初始化與查詢server/vectorstore/sqlite.go向量后端抽象與后端選擇server/vectorstore/vectorstore.go贊分享搜索引擎全文檢索后端前端CLI【免費(fèi)下載鏈接】histerYour own search engine項(xiàng)目地址https://gitcode.com/GitHub_Trending/hi/hister點(diǎn)擊查看免費(fèi)下載相關(guān)推薦如何用sqlite-vec構(gòu)建本地AI知識(shí)庫向量搜索終極指南如何用sqlite vec構(gòu)建本地AI知識(shí)庫向量搜索終極指南 在人工智能快速發(fā)展的今天 向量搜索 技術(shù)已成為構(gòu)建智能應(yīng)用的核心。sqlite vec作為一款向量數(shù)據(jù)庫數(shù)據(jù)庫C語言集成sqlite-vec構(gòu)建高效向量搜索應(yīng)用的完整指南C語言集成sqlite vec構(gòu)建高效向量搜索應(yīng)用的完整指南 sqlite vec是一個(gè)輕量級(jí)的向量搜索SQLite擴(kuò)展專為C語言開發(fā)者設(shè)計(jì)提供高效的向量向量數(shù)據(jù)庫數(shù)據(jù)庫SQLite向量搜索Python實(shí)戰(zhàn)5步實(shí)現(xiàn)本地語義搜索SQLite向量搜索Python實(shí)戰(zhàn)5步實(shí)現(xiàn)本地語義搜索 SQLite向量搜索sqlite vec是一個(gè)強(qiáng)大的本地向量搜索擴(kuò)展讓你能夠在任何SQLite向量數(shù)據(jù)庫數(shù)據(jù)庫創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考