Claude를 활용한 RAG 시스템 구축 방법: 내 데이터로 구동하는 AI (전체 가이드)

@undefinedKi
영어2일 전 · 2026년 7월 11일
206K
150
25
16
575

TL;DR

본 종합 가이드에서는 Claude를 사용하여 로컬 RAG (Retrieval-Augmented Generation) 시스템을 구축하는 방법을 설명합니다. 이를 통해 사용자는 API 비용을 최소화하면서 자신의 문서를 효율적으로 조회할 수 있습니다.

클로드에게 회사, 노트, 파일에 대해 물어보면 아무것도 모른다고 답합니다. 클로드는 그런 내용을 본 적이 없기 때문입니다. 클로드는 훈련 과정에서 배운 것만 알고 있으며, 사용자의 데이터는 그 훈련에 포함되지 않았습니다.

RAG 시스템이 이 문제를 해결합니다. 기억에 의존해 답변하는 대신, 클로드는 먼저 문서에서 관련 정보를 찾고, 중요한 부분을 가져와 실제로 찾은 내용을 바탕으로 답변합니다. 사용자의 데이터가 곧 출처이며, 추측은 없습니다.

파일을 채팅에 직접 붙여넣는 것보다 나은 이유:

확장성. 전체 지식 기반을 한 번의 채팅에 담을 수 없습니다. RAG는 모든 것을 저장하고 각 질문에 필요한 부분만 가져옵니다.

비용 효율성. 파일을 붙여넣으면 클로드가 모든 질문에 대해 전체 파일을 다시 읽습니다. RAG는 한 번 읽은 후 관련 부분만 가져옵니다. 매번 10,000 토큰 분량의 매뉴얼을 보내는 대신, 필요한 정확한 섹션의 500 토큰만 보낼 수 있습니다. 실제 운영 환경에서는 토큰 사용량을 80% 이상 줄입니다.

정확성. 모델에 거대한 텍스트 덩어리를 입력하면 중간에 있는 세부 정보를 놓칩니다. 몇 개의 정확한 청크만 전달하면 답변의 정확도가 높아집니다.

최신 상태 유지. 파일을 한 번 업데이트하면 시스템이 새 버전을 사용합니다. 다시 붙여넣을 필요가 없습니다.

이 가이드를 마치면 박사 학위 없이도 단계별로 나만의 파일로 RAG 시스템을 실행할 수 있습니다.

필요한 것

코드를 다루기 전에 필요한 전체 목록을 알려드립니다. 좋은 소식은 이 버전에는 API 키 하나만 필요하며, 나머지는 모두 사용자 컴퓨터에서 무료로 실행된다는 점입니다.

1. Python 3.9 이상. 설치 여부를 확인하려면 터미널(Mac의 경우 터미널, Windows의 경우 명령 프롬프트)을 열고 python --version을 입력하세요. 3.11과 같은 버전이 표시되면 괜찮습니다. 그렇지 않다면 python.org에서 다운로드하여 설치 프로그램을 실행하세요. Windows의 경우 설치 중 "Add Python to PATH" 상자를 선택해야 아래 명령이 작동합니다.

2. 하나의 Claude API 키와 소액의 크레딧 잔액. 이 키만 있으면 가이드 전체에 필요한 유일한 비용입니다. 정확한 경로는 다음과 같습니다.

platform.claude.com으로 이동하여 로그인(또는 가입)하세요.

API를 실행하려면 잔액이 있어야 하므로 먼저 자금을 추가하세요. 크레딧이 본인용인지 회사용인지 선택하라는 메시지가 표시되면 선택하면 결제 화면으로 이동합니다. $5 "Starting out" 옵션을 선택하세요. 이 가이드의 다른 모든 것은 무료이며 로컬에서 실행되므로 Claude만 유일한 비용 항목이며, 각 질문당 비용은 1센트의 극히 일부에 불과합니다. 크레딧은 구매 후 1년 동안 유효합니다.

결제 후 콘솔 대시보드로 이동합니다. 왼쪽 상단의 "Organization credits" 아래에 잔액(예: $5.00)이 표시됩니다.

이제 키를 가져옵니다. Get API key(오른쪽 상단)를 클릭한 다음 Create Key를 클릭하세요. 원하는 이름(예: my-rag-key)을 지정하고 워크스페이스는 Default로 둡니다. 생성을 클릭한 다음 표시되는 문자열을 복사하세요. sk-ant-로 시작하며 한 번만 표시되므로 잠시 안전한 곳에 붙여넣어 두세요.

