技术栈
- 框架:Spring Boot 4.1.1
- 嵌入模型:Qwen3-Embedding-4B
- 向量持久化存储:PGVector 17(PostgreSQL 17 + 预装 pgvector 扩展)
步骤

<!– LangChian4j 基础 –>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>1.19.0</version>
</dependency>
<!– OpenAI 适配 –>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>1.19.0</version>
<scope>compile</scope>
</dependency>
<!– pgvector –>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-pgvector</artifactId>
<version>1.19.0-beta29</version>
<scope>compile</scope>
</dependency>
@Configuration
public class LLMConfig {
@Bean
public EmbeddingModel embeddingModel() {
return OpenAiEmbeddingModel.builder()
.apiKey("sk-xxxxx")
.baseUrl("https://api.siliconflow.cn/v1")
.modelName("Qwen/Qwen3-Embedding-4B") // 2560维
.build();
}
@Bean
public PgVectorEmbeddingStore pgVectorEmbeddingStore() {
return PgVectorEmbeddingStore.builder()
.host("xxx.xxx.xxx.xxx")
.port(15432)
.database("test_db")
.user("xxx")
.password("xxx")
.table("document_embeddings")
.dimension(2560) // 必须与嵌入模型的维度一致
.build();
}
}

可以在test_db中执行SELECT extname FROM pg_extension WHERE extname = 'vector'来验证是否已经启用了拓展

注意:PgVectorEmbeddingStore在初始化(首次建立连接、准备表结构)时,会默认自动执行类似这样的 SQL来启用拓展
CREATE EXTENSION IF NOT EXISTS vector; — 若未启用则自动启用
同时还会执行建表CREATE TABLE IF NOT EXISTS …和建索引,但是连接账号必须有权限执行
- 在 PostgreSQL 15 及以上:只有超级用户或该**数据库的所有者(owner)**才能执行CREATE EXTENSION。如果既不是超级用户也不是test_db的所有者,会自动执行失败,抛异常。
- 在 PostgreSQL 14 及以下:只要用户有数据库的 CREATE 权限就能建
@SpringBootTest
public class RAGTests {
@Autowired
private EmbeddingModel embeddingModel;
@Autowired
private EmbeddingStore<TextSegment> pgVectorEmbeddingStore;
// 测试文本向量化入库
@Test
void testRAG() {
// 构建文档元信息
Metadata metadata = new Metadata();
metadata.put("doc_id", "DOC_2026001");
metadata.put("author", "张三");
metadata.put("create_time", System.currentTimeMillis());
Document document = Document.from("Spring Boot 是一个用于构建微服务的框架,它基于 Spring 框架,提供自动化配置……", metadata);
// 切分文档为 300 字符的片段,每个片段之间间隔 50 字符
List<TextSegment> segments = DocumentSplitters.recursive(300, 50)
.split(document);
// 向量化
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
// 向量化入库
pgVectorEmbeddingStore.addAll(embeddings, segments);
System.out.println("文档切分为 " + segments.size() + " 个片段,已全部向量化并入库。");
}
// 测试相似度查询
@Test
void testQuery() {
String query = "什么是 Spring Boot?";
// 将查询文本向量化
Embedding queryEmbedding = embeddingModel.embed(query).content();
// 执行相似度检索(取最相似的 2 条)
EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(2)
.minScore(0.6) // 相似度阈值
.build();
EmbeddingSearchResult<TextSegment> searchResult = pgVectorEmbeddingStore.search(searchRequest);
System.out.println("【检索结果】:");
for (EmbeddingMatch<TextSegment> match : searchResult.matches()) {
System.out.println("相似度得分: " + match.score());
System.out.println("匹配内容: " + match.embedded().text());
System.out.println("metadata:" + match.embedded().metadata());
}
}
}





