본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 04. 01:36

26/06/04 AI를 이용한 0부터 시작하는 개인 개발 공부 with AI Day4

요약

numpy 라이브러리를 활용하여 외부 벡터 데이터베이스 없이 간이 벡터 검색 엔진을 구축하는 실전 RAG 구현 과정을 다룹니다. 텍스트 청킹, 임베딩, 코사인 유사도 계산을 통해 질문과 가장 유사한 문맥을 찾아내는 원리를 학습합니다.

핵심 포인트

  • numpy를 이용한 경량 벡터 검색 엔진 구현
  • 텍스트 청킹 및 임베딩의 개념 이해
  • 코사인 유사도를 활용한 문장 간 의미적 근접성 계산
  • Ollama와 Qwen 모델을 연동한 실전 RAG 워크플로우

안녕하세요. 이번에는 4일째입니다. 오늘은 지난번의 RAG 구축에 이어, 「벡터 검색 (Embedding)을 사용한 보다 실전적인 RAG 구축」을 진행하겠습니다. 외부의 벡터 데이터베이스 (Vector Database)를 사용하면 무거우므로, 행렬·벡터 계산이 가능한 라이브러리 numpy를 사용하여 간이 벡터 검색 엔진을 구축합니다.

RAG의 기초 지식은 지난번 기사에 있습니다.

청크 분할 (Chunking): RAG에서 사용할 참고 자료를 의미 있는 덩어리(문장 단위)로 나눈다.

임베딩 (Embedding): 각 문장을 다차원 벡터 (숫자 배열)로 변환한다. (이번에는 Ollama에 기본적으로 있는 기능을 사용합니다)

벡터 검색 (유사도 계산): 사용자의 질문도 벡터화하여, 벡터의 「방향(의미)」이 가장 가까운 문장을 행렬 계산으로 찾아낸다.

먼저, 이번에 사용할 라이브러리 numpy를 설치합니다.

pip install numpy

다음으로 프로그램 main.py와 참조할 자료("강의 노트"라고 부름) lecture_note.txt를 같은 폴더 내에 생성합니다. 이번 참조 자료는 일부러 「전혀 관계없는 잡다한 정보」를 섞은 긴 구성으로 만듭니다.

인공지능 (AI)의 역사는 1950년대부터 시작되었습니다.
아카디아 프로토콜이란, 2026년에 개발된 양자 컴퓨터 내성을 가진 새로운 암호화 통신 프로토콜이다.
오늘 점심은 토마토 파스타와 닭고기, 샐러드를 먹었습니다.
...

main.py에는 지난번 프로그램에 추가 및 변경을 가하여, 주로

  • ① 텍스트를 벡터로 변환하는 함수
  • ② 두 벡터의 「코사인 유사도 (Cosine Similarity)」를 계산하는 함수
  • ③ 참고 자료(강의 노트)를 한 줄씩 「청크 (Chunk)」로 분할하여 읽어오는 부분

를 만듭니다.

