Zvec 是阿里巴巴开源的嵌入式(进程内)向量数据库 —— 轻量、极速,可直接嵌入应用程序。本文将介绍如何使用 Zvec 的 Go 和 Rust SDK,从零搭建一套完整的 RAG(Retrieval-Augmented Generation)系统。

署名:本文由小米 MiMo-2.5-Pro 编写,Codex-5.5 审校。


什么是 RAG?

RAG(Retrieval-Augmented Generation,检索增强生成)是一种将外部知识检索大语言模型生成相结合的技术范式。其核心流程为:

  1. 索引(Indexing):将文档切分、向量化,存入向量数据库
  2. 检索(Retrieval):用户提问时,将问题向量化,在数据库中搜索最相关的文档片段
  3. 生成(Generation):将检索到的相关文档作为上下文,连同用户问题一起送入 LLM 生成回答

RAG 解决了 LLM 的几个核心痛点:

  • 知识时效性:无需重新训练模型,通过更新知识库即可获取最新信息
  • 幻觉问题:基于真实文档生成回答,大幅降低虚构内容的概率
  • 可溯源性:回答可追溯到具体来源文档,增强可信度

为什么选择 Zvec?

在 RAG 系统中,向量数据库是核心组件。Zvec 相比其他方案有以下优势:

特性 Zvec 传统方案(Milvus/Qdrant/Weaviate)
部署模式 进程内嵌入,无需独立服务 需要单独部署服务
延迟 毫秒级,零网络开销 需要网络往返
依赖 零外部服务依赖(仍需链接 Zvec C 库) 需要 Docker/K8s 等
运维 零运维 需要运维团队
运行形态 随应用进程部署,数据本地持久化 依赖服务端实现
检索能力 向量 + 全文 + 混合检索 各有差异

对于中小型或单机优先的 RAG 系统,Zvec 的嵌入式架构意味着:

  • 更简单的部署:你的 Go/Rust 服务本身就是一个向量数据库
  • 更低的延迟:没有网络序列化/反序列化开销
  • 更少的运维:无需管理独立的数据库集群

架构概览

┌─────────────────────────────────────────────────────────┐
│                    RAG Application                       │
│                                                          │
│  ┌──────────┐    ┌──────────────┐    ┌───────────────┐  │
│  │  文档    │───▶│  Embedding   │───▶│  Zvec 向量DB  │  │
│  │  加载器  │    │  向量化模型   │    │  (进程内)     │  │
│  └──────────┘    └──────────────┘    └───────┬───────┘  │
│                                              │          │
│  ┌──────────┐    ┌──────────────┐            │          │
│  │  LLM     │◀──│  Prompt 组装  │◀───────────┘          │
│  │  生成    │    │  上下文拼接   │     检索 Top-K        │
│  └──────────┘    └──────────────┘                       │
└─────────────────────────────────────────────────────────┘

核心流程:

  1. 文档加载 → 文本切分 → 向量化 → 存入 Zvec
  2. 用户提问 → 问题向量化 → Zvec 检索 → 获取相关文档
  3. 相关文档 + 用户问题 → Prompt 模板 → LLM 生成回答

环境准备

Zvec Go SDK

前置条件:

  • Go ≥ 1.21
  • C 编译器(gcc 或 clang)
  • CMake ≥ 3.20 和 Ninja
# 克隆仓库(含子模块)
git clone --recursive https://github.com/zvec-ai/zvec-go.git
cd zvec-go

# 下载预编译库(推荐,无需从源码构建)
go run ./cmd/download-libs -version v0.5.0

# 或者从源码构建
make build-zvec

Zvec Rust SDK

前置条件:

  • Rust 1.70+
  • CMake(用于构建 C 库,可选,SDK 会自动下载预编译库)
# Cargo.toml
[dependencies]
zvec = { git = "https://github.com/zvec-ai/zvec-rust.git", tag = "v0.5.0" }

注意:首次构建时,SDK 会自动从 GitHub Releases 下载预编译的 libzvec_c_api 库。如需自定义构建,可设置 ZVEC_LIB_DIR 环境变量。


Go 实战:构建 RAG 管道

1. 项目结构

rag-go/
├── main.go
├── embedder.go      # 向量化接口
├── splitter.go      # 文本切分
├── retriever.go     # 检索器
├── generator.go     # LLM 生成
└── go.mod

