Help us shape the future of Go! Take the 2026 Go Developer Survey

rag

package module
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 23 Imported by: 0

README

rag

知识检索——向量化/混合召回/重排,向量后端可插拔 —— oagentkit 模块矩阵 tier 1(能力层,依赖 tier0)。

go get github.com/oagentkit/rag
包 职责
rag 知识检索:向量化接口(Embedder)、向量后端可插拔、混合召回与重排

定位

tier 1 — 能力层,依赖 tier0。

  • 本仓依赖的矩阵内仓:textx。

外部依赖地板

  • github.com/cloudwego/eino
  • github.com/milvus-io/milvus-sdk-go/v2

与 oekit 的关系

本矩阵(oagentkit,Agent/LLM 编排工具链)依赖 oekit(Open Easy Kit,Go 微服务工具链): oekit/pkg / oekit/concurrency / oekit/logx 等。oekit 是另一套独立矩阵,不是子品牌。

开发

go test ./... -race
go vet ./...
gofmt -l .

规范见 AGENTS.md。

License

MIT

  • 单路召回失败不得降级为 (nil, nil)。 混合召回中任一路 panic 或失败 要作为该路失败参与裁决;全部路失败时返回 panic 错误而非静默空结果。
  • 向量后端可插拔,新增后端不得改 Embedder/KnowledgeService 接口形状 —— 那会让所有后端同时 breaking。

Documentation

Overview

Package rag Embedding 接口定义与 OpenAI 兼容实现。

Hybrid 向量+关键词双路混合检索(R10,RRF 融合):语义路(MilvusStore,embedding 近邻)与词料路(Local,TF-IDF)各取候选,倒数排名融合(Reciprocal Rank Fusion)—— 跨路命中的文档得分累加(双路都认为相关=真相关的最强信号),单路独有的按名次计分。 降级哲学与装配侧一致:任一路失败降级为另一路纯检索(检索面永不因一路缺失禁用), 双路全败才回错。

Package rag Milvus 向量检索后端。 使用 Milvus Go SDK v2 实现 KnowledgeService 接口, 支持向量相似度检索(余弦相似度 / L2 距离)。

Package rag 知识检索服务。 提供两种后端:Local(本地 TF-IDF)和 MilvusStore(向量数据库)。 检索算法 = 词元重叠打分(ASCII 词 + CJK 二元组)或向量相似度, 零外部向量库依赖(Local)或 Milvus 向量数据库(MilvusStore)。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewSearchTool

func NewSearchTool(svc KnowledgeService) tool.BaseTool

NewSearchTool 构建 search_knowledge eino 工具(v0.14.1 导出缝):消费方包装 KnowledgeService 后须重建工具面——包装层 AsTool 直透内层会把工具调用绕过包装 检索语义(bianque 知识组去重包装实需)。schema/文案与 buildAsTool 单源。

Types

type Chunk

type Chunk struct {
	ID       string
	Content  string
	Score    float64
	Metadata map[string]string
}

Chunk 检索片段。

func ChunkPreview

func ChunkPreview(content string) []Chunk

ChunkPreview 切块只读预览(v0.14.2):与索引侧 chunkMarkdown 同一状态机——消费方 (bianque 知识文档管理面,对标 Dify/RAGFlow 分段预览)展示「这篇会切成几块、每块什么 内容」,预览与实际索引不分叉。返回块内容与所属标题(Metadata["heading"],无标题块为空)。

func FuseRRF

func FuseRRF(topK int, lists ...[]Chunk) []Chunk

FuseRRF 倒数排名融合:score=Σ 1/(k+rank_i)(rank 从 1 起),同 ID 跨路累加 (双路共识加权=混合检索的本意);输出按得分降序、同分按 ID 字典序(确定性可重放), 截 topK。lists 为空返回空。

type Embedder

type Embedder interface {
	// Embed 将文本切片转为向量切片,返回的向量维度应一致。
	Embed(ctx context.Context, texts []string) ([][]float32, error)
	// Dim 返回向量维度。
	Dim() int
}

