Files
xk-ai-agent/internal/kb/embedder.go
2026-08-14 21:50:48 +08:00

104 lines
3.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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()
}
}