Leviathan: 긴 로그를 전부 읽히는 대신 필요한 기록 몇 개만 AI에 건네기
바탕이 된 글: Leviathan: 대용량 티켓과 로그를 grep 대신 수백 토큰의 검색 결과로 에이전트에 건네는 로컬 인덱서
로컬 BM25 인덱서가 합성 정비 기록에서 검색 결과의 토큰을 줄인 자체 벤치마크와, 한국어 검색·최종 답변 정확도·그룹 범위의 한계를 함께 소개합니다.
쉽게 말하면비유하자면 두꺼운 정비 일지를 통째로 건네는 대신, 미리 만들어 둔 색인에서 관련 쪽 몇 장만 뽑아 메모 카드로 건네는 일이다. 다만 색인은 적힌 낱말로 찾기 때문에 질문과 기록의 표현이 다르면 놓칠 수 있다.
- 왜 봐야 하나
- 고객이나 장비마다 기록이 많이 쌓인 데이터를 AI 에이전트에 물어보는 팀이 참고할 만하다. 개발자가 합성 데이터로 한 자체 측정이므로, 자기 데이터로 검색 품질을 먼저 확인해야 한다.
10월 10일 한국어 해설은 10월 6일 v0.1.0이 공개된 Leviathan을 소개한다. 이 도구는 고객 지원 티켓, 설비 정비 기록, 장애 로그처럼 한 대상에 기록이 많이 쌓이는 데이터를 코딩 에이전트가 효율적으로 검색하도록 돕는 로컬 인덱서다. 원본 검색 결과를 통째로 에이전트에 넣으면 수만~수십만 토큰이 필요할 수 있어, Leviathan은 SQLite FTS5 기반 BM25 검색 인덱스를 미리 만들어 질문마다 관련 레코드 몇 건만 짧은 카드로 돌려준다. 개발자가 공개한 합성 설비 정비 기록 100만 건 벤치마크에서 Leviathan은 질문당 중앙값 436토큰, 상위 5건 내 관련 레코드 포함률 99.0%를 기록했고, 비교한 두 grep 전략 중 출력량이 적은 방식은 107,122토큰을 반환했다. 이 도구는 Rust 단일 바이너리로 네트워크 연결이 없고, CLI와 스킬 파일 또는 읽기 전용 MCP 서버로 에이전트에 연결할 수 있다.
알아낸 것
- 합성 정비 기록 100만 건에서 Leviathan의 검색 결과는 질문당 중앙값 436토큰이었다. 질문 낱말로 거른 grep(일치한 줄을 그대로 뽑는 검색) 출력은 중앙값 107,122토큰으로 약 245배였다.
- 100만 건 규모의 질문 200개 가운데 상위 5건 안에 관련 기록이 든 비율은 99.0%였다. 이는 검색 결과만 잰 값이다. AI가 그 결과를 읽고 낸 최종 답의 정확도는 재지 않았다.
- 커뮤니티 작성자가 한국어 기록 세 개로 한 작은 확인에서 '쿠키를'이라고 적힌 기록은 '쿠키'로 찾으면 0건이었다. 조사가 붙은 낱말을 다른 낱말로 다루기 때문이다.
한계와 주의할 점
- 한국어 해설은 10월 10일, 확인한 v0.1.0 릴리스는 10월 6일 공개됐다. 초기 도구의 개발자 자체 벤치마크를 소개하는 글이다.
- 합성 정비 기록 한 구조를 사용했다. 436토큰은 검색 결과 출력의 중앙값이며, hit@5 99.0%도 관련 기록 포함률이다. LLM 최종 답변의 비용·정확도는 측정하지 않았다.
- grep 비교는 간단한 두 전략이고 정확한 장비 키를 미리 줬다. 관련 기록 포함률은 출력 앞 3만 자를 기준으로 하므로 출력 제한이 없는 결과와 다르다.
- 33.4ms는 개발자의 단일 데스크톱에서 프로세스 시작을 포함한 단일 측정이다. 인덱스 구축 시간·추가 저장 공간이 필요하고 작은 데이터에서는 grep이 더 빠를 수 있다.
- BM25는 의미 검색이 아니며 한국어 조사·어미에 취약하다. 커뮤니티의 한국어 세 기록 확인은 대규모 성능 검증이 아니다.
용어 풀이
- BM25
- 검색 결과의 관련성을 점수로 매기는 확률적 순위 함수다. 단어 빈도와 문서 길이를 고려해 질문과 가장 관련 있는 레코드를 찾는다. Leviathan은 FTS5의 BM25 점수에 설정한 가중치를 곱해 결과를 정렬한다.
- FTS5
- SQLite에 내장된 전문 검색(Full-Text Search) 엔진이다. 텍스트를 토큰으로 나누어 인덱스를 만들어 빠르게 검색한다. Leviathan은 이 인덱스를 SQLite 파일 하나에 저장한다.
- 토큰
- 언어 모델이 텍스트를 처리하는 최소 단위다. 대략 영어 단어의 일부나 한 글자에 해당한다. Leviathan 벤치마크에서는 tiktoken의 o200k_base로 토큰 수를 세어 에이전트 컨텍스트에 들어가는 양을 측정했다.
- 그룹
- 고객, 장비, 호스트처럼 사람들이 이름으로 묻는 대상이다. Leviathan은 -g 옵션으로 그룹을 지정해 검색 범위를 좁힌다. 그룹 이름 해석은 정확한 키부터 퍼지 일치까지 단계적으로 진행한다.
- hit@1 / hit@5
- 검색 결과의 상위 1건 또는 상위 5건 안에 관련 레코드가 포함된 질문의 비율이다. Leviathan 벤치마크에서 100만 건 기준 hit@1 98.5%, hit@5 99.0%를 기록했다.
- MCP
- Model Context Protocol의 약자로, 에이전트가 외부 도구와 통신하는 표준 인터페이스다. Leviathan은 선택적으로 읽기 전용 MCP 서버를 제공하여 search, resolve_group, get, describe 도구를 노출한다.
더 깊이 읽기 읽는 데 약 8분
배경과 문제
고객 지원 티켓이나 설비 정비 기록처럼 한 대상에 기록이 수천 건씩 쌓이는 데이터를 코딩 에이전트에 연결하면, 에이전트는 보통 grep으로 해당 고객이나 장비의 이력을 추출해 통째로 읽는다. 이력이 짧을 때는 이 방법으로 충분하지만, 데이터가 커지면 한 번의 질문에 수만에서 수십만 토큰이 컨텍스트로 들어간다. 에이전트 셸이 도구 출력을 일정 길이에서 자르면 답이 담긴 레코드가 잘린 뒤쪽에 남을 수 있다.
또한 질문에 쓰인 낱말과 기록에 적힌 낱말이 다르거나 '완료', '조치함' 같은 형식적인 기록이 대부분을 차지하면 키워드 grep만으로는 의미 있는 레코드를 골라내기 어렵다. Leviathan은 이런 레코드를 한 번 색인해 두고, 에이전트가 질문할 때마다 관련 레코드 몇 건만 짧은 카드로 돌려주는 로컬 검색 도구다. 읽어야 할 출력량을 줄이지만, 낱말이 전혀 겹치지 않는 표현까지 의미로 찾아주는 방식은 아니다.
기존 접근의 한계
이 벤치마크의 grep 방식은 원본 레코드를 검색해 일치한 줄을 그대로 반환한다. 100만 건에서 grep+질문 낱말 전략의 출력 중앙값은 107,122토큰, 대상 전체 이력은 209,412토큰이었다. Leviathan의 436토큰과 비교하면 전자의 출력량은 약 245배다. 이 실험은 모델에 실제로 모두 읽히거나 답을 생성시키지 않았으므로 모델 비용이나 응답 정확도가 같은 비율로 바뀌었다는 뜻은 아니다.
grep에는 장비의 정확한 키가 미리 주어졌다. 그래도 질문 낱말까지 이용한 전략에서 출력 앞 3만 자 안에 관련 기록이 있는 비율은 96.0%였다. 출력 제한을 없애면 두 grep 전략은 98.5~100%의 질문에서 관련 기록을 포함했다. 100만 규모의 최대 출력은 약 970만 토큰이었으며, 대상의 전체 이력을 반환하는 전략에서는 질문 절반의 출력이 200K 토큰 창에 들어갔다. 마지막 절반이라는 수치는 질문 낱말로 추가 필터링한 전략에 대한 값이 아니다.
연구방법을 단계별로
Leviathan은 원본을 매번 읽는 대신 SQLite FTS5 전문 검색 인덱스를 미리 만들어 두는 접근을 택한다. 사용자는 레코드의 ID, 제목, 본문, 그룹, 날짜, 필터 필드를 매핑해 둔다. 여기서 그룹은 고객, 장비, 호스트처럼 사람들이 이름으로 묻는 대상이다. 그러면 에이전트는 -g acme처럼 그룹을 이름이나 이름 일부로 지정하고 자연어 그대로 질문할 수 있다.
검색 시 그룹 이름 해석은 정확한 키, 대소문자를 무시한 키, 이름, 부분 이름, 퍼지 일치 순서로 진행한다. 한 단계에서 후보가 둘 이상 나오면 추측하지 않고 후보 목록을 출력한 뒤 종료 코드 3으로 끝난다. 지정한 그룹 안에서 일치하는 레코드가 없으면 다른 그룹의 결과에 OTHER CUSTOMER 같은 라벨을 붙여 보여준다.
결과는 BM25 점수 순으로 정렬되고, 각 카드에는 레코드 ID와 날짜, 설정한 표시 필드, 질문과 일치한 문장이 들어간다. 원본 전체가 필요하면 에이전트가 카드의 ID로 leviathan get을 호출한다. 모든 응답 머리말에는 shown N of M이 붙어서 에이전트가 '일치하는 기록이 없음'과 '데이터가 없음'을 구분할 수 있다.
결과와 숫자의 의미
개발자가 공개한 벤치마크는 생성기가 만든 합성 설비 정비 기록을 사용한다. 장비 1,500대에 기록이 지프 분포로 쏠려 있고, 고장 수리 기록의 조치 내용 중 27%는 'done', 'fixed' 같은 형식적인 문구, 15%는 빈 값으로 두어 검색을 일부러 어렵게 만들었다. 규모마다 질문 200개를 만들고, 같은 장비의 같은 고장 유형이면서 실제 조치 내용이 담긴 레코드를 관련 기록으로 본다. 100만 규모에서는 질문마다 해당하는 기록이 중앙값 90개로, 이 중 하나를 찾으면 성공이다.
100만 건 데이터에서 Leviathan은 질문당 중앙값 436토큰, hit@1 98.5%, hit@5 99.0%를 기록했다. grep + 질문 낱말은 중앙값 107,122토큰, 출력 앞 3만 자 내 정답 포함률 96.0%였다. 개발자의 AMD Ryzen 7 2700X·Linux 한 대에서 단일 측정한 Leviathan의 지연 중앙값은 프로세스 시작을 포함해 33.4ms로 grep history의 88.9ms보다 빠르지만, 10만 건 이하에서는 grep이 비슷하거나 더 빠르다.
토큰 수는 tiktoken의 o200k_base로 세었고, 1MB 미만 출력은 정확히 세고 더 큰 출력은 균등한 512줄 표본으로 추정했다. 100만 규모의 큰 출력 네 개에서 보고한 최대 오차는 0.28%다. 602토큰 최댓값은 여섯 규모 전체 1,200질의의 결과이며 임의 데이터 크기에서 항상 보장되는 상한이 아니다.
구체적인 예시
저장소의 예제 티켓에서는 사용자가 비밀번호를 바꾼 뒤 반복되는 SSO 로그인 문제를 묻는다. 검색은 24개 예제 티켓 중 Acme 고객의 기록을 좁혀 세 개의 카드를 보여주며, 카드에는 ID·날짜·상태와 오래된 세션 쿠키를 지워 해결했다는 기록이 포함된다. 이는 공개 예제로 사용법을 보여준 것이며 실제 고객 상담을 성공시킨 실험 결과는 아니다. 자세한 기록은 카드 ID로 다시 열 수 있다.
커뮤니티 작성자가 한국어 기록 세 개로 수행한 작은 확인에서, 기록에 '세션 쿠키를 삭제해서'라고 적혀 있고 질의가 '쿠키'이면 0건이 나온다. FTS5의 porter unicode61 토크나이저가 공백과 구두점으로 낱말을 나누므로 '쿠키를'과 '쿠키'는 서로 다른 토큰이 되기 때문이다. 형태소 단위로 띄어 쓴 보조 필드를 추가하고 --text body --text body_morph로 검색 대상에 넣으면 '쿠키' 질의가 해당 레코드를 찾는다. 다만 이 방법은 공식 안내 기능이 아니며 대규모 한국어 성능 검증은 확인되지 않았다.
한계와 오해하기 쉬운 점
이 벤치마크는 합성 데이터 한 가지 구조의 자체 비교이며 실제 운영 데이터, 전체 데이터 집계 질문, 의미 검색과의 비교 및 LLM 최종 정답 평가는 확인되지 않았다. 검색 결과만 측정하며 LLM이 출력을 읽고 최종 답을 낸 결과가 아니다. LLM을 포함한 벤치마크는 로드맵에 있다고 적혀 있다.
Leviathan은 임베딩 없는 BM25 어휘 검색이라 질문과 기록의 표현이 다르면 놓칠 수 있다. 개발자도 질문은 'weeping'이라고 쓰고 기록은 'leak'이라고 쓴 경우 질문의 다른 낱말이 일치해야 찾을 수 있다고 적어 두었다. 한국어는 조사가 붙은 낱말을 별개 토큰으로 다루므로 데이터 전처리나 질의 표현에 신경 써야 한다.
오프라인 인덱서와 네트워크·텔레메트리 없음은 연결된 LLM까지 외부 전송을 하지 않는다는 보장이 아니다. 검색 결과를 받은 에이전트의 모델·전송 설정은 별도다. 또한 그룹을 못 찾거나 이름이 모호하면 종료 코드 3으로 끝나지만, 유효한 그룹 안에서 검색 결과가 없으면 다른 그룹 결과를 OTHER CUSTOMER로 표시해 반환한다. 이 검색 범위 기능 자체가 고객별 접근 권한 통제는 아니다.
실제로 어떻게 활용할까
Leviathan은 고객, 장비, 호스트처럼 이름으로 부르는 대상이 있고 대상마다 기록이 많이 쌓인 운영 데이터를 에이전트에게 물어보는 팀에 맞다. 지원 티켓에서 '이 고객이 전에 같은 문제를 겪었나', 정비 기록에서 '이 장비는 지난번에 무엇으로 고쳤나' 같은 질문이 벤치마크가 가정한 형태다. 검색을 로컬에서 수행할 수 있다는 점은 활용 근거지만, 결과를 받는 에이전트의 데이터 전송 설정과 접근 범위는 별도로 확인해야 한다.
연결 방식은 셸에서 CLI를 호출하거나 읽기 전용 MCP 서버를 등록하는 두 가지다. MCP는 search, resolve_group, get, describe를 제공하며, 100만 레코드 인덱스에서 도구 설명과 데이터셋 요약을 담은 tools/list는 638토큰이었다. CLI 방식은 이 MCP 설명을 상시 등록할 필요가 없지만, 스킬이나 AGENTS.md에 넣은 설명을 모델이 읽는 비용까지 항상 0이라는 뜻은 아니다. 전체 CLI에는 인덱스를 만들고 갱신·삭제하는 쓰기 명령도 있다.
첫 릴리스 직후의 프로젝트이므로 운영 환경에 붙이기 전에 자체 데이터로 검색 품질을 먼저 확인하는 편이 안전하다. 데이터 전체를 가로지르는 집계 질문이나 표현이 크게 다른 질문까지 찾아야 하는 경우, 그리고 한국어 원문을 전처리 없이 그대로 색인하려는 팀에게는 Leviathan이 아직 적절한 선택지가 아니다.
원문에서 확인한 근거 4곳
- Leviathan은 합성 기록 100만 건, 질문당 상위 5개 반환 조건에서 출력 중앙값 436토큰과 관련 기록 포함률 hit@5 99.0%를 기록했다.### Tokens and answers
- 비교한 grep 전략 중 질문 낱말로 필터링한 방식의 출력 중앙값은 107,122토큰으로, Leviathan의 약 245배였다.### Tokens and answers
- Leviathan은 임베딩 없는 BM25 어휘 검색을 사용하며, 질문과 기록의 표현이 다르면 놓칠 수 있다.## Limitations
- 한국어 레코드에서 '쿠키를'과 '쿠키'는 서로 다른 토큰으로 처리되어 '쿠키' 질의가 '세션 쿠키를 삭제해서' 기록을 찾지 못한다.Leviathan으로 한국어 레코드를 검색할 때의 제약
10월 11일(일) 처음 실음 · 10월 12일(월) 고침 · AI가 쓰고 원문과 대조