참고 문헌 / 아카이브 및 연동 기능
Telegram · 전체 텍스트 검색
저장된 메시지를 단어 형태, 정확한 구문, 도메인 및 @사용자명으로 검색하며, 서명된 저널에 인덱스가 연동되어 가장 일치도가 높은 결과부터 우선적으로 표시됩니다.
아카이브 분석 · 로컬 OCR 및 텍스트 변환 · 위키
미리 보기. ‘저널’에서 검색 필드 옆에 있는 ‘최적 일치 · 단어 형태’를 선택하세요. 결과는 BM25 알고리즘으로 순위가 매겨지며, 같은 단어의 다른 형태와도 일치합니다. 예를 들어, ‘перевод’를 검색하면 ‘переводом’과 ‘переводы’가 검색되고, ‘transfer’를 검색하면 ‘transfers’가 검색되며, 중국어 구문은 공백 없이 검색됩니다. ‘최신순 · 정확한 텍스트’를 선택하면 전체 레코드에 대한 기존 부분 문자열 검색이 유지됩니다.
인덱스는 파생 데이터입니다. 이 인덱스는 서명된 저널을 기반으로 재구성되며, 그 자체로는 서명되지 않으며 내보내기 대상에도 포함되지 않습니다. 원본 기록은 변경되지 않습니다.
이 페이지에서
검색 구문#
| 작성 | 검색 결과 |
|---|---|
перевод карта |
두 단어가 모두 포함된 기록(형식 불문) |
"переводом на карту" |
정확한 문구를 이 순서대로 기재하십시오. |
бонус OR подарок |
두 단어 중 하나 |
перевод -казино |
제외된 단어가 포함되지 않은 기록 |
example.com |
도메인 및 그 하위 도메인(숨겨진 링크 및 버튼 URL 내 포함) |
@username, t.me/username |
해당 계정의 멘션 및 링크, 그리고 해당 계정이 보낸 메시지 |
#tag |
해시태그 |
+79991234567, 지갑 주소, 이메일 주소 |
텍스트 또는 링크로 동일한 값을 표시 |
from:@username, from:123456 |
해당 발신자가 보낸 메시지 |
chat:-1001234567890 |
채팅은 하나뿐이며, 자신의 접근 권한만 제한할 수 있습니다. |
id:42 |
메시지 42의 저장된 버전 |
since:2026-01-01 until:2026-01-31 |
관찰 기간: 시간이 명시되지 않은 날짜는 하루 전체를 의미합니다. |
kind:edited |
수정 사항만 (new, snapshot, edited, recovered) |
source:ocr, source:transcription, source:all |
메시지 대신, 또는 메시지와 함께 인식된 텍스트 |
다른 단어가 함께 존재할 경우 전치사 및 기타 기능어는 무시됩니다. 단어 내에 섞여 있는 유사 문자(키릴 문자 단어 내의 라틴 문자 ‘a’), 전각 및 장식용 유니코드 문자, 보이지 않는 문자는 정규화됩니다.
언어#
언어는 각 레코드의 스크립트와 문자를 기반으로 감지됩니다:
| 스크립트 | 일치 |
|---|---|
| 키릴 문자 | pymorphy3를 사용한 러시아어 및 우크라이나어 어간. 선택 사항인 우크라이나어 사전을 사용하지 않을 경우, 경량 우크라이나어 어간 추출기가 사용됩니다. |
| 라틴어 | 영어 Snowball 스템머; 분음 부호는 무시됩니다 |
| 중국어, 일본어, 한국어, 태국어, 라오스어, 크메르어, 미얀마어 | 중복되는 문자 쌍: 공백 없이 모든 구문이 검색됩니다. 중국어 쿼리는 jieba를 사용하여 단어로 분할됩니다. |
| 기타 스크립트 | 정확한 문구 |
우크라이나어 사전(pymorphy3-dicts-uk)은 GPL-3.0 라이선스로 배포되므로
기본적으로 설치되어 있지 않습니다. 다음 명령어로 설치하십시오 pip install "tgwitness[uk-dictionary]";
인덱서가 새로운 분석기를 감지하여 자동으로 재구축됩니다.
인덱스가 저장되는 위치#
| 모드 | 저장소 | 사용법 |
|---|---|---|
| 디스크에 저장 (기본값) | search/fulltext.sqlite3 작업 공간 디렉터리 내 |
대용량 아카이브; 재시작 후에도 데이터가 유지됨 |
| 메모리 내 전용 | 디스크에 아무것도 저장되지 않으며, 매 시작 시마다 재구축됩니다. | 디스크에 메시지 텍스트의 파생 사본을 저장하지 마십시오. |
| 끄기 | 색인 없음; 최신순 · 정확한 텍스트 그대로 유지 | 최소 설치 환경 |
주 관리자는 각 워크스페이스에 대해 ‘저널(Journal) → 필터(Filters) → 검색 인덱스(Search index)’에서
모드를 선택합니다. TGWITNESS_FULLTEXT=disk|memory|off 별도의 설정이 없는
워크스페이스의 경우 기본값이 적용됩니다. 메모리 모드로 전환하거나 비활성화하면 파일이 삭제됩니다.
인덱스 파일은 저널과 동일한 보호 기능을 갖습니다. 즉, 개인 데이터
디렉터리에 저장됩니다. 이 파일은 암호화되지 않으며, 백업이나 외부 복사본의 대상이 아닙니다.
새 기록은 백그라운드에서 몇 초 내에 색인화되며, 검색 시에도 짧은 백로그가 먼저 색인화되므로 방금 저장된 기록도 찾을 수 있습니다. 기존 저널은 업데이트 후 패널을 차단하지 않고 색인화되며, 그 전까지는 검색 결과가 색인화된 기록만 포함하고 저널에는 진행 상황이 표시됩니다. 색인 재구축은 첫 번째 기록부터 다시 시작됩니다.
python -m tgwitness index status --data-dir data/live
python -m tgwitness index rebuild --data-dir data/live --json
rebuild 패널을 중지해야 합니다(그렇지 않으면 종료 코드 3). --json,
표준 출력에는 결과만 표시되며, 진행 상황은 표준 오류로 출력됩니다.
결과 및 서명된 저널#
인덱스는 해당 인덱스가 다루는 마지막 저널 레코드의 시퀀스 번호와 해시를 저장하며, 저널을 열 때 이를 저널과 대조하여 확인합니다. 저널이 교체, 복원 또는 편집되면 인덱스가 재구축됩니다. 모든 응답은 이 위치를 보고하며, 모든 조회 결과는 시퀀스 번호를 통해 서명된 저널에서 다시 읽어옵니다. 인덱스는 어떤 레코드를 어떤 순서로 표시할지 결정할 뿐, 레코드의 내용은 절대 결정하지 않습니다. 채팅 액세스는 인덱스 콘텐츠가 아닌 저널 자체의 채팅 필드에 적용됩니다.
인식된 텍스트#
OCR 및 전사본은 암호화된 아티팩트 내에 그대로 유지됩니다. 해당 인덱스는
메모리에만 존재하며, 인식 작업이 완료되면 재구축됩니다. 일치 항목은
media.saved 기록에 ‘기계 인식’으로 표시되며, 엔진, 모델 및
발췌문이 함께 제공됩니다. 이는 텔레그램에서 전송된 텍스트로 표시되지 않습니다. 동일한 인덱스는
인식된 텍스트 검색 기능에도 사용되며, 이 기능은 여전히 일반 부분 문자열과도 일치합니다.
접근#
채팅 범위 내 액세스는 해당 채팅의 기록만 검색하며, 여기에는 첨부 파일의
인식된 텍스트도 포함됩니다. chat: 기타 필터는 해당 기록 집합을 좁히는 용도로만 사용할 수 있습니다. 범위 지정된 액세스에 표시되는 인덱스 상태에는
저널의 총 기록 수가 포함되지 않습니다. 모드 변경이나 인덱스 재구성은
주 관리자만 수행할 수 있습니다.
아카이브 및 MCP에 문의하기#
아카이브는 인덱스 생성이 완료되면 이 인덱스에서 소스 데이터를 가져옵니다: 선택된 채팅 전체에서 가장 잘 일치하는 항목들을, 저장된 텍스트는 한 번만 계산하여 제공합니다. 최대 24개의 소스 데이터가 전송되며, 긴 텍스트는 일치하는 부분 주변에서 잘리고 잘린 것으로 표시됩니다. 최근 변경 사항, 특정 메시지의 저장된 버전, 그리고 인덱스가 아직 생성 중인 상태에서의 검색에 대한 질의는 이전의 시간순 검색 방식을 사용합니다. 미리보기 창에는 어떤 방식이 사용되었는지 표시됩니다.
MCP 클라이언트는 다음을 호출할 수 있습니다 search_messages 다음과 같이 호출할 수 있습니다 ranked=true 를 사용하여 호출하고
next_offset를 사용하여 페이지를 호출할 수 있습니다. 범위 지정된 연결은 해당 채팅 내용만 수신합니다.
순위 기반 페이지 나누기는 페이지 크기와 관계없이 최대 첫 1,000개의 결과만 표시합니다. 더 많은 일치 항목을 확인하려면 검색어, 채팅 또는 기간을 좁혀 주세요. 최신순 검색은 각 페이지를 선택하기 전에 메시지, OCR 및 전사 결과를 최신 순으로 정렬합니다.
의존성#
| 패키지 | 라이선스 | 이유 |
|---|---|---|
| pymorphy3, pymorphy3-dicts-ru, DAWG2-Python | MIT | 러시아어 및 우크라이나어 어근; 사전은 로컬에서 불러옵니다. |
| snowballstemmer | BSD-3-Clause | 영어 어간, 순수 파이썬 |
| jieba | MIT | 중국어 쿼리 분할, 순수 파이썬 (소스 배포만 제공) |
| pymorphy3-dicts-uk (선택 사항) | GPL-3.0 | 전체 우크라이나어 사전 |
SQLite FTS5의 경우 unicode61 토큰화기가 필수이며, 이는
현재 Python 빌드에 포함된 SQLite의 일부입니다. 이 기능이 없으면 최상위 일치 검색 시 사용할 수 없다는 오류가 발생합니다.
벤치마크#
python tools/bench_fulltext.py --messages 1000000 --work <empty directory>200개의 채팅에서 링크와 핸들이 포함된 러시아어, 우크라이나어, 영어,
중국어 및 일본어 메시지가 혼합된 결정론적 서명된 저널을 생성하고, 색인을 구축하며
일반적인 검색 시간(50개 결과, 7회 실행의 중앙값)을 측정합니다.
Windows 11, Intel Core i9-13900K, 128 GB RAM, Python 3.12.10, SQLite
3.49.1 환경에서 측정되었으며, 데이터는 exFAT 드라이브에 저장되어 있고, 분석기를 사용했습니다. fulltext-v1+pymorphy3-ru+light-uk+snowball-en:
| 측정 | 결과 |
|---|---|
| 서명된 저널 | 메시지 1,000,000개, 1.50 GiB, 19분 만에 기록됨 |
| 저널을 기반으로 한 색인 생성 | 71초, 초당 약 14,141개의 메시지 |
| 인덱스 파일 | 58 MiB, 저널의 3.8% |
| 새 기록이 생성된 직후 검색 | 중앙값 8 ms, 95% 신뢰구간 9 ms |
| 이전 부분 문자열 검색, 동일한 저널 | перевод 3.2초, 银行转账 2.6초, verify-account.example 2.6초 |
| 검색 | 일치하는 기록 | 최적 일치, 중앙값 | p95 | 최신순, 중간값 |
|---|---|---|---|---|
일반적인 단어 및 어형: перевод |
134,403 | 82 ms | 85 ms | 7 ms |
두 단어: оплата карта |
28,996 | 43 ms | 43 ms | 14 ms |
생소한 단어: розыгрыш подарок |
28,881 | 42 ms | 47 ms | 13 ms |
정확한 문구: "переказ коштів на картку" |
계산되지 않음 | 35 ms | 36 ms | 6 ms |
도메인 및 하위 도메인: verify-account.example |
12,435 | 17 ms | 17 ms | 3 ms |
@사용자명: @support_desk_bot |
10,331 | 15 ms | 16 ms | 3 ms |
공백 없이 중국어로: 银行转账 |
17,691 | 23 ms | 24 ms | 3 ms |
일본어: リンク |
16,603 | 23 ms | 25 ms | 3 ms |
영어 어간: withdrawal |
27,775 | 26 ms | 26 ms | 2 ms |
또는 및 제외: бонус OR подарок -казино |
268,034 | 190 ms | 193 ms | 19 ms |
채팅 필터: chat:-1000000000007 перевод |
652 | 9 ms | 9 ms | 6 ms |
기간 필터: since:2026-01-01 until:2026-01-31 выплата |
115,732 | 155 ms | 156 ms | 81 ms |
정확한 문구는 페이지가 가득 찰 때까지 순위 순으로 후보 항목에 대해 문자 그대로 검사되므로, 해당 총계는 집계되지 않습니다. 소요 시간은 일치하는 레코드 수에 따라 증가하며, 채팅 대상이나 기간을 좁히면 광범위한 검색 속도가 빨라집니다. 합성 코퍼스는 제한된 어휘를 반복적으로 사용하므로, 일반적인 단어는 실제 채팅보다 훨씬 더 많은 레코드와 일치합니다.