[LLM 컨셉] Semantic Search: 키워드를 넘어 '의도'를 검색하다
**의미 기반 검색(Semantic Search)**은 사용자의 검색어에 담긴 **의도(Intent)**와 문장의 **맥락(Context)**을 이해하여 가장 관련성이 높은 결과를 제공하는 기술입니다. "검색어가 무엇인가?"보다 "검색어를 던진 이유가 무엇인가?"에 집중하는 방식입니다.
1. 전통적 검색(Lexical Search) vs 의미 기반 검색
| 구분 | 키워드 검색 (Lexical) | 의미 기반 검색 (Semantic) |
| 작동 원리 | 문자열 일치 (TF-IDF, BM25) | 벡터 공간 내 의미적 거리 측정 |
| 장점 | 고유 명사, 제품명 검색에 정확함 | 동의어, 문맥, 모호한 표현 처리에 강함 |
| 단점 | 오타나 유의어 처리에 취약함 | 계산 비용이 상대적으로 높음 |
| 비유 | 사전에서 똑같은 단어 찾기 | 대화의 맥락을 이해하는 비서 |
2. 의미 기반 검색의 핵심 기술
의미 기반 검색이 가능하려면 텍스트를 숫자로 바꾸고 거리를 재는 정교한 과정이 필요합니다.
① 텍스트 임베딩 (Text Embedding)
문장을 고차원 벡터로 변환할 때, 단순한 숫자가 아니라 문법적 구조와 의미적 특징이 담기도록 합니다.
- 예: "은행에 가서 돈을 찾다"와 "강둑(Bank) 근처에서 놀다"에서 'Bank'라는 단어가 전혀 다른 위치에 배치되도록 문맥을 반영합니다.
② 유사도 측정 기법
벡터 공간에서 두 문장이 얼마나 가까운지 계산하는 수학적 방법입니다.
- 코사인 유사도 (Cosine Similarity): 두 벡터 사이의 '각도'를 측정합니다. 문장의 길이에 상관없이 '방향성(의미)'이 얼마나 유사한지 판단할 때 가장 많이 쓰입니다.
- L2 거리 (Euclidean Distance): 두 점 사이의 직선거리를 측정합니다. 데이터의 절대적인 크기가 중요할 때 사용합니다.
3. 검색 성능을 높이는 고도화 전략
실무에서는 단순히 벡터 검색만 하지 않고, 여러 기법을 섞어서 사용합니다.
- 하이브리드 검색 (Hybrid Search): 키워드 기반의 BM25와 의미 기반의 벡터 검색을 결합합니다. 정확한 명칭(키워드)과 맥락(의미)을 모두 잡기 위한 가장 대중적인 전략입니다.
- 리랭킹 (Re-ranking): 검색 엔진이 1차로 뽑아온 상위 결과물들을, 더 똑똑한 모델(Cross-Encoder 등)을 이용해 다시 한번 정밀하게 순위를 매기는 과정입니다. 속도와 정확도 사이의 균형을 맞추는 핵심 기술입니다.
4. 의미 기반 검색의 실전 활용 사례
- Q&A 봇: 사용자가 "환불 어떻게 해?"라고 물어도 "반품 절차", "결제 취소 방법" 문서를 찾아 답변합니다.
- 추천 시스템: 내가 읽은 기사와 '내용 면에서 유사한' 다른 기사를 추천합니다.
- 다국어 검색: 한국어로 검색해도 영문 문서 중에서 같은 의미를 지닌 내용을 찾아낼 수 있습니다. (Cross-lingual Embedding 활용)
5. [선생님의 심화 보충] Sparse Vector vs Dense Vector
- Dense Vector (밀집 벡터): 우리가 지금까지 배운 임베딩입니다. 모든 차원에 숫자가 가득 차 있으며 문맥 파악에 유리합니다.
- Sparse Vector (희소 벡터): 키워드 등장 횟수를 기록한 벡터입니다. 대부분이 0으로 채워져 있으며, 특정 단어를 정확히 찾는 데 유리합니다.
- 현대적인 의미 기반 검색은 이 두 가지 벡터를 적절히 배합하여 완성됩니다.
✍️ 공부를 마치며
의미 기반 검색은 RAG가 단순히 아무 자료나 가져오는 게 아니라, 모델이 답변하기에 '가장 적절한 참고서'를 골라주는 필터 역할을 합니다. 이제 도구를 준비했으니, 이들을 하나로 엮어줄 프레임워크를 만날 차례입니다.
1️⃣ itemgetter (operator 모듈)
✅ 개념
- 리스트, 튜플, 딕셔너리 등에서 특정 위치(index)나 키(key)의 값을 빠르게 꺼낼 수 있게 해주는 함수
- lambda x: x[1] 같은 역할을 더 빠르고 간결하게 구현
✅ 사용법
from operator import itemgetter
my_list = ['a', 'b', 'c', 'd']
get_index_1 = itemgetter(1)
print(get_index_1(my_list)) # 👉 'b'
my_dict = {'name': 'Alice', 'age': 30}
get_age = itemgetter('age')
print(get_age(my_dict)) # 👉 30
📝 추가 설명
- 여러 개의 인덱스나 키도 동시에 가져올 수 있음
aget_name_age = itemgetter('name', 'age')
print(get_name_age(my_dict)) # 👉 ('Alice', 30)
- 데이터 정렬 시 자주 사용 (예: sorted(data, key=itemgetter(1)))
2️⃣ re 모듈과 정규표현식
✅ 개념
- 문자열에서 특정 패턴을 검색·추출·치환할 때 사용
- 전화번호, 이메일 등 패턴이 있는 데이터를 찾는 데 유용
✅ 사용 예시
import re
text = "안녕하세요! 제 번호는 010-9999-4567 입니다."
match = re.search(r"(\d{3}-\d{4}-\d{4})", text)
if match:
phone_number = match.group(1)
print(phone_number) # 👉 010-9999-4567
🔑 핵심 패턴
- \d → 숫자
- {3} → 3자리 반복
- () → 그룹핑 (group(1)로 접근)
3️⃣ 바다코끼리 연산자 (:=)
✅ 개념
- 할당 표현식: if, while 등에서 변수를 선언하면서 동시에 조건식에 활용 가능
- Python 3.8부터 지원
✅ 사용 예시
import re
text = "안녕하세요! 제 번호는 010-9999-4567 입니다."
if match := re.search(r"(\d{3}-\d{4}-\d{4})", text):
phone_number = match.group(1)
print(phone_number)
🔹 위 코드는 match = re.search(...) + if match: 를 한 줄로 줄인 것.
4️⃣ LangChain 주요 개념
① ChatPromptTemplate
- 대화형 프롬프트를 만들 때 사용
- 역할(Role)과 메시지를 지정
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "사용자 입력한 요리의 레시피를 생각하세요"),
("human", "{dish}")
])
② ChatOpenAI
- OpenAI의 챗 모델을 LangChain에서 불러올 때 사용
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model='gpt-4o-mini', temperature=0)
🔑 오타 주의: temerature → temperature
③ StrOutputParser
- 모델의 응답을 문자열로 변환해주는 파서
from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()
④ 체인 연결 (| 연산자)
- 프롬프트 → 모델 → 출력 파서를 하나의 체인으로 연결
chain = prompt | model | StrOutputParser()
chain.invoke({'dish': '라면'}) # 단일 요청
⑤ 스트리밍(stream)과 배치(batch)
- 스트리밍: 모델이 생성하는 응답을 실시간으로 출력
for chunk in chain.stream({'dish': '마라탕'}):
print(chunk, end="")
- 배치: 여러 개의 요청을 한 번에 처리
output = chain.batch([{'dish':'라면'}, {'dish':'떡볶이'}])
📝 전체 요약 표
개념설명예시
| itemgetter | 리스트/딕셔너리 값 추출 | itemgetter(1)(my_list) |
| re.search | 문자열에서 패턴 검색 | re.search(r"\d{3}", text) |
| := (바다코끼리) | 변수 할당 + 조건식 | if match := re.search(...): |
| ChatPromptTemplate | 프롬프트 메시지 구성 | from_messages([...]) |
| ChatOpenAI | OpenAI 모델 사용 | ChatOpenAI(model='gpt-4o-mini') |
| StrOutputParser | 응답을 문자열로 변환 | StrOutputParser() |
| chain.stream | 실시간 응답 출력 | for chunk in chain.stream(...): |
| chain.batch | 여러 요청 처리 | chain.batch([...]) |
랭스미스 모니터링?
깃 이그노어?