Embedder 文本向量化接口。

type Filter

type Filter map[string]string

Filter 检索过滤条件(如 repo、规范文档名)。

type Hybrid

type Hybrid struct {
	// contains filtered or unexported fields
}

Hybrid 组合检索器:vector=语义路(必选),keyword=词料路(Local 的 TF-IDF 索引, 纯内存随目录重建)。

func NewHybrid

func NewHybrid(vector KnowledgeService, keyword *Local) *Hybrid

NewHybrid 构造混合检索器。

func (*Hybrid) AsTool

func (h *Hybrid) AsTool() tool.BaseTool

AsTool 工具化透传语义路(检索语义对 LLM 不可见——混合是检索器内部实现细节)。

func (*Hybrid) Retrieve

func (h *Hybrid) Retrieve(ctx context.Context, query string, topK int, filter Filter) ([]Chunk, error)

Retrieve 双路并行检索 → RRF 融合 → topK。两路各取 topK*2 候选(融合后截断, 候选池放大让跨路重叠有归并空间);单路失败降级单路,双路全败回 first error。 双路经 syncx.FanInErr 收口(concurrency v0.5.0 起 Slot 三态):路内 panic 不再 伪装成空路,而是作为该路失败参与降级裁决——单路 panic 降级另一路,双路全败 (含 panic)回错不再静默返回空结果;恐慌经全局 handler 上报,不出宿主进程。

type KnowledgeService

type KnowledgeService interface {
	Retrieve(ctx context.Context, query string, topK int, filter Filter) ([]Chunk, error)
	AsTool() tool.BaseTool
}

KnowledgeService 知识检索服务接口。 模式一:预检索(确定性)—— workflow 阶段在拼 prompt 前取 topK 片段。 模式二:工具化(自主)—— 包成 search_knowledge(query) 挂进 ReAct agent。

type Local

type Local struct {
	// contains filtered or unexported fields
}

Local 本地文件知识库(启动扫描 + 过期重扫)。

func NewLocal

func NewLocal(dir string) (*Local, error)

NewLocal 构造并立即扫描。dir 不存在时返回错误。

func (*Local) AsTool

func (l *Local) AsTool() tool.BaseTool

AsTool 把检索包成 search_knowledge 工具。

func (*Local) Rescan

func (l *Local) Rescan()

Rescan 强制重新扫描知识库目录(不等待自动过期)。 根目录不可达(卷卸载/被删)时保留旧索引并告警——静默换入空索引会让 知识库"消失"且无任何信号。

func (*Local) Retrieve

func (l *Local) Retrieve(ctx context.Context, query string, topK int, filter Filter) ([]Chunk, error)

Retrieve 检索 topK 片段。 重扫在锁外进行(构建新索引后原子换入)——并发检索不被文件 I/O 阻塞; 多 goroutine 同时判过期时重扫收敛为单份(scanning 标志让位,换入后对 所有人可见;此前并发各扫一遍,大目录下内存峰值按并发数放大)。

type MilvusConfig

type MilvusConfig struct {
	Address    string            // Milvus 地址,如 "localhost:19530"
	Collection string            // 集合名,默认 "agentkit_knowledge"
	Dimension  int               // 向量维度(需与 Embedder.Dim() 一致)
	MetricType entity.MetricType // 距离度量,默认 COSINE
	NProbe     int               // 搜索时的 nprobe,默认 16
}

MilvusConfig Milvus 连接配置。

type MilvusStore

type MilvusStore struct {
	// contains filtered or unexported fields
}

MilvusStore Milvus 向量检索后端。

func NewMilvusStore

func NewMilvusStore(ctx context.Context, cfg MilvusConfig, embedder Embedder) (*MilvusStore, error)

NewMilvusStore 创建 Milvus 向量检索后端。

func (*MilvusStore) AsTool

func (s *MilvusStore) AsTool() tool.BaseTool