2. 定义 Zvec 集合

package rag

import (
    "fmt"
    zvec "github.com/zvec-ai/zvec-go"
)

// RAGCollection 封装 Zvec 集合操作
type RAGCollection struct {
    collection *zvec.Collection
}

// NewRAGCollection 创建一个用于 RAG 的向量集合
// dimension: embedding 向量维度(如 OpenAI text-embedding-3-small 为 1536)
func NewRAGCollection(path string, dimension int) (*RAGCollection, error) {
    // 初始化 Zvec
    if err := zvec.Initialize(nil); err != nil {
        return nil, err
    }

    // 定义 Schema
    schema := zvec.NewCollectionSchema("rag_docs")
    defer schema.Destroy()

    // 文档 ID 字段(带倒排索引,支持精确查找)
    idField := zvec.NewFieldSchema("doc_id", zvec.DataTypeString, false, 0)
    defer idField.Destroy()
    invertParams, _ := zvec.NewInvertIndexParams(true, false)
    defer invertParams.Destroy()
    idField.SetIndexParams(invertParams)
    schema.AddField(idField)

    // 文档内容字段
    contentField := zvec.NewFieldSchema("content", zvec.DataTypeString, false, 0)
    defer contentField.Destroy()
    schema.AddField(contentField)

    // 来源元数据字段
    sourceField := zvec.NewFieldSchema("source", zvec.DataTypeString, true, 0)
    defer sourceField.Destroy()
    schema.AddField(sourceField)

    // 向量字段(HNSW 索引,余弦相似度)
    embField := zvec.NewFieldSchema("embedding", zvec.DataTypeVectorFP32, false, dimension)
    defer embField.Destroy()
    hnswParams, _ := zvec.NewHNSWIndexParams(zvec.MetricTypeCosine, 16, 200)
    defer hnswParams.Destroy()
    embField.SetIndexParams(hnswParams)
    schema.AddField(embField)

    // 创建并打开集合
    collection, err := zvec.CreateAndOpen(path, schema, nil)
    if err != nil {
        _ = zvec.Shutdown()
        return nil, err
    }

    return &RAGCollection{
        collection: collection,
    }, nil
}

func (r *RAGCollection) Close() error {
    if r.collection != nil {
        if err := r.collection.Close(); err != nil {
            return err
        }
    }
    return zvec.Shutdown()
}

3. 文档索引(写入)

// Document 表示一个待索引的文档片段
type Document struct {
    ID      string
    Content string
    Source  string
}

// IndexDocuments 批量索引文档片段
func (r *RAGCollection) IndexDocuments(docs []Document, embedder EmbedFunc) error {
    zvecDocs := make([]*zvec.Doc, 0, len(docs))

    for _, doc := range docs {
        // 将文档内容向量化
        embedding, err := embedder(doc.Content)
        if err != nil {
            return fmt.Errorf("embed doc %s: %w", doc.ID, err)
        }

        // 构建 Zvec 文档
        zdoc := zvec.NewDoc()
        zdoc.SetPK(doc.ID)
        zdoc.AddStringField("doc_id", doc.ID)
        zdoc.AddStringField("content", doc.Content)
        zdoc.AddStringField("source", doc.Source)
        zdoc.AddVectorFP32Field("embedding", embedding)

        zvecDocs = append(zvecDocs, zdoc)
    }

    // 释放文档资源
    defer func() {
        for _, doc := range zvecDocs {
            doc.Destroy()
        }
    }()

    // 批量插入
    if _, err := r.collection.Insert(zvecDocs); err != nil {
        return err
    }

    // 刷新到磁盘
    return r.collection.Flush()
}

// EmbedFunc 向量化函数类型
type EmbedFunc func(text string) ([]float32, error)

4. 检索(查询)

// SearchResult 检索结果
type SearchResult struct {
    DocID   string
    Content string
    Source  string
    Score   float32
}

// Retrieve 检索与 query 最相关的 topK 个文档
func (r *RAGCollection) Retrieve(queryEmbedding []float32, topK int) ([]SearchResult, error) {
    query := zvec.NewSearchQuery()
    query.SetFieldName("embedding")
    query.SetQueryVector(queryEmbedding)
    query.SetTopK(topK)
    query.SetOutputFields([]string{"doc_id", "content", "source"})

    results, err := r.collection.Query(query)
    query.Destroy()
    if err != nil {
        return nil, err
    }
    defer zvec.FreeDocs(results)

    searchResults := make([]SearchResult, 0, len(results))
    for _, r := range results {
        sr := SearchResult{
            DocID: r.GetPK(),
            Score: r.GetScore(),
        }
        // 读取字段值(简化示意,实际需要根据 SDK API 获取字段)
        searchResults = append(searchResults, sr)
    }

    return searchResults, nil
}

