인공지능 - LangChain으로 스타트업 창업 가이드 문서 검색 시스템 만들기
🛠 LangChain으로 스타트업 창업 가이드 문서 검색 시스템 만들기
AI 시대에 “문서에서 질문하고 답변하는” 기능은 정말 흔하게 요구됩니다.
이를 구현하려면 단순히 LLM 호출만으로는 부족합니다.
✨ 문서를 쪼개고, 벡터로 바꾸고, 의미상 비슷한 걸 찾아 LLM에 던져줘야 합니다.
이런 과정을 자동화하는 것이 바로 LangChain의 힘입니다.
오늘은
- LangChain 전체 흐름
- 청크(Chunk) 분할
- 임베딩(Embedding)
- 유사도 검색(Retrieval)
- GPT 쿼리(질문-답변 매커니즘)
까지 실습 코드와 함께 한 번에 정리해보겠습니다.
🛠 전체 흐름 요약
- PDF 문서를 로드
- 문서를 적당한 길이로 쪼개기 (Chunk)
- 각 청크를 임베딩(벡터화)
- 벡터를 FAISS에 저장
- 질문을 임베딩하여 가장 유사한 문서 조각 검색
- 검색된 내용을 기반으로 GPT가 답변 생성
📄 코드 설명
1. 문서 로드
from langchain.document_loaders import PyPDFLoader
pdfloader = PyPDFLoader("pdf/Startup_Guide.pdf")
documents = pdfloader.load()
print(f"불러온 문서 수: {len(documents)}")
- PDF 파일을 한 페이지 단위로 읽어옵니다.
- 각 페이지는 텍스트와 메타데이터를 포함하는 Document 객체가 됩니다.
2. 문서 청크(Chunk) 분할
from langchain.text_splitter import RecursiveCharacterTextSplitter
txt_split = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
docs = txt_split.split_documents(documents)
print(f"생성된 청크 수: {len(docs)}")
- 긴 문서를 1000자 단위로 쪼개고, 200자씩 겹치게 합니다.
- 이유는?
문맥이 부드럽게 이어지도록 일부 내용을 중복시켜 연결성을 높이기 위함입니다.
✅ Chunking이 중요한 이유
LLM은 한 번에 처리할 수 있는 토큰 수(약 4000~8000 tokens)가 제한되어 있기 때문에, 문서를 나누어야 합니다.
3. 임베딩(Embedding) 생성 및 저장
from langchain_openai import OpenAIEmbeddings
from langchain.vectorstores import FAISS
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
vdb = FAISS.from_documents(docs, embeddings)
vdb.save_local("myfaiss")
- 각 청크를 OpenAI의 “text-embedding-ada-002” 모델로 1536차원 벡터로 변환합니다.
- 변환된 벡터를 FAISS라는 벡터 데이터베이스에 저장합니다.
✅ Embedding이 중요한 이유
텍스트를 숫자 공간으로 변환하면, 텍스트끼리 ‘의미상 가까운 정도’ 를 수치로 비교할 수 있습니다.
4. 질문 임베딩 및 유사도 검색 (Retrieval)
gpt_llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
retriever = vdb.as_retriever()
- 사용자가 질문을 입력하면,
- 질문도 임베딩으로 변환해서,
- 저장된 문서 청크들 중 의미상 가장 가까운 조각들 4~5개를 검색합니다.
✅ Retrieval이 중요한 이유
GPT에게 “전체 문서”를 던지면 토큰 초과 오류가 나지만,
질문과 관련된 부분만 추려서 보내면 훨씬 정확하고 빠릅니다.
5. GPT에게 문맥(Context) + 질문(Query) 보내 답변 생성
from langchain.chains import RetrievalQA
qa = RetrievalQA.from_chain_type(
llm=gpt_llm,
chain_type='stuff',
retriever=retriever,
return_source_documents=True
)
query = "스타트업 초기 투자 유치 방법 알려줘."
result = qa.invoke({'query': query})
print(f"질문: {query}")
print(f"답변: {result['result']}")
- 검색된 문서 조각들을 하나로 Stuff(이어붙이기) 합니다.
- 이어붙인 Context + 질문을 LLM에게 보내서 답변을 생성합니다.
✅ 여기서 ‘stuff’란?
검색된 문서들을 “하나로 합쳐서” (stuffing) 프롬프트에 넣는다는 뜻입니다.
(문서가 적을 때 효과적)
📈 전체 구조 그림 요약
단계 | 설명 |
---|---|
문서 로드 | PDF 등에서 원본 문서를 가져옴 |
청크 분할 | 문서를 적절한 크기로 조각냄 |
임베딩 생성 | 문서 조각을 의미 벡터로 변환 |
벡터 저장 | FAISS에 벡터 저장 |
질문 임베딩 | 질문도 의미 벡터로 변환 |
유사도 검색 | 질문과 가장 비슷한 문서 조각 찾기 |
GPT 호출 | 문맥(Context) + 질문을 입력해 답변 생성 |
🧩 추가로 알아두면 좋은 개념
개념 | 설명 |
---|---|
Chunk 크기 | 너무 작으면 맥락을 잃고, 너무 크면 검색/토큰 초과 문제가 생김 |
임베딩 모델 | text-embedding-ada-002가 가장 일반적이지만, 다양한 모델 존재 |
검색 방법 | 코사인 유사도(Cosine Similarity)나 L2 거리 기반 |
chain_type=’stuff’ | 단순 이어붙이기 방식. 문서가 클 경우는 ‘map_reduce’ 같은 다른 방법도 고려 |
📝 마무리
정리하면,
LangChain은 문서를 다루는 전체 AI 파이프라인(로드 → 분할 → 임베딩 → 검색 → 답변)을 깔끔하게 관리하는 프레임워크입니다.
특히 “청크 분할 + 임베딩 + 유사도 검색 + GPT 호출” 이 4단계를 이해하면,
대부분의 “내 데이터로 답변하기” 시스템을 직접 구현할 수 있습니다. 🚀
🚀 다음 글 예고
👉 “Chunk 크기와 Overlap 설정 최적화 방법”
👉 “stuff, map_reduce, refine 체인 방식 비교”
👉 “FAISS 인덱스를 파일로 저장하고 불러오는 실습”
댓글남기기