이것으로 설정이 완료되었습니다.

1단계: 키 추가 및 파일 로드

1. 프로젝트 폴더를 만듭니다. 바탕 화면에 새 폴더를 만들고 이름을 rag-project로 지정하세요. 모든 파일이 여기에 들어갑니다.

2. 터미널을 엽니다. Mac: Cmd+Space, Terminal 입력, Enter. Windows: 시작 버튼, cmd 입력, Enter.

3. 터미널을 폴더로 지정합니다. cd와 공백을 입력한 다음 rag-project 폴더를 터미널 창으로 끌어다 놓고 Enter를 누르세요. 아래의 모든 명령은 이 폴더 안에서 실행됩니다.

bash
1cd Desktop/rag-project

4. 도구를 설치합니다. 다음을 터미널에 붙여넣고 Enter를 누르세요(첫 실행은 1분 정도 걸릴 수 있습니다).

bash
1pip install anthropic chromadb sentence-transformers pypdf python-dotenv

pip: command not found 오류가 발생하면 pip 대신 pip3를 사용하세요. 터미널에 빨간색 오류 없이 새 줄이 표시되면 완료된 것입니다.

5. 코드 파일을 만듭니다. rag-project 안에 rag.py라는 이름의 빈 파일을 만듭니다. 텍스트 편집기에서 엽니다.

6. 키 파일을 만듭니다. 같은 폴더에 .env라는 이름의 파일을 만듭니다(점으로 시작하며 앞에 이름이 없습니다). 다음을 안에 붙여넣고, 설정에서 만든 실제 키를 = 뒤에 공백이나 따옴표 없이 붙여넣습니다.

text
1ANTHROPIC_API_KEY=sk-ant-paste-your-real-key-here

키를 코드 대신 .env에 보관하면 스크립트를 공유하거나 GitHub에 업로드할 때 누출되지 않습니다.

7. 키를 로드합니다. rag.py의 맨 위에 다음을 넣습니다.

python
1import os
2from dotenv import load_dotenv
3
4load_dotenv() # .env 파일을 읽습니다
5api_key = os.getenv("ANTHROPIC_API_KEY")

8. 지식 베이스를 만듭니다. rag-project 안에 documents라는 폴더를 만듭니다. .txt, .md 또는 .pdf 파일을 여기에 넣으세요: 노트, 제품 문서, 회의 요약 등 무엇이든 좋습니다.

8.1. 아직 파일이 없다면 이 테스트 파일을 사용하세요. documents 폴더 안에 notes.txt 파일을 만들고 다음을 붙여넣습니다.

Project Northstar는 고객 피드백을 추적하기 위한 내부 도구입니다. 2026년 3월에 출시되었으며 플랫폼 팀이 유지 관리합니다. 수석 엔지니어는 Dana Reyes입니다. 피드백은 매주 금요일에 검토됩니다. Northstar는 2025년까지 사용하던 기존 스프레드시트 시스템을 대체했습니다.

마지막에 Northstar에 대해 Claude에게 질문하고 이 파일에서 답변을 얻는 것을 확인할 수 있습니다.

9. 파일을 읽는 코드를 추가합니다. 7단계의 코드 아래, rag.py에 다음을 추가합니다.

python
1from pathlib import Path
2from pypdf import PdfReader
3
4def load_documents(folder="documents"):
5 docs = []
6 for file in Path(folder).iterdir():
7 if file.suffix in [".txt", ".md"]:
8 text = file.read_text(encoding="utf-8")
9 docs.append({"source": file.name, "text": text})
10 elif file.suffix == ".pdf":
11 reader = PdfReader(str(file))
12 text = "\n".join(page.extract_text() or "" for page in reader.pages)
13 docs.append({"source": file.name, "text": text})
14 return docs
15
16documents = load_documents()
17print(f"Loaded {len(documents)} document(s).")

10. 실행합니다. rag.py를 저장한 다음 터미널에서 다음을 실행합니다.

bash
1python rag.py

다음과 같이 표시되어야 합니다.

Loaded 1 document(s)

Loaded 0 document(s)가 표시되면 documents 폴더가 비어 있거나 잘못된 위치에 있는 것입니다. documents 폴더는 rag-project 바로 안에, rag.py 옆에 있어야 합니다.