5. 完整 RAG 管道

package main

import (
    "fmt"
    "log"
    "strings"

    rag "your-project/rag"
)

func main() {
    // 1. 创建向量集合
    collection, err := rag.NewRAGCollection("./rag_data", 1536)
    if err != nil {
        log.Fatal(err)
    }
    defer collection.Close()

    // 2. 准备文档(示例:知识库文档片段)
    docs := []rag.Document{
        {
            ID:      "doc_001",
            Content: "Zvec 是阿里巴巴开源的嵌入式向量数据库,支持 HNSW、IVF 等多种索引类型...",
            Source:  "zvec_readme.md",
        },
        {
            ID:      "doc_002",
            Content: "RAG 系统通过检索外部知识来增强 LLM 的生成能力,减少幻觉问题...",
            Source:  "rag_introduction.md",
        },
        // ... 更多文档
    }

    // 3. 索引文档
    embedder := createEmbedder() // 调用 OpenAI / 本地模型的向量化接口
    if err := collection.IndexDocuments(docs, embedder); err != nil {
        log.Fatal(err)
    }

    // 4. RAG 查询
    question := "Zvec 支持哪些索引类型?"
    qEmbedding, _ := embedder(question)
    results, _ := collection.Retrieve(qEmbedding, 5)

    // 5. 组装 Prompt 并调用 LLM
    context := buildContext(results)
    prompt := fmt.Sprintf(`基于以下参考资料回答问题。

参考资料:
%s

问题:%s

请用中文回答,并注明信息来源。`, context, question)

    answer, _ := callLLM(prompt)
    fmt.Println(answer)
}

func buildContext(results []rag.SearchResult) string {
    var parts []string
    for i, r := range results {
        parts = append(parts, fmt.Sprintf(
            "[%d] (来源: %s, 相关度: %.4f)\n%s",
            i+1, r.Source, r.Score, r.Content,
        ))
    }
    return strings.Join(parts, "\n\n")
}

Go 示例中的 createEmbeddercallLLM 需要按你实际使用的 embedding 模型和 LLM API 自行实现,不属于 Zvec SDK。


Rust 实战:构建 RAG 管道

1. 项目结构

rag-rust/
├── Cargo.toml
├── src/
│   ├── main.rs
│   ├── collection.rs    # Zvec 集合封装
│   ├── embedder.rs      # 向量化接口
│   ├── retriever.rs     # 检索器
│   └── generator.rs     # LLM 生成

2. Cargo.toml

[package]
name = "rag-rust"
version = "0.1.0"
edition = "2021"

[dependencies]
zvec = { git = "https://github.com/zvec-ai/zvec-rust.git", tag = "v0.5.0" }
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
anyhow = "1"

3. 定义集合与索引

use zvec::*;
use anyhow::Result;

pub struct RagCollection {
    collection: Collection,
}

/// 创建 RAG 用的向量集合
pub fn create_rag_collection(path: &str, dimension: u32) -> Result<RagCollection> {
    // 初始化引擎
    initialize(None)?;

    // 定义 Schema
    let schema = CollectionSchema::builder("rag_docs")
        // 文档 ID 字段
        .add_field(FieldSchema::new("doc_id", DataType::String, false, 0)?)
        // 文档内容字段
        .add_field(FieldSchema::new("content", DataType::String, false, 0)?)
        // 来源元数据
        .add_field(FieldSchema::new("source", DataType::String, true, 0)?)
        // 向量字段(HNSW 索引 + 余弦相似度)
        .add_vector_field(
            "embedding",
            DataType::VectorFp32,
            dimension,
            IndexParams::hnsw(MetricType::Cosine, 16, 200)?,
        )
        .build()?;

    // 创建并打开集合
    let collection = Collection::create_and_open(path, &schema, None)?;

    Ok(RagCollection { collection })
}

4. 文档索引

/// 文档片段
pub struct Document {
    pub id: String,
    pub content: String,
    pub source: String,
}

