13장. 임베딩과 벡터 DB
왜 임베딩이 필요한가 — 청크는 있는데, 찾을 방법이 없다
한 줄 요약
12장에서는 정책 문서를 12개의 청크로 나눴습니다. 이제 고객의 질문에 답하는 데 어떤 청크가 필요한지 찾는 방법이 필요합니다. 이번 장에서는 청크를 임베딩으로 변환해 벡터 DB에 저장하고, 질문의 의미와 관련된 내용을 검색하는 방법을 배웁니다.
1. 지금 가진 것과 없는 것
12장의 load_policy_chunks()는 청크 12개를 돌려줍니다. 청크마다 id, text(본문), metadata(출처 문서와 조항)가 들어 있습니다.
| 가진 것 | 없는 것 |
|---|---|
| 정책 PDF 두 개를 나눈 청크 12개 | 질문과 관련된 청크를 골라내는 방법 |
| 청크마다 붙은 출처(문서 이름, 조항) | 고른 청크를 저장해 두고 다시 쓰는 곳 |
질문이 올 때마다 청크 12개를 전부 프롬프트에 넣을 수는 없습니다. 지금은 12개지만 문서가 늘면 수백, 수천 개가 됩니다. 질문과 관련된 몇 개만 골라야 합니다.
2. 가장 먼저 떠오르는 방법 — 단어가 들어 있는지 본다
질문에 나온 단어가 들어 있는 청크를 찾으면 될 것 같습니다. 청크 12개에 실제로 해 보면 이렇게 됩니다.
| 고객이 쓴 말 | 그 말이 들어 있는 청크 | 문서가 쓰는 말 | 그 말이 들어 있는 청크 |
|---|---|---|---|
| 택배비 | 0개 | 배송비 | 8개 |
| 돌려줘요 | 0개 | 환불 | 9개 |
| 돈 | 0개 | 결제대금, 환불 금액 | — |
"택배비 누가 내요?"라고 물으면 단어 검사는 한 건도 찾지 못합니다. 문서에는 "택배비"라는 말이 없고 "배송비"만 있기 때문입니다. 사람에게는 같은 말이지만, 글자를 비교하는 코드에게는 전혀 다른 글자입니다.
반대의 문제도 있습니다. "배송비"로 찾으면 12개 중 8개가 걸립니다. 너무 많아서 고른 것이 아닙니다.
고객의 말과 문서의 말은 다른 것이 보통입니다. 고객은 정책 문서를 읽고 질문하지 않습니다.
3. 필요한 것 — 글자가 아니라 뜻으로 찾기
필요한 것은 "택배비"와 "배송비"가 같은 뜻임을 아는 검색입니다. 컴퓨터가 뜻을 다루게 하려면 뜻을 계산할 수 있는 모양, 곧 숫자로 바꿔야 합니다. 그 변환이 임베딩(embedding) 입니다.
이번 장에서 하는 일은 세 가지입니다.
| 단계 | 하는 일 | 쓰는 것 |
|---|---|---|
| 1 | 청크와 질문을 숫자 목록으로 바꾼다 | 임베딩 모델 gemini-embedding-001 |
| 2 | 그 숫자 목록을 저장해 둔다 | 벡터 DB Chroma → chroma_db/ 폴더 |
| 3 | 질문과 가까운 청크를 찾는다 | 유사도 검색 |
이번 장에서는 아직 답변을 만들지 않습니다. LLM에게 답을 쓰게 하는 일은 14장에서 합니다. 여기서는 "찾기"만 봅니다.
4. 이걸 모르면 무엇을 판단하지 못하는가
- 답이 틀렸을 때 검색이 못 찾은 것인지, 모델이 잘못 쓴 것인지 가려내지 못합니다. 검색 결과를 읽을 줄 알아야 가릴 수 있습니다.
- 검색 결과 옆에 나오는 점수가 좋은 것인지 나쁜 것인지 읽지 못합니다. 클수록 좋은 점수도 있고 작을수록 좋은 점수도 있습니다.
- 정책 문서가 바뀌었을 때, 또는 임베딩 모델을 바꿨을 때 무엇을 다시 해야 하는지 알지 못합니다.
핵심 정리
- 12장의 청크 12개에는 찾는 방법이 아직 없습니다.
- 단어 검사는 고객의 말("택배비")과 문서의 말("배송비")이 다르면 0건을 냅니다.
- 뜻으로 찾으려면 글을 숫자로 바꿔야 하고, 그 변환이 임베딩입니다.
- 이번 장의 산출물은 청크 12개가 저장된
chroma_db/폴더입니다. 14장 이후가 모두 이 폴더를 씁니다.