Appearance
向量存储
嵌入模型选择
嵌入模型用于将文本转换为向量表示。LangChain 4J 支持多种嵌入模型:
OpenAI 嵌入模型
java
import dev.langchain4j.embedding.openai.OpenAiEmbeddingModel;
import dev.langchain4j.embedding.EmbeddingModel;
// 创建 OpenAI 嵌入模型
EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("text-embedding-ada-002")
.build();
// 生成嵌入
List<Double> embedding = embeddingModel.embed("这是一段文本");
System.out.println("嵌入向量维度:" + embedding.size());Hugging Face 嵌入模型
java
import dev.langchain4j.embedding.huggingface.HuggingFaceEmbeddingModel;
// 创建 Hugging Face 嵌入模型
EmbeddingModel embeddingModel = HuggingFaceEmbeddingModel.builder()
.accessToken(System.getenv("HUGGING_FACE_ACCESS_TOKEN"))
.modelId("sentence-transformers/all-MiniLM-L6-v2")
.build();
// 生成嵌入
List<Double> embedding = embeddingModel.embed("这是一段文本");
System.out.println("嵌入向量维度:" + embedding.size());本地嵌入模型
java
import dev.langchain4j.embedding.local.LocalEmbeddingModel;
// 创建本地嵌入模型
EmbeddingModel embeddingModel = LocalEmbeddingModel.builder()
.modelPath("path/to/model")
.build();
// 生成嵌入
List<Double> embedding = embeddingModel.embed("这是一段文本");
System.out.println("嵌入向量维度:" + embedding.size());向量数据库集成
LangChain 4J 支持多种向量数据库:
Chroma 集成
java
import dev.langchain4j.store.embedding.chroma.ChromaEmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStore;
// 创建 Chroma 嵌入存储
EmbeddingStore embeddingStore = ChromaEmbeddingStore.builder()
.baseUrl("http://localhost:8000")
.collectionName("documents")
.build();Pinecone 集成
java
import dev.langchain4j.store.embedding.pinecone.PineconeEmbeddingStore;
// 创建 Pinecone 嵌入存储
EmbeddingStore embeddingStore = PineconeEmbeddingStore.builder()
.apiKey(System.getenv("PINECONE_API_KEY"))
.environment("gcp-starter")
.indexName("documents")
.build();Milvus 集成
java
import dev.langchain4j.store.embedding.milvus.MilvusEmbeddingStore;
// 创建 Milvus 嵌入存储
EmbeddingStore embeddingStore = MilvusEmbeddingStore.builder()
.host("localhost")
.port(19530)
.collectionName("documents")
.build();FAISS 集成
java
import dev.langchain4j.store.embedding.faiss.FaissEmbeddingStore;
// 创建 FAISS 嵌入存储
EmbeddingStore embeddingStore = FaissEmbeddingStore.builder()
.indexPath("path/to/index")
.build();相似度搜索
基本搜索
java
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingMatch;
// 添加文档到存储
embeddingStore.add("文档1内容", "文档1");
embeddingStore.add("文档2内容", "文档2");
embeddingStore.add("文档3内容", "文档3");
// 搜索相似文档
List<EmbeddingMatch> matches = embeddingStore.findRelevant("查询文本", 3);
for (EmbeddingMatch match : matches) {
System.out.println("相似度:" + match.score());
System.out.println("文档内容:" + match.embedded().text());
}高级搜索
java
// 高级搜索配置
List<EmbeddingMatch> matches = embeddingStore.findRelevant(
"查询文本",
3, // 返回的结果数量
0.7 // 相似度阈值
);检索增强生成 (RAG)
基本 RAG
java
import dev.langchain4j.retriever.EmbeddingStoreRetriever;
import dev.langchain4j.chain.rag.RetrievalAugmentedGenerationChain;
import dev.langchain4j.model.openai.OpenAiChatModel;
// 创建检索器
EmbeddingStoreRetriever retriever = EmbeddingStoreRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(3)
.minScore(0.7)
.build();
// 创建模型
OpenAiChatModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// 创建 RAG 链
RetrievalAugmentedGenerationChain ragChain = RetrievalAugmentedGenerationChain.builder()
.retriever(retriever)
.model(model)
.build();
// 执行 RAG
String response = ragChain.run("查询问题");
System.out.println("RAG 响应:" + response);高级 RAG
java
// 高级 RAG 配置
RetrievalAugmentedGenerationChain ragChain = RetrievalAugmentedGenerationChain.builder()
.retriever(retriever)
.model(model)
.promptTemplate(PromptTemplate.from("根据以下信息回答问题:\n{information}\n\n问题:{question}"))
.build();
// 执行 RAG
String response = ragChain.run("查询问题");
System.out.println("RAG 响应:" + response);自定义向量存储
您可以通过实现 EmbeddingStore 接口来创建自定义向量存储:
基本自定义存储
java
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.data.segment.TextSegment;
public class CustomEmbeddingStore implements EmbeddingStore {
private final Map<String, List<Double>> embeddings = new HashMap<>();
private final Map<String, String> texts = new HashMap<>();
@Override
public void add(String text, String id) {
// 生成嵌入并存储
List<Double> embedding = generateEmbedding(text);
embeddings.put(id, embedding);
texts.put(id, text);
}
@Override
public List<EmbeddingMatch> findRelevant(String text, int maxResults) {
// 生成查询嵌入
List<Double> queryEmbedding = generateEmbedding(text);
// 计算相似度
List<EmbeddingMatch> matches = new ArrayList<>();
for (Map.Entry<String, List<Double>> entry : embeddings.entrySet()) {
double similarity = calculateSimilarity(queryEmbedding, entry.getValue());
TextSegment segment = TextSegment.from(texts.get(entry.getKey()));
EmbeddingMatch match = EmbeddingMatch.from(similarity, segment);
matches.add(match);
}
// 按相似度排序并返回
matches.sort(Comparator.comparing(EmbeddingMatch::score).reversed());
return matches.stream().limit(maxResults).collect(Collectors.toList());
}
private List<Double> generateEmbedding(String text) {
// 实现嵌入生成逻辑
return new ArrayList<>();
}
private double calculateSimilarity(List<Double> embedding1, List<Double> embedding2) {
// 实现相似度计算逻辑
return 0.0;
}
}高级自定义存储
java
public class DatabaseEmbeddingStore implements EmbeddingStore {
private final DataSource dataSource;
public DatabaseEmbeddingStore(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void add(String text, String id) {
// 存储到数据库
try (Connection conn = dataSource.getConnection()) {
String sql = "INSERT INTO embeddings (id, text, embedding) VALUES (?, ?, ?)";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, id);
stmt.setString(2, text);
stmt.setString(3, embeddingToString(generateEmbedding(text)));
stmt.executeUpdate();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public List<EmbeddingMatch> findRelevant(String text, int maxResults) {
// 从数据库查询并计算相似度
List<EmbeddingMatch> matches = new ArrayList<>();
List<Double> queryEmbedding = generateEmbedding(text);
try (Connection conn = dataSource.getConnection()) {
String sql = "SELECT id, text, embedding FROM embeddings";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
String id = rs.getString("id");
String storedText = rs.getString("text");
List<Double> storedEmbedding = stringToEmbedding(rs.getString("embedding"));
double similarity = calculateSimilarity(queryEmbedding, storedEmbedding);
TextSegment segment = TextSegment.from(storedText);
EmbeddingMatch match = EmbeddingMatch.from(similarity, segment);
matches.add(match);
}
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
matches.sort(Comparator.comparing(EmbeddingMatch::score).reversed());
return matches.stream().limit(maxResults).collect(Collectors.toList());
}
private List<Double> generateEmbedding(String text) {
// 实现嵌入生成逻辑
return new ArrayList<>();
}
private double calculateSimilarity(List<Double> embedding1, List<Double> embedding2) {
// 实现相似度计算逻辑
return 0.0;
}
private String embeddingToString(List<Double> embedding) {
// 实现嵌入转字符串逻辑
return "";
}
private List<Double> stringToEmbedding(String embeddingString) {
// 实现字符串转嵌入逻辑
return new ArrayList<>();
}
}最佳实践
选择合适的嵌入模型:
- 考虑模型的性能和准确性
- 对于特定领域,使用领域特定的嵌入模型
- 平衡模型大小和性能
选择合适的向量数据库:
- 根据数据规模选择合适的数据库
- 考虑部署环境和成本
- 评估数据库的查询性能
优化嵌入存储:
- 批量添加文档以提高性能
- 定期优化索引
- 监控存储使用情况
优化相似度搜索:
- 设置合理的相似度阈值
- 限制返回结果数量
- 使用过滤条件减少搜索空间
RAG 优化:
- 调整检索参数以提高相关性
- 优化提示词以提高生成质量
- 考虑多步检索策略
性能考虑:
- 缓存频繁使用的嵌入
- 使用并行处理提高批量操作速度
- 监控和优化查询性能
扩展性:
- 设计可扩展的存储架构
- 考虑数据增长和查询负载
- 实现数据分片和负载均衡