Spring AI与RAG技术实战:构建企业级智能文档问答系统
引言
随着人工智能技术的快速发展,企业对于智能化文档处理的需求日益增长。传统的文档检索方式已经无法满足用户对精准、智能问答的需求。Spring AI结合RAG(检索增强生成)技术,为企业提供了一种全新的智能文档问答解决方案。本文将详细介绍如何使用Spring AI框架构建企业级智能文档问答系统。
技术栈概述
核心组件
- Spring AI: Spring生态系统中的AI集成框架
- RAG架构: 检索增强生成技术
- 向量数据库: Milvus/Chroma/Redis
- Embedding模型: OpenAI/Ollama
- Spring Boot: 后端开发框架
系统架构设计
整体架构
我们的智能文档问答系统采用分层架构设计:
┌─────────────────────────────────────────────┐
│ 表示层 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Web界面 │ │ API接口 │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 业务层 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 问答服务 │ │ 文档处理 │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 数据层 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 向量数据库 │ │ 关系数据库 │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────┘
RAG工作流程
-
文档预处理阶段
- 文档加载与解析
- 文本分割与清理
- 向量化处理
-
检索阶段
- 用户查询向量化
- 相似度检索
- 相关文档片段获取
-
生成阶段
- 上下文构建
- 提示词工程
- 答案生成与优化
环境准备与配置
Maven依赖配置
<dependencies>
<!-- Spring AI Core -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
<version>1.0.0</version>
</dependency>
<!-- OpenAI Integration -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Vector Store -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-vector-store</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Redis for Vector Store -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
应用配置
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4-turbo
temperature: 0.7
vectorstore:
redis:
uri: redis://localhost:6379
index: document_vectors
redis:
host: localhost
port: 6379
核心功能实现
1. 文档处理服务
@Service
public class DocumentProcessingService {
@Autowired
private EmbeddingClient embeddingClient;
@Autowired
private VectorStore vectorStore;
/**
* 处理并存储文档
*/
public void processDocument(String documentId, String content) {
// 文本分割
List<TextSegment> segments = splitText(content);
// 生成嵌入向量
List<Embedding> embeddings = embeddingClient.embed(segments);
// 存储到向量数据库
for (int i = 0; i < segments.size(); i++) {
Vector vector = new Vector(
documentId + "_" + i,
embeddings.get(i),
Map.of("content", segments.get(i).getText())
);
vectorStore.add(vector);
}
}
private List<TextSegment> splitText(String content) {
// 实现文本分割逻辑
return TextSplitter.split(content, 500); // 每段500字符
}
}
2. 智能问答服务
@Service
public class SmartQAService {
@Autowired
private ChatClient chatClient;
@Autowired
private VectorStore vectorStore;
/**
* 基于RAG的智能问答
*/
public String answerQuestion(String question) {
// 1. 检索相关文档片段
List<SearchResult> results = retrieveRelevantDocuments(question);
// 2. 构建上下文
String context = buildContext(results);
// 3. 生成答案
return generateAnswer(question, context);
}
private List<SearchResult> retrieveRelevantDocuments(String query) {
Embedding queryEmbedding = embeddingClient.embed(query);
return vectorStore.search(queryEmbedding, 5); // 返回最相关的5个结果
}
private String buildContext(List<SearchResult> results) {
StringBuilder context = new StringBuilder();
for (SearchResult result : results) {
context.append(result.getMetadata().get("content")).append("\n\n");
}
return context.toString();
}
private String generateAnswer(String question, String context) {
String prompt = String.format("""
基于以下上下文信息,请回答用户的问题。
上下文:
%s
问题:%s
要求:回答要准确、简洁,如果上下文信息不足,请如实告知。
""", context, question);
return chatClient.generate(prompt);
}
}
3. REST API控制器
@RestController
@RequestMapping("/api/qa")
public class QAController {
@Autowired
private SmartQAService qaService;
@Autowired
private DocumentProcessingService documentService;
@PostMapping("/ask")
public ResponseEntity<AnswerResponse> askQuestion(@RequestBody QuestionRequest request) {
try {
String answer = qaService.answerQuestion(request.getQuestion());
return ResponseEntity.ok(new AnswerResponse(answer));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new AnswerResponse("系统繁忙,请稍后重试"));
}
}
@PostMapping("/document")
public ResponseEntity<String> uploadDocument(@RequestBody DocumentUploadRequest request) {
try {
documentService.processDocument(request.getDocumentId(), request.getContent());
return ResponseEntity.ok("文档处理成功");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("文档处理失败");
}
}
}
高级特性实现
1. 多模型支持
@Configuration
public class ModelConfiguration {
@Bean
@ConditionalOnProperty(name = "ai.provider", havingValue = "openai")
public ChatClient openAIChatClient(OpenAIChatProperties properties) {
return new OpenAIChatClient(properties);
}
@Bean
@ConditionalOnProperty(name = "ai.provider", havingValue = "ollama")
public ChatClient ollamaChatClient(OllamaProperties properties) {
return new OllamaChatClient(properties);
}
}
2. 缓存优化
@Service
public class CachedQAService {
@Autowired
private SmartQAService delegate;
@Cacheable(value = "qaCache", key = "#question")
public String answerQuestionWithCache(String question) {
return delegate.answerQuestion(question);
}
}
3. 性能监控
@Aspect
@Component
public class PerformanceMonitor {
private final MeterRegistry meterRegistry;
public PerformanceMonitor(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@Around("execution(* com.example.service..*(..))")
public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Timer.Sample sample = Timer.start(meterRegistry);
try {
return joinPoint.proceed();
} finally {
sample.stop(Timer.builder("service.method.duration")
.tag("method", methodName)
.register(meterRegistry));
}
}
}
部署与运维
Docker容器化部署
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/qa-system.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Kubernetes部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: qa-system
spec:
replicas: 3
selector:
matchLabels:
app: qa-system
template:
metadata:
labels:
app: qa-system
spec:
containers:
- name: qa-app
image: qa-system:latest
ports:
- containerPort: 8080
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: ai-secrets
key: openai-api-key
---
apiVersion: v1
kind: Service
metadata:
name: qa-service
spec:
selector:
app: qa-system
ports:
- port: 80
targetPort: 8080
性能优化策略
1. 向量检索优化
public class OptimizedVectorSearch {
/**
* 使用近似最近邻搜索提高性能
*/
public List<SearchResult> optimizedSearch(Embedding query, int topK) {
// 使用HNSW算法进行近似搜索
return vectorStore.approximateSearch(query, topK, 0.8);
}
/**
* 批量处理查询
*/
public Map<String, List<SearchResult>> batchSearch(List<String> queries) {
List<Embedding> queryEmbeddings = embeddingClient.embed(queries);
Map<String, List<SearchResult>> results = new HashMap<>();
for (int i = 0; i < queries.size(); i++) {
results.put(queries.get(i),
optimizedSearch(queryEmbeddings.get(i), 3));
}
return results;
}
}
2. 内存管理优化
@Configuration
public class MemoryConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000));
return cacheManager;
}
}
测试策略
单元测试
@SpringBootTest
public class SmartQAServiceTest {
@MockBean
private ChatClient chatClient;
@MockBean
private VectorStore vectorStore;
@Autowired
private SmartQAService qaService;
@Test
public void testAnswerQuestion() {
// 模拟向量检索结果
when(vectorStore.search(any(), anyInt()))
.thenReturn(Collections.singletonList(
new SearchResult("doc1", 0.9,
Map.of("content", "测试上下文内容"))
));
// 模拟AI回答
when(chatClient.generate(anyString()))
.thenReturn("这是测试回答");
String answer = qaService.answerQuestion("测试问题");
assertEquals("这是测试回答", answer);
}
}
集成测试
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class QAControllerIntegrationTest {
@LocalServerPort
private int port;
@Test
public void testAskEndpoint() {
RestTemplate restTemplate = new RestTemplate();
QuestionRequest request = new QuestionRequest("什么是Spring AI?");
ResponseEntity<AnswerResponse> response = restTemplate.postForEntity(
"http://localhost:" + port + "/api/qa/ask",
request,
AnswerResponse.class
);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody().getAnswer());
}
}
安全考虑
1. API访问控制
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/qa/**").authenticated()
.anyRequest().permitAll()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.build();
}
}
2. 输入验证
public class QuestionRequest {
@NotBlank
@Size(max = 1000)
private String question;
// getters and setters
}
总结与展望
本文详细介绍了如何使用Spring AI和RAG技术构建企业级智能文档问答系统。通过合理的架构设计、性能优化和安全考虑,我们能够构建出高效、可靠的智能问答平台。
未来的发展方向包括:
- 多模态支持:支持图片、表格等非文本内容的处理
- 实时学习:系统能够从用户反馈中持续学习优化
- 个性化推荐:基于用户历史提供个性化问答服务
- 边缘计算:在边缘设备上部署轻量级模型
Spring AI作为一个新兴的框架,为Java开发者提供了便捷的AI集成方案。随着技术的不断发展,相信会有更多优秀的功能和特性被加入其中。
构建企业级智能问答系统实战指南

被折叠的 条评论
为什么被折叠?



