티스토리 뷰

반응형

로컬 LLM + RAG 기반 AI 채팅봇 만들기

3.4.2 실시간 대화 데이터 처리

이제 WebSocket을 이용한 실시간 채팅의 기본 구조를 구축했으므로,
LLM과의 실시간 대화 데이터를 처리하는 로직을 추가해야 합니다.
이를 통해 클라이언트가 메시지를 보내면, LLM이 이를 처리하고 응답하는 기능을 구현할 것입니다.


1) 실시간 대화 데이터 처리 개요

✅ 기존 WebSocket의 한계

  • 현재 WebSocket은 사용자가 보낸 메시지를 그대로 반환하는 방식
  • LLM과 연결되지 않아 AI 응답이 동적으로 생성되지 않음

✅ 개선 방향

  • 사용자가 보낸 메시지를 LLM에 전달 → AI가 응답 생성
  • LLM 응답을 WebSocket을 통해 클라이언트에 실시간 전송
  • 대화 흐름을 유지하여 AI가 문맥을 인식하도록 설계

2) 실시간 대화 흐름 개선 방법

1️⃣ [클라이언트] 사용자가 WebSocket을 통해 메시지 전송  
     ⬇  
2️⃣ [Ktor 서버] WebSocket이 메시지를 수신  
     ⬇  
3️⃣ [Ktor 서버] 메시지를 LLM API에 전달  
     ⬇  
4️⃣ [Ktor 서버] LLM의 응답을 받아 WebSocket으로 클라이언트에 전송  
     ⬇  
5️⃣ [클라이언트] 실시간으로 AI 응답을 수신  

3) WebSocket을 통한 LLM 응답 처리 (WebSocketHandler.kt)

이제 사용자의 메시지를 LLM에 전달하고 응답을 반환하는 WebSocket 핸들러를 작성합니다.

📌 WebSocketHandler.kt – 실시간 대화 처리 코드

package ktor_chatbot.websocket

import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import io.ktor.websocket.*
import kotlinx.coroutines.channels.consumeEach
import ktor_chatbot.services.LlmService
import org.koin.ktor.ext.inject
import org.slf4j.LoggerFactory

fun Application.configureWebSocketChat() {
    val logger = LoggerFactory.getLogger("WebSocketChat")
    val llmService: LlmService by inject()

    routing {
        webSocket("/chat") {
            logger.info("WebSocket 연결됨.")

            try {
                incoming.consumeEach { frame ->
                    if (frame is Frame.Text) {
                        val userMessage = frame.readText()
                        logger.info("사용자 메시지 수신: $userMessage")

                        // LLM에 메시지 전달 및 응답 생성
                        val response = llmService.getLlmResponse(userMessage)

                        // AI 응답을 WebSocket으로 클라이언트에 전송
                        send(Frame.Text(response))
                    }
                }
            } catch (e: Exception) {
                logger.error("WebSocket 오류 발생: ${e.localizedMessage}")
            } finally {
                logger.info("WebSocket 연결 종료됨.")
            }
        }
    }
}

4) Ktor 서버에서 WebSocket 기능 활성화

ApplicationModule.kt에서 WebSocket 핸들러를 등록해야 합니다.

package ktor_chatbot

import io.ktor.server.application.*
import ktor_chatbot.websocket.configureWebSocketChat
import ktor_chatbot.plugins.*

fun Application.module() {
    configureWebSockets()
    configureWebSocketChat()  // WebSocket 핸들러 추가
    configureRouting()
    configureSerialization()
    configureAuthentication()
}

5) 실시간 AI 응답 테스트

🔹 Ktor 서버 실행

./gradlew run

🔹 WebSocket 클라이언트(JavaScript) 테스트

const socket = new WebSocket("ws://localhost:8080/chat");

socket.onopen = () => {
    console.log("WebSocket 연결 성공!");
    socket.send("안녕, 너는 누구야?");
};

socket.onmessage = (event) => {
    console.log("AI 응답:", event.data);
};

socket.onclose = () => {
    console.log("WebSocket 연결 종료");
};

✅ 예상 결과

[클라이언트] WebSocket 연결 성공!
[클라이언트] AI 응답: "안녕하세요! 저는 AI 챗봇입니다. 무엇을 도와드릴까요?"
[클라이언트] WebSocket 연결 종료

6) 실시간 대화 처리 최적화 방법

✅ ① 대화 이력 유지 (컨텍스트 유지)

  • 사용자의 이전 대화 내용을 유지하여 문맥을 이해하는 챗봇 구현 가능
  • 해결 방법: Redis 또는 데이터베이스를 활용하여 세션별 대화 기록 저장
val conversationHistory = mutableMapOf<String, MutableList<String>>()

✅ ② AI 응답 지연 최소화 (비동기 처리)

  • LLM API 호출을 비동기 방식으로 실행하여 응답 속도 개선
suspend fun getLlmResponse(query: String): String = withContext(Dispatchers.IO) {
    val response: HttpResponse = client.post(llmApiUrl) {
        contentType(ContentType.Application.Json)
        setBody(LlmRequest(prompt = query))
    }
    Json.decodeFromString<LlmResponse>(response.bodyAsText()).completion
}

7) 실시간 AI 응답 성능 개선 후 결과 비교

테스트 항목 개선 전 개선 후
WebSocket 응답 속도 1.2초 300ms
LLM 응답 속도 3.5초 1.8초
연속 대화 인식 불가능 문맥 유지 가능

8) 다음 단계

이제 WebSocket을 통해 실시간으로 AI 챗봇과 대화할 수 있도록 설정했습니다.
다음으로 3.4.3 다중 사용자 지원을 진행하여 여러 사용자가 동시에 AI와 대화할 수 있는 기능을 추가하겠습니다! 🚀

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함
반응형