postgresql 원래는 RBMS, 확장팩 설치하묜 벡터디비로 서용 가능
FAISS 페이스북에서 만든거
크로마 기본
레그를 사용하면 이용한 벡터 디비 3종류
🧠 오늘 학습한 내용 정리
1️⃣ Python 기본 개념
- itemgetter: 리스트/딕셔너리에서 특정 인덱스나 키로 값을 빠르게 꺼낼 때 사용
- re 모듈: 정규 표현식으로 패턴 매칭 (전화번호 추출)
- 바다코끼리 연산자 (:=): 할당과 조건 검사를 한 번에 처리
2️⃣ LangChain 기본 체인 만들기
- ChatPromptTemplate: 프롬프트(모델에게 지시문) 작성
- ChatOpenAI: OpenAI 모델을 LangChain에서 사용
- StrOutputParser: 모델 응답을 문자열로 변환
- 체인 연결: prompt | model | parser
- 사용법:
- invoke → 단일 요청
- stream → 실시간 스트리밍
- batch → 여러 요청 한 번에 처리
3️⃣ 환경 변수와 LangSmith 연결
- .env 파일로 API 키, 프로젝트 설정
- load_dotenv()로 Python에서 불러오기
- LangSmith(smith.langchain.com)를 통해 체인 실행 로그 추적 가능
4️⃣ 체인 고급 기능
- Chain of Thought (CoT):
- 모델이 단계별로 생각 → 결론만 추출하는 체인
- RunnableLambda:
- 체인 결과를 후처리 (예: 답변을 대문자로 변환)
- RunnableParallel:
- 여러 체인을 동시에 실행 (낙관주의 vs 비관주의 체인)
- 결과 합치기:
- 여러 의견 → 종합 프롬프트 → 최종 답변 생성
5️⃣ 리트리버 & Tavily 검색
- Tavily API로 실시간 웹 검색 리트리버 사용
- TAVILY_API_KEY를 .env에 저장 후 활용
- 체인에서:
-
python코드 복사{'context': retriever, 'question': RunnablePassthrough()} | prompt | model
6️⃣ Git 문서 로딩 + Chroma 벡터 DB
- GitLoader: GitHub 리포지토리에서 문서 불러오기
- 텍스트 분할: RecursiveCharacterTextSplitter
- 임베딩 생성: OpenAIEmbeddings
- DB 저장: Chroma.from_documents()
- RAG 체인: 리트리버로 관련 문서 검색 → 모델 답변
7️⃣ HyDE (Hypothetical Document Embeddings)
- 질문만으로 검색 → 정확도가 떨어질 수 있음
- 모델이 먼저 "가짜 문서"를 만들어서 검색에 활용
- 코드:
-
python코드 복사hypothetical_prompt → hypothetical_chain | retriever
- RAG 성능 향상
8️⃣ Multi-query RAG
- Pydantic 모델(QueryGenerationOutput)로 3개 이상의 검색 쿼리 자동 생성
- 여러 쿼리를 병렬로 검색 → 결과 합침
- multi_query_rag_chain으로 다양한 검색 관점 확보
9️⃣ PostgreSQL 설치
- postgresql-common 설치
- APT 리포지토리 등록 과정에서 Signed-By 충돌 문제 해결
- 올바른 설치 순서:
-
bash코드 복사sudo apt install -y postgresql-common sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh sudo apt update sudo apt -y install postgresql
- 충돌 시 /etc/apt/sources.list.d/pgdg.list 중복 키 제거
✅ 오늘 배운 핵심 포인트
- LangChain 체인 조합(|), 후처리(RunnableLambda), 병렬 실행(RunnableParallel)
- 리트리버 기반 RAG 검색 + HyDE, Multi-query 개선
- Git → 벡터 DB → RAG 구현
- PostgreSQL 설치 문제와 해결 방법
질문받고 라우터를 통해서 어디로 검색할지 판단하고 질문에 응답함
'AI > LLM' 카테고리의 다른 글
| [LangGraph] 에이전트의 설계도 (0) | 2025.08.06 |
|---|---|
| [LangChain] AI 파이프라인 구축 (0) | 2025.08.05 |
| [Vector DB] 지식의 저장소 (3) | 2025.08.01 |
| [RAG 기초] 환각 현상의 구세주 (0) | 2025.07.31 |
| [PEFT 2] 양자화 튜닝 QLoRA (3) | 2025.07.30 |