Embedding 向量化
约 593 字大约 2 分钟
布欧-Lewyon
2026-05-15
首页 › Spring AI › 多模态与 Embedding
什么是 Embedding
Embedding(嵌入/向量化)是将文本转换为浮点数向量的过程,使得语义相近的文本在向量空间中的距离更近。
EmbeddingClient
@Service
public class EmbeddingService {
private final EmbeddingClient embeddingClient;
public EmbeddingService(EmbeddingClient embeddingClient) {
this.embeddingClient = embeddingClient;
}
// 单文本向量化
public float[] embed(String text) {
return embeddingClient.embed(text);
}
// 批量向量化
public List<float[]> embedBatch(List<String> texts) {
List<List<Double>> embeddings = embeddingClient.embed(texts);
return embeddings.stream()
.map(this::toFloatArray)
.toList();
}
// 文档对象向量化
public float[] embedDocument(Document doc) {
return embeddingClient.embed(doc);
}
private float[] toFloatArray(List<Double> doubles) {
float[] result = new float[doubles.size()];
for (int i = 0; i < doubles.size(); i++) {
result[i] = doubles.get(i).floatValue();
}
return result;
}
}Embedding 配置
OpenAI
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
embedding:
options:
model: text-embedding-ada-002 # 1536 维Ollama(本地)
spring:
ai:
ollama:
base-url: http://localhost:11434
embedding:
options:
model: nomic-embed-text # 本地向量模型# 拉取本地 Embedding 模型
ollama pull nomic-embed-text相似度计算
@Component
public class SimilarityCalculator {
// 余弦相似度(0~1,1 表示完全相同)
public double cosineSimilarity(float[] vectorA, float[] vectorB) {
double dotProduct = 0;
double normA = 0;
double normB = 0;
for (int i = 0; i < vectorA.length; i++) {
dotProduct += vectorA[i] * vectorB[i];
normA += Math.pow(vectorA[i], 2);
normB += Math.pow(vectorB[i], 2);
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
// 文本语义相似度
public double textSimilarity(String textA, String textB) {
float[] vecA = embeddingService.embed(textA);
float[] vecB = embeddingService.embed(textB);
return cosineSimilarity(vecA, vecB);
}
}文档相似度搜索
@Service
public class SemanticSearchService {
private final EmbeddingClient embeddingClient;
private final List<Document> documents = new ArrayList<>();
// 添加文档
public void addDocument(String id, String text, Map<String, Object> metadata) {
float[] embedding = embeddingClient.embed(text);
documents.add(new Document(id, text, metadata, embedding));
}
// 语义搜索
public List<ScoredDocument> search(String query, int topK) {
float[] queryEmbedding = embeddingClient.embed(query);
return documents.stream()
.map(doc -> new ScoredDocument(
doc, cosineSimilarity(queryEmbedding, doc.embedding())))
.sorted((a, b) -> Double.compare(b.score(), a.score()))
.limit(topK)
.toList();
}
record Document(String id, String text, Map<String, Object> metadata, float[] embedding) {}
record ScoredDocument(Document document, double score) {}
}小结
- Embedding 将文本转为浮点数向量,语义相近的文本向量距离近。
EmbeddingClient提供embed(String)和embed(List<String>)接口。- OpenAI 用
text-embedding-ada-002(1536 维),Ollama 用nomic-embed-text。 - 余弦相似度衡量向量之间的语义相似度(0~1)。
- 嵌入(Embedding)是构建 RAG 和语义搜索的基础。
- 本地开发推荐 Ollama +
nomic-embed-text,生产推荐 OpenAI。
上一节:图像理解 下一节:VectorStore 与 PGVector
