시작하며
현대 채용 플랫폼에서는 방대한 데이터를 효율적으로 활용하면서도 맞춤형 결과를 제공하는 것이 점점 중요해지고 있습니다. 기존의 검색 엔진이나 AI 모델만으로는 제한이 많았던 문제를 해결하기 위해 등장한 기술 중 하나가 RAG(Retrieval-Augmented Generation)입니다. 이번 글에서는 RAG의 개념과 이를 활용한 채용 시스템 구축 방법을 알아보고, Python과 OpenAI의 GPT를 사용한 간단한 예제를 소개하겠습니다.
Retrieval-Augmented Generation
RAG(Retrieval-Augmented Generation)는 대규모 언어 모델(LLM)의 한계를 극복하기 위해 제안된 새로운 자연어 처리 기술입니다. 기존의 언어 모델들이 생성하는 텍스트의 정확성을 높이기 위한 방법으로 등장한 RAG는, 사용자가 제공한 질문에 대해 외부 데이터를 실시간으로 검색하고 그 정보를 바탕으로 텍스트를 생성하는 방식으로 작동합니다.
RAG의 등장 배경
기존의 언어 모델들은 훈련된 데이터셋에 기반하여 텍스트를 생성합니다. 그러나 이들은 고정된 데이터셋을 바탕으로 학습되기 때문에, 새로운 정보나 실시간으로 변화하는 지식을 반영하기 어렵습니다. 예를 들어, 최근 뉴스나 특정 분야의 최신 정보에 대해 답변할 때, 훈련된 데이터에 포함되지 않은 정보는 제대로 처리할 수 없습니다.
RAG는 이러한 한계를 극복하기 위해 등장했습니다. RAG는 외부 데이터베이스나 지식베이스에서 실시간으로 정보를 검색하고, 그 정보를 바탕으로 답변을 생성할 수 있도록 설계되었습니다. 이를 통해 최신 정보나 그동안 모델이 학습하지 못한 정보도 활용할 수 있게 되어, 더 정확하고 동적인 텍스트 생성이 가능해졌습니다.
RAG의 기본 개념
RAG 모델은 두 가지 주요 구성 요소를 중심으로 작동합니다:
•
검색기 (Retriever): 사용자가 입력한 텍스트를 바탕으로 관련된 정보를 외부에서 검색합니다. 이 정보는 미리 구축된 대규모 문서 코퍼스나 지식베이스에서 검색될 수 있습니다.
•
생성기 (Generator): 검색된 정보를 바탕으로 자연스러운 언어를 생성합니다. 생성기는 일반적으로 GPT나 BERT 기반의 언어 모델을 사용합니다.
이 두 가지 구성 요소가 결합되어, RAG는 검색과 생성 두 가지 작업을 동시에 수행할 수 있는 능력을 가지고 있습니다.
RAG의 동작 과정
RAG 모델은 크게 네 가지 주요 단계로 작동합니다:
1.
입력: 사용자가 질문이나 텍스트를 입력합니다. 이 입력은 모델의 검색기와 생성기에 중요한 역할을 합니다.
2.
정보 검색: 입력된 텍스트를 기반으로 검색기가 관련된 정보를 외부 데이터베이스나 지식베이스에서 실시간으로 검색합니다. 검색기는 보통 입력 텍스트와 관련된 문서들을 빠르게 찾아냅니다.
3.
생성: 검색된 정보를 바탕으로 생성기가 자연스러운 텍스트를 생성합니다. 이 과정에서 생성기는 검색된 정보뿐만 아니라, 입력된 텍스트도 반영하여 답변을 생성합니다.
4.
출력: 최종적으로 생성된 텍스트가 사용자에게 출력됩니다. 이 텍스트는 검색된 정보를 기반으로 생성된 답변이 됩니다.
이렇게 RAG는 정보 검색과 텍스트 생성을 결합하여, 기존의 생성 모델들이 갖는 정보의 한계를 극복하고, 더 많은 외부 지식을 활용할 수 있게 합니다.
코드 예시
아래는 Python과 OpenAI GPT를 사용해 RAG 기반 채용 챗봇을 구현한 예제입니다. 이 챗봇은 사용자가 입력한 직무 요구 사항에 따라 적합한 후보자를 추천합니다.
1단계: 데이터 준비
먼저, 후보자들의 프로필 데이터를 준비하고 이를 임베딩(벡터화)하여 검색 가능한 형태로 만듭니다. 이 작업은 SentenceTransformer를 사용하여 수행합니다.
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
profiles = [
"React 3년 경험, TypeScript 2년, 프론트엔드 프로젝트 다수",
"Python과 Django로 백엔드 개발, Flask 프로젝트 3건",
"TensorFlow와 PyTorch로 머신러닝 모델 구축 경험 5년"
]
embedding_model = SentenceTransformer('bert-base-multilingual-cased')
profile_embeddings = embedding_model.encode(profiles)
Python
복사
•
SentenceTransformer 모델을 사용하여 후보자 프로필을 임베딩 벡터로 변환합니다.
•
각 프로필은 해당 스킬셋, 경력 등을 설명하는 텍스트로 되어 있습니다.
2단계: 정보 검색
FAISS 인덱스를 사용하여 임베딩된 프로필 데이터로 인덱스를 생성하고, 직무 요구 사항에 가장 적합한 후보자를 검색합니다.
dimension = profile_embeddings.shape[1] # 임베딩 벡터 차원
index = faiss.IndexFlatL2(dimension) # L2 거리 기준으로 검색
index.add(profile_embeddings) # 후보자 벡터 추가
def retrieve_candidates(job_description, top_k=3):
"""
직무 요구 사항에 가장 적합한 상위 N명의 후보자를 검색합니다.
"""
job_embedding = embedding_model.encode([job_description]) # 직무 요구 사항 벡터화
distances, indices = index.search(job_embedding, top_k) # 상위 N명 후보 검색
return [(profiles[i], distances[0][idx]) for idx, i in enumerate(indices[0])]
Python
복사
•
FAISS 인덱스를 사용하여 빠르게 유사한 후보자를 검색합니다.
•
retrieve_candidates 함수는 직무 요구 사항을 입력받고, 가장 유사한 상위 N명의 후보자를 검색하여 반환합니다.
3단계: 생성
검색된 후보자 데이터를 바탕으로 GPT 모델을 사용하여, 가장 적합한 후보자를 추천하는 자연어 응답을 생성합니다.
from openai import OpenAI
# OpenAI API 키 설정
api_key = "your-openai-api-key"
# OpenAI 객체 생성
client = OpenAI(api_key=api_key)
def generate_gpt_response(job_description, candidates):
"""
GPT를 사용해 검색된 후보자 중 적합한 인재를 추천.
"""
candidate_descriptions = "\n".join(
[f"{i+1}. {candidate[0]} (유사도: {candidate[1]:.2f})" for i, candidate in enumerate(candidates)]
)
prompt = f"""
직무 요구 사항: {job_description}
후보자 목록: {candidate_descriptions}
가장 적합한 후보자를 추천하고 그 이유를 설명해주세요.
"""
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt}
]
)
# 결과 출력
return completion.choices[0].message['content'].strip()
Python
복사
•
GPT 모델을 사용하여 직무 요구 사항과 검색된 후보자 목록을 기반으로 가장 적합한 후보자를 추천하고, 그 이유를 자연어로 생성합니다.
4단계: 시스템 통합
마지막으로, 사용자 인터페이스를 만들어 사용자와 상호작용할 수 있는 챗봇을 구성합니다. 사용자가 직무 요구 사항을 입력하면, 시스템이 적합한 후보자를 추천합니다.
def chat():
"""
RAG 기반 챗봇 인터페이스.
"""
print("직무 요구 사항을 입력하면 적합한 후보자를 추천해 드립니다.")
print("종료하려면 'exit'를 입력하세요.")
while True:
job_description = input("\n직무 요구 사항을 입력하세요: ")
if job_description.lower() == "exit":
print("챗봇을 종료합니다.")
break
candidates = retrieve_candidates(job_description)
response = generate_gpt_response(job_description, candidates)
# 결과 출력
print("\n[추천 결과]")
print(response)
if __name__ == "__main__":
chat()
Python
복사
•
chat 함수는 사용자에게 직무 요구 사항을 입력받고, 그에 맞는 후보자를 추천하는 과정입니다.
•
사용자가 직무를 입력하면, 해당 직무에 맞는 후보자를 검색하고, GPT 모델을 통해 추천 이유를 생성하여 출력합니다.
실행 예시
1.
프로그램 시작
직무 요구 사항을 입력하면 적합한 후보자를 추천해 드립니다.
종료하려면 'exit'를 입력하세요.
Shell
복사
2.
사용자 입력: 직무 요구 사항
직무 요구 사항을 입력하세요: Python 백엔드 개발자
Shell
복사
3.
출력
[추천 결과]
1. Python과 Django로 백엔드 개발, Flask 프로젝트 3건 (유사도: 0.92)
이 후보자는 Python과 Django에서의 경험이 풍부하여, 해당 직무에서 요구하는 기술 스택에 적합합니다. 다른 후보자들보다 직무에 더 근접한 기술 경험을 보유하고 있습니다.
Shell
복사
4.
종료
직무 요구 사항을 입력하세요: exit
챗봇을 종료합니다.
Shell
복사
마치며
RAG는 단순한 검색 시스템을 넘어선 가능성을 제공합니다. 검색과 생성 능력을 결합함으로써 채용 담당자에게 더욱 유용하고 직관적인 검색 결과를 제공할 수 있습니다.
참고문헌
•
Lewis, P., Perez, E., Piktus, A., Petroni, F., Karpukhin, V., Goyal, N., ... & Kiela, D. (2020). Retrieval-augmented generation for knowledge-intensive nlp tasks. Advances in Neural Information Processing Systems, 33, 9459-9474.
•
Gao, Y., Xiong, Y., Gao, X., Jia, K., Pan, J., Bi, Y., ... & Wang, H. (2023). Retrieval-augmented generation for large language models: A survey. arXiv preprint arXiv:2312.10997.