AsTool 实现 KnowledgeService 接口。

func (*MilvusStore) Close

func (s *MilvusStore) Close() error

Close 关闭 Milvus 连接。

func (*MilvusStore) DeleteFile

func (s *MilvusStore) DeleteFile(ctx context.Context, file string) error

DeleteFile 删除指定文件的所有索引数据。

func (*MilvusStore) Flush

func (s *MilvusStore) Flush(ctx context.Context) error

Flush 持久化本集合全部未落盘写入(批量写入收尾点)。

func (*MilvusStore) Index

func (s *MilvusStore) Index(ctx context.Context, file string, content string) error

Index 将文档分块并索引到 Milvus(单文件写=embed→delete→upsert→flush)。 批量写入请用 IndexQuiet+收尾 Flush——per-file Flush 实测 ~20s/文件(对象存储 落盘 RPC 主导,向量计算亚秒),千级文件会把全量重索引拖成小时级(2026-10-08 bianque 对拍实弹)。 幂等:成功路径上先清该文件旧数据再写入——文件变短(删章节/内容精简)时 chunk 数变少,只 Upsert 新块会残留 chunk_M..N-1 旧行携带过期内容参与检索 挤占 topK(与 Local.Rescan 的全量重建同语义)。 顺序:chunk → Embed 成功 → Delete → Upsert。Embed 是外部网络调用(抖动/ 限流/超时是常规事件),先删后嵌会把旧索引一并清掉;倒序后最常见的失败 (embedding)不再动旧数据。残余窗口:Delete 成功而 Upsert/Flush 失败时旧 数据已删新数据未写(该文件暂时从检索面消失,直到下次 Index 重建)—— 该窗口远小于原形态且失败以错误上抛,调用方可重试。

func (*MilvusStore) IndexQuiet

func (s *MilvusStore) IndexQuiet(ctx context.Context, file string, content string) error

IndexQuiet 单文件写入但不 Flush(批量收尾点由调用方 Flush 一次)。数据在 flush 前已可检索(growing segments),Flush 语义=持久化到 sealed segments—— 调用方须保证批次终态调 Flush,否则进程崩溃窗内未 flush 写入丢失(重跑幂等)。

func (*MilvusStore) Retrieve

func (s *MilvusStore) Retrieve(ctx context.Context, query string, topK int, filter Filter) ([]Chunk, error)

Retrieve 实现 KnowledgeService 接口:向量相似度检索。

type Noop

type Noop struct{}

Noop 空实现:Retrieve 返回空、AsTool 返回 nil。

func NewNoop

func NewNoop() *Noop

NewNoop 创建空实现。

func (*Noop) AsTool

func (n *Noop) AsTool() tool.BaseTool

func (*Noop) Retrieve

func (n *Noop) Retrieve(_ context.Context, _ string, _ int, _ Filter) ([]Chunk, error)

type OpenAIEmbedder

type OpenAIEmbedder struct {
	BaseURL string // 如 https://api.openai.com/v1 或 https://dashscope.aliyuncs.com/compatible-mode/v1
	APIKey  string
	Model   string // 如 text-embedding-3-small / text-embedding-v3
	// contains filtered or unexported fields
}

OpenAIEmbedder OpenAI 兼容 Embedding API 适配器。 支持 OpenAI / 百炼 / 任何兼容 /v1/embeddings 端点。

func NewOpenAIEmbedder

func NewOpenAIEmbedder(baseURL, apiKey, model string, dim int) *OpenAIEmbedder

NewOpenAIEmbedder 创建 OpenAI 兼容 Embedding 客户端。

func (*OpenAIEmbedder) Dim

func (e *OpenAIEmbedder) Dim() int

Dim 返回向量维度。

func (*OpenAIEmbedder) Embed

func (e *OpenAIEmbedder) Embed(ctx context.Context, texts []string) ([][]float32, error)

Embed 将文本切片转为向量切片。

func (*OpenAIEmbedder) String

func (e *OpenAIEmbedder) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL