티스토리 뷰

반응형

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

FAISS를 활용하여 검색된 문서를 로컬 LLM (Llama 3)과 결합하여 더욱 정확한 응답을 생성하는 과정을 구현합니다.
이 과정에서 RAG (Retrieval-Augmented Generation) 기법을 적용하여 검색된 문서를 기반으로 LLM이 답변을 생성하도록 만듭니다.


1) 검색된 문서 + LLM 결합 방식

✅ 기존 LLM 방식의 문제점

  • LLM 단독으로 응답을 생성할 경우, 사전 학습된 데이터만 사용
  • 최신 정보가 포함되지 않아 정확성이 낮을 수 있음
  • 문맥과 관련 없는 답변이 생성될 가능성 있음

✅ RAG 적용 후 기대 효과

  • 검색된 문서를 참고하여 LLM이 보다 정확한 응답 생성
  • 최신 정보를 포함할 수 있어 업데이트된 답변 제공 가능
  • 불필요한 환각(Hallucination) 현상 감소

2) 검색된 문서를 활용한 LLM 응답 생성 원리

[ 사용자의 질문 ]  
     ⬇  
[ 벡터 변환 (Sentence Transformer) ]  
     ⬇  
[ FAISS 벡터 검색 → 관련 문서 찾기 ]  
     ⬇  
[ 검색된 문서와 함께 LLM에게 전달 ]  
     ⬇  
[ LLM이 문서를 참고하여 최종 응답 생성 ]  

📌 핵심 개념:

  • 검색된 문서를 LLM 입력 프롬프트(Prompt)에 포함하여 문맥을 확장
  • FAISS 검색 결과를 LLM이 직접 활용하도록 구성

3) RAG 응답 생성 코드 구현 (LlmRagService.kt)

FAISS 검색 결과를 LLM에 입력하는 방식으로 RAG 시스템을 구현합니다.

🔹 RAG 응답 생성 코드 (LlmRagService.kt)

package ktor_chatbot.services

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.slf4j.LoggerFactory

@Serializable
data class LlmRequest(val prompt: String)

@Serializable
data class LlmResponse(val completion: String)

class LlmRagService(private val client: HttpClient, private val faissService: FaissService) {
    private val llmApiUrl = "http://localhost:8081/completion"
    private val logger = LoggerFactory.getLogger(LlmRagService::class.java)

    suspend fun getRagResponse(query: String): String = withContext(Dispatchers.IO) {
        try {
            // 1️⃣ FAISS에서 관련 문서 검색
            val retrievedDocs = faissService.search(query)

            // 2️⃣ 검색된 문서를 포함하여 LLM 프롬프트 구성
            val prompt = """
                |질문: $query
                |검색된 문서: $retrievedDocs
                |위 정보를 참고하여 답변을 생성하세요.
            """.trimMargin()

            // 3️⃣ LLM API 요청
            val response: HttpResponse = client.post(llmApiUrl) {
                contentType(ContentType.Application.Json)
                setBody(LlmRequest(prompt = prompt))
            }

            // 4️⃣ LLM 응답 반환
            val result = Json.decodeFromString<LlmResponse>(response.bodyAsText()).completion
            logger.info("RAG 응답: $result")
            return@withContext result
        } catch (e: Exception) {
            logger.error("RAG 응답 생성 실패: ${e.localizedMessage}")
            return@withContext "AI 응답을 가져오는 중 오류가 발생했습니다."
        }
    }
}

4) Ktor API 엔드포인트 추가 (Routing.kt)

이제 RAG 기반의 AI 응답을 제공하는 API 엔드포인트를 추가합니다.

package ktor_chatbot.plugins

import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.server.response.*
import ktor_chatbot.services.LlmRagService
import org.koin.ktor.ext.inject

fun Application.configureRouting() {
    val llmRagService: LlmRagService by inject()

    routing {
        get("/chat-rag") {
            val query = call.request.queryParameters["q"] ?: "RAG란?"
            val response = llmRagService.getRagResponse(query)
            call.respondText(response)
        }
    }
}

📌 엔드포인트 설명

  • GET /chat-rag?q=질문 → 사용자가 질문을 입력하면 RAG 기반 AI 응답 반환
  • faissService.search(query) → 관련 문서 검색 후 LLM에 전달

5) Ktor 서버 실행 및 테스트

🔹 Ktor 서버 실행

./gradlew run

🔹 LLM API 서버 실행 (로컬 Llama 3)

llama-cpp -m models/llama-3-8b.Q4_K_M.gguf --server -p 8081

🔹 API 테스트

curl "http://localhost:8080/chat-rag?q=RAG가 뭐야?"

✅ 응답 예시

RAG(Retrieval-Augmented Generation)는 검색과 생성 모델을 결합하여 더욱 정확한 AI 응답을 제공하는 기술입니다. 예를 들어, FAISS 검색을 통해 관련 문서를 찾고, 이를 기반으로 LLM이 답변을 생성합니다.

6) 검색된 문서를 활용한 AI 응답 성능 비교

테스트 질문 기존 LLM 응답 RAG 기반 응답

"RAG란?" RAG는 검색과 생성 모델을 결합한 기법입니다. RAG는 검색을 통해 문서를 참조한 후, 생성 모델이 문맥을 반영하여 응답을 생성하는 기법입니다.
"FAISS의 역할은?" FAISS는 유사성 검색을 수행하는 라이브러리입니다. FAISS는 대규모 데이터에서 벡터 간 유사도를 빠르게 계산하는 라이브러리로, RAG 시스템에서 검색 엔진으로 사용됩니다.
"로컬 LLM의 장점은?" 로컬 LLM은 인터넷 연결 없이 사용할 수 있습니다. 로컬 LLM은 인터넷 연결 없이 작동하며, 검색된 문서를 활용하여 보다 정확한 정보를 제공합니다.

📌 RAG 적용 후 향상된 점

  • 검색된 문서를 기반으로 더 정확한 문맥 반영
  • LLM 단독보다 신뢰할 수 있는 정보 제공 가능

7) RAG 기반 검색 및 응답 결합 요약

단계 작업 내용 코드 적용 위치

1 FAISS 검색 결과 활용 FaissService.kt
2 검색된 문서를 LLM에 전달 LlmRagService.kt
3 RAG 기반 API 추가 Routing.kt
4 Ktor 서버 실행 및 테스트 ./gradlew run

8) 다음 단계

이제 FAISS 검색 결과를 LLM과 결합하여 보다 정확한 AI 응답을 생성할 수 있습니다.
다음으로 3.3.3 검색 성능 모니터링 및 개선을 진행하여 FAISS 및 LLM 성능을 측정하고 최적화하는 방법을 다루겠습니다! 🚀

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
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
글 보관함
반응형