Embedding词向量技术详解
2026年4月16日 · 589 字 · 3 分钟
什么是Embedding词向量技术,以及如何使用eino框架实现文本向量化 Embedding(嵌入)是自然语言处理中的核心技术,它将文本转换为高维向量表示。简单来说,就是把人类可读的文字转换成计算机能够理解和计算的一串数字。 每个词或句子都会被映射到一个高维向量空间中。例如: 在向量空间中,语义相近的词语距离更近。这是Embedding最神奇的地方: Eino是字节跳动开源的Golang AI应用开发框架,提供了丰富的组件支持。我们使用其 首先需要一个配置文件 这里使用Ollama本地部署的 归一化是将向量缩放到单位长度,这样计算相似度时更方便: 归一化后,向量的模长为1,此时向量的内积等于余弦相似度。 内积是最常用的相似度计算方法,值越大表示越相似。 当需要表示一段包含多个词的文本时,可以用这些词向量的平均值: 让我们看一个完整的词向量相似度计算示例:什么是Embedding词向量技术
核心概念
向量化
"大连理工大学" → [0.123, -0.456, 0.789, ...] // 768维或更高
"中国海洋大学" → [0.234, -0.345, 0.678, ...]
语义相似度
应用场景
使用Eino框架实现Embedding
eino-ext中的Ollama Embedding组件。安装依赖
go get github.com/cloudwego/eino-ext/components/embedding/ollama
配置说明
config.json:{
"embedding_api_url": "http://localhost:11434",
"embedding_model": "nomic-embed-text"
}
nomic-embed-text模型,你也可以替换成其他Embedding模型。代码实现
初始化Embedder
package rag
import (
"context"
"eino_study/config"
"fmt"
"log"
"math"
"github.com/cloudwego/eino-ext/components/embedding/ollama"
)
var Embeddder *ollama.Embedder
func NewEmbedder() *ollama.Embedder {
ctx := context.Background()
var err error
config := config.NewConfig("../config/config.json")
Embeddder, err = ollama.NewEmbedder(ctx, &ollama.EmbeddingConfig{
BaseURL: config.EmbeddingAPIURL,
Model: config.EmbeddingModel,
})
if err != nil {
log.Fatalf("NewEmbedder failed, err=%v", err)
}
return Embeddder
}
ollama.NewEmbedder创建了一个Embedding客户端,配置了API地址和模型名称。文本向量化
func Embedding(ctx context.Context, text []string) ([][]float64, error) {
embedder := NewEmbedder()
embeddings, err := embedder.EmbedStrings(ctx, text)
if err != nil {
log.Fatalf("EmbedStrings failed, err=%v", err)
}
// 归一化处理
for i, v := range embeddings {
embeddings[i] = NormalizeVector(v)
}
return embeddings, nil
}
EmbedStrings方法将字符串数组转换为向量数组。返回的是一个二维切片[][]float64,每个字符串对应一个向量。向量归一化
func NormalizeVector(v []float64) []float64 {
if len(v) == 0 {
return nil
}
// 计算向量的模长
a := 0.
for _, x := range v {
a += x * x
}
a = math.Sqrt(a)
// 归一化向量
for i := range v {
v[i] /= a
}
return v
}
计算相似度
// 计算向量内积
// 如果向量已经归一化,那么内积的结果就是向量之间的夹角余弦值
func DotProduct(v1, v2 []float64) float64 {
if len(v1) != len(v2) {
return 0.
}
a := 0.
for i := range v1 {
a += v1[i] * v2[i]
}
return a
}
文档向量化
// 多个向量按位求平均
func AvgOfVector(vectors [][]float64) ([]float64, error) {
if len(vectors) == 0 {
return nil, nil
}
if len(vectors) == 1 {
return NormalizeVector(vectors[0]), nil
}
sum := make([]float64, len(vectors[0]))
for i := 0; i < len(vectors); i++ {
if len(vectors[i]) != len(sum) {
return nil, fmt.Errorf("%dth vector dim not equal to first vector", i+1)
}
for index, v := range vectors[i] {
sum[index] += v
}
}
for i := range sum {
sum[i] /= float64(len(vectors))
}
return NormalizeVector(sum), nil
}
完整示例
func WordSim() {
// 定义待比较的词语
words := []string{"大连理工大学", "中国海洋大学", "大连", "青岛"}
ctx := context.Background()
// 获取向量
embeddings, err := Embedding(ctx, words)
if err != nil {
log.Fatal(err)
}
// 计算两两之间的相似度
for i := 0; i < len(words); i++ {
for j := i + 1; j < len(words); j++ {
dot := DotProduct(embeddings[i], embeddings[j])
fmt.Printf("sim of %s and %s is %.4f\n", words[i], words[j], dot)
}
}
// 文档向量化示例
// doc1: 大学相关文档
doc1, _ := AvgOfVector([][]float64{embeddings[0], embeddings[1]})
// doc2: 城市相关文档
doc2, _ := AvgOfVector([][]float64{embeddings[2], embeddings[3]})
// 测试新词与文档的相似度
words = []string{"中国计量大学", "杭州"}
vectors, _ := Embedding(ctx, words)
for i, vector := range vectors {
dot := DotProduct(vector, doc1)
fmt.Printf("sim of word %s and doc1 is %.4f\n", words[i], dot)
dot = DotProduct(vector, doc2)
fmt.Printf("sim of word %s and doc2 is %.4f\n", words[i], dot)
}
}
运行结果
=== RUN TestEmbedding
sim of 大连理工大学 and 中国海洋大学 is 0.8183
sim of 大连理工大学 and 大连 is 0.8241
sim of 大连理工大学 and 青岛 is 0.5443
sim of 中国海洋大学 and 大连 is 0.6569
sim of 中国海洋大学 and 青岛 is 0.5597
sim of 大连 and 青岛 is 0.5946
sim of word 中国计量大学 and doc1 is 0.9411
sim of word 中国计量大学 and doc2 is 0.6970
sim of word 杭州 and doc1 is 0.5964
sim of word 杭州 and doc2 is 0.6367
--- PASS: TestEmbedding (0.67s)
PASS
结果分析
词语相似度
词语对
相似度
解释
大连理工大学 vs 中国海洋大学
0.8183
两所大学,语义非常相近
大连理工大学 vs 大连
0.8241
大学位于大连,关联性强
中国海洋大学 vs 大连
0.6569
大学与城市的中等相关性
大连 vs 青岛
0.5946
两个城市,有一定相似度
大连理工大学 vs 青岛
0.5443
大学与城市,关联较弱
文档相似度
测试词
doc1(大学文档)
doc2(城市文档)
中国计量大学
0.9411
0.6970
杭州
0.5964
0.6367