def get_embedding(text):
response = ollama.embeddings(
model='qwen2.5:3b', # 임베딩 모델로도 Qwen을 사용
...
def cosine_similarity(v1, v2):
# 코사인 유사도 = (A·B) / (||A|| * ||B||)
dot_product = np.dot(v1, v2)
...
with open(filepath, "r", encoding="utf-8") as f:
chunks = [line.strip() for line in f.readlines() if line.strip()]

최종적인 프로그램 전체는 다음과 같습니다.

import ollama
import numpy as np
# 1. Ollama를 사용하여 텍스트를 벡터 (Embedding)로 변환하는 함수
...

이 프로그램을 실행해 보니 다음과 같은 출력을 얻었습니다.

📦 강의 노트를 7개의 청크로 분할했습니다.

🔍 사용자의 질문을 벡터화하고 있습니다...

🧮 수학 공간에서 의미의 근접성을 계산 중 (코사인 유사도)...

  • 유사도: 0.7978 -> 「인공지능 (AI)의 역사는 195...」
  • 유사도: 0.8574 -> 「아카디아 프로토콜이란, ...」
  • 유사도: 0.7774 -> 「오늘 점심은 토마토 파스타와 샐...」
  • 유사도: 0.8643 -> 「이 프로토콜에서는, 통신할 때마다...」
  • 유사도: 0.8399 -> 「대학교 기말고사 일정은...」
  • 유사도: 0.8502 -> 「DCKG는, 단말의 온도 변화와 대...」
  • 유사도: 0.8285 -> 「요즘 빠져 있는 게임은 스트리...」

🎯 가장 의미가 가깝다고 판정된 청크 (점수: 0.8643):

👉 「이 프로토콜에서는, 통신할 때마다 「동적 카오스 키 생성 (DCKG)」라고 불리는 알고리즘을 사용한다.」

🤖 LLM이 사고 중...

📝 【RAG 시스템으로부터의 최종 답변】

이 프로토콜에서는, 통신할 때마다 「동적 카오스 키 생성 (DCKG)」라는 알고리즘을 사용하여 암호 키를 생성한다고 합니다. 구체적인 방법에 대해서는 상세 내용이 기재되어 있지 않으므로, 어떠한 카오스 모델을 사용하여 동적으로 암호 키를 작성하기 위한 알고리즘일 가능성이 있습니다.

사실은 강의 노트의 6행째(가공의 기술인 DCKG의 이론 설명문)를 참조하기를 바랐지만, 생각보다 코사인 유사도에 차이가 나지 않아 다른 행이 참조되어 버렸습니다.

선생님 (Gemini) 말로는, 원인으로서,

  • 사용한 모델인 Qwen2.5와 같은 고기능 모델이 추출하는 벡터는 「단어의 완전 일치」보다 「문장으로서의 구조나 문체」에 더 강하게 반응할 가능성
  • 청크 (Chunk)가 너무 짧아서 문맥이 결여되었을 가능성

내용이라기보다 기술 설명에 가까운 「문장의 구조」나 「~에 대해 알려줘」와 같은 정중한 질문의 분위기에 끌려, 베이스 유사도 점수가 전체적으로 높아져 버린 것이군요. 또한, 한 줄씩 청크 (Chunk)를 나누었기 때문에, 「~라는 기술이다.」라는 해설 문장보다 「~라는 알고리즘을 사용한다.」라는 문장이 「질문 내용(DCKG 기술의 「원리」)」이라는 개념에 더 가깝다고 판단된 듯합니다.

그래서 다음으로는 청크 (Chunk) 나누기를 한 줄씩이 아니라 두 줄씩 해보겠습니다. 이번 강의 노트는 관련 있는 문장과 관련 없는 문장이 번갈아 들어있는 「최악의 노이즈 환경」이지만 일단 시도해 보겠습니다. 프로그램은 다음과 같습니다.

import ollama
import numpy as np
def get_embedding(text):
...
  • 유사도: 0.8571 -> 「인공지능 (AI)의 역사는 195...」
  • 유사도: 0.8330 -> 「아카디아 프로토콜이란, ...」
  • 유사도: 0.8859 -> 「오늘 점심은 토마토 파스타와 사라...」
  • 유사도: 0.8363 -> 「이 프로토콜에서는, 통신의 매번...」
  • 유사도: 0.8766 -> 「대학교 기말고사 스케줄은...」
  • 유사도: 0.8505 -> 「DCKG는, 단말의 온도 변화와 대...」

두 줄씩 (중첩 있음)으로 실행해 보았지만, 결과는 별로 변하지 않고 DCKG를 설명하는 부분이 아니라 「DCKG라는 알고리즘이 사용되고 있다」라는 문장이 우선시되어 버렸습니다. 어느 정도 그렇게 될 줄은 알고 있었습니다. 기왕이면 깔끔하게 하고 싶어서 원래의 문장(강의 노트)에서 서로 관련 있는 문장을 인접하게 배치하여 실행해 보았습니다.

  • 유사도: 0.8571 -> 「인공지능 (AI)의 역사는 195...」
  • 유사도: 0.8471 -> 「아카디아 프로토콜이란, ...」
  • 유사도: 0.8445 -> 「이 프로토콜에서는, 통신의 매번...」
  • 유사도: 0.8342 -> 「DCKG는, 단말의 온도 변화와 대...」
  • 유사도: 0.8420 -> 「오늘 점심은 토마토 파스타와 사라...」
  • 유사도: 0.8463 -> 「대학교 기말고사 스케줄은...」

🎯 가장 의미가 가깝다고 판정된 청크 (Chunk) (점수: 0.8571):

👉

인공지능 (AI)의 역사는 1950년대부터 시작되었습니다.

아카디아 프로토콜이란, 2026년에 개발된 양자 컴퓨터 내성을 가진 새로운 암호화 통신 프로토콜이다.

하지만 결과는 이런 식으로 잘 풀리지 않았습니다. 이렇게 되면 상당히 손을 쓸 수 없겠네요. 선생님 (Gemini)의 차례입니다.

선생님 말씀으로는, 실무에서 RAG를 구축할 때 채팅용 LLM (이번의 경우 Qwen2.5:3b)에게 벡터를 만들게 하는 일은 절대 하지 않는다고 합니다. 임베딩 (Embedding) 전용 모델이 필수적인 것 같네요. 이번 사례의 경우라면, 「생성」, 「원리」라는 단어가 「인공지능 (AI)」라는 단어와 너무 강하게 결합되어 버려서, 가상의 DCKG라는 가상 단어를 완전히 짓눌러 버린 듯합니다.

이번에는 꽤 잘 풀리지 않아서 재미있었네요.

어중간해서 죄송합니다만, 이어지는 임베딩 (Embedding) 전용 모델을 다운로드하여 사용하는 것은 다음 회차로 넘기겠습니다. 천천히 하지 않으면 계속할 수 없으니까요.

읽어주셔서 감사합니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0