2단계: 파일을 청크로 분할

현재 각 파일은 하나의 큰 텍스트 블록입니다. 검색하려면 먼저 청크라는 더 작은 조각으로 잘라야 합니다. 그 이유는 다음과 같습니다. 누군가 질문하면 시스템은 일치하는 청크를 찾아서 Claude에만 보냅니다. 청크가 50페이지 분량의 전체 문서라면 너무 많은 양을 보내게 됩니다. 반면 단일 문장이면 맥락을 잃습니다. 작은 단락이 적절한 크기입니다.

1. 청크 분할 코드를 추가합니다. 10단계의 코드 아래, rag.py에 다음을 추가합니다.

python
1def chunk_text(text, chunk_size=500, overlap=100):
2 words = text.split()
3 chunks = []
4 start = 0
5 while start < len(words):
6 end = start + chunk_size
7 chunk = " ".join(words[start:end])
8 chunks.append(chunk)
9 start = end - overlap # 약간 뒤로 이동하여 청크가 겹치도록 함
10 return chunks

여기서 두 숫자를 이해해야 합니다.

  • chunk_size=500 은 각 청크가 약 500단어임을 의미합니다. 완전한 아이디어를 담을 만큼 크고, 정확성을 유지할 만큼 작습니다.
  • overlap=100 은 각 청크가 이전 청크의 마지막 100단어를 반복함을 의미합니다. 답변이 두 청크가 만나는 경계선에 있을 수 있기 때문에 중요합니다. 겹침이 없으면 중간에서 분할된 문장이 손실될 수 있습니다. 겹침을 통해 어떤 아이디어도 틈새로 빠지지 않도록 합니다.

2. 모든 문서를 청크로 변환합니다. 아래에 다음을 추가합니다.

python
1all_chunks = []
2for doc in documents:
3 for chunk in chunk_text(doc["text"]):
4 all_chunks.append({"source": doc["source"], "text": chunk})
5
6print(f"Created {len(all_chunks)} chunk(s) from {len(documents)} document(s).")

각 청크에는 source (출처 파일 이름)가 함께 제공됩니다. 전체 과정에서 이를 유지하여 나중에 Claude가 답변할 때 답변이 어떤 파일에서 왔는지 알려줄 수 있습니다.

3. 실행합니다. rag.py를 저장한 다음 터미널에서 다음을 실행합니다.

bash
1python rag.py

다음과 같이 표시되어야 합니다.

Loaded 1 document(s).

Created 1 chunk(s) from 1 document(s).

작은 테스트 파일은 짧기 때문에 하나의 청크만 생성됩니다. 실제 문서는 여러 개를 생성합니다. 폴더에 긴 PDF를 넣었다면 수십 또는 수백 개의 청크가 표시될 수 있으며, 이는 정확히 원하는 결과입니다.

3단계: 청크를 임베딩으로 변환

이 단계를 통해 컴퓨터가 정확한 단어 대신 의미를 기준으로 검색할 수 있습니다. 각 청크는 내용을 포착하는 숫자 목록(임베딩)으로 변환됩니다. 의미가 비슷한 청크는 비슷한 숫자를 갖게 됩니다. 나중에 질문이 들어오면 질문도 숫자로 변환하여 가장 가까운 일치 항목을 찾습니다.

이 작업을 수행하는 모델은 사용자 컴퓨터에서 로컬로 실행됩니다. 한 번 다운로드하면 오프라인에서 무료로 작동하며, 파일이 컴퓨터를 떠나지 않습니다.

1. 임베딩 모델을 로드합니다. 2단계의 코드 아래, rag.py에 다음을 추가합니다.

python
1from sentence_transformers import SentenceTransformer
2
3print("Loading the embedding model (first run downloads it, about 90 MB)...")
4embedder = SentenceTransformer("all-MiniLM-L6-v2")

처음 실행할 때 모델을 다운로드하므로 시간이 걸릴 수 있습니다. 이후 실행은 이미 컴퓨터에 있으므로 즉시 완료됩니다.

2. 모든 청크를 임베딩으로 변환합니다. 아래에 다음을 추가합니다.

python
1chunk_texts = [chunk["text"] for chunk in all_chunks]
2embeddings = embedder.encode(chunk_texts)
3
4print(f"Created {len(embeddings)} embedding(s).")
5print(f"Each embedding is a list of {len(embeddings[0])} numbers.")

