package kb import "context" // ======================================================================== // Embedder 接口(V2 预留) // ======================================================================== // V1 只实现 NoopEmbedder(默认),不调任何向量化服务 // // V2 接入 BGE-M3 / 阿里 / OpenAI 时只需: // 1. 新增文件 embedder_bge.go 实现 Embedder 接口 // 2. 在 NewEmbedder 工厂函数里加 case // 3. 业务代码(Searcher / Importer)零改动 // ======================================================================== // Embedder 向量化接口 // // 各实现的差异主要在: // - Name():返回 provider 标识(noop/bge_m3/aliyun/openai) // - Embed():批量把文本转成向量(V1 noop 直接返回 nil) // - Dim():向量维度(V1 noop 返回 0) // - Available():是否能用(V1 noop 返回 false) type Embedder interface { // Name 返回 provider 名(用于日志/前端展示) Name() string // Embed 批量向量化 // // 入参:texts 一段或多段文本 // 出参:与 texts 等长的向量数组;每个向量是 []float32(维度由实现决定) // V1 NoopEmbedder 返回 nil, nil(不报错,调用方判断 Available() 后再调用) Embed(ctx context.Context, texts []string) ([][]float32, error) // Dim 返回向量维度 // NoopEmbedder 返回 0 // BGE-M3 返回 1024,阿里 text-embedding-v3 返回 1024 Dim() int // Available 是否可用 // NoopEmbedder 返回 false(明确告知调用方"我不做向量化") // 真实 provider 返回 true Available() bool } // ======================================================================== // NoopEmbedder —— V1 默认实现(不做任何向量化) // ======================================================================== // NoopEmbedder 空实现,所有方法返回零值 // // 设计意图: // - 让 V1 的 Importer/Searcher 代码结构里就有 Embedder 接口位置 // - 通过判断 Available() 自动跳过向量化逻辑 // - V2 替换为真实 Embedder 时无需改业务代码 type NoopEmbedder struct{} // NewNoopEmbedder 构造 func NewNoopEmbedder() *NoopEmbedder { return &NoopEmbedder{} } // Name 返回 provider 名 func (n *NoopEmbedder) Name() string { return "noop" } // Embed 不做向量化,直接返回 nil func (n *NoopEmbedder) Embed(ctx context.Context, texts []string) ([][]float32, error) { return nil, nil } // Dim 返回 0(noop 没有维度) func (n *NoopEmbedder) Dim() int { return 0 } // Available 返回 false(明确告知调用方不要依赖我) func (n *NoopEmbedder) Available() bool { return false } // ======================================================================== // Embedder 工厂(V1 只支持 noop;V2 扩展) // ======================================================================== // NewEmbedder 根据 provider 名构造对应的 Embedder // // 参数: // - provider:从 xk_system_config.ai_kb_embedding_provider 读到的值 // - apiKey:从 xk_system_config.ai_kb_embedding_api_key 读到的值(V1 noop 不用) // // 返回: // V1 默认走 noop 分支 // V2 新增 bge_m3/aliyun/openai 时在这里加 case // 未知 provider 也回落到 noop(不阻断业务) func NewEmbedder(provider, apiKey string) Embedder { switch provider { case "noop", "": return NewNoopEmbedder() // V2 预留: // case "bge_m3": // return NewBGEM3Embedder(apiKey) // case "aliyun": // return NewAliyunEmbedder(apiKey) // case "openai": // return NewOpenAIEmbedder(apiKey) default: // 未知 provider 回落到 noop(保证可用性) return NewNoopEmbedder() } }