Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
Tags
- OpenAI
- 프로그래머스
- LLM
- javascirpt
- retriever
- 코딩테스트
- InfluxDB
- modbus
- 파이썬
- Two Pointer
- 완전탐색
- MCP
- python
- 스택/큐
- chroma
- DP
- typescript
- rag
- dfs
- heapq
- javascript
- Algorithm
- 알고리즘
- VectoreStore
- frontend
- BFS
- backend
- AI
- React
- queue
Archives
- Today
- Total
DM Log
[AI 실습 #4] 다중 PDF RAG 확장하기 본문
다중 PDF에서 답변 받기
- 여러 PDF를 동시에 다루는 RAG 구조를 생성, 질문과 관련 잇는 파일을 우선순위로 정하여 답변하는 방법 실
[구현 전략]
1. 여러 PDF를 로딩 → 분할 → 임베딩 → Chroma에 저장
2. 각 문서에 source 메타데이터(파일명)을 붙임
3. 사용자 질문 → 관련 문서 검색 → 파일별 점수 집계
4. 관련성 높은 파일 우선순위 반환
5. 선택된 파일만을 기반으로 QA 실행
다중 PDF RAG 서버 구축
[코드 예시]
1. 여러 PDF 로드 및 벡터 스토어 생성
import os
from langchain_community.vectorstores import Chroma
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
def process_pdf(file_path, persist_directory="chroma_db"):
loader = PyPDFLoader(file_path)
pages = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
docs = splitter.split_documents(pages)
# 파일명 메타데이터 추가
for doc in docs:
doc.metadata["source"] = os.path.basename(file_path)
vectorstore = Chroma.from_documents(
docs,
embeddings,
persist_directory=persist_directory
)
return vectorstore
2. 관련 문서 검색 & 파일 우선순위 산정
def find_related_files(query, vectorstore, top_k=3):
results = vectorstore.similarity_search(query, k=top_k)
file_scores = {}
for r in results:
fname = r.metadata["source"]
file_scores[fname] = file_scores.get(fname, 0) + 1
return sorted(file_scores.items(), key=lambda x: x[1], reverse=True)
3. 선택된 파일 기반 QA 실행
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")
def answer_from_file(query, vectorstore, filename):
retriever = vectorstore.as_retriever(
search_kwargs={"filter": {"source": filename}}
)
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
return qa_chain.run(query)
4. MCP 도구 등록
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("MultiPDF-RAG")
@mcp.tool()
def ask_pdf_multi(query: str) -> dict:
"""여러 PDF 중 관련 있는 파일 우선순위 반환"""
related_files = find_related_files(query, vectorstore)
return {"files": [f for f, _ in related_files]}
@mcp.tool()
def answer_pdf(query: str, filename: str) -> str:
"""선택된 파일에서 답변 생성"""
return answer_from_file(query, vectorstore, filename)
if __name__ == "__main__":
mcp.run(transport="stdio")
[실행 예시]
1. 여러 PDF를 처리 후 Chroma에 저장
2. 질문: 스마트팜 기술의 장점은?
3. MCP ask_pdf_multi 호출 결과:
{ "files": ["스마트팜.pdf", "농업혁신.pdf"] }
4. 사용자가 "스마트팜.pdf"를 선택
5. MCP answer_pdf 호출 결과 출력
(부록) 용어 정리
- metadata["source"]: 문서 출처(파일명) 저장
- similarity_search: 질문과 유사한 문서 검색
- 우선순위 산정: 검색된 문서의 출처 빈도수 기반 점수
'개발공부 > AI' 카테고리의 다른 글
[AI 프로젝트 #0] 초기 세팅 #1: Node, Python, Vite 기반 모노레포 환경 설명 (0) | 2025.09.14 |
---|---|
[AI 실습 #3] PDF 단일 파일 RAG 만들기 (0) | 2025.09.13 |
[AI 실습 #2] MCP 소개와 FastMCP 실습 (0) | 2025.09.13 |
[AI 실습 #1] Chroma 실습: 벡터DB를 활용한 문서 검색 (0) | 2025.09.13 |
[AI 개념 및 이해 #5] RAG: 검색과 생성을 결합하는 기술 (0) | 2025.09.07 |