impl RagCollection {
    /// 批量索引文档
    pub fn index_documents(
        &self,
        docs: &[Document],
        embedder: &dyn Fn(&str) -> Result<Vec<f32>>,
    ) -> Result<()> {
        let mut zvec_docs = Vec::new();

        for doc in docs {
            let embedding = embedder(&doc.content)?;

            let mut zdoc = Doc::new()?;
            zdoc.set_pk(&doc.id);
            zdoc.add_string("doc_id", &doc.id)?;
            zdoc.add_string("content", &doc.content)?;
            zdoc.add_string("source", &doc.source)?;
            zdoc.add_vector_f32("embedding", &embedding)?;

            zvec_docs.push(zdoc);
        }

        // 批量插入(借用引用)
        let doc_refs: Vec<&Doc> = zvec_docs.iter().collect();
        self.collection.insert(&doc_refs)?;

        // 刷新到磁盘
        self.collection.flush()?;

        Ok(())
    }

    /// 检索最相关的文档
    pub fn retrieve(&self, query_embedding: &[f32], top_k: i32) -> Result<Vec<SearchResult>> {
        let query = SearchQuery::builder()
            .field_name("embedding")
            .vector(query_embedding)
            .topk(top_k)
            .output_fields(&["doc_id", "content", "source"])
            .build()?;

        let results = self.collection.query(&query)?;

        let search_results: Vec<SearchResult> = results
            .iter()
            .map(|r| SearchResult {
                doc_id: r.get_pk().unwrap_or_default().to_string(),
                score: r.get_score(),
                // 实际字段读取需根据 SDK API 获取
                content: String::new(),
                source: String::new(),
            })
            .collect();

        Ok(search_results)
    }
}

#[derive(Debug)]
pub struct SearchResult {
    pub doc_id: String,
    pub content: String,
    pub source: String,
    pub score: f32,
}

5. 完整 RAG 管道

use anyhow::Result;

mod collection;
mod embedder;

#[tokio::main]
async fn main() -> Result<()> {
    // 1. 创建向量集合
    let rag = collection::create_rag_collection("./rag_data", 1536)?;

    // 2. 准备文档
    let docs = vec![
        collection::Document {
            id: "doc_001".into(),
            content: "Zvec 是阿里巴巴开源的嵌入式向量数据库,支持 HNSW、IVF 等多种索引类型...".into(),
            source: "zvec_readme.md".into(),
        },
        collection::Document {
            id: "doc_002".into(),
            content: "RAG 系统通过检索外部知识来增强 LLM 的生成能力,减少幻觉问题...".into(),
            source: "rag_introduction.md".into(),
        },
    ];

    // 3. 索引文档
    let embedder = embedder::create_embedder();
    rag.index_documents(&docs, &embedder)?;

    // 4. RAG 查询
    let question = "Zvec 支持哪些索引类型?";
    let q_embedding = embedder(question)?;
    let results = rag.retrieve(&q_embedding, 5)?;

    // 5. 组装 Prompt 并调用 LLM
    let context: String = results
        .iter()
        .enumerate()
        .map(|(i, r)| {
            format!(
                "[{}] (来源: {}, 相关度: {:.4})\n{}",
                i + 1, r.source, r.score, r.content
            )
        })
        .collect::<Vec<_>>()
        .join("\n\n");

    let prompt = format!(
        "基于以下参考资料回答问题。\n\n参考资料:\n{}\n\n问题:{}\n\n请用中文回答,并注明信息来源。",
        context, question
    );

    let answer = call_llm(&prompt).await?;
    println!("{}", answer);

    Ok(())
}

Rust 示例中的 create_embeddercall_llm 同样需要按你实际使用的 embedding 模型和 LLM API 自行实现,不属于 Zvec SDK。

6. Rust 中的资源管理优势

Rust SDK 采用 RAII(资源获取即初始化)模式,所有 C 资源通过 Drop trait 自动释放:

{
    let doc = Doc::new()?;
    doc.set_pk("test");
    doc.add_vector_f32("embedding", &[0.1, 0.2, 0.3])?;
    // ... 使用 doc
} // <-- doc 在此处自动释放,无需手动 Destroy()

配合 Rust 的所有权系统,可以有效避免资源泄漏和悬垂指针问题,这在长时间运行的 RAG 服务中尤为重要。


混合检索:向量 + 全文搜索

Zvec v0.5.0 引入了原生全文检索(FTS)能力,可以在 RAG 系统中实现混合检索——同时利用语义相似度和关键词精确匹配,显著提升检索质量。

为什么需要混合检索?

查询类型 纯向量检索 纯关键词检索 混合检索
“什么是深度学习?” ✅ 语义匹配好 ⚠️ 关键词不精确 ✅✅
“error code 0x80070005” ⚠️ 语义相近但不精确 ✅ 精确匹配 ✅✅
“如何优化数据库查询性能” ✅ 语义好 ⚠️ 可能漏掉同义词 ✅✅

Go 中的混合检索

需要注意:在 zvec-go v0.5.0 中,FTS 查询通过 FTS 载荷挂到 SearchQuery.SetFTS 上;SubQuery 暴露的是向量/稀疏向量检索相关方法,并没有 SetMatchStringSetTopK。因此 Go 侧更稳妥的写法是先分别执行向量检索和全文检索,再在应用层做 RRF 或加权融合。

// 创建 FTS 索引参数
ftsParams, _ := zvec.NewFTSIndexParams("default", nil, "")
defer ftsParams.Destroy()
contentField := zvec.NewFieldSchema("content", zvec.DataTypeString, false, 0)
defer contentField.Destroy()
contentField.SetIndexParams(ftsParams)
schema.AddField(contentField)

// 第一路:向量检索
vectorQuery := zvec.NewSearchQuery()
defer vectorQuery.Destroy()
vectorQuery.SetFieldName("embedding")
vectorQuery.SetQueryVector(queryEmbedding)
vectorQuery.SetTopK(20)
vectorQuery.SetOutputFields([]string{"doc_id", "content", "source"})

vectorResults, err := collection.Query(vectorQuery)
if err != nil {
    return err
}
defer zvec.FreeDocs(vectorResults)

// 第二路:全文检索
ftsQuery := zvec.NewSearchQuery()
defer ftsQuery.Destroy()
ftsQuery.SetFieldName("content")
ftsQuery.SetQueryVector(queryEmbedding) // v0.5.0 官方示例仍会设置 query vector
ftsQuery.SetTopK(20)
ftsQuery.SetOutputFields([]string{"doc_id", "content", "source"})

fts := zvec.NewFTS()
fts.SetMatchString("Zvec 索引类型")
ftsQuery.SetFTS(fts)
fts.Destroy()

ftsResults, err := collection.Query(ftsQuery)
if err != nil {
    return err
}
defer zvec.FreeDocs(ftsResults)

// 应用层融合:按 doc_id 对 vectorResults 与 ftsResults 做 RRF 或加权合并
results := rrfFuse(vectorResults, ftsResults, 60)

Rust 中的混合检索

Rust SDK v0.5.0 的接口形态也类似:FTS 通过 SearchQueryBuilder::fts_match_stringFts 载荷挂到 SearchQuery 上;MultiQuery 当前面向多个向量/稀疏向量 SubQuery,不是下面这种 FTS 子查询 builder。

// 创建带 FTS 索引的 Schema
let schema = CollectionSchema::builder("rag_docs")
    .add_indexed_field(
        "content",
        DataType::String,
        IndexParams::fts(Some("default"), None, None)?,
    )
    .add_vector_field(
        "embedding",
        DataType::VectorFp32,
        1536,
        IndexParams::hnsw(MetricType::Cosine, 16, 200)?,
    )
    .build()?;

// 第一路:向量检索
let vector_query = SearchQuery::builder()
    .field_name("embedding")
    .vector(&query_embedding)
    .topk(20)
    .output_fields(&["doc_id", "content", "source"])
    .build()?;
let vector_results = collection.query(&vector_query)?;

// 第二路:全文检索
let fts_query = SearchQuery::builder()
    .field_name("content")
    .vector(&query_embedding)
    .topk(20)
    .output_fields(&["doc_id", "content", "source"])
    .fts_match_string("Zvec 索引类型")
    .build()?;
let fts_results = collection.query(&fts_query)?;

// 应用层融合:按 doc_id 对两路结果做 RRF 或加权合并
let results = rrf_fuse(&vector_results, &fts_results, 60);

这里的 rrfFuse / rrf_fuse 是应用层融合函数,需要按文档 ID 去重并按 RRF 分数重新排序。

