mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-23 02:18:06 +00:00
与 internal/memory/clip 同模式:`//go:build onnxruntime` 编真实实现,无标签时 走 stub,默认构建不链接 onnxruntime、行为不变。 加载契约(目录由 core.memory.multimodal_space.model_dir 指定): TextTower.onnx + 外部权重分片、tokenizer.json、embed_config.json。 图内已含 last-token 池化,输出即 [batch, dim];L2 归一化在 Go 侧做。 两个刻意的设计选择: 1. **EmbedImageDense 明确报错,不返回零向量** 导出的是文本塔,视觉塔未导出。返回零向量会让「写入了但检索不到」, 把跨模态检索失效变成静默故障;明确报错则调用方(mediaref.go)log 后 跳过写向量,文本路径不受影响。 2. **Fingerprint 只哈希图文件 + 配置 + 外部权重的文件名与大小** 该目录有 6.5GB 权重分片,启动时全读一遍要几十秒、会阻塞 homeagent 启动。 换模型必然改变文件集合或大小,足以识别切换;代价是理论上存在 「大小相同但内容不同」的漏判,对本地单机部署可接受。已写入注释。 模板渲染(renderInstructionInput)放在无构建标签的 tokenizer.go,因此可被 测试覆盖:参考数据里有该模板串的用例,逐 token 对齐验证——模板差一个字符, 池化取到的「最后一个有效 token」位置就变,向量就不同,且不会报错。 验证:6 个测试全绿;go build ./...(stub)与 go build -tags onnxruntime (真实实现)均通过。
29 lines
889 B
Go
29 lines
889 B
Go
//go:build !onnxruntime
|
||
|
||
package qwen
|
||
|
||
import "fmt"
|
||
|
||
// Embedder 在未启用 onnxruntime 时为 no-op 实现(与 internal/memory/clip 同模式)。
|
||
// 默认构建不链接 onnxruntime,保持原有 fastText/TF-IDF 行为不变。
|
||
type Embedder struct {
|
||
loaded bool
|
||
}
|
||
|
||
func New(_ string) (*Embedder, error) {
|
||
return nil, fmt.Errorf("qwen embedder requires build tag 'onnxruntime' (go build -tags onnxruntime)")
|
||
}
|
||
|
||
func (e *Embedder) Fingerprint() string { return "" }
|
||
func (e *Embedder) Dim() int { return 0 }
|
||
func (e *Embedder) Loaded() bool { return e.loaded }
|
||
func (e *Embedder) Close() {}
|
||
|
||
func (e *Embedder) VectorizeDense(_ string) ([]float64, error) {
|
||
return nil, fmt.Errorf("qwen embedder not available")
|
||
}
|
||
|
||
func (e *Embedder) EmbedImageDense(_ []byte, _ string) ([]float64, error) {
|
||
return nil, fmt.Errorf("qwen embedder not available")
|
||
}
|