embedder.encode(...) 는 청크 텍스트 목록을 가져와 각 청크에 대한 임베딩 하나를 반환합니다. 이것이 전부입니다.

3. 실행합니다. rag.py를 저장한 다음 터미널에서 다음을 실행합니다.

bash
1python rag.py

첫 실행은 모델을 다운로드하는 동안 잠시 멈춘 후 다음과 같이 표시됩니다.

Loaded 1 document(s).

Created 1 chunk(s) from 1 document(s).

Loading the embedding model (first run downloads it, about 90 MB)...

Created 1 embedding(s).

Each embedding is a list of 384 numbers.

"384 numbers" 줄은 이 개념을 시각적으로 보여줍니다. 텍스트가 이제 컴퓨터가 비교할 수 있는 숫자 행이 되었습니다. 이 숫자를 직접 읽거나 이해할 필요는 없습니다. 다음 단계의 데이터베이스가 모든 비교를 처리합니다.

연결 오류로 다운로드가 실패하면 명령을 다시 실행하세요. 중단된 지점부터 다시 시작합니다.

4단계: 벡터 데이터베이스에 모든 것 저장

이제 청크와 해당 임베딩을 로컬 데이터베이스인 Chroma에 넣습니다. 이렇게 하면 검색이 빨라집니다. 매번 질문을 모든 청크와 수동으로 비교하는 대신 Chroma가 준비된 상태로 저장하고 일치 작업을 수행합니다. 컴퓨터의 폴더에 저장되므로 한 번만 구축하면 됩니다.

1. 데이터베이스를 설정합니다. 3단계의 코드 아래, rag.py에 다음을 추가합니다.

python
1import chromadb
2
3client = chromadb.PersistentClient(path="chroma_db")
4collection = client.get_or_create_collection("my_documents")

PersistentClient(path="chroma_db") 는 Chroma에 chroma_db 폴더에 저장하도록 지시합니다(스크립트 바로 옆에 자동으로 생성됨). 디스크에 저장되므로 스크립트가 종료된 후에도 데이터가 유지됩니다. collection은 청크가 저장되는 명명된 상자일 뿐입니다.

2. 데이터베이스에 청크를 추가합니다. 아래에 다음을 추가합니다.

python
1collection.add(
2 ids=[str(i) for i in range(len(all_chunks))],
3 embeddings=[emb.tolist() for emb in embeddings],
4 documents=[chunk["text"] for chunk in all_chunks],
5 metadatas=[{"source": chunk["source"]} for chunk in all_chunks],
6)
7
8print(f"Stored {collection.count()} chunk(s) in the database.")

각 줄이 Chroma에 전달하는 내용을 설명하면 다음과 같습니다. ids는 각 청크에 고유 레이블(0, 1, 2...)을 부여하고, embeddings는 3단계의 숫자이며, documents는 실제 청크 텍스트이고, metadatas는 나중에 출처를 표시할 수 있도록 파일 이름을 함께 전달합니다. Chroma는 이 네 가지를 모두 함께 유지합니다.

3. 실행합니다. rag.py를 저장한 다음 터미널에서 다음을 실행합니다.

bash
1python rag.py

다음과 같이 표시되어야 합니다.

Stored 1 chunk(s) in the database.

나중에 알아두어야 할 사항. 현재 스크립트를 실행할 때마다 청크가 다시 추가되므로 반복 실행 시 개수가 증가할 수 있습니다(1, 2, 3...). 구축 중에는 괜찮습니다. 깨끗하게 시작하려면 chroma_db 폴더를 삭제하고 한 번 더 실행하세요. 최종 버전에서는 중복되지 않도록 제대로 처리할 것입니다.

5단계: 문서 검색

이것은 RAG의 "검색(Retrieval)" 부분, 즉 이름의 R에 해당합니다. 질문을 가져와 청크와 동일한 방식으로 임베딩으로 변환하고 Chroma에 의미가 가장 가까운 청크를 요청합니다. 그 일치하는 청크가 다음 단계에서 Claude에 전달할 내용입니다.

1. 검색 함수를 추가합니다. 4단계의 코드 아래, rag.py에 다음을 추가합니다.

