지난 10년 동안 고객을 위한 엔터프라이즈 검색을 구축했습니다. 그리고 그 모든 것을 오픈 소스로 공개했습니다.
요약
엔터프라이즈 검색 경험을 바탕으로 구축된 오픈 소스 RAG 플랫폼 'Viglet Turing ES'를 소개합니다. 기존 검색 엔진(Solr, Elasticsearch 등)을 교체하지 않고 그 위에 구축하여 하이브리드 검색과 신뢰할 수 있는 답변 생성을 지원합니다.
핵심 포인트
- 기존 검색 엔진(Solr, Elasticsearch)을 유지하며 그 위에 레이어로 작동
- 하이브리드 검색 및 플러그형 리랭커를 통한 검색 품질 최적화
- 인라인 인용과 근거 확인을 통해 신뢰할 수 있는 RAG 답변 제공
- 데이터 보안을 위해 로컬 모델 및 에어갭(Air-gapped) 환경 지원
- 검색과 RAG가 동일한 인덱스를 공유하는 에이전트 구조
지난 10년 동안 제가 수행한 모든 엔터프라이즈 검색 (Enterprise Search) 프로젝트는 똑같은 방식으로 끝났습니다. 검색 엔진 (Solr 또는 Elasticsearch), 패싯 (Facets)과 관련성 (Relevance)을 위한 일련의 글루 코드 (Glue code), 그리고 최근 몇 년 동안에는 측면에 덧붙여진 RAG 파이프라인 (RAG pipeline), 마지막으로 그 위에 구축된 에이전트 프레임워크 (Agent framework)였습니다. 세 개의 스택, 세 세트의 버그, 그리고 반복되는 하나의 고객 요구사항: 데이터가 우리 네트워크를 벗어나서는 안 된다는 것이었습니다.
그 구축 과정을 충분히 반복한 후, 저는 이를 하나의 플랫폼으로 만들었습니다. 올해 저는 이 모든 것을 Apache 2.0 라이선스 하에 오픈 소스로 공개했습니다: Viglet Turing ES.
이 포스트는 제가 가장 중요하다고 생각하는 세 가지 설계 결정과, 단 하나의 명령어로 이를 시도하는 방법에 대해 다룹니다.
결정 1: 이미 보유하고 있는 엔진에서 실행하세요
"AI 검색"을 평가하는 대부분의 팀은 이미 Solr 또는 Elasticsearch를 운영하고 있습니다. RAG를 사용하기 위해 새로운 엔진으로 마이그레이션(Migrate)하라고 요구하는 것은 시작조차 할 수 없는 일입니다.
따라서 Turing은 엔진을 교체하는 대신 엔진 위에 자리 잡습니다. 하나의 쿼리 API (Query API) 뒤에서 Solr, Elasticsearch 또는 임베디드 Lucene 인덱스 (Embedded Lucene index)가 작동합니다. 하이브리드 검색 (Hybrid retrieval)은 키워드 (BM25) 결과와 벡터 (Vector) 결과를 상호 순위 결합 (Reciprocal Rank Fusion) 방식으로 융합하며, 플러그형 리랭커 (Pluggable reranker) (LLM, Cross-encoder 또는 Cohere)가 페이지 순서를 재정렬합니다. 설치된 것이 아무것도 없다면, 임베디드 Lucene 엔진을 통해 전체 스택이 단일 컨테이너 (Container)에서 실행됩니다.
동일한 개념이 모델에도 적용됩니다: OpenAI, Anthropic, Gemini, Azure, 또는 Ollama를 통한 완전한 로컬 실행까지 가능합니다. 에어갭 (Air-gapped) 배포의 경우, 로컬 모델과 로컬 임베딩 (Local embeddings), 그리고 임베디드 Lucene의 조합은 말 그대로 아무것도 기계 외부로 나가지 않음을 의미합니다.
결정 2: "답변 없음"을 포함하여 감사 가능한 답변
기업들이 실제로 요구하는 기능은 채팅이 아닙니다. 그것은 바로 **신뢰 (Trust)**입니다. 고객 지원 포털이나 인트라넷 (Intranet)은 확신에 찬 오답을 내보내서는 안 됩니다.
Turing의 RAG (Retrieval-Augmented Generation) 채팅은 정확한 소스 구절로 추적 가능한 인라인 인용 (inline citations)과 함께 답변을 스트리밍합니다. LLM (Large Language Model)이 무엇인가를 보기 전에, 관련성 게이트 (relevance gate)가 약한 매칭 결과들을 걸러냅니다. 생성 후에는 선택적인 근거 확인 (groundedness check)을 통해 소스가 지원하지 않는 주장에 플래그를 표시합니다. 그리고 인덱스 내의 어떤 것도 기준을 통과하지 못하면, 어시스턴트는 즉흥적으로 답변하는 대신 결정론적인 (deterministic) "여기에는 해당 내용이 없습니다"라는 답변을 제공합니다.
이 마지막 동작은 사소하게 들릴 수 있습니다. 하지만 실제로 이는 데모와 규제 대상 조직이 사용자 앞에 내놓을 수 있는 서비스 사이의 차이를 만듭니다.
결정 3: 동일한 인덱스에 기반을 둔 에이전트 (agents)
검색과 RAG가 인덱스를 공유하게 되면, 에이전트 (agents)는 흥미로워집니다. 단순히 답변하는 것을 넘어 콘텐츠에 따라 행동할 수 있기 때문입니다. Turing의 에이전트는 도구 호출 (tool calling)을 수행하고, Docker 샌드박스 (sandbox)에서 기술 (skills)을 실행하며, MCP 서버에 연결합니다. 따라서 귀하의 문서를 인용하는 것과 동일한 어시스턴트가 귀하의 내부 API를 호출할 수도 있습니다.
직접 시도해보기
단 한 번의 명령으로, 계정 없이, 텔레메트리 (telemetry) 없이 실행 가능합니다:
docker run -p 2700:2700 ghcr.io/openviglet/turing-ce
콘솔은 http://localhost:2700/console에서 실행됩니다 (첫 실행 시 TURING_ADMIN_PASSWORD 환경 변수로 관리자 비밀번호를 설정하세요).
검색은 단순한 REST 호출입니다:
curl "http://localhost:2700/api/sn/sample-site/search?q=enterprise+search&rows=10&_setlocale=en_US"
그리고 RAG 채팅은 SSE (Server-Sent Events)를 통해 스트리밍됩니다:
curl "http://localhost:2700/api/sn/sample-site/chat?q=What+is+enterprise+search"
프론트엔드에 검색을 임베딩 (embedding)하려는 경우 TypeScript SDK (의존성이 없는 vanilla 버전과 React 버전)가 제공됩니다. 사이트의 라이브 데모는 동일한 SDK를 사용하여 Turing의 자체 문서를 기반으로 실행되므로, 아무것도 설치하기 전에 인용된 답변을 확인할 수 있습니다: turing.viglet.org/#playground
리포지토리 (repo)에 대한 솔직한 한 마디
공개 리포지토리 (repository)는 릴리스(release)마다 깔끔하게 스냅샷 형태로 제공됩니다. 이는 일상적인 개발이 제가 공개할 수 없는 고객 업무를 바탕으로 진행되기 때문입니다. 얇은 커밋 히스토리 (commit history)가 언뜻 보기에 이상해 보일 수 있다는 점을 알고 있기에, 여러분이 궁금해하시기 전에 여기서 미리 말씀드리고 싶습니다. 이슈 (Issues)와 풀 리퀘스트 (PRs)는 매우 실질적으로 운영되고 있으며, 다음 릴리스에 반영됩니다.
피드백을 받고 싶은 부분
만약 여러분이 Elasticsearch를 셀프 호스팅 (self-host)하거나 로컬 LLM (local LLMs)을 실행하고 있으며, 하이브리드 랭킹 (hybrid ranking), 인용 UX (citation UX), 또는 검색 플랫폼이 답변을 거부해야 하는 기준 등에 대한 의견이 있다면 꼭 듣고 싶습니다. 리포지토리는 github.com/openviglet/turing-ce이며, 문서는 docs.viglet.org에서 확인하실 수 있습니다.
읽어주셔서 감사합니다!
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기