Sign in to save your progressYou can keep reading without an account, but completed lessons won't be saved.
Sign in

이제 RAG 흐름을 개념적으로 이해했으니, 실제 예제를 사용하여 단계별로 구현해 보겠습니다. 텍스트 청킹부터 사용자 쿼리에 대한 관련 문서 찾기까지, RAG 프로세스의 다섯 단계를 모두 살펴보겠습니다.

벡터 데이터베이스 설정하기

이번 구현에서는 임베딩을 저장하고 검색하는 데 필요한 기본 기능을 제공하는 커스텀 VectorIndex 클래스를 사용합니다. 이 클래스는 벡터 저장, 거리 계산(코사인 유사도 사용), 문서 검색을 처리합니다.

5단계 RAG 구현

RAG 프로세스의 각 단계를 살펴보겠습니다:

1단계: 섹션별로 텍스트 청킹하기

먼저, 원본 문서를 관리 가능한 청크로 나눠야 합니다. 앞서 사용했던 섹션 기반 청킹 방식을 동일하게 사용하겠습니다:

python
chunks = chunk_by_section(text)

이렇게 하면 report.md 파일이 개별적으로 처리할 수 있는 논리적 섹션으로 분할됩니다.

2단계: 각 청크에 대한 임베딩 생성하기

다음으로, 각 텍스트 청크를 해당 텍스트의 의미를 담아내는 수치 임베딩으로 변환합니다:

python
embeddings = generate_embedding(chunks)

이러한 임베딩을 통해 서로 다른 텍스트 조각 간의 수학적 비교를 수행할 수 있습니다.

3단계: 벡터 데이터베이스에 임베딩 저장하기

이제 벡터 스토어를 생성하고 임베딩과 관련 텍스트로 채워 넣습니다:

python
store = VectorIndex()

for embedding, chunk in zip(embeddings, chunks):
    store.add_vector(embedding, {"content": chunk})

임베딩과 원본 텍스트 콘텐츠를 모두 저장한다는 점에 주목하세요. 이는 매우 중요한데, 나중에 유사한 임베딩을 검색할 때 숫자 벡터뿐만 아니라 실제 텍스트에도 접근해야 하기 때문입니다. 임베딩 자체만으로는 개발자인 우리에게 유용하지 않습니다 - 임베딩이 나타내는 사람이 읽을 수 있는 콘텐츠가 필요합니다.

4단계: 사용자 쿼리에 대한 임베딩 생성하기

사용자가 질문을 하면, 해당 쿼리를 저장된 문서와 동일한 임베딩 공간으로 변환해야 합니다:

python
user_embedding = generate_embedding("What did the software engineering dept do last year?")

5단계: 관련 문서 검색하기

마지막으로, 벡터 스토어를 검색하여 가장 관련성 높은 청크를 찾습니다:

python
results = store.search(user_embedding, 2)

for doc, distance in results:
    print(distance, "\n", doc["content"][0:200], "\n")

이렇게 하면 코사인 거리 점수와 함께 가장 유사한 두 개의 청크가 반환됩니다.

위 다이어그램은 벡터 데이터베이스가 사용자 쿼리를 처리하는 방식을 보여줍니다. 질문을 하면 해당 질문이 임베딩 벡터로 변환되고, 데이터베이스는 고차원 공간에서 그 벡터와 "가장 가까운" 저장된 벡터를 찾습니다.

결과 이해하기

소프트웨어 엔지니어링 부서에 관한 쿼리로 이 예제를 실행하면, 관련성 있는 두 개의 섹션을 얻게 됩니다:

  • 섹션 2: 소프트웨어 엔지니어링 - Project Phoenix 안정성 개선 (거리: 0.71)
  • 방법론 섹션 (거리: 0.72)

거리 점수가 낮을수록 콘텐츠가 쿼리와 더 유사합니다. 두 결과 모두 소프트웨어 엔지니어링 부서가 달성한 성과에 관한 우리의 질문과 관련이 있습니다.

임베딩과 함께 콘텐츠를 저장하는 이유

각 임베딩과 함께 원본 텍스트를 저장하는 이유가 궁금할 수 있습니다. 그 이유는 실용적입니다: 임베딩은 단지 숫자 배열일 뿐이며 사람에게는 직접적인 의미가 없습니다. 검색이 가장 유사한 임베딩을 반환할 때, 무엇이 발견되었는지 이해하고 이를 응답 생성에 활용하기 위해서는 실제 텍스트 콘텐츠가 필요합니다.

일부 구현에서는 원본 텍스트를 가리키는 ID만 저장하지만, 단순화를 위해 여기서는 각 벡터와 함께 콘텐츠를 직접 저장합니다.

다음 단계

이 구현은 핵심 RAG 워크플로를 다루지만, 여전히 개선할 수 있는 부분이 있습니다. 실제 애플리케이션에서는 이 기본적인 접근 방식이 예상대로 작동하지 않는 상황을 마주할 수 있으며, 다음 섹션에서 이러한 개선 사항들을 살펴보겠습니다.