<div align="center">
<img src="https://raw.githubusercontent.com/harinaralasetty/CORAG/HEAD/CORAG_ICON.png" alt="CORAG logo" width="96">
CORAG
브라우저에서 PDF 및 음성 녹음 파일로 채팅하세요.
PDF 및 오디오 문서용 오픈소스 RAG(Retrieval-Augmented Generation) 채팅 앱으로, Python과 NiceGUI로 작성되었습니다. 파일을 업로드하고 일반 언어로 질문하며 Google Gemini 또는 Anthropic Claude, 혹은 Ollama를 통한 로컬 모델로부터 답변을 받을 수 있습니다. 이때 파일명(및 PDF 페이지) 출처가 명시되며, HNSW 벡터 검색, 클라우드 또는 로컬 임베딩을 사용하고 재시작 후에도 채팅 기록이 남아있습니다.
Apache-2.0 license
Python 3.13
CI
빠른 시작(Quick start) · 왜 CORAG인가(Why CORAG) · 무엇을 하는가(What it does) · 작동 방식(How it works) · 스크린샷(Screenshots) · FAQ · 문서(Docs)
git clone https://github.com/harinaralasetty/CORAG.git && cd CORAG
pip install -r requirements.txt
cp .env.example .env
...
<img src="https://raw.githubusercontent.com/harinaralasetty/CORAG/HEAD/docs/assets/flow.svg" alt="CORAG 파이프라인: PDF, MP3 또는 WAV 파일이 추출되어 1,000자 청크로 분할되고 임베딩되어 HNSW 인덱스에 저장됩니다. 질문은 재구성되고 가장 가까운 20개 청크가 검색되며, Gemini 또는 Claude가 출처 파일을 명시하여 답변합니다." width="880">
</div>
[!NOTE]
Google Gemini 또는 Anthropic Claude API 키를 사용하면, 각 질문은 해당 제공업체와 함께 파일의 일치하는 구절을 전송받습니다. 문서를 로컬 컴퓨터에 유지하려면, 로컬 임베딩 모델과 함께 로컬 Ollama 모델(기본 OLLAMA_BASE_URL에서 사용 가능)을 사용하세요. 오디오는 항상 Google의 Web Speech 서비스를 통해 전사됩니다.
왜 CORAG인가 (Why CORAG)
PDF나 녹음 파일 스택을 가지고 있고, 내용을 일일이 스크롤하는 대신 질문하고 싶을 때.
- 여러 파일에 걸쳐 질문하기. 원하는 만큼 많은 PDF, 텍스트 또는 Markdown 파일을 채팅에 추가하거나 MP3 및 WAV 녹음을 추가한 다음, 이들을 함께 질문할 수 있습니다. 모든 구절은 파일 이름으로 레이블이 지정되며, PDF 구절은 페이지 번호로 레이블이 지정되어 답변의 출처를 알 수 있습니다.
- 사용할 모델 선택하기. 드롭다운 메뉴에서 Gemini, Claude 및 로컬 Ollama 모델 간에 질문별로 전환할 수 있습니다.
- 키가 필요 없는 임베딩. Google, Voyage 또는 OpenAI 임베딩을 사용하거나 API 키가 필요 없는 로컬 sentence-transformers 모델을 사용할 수 있습니다.
- 재시작에도 유지되는 채팅. 채팅, 파일 목록 및 검색 인덱스는 로컬
data/ 폴더에 저장됩니다.
- 도움이 될 때만 도구 사용. Gemini 모델은 계산기 및 선택적 웹 검색(SerpApi 또는 Tavily)을 호출할 수 있습니다.
- 간결하고 읽기 쉬운 코드. 색인화(ingestion), 검색(retrieval), 추론(inference) 및 도구에 대한 순수 Python 모듈과 API 키가 필요 없는 테스트를 제공합니다.
빠른 시작
필요한 것: Python 3.13 (의존성이 고정되고 테스트된 버전)과 Google AI Studio에서 얻은 API 키(Gemini) 또는 Anthropic Console에서 얻은 API 키(Claude), 혹은 키 없이 실행하려면 다운로드한 모델이 있는 Ollama (예: ollama pull llama3.2)가 필요합니다.
1. 코드 받기 및 가상 환경에 설치하기:
git clone https://github.com/harinaralasetty/CORAG.git
cd CORAG
python -m venv .venv
...
2. 키 추가하기. 예시 설정 파일인 .env.example을 복사하고, 텍스트 편집기에서 .env를 열어 GOOGLE_API_KEY 또는 ANTHROPIC_API_KEY를 채우거나, CORAG_OLLAMA_MODELS=llama3.2로 설정합니다 (다운로드한 Ollama 모델 이름들을 쉼표로 구분).:
3. 실행하고 http://localhost:8080 열기:
4. 사용하기. 오른쪽의 문서(Documents) 패널에 PDF, TXT, Markdown, MP3 또는 WAV 파일을 드롭하고, "처리됨(Processed)"을 기다린 후 질문을 입력합니다. 왼쪽 패널에서 모델과 임베딩 제공업체를 선택하고, **+**를 눌러 새 채팅을 시작합니다.
또는 Python 설정 없이 Docker로 실행합니다. 저장소를 클론하고, 2단계와 같이 .env 파일을 생성한 다음, 컨테이너를 빌드 및 시작하고 http://localhost:8080을 엽니다:
docker build -t corag .
docker run --rm -p 127.0.0.1:8080:8080 -v "$PWD/.env:/app/.env:ro" -v corag-data:/data corag
채팅 기록, 인덱스 및 다운로드된 로컬 임베딩 모델은 corag-data 볼륨에 저장됩니다. Docker Desktop을 사용하여 컨테이너에서 컴퓨터에 실행되는 Ollama를 사용하려면, .env 파일에 OLLAMA_BASE_URL=http://host.docker.internal:11434/v1로 설정합니다.
<details>
<summary><b>설정, 모델, 저장소 및 테스트</b></summary>
<br>
환경 변수 (.env 파일에 있음, .env.example 참조):
| 변수 | 기능 |
|---|
GOOGLE_API_KEY | Gemini 모델 및 Google 임베딩. |
| ... | |
기본값. 기본 모델은 gemini-2.5-flash이며, Anthropic 키만 설정된 경우 claude-haiku-4-5-20251001이거나, 클라우드 키가 둘 다 설정되지 않은 경우 첫 번째 CORAG_OLLAMA_MODELS 항목입니다. 기본 임베딩 제공업체는 순서상 Google, Voyage, OpenAI 중 키가 있는 첫 번째 항목입니다. 아무것도 설정되지 않은 경우 로컬 sentence-transformers/all-MiniLM-L6-v2 모델이 사용됩니다 (최초 사용 시 다운로드). | |
선택기 내 모델 목록 (config.py의 models_list): gemini-2.5-flash, gemini-2.5-pro, gemini-2.5-flash-lite, gemini-2.0-flash, gemini-flash-latest, gemini-pro-latest, claude-haiku-4-5-20251001, claude-sonnet-4-6, claude-opus-4-7와 각 CORAG_OLLAMA_MODELS 항목에 대한 ollama/<name>이 추가됩니다.
Ollama 컨텍스트 창(context window). CORAG 프롬프트는 최대 20개의 패시지(passage)와 각 패시지가 1,000자이며 채팅 기록을 포함할 수 있습니다. Ollama는 자체적으로 컨텍스트 창보다 긴 프롬프트를 잘라냅니다. 만약 답변에서 일부 패시지가 누락된다면, OLLAMA_CONTEXT_LENGTH=16384 ollama serve와 같이 더 큰 창으로 Ollama를 시작하세요.
임베딩 모델(Embedding models) (retrieval/embeddings_router.py): Google의 models/gemini-embedding-001, Voyage의 voyage-3-lite, OpenAI의 text-embedding-3-small, 로컬 환경의 sentence-transformers/all-MiniLM-L6-v2를 사용할 수 있습니다. 채팅은 시작할 때 사용한 임베딩 제공업체를 유지하며, 다른 제공업체는 새 채팅에서 선택해야 합니다.
청크 분할 및 검색(Chunking and search) (config.py): 청크는 1,000자로 설정하고 중복(overlap)은 200자입니다 (CHUNK_SETTINGS); HNSW 인덱스는 M=30, ef_construction=500을 사용합니다. 파일의 처음 2,000자(THEME_LENGTH)는 질문 재구성(rephrasing)에 도움을 줍니다.
업로드(Uploads). 파일당 최대 200MB까지, 채팅당 여러 파일을 업로드할 수 있습니다. 같은 이름의 파일을 채팅에서 두 번 업로드하는 것은 건너뜁니다.
저장소(Storage). 채팅은 data/chat_threads_info.json에 저장되며, 각 채팅의 인덱스는 data/<채팅 ID>/에 저장됩니다. 깨끗하게 시작하려면 data/ 폴더를 삭제하세요.
종속성(Dependencies). requirements.txt에는 직접적인 종속성이 나열되어 있으며, requirements-lock.txt에는 정확히 고정된 세트가 있습니다. google_search_results는 serpapi 모듈을 제공하므로, 별도로 serpapi 패키지를 설치하지 마세요. 충돌이 발생합니다.
테스트(Tests):
pip install -r requirements-dev.txt
pytest
테스트는 가짜 임베딩 및 모델을 사용하므로 API 키가 필요하지 않습니다.
</details>
무엇을 하는가 (What it does)
| 영역 | 상세 내용 |
|---|
| 문서(Documents) | 리가처 및 줄 바꿈 정리 기능이 포함된 PDF 텍스트 추출; 일반 텍스트 및 Markdown (UTF-8); 최대 45초 분량의 MP3 및 WAV 음성-텍스트 변환; 채팅당 여러 파일 지원 |
| ... | |
<div align="center">
<img src="https://raw.githubusercontent.com/harinaralasetty/CORAG/HEAD/Flowchart.png" alt="CORAG 구성 요소: 문서 및 대화 메모리가 LLM 에이전트에 피드되며, 이 에이전트는 동적 프롬프팅, HNSW 검색을 사용한 임베딩 및 재순위 지정, 그리고 검색 및 계산기 도구 키트를 사용합니다." width="760">
</div>
- 에이전트(
inference/inference_manager.py)는 각 질문을 처리합니다: 질문을 재구성하고(rephrase), 이를 임베딩하며, 채팅 인덱스에서 가장 가까운 구절들을 가져와 해당 구절들, 파일 이름, 그리고 이전 메시지들과 함께 하나의 프롬프트를 구성합니다.
- Gemini 모델은 계산기 또는 웹 검색을 호출할 수 있습니다. 도구의 출력 결과는 프롬프트에 추가되고 모델에게 다시 질문이 주어집니다. Claude 및 Ollama 모델은 도구 없이 프롬프트를 받습니다.
- 검색(Retrieval)은 항상 최대 20개의 구절을 전송하며, 답변의 품질은 추출된 텍스트만큼만 좋습니다: 스캔된 PDF에 대한 OCR 기능은 없습니다.
자세한 내용은 Architecture를 참고하세요.
스크린샷
<img src="https://raw.githubusercontent.com/harinaralasetty/CORAG/HEAD/Screenshot.png" alt="사용자가 업로드한 자두 과수원 핸드북 PDF에서 질문에 답변하는 CORAG: 모델 선택기가 ollama/qwen2.5:3b로 설정되어 있고, 왼쪽에는 로컬 임베딩이, 중앙에는 7월 말과 섭씨 4도라는 출처가 명시된 답변이, 오른쪽의 문서 패널에는 PDF가 있습니다." width="880">
현재 인터페이스는 하나의 컴퓨터에서 완전히 실행됩니다: Ollama를 통해 로컬 qwen2.5:3b 모델, 로컬 임베딩, 그리고 API 키 없이 작동합니다. 답변은 업로드된 2페이지짜리 PDF에서 나옵니다.
FAQ
무료인가요? 코드는 Apache-2.0 하에 무료입니다. Google, Anthropic 및 선택적 임베딩/검색 제공업체들은 자체 가격 정책에 따라 API 사용량을 청구합니다. 기본 OLLAMA_BASE_URL에서 실행되는 Ollama 모델은 비용 없이 사용자 자신의 컴퓨터에서 작동합니다.
내 데이터가 내 컴퓨터를 떠나나요? Gemini나 Claude 같은 경우, 네: 질문과 검색된 구절이 해당 제공업체로 전송됩니다. 기본 OLLAMA_BASE_URL의 Ollama 모델과 로컬 임베딩 모델을 사용하면 문서와 질문은 컴퓨터에 머무릅니다. 오디오는 항상 Google의 Web Speech 서비스로 전송됩니다. 추출된 텍스트, 채팅 기록 및 인덱스는 로컬 data/ 폴더에만 저장됩니다. 로컬 임베딩 모델을 사용하므로 문서 텍스트가 임베딩을 위해 어딘가로 전송되지 않습니다.
어떤 파일을 업로드할 수 있나요? 텍스트 레이어가 있는 PDF, UTF-8 형식의 .txt 및 .md 파일, MP3 또는 WAV 오디오(60분 이상 녹음은 거부됩니다). 스캔된 PDF는 먼저 OCR이 필요합니다.
기존 채팅에서 임베딩 제공업체를 변경할 수 있나요? 안 됩니다. 다른 제공업체의 벡터를 혼합할 수 없으므로, 채팅은 처음 사용한 제공업체를 유지합니다. 다른 제공업체를 사용하려면 새 채팅을 시작하세요.
Claude와 Ollama 모델은 계산기나 웹 검색 기능을 사용하지 않는 이유는 무엇인가요? 도구는 Gemini에 한해서 LangChain을 통해 연결되어 있으며, 다른 모델들은 일반 프롬프트만 받습니다.
여러 사람이 하나의 인스턴스를 공유할 수 있나요? 단일 사용자 로컬 앱으로 구축되었습니다. 열린 브라우저 탭은 모두 동일한 채팅 기록을 봅니다.
문서화 (Documentation)
기여 (Contributing)
이슈(Issues)와 풀 리퀘스트(pull requests)를 환영합니다. 풀 리퀘스트를 열기 전에 pytest를 실행하세요 (pip install -r requirements-dev.txt 후). 테스트에는 API 키가 필요하지 않습니다. 질문이나 피드백은 LinkedIn의 Hari Naralasetty에게 보내주세요.
라이선스 (License)
Apache-2.0