python
1def search(question, n_results=3):
2 question_embedding = embedder.encode([question])[0]
3 results = collection.query(
4 query_embeddings=[question_embedding.tolist()],
5 n_results=n_results,
6 )
7 return results

이 함수가 수행하는 작업을 한 줄씩 설명하면 다음과 같습니다. 청크에 사용한 것과 동일한 모델로 질문을 숫자로 변환하고(둘 다 동일한 "숫자 언어"를 사용해야 하므로 중요), Chroma에 가장 가까운 일치 항목을 요청합니다. n_results=3은 "가장 관련성 높은 청크 3개를 제공"한다는 의미입니다. 3개는 좋은 기본값입니다. 충분한 맥락을 제공하면서 토큰을 낭비하지 않습니다.

2. 검색을 시도합니다. 아래에 다음을 추가하여 테스트합니다.

python
1question = "Who runs Northstar and when is feedback reviewed?"
2results = search(question)
3
4for i, doc in enumerate(results["documents"][0]):
5 source = results["metadatas"][0][i]["source"]
6 print(f"\n--- Match {i+1} (from {source}) ---")
7 print(doc)

이것은 데이터베이스에 대해 실제 질문을 실행하고 찾은 청크를 각각 출처 파일 이름과 함께 출력합니다.

3. 실행합니다. rag.py를 저장한 다음 터미널에서 다음을 실행합니다.

bash
1python rag.py

Northstar 테스트 파일을 사용하면 일치하는 청크를 가져와서 다음과 같이 표시되어야 합니다.

--- Match 1 (from notes.txt) ---

Project Northstar는 고객 피드백을 추적하기 위한 내부 도구입니다. 2026년 3월에 출시되었으며 플랫폼 팀이 유지 관리합니다. 수석 엔지니어는 Dana Reyes입니다. 피드백은 매주 금요일에 검토됩니다. Northstar는 2025년까지 사용하던 기존 스프레드시트 시스템을 대체했습니다.

방금 일어난 일을 주목하세요. 질문에는 "who runs"와 "reviewed"라는 단어가 사용되었지만 파일에는 "lead engineer"와 "reviewed every Friday"라고 되어 있습니다. 검색이 정확한 단어가 아닌 의미를 기반으로 작동하기 때문에 여전히 일치했습니다. 이것이 임베딩의 핵심이며, 파일에 대한 단순 키워드 검색(Ctrl+F)보다 이 방법이 더 나은 이유입니다.

더 많은 파일이 있으면 전체 파일에서 상위 3개 청크가 일치 정도에 따라 정렬되어 표시됩니다.

6단계: Claude가 찾은 내용을 바탕으로 답변하도록 하기

이것은 "생성(Generation)" 부분, 즉 RAG의 G에 해당합니다. 5단계의 청크를 가져와 질문과 함께 Claude Opus 4.8에 전달하고 해당 컨텍스트만 사용하여 답변하도록 지시합니다. 이것이 Claude가 추측하는 것을 방지합니다. Claude는 자체 메모리가 아닌 사용자 파일에서 답변하며, 사용한 파일을 알려줍니다.

1. 답변 함수를 추가합니다. 5단계의 코드 아래, rag.py에 다음을 추가합니다.

python
1import anthropic
2
3claude = anthropic.Anthropic(api_key=api_key)
4
5def answer(question):
6 results = search(question)
7 chunks = results["documents"][0]
8 sources = [m["source"] for m in results["metadatas"][0]]
9
10 context = ""
11 for i, chunk in enumerate(chunks):
12 context += f"[From {sources[i]}]\n{chunk}\n\n"
13
14 message = claude.messages.create(
15 model="claude-opus-4-8",
16 max_tokens=1024,
17 system=(
18 "You answer questions using only the context provided. "
19 "If the answer is not in the context, say you don't know. "
20 "Always mention which file your answer came from."
21 ),
22 messages=[
23 {
24 "role": "user",
25 "content": f"Context:\n{context}\nQuestion: {question}",
26 }
27 ],
28 )
29 return message.content[0].text

여기서 일어나는 일을 설명하면 다음과 같습니다. 관련 청크를 검색하고, 하나의 context 블록으로 결합하고(각각 파일 이름이 표시됨), 해당 블록과 질문을 Claude에 전송합니다. system 지시문이 핵심 부분입니다. Claude에 세 가지를 지시합니다. 컨텍스트에서만 답변하고, 답변이 없으면 인정하고, 출처 파일을 명시하라는 것입니다. 이 세 가지 규칙이 답변을 조작된 것이 아닌 신뢰할 수 있게 만듭니다.

