실무에 바로 적용하는 Spring AI: Spring 서비스에 챗봇·RAG·MCP 도입하기
practice-implementing-rag-rest-api
✅ 1. Controller 소스 코드 변경
RagChatController.java
package com.jscode.chat.controller;
@RestController
@RequestMapping("/rag")
public class RagChatController {
private final RagChatService ragChatService;
public RagChatController(RagChatService ragChatService) {
this.ragChatService = ragChatService;
}
public record RagPromptBody(@NotEmpty String conversationId, @NotEmpty String userPrompt,
@Nullable String systemPrompt, DefaultChatOptions chatOptions,
@Nullable String filterExpression){}
@PostMapping(value = "/call", produces = MediaType.APPLICATION_JSON_VALUE)
public ChatResponse call(@RequestBody @Valid RagPromptBody ragPromptBody) {
Prompt prompt = createPrompt(ragPromptBody);
// 완성된 프롬프트와 conversationID를 가지고 서비스 메서드 호출
return ragChatService.call(prompt, ragPromptBody.conversationId, Optional.ofNullable(ragPromptBody.filterExpression()));
}
@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> stream(@RequestBody @Valid RagPromptBody ragPromptBody){
Prompt prompt = createPrompt(ragPromptBody);
return ragChatService.stream(prompt, ragPromptBody.conversationId(), Optional.ofNullable(ragPromptBody.filterExpression()));
}
private static Prompt createPrompt(RagPromptBody ragPromptBody) {
// 1. 메시지들을 차곡차곡 담을 빈 List를 생성
List<Message> messages = new ArrayList<>();
// 2. systemPrompt가 입력으로 들어왔다면 리스트에 넣자
if(ragPromptBody.systemPrompt() != null && !ragPromptBody.systemPrompt().isBlank()){
messages.add(new SystemMessage(ragPromptBody.systemPrompt()));
}
// 3. userPrompt는 필수 값이니 무조건 리스트에 넣자
messages.add(new UserMessage(ragPromptBody.userPrompt()));
// 4. 리스트에 담긴 메시지들로 프롬프트 조립하기
Prompt.Builder promptBuilder = Prompt.builder().messages(messages);
// 5. 프론트엔드에서 보낸 chatOptions가 있다면 적용하기
if(ragPromptBody.chatOptions() != null){
promptBuilder.chatOptions(ragPromptBody.chatOptions());
}
return promptBuilder.build();
}
}
✅ 2. application.yaml 파일 수정
app:
rag:
documents-location-pattern: classpath:spring-ai-llm2.pdf
etl:
pipeline:
init: true
cli:
# enabled: true
✅ 3. 테스트
{
"conversationId": "string",
"userPrompt": "SummaryMetadataEnricher에 대해 설명해줘"
}
{
"conversationId": "string",
"userPrompt": "etl이 뭐야? 한국어로 답변줘"
}