融合策略说明

Zvec 支持两种融合策略:

  • RRF(Reciprocal Rank Fusion):基于排名的融合,适合大多数场景。rankConstant 通常设为 60。
  • Weighted(加权融合):为每个子查询分配权重,适合你明确知道各路检索重要性的场景。

性能优化建议

1. 索引类型选择

数据规模 推荐索引 说明
< 10 万条 Flat 暴力搜索,100% 准确率
10 万 ~ 1000 万 HNSW 图索引,速度与精度的最佳平衡
> 1000 万 HNSW + 量化 优先控制内存占用,并按实际数据分布压测
// HNSW + FP16 量化(内存减半,精度损失极小)
hnswParams, _ := zvec.NewHNSWIndexParams(zvec.MetricTypeCosine, 16, 200)
_ = hnswParams.SetQuantizeType(zvec.QuantizeTypeFP16)

2. 批量操作

// ❌ 逐条插入(慢)
for doc in docs {
    collection.insert(&[&doc])?;
}

// ✅ 批量插入(快)
let doc_refs: Vec<&Doc> = docs.iter().collect();
collection.insert(&doc_refs)?;

3. 文本切分策略

在 RAG 中,文档切分质量直接影响检索效果:

// 推荐切分参数
type SplitConfig struct {
    ChunkSize    int  // 每个片段的 token 数(建议 256-512)
    ChunkOverlap int  // 片段间的重叠 token 数(建议 50-100)
    SplitBy      string // 切分单位:"sentence" | "paragraph" | "token"
}

4. Top-K 与重排序

// 两阶段检索:先粗检索更多候选,再精排
coarseResults, _ := collection.Retrieve(queryEmbedding, 50)  // 粗检索 Top-50
fineResults := reranker.Rerank(question, coarseResults, 5)     // 精排取 Top-5

完整示例项目结构

Go 项目

rag-go/
├── go.mod
├── go.sum
├── main.go                  # 入口,编排 RAG 流程
├── config.go                # 配置管理
├── splitter/
│   ├── splitter.go          # 文本切分器
│   └── splitter_test.go
├── embedder/
│   ├── openai.go            # OpenAI Embedding API
│   ├── local.go             # 本地模型(如 ONNX Runtime)
│   └── embedder.go          # 接口定义
├── store/
│   └── zvec_store.go        # Zvec 向量存储封装
├── retriever/
│   └── retriever.go         # 检索器(支持混合检索)
├── generator/
│   ├── llm.go               # LLM 调用接口
│   ├── openai.go            # OpenAI 实现
│   └── prompt.go            # Prompt 模板
└── loader/
    ├── pdf.go               # PDF 加载器
    ├── markdown.go          # Markdown 加载器
    └── loader.go            # 接口定义

Rust 项目

rag-rust/
├── Cargo.toml
├── src/
│   ├── main.rs
│   ├── config.rs
│   ├── splitter/
│   │   ├── mod.rs
│   │   └── strategies.rs
│   ├── embedder/
│   │   ├── mod.rs
│   │   ├── openai.rs
│   │   └── local.rs
│   ├── store/
│   │   └── zvec_store.rs
│   ├── retriever/
│   │   └── mod.rs
│   ├── generator/
│   │   ├── mod.rs
│   │   ├── openai.rs
│   │   └── prompt.rs
│   └── loader/
│       ├── mod.rs
│       ├── pdf.rs
│       └── markdown.rs
└── tests/
    └── integration_test.rs

总结

Zvec 作为一款嵌入式向量数据库,为构建 RAG 系统提供了独特的优势:

  1. 零部署成本:无需独立的数据库服务,直接嵌入你的 Go/Rust 应用
  2. 极致性能:进程内调用,毫秒级检索延迟
  3. 混合检索:支持向量 + 全文检索,可通过两路检索和 RRF/加权融合提升 RAG 检索质量
  4. 资源模型清晰:进程内调用,集合关闭、Flush、SDK Shutdown 都可以在应用生命周期中显式管理
  5. 多语言支持:Go(cgo 绑定)和 Rust(FFI 绑定)SDK 均提供完整的类型安全 API

对于需要快速搭建、低运维成本的 RAG 系统,Zvec 是一个非常值得考虑的选择。


参考链接


本文基于 Zvec Go/Rust SDK v0.5.0 编写。