model="claude-opus-4-8" 는 정확한 모델 이름입니다(대시 사용, 점 아님). max_tokens=1024는 답변 길이를 제한합니다.

2. 질문을 합니다. 아래에 다음을 추가합니다.

python
1question = "Who runs Northstar and when is feedback reviewed?"
2print(answer(question))

3. 실행합니다. rag.py를 저장한 다음 터미널에서 다음을 실행합니다.

bash
1python rag.py

파일에서 작성된 실제 답변을 받아야 합니다. 다음과 같은 형식입니다.

Dana Reyes는 Project Northstar를 운영하는 수석 엔지니어이며, 피드백은 매주 금요일에 검토됩니다. (출처: notes.txt)

이것이 완전한 RAG 시스템입니다. Claude는 훈련 중에 이 파일을 본 적이 없으며 Dana Reyes가 누군지 알 수 없지만, 정확하게 답변하고 답변의 출처를 정확히 알려줍니다. 파일에 없는 내용을 물으면 답변을 만들어내는 대신 모른다고 말할 것입니다. 그 "모른다"는 것은 실패가 아니라 기능입니다. 신뢰할 수 있는 도구와 추측하는 도구의 차이입니다.

7단계: 실제로 사용할 수 있는 형태로 만들기

현재는 질문할 때마다 코드를 편집하고 전체 스크립트를 다시 실행해야 합니다. 더 나쁜 점은 실행할 때마다 파일을 다시 읽고 데이터베이스에 다시 추가하여 청크가 쌓인다는 것입니다. 두 가지를 모두 해결해 보겠습니다. 데이터베이스를 한 번만 구축한 다음 터미널에 직접 입력하여 질문을 반복할 수 있도록 합니다.

1. 중복 추가 문제를 해결합니다. 4단계의 청크를 추가하는 블록(collection.add(...) 부분)을 찾아 데이터베이스가 비어 있는 경우에만 구축하는 다음 버전으로 바꿉니다.

python
1if collection.count() == 0:
2 collection.add(
3 ids=[str(i) for i in range(len(all_chunks))],
4 embeddings=[emb.tolist() for emb in embeddings],
5 documents=[chunk["text"] for chunk in all_chunks],
6 metadatas=[{"source": chunk["source"]} for chunk in all_chunks],
7 )
8 print(f"Stored {collection.count()} chunk(s) in the database.")
9else:
10 print(f"Database already has {collection.count()} chunk(s), skipping rebuild.")

이제 파일 읽기, 임베딩 생성, 데이터베이스 채우기와 같은 무거운 작업은 처음에만 수행됩니다. 이후 실행은 답변으로 바로 건너뜁니다.

2. 질문 루프를 추가합니다. rag.py의 맨 아래에서 6단계의 단일 테스트 질문을 다음으로 바꿉니다.

python
1print("\nAsk a question about your documents (or type 'quit' to exit).\n")
2
3while True:
4 question = input("You: ")
5 if question.lower() in ["quit", "exit"]:
6 break
7 print("\nClaude: " + answer(question) + "\n")

input("You: ") 은 질문을 입력하고 Enter를 누를 때까지 기다립니다. while True는 계속 유지하여 원하는 만큼 질문할 수 있도록 합니다. quit를 입력하면 중지됩니다.

3. 실행합니다. rag.py를 저장한 다음 터미널에서 다음을 실행합니다.

bash
1python rag.py

이제 파일과 대화할 수 있습니다.

Ask a question about your documents (or type 'quit' to exit).

You: who is the lead engineer on Northstar?

Claude: Project Northstar의 수석 엔지니어는 Dana Reyes입니다. (출처: notes.txt)

You: what did it replace?

Claude: Northstar는 2025년까지 사용하던 기존 스프레드시트 시스템을 대체했습니다. (출처: notes.txt)

You: quit

이것이 완성된 RAG 시스템입니다. 파일을 한 번 읽고, 기억하고, 요청 시 파일에 대한 질문에 답변하며, 매번 출처를 제공합니다.

새 파일을 추가할 때 알아두어야 할 사항. 데이터베이스가 이제 한 번만 구축되므로 documents에 새 파일을 넣어도 자동으로 표시되지 않습니다. 새 파일을 로드하려면 chroma_db 폴더를 삭제하고 스크립트를 한 번 실행하세요. 폴더의 모든 항목으로 처음부터 다시 구축됩니다.

