在当今人工智能迅猛发展的时代,Java开发者如何利用最新的AI技术构建智能应用?本文将深入探讨模型API、检索增强生成(RAG)和向量数据库这三种关键技术,以及它们如何协同工作来提升Java应用的智能化水平。
模型API是大型语言模型(LLM)提供的编程接口,允许开发者通过HTTP请求与AI模型交互。在Java生态中,我们可以通过多种方式接入这些API:
// 使用Spring WebClient调用OpenAI API示例
public String getChatCompletion(String prompt) {
WebClient client = WebClient.create("https://api.openai.com/v1");
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "gpt-3.5-turbo");
requestBody.put("messages", List.of(Map.of("role", "user", "content", prompt)));
return client.post()
.uri("/chat/completions")
.header("Authorization", "Bearer " + apiKey)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(String.class)
.block();
}
尽管强大,模型API存在一些限制:
RAG(Retrieval-Augmented Generation)通过以下流程工作:
// 简化的RAG流程伪代码
public String ragAnswer(String question) {
// 1. 检索相关文档
List<Document> relevantDocs = vectorDB.search(question, topK=3);
// 2. 构建增强提示
String augmentedPrompt = buildAugmentedPrompt(question, relevantDocs);
// 3. 调用模型API生成回答
return modelAPI.generate(augmentedPrompt);
}
Spring AI项目提供了RAG的原生支持:
@Bean
public RetrievalAugmentor retrievalAugmentor(VectorStore vectorStore) {
return new VectorStoreRetriever(vectorStore);
}
@Bean
public ChatClient chatClient(OpenAiChatOptions options, RetrievalAugmentor augmentor) {
return ChatClient.builder()
.chatModel(new OpenAiChatModel(options))
.augmentor(augmentor)
.build();
}
对于更复杂的需求,可以自定义RAG流程:
public class CustomRagService {
private final VectorStore vectorStore;
private final ChatModel chatModel;
public String generateWithRag(String question) {
// 1. 检索相关文档
List<Document> docs = vectorStore.similaritySearch(question);
// 2. 构建提示模板
PromptTemplate promptTemplate = new PromptTemplate("""
基于以下上下文回答问题:
{context}
问题:{question}
""");
Prompt prompt = promptTemplate.create(Map.of(
"context", formatContext(docs),
"question", question
));
// 3. 调用模型
return chatModel.call(prompt).getResult().getOutput().getContent();
}
}
向量数据库专门为存储和检索向量嵌入(embeddings)而优化,具有以下特点:
// Pinecone Java客户端示例
PineconeClient client = new PineconeClient("api-key", "environment");
VectorOperations ops = client.vectorOperations("index-name");
// 插入向量
UpsertRequest upsert = new UpsertRequest()
.addVector("vec1", Arrays.asList(0.1f, 0.2f, 0.3f),
Map.of("category", "science"));
ops.upsert(upsert);
// 查询相似向量
QueryRequest query = new QueryRequest()
.setTopK(3)
.setVector(Arrays.asList(0.1f, 0.15f, 0.25f));
QueryResponse response = ops.query(query);
// Weaviate Java客户端示例
Config config = new Config("https://your-weaviate-instance", "API-KEY");
WeaviateClient client = new WeaviateClient(config);
// 创建数据对象
Result<WeaviateObject> result = client.data()
.creator()
.withClassName("Article")
.withProperties(Map.of(
"title", "Java AI Development",
"content", "Building intelligent apps with Java..."
))
.run();
// Redis向量搜索示例
JedisPooled jedis = new JedisPooled("localhost", 6379);
// 创建索引
jedis.ftCreate("idx:articles",
FTCreateParams.createParams()
.on(IndexDataType.HASH)
.addPrefix("article:"),
TextField.of("title"),
VectorField.builder()
.fieldName("content_vector")
.algorithm(VectorAlgorithm.HNSW)
.build()
);
// 存储文档和向量
Map<String, String> fields = new HashMap<>();
fields.put("title", "Java RAG Patterns");
fields.put("content_vector", Arrays.toString(new float[]{...}));
jedis.hset("article:1", fields);
// 使用Lucene实现向量搜索
Directory directory = FSDirectory.open(Paths.get("index"));
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
// 添加向量字段
FieldType vectorType = new FieldType();
vectorType.setVectorDimensions(128);
vectorType.freeze();
Document doc = new Document();
doc.add(new Field("title", "Java AI", TextField.TYPE_STORED));
doc.add(new KnnVectorField("vector", new float[]{...}, vectorType));
// 向量搜索
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
TopDocs hits = searcher.search(
new KnnVectorQuery("vector", new float[]{...}, 10),
10
);
用户请求 → Java后端 → [检索 → 向量数据库] → [增强 → 模型API] → 生成响应
public class DocumentIndexer {
private final EmbeddingModel embeddingModel;
private final VectorStore vectorStore;
public void indexDocuments(List<Document> docs) {
docs.forEach(doc -> {
// 生成嵌入向量
List<Double> embedding = embeddingModel.embed(doc.getContent());
// 存储到向量数据库
vectorStore.add(
doc.getId(),
embedding,
Map.of(
"title", doc.getTitle(),
"author", doc.getAuthor()
)
);
});
}
}
public class RagService {
private final VectorStore vectorStore;
private final ChatModel chatModel;
private final EmbeddingModel embeddingModel;
public String query(String question) {
// 1. 将问题转换为向量
List<Double> queryVector = embeddingModel.embed(question);
// 2. 检索相关文档
List<Document> relevantDocs = vectorStore.findSimilar(
queryVector,
3, // topK
0.7 // 相似度阈值
);
// 3. 构建增强提示
String context = relevantDocs.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n\n"));
String prompt = String.format("""
基于以下上下文回答问题。如果上下文不包含答案,
请回答"我不知道"。
上下文:
%s
问题:%s
""", context, question);
// 4. 调用模型生成回答
return chatModel.generate(prompt);
}
}
public class CustomerSupportService {
private final RagService ragService;
private final KnowledgeBase knowledgeBase;
public SupportResponse handleQuery(SupportRequest request) {
// 1. 检查是否标准问题
if (knowledgeBase.isKnownIssue(request.getQuestion())) {
return knowledgeBase.getStandardResponse(request.getQuestion());
}
// 2. 使用RAG处理复杂问题
String answer = ragService.query(request.getQuestion());
// 3. 记录交互用于改进
knowledgeBase.recordInteraction(request, answer);
return new SupportResponse(answer, List.of("helpful", "accurate"));
}
}
@RestController
@RequestMapping("/api/knowledge")
public class KnowledgeController {
private final DocumentIndexer indexer;
private final RagService ragService;
@PostMapping("/index")
public ResponseEntity<?> indexDocument(@RequestBody DocRequest request) {
indexer.index(request.getDocuments());
return ResponseEntity.ok().build();
}
@GetMapping("/query")
public ResponseEntity<Answer> queryKnowledge(@RequestParam String q) {
return ResponseEntity.ok(
new Answer(ragService.query(q))
);
}
}
public class ProductRecommender {
private final VectorStore productVectorStore;
public List<Product> recommendSimilarProducts(Product product, int count) {
// 获取产品向量
List<Double> vector = productVectorStore.getVector(product.getId());
// 查找相似产品
return productVectorStore.findSimilar(vector, count).stream()
.map(this::convertToProduct)
.collect(Collectors.toList());
}
}
分块策略优化:
元数据增强:
// 添加丰富的元数据
document.setMetadata(Map.of(
"document_type", "technical_spec",
"product_version", "2.4",
"language", "zh-CN"
));
混合检索策略:
public List<Document> hybridSearch(String query, int topK) {
// 关键词搜索
List<Document> keywordResults = fullTextSearch(query, topK/2);
// 向量搜索
List<Double> vector = embeddingModel.embed(query);
List<Document> vectorResults = vectorStore.findSimilar(vector, topK/2);
// 合并和去重
return mergeAndDedup(keywordResults, vectorResults);
}
结果后处理:
public String postProcessAnswer(String rawAnswer) {
// 移除引用标记
String cleaned = rawAnswer.replaceAll("\\[\\d+\\]", "");
// 验证事实性声明
if (containsFactualClaim(cleaned)) {
return verifiedAnswer(cleaned);
}
return cleaned;
}
history_rag
基于Milvus/Zilliz Cloud构建的历史问答系统,支持本地和云端部署,使用BAAI/bge中文嵌入模型和GPT-4生成回答。
GitHub: https://github.com/wxywb/history_rag 79
Gitee镜像: https://gitee.com/lobyliang/history_rag 9
Eino框架RAG示例
Golang实现的文档检索系统,结合Redis向量搜索和Doubao大模型,适用于知识库问答。
GitHub: https://github.com/BaiZe1998/go-learning 6
ChromaDB官方示例
轻量级Python向量数据库,支持快速原型开发,集成LangChain和自定义嵌入模型。
GitHub: https://github.com/chroma-core/chroma 3
文档: https://docs.trychroma.com/
Canopy知识图谱引擎
基于Pinecone的RAG框架,支持文档切分、嵌入和会话管理,适合领域问答系统构建。
项目地址: https://www.msbd123.com/sites/80978.html 5
Infinity混合搜索Demo
支持向量+稀疏向量+全文搜索的三路召回,内置RRF融合排序算法。
相关技术博客: http://www.ppmy.cn/news/1610931.html 8
这些项目覆盖了从轻量级开发(Chroma)到企业级方案(Infinity),涉及Python、Golang等语言栈,可作为RAG实践的参考模板。如需具体部署指导,可查阅各项目的文档或示例代码。
这些项目涵盖了从AI Agent开发平台到向量数据库、RAG优化工具等多个方向,适合不同需求的开发者参考和使用。
模型API、RAG和向量数据库的组合为Java开发者提供了构建新一代智能应用的强大工具集。通过合理利用这些技术,我们可以在不牺牲Java生态系统优势的情况下,为应用注入AI能力。随着技术的不断演进,这种架构模式将在企业级应用中扮演越来越重要的角色。
对于Java团队来说,现在正是探索这些技术、积累经验的最佳时机。从小的概念验证开始,逐步构建复杂系统,最终实现真正的智能企业应用。