I3K RAG Engine
자체 문서에 대해 질문하세요. 모든 것이 사용자의 장치에서 실행됩니다.
License: AGPL v3
Release
Rust
자체 호스팅(self-hosted) 검색 증강 생성(Retrieval-Augmented Generation, RAG) 시스템입니다. 문서를 업로드하고 일반 언어로 질문하면, 해당 문서가 실제로 말하는 내용에 근거한 답변을 출처와 함께 얻을 수 있습니다. 데이터는 절대 서버를 떠나지 않으며, 원격 측정(telemetry) 기능이 없고 외부 API로 아무것도 전송되지 않습니다.
이는 Rust로 완전히 재작성된 버전입니다. 1.x 릴리스는 Python 스택이었으며, Docker Compose 아래 네 개의 컨테이너(백엔드, 프론트엔드, Qdrant, Ollama)를 사용했습니다. 이 중 두 개는 사용자 장치에서 구축해야 했고, 상태 유지를 위해 일곱 개의 볼륨이 필요했습니다. 하지만 이것은 단일 바이너리입니다. Qdrant와 추론 엔진 자체를 시작하며, 구성하거나 빌드할 것이 아무것도 없습니다.
재작성은 아래 1.0부터 번호를 다시 매겼기 때문에, 대체하는 1.x 라인보다 낮은 번호가 부여되었습니다. 이는 아직 저장 레이아웃과 HTTP 인터페이스가 확정되지 않은 새로운 코드베이스입니다. Python 버전은 python-legacy 브랜치와 1.x 태그에 보존되어 있으니, 1.x에서 업그레이드하는 방법을 참조하세요.
왜 (Why)
대부분의 RAG 시스템은 사용자의 문서를 다른 사람의 API로 전송하거나, 단 하나의 질문을 하기 위해 다섯 개의 컨테이너를 직접 구성하도록 요구합니다. 이 시스템은 그 어느 것도 하지 않습니다.
- 단일 바이너리(One binary). Docker도, Compose도, Java도 필요 없습니다. 첫 실행 시 필요한 모든 것(벡터 데이터베이스, 추론 엔진, 모델, OCR 데이터)을 다운로드하고 sha256으로 검증한 다음, 스스로 실행합니다.
- 진정한 오프라인(Genuinely offline). 첫 실행 후에는 네트워크가 전혀 필요하지 않습니다.
- 감사 가능(Auditable). AGPL-3.0 라이선스이며, 사용자의 데이터에 접근하는 모든 줄을 읽을 수 있습니다.
규제, 개인 정보 보호 또는 데이터 주권 문제 때문에 클라우드 RAG를 사용할 수 없는 사람들을 위해 제작되었습니다: 로펌, 헬스케어, 금융, 공공 행정 분야.
플랫폼에 맞는 tarball을 releases 페이지에서 다운로드하세요.
— CHANGELOG.md에는 각 버전별 변경 사항이 기록되어 있습니다:
| 파일 | 용도 |
|---|
linux-x86_64 | Linux PC 또는 서버 (x86_64) |
| ... | |
| 매 tarball은 임베딩 단계(bge-m3, Candle를 통해 이 바이너리 내부에서)를 CPU로 실행합니다. 이것이 GPU가 사용되지 않는다는 의미는 아닙니다: eullm — 별도의 프로세스로 시작되어 자동으로 업데이트 상태를 유지하는 — 은 시작 시 NVIDIA GPU를 감지하고 모든 플랫폼에서 채팅 모델에 사용하며, eullm 0.6.82 버전부터는 요청 시 임베딩에도 사용합니다(참고 Architecture). | |
| 따로 GPU 빌드를 하거나 다운로드할 필요가 없습니다. | |
mkdir i3k-rag-engine-v0.2.5-linux-x86_64
tar -xzf i3k-rag-engine-v0.2.5-linux-x86_64.tar.gz -C i3k-rag-engine-v0.2.5-linux-x86_64
cd i3k-rag-engine-v0.2.5-linux-x86_64
...
(tarball 자체의 내용은 플랫합니다 — 바이너리, .env.example, frontend/dist/ — 내부 폴더로 감싸져 있지 않으므로, 먼저 mkdir을 하거나 원하는 설치 위치에 바로 압축을 풀면 됩니다.)
최초 실행 시 약 12 GB의 구성 요소를 다운로드하고 각 구성 요소가 고정된 sha256 값과 일치하는지 확인합니다 — 주로 언어 및 임베딩 모델입니다. 시간이 걸릴 수 있습니다. 이후 시작은 즉시 이루어집니다.
준비되면 브라우저가 **http://localhost:8000**에서 열립니다. 초기 관리자 비밀번호는 로그에 출력됩니다:
SAVE THIS PASSWORD — it will not be shown again!
원하는 경우 사전에 .env 파일의 AUTH__ADMIN_DEFAULT_PASSWORD를 설정하세요.
업그레이드
DATA__DIR는 실행 파일이 위치한 디렉터리를 기본값으로 사용하며(아래 Configuration 참조), 모든 구성 요소—qdrant, eullm, 채팅 및 임베딩 모델—는 누락되었거나 고정된 sha256 값에 실패할 경우에만 이 디렉터리로 가져와집니다(bootstrap::ensure_component). 따라서 새로운 릴리스의 tarball을 기존 설치본 위에 추출하는 것(같은 디렉터리에서 바이너리, .env.example, frontend/dist/를 덮어쓰는 경우)은 이미 다운로드된 모든 것을 재사용합니다—해당 릴리스가 실제로 다른 버전으로 고정하지 않는 한 아무것도 다시 가져오지 않습니다. 사용자의 .env 파일은 절대 건드리지 않습니다(tarball은 항상 .env.example만 배포합니다). 대신 신규의 빈 디렉터리에 추출하는 경우—Quick start 기본값—새로운 경로에 아무것도 존재하지 않기 때문에 모든 구성 요소의 다운로드를 처음부터 다시 시작합니다.
기능
문서. PDF(OCR을 통한 스캔 페이지 포함); Word(DOCX, DOC), OpenDocument text(ODT) 및 RTF; 스프레드시트(XLSX, XLSM, XLSB, XLS, ODS, CSV); 프레젠테이션(PPTX, PPT, ODP), 발표자 노트 포함; HTML, Markdown, 일반 텍스트 및 EPUB 전자책; 이메일(EML, Outlook MSG), 첨부 문서 포함; 그리고 사진(PNG, JPEG, TIFF—다중 페이지 스캔 포함—BMP, GIF, WebP)을 OCR을 통해 읽습니다. 스캔된 PDF는 자동으로 감지됩니다—페이지에서 텍스트가 너무 적게 나오면 라스터화되어 이탈리아어와 영어 Tesseract를 거치고, 동일한 OCR 이미지를 통과합니다.
검색. 문서는 중첩된 청크(overlapping chunks)로 분할되고, BAAI/bge-m3(1024 차원, 100개 이상의 언어 다국어 지원)를 사용하여 임베딩되어 Qdrant에 저장됩니다. 질문도 같은 방식으로 임베딩되고 가장 가까운 구절에서 답변을 얻으며, 각 출처가 표시됩니다.
법률 조항 검색(Article lookup), 법규 모음집용 기능입니다. 임베딩에 있어서는 번호가 거의 의미를 갖지 못하므로, "민법 제2875조", "민법 제1176조 및 1375조"와 같이 조항을 명시하는 질문은 해당 조항 자체보다는 주변 내용을 가져오게 됩니다. 라이브러리가 파일당 하나의 조항을 가지고 있고, 그 이름이 인용되는 방식("민법, 제2875조 - Rubrica.txt")으로 지정되어 있을 경우, 질문에서 언급된 조항은 파일 이름을 통해 검색되고 의미로 찾은 구절들보다 먼저 배치됩니다. 이 기능은 질문이 특정 조항을 명시하고 파일이 해당 규칙을 따를 때만 작동하며, 다른 문서에서는 아무것도 찾지 못하고 비용도 발생하지 않습니다. 기본적으로 활성화되어 있으며, 관리자는 Answers 탭에서 비활성화할 수 있습니다.
채팅(Chat). 대화 기록이 유지되며, 답변은 토큰 단위로 스트리밍되고, 이전 질문에 대한 이력이 다음 질문으로 전달됩니다.
답변(Answers). 모델의 답변 방식—역할, 답변 구조, 인용 방법, 언어 등—은 관리자가 관리자 패널의 Answers 탭에서 설정할 수 있습니다 (최대 8,000자). 검색된 구절, 이력, 그리고 질문은 이러한 지침들 이후에 엔진에 의해 추가됩니다. 변경 사항은 다음 질문부터 적용되며, *기본값 복원(Restore defaults)*을 누르면 내장된 지침이 다시 돌아옵니다. 프롬프트는 모델 자체의 채팅 형식으로 전송되므로 Qwen 이외의 다른 모델들도 깔끔하게 답변합니다.
사용자(Users). 사용자, 슈퍼 유저, 관리자 세 가지 역할에 대한 JWT 인증을 통해 누가 업로드하고 삭제할 수 있는지 제어합니다.
백업(Backups). SQLite 데이터베이스와 Qdrant 스냅샷이 함께 포함된 일일 예약 아카이브를 보유하며, 이 쌍은 일관성을 유지합니다. 또한 실행 중인 설치본에 하나를 복원할 수 있는 관리자 엔드포인트가 있습니다. 백업 파일은 BACKUP__DIR 아래의 로컬 파일이며, 어떠한 것도 어디에도 업로드되지 않습니다.
아키텍처(Architecture)
API 및 서버
Rust, axum
...
임베딩 모델은 의도적으로 언어 모델보다 먼저 로드됩니다: eullm은 시작 시 관찰하는 여유 VRAM에서 자체 GPU 오프로드를 수행하므로, 임베딩 모델이 이미 차지한 메모리를 확인해야 합니다.
설정 (Configuration)
설정은 환경 변수 또는 .env 파일을 사용하며, 레벨 구분자로 __를 사용합니다. 기본값이 없는 것은 정확히 하나입니다:
나머지 모든 것은 선택 사항입니다:
SERVER__HOST=127.0.0.1
SERVER__PORT=8000
...
EMBEDDINGS__REQUIRE_GPU는 알아두면 유용한 설정입니다: 이 설정이 없으면, 손상된 CUDA 설정은 CPU로 저하되며 데이터 수집(ingestion) 시간이 몇 초에서 몇 분으로 늘어나는데, 이는 쉽게 눈치채지 못할 수 있습니다. 폴백(fallback)은 항상 에러 레벨로 기록되고 GET /api/info에서 노출됩니다.
다른 기기에서 접근하기 (Reaching it from another machine)
SERVER__HOST의 기본값은 127.0.0.1이므로, 별도의 설정 없이 엔진은 실행된 기기에서만 응답합니다 — 이는 위 빠른 시작 가이드가 설명하는 내용입니다.
이를 0.0.0.0으로 설정하면 네트워크에서 접근할 수 있게 되며, 그렇게 하기 전에 이해해야 할 한 가지 사항이 있습니다: 이 바이너리는 일반 HTTP를 서비스하며 TLS를 종료하지 않습니다. 라우팅 가능한 주소에서는 로그인 비밀번호와 이후의 모든 세션 토큰이 평문(clear text)으로 네트워크를 가로지르므로, 트래픽을 볼 수 있는 누구에게나 읽힐 수 있습니다. 따라서 SERVER__HOST가 루프백 주소가 아닐 경우, 서버는 시작 시 경고를 기록합니다. 바로 이 이유 때문에 그렇습니다.
그러므로 TLS를 종료하는 무언가 뒤에 노출해야 합니다. Caddy의 경우 전체 설정 파일이 필요합니다:
rag.example.com {
reverse_proxy 127.0.0.1:8000
}
이 설정에서는 SERVER__HOST를 127.0.0.1로 유지하세요: 프록시가 루프백을 통해 엔진에 접근하며, 오직 프록시만이 직접적으로 접근할 수 있습니다.
이 바이너리는 사용자의 하드웨어에서 자체적으로 벤치마킹을 수행하고 결과를 문서화할 수 있습니다:
./i3k-rag-engine --bench /path/to/document.pdf
이는 검색(ingestion) 및 추론(inference)의 각 단계를 시간별로 기록하는 Markdown 보고서를 작성합니다 — 추출(extraction), 청킹(chunking), 임베딩(embedding), 업서트(upsert), 프리필(prefill), 디코드(decode) 등— 그리고 시간이 어디에 쓰였는지 보여주는 차트가 포함됩니다. --bench-live는 대신 세션의 모든 실제 검색 및 질의를 기록하고 종료 시점에 보고합니다.
1.x 버전에서 업그레이드하기
자동 마이그레이션 경로가 없습니다. 왜냐하면 리라이트는 저장소 레이아웃과 런타임 모델을 모두 변경했기 때문입니다: 1.x는 컨테이너 간에 공유되는 Docker 볼륨에 상태를 유지했고, 0.x는 바이너리 옆의 단일 데이터 디렉토리에 상태를 유지합니다.
이 두 버전은 한 대의 컴퓨터에서 동시에 실행될 수 없습니다. 둘 다 8000, 6333, 11434 포트를 필요로 하기 때문입니다. 먼저 Compose 스택을 중지하십시오 — 어차피 다시 업로드할 것이므로, 이 두 가지가 모두 필요한 순간은 없습니다. 1.x 데이터는 볼륨을 제거하기 전까지 해당 Docker 볼륨에 남아 있으므로, Compose를 다시 실행하여 되돌아갈 수 있습니다. 만족하면, docker compose down -v로 완전히 폐기하십시오.
1.x Python 버전은 python-legacy 브랜치와 1.x 태그에서 계속 사용할 수 있습니다. 더 이상 개발되지는 않지만, 삭제된 것은 없습니다.
소스에서 빌드하기
대부분의 사람들은 필요하지 않습니다: 릴리스 tarball은 자체적으로 완결되어 있기 때문입니다. 엔진을 수정하거나 우리가 배포하지 않는 플랫폼을 목표로 하려면, 네이티브 종속성과 기능 플래그에 대한 내용은 BUILD.md를 참조하십시오.
cargo build --release --features cuda
개인 정보 보호 및 보안
- 외부 호출 없음. 첫 실행 후에는 네트워크 접근이 필요하지 않습니다.
- 텔레메트리 없음. 아무것도 수집하거나 전송되지 않습니다.
- 로컬 모델. 언어 모델과 임베딩 모두 사용자의 하드웨어에서 실행됩니다.
- 검증된 구성 요소. 다운로드되는 모든 구성 요소는
manifest.toml에 고정된 sha256 값과 비교되며, 불일치 시 실행이 중단됩니다.
- 제한된 로그인. 하나의 계정에 대한 반복적인 실패는 증가하는 지연 시간을 초래하며, 한 번에 몇 개의 비밀번호 인증만 실행될 수 있습니다. 나머지는 해시 비용을 발생시키지 않고
429를 반환합니다. 스크립트 클라이언트는 다음 두 가지 모두를 예상해야 합니다: 로그인이 몇 초가 걸리거나, 429로 돌아와 재시도할 가치가 있을 수 있다는 점입니다.
취약점은 공개 이슈보다는 비공개로 보고해 주십시오.
인용 방법
@software{i3k_rag_engine,
author = {Marchetti, Francesco},
title = {i3k RAG Engine: self-hosted document intelligence},
...
보관된 1.x Python 릴리스는 자체 DOI를 가지고 있습니다:
10.5281/zenodo.20413005.
라이선스
AGPL-3.0 전용 — [LICENSE]를 참조하십시오.
이것을 실행하고, 읽고, 수정하고, 공유할 수 있습니다. 이것을 기반으로 구축하기 전에 알아야 할 유일한 의무는 AGPL 섹션 13입니다: 만약 사용자가 네트워크를 통해 수정된 버전을 제공한다면, 해당 사용자에게도 상응하는 소스 코드를 제공해야 합니다. 사적으로 실행하는 것(자사 회사 내부에서 자체 문서로)은 그러한 의무가 없으며, 이것이 이와 같은 자체 호스팅 시스템의 일반적인 경우입니다.
상업용 라이선스
I3K Technologies Srl이 저작권을 보유하며, AGPL 약관을 수락할 수 없는 조직을 위해 별도의 상업적 라이선스로도 이 소프트웨어를 제공합니다. 동일한 라이선스가 자체 독점 제품인 i3k RAG Pro가 이 코드를 기반으로 구축할 수 있게 합니다. 문의: [email protected]
이전 릴리스