선택 사항: 브라우저에 채팅 창 제공

터미널도 작동하지만 실제 채팅 창을 원한다면 Streamlit을 사용하여 약 20줄로 추가할 수 있습니다.

1. 설치합니다. 터미널에서 다음을 실행합니다.

bash
1pip install streamlit

2. 같은 폴더에 app.py를 만들고 다음을 붙여넣습니다. rag.py의 answer 함수를 재사용합니다.

python
1import streamlit as st
2from rag import answer
3
4st.title("Chat with your documents")
5
6if "history" not in st.session_state:
7 st.session_state.history = []
8
9question = st.chat_input("Ask about your files...")
10
11if question:
12 reply = answer(question)
13 st.session_state.history.append((question, reply))
14
15for q, a in st.session_state.history:
16 st.chat_message("user").write(q)
17 st.chat_message("assistant").write(a)

3. 실행합니다. 터미널에서 다음을 실행합니다(참고: python이 아닌 streamlit run).

bash
1streamlit run app.py

브라우저에서 자동으로 채팅 창이 열립니다. 질문을 입력하면 출처와 함께 답변을 얻을 수 있습니다. 터미널과 동일하지만 보기에 더 좋습니다.

한 가지 참고 사항: 이 기능이 작동하려면 7단계의 질문 루프가 가져오기 시 실행되지 않아야 합니다. rag.py 하단의 해당 루프를 if __name__ == "__main__": 으로 감싸서 rag.py를 직접 실행할 때만 실행되고 app.py에서 가져올 때는 실행되지 않도록 하세요.

일반 질문에도 답변하도록 하기

일반 질문에도 답변하도록 하려면. 현재 시스템은 파일에서만 답변하므로 "베네수엘라의 수도는 어디인가요?"와 같은 질문에 대해 Claude가 답을 알고 있음에도 "문서에 없습니다"라고 답합니다. Claude가 자체 지식에 의존하도록 하려면 rag.py를 열고 6단계의 system=(...) 블록을 찾아 다음 줄을 바꾸세요.

python
1"답변이 맥락에 없으면 모른다고 말하세요."

이 부분은:

python
1"답변이 맥락에 없으면 일반적인 지식을 바탕으로 답변하되, 그렇게 하고 있다는 점을 알리세요."

저장하고 다시 실행하세요. 이제 파일에서 먼저 답변을 찾고, 파일에 내용이 없으면 일반적인 지식으로 대체하면서 어떤 것을 사용했는지 알려줍니다.

마무리

이제 작동하는 RAG 시스템을 구축했습니다. 자신의 파일을 읽고, 중요한 부분을 찾아내며, Claude가 매번 정확한 출처와 함께 답변하도록 합니다. 이 동일한 설정은 몇 개의 노트부터 전체 지식 베이스까지 확장 가능합니다.

여기서부터는 원하는 곳 어디든 연결할 수 있습니다: Obsidian 보관함, 업무 문서, 저장된 연구 자료 등. 파일을 넣고, 한 번 재구축한 후 질문을 시작하세요. 여기서 배운 모든 것(청크, 임베딩, 검색, 답변)은 여러분이 본 모든 "문서와 대화하기" 도구의 동일한 핵심 기술입니다.

도움이 되셨다면 제 프로필로 와서 팔로우해 주세요. 저는 기술, AI, 그리고 실제로 작동하는 시스템에 대해 글을 씁니다.

안녕,

[@undefinedKi**](https://x.com/@undefinedKi

YouMind에서 다시 만들기

Turn one viral article into a full content workflow

Collect the source, decode the pattern, create assets, draft the story, and distribute from one AI workspace.

Explore YouMind
크리에이터를 위해

당신의 Markdown을 깔끔한 𝕏 글로

직접 쓴 장문을 올릴 때 이미지, 표, 코드 블록을 𝕏에 맞게 정리하는 일은 번거롭습니다. YouMind는 전체 Markdown 초안을 깔끔하고 바로 게시할 수 있는 𝕏 글로 바꿔 줍니다.

Markdown → 𝕏 사용해 보기

분석할 패턴 더 보기

최근 바이럴 아티클

더 많은 바이럴 아티클 보기