Milvus, LangChain, OpenAI LLM으로 다국어 RAG 구축하기
지난 2년 동안 검색 증강 생성(RAG)은 대규모 언어 모델(LLM)로 구동되는 GenAI 애플리케이션 구축에 있어 가장 인기 있는 기술 중 하나로 급부상했습니다. RAG의 핵심은 모델이 사전 학습되지 않은 문맥 정보를 제공함으로써 LLM의 출력을 향상시키는 것입니다. 다국어 RAG는 여러 언어로 된 텍스트 데이터를 처리하는 확장된 RAG입니다.
최근 질리즈가 주최한 비정형 데이터 밋업에서 OSS4AI의 CEO인 Yujian Tang이 연사로 나섰습니다. 그는 RAG와 그 기본 구성 요소에 대해 논의하고 다양한 실제 언어 문제를 해결하기 위해 다국어 RAG를 구축하는 방법을 시연했습니다.
이 글에서는 Yujian의 프레젠테이션에서 얻은 핵심 인사이트를 요약하고 다국어 RAG를 구현하는 방법을 안내합니다. Yujian의 강연에 대해 더 자세히 알고 싶으시다면 YouTube에서 프레젠테이션을 시청하는 것을 추천합니다.
RAG란 무엇이며 어떻게 작동하나요?
LLM 기반 애플리케이션의 한 가지 핵심적인 한계는 학습된 데이터에 의존한다는 점입니다. 사전 학습 중에 특정 정보나 전체 지식 영역에 노출되지 않은 LLM은 정확한 응답을 생성하는 데 필요한 언어적 관계를 이해하지 못합니다. 이러한 데이터 부족은 LLM이 답을 모른다고 인정하거나, 더 심하게는 "환각"을 일으켜 잘못된 정보를 제공할 수 있습니다.
RAG는 추가적인 문맥 정보를 제공함으로써 LLM의 환각 문제를 해결하는 데 널리 사용되는 기술입니다. 또한 개발자와 기업이 보안 문제에 대한 걱정 없이 개인 또는 독점 데이터를 활용할 수 있게 해줍니다.
그림 1- RAG의 작동 원리](https://assets.zilliz.com/Figure_1_How_RAG_works_246044aacf.png)
RAG는 텍스트 데이터를 텍스트의 의미적 의미를 포착하는 수치 표현인 벡터 임베딩으로 변환하는 임베딩 모델로 시작합니다. 그런 다음 RAG 시스템은 이러한 벡터를 Milvus 또는 Zilliz Cloud와 같은 벡터 데이터베이스에 저장하여 유사성 검색을 위해 색인을 생성합니다.
사용자가 쿼리를 제출하면 임베딩 모델도 입력을 벡터로 변환합니다. 그런 다음 RAG 시스템은 고차원 벡터 공간에서 거리를 계산하여 이 쿼리 벡터와 벡터 데이터베이스에 있는 벡터의 유사도를 비교합니다. 관련 데이터가 발견되면 RAG 시스템은 이 정보를 검색하여 원래 쿼리에 추가하여 LLM에 대한 새로운 프롬프트를 구성합니다. LLM은 이 추가 정보를 사용하여 학습 데이터만으로 생성할 수 있는 것보다 더 정확하고 맥락에 맞는 응답을 생성합니다.
다국어 RAG란 무엇인가요?
다국어 RAG는 기존 RAG의 기능을 확장하여 여러 언어를 지원합니다. 다양한 언어로 학습된 임베딩 모델을 통합하여 시스템이 여러 언어에 걸쳐 응답을 처리하고 생성할 수 있도록 합니다. 이러한 다국어 접근 방식을 통해 RAG 시스템은 모든 언어로 된 쿼리를 처리하고, 원래 언어에 관계없이 관련 정보를 검색하며, 사용자가 선호하는 언어로 문맥에 맞는 정확한 답변을 제공할 수 있습니다.
다국어 RAG 애플리케이션을 구축하는 방법: 단계별 가이드
이제 RAG의 핵심 개념과 구성 요소를 배웠으니 다국어 RAG 애플리케이션을 단계별로 구현해 보겠습니다.
이 예제 애플리케이션은 웹 스크레이퍼와 기본 애플리케이션의 두 부분으로 구성되어 있습니다.
웹 스크레이퍼**는 인터넷에서 필요한 데이터 세트를 스크랩합니다.
메인 애플리케이션**은 벡터 임베딩을 생성하고, 벡터 유사도 검색을 수행하며, 답을 생성합니다.
웹 스크레이퍼
먼저, Wikipedia에서 데이터를 스크랩하여 이 RAG 예제의 컨텍스트 정보로 사용하겠습니다.
제목 정의하기:** 먼저 도시 목록이 들어 있는 'wiki_titles'라는 목록을 정의합니다. 각 도시는 웹 스크래퍼가 해당 위키백과 항목의 콘텐츠로 채울 텍스트 파일을 나타냅니다. 예를 들어, 'Atlanta.txt'에는 Wikipedia의 애틀랜타 페이지에서 스크랩한 텍스트가 포함됩니다.
데이터 스크래핑하기:
위키 제목의 각 도시를 반복하여 Wikipedia API에 GET 요청을 하고 JSON 응답에서 페이지 콘텐츠를 추출합니다. 그런 다음 텍스트는 각 도시에 해당하는 텍스트 파일에 저장됩니다.
경로 라이브러리에서 경로 가져오기
가져오기 요청
위키 제목 = [
"애틀랜타",
"Berlin",
"Boston",
"카이로",
"Chicago",
"코펜하겐",
"Houston",
"카라치",
"리스본",
"London",
"모스크바",
"Munich",
"파리",
"페킨", # 베이징의 프랑스어
"샌프란시스코",
"시애틀",
"상하이",
"도쿄"
"토론토",
]
data_path = Path("./french_city_data")
data_path.mkdir(exist_ok=True) # 디렉터리 존재 여부 확인
디렉터리가 있는지 확인합니다:
응답 = 요청.get(
"https://fr.wikipedia.org/w/api.php",
params={
"action": "쿼리",
"format": "json",
"titles": 제목,
"prop": "추출",
"설명 텍스트": True,
},
).json()
page = next(iter(response["query"]["pages"].values()))
wiki_text = page.get("extract", "") # 키 오류를 피하려면 .get()을 사용하세요.
를 피하려면 .get()을 사용하세요: # 추출이 비어 있지 않은지 확인
열다(데이터_경로 / f"{title}.txt", "w")를 fp로 사용합니다:
fp.write(wiki_text)
else:
print(f"{title}에 대한 추출을 찾을 수 없습니다.")
환경 준비하기
먼저, 필요한 라이브러리인 밀버스 벡터 데이터베이스, LangChain, OpenAI, 문장 변환기를 설치하여 개발 환경을 설정합니다.
또한 OpenAI와 같은 API를 통해 LLM에 연결할 경우 API 키를 포함해야 합니다. 이 키는 별도의 .env 파일에 저장하고 load_dotenv() 및 os를 사용하여 액세스할 수 있습니다.
다음은 라이브러리를 설치하고 API 키를 로드하는 코드입니다:
!.pip 설치 -qU pymilvus 랭체인 문장-변환기 토큰 토큰 오픈아이
닷텐브이에서 load_dotenv를 가져옵니다.
import os
load_dotenv() # .env 파일에서 환경 변수를 로드합니다.
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY") # API 키 설정
라이브러리 설치하기:
pip을 사용하여pymilvus,랑체인,sentence-transformers,tiktoken및openai를 설치합니다.환경 변수 로드하기:**
.env파일에서 환경 변수를 로드하려면dotenv를 사용합니다.API 키 설정:** 환경 변수에서 OpenAI API 키를 가져와 설정합니다.
.env` 파일에 다음 형식의 OpenAI API 키가 포함되어 있는지 확인합니다:
OPENAI_API_KEY=your_api_key_here
LLM 초기화 중 ###
환경이 설정되었으면 다음 단계는 애플리케이션 내에서 사용할 LLM을 정의하는 것입니다. 아래 코드 스니펫에서는 OpenAI 라이브러리를 임포트하고 OpenAI의 생성자로 LLM을 정의하여 이를 수행합니다.
langchain.llms에서 OpenAI 가져오기
llm = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
오픈 소스 LLM을 선택하면 OpenAI API 호출과 관련된 비용을 피할 수 있습니다. Hugging Face는 실험할 수 있는 수십만 개의 딥러닝 모델을 제공합니다. 허깅페이스에서 오픈 소스 LLM을 사용하려면 트랜스포머 라이브러리를 가져와야 합니다.
에서 트랜스포머 가져오기 파이프라인
llm = pipeline('text-generation', model='gpt2') # 'gpt2'를 원하는 모델로 바꿉니다.
관련 가져오기 및 초기화 코드를 수정하여 OpenAI와 오픈 소스 모델 간에 전환할 수 있습니다.
적절한 임베딩 모델 선택하기
다국어 RAG 시스템을 구축할 때는 임베딩 모델이 작업 중인 언어와 호환되어야 하므로 임베딩 모델 선택이 LLM 선택만큼이나 중요합니다. 언어가 프랑스어인 이 예시의 경우, 기본 HuggingFace 임베딩으로 충분합니다. 그러나 다른 언어에 대해서는 가장 적합한 임베딩 모델을 찾아서 사용해야 합니다.
허깅페이스의 MTEB 리더보드는 임베딩 모델을 찾는 데 유용한 리소스입니다. 이 리더보드에는 중국어 및 폴란드어 임베딩과 같이 다양한 언어에 대한 최고 성능의 임베딩 모델이 나열되어 있습니다. 임베딩 모델을 선택할 때는 모델 이름을 파라미터로 지정해야 합니다.
임베딩 모델을 설정하는 방법은 다음과 같습니다:
langchain_community.embeddings에서 허깅페이스임베딩 가져오기
embeddings = 허깅페이스임베딩()
# 또는 중국어 임베딩의 경우 # 모델을 매개변수로 전달합니다(예: 다음과 같이),
# HuggingFaceEmbeddings(model_name="TownsWu/PEG")
데이터 로드 및 청크로 분할하기
다음으로, Wikipedia에서 스크랩한 도시 데이터 파일을 로드하고 세그먼트 또는 청크로 나눕니다. 텍스트를 청크로 나누면 쿼리를 전체 문서와 비교하지 않아도 되므로 정보 검색의 효율성이 향상됩니다. 청크는 chunk_size 매개변수에 의해 결정되며, 청크가 작을수록 정확도는 높아지지만 더 많은 검색 작업이 필요합니다. 청크 간 겹침이 많을수록 chunk_overlap으로 정의된 대로 중복성이 증가하는 대신 컨텍스트 손실 가능성이 줄어듭니다.
langchain.text_splitter에서 CharacterTextSplitter 임포트
langchain.schema에서 Document
files = os.listdir("./french_city_data")
file_texts = []
파일 내 파일의 경우:
열다(f"./french_city_data/{file}")를 f로 사용합니다:
file_text = f.read()
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
청크_크기=512, 청크_오버랩=64,
)
텍스트 = text_splitter.split_text(file_text)
for i, chunked_text in enumerate(texts):
file_texts.append(Document(page_content=chunked_text,
metadata={"doc_title": file.split(".")[0], "chunk_num":i}))
밀버스에 문서 로드하기
도시 데이터 파일을 청크화하여 문서 목록으로 저장한 후에는 이를 벡터 저장소(이 경우 Milvus 벡터 데이터베이스)에 로드해야 합니다. 아래 코드는 도시 데이터가 Milvus에 저장될 때 초기 로드 및 업데이트를 처리합니다.
langchain_community.vectorstores에서 Milvus를 가져옵니다.
# 첫 번째 실행의 경우
vector_store = Milvus.from_documents(
파일_텍스트,
임베딩 = 임베딩,
connection_args={"host": "localhost", "port": 19530},
collection_name="french_cities"
)
# 데이터가 이미 Milvus에 저장되어 있는 경우
벡터 저장소 = Milvus(
임베딩_함수 = 임베딩,
connection_args={"host": "localhost", "port": 19530},
collection_name="프랑스 도시"
)
리트리버 생성
다음으로, 주어진 쿼리에 따라 특정 소스에서 문서를 반환하는 인터페이스인 리트리버를 초기화하겠습니다. 아래 코드는 지난 단계에서 만든 벡터 저장소를 리트리버로 사용하고 이를 변수에 할당합니다.
retriever = vector_store.as_retriever()
LangChain을 사용하여 프롬프트 템플릿 만들기
프롬프트 템플릿을 사용하면 애플리케이션 내에서 입력 형식을 LLM에 정확하게 지정할 수 있습니다. 특히 다양한 언어에 동일한 프롬프트 템플릿을 사용할 수 있는 다국어 RAG 애플리케이션처럼 동일한 프롬프트 개요를 재사용하되 약간의 조정을 가하고 싶은 경우에 유용합니다.
프롬프트 템플릿을 사용하면 사용자 입력이나 벡터 스토어에서 검색된 데이터와 같은 동적 입력으로 프롬프트를 구성할 수도 있습니다. 저희 애플리케이션에서는 체인에 직접 전달되는 질문과 벡터 스토어에서 가져온 컨텍스트를 동적으로 포함할 것입니다.
langchain.prompts에서 채팅 프롬프트 템플릿 가져오기
template="""
여러분은 질문 답변 작업의 어시스턴트입니다. 검색된 다음 문맥을 사용하여 질문에 답하세요. 답을 모른다면 모른다고 말하세요.
답변은 최대 세 문장으로 간결하게 작성하세요.
프랑스어로 답하세요.
질문: 질문: {질문}
문맥: 문맥: {문맥}
Answer:"""
prompt = ChatPromptTemplate.from_template(template)
컴포넌트들을 서로 연결하여 RAG 애플리케이션 만들기
체인화는 구성 요소를 연결하여 엔드투엔드 AI 애플리케이션을 생성하는 과정으로, 랭체인의 핵심 기능 중 하나입니다.
아래 코드는 리트리버의 컨텍스트, runnablepassthrough() 함수가 처리하는 입력 프롬프트, 프롬프트 템플릿, LLM, 체인 호출의 응답을 출력하는 stroutparser() 등의 요소를 포함하는 체인을 구성하는 방법을 보여줍니다.
langchain_core.runnables에서 RunnablePassthrough를 가져옵니다.
langchain_core.output_parsers에서 StrOutputParser를 임포트합니다.
체인 = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
체인으로 쿼리 만들기
체인이 구성되면 다양한 쿼리로 체인을 호출할 수 있습니다. 예를 들어
response = chain.invoke("카라치에 대한 역사적 사실을 알려주세요.")
이 쿼리는 프랑스어로 다음과 같은 응답을 반환합니다!
"카라치가 처음 언급된 것은 3세기경의 테오프라스테의 식물에 대한 역사에서입니다. J.-C. 엘레는 1839년 영국에 의해 점령되었고 1839년 신드의 수도가 되었습니다. 1876년 미래의 파키스탄 건국자인 무하마드 알리 진나가 태어나 카라치에 입성했습니다."
다국어 기능을 보여주기 위해 이번에는 프랑스어로 된 또 다른 쿼리가 있습니다:
response_2 = chain.invoke("Racontez-moi un fait historique sur Karachi.")
기본 질문은 동일하지만 언어(영어와 프랑스어)가 다르기 때문에 임베딩이 달라져 서로 다른 출력이 나옵니다:
"카라치는 16세기 초 영국인에 의해 세워졌으며 신드의 수도가 된 도시입니다. 중요한 경제 중심지였으며 특히 항구 덕분에 급속한 성장을 이룩했습니다. 1980년대 이후 이 도시는 민족적, 종교적 분쟁의 중심지였으며 2012년에는 역사상 가장 심각한 산업 화재의 현장이 되었습니다."
축하합니다! 다국어 RAG 애플리케이션을 성공적으로 구축하셨습니다. 임베딩은 LLM이 언어를 해석하는 방법의 핵심이라는 점을 명심하세요. 여러 언어를 지원하는 데 가장 적합한 임베딩을 선택하여 애플리케이션에 통합하세요.
요약
와우! 꽤 긴 글입니다. 몇 가지 핵심 사항을 요약해 보겠습니다.
검색 증강 생성](https://zilliz.com/learn/Retrieval-Augmented-Generation)(RAG)은 입력 프롬프트에 추가 데이터를 삽입하여 LLM 출력을 증강하는 프레임워크입니다. RAG는 성가신 LLM 환각 문제를 해결할 수 있습니다.
다국어 RAG는 다국어 문서를 처리하는 확장된 RAG입니다.
임베딩 모델, 벡터 데이터베이스, LLM은 RAG 애플리케이션의 세 가지 핵심 구성 요소입니다.
다국어 RAG 애플리케이션을 개발할 때 가장 중요한 고려 사항은 임베딩 모델의 선택입니다. 허깅페이스의 MTEB 리더보드는 애플리케이션에 적합한 모델을 찾는 데 훌륭한 리소스입니다.
추가 리소스
유이잔 탕의 유튜브 프레젠테이션 전문](https://www.youtube.com/watch?v=UhRD_ALzAnU&list=PLPg7_faNDlT5F_6J8jjFSMw-Ars_ogtZk&index=28)
RAG 향상 기술:
RAG 파이프라인의 성능을 향상시키는 방법](https://zilliz.com/learn/how-to-enhance-the-performance-of-your-rag-pipeline)
RAG 애플리케이션을 구축하는 개발자를 위한 실용적인 팁과 요령](https://zilliz.com/blog/praticial-tips-and-tricks-for-developers-building-rag-applications)
계속 읽기

How Zilliz Saw the Future of Vector Databases—and Built for Production
An inside look at how Zilliz built vector databases for real-world use, focusing on scalability, stability, and running them reliably at scale.

Cosmos World Foundation Model Platform for Physical AI
NVIDIA's Cosmos platform enables safe, digital twin training of GenAI models for physical applications, overcoming data scarcity and safety challenges.

Empowering Innovation: Highlights from the Women in AI RAG Hackathon
On January 25, 2025, the inaugural Women in AI RAG Hackathon brought together a diverse group of women technologists at Stanford University
