CLOVA Studio 운영자7 Posted July 2 공유하기 Posted July 2 최근 LLM을 활용한 RAG 시스템 구축이 활발해지면서, 방대한 데이터 속에서 쿼리에 가장 적합한 정보를 효율적으로 찾아내는 것이 중요한 과제로 떠오르고 있습니다. 이러한 흐름에 발맞춰, 이번 쿡북에서는 CLOVA Studio의 리랭커 API를 활용하여 RAG 시스템을 간편하게 구현하는 방법을 소개합니다. 1. 리랭커 소개 리랭커는 유저 쿼리에 대한 RAG의 응답 품질을 결정하는 핵심적인 역할을 합니다. RAG 시스템 중 초기 검색 단계에서 얻는 문서들은 방대하고 때론 쿼리의 의도와 거리가 멀 수 있습니다. 이때 리랭커는 단순히 많은 검색 정보를 제공하는 것을 넘어, 검색 API로 불러온 결과값을 보정하고 가장 관련성 높은 정보만을 선별하여 압축해 제공합니다. 이러한 선별 과정은 불필요한 정보가 주입되는 것을 방지하고, 토큰 낭비를 줄이며, 결과적으로 더욱 신뢰도 높은 답변을 생성하도록 돕습니다. 1.1 스튜디오 리랭커 작동 원리 스튜디오 리랭커는 리랭커의 기능을 수행할 수 있도록 프롬프팅 된 LLM 입니다. 즉, 일반적인 리랭커와 달리 별도의 리랭커와 LLM이 분리되어 있지 않으며, 하나의 가공된 LLM이 리랭커의 기능과 더불어 답변 생성까지 직접 수행하도록 설계되어 있습니다. 리랭커 API는 유저 쿼리와 각 문서를 심층적으로 분석하여 관련성이 높은 문서를 필터링하는 것에 중점을 둡니다. 이 과정에서 단순히 단어 일치만을 보는 것이 아니라, 문맥 그리고 쿼리 의도 등 다양한 값들을 종합적으로 고려합니다. 이렇게 유저 질문에 대한 가장 중요한 정보를 담고 있는 문서를 정확시 찾아낸 뒤, 문서 내 정보들을 압축 요약하고 LLM을 통해 최종 답변까지 직접 생성합니다. 이를 동한 주요 이점을 다음과 같습니다: 정확도 향상 : 유저 질문과 가장 관련성 높은 문서를 정확히 골라내어 RAG 시스템의 LLM에 주입합니다. 토큰 효율성 : LLM에 들어가는 정보량을 줄여 토큰을 효율적으로 사용하게 합니다. 이는 비용 절감과 함께 LLM 처리 속도 향상에도 기여합니다. 환각 현상 감소 : 불필요하거나 관련 없는 정보로 인한 LLM의 환각 현상을 줄여 답변의 정확성과 신뢰도를 극대화합니다. 2. 리랭커 적용 시나리오 2.1 네이버 클라우드 플랫폼 CS 문의 대응을 위한 RAG 시스템 구현 CS 분야에서 정확하고 신뢰성 있는 답변을 제공하는 것은 매우 중요한 사항입니다. 본 섹션에서는 리랭커 API를 이용해 네이버 클라우드 플랫폼 CS 문의 대응에 활용할 RAG 시스템을 구축하는 과정을 소개합니다. 사용 가이드 데이터와 FAQ 데이터를 효율적으로 활용하여 고객 문의에 대한 정확한 답변을 제공하는 것을 목표로 합니다. 2.1.1 사용 데이터 사용 가이드 : 네이버 클라우드 플랫폼의 가이드 센터에서 제공하는 '사용 가이드' 를 활용합니다. 유저 가이드에 대한 자세한 정보는 NCloud 가이드에서 확인할 수 있습니다. FAQ 데이터셋 : 네이버 클라우드 '자주 묻는 질문'을 가공한 데이터 셋입니다. Quote 서비스는 지속적인 기능 개선 및 업데이트가 이루어지므로, 이용 가이드의 내용 또한 빈번하게 변경됩니다. 따라서 본 쿡북에서는 2025년 1분기 시점에 업데이트된 사용 가이드와 FAQ 데이터셋을 기준으로 구성하였습니다. 이와 더불어 본 쿡북에서 제공하는 예시 데이터 파일은 간단한 구현을 위해 네이버 클라우드 플랫폼의 CLOVA Studio 상품과 관련된 내용만을 포함하고 있습니다. 2.1.2 검색 API 구현 네이버 클라우드 플랫폼의 가이드 문서 및 FAQ 데이터를 기반으로, 유저 쿼리에 가장 적합한 문서를 찾아 제공하는 검색 API를 구성합니다. 데이터 준비 : 사용 가이드와 FAQ 데이터를 결합하고 중복 제거, 이미지 제거 등 전처리 작업을 수행하고 csv 형태로 통합합니다. 임베딩 생성 : CLOVA Studio의 embedding 모델 API를 호출하여 각 텍스트 데이터에 대해 벡터 임베딩을 생성하고, 이를 새로운 컬럼으로 추가합니다. CLOVA Studio의 embedding에 대한 자세한 정보는 embedding 가이드에서 확인할 수 있습니다. 구현의 편의를 위해 임베딩 파일을 첨부해 두었습니다. (파일: CLOVA_Studio.csv) 검색 API 구성 : 유저 쿼리를 임베딩한 뒤 기존에 생성한 문서 임베딩 간의 코사인 유사도를 계산하여 가장 관련성 높은 상위 문서들을 반환하는 검색 API를 구성합니다. FastAPI 기반으로 활용할 수 있도록 설정해주었습니다. Quote # 핵심 기능만 간소화한 코드 예시 import os import pandas as pd import numpy as np from numpy import dot from numpy.linalg import norm import ast from fastapi import FastAPI from pydantic import BaseModel from typing import List import requests app = FastAPI() #쿼리 임베딩 생성 def get_embedding(input_text, api_key): EMBEDDING_API_URL = "https://clovastudio.stream.ntruss.com/v1/api-tools/embedding/v2" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } data = {"text": input_text} response = requests.post(EMBEDDING_API_URL, headers=headers, json=data) response.raise_for_status() embedding = response.json()["result"]["embedding"] return embedding def start(): file_path = 'CLOVA_Studio.csv' if os.path.isfile(file_path): print(f"{file_path} 파일이 존재합니다.") df = pd.read_csv(file_path) df['ID'] = df.index df['embedding'] = df['embedding'].apply(ast.literal_eval) else: print('임베딩 파일을 찾을 수 없습니다.') return df #코사인 유사도 계산 def cos_sim(A, B): return dot(A, B)/(norm(A)*norm(B)) #후보 문서 추출 def return_answer_candidate(df, query, top_k, api_key): embedding = get_embedding(query, api_key) df["similarity"] = df.embedding.apply(lambda x: cos_sim(np.array(x), np.array(embedding))) top_k_doc = df.sort_values("similarity", ascending=False).head(top_k) return top_k_doc #응답 데이터 생성 def return_results(df, query, top_k, api_key): result_lst = [] result = return_answer_candidate(df, query, top_k, api_key) for i in range(0, top_k): result_lst.append({"id": str(result.iloc[i]['ID']), "content":str(result.iloc[i]['text'])}) return result_lst class SearchInput(BaseModel): query: str top_k: int class SearchResult(BaseModel): id: str content: str class SearchOutput(BaseModel): result: List[SearchResult] df = start() api_key = "API_KEY_HERE" #실제 API키 입력 # FastAPI 설정 @app.post("/search/", response_model=SearchOutput) # 로컬 주소에 /search/를 더해줍니다. async def search(input: SearchInput) -> SearchOutput: results = return_results(df, input.query, input.top_k, api_key) print(results) return SearchOutput(result=results) 쿡북 코드 예시는 아래와 같은 로컬 환경 경로에 검색 API를 구현하는 것을 전제로 합니다 http://127.0.0.1:8000/ 다음 명령어를 터미널에 입력하면 FastAPI 서버를 실행할 수 있습니다. uvicorn filename:app --reload 2.2 코드 작성 본격적으로 리랭커 기능을 포함한 RAG 시스템 구현 코드를 작성해보겠습니다. 먼저 필수 라이브러리를 임포트 합니다. import requests 예제 코드는 Python 3.11.1에서 실행 확인하였으며, 최소 Python3.7 이상을 필요로 합니다. 간단한 예시를 위해 tqdm 라이브러리는 포함하지 않았지만, 실제 문서의 양이 많아질 경우 진행 상황을 시각적으로 확인할 수 있어 활용하기를 권장합니다. 2.2.1 검색 API 호출 2.1.2에서 구현한 검색 API 호출하여 유저 쿼리와 관련된 문서을 검색해냅니다. def search(query, api_url): headers = { 'accept': 'application/json', 'Content-Type': 'application/json', } json_data = { 'query': query, 'top_k': 5, } response = requests.post(api_url, headers=headers, json=json_data) response.raise_for_status() return [ {"id": str(i+1), "doc": sample["content"]} for i, sample in enumerate(response.json()["result"]) ] result 필드는 문서 객체들을 포함합니다. 각 객체는 다양한 정보를 가지지만, 여기서는 리랭커 함수에 전달하기 위해 id와 doc에 해당하는 필드만 추출합니다. 2.2.2 리랭커 API 호출 2.1.2에서 구현한 검색 API리랭커 API를 호출하여 관련성 높은 정보를 선별하고 그 결과를 요약하여 답변을 생성합니다. def reranker_call(documents, query, api_key, url): headers = { 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' } json_data = { "documents": documents, "query": query, "maxTokens": 3000 } response = requests.post(url, headers=headers, json=json_data) response.raise_for_status() return response.json() documents는 리랭커 API에 전달할 문서 리스트입니다. query는 사용자의 질문으로, 리랭커 API는 query와 전달된 문서들을 바탕으로 적절한 답변을 생성합니다. 요청과 응답을 포함한 리랭커 API에 대한 더욱 자세한 가이드는 [API 가이드] 리랭커를 참고해 주세요. 2.3 리랭커 시나리오 실행 예시 앞서 구성한 RAG 시스템의 전체 로직을 실행시키기 위해, main 함수를 정의하고 다음과 같이 3가지 예시 쿼리로 모델을 실행해 보았습니다. 정의한 함수들을 순서대로 호출하여 답변을 생성합니다. 본 코드에서는 예시로 입력한 3개의 쿼리에 대해 답변을 생성하였습니다. 실제 실행시에는 발급받은 api_key와 서비스에 맞는 적절한 api_url을 입력해줍니다. def main(): api_key = 'API_KEY' search_api_url = 'http://127.0.0.1:8000/search/' # 앞서 구현한 검색 API 기본 주소 reranker_api_url = 'https://clovastudio.stream.ntruss.com/v1/api-tools/reranker' queries = [ "CLOVA STUDIO Instruction 데이터셋으로 활용 가능한 파일 확장자가 어떻게 돼?", "clova studio에서 이용량이 제한되는 수치에는 어떤 게 있나요?", "토큰이 뭔지 모르겠어요..." ] for q in queries: documents = search(q, search_api_url) response = reranker_call(documents, q, api_key, reranker_api_url) print(f"질문: {q}") print(response['result']['result']) print() if __name__ == "__main__": main() 위 코드를 실행하여 얻은 답변은 다음과 같습니다. Quote 질문: CLOVA STUDIO Instruction 데이터셋으로 활용 가능한 파일 확장자가 어떻게 돼? 답변: 답변: CLOVA STUDIO Instruction 데이터셋으로 활용 가능한 파일 확장자는 <doc1>.csv 또는 .jsonl</doc1>입니다. 이 파일들은 <doc1>UTF-8 인코딩 형식</doc1>을 사용하며, <doc1>1TB 이하의 용량</doc1>으로 제한됩니다. 또한, <doc4>CSV 파일의 경우 첫 번째 행에는 'C_ID', 'T_ID', 'Text', 'Completion'이 정확하게 입력되어야 하고, JSONL 파일의 경우 각 행은 {"C_ID": 순서, "T_ID": 순서, "Text": "입력값", "Completion": "원하는 결괏값"}으로 구성되어야 합니다.</doc4> 질문: clova studio에서 이용량이 제한되는 수치에는 어떤 게 있나요? 답변: 답변: CLOVA Studio에서 이용량이 제한되는 수치에는 <doc4>분당 요청 횟수인 QPM(Queries per Minute)과 분당 처리 토큰 수를 의미하는 TPM(Tokens per Minute)</doc4>이 있습니다. 이 두 가지 수치는 <doc1>특정 시간 내에 이용할 수 있는 API 요청 횟수와 토큰 수에 상한선을 두는 이용량 제어 정책</doc1>의 일환으로 관리되며, <doc4>두 개의 값 중 하나라도 최댓값에 먼저 도달하면 오류 코드가 반환됩니다.</doc4> 예를 들어, <doc2>API 응답 헤더를 통해 확인 가능한 정보에는 QPM이 60, TPM이 10,000으로 설정된 경우가 있습니다.</doc2> 이러한 제한은 서비스의 가용성을 유지하고 안정성을 확보하기 위해 필요하며, <doc1>악의적인 API 호출이나 과도한 트래픽으로부터 서비스를 보호하는 역할을 합니다.</doc1> 또한, <doc4>모델 및 도구별로 이용 가능한 최대 QPM과 TPM이 다르며, 예를 들어 HCX-003 모델의 경우 QPM은 60, TPM은 10,000으로 설정되어 있습니다.</doc4> 사용자는 이러한 최대 이용량을 초과하지 않도록 주의해야 하며, <doc3>최대 이용량을 초과할 경우 HTTP 429 코드가 반환되거나 오류 메시지가 나타납니다.</doc3> 따라서, <doc3>API 호출 시 입력한 문자열의 토큰 수를 확인하거나, 결괏값에 사용할 최대 토큰 수를 조정하는 등의 방법으로 이용량을 관리해야 합니다.</doc3> 질문: 토큰이 뭔지 모르겠어요... 답변: 답변: 토큰은 <doc3>자연어 처리를 위해 하나의 단어를 세분화한 단어 조각을 의미합니다.</doc3> 예를 들어, <doc3>'맛있어'라는 표현은 각각 '맛'과 '있어'라는 두 개의 토큰으로 나뉠 수 있습니다.</doc3> 이러한 토큰은 <doc1>HyperCLOVA 언어 모델이 학습한 내용에 맞춰 나누어지며, 동일한 표현이 항상 같은 토큰으로 이루어져 있지는 않습니다.</doc1> 토큰의 개념은 CLOVA Studio와 같은 AI 서비스에서 프롬프트를 처리하고 결과를 생성하는 데 중요한 역할을 합니다. 3. 결론 본 쿡북에서는 리랭커를 활용하여 RAG 시스템의 검색 정확도를 높이고 간편하게 RAG 시스템을 구성하는 방법에 대해 알아봤습니다. 하지만 리랭커 API를 통해 간단하게 구현한 RAG 구조로는 모든 시나리오에 대응할 수 있는 것은 아니며 다음과 같은 제약 사항을 지니고 있습니다. 1) 싱글 쿼리에 적합: 리랭커는 주로 싱글 쿼리에 대한 RAG 답변 생성에 적합합니다. 2) 제한된 멀티 쿼리, 멀티 턴 구현: 리랭커는 검색 결과의 품질을 높이는 데 기여하지만, 모든 시나리오에 완벽하게 대응하는 것은 아닙니다. 매번 새로운 질문을 개별적으로 처리하는 단일 호출 방식으로는 이전 대화의 맥락을 연결하거나 여러 질문을 동시에 처리하기가 어렵습니다. 즉, 이런 복잡한 대화의 흐름인 멀티 쿼리나 멀티 턴 대화를 구현하기 위해서는 리랭커 API 단독 활용으로는 충분하지 않습니다. 그렇기에 이전 질문과 답변, 대화의 맥락 등을 이해하고 이를 기반으로 새로운 검색어를 생성하거나 대화의 흐름을 이어갈 수 있는 구현 방법이 필요합니다. 싱글 쿼리 : 유저의 인텐트가 하나이고, 한 번의 검색으로 답을 찾을 수 있는 단일 요청인 케이스 멀티 쿼리 : 유저의 인텐트가 두 개 이상이거나, 답을 찾는데 여러번의 검색이 필요한 케이스 멀티 턴 : 유저와 시스템 간 여러 차례 질문과 답변이 오가며 대화의 맥락이 이어지는 케이스 실제로 CS 문의를 대응하는 상황에서는 두 개 이상의 요청을 포함하는 멀티 쿼리가 빈번하게 발생할 수 있으므로, 유저의 의도를 정확히 파악하고 여러 단계의 질문과 답변을 통해 문제를 해결하는 RAG Reasoning 모델과의 체이닝 기법이 필수적입니다. 해당 내용은 멀티턴, 멀티 쿼리 CS 시나리오를 위한 Advanced RAG 시스템 구현하기 쿡북에서 다뤄보도록 하겠습니다. 링크 복사 다른 사이트에 공유하기 More sharing options...
Recommended Posts
게시글 및 댓글을 작성하려면 로그인 해주세요.
로그인