Skip to content
semantic-reasoningPublic

About

Honest knowledge base: an LLM extracts source-backed facts, the wirelog logic engine verifies them. Local web app.

Resources

Stars

10 stars

Watchers

0 watching

Forks

Repository files navigation

verinote

원문을 등록하고, 개체·별칭·관계 사전을 먼저 승인하고, 그 사전으로 추출한 위키와 관계를 사람이 검토한 뒤, 실제 Wirelog로 승인된 지식만 조회하는 로컬 웹 애플리케이션입니다. 문서 버전·정확한 인용·승인 이력·질의 스냅샷을 보존합니다. 여기서 xAI는 설명 가능한 AI(eXplainable AI)를 의미합니다.

라이선스

이 프로젝트의 소스 코드는 Mozilla Public License 2.0 (SPDX: MPL-2.0)에 따라 배포됩니다. 전문은 LICENSE를 참고하세요.

실행

Python 3.11 이상이 필요합니다. 로컬 CLI를 쓰려면 해당 CLI의 설치·로그인이, OpenRouter API를 쓰려면 서버 키 파일과 모델 ID가 필요합니다.

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
python -m verinote

브라우저에서 http://localhost:8765를 엽니다. 데이터 위치와 포트를 바꾸려면 python -m verinote --data-dir /path/to/storage --port 8766을 사용합니다. verinote 명령도 동일합니다. 프로그램은 127.0.0.1에만 바인딩됩니다.

서버 전용 비밀 설정 파일

서버 자격 증명은 SQLite의 에이전트·모델·단가 설정과 별도로 TOML 파일에 보관합니다. 설정 화면에서 로컬 CLI 5종 또는 **OpenRouter (API)**를 선택해 사전·추출·인용 보정·질문을 실행합니다. API에는 실행 파일 설치가 필요하지 않습니다. 기본 위치는 다음과 같습니다.

환경 기본 경로
macOS ~/Library/Application Support/verinote/config.toml
Linux/기타 POSIX 절대 경로인 XDG_CONFIG_HOME 아래 verinote/config.toml, 없거나 상대 경로이면 ~/.config/verinote/config.toml
Windows %APPDATA%/verinote/config.toml (APPDATA가 없으면 ~/AppData/Roaming/verinote/config.toml)

POSIX에서 빈 파일을 안전하게 생성한 뒤 로컬 편집기로 [openrouter]의 api_key를 입력하세요. 실제 키를 명령 인자에 넣지 마세요.

python -m verinote --init-config
# 생성된 파일을 로컬 편집기로 편집한 뒤 서버 시작
python -m verinote

--init-config는 빈 api_key = ""를 쓰고 종료하며 서버·DB를 시작하지 않습니다. config.example.toml은 비밀 없는 형식 예제입니다. 다른 위치를 사용하려면 생성과 실행 모두 --config /absolute/path/config.toml을 지정하세요. 명시적인 상대 경로는 실행 시 작업 디렉터리를 기준으로 해석합니다. 지정한 파일 하나만 읽으며 다른 파일이나 OPENROUTER_API_KEY 환경변수로 대체하지 않습니다.

파일은 최초 생성부터 0600, 앱이 새로 만드는 디렉터리는 0700으로 제한합니다. 생성 대상의 직접 부모는 현재 사용자 소유이며 그룹/다른 사용자 쓰기가 금지되어야 합니다. 기존 파일을 덮어쓰거나 기존 파일·디렉터리의 권한을 자동 수정하지 않습니다. 읽을 때도 현재 사용자 소유의 일반 파일과 정확한 0600을 요구하며 파일 자체의 심볼릭 링크·특수 파일은 거부합니다. 권한 오류가 있으면 소유자와 경로를 먼저 확인하고 chmod 600 /absolute/path/config.toml로 직접 복구하세요. 파일 크기는 64 KiB 이하이며 허용 항목은 [openrouter].api_key 문자열뿐입니다.

기본 파일이 없거나 키 항목이 없거나 비어 있으면 미설정 상태로 기존 CLI를 사용할 수 있습니다. 명시한 파일 미존재·파싱/타입·읽기·권한 오류는 DB 복구 전에 서버 시작을 중단합니다. 파일은 서버 시작 시 한 번 읽으므로 편집 후 서버를 재시작하세요. 로더는 키를 환경변수나 DB에 쓰지 않으며 설정 여부만 공개할 수 있습니다.

Windows의 파일 기반 비밀 설정은 이번 버전에서 지원하지 않습니다. ACL을 검증하지 못하므로 chmod 결과를 보호의 증거로 사용하지 않습니다. 기본 파일이 없으면 CLI를 사용할 수 있지만, 기존 기본 파일·명시적 --config·--init-config는 안전한 오류로 거부합니다. 파일 기능이 필요하면 POSIX/WSL 환경을 사용하세요. Windows ACL 실제 검증은 수행하지 않았으며 지원을 주장하지 않습니다.

기본 위치는 저장소 밖이며 저장소 루트의 config.toml도 Git에서 제외합니다. 다른 이름으로 지정한 파일은 자동 제외되지 않으므로 실제 키 파일은 저장소 밖에 두세요. 파일은 평문이고 백업·같은 사용자·관리자 접근 및 추가 ACL에 대한 완전한 비밀 보호를 제공하지 않습니다. 파일 생성/읽기는 열린 디스크립터를 기준으로 검사하지만 악의적인 같은 사용자의 동시 내용 변경까지 막지는 않습니다.

사용 흐름

  1. 문서 등록: 파일을 선택하거나 텍스트를 붙여 넣습니다. TXT/MD/CSV/JSON/RST/LOG(UTF-8), 텍스트 PDF, DOCX를 지원합니다. 최대 원본 32 MiB, 추출 텍스트 128,000자, PDF 200쪽입니다. DOCX는 실제로 읽는 본문 XML(word/document.xml)의 압축 해제 크기가 16 MiB 이하여야 합니다. 이미지·첨부 파일은 압축을 풀지 않으며 이 본문 한도에 포함하지 않습니다. 다만 원본 32 MiB 제한에는 파일 전체가 포함됩니다. 원본 파일 크기와 본문 분석 한도는 별개이며 본문이 길면 문서를 나누어 등록하세요. OCR·암호화 PDF·이미지는 지원하지 않습니다. DOCX 본문 텍스트를 읽으며 페이지 배치·이미지·주석을 복원하지 않습니다.
  2. 사전 생성 → 승인 → 추출: 에이전트와 모델을 선택해 개체·별칭·관계 사전 초안을 생성합니다. 사전의 개체 ID·타입, 별칭의 동일성, 관계의 의미·방향·타입을 원문과 대조하고 필요하면 내용 수정의 JSON 편집기로 고친 뒤 승인합니다. 이어 승인 사전으로 추출을 누릅니다. 사전은 최대 4,000자 구간 64개, 관계 추출은 최대 8,000자 청크 16개를 처리하며 미완료 구간마다 선택한 CLI 또는 API를 호출합니다. 원문과 사전은 해당 모델 제공자에게 전달됩니다. 사전 승인 전에는 관계 추출을 시작할 수 없습니다. 위키와 관계는 다시 검토 대기로 저장됩니다.
  3. 검토: 각 위키 초안과 관계 사실을 원문과 대조하여 승인·보류·반려합니다. 여러 항목은 체크박스 또는 검토 대기 전체 선택으로 고른 뒤 선택 N개 승인을 누릅니다. 확인창에서 문서 버전·위키/관계 개수와 원문 근거를 확인하고 검토자·공통 승인 이유를 한 번 입력합니다. 위키 승인과 관계 승인은 별개이며 각 항목에 승인 이력이 남습니다. 관계를 수정하면 새 후보 revision이 생기고 다시 검토해야 합니다. 기존 승인 철회도 가능합니다.
  4. 자연어 질문: 관계 탐색 화면에서 질문과 에이전트·모델을 선택합니다. LLM이 고정 도구를 선택하고 실제 Wirelog 결과를 받은 뒤 인용이 연결된 답변을 생성합니다. 질문 이력·실행 추적·원문 버전·JSON 다운로드를 제공합니다. 고급 관계 탐색: 직접 관계 또는 특정 관계의 도달 대상·역방향 출발점·경로를 조회합니다. 예를 들어 주문 / depends_on / 원장을 경로 조회하면 실제 PyreWire 결과와 사실 ID 경로, 원문 인용을 표시합니다. 문장 생성과 관계 조회는 구분됩니다.
  5. 새 문서 버전: 문서 상세의 새 버전 등록으로 같은 문서의 다음 버전을 추가합니다. 버전 선택·원본 다운로드·이전 버전 텍스트 diff를 제공합니다. 새 버전 등록 즉시 최신 버전이 현재 기준이 되며, 이전 버전의 승인 사실은 현재 그래프에서 제외됩니다. 새 버전은 다시 추출·검토합니다. 새 버전 등록만으로 과거 원문과 판정이 삭제되지는 않습니다.
  6. 재현: 질의 결과 JSON을 다운로드하거나 최근 질의에서 과거 스냅샷을 재조회합니다. 당시 승인 사실의 내용과 문서 버전을 보존하므로 이후 수정·철회와 분리하여 탐색할 수 있습니다.

승인 사전으로 추출할 때 모든 관계 종류를 하나씩 점검하고 기술 구성·운영 관계와 나열된 항목을 검토합니다. 특허·설계의 직접 서술은 승인 관계 정의가 그 설계 의미를 보존할 때만 관계 후보로 추출합니다. 조건·부정·선택적 동작을 무조건적 사실로 바꾸지 않습니다. 실행 기록의 관계별 판단·사전 제약 보기에서 관계별 추출 개수, 직접 근거 없음, 표현 제약, 사전의 개체·관계·타입 부족과 해당 위키 주장 번호를 확인하세요. 주장 번호는 그 실행의 위키에 대응하며 기존 결과와 실행 ID로 구분합니다.

이 점검은 모델 자체 판단입니다. 보고서가 일관되어도 누락이 없거나 의미가 정확하다는 보장은 없으며, 최소 사실 수를 강제하지 않습니다. 필수 점검 항목이 잘못되면 인용이 정확한 응답도 저장 전에 실패할 수 있습니다. 별도 누락 보충 호출은 추가하지 않지만 보고서 출력 토큰은 사용량에 포함됩니다. 사전의 반복 인용을 프롬프트에서 제외해 중복 입력을 줄이며 저장된 승인 사전과 검증 기준은 유지합니다.

이전 방식으로 추출한 문서는 같은 승인 사전에서 개선된 방식으로 다시 추출을 한 번 사용할 수 있습니다. 같은 사전 revision·현재 방식의 성공 실행은 반복하지 못하며 실패는 재시도할 수 있습니다. 이전 승인·보류·거절 이력은 보존되고 새 결과는 검토 대기로 추가되므로 중복 관계가 생길 수 있습니다. 사전 자체에 필요한 관계 정의가 없으면 사전을 수정·재승인해야 합니다. 보고서 파일 저장 실패는 검증된 결과의 저장을 취소하지 않으며, 보고서 미확인을 누락 0개로 표시하지 않습니다.

업로드 창의 진행 막대는 파일 준비 → 서버 전송 → 서버 문서 처리 → 원문 등록 완료를 구분합니다. 전송률은 원본 파일 크기가 아니라 base64를 포함한 실제 HTTP 요청 바이트 기준입니다. 전송 100% 뒤에도 본문 추출·저장이 남아 있으므로 서버의 등록 완료 응답 전에는 처리 중으로 표시합니다. 전송 중에는 입력·중복 등록·창 닫기를 잠그고, 실패하면 입력을 다시 사용할 수 있습니다. 연결 중단이나 응답 시간 초과 시에는 서버가 이미 저장했을 수 있으므로 문서 목록을 확인한 뒤 재시도하세요.

문서 상세와 실행 기록에서 사전 생성 및 위키·관계 추출 진행 막대를 볼 수 있습니다. 검증을 마친 글자 수와 구간 수를 표시하며, 사전 재시도에서는 재사용한 검증 구간도 포함합니다. 모델이 응답하는 동안에는 다음 구간이 검증될 때까지 수치가 그대로입니다. 모든 구간 검증 후에도 저장 중에는 최대 99%이며 DB 저장 성공 후 100%가 됩니다. 실패·중단은 해당 상태로 표시하고 진행 기록이 없거나 손상됐으면 비율을 추측하지 않습니다. 페이지를 새로고침한 뒤 문서나 실행 기록을 열면 진행 중인 작업 조회가 이어집니다. 진행률은 예상 남은 시간이나 크레딧을 뜻하지 않습니다.

에이전트와 모델

UI 이름 실행 방식 모델 선택
Claude claude --output-format json --tools '' --strict-mcp-config -p PROMPT --model ID
Antigravity agy --output-format json --mode plan --sandbox --disable-slash-commands -p PROMPT --model ID
GitHub Copilot copilot --silent --usage-output-file PATH --available-tools '' --disable-builtin-mcps -p PROMPT (Windows에서는 prompt를 stdin으로 전달) --model ID
Cursor cursor-agent --output-format stream-json --mode ask --sandbox enabled --trust -p PROMPT --model ID
Codex codex exec --json --skip-git-repo-check --ephemeral --sandbox read-only --color never - --model ID, prompt는 stdin

Cursor는 cursor-agent가 없으면 agent 실행 파일을 탐색합니다. 설정 화면에서 기본 에이전트와 각 에이전트별 모델 ID를 저장하고, 추출 직전에 해당 작업의 모델을 바꿀 수도 있습니다. 모델 목록을 하드코딩하지 않으며 빈 값은 CLI 기본 모델을 뜻합니다. 모델 가용성·로그인은 CLI 계정에 따릅니다. 설치 여부만으로 모델 접근 가능성을 보장하지 않습니다.

Windows의 Copilot은 서버 프로세스의 PATH를 먼저 탐색하고, 찾지 못하면 WinGet의 %LOCALAPPDATA%\Microsoft\WinGet\Links와 npm의 %APPDATA%\npm도 확인합니다. 터미널에서 실행되더라도 서버가 설치 전의 PATH를 상속했다면 기존 PATH 탐색만으로는 미설치로 표시될 수 있습니다. 다른 경로에 설치했다면 해당 경로를 PATH에 추가한 터미널에서 서버를 다시 시작하세요.

CLI는 별도 작업 폴더에서 실행하며 shell 문자열을 사용하지 않습니다. 권한 우회 옵션은 사용하지 않습니다. 기본 실행 제한은 사전 생성은 모든 에이전트에서 호출당 600초(10분), **승인 사전 기반 위키·관계 추출은 모든 CLI/API에서 청크당 최대 360초(6분)**입니다. 인용 보정 호출도 해당 청크의 남은 360초 예산을 공유합니다. 자연어 질문은 Antigravity(agy)와 GitHub Copilot 600초, 나머지 180초입니다. 코드에서 지정한 CLI(timeout=...)는 사전 생성·질문에 우선 적용하며, 추출에서는 더 짧은 제한만 적용합니다. 전체 작업은 여러 청크로 더 오래 걸릴 수 있습니다. 시간 초과나 검증 실패에 대한 자동 유료 재호출은 없습니다. 적용된 제한은 실행 로그의 timeout_seconds와 시간 초과 메시지에서 확인할 수 있습니다. stdout+stderr 제한은 1 MiB이며 오류·시간 초과는 실패로 기록합니다. 작업 큐는 최대 8개, 실행은 한 번에 1개입니다. 서버 재시작 시 미완료 작업은 중단 상태로 바뀝니다. 실행 폴더 격리가 OS 수준의 완전한 격리를 뜻하지 않으며 각 CLI 자체 권한 정책도 적용됩니다.

추출은 검증 완료된 청크 결과를 data/runs/<run-id>/extraction-checkpoint.json에 저장합니다. 실패·서버 중단 후 같은 문서 버전·승인 사전 revision·에이전트·모델로 승인 사전 추출을 다시 실행하면 완료 청크를 재검증해 재사용하고 실패한 청크부터 이어갑니다. OpenRouter의 토큰 상한·어댑터 계약과 소스·프롬프트·추출 방식도 일치해야 합니다. 시간 제한만 바뀐 경우에는 완료 청크를 재사용합니다. 복구 기록이 없거나 손상·비호환이면 다시 처리하며 실행 상세에 이유를 표시합니다. 저장 실패도 상세에 표시하므로 이전 청크를 반드시 재사용한다고 보장하지는 않습니다. 재사용 청크에는 모델을 다시 호출하지 않으며, 전체 추출이 성공해야만 위키·관계 후보를 한 번에 저장합니다. 후보의 별도 검토·승인 절차는 유지합니다.

관계 추출 결과의 인용이 원문에 없으면, 먼저 전체 응답의 형식과 승인 사전의 개체·관계·타입을 검사합니다. 다른 문제가 없을 때만 같은 에이전트·모델에 문제가 있는 인용문만 다시 선택하도록 요청합니다. 원문에 없는 단어를 임의로 지우거나 유사한 문장을 자동 인정하지 않습니다. 보정은 청크당 한 번, 문서 실행당 추가 CLI 호출 최대 2회이며 그만큼 시간과 크레딧이 더 들 수 있습니다. 사전 생성과 자연어 질문에는 이 보정을 적용하지 않습니다.

보정은 주장 내용·관계 triple·항목 수·정상 인용을 유지하고, 해당 청크의 정확한 연속 원문 인용만 허용합니다. 한 항목이라도 보정에 실패하면 부분 결과 없이 실행을 실패 처리하며 청크와 주장/관계 번호를 표시합니다. 성공하면 보정 건수와 위치를 실행 기록 및 완료 알림에 표시하고 결과는 검토 대기로 저장합니다. 정확한 문구 일치는 의미가 맞다는 보증이 아니므로 보정된 인용도 사람이 대조해야 합니다. 최초 응답 로그는 유지하며 data/runs/<run-id>/<chunk>/quote-repair/에 보정 호출 로그와 변경 전후 changes.json을 남깁니다.

CLI 옵션은 설치된 도움말과 Claude 공식 CLI 문서, Cursor CLI 문서, Copilot 도구 제한 문서를 기준으로 확인했습니다. CLI 버전이 달라 옵션 오류가 발생하면 실행 로그를 확인하세요.

사용량과 크레딧

로컬 CLI 5종과 OpenRouter API가 보고한 토큰을 자동 저장합니다. 실행 기록에서 에이전트·모델·사전 생성/관계 추출/인용 보정/질문별 합계와 JSON 다운로드를, 개별 실행·질문에서 호출별 사용량과 계산 근거를 확인합니다. 실패한 작업의 호출, 재시도, 질문의 여러 LLM 호출도 포함합니다. 승인과 고급 관계 탐색 자체는 LLM을 호출하지 않습니다.

값 계산 근거
입력·출력 토큰 CLI 또는 API envelope가 보고한 카운터. 입력에는 캐시, 출력에는 추론이 포함되어 세부 값을 다시 더하지 않습니다.
제공자 보고 크레딧 Copilot의 GitHub AI credits 또는 OpenRouter envelope usage.cost의 OpenRouter credits. 단위별로 구분합니다.
CLI 보고 비용 Claude의 total_cost_usd. CLI가 계산한 비용이며 계정의 실제 청구액을 뜻하지 않습니다.
설정 단가 추정 비용·크레딧 사용자가 지정한 USD/100만 토큰 단가와 선택적 크레딧당 USD 환산값

설정 → 사용량 계산 단가에서 에이전트별 추정을 켜고 일반 입력·출력·캐시 읽기·캐시 쓰기 단가를 모두 입력합니다. 크레딧으로도 보려면 계약상의 단위 이름과 크레딧 1개당 USD를 지정합니다. 단가는 자동으로 추측하지 않습니다. 모델 ID를 지정하면 제공자가 보고한 실제 모델과 우선 대조하고, 보고가 없을 때만 요청 모델을 가정으로 사용합니다. 단가 모델을 비우면 모델을 지정하지 않은 호출에만 ‘CLI 기본 모델 가정’으로 적용합니다. 여러 모델을 합산한 호출이나 모델 불일치는 추정하지 않습니다.

단가와 환산 기준은 각 호출 시작 시 고정됩니다. 설정을 바꿔도 과거 비용은 재계산하지 않습니다. 보고 비용과 추정 비용을 서로 더하지 않으며 크레딧은 단위별로 구분합니다. 구독 한도, 할인, 실제 청구액·잔액은 별도입니다.

집계는 보존된 최근 1,000개 실행·질문 작업의 읽을 수 있는 호출 로그를 대상으로 하며 전체 작업 수와 누락 범위를 표시합니다. 오래된 기록, 손상·누락된 로그, 제공자가 보내지 않은 값은 미확인이지 0이나 무료가 아닙니다. 이미 끝난 과거 호출은 원문 글자 수로 토큰을 추측하거나 로그를 재작성하지 않습니다. 일부 카운터만 있으면 확인된 값의 소계와 기록 수를 표시합니다. 문서 삭제로 연결된 실행·질문이 제거되면 해당 사용량도 집계에서 빠지므로 평생 누적 지출이 아닙니다.

사용량은 data/runs/{id}/{구간}/usage.json(사전 164, 관계 추출 116), 인용 보정은 그 아래 quote-repair/usage.json, 질문은 data/questions/{id}/llm-{회차}/usage.json에 저장합니다. 원본 CLI 출력과 별도로 저장하며 Copilot 전용 파일과 정규화된 사용량 파일의 읽기 한도는 각각 256 KiB입니다. CLI 응답 형식이 달라지면 사용량이 미확인이 되거나 명시적인 실행 오류가 발생할 수 있습니다.

결정성과 설명 가능성의 경계

  • LLM 추출 자체는 비결정적입니다. 같은 승인 사실 스냅샷 + 같은 규칙 + 같은 PyreWire 버전 + 같은 질의에서 정렬된 관계 결과와 선택된 증명 경로가 같습니다.
  • 모든 관계는 일반 triple입니다. 전이는 사용자가 지정한 동일 predicate 내에서만 계산합니다. 관계 이름이 같다는 이유로 인과관계·장애 발생·시간적 유효성을 보장하지 않습니다. 필요하면 의미가 다른 관계는 후보 검토 시 이름을 분리하세요.
  • 증명 경로는 정렬된 승인 사실에서 결정적으로 고른 최단 경로 하나입니다. 엔진 내부 provenance 전체를 출력하는 기능은 아닙니다. 직접 관계에는 이를 지지하는 모든 승인 사실 ID가 표시됩니다.
  • 정확한 인용의 존재는 의미의 정확성을 증명하지 않습니다. 조건·부정·시점이 손실된 관계는 승인하지 않아야 합니다. 시스템은 사람의 판정을 대신하지 않습니다.
  • 자연어 질의 해석과 답변 문장은 비결정적입니다. 실제 도구 호출·결과·인용을 기록합니다. 인용 ID와 근거 유형 검증은 의미적 정답 보증이 아닙니다. 승인 그래프·승인 위키·미검토 원문·추론을 구분합니다. 빈 결과는 현실의 부재를 뜻하지 않습니다. 임베딩 검색과 사용자 정의 Datalog 실행은 제공하지 않습니다.

질문의 지식 조회 순서

질문은 승인된 위키와 관계 그래프를 우선 사용합니다. 승인 사전의 개체·별칭·관계 정의는 어휘 안내로 검색되며, 그 자체를 관계 사실의 근거로 인용하지 않습니다. 그래프만으로 답할 수 있으면 위키·원문 읽기를 추가하지 않습니다. 문서 설명은 승인 위키를 찾아 읽고 승인 위키 근거로 답합니다.

원문 본문 검색·읽기는 해당 문서의 승인 지식 검색과 그래프 조회 결과를 받은 뒤에만 가능합니다. 관련 위키가 검색되면 먼저 읽고, 다음 모델 회차에서 부족한 내용을 구체적으로 설명해야 합니다. 실행 기록과 원문 근거에 검색 ID·이유·읽은 위키 근거 ID가 남습니다. 승인 위키 없음, 관련 위키 검색 결과 없음, 읽은 위키의 설명 부족, 과거 스냅샷에 위키 정보 없음을 구분합니다. 이 검사는 조회 순서·문서 범위를 확인하며 모델의 검색어 선택이나 의미적 부족 판단의 정확성을 보장하지 않습니다. 원문 내용은 계속 미검토 원문으로 표시합니다.

위키 읽기는 원문 인용을 포함한 페이지 내용을 2,000자씩 제공하며 부분 구간·주장 번호·다음 위치를 표시합니다. 승인 지식 검색은 20개씩 제공하며 잘린 검색 결과로 원문 접근을 허용하지 않습니다. 검색어·문서 범위를 좁혀야 합니다. 제목·파일명 검색은 원문을 읽지 않습니다. 모델은 최대 6회, 도구는 최대 10회이며 예산이 부족하면 실패하거나 확인 범위를 한정해 답합니다. 자연어 질문은 문서 100개·사실 500개·위키 500개·사전 100개, 승인 위키·사전 합계 8 MiB까지입니다. 도구 결과는 UTF-8 30,000바이트, 누적 프롬프트는 60,000바이트까지입니다.

6회 중 탐색은 최대 5회이며 마지막 1회는 답변 전용입니다. 도구 10회를 먼저 사용하면 바로 다음 모델 호출을 답변 전용으로 전환합니다. 마지막 탐색 결과를 전달하고 이미 읽은 근거로 답하며, 부족하거나 읽지 못한 부분은 확인 불가로 한정하도록 요청합니다. 답변 전용 회차의 추가 도구 요청은 실행하지 않습니다. 모델이 형식을 어기거나 인용이 잘못된 경우에는 여전히 실패하며, 자동으로 7번째 호출을 추가하지 않습니다.

긴 검색어로 승인 지식을 찾지 못하면 그 문장에 포함된 문서명·파일명(확장자 제외)·승인 사전 개체·별칭으로 후보를 찾습니다. 문서명은 한국어 띄어쓰기 차이도 허용하며, 별칭은 해당 문서 사전의 정규 명칭으로만 확장합니다. 한 글자나 일반적인 이름은 이 보조 검색에서 제외합니다. 위키 후보를 사전 안내보다 먼저 표시하고, 검색 결과에 match_mode와 matched_terms를 남깁니다. 보조 검색의 후보 이름이 12개를 넘으면 불완전한 검색으로 표시하므로 문서 범위·검색어를 좁혀야 합니다. 후보 검색은 원문이나 인용문을 검색하지 않으며 그 자체를 답변 근거로 인용할 수 없습니다.

같은 질문에서 성공한 그래프 조회를 반복하면 기존 결과와 근거 ID를 재사용합니다. 실행 추적의 reused_from은 처음 성공한 도구 요청 번호(1부터 시작)를 가리키며, 반복 요청도 10회 한도에 포함됩니다. Copilot의 빈 <final_answer> 접두 태그와 Cursor의 정확히 동일한 JSON 객체 2회 반복은 추가 모델 호출 없이 정리합니다. 처리 내역은 호출 로그 run.json의 response_normalizations에 남으며 원본 출력과 사용량은 보존합니다. 서로 다른 응답이 섞이거나 알려지지 않은 형식이면 계속 실패합니다.

새 스냅샷은 승인 위키·사전·관계와 문서 메타데이터를 함께 고정합니다. 이후 승인 철회·새 버전 등록은 과거 질문의 근거를 바꾸지 않습니다. 기존 스냅샷은 재작성하지 않으며, 위키 정보가 없으면 현재 위키를 가져오지 않고 명시적인 원문 fallback을 사용합니다. 위키와 관계의 승인은 여전히 별개이며, 검토 대기·보류·반려 위키는 질문 근거에 포함하지 않습니다.

저장과 운영 범위

기본 data/verinote.sqlite3에 원본 바이트·추출 텍스트·SHA-256·문서 버전·초안·사실·검토 이벤트·설정·스냅샷·질의 기록이 저장됩니다. data/runs/<run-id>/<chunk>/에는 CLI의 실제 prompt, stdout, stderr, 실행 메타데이터가 저장됩니다. API 호출은 stdout을 만들지 않고 안전 검사한 response.json, run.json, usage.json을 별도 보관합니다. 일반 API·다운로드에는 원시 HTTP 응답이나 Authorization 헤더를 포함하지 않습니다. SQLite 실행 기록에는 단계와 추출에 사용한 승인 사전의 ID·revision·내용·SHA-256도 고정하여 보존합니다. 이 폴더는 Git에서 제외합니다. 백업할 때 서버를 종료한 뒤 데이터 폴더 전체를 복사하세요.

단일 사용자 로컬 애플리케이션입니다. 검토자 이름은 사용자가 입력하는 감사 기록이며 인증된 신원이 아닙니다. 인터넷 공개·다중 사용자 권한 관리·데이터 암호화를 제공하지 않습니다. 같은 데이터 디렉터리에 서버를 여러 개 실행하지 마세요. HTTP 서버는 로컬 Origin/Host 검사와 JSON 요청 제한을 사용합니다. UI는 원문·모델 출력을 HTML로 실행하지 않습니다.

일괄 승인은 현재 보고 있는 한 문서 버전의 검토 대기 위키·관계 중 선택한 항목에만 적용합니다. 사전은 별도로 승인하며 보류·반려·이미 승인된 항목은 개별 검토합니다. 한 번에 최대 2,000개를 처리하고, 전체 선택이 한도를 넘으면 일부를 해제해야 합니다. 확인창을 연 뒤 새로 생성된 항목은 자동으로 포함되지 않습니다. 선택한 항목이나 문서가 변경되면 전체 요청을 취소하고 새로 선택하도록 안내합니다. 부분 승인과 자동 재시도는 하지 않습니다. 과거 버전도 명시적으로 검토할 수 있지만 현재 그래프에는 현재 버전의 승인 사실만 들어갑니다. 승인은 모델을 호출하지 않으므로 AI 크레딧을 사용하지 않습니다.

검증

python -m unittest discover -s tests -v
node --check verinote/web/app.js

테스트는 실제 PyreWire 엔진으로 승인/미승인, 경로, 사이클, 관계 혼합 방지, 철회 및 스냅샷 재현을 확인합니다. 문서 버전·동시 승인·추출 중 새 버전·잘못된 인용·실패/타임아웃·HTTP 신뢰 경계도 검사합니다. 외부 CLI는 테스트 transport와 실제 연동 검증을 구분합니다.

설계와 참고 자료 학습 내용은 architecture, learning notes에 있습니다.

자연어 질문은 제출 시 스냅샷과 에이전트·모델을 고정합니다. 최대 문서 100개/승인 사실 500개, 모델 6회, 도구 10회(회당 3개), 원문 읽기 2,000자, UTF-8 프롬프트 60,000바이트/개별 결과 30,000바이트를 허용합니다. 한도 초과·잘못된 인용·실행 오류는 실패로 남깁니다. 질문 로그는 data/questions/<id>/llm-<round>/, 답변과 도구 추적은 SQLite에 보존합니다. 질문 이력은 저장 답변을 열고, 다시 질문은 별도 실행을 생성합니다.

원문 삭제

문서 상세에서 최신 리비전 vN만 삭제와 문서 전체 삭제를 구분합니다. 과거 버전을 보고 있어도 최신 삭제의 대상은 표시된 현재 최신 vN입니다. 확인창에서 삭제 범위를 확인한 뒤 실행합니다.

  • 최신 리비전만 삭제하면 남은 가장 최신 리비전과 그 위키·승인 사실이 현재 기준으로 돌아옵니다. 리비전이 하나뿐이면 전체 삭제를 사용합니다.
  • 문서 전체 삭제는 문서 및 모든 리비전의 원문·위키·사실·검토 이력·추출 기록을 제거합니다.
  • 삭제한 버전을 포함한 스냅샷과 그 스냅샷의 모든 질문·답변·조회 이력도 제거합니다. 여러 문서를 함께 조회한 이력도 포함됩니다. 영향받지 않은 과거 스냅샷은 유지합니다.
  • 삭제한 버전 번호는 재사용하지 않습니다. 예를 들어 v2 삭제 후 v1로 돌아가도 다음 등록은 v3입니다. 버전 비교는 가장 가까운 남은 이전 버전을 사용합니다.
  • 추출·질문 작업이 대기/실행 중이면 삭제를 거부합니다. 작업 완료 후 다시 선택하세요. 오래된 화면의 변경 요청도 충돌로 거부하며 자동 재시도하지 않습니다.
  • 관련 로컬 CLI 로그도 정리합니다. 파일 삭제 실패 시 DB 삭제는 유지하고 로그 정리 대기를 표시합니다. 실행 기록의 재시도 버튼이나 서버 재시작으로 남은 작업을 재시도합니다.

삭제는 되돌릴 수 없습니다. 이미 다운로드한 파일, 별도 백업, 모델 제공자 측 기록을 회수하거나 디스크의 물리적 완전 소거를 보장하는 기능은 아닙니다. 기존 API 클라이언트는 다음 버전 등록 및 삭제 시 문서 GET 응답의 current_version, generation을 각각 expected_version, expected_generation으로 보내야 합니다.

문서 이름으로 질문하기

“등록한 문서가 무엇인가?”처럼 제목을 묻는 질문에는 승인 위키를 먼저 읽고 승인 위키 근거로 설명합니다. 승인 그래프가 비어 있어도 위키 설명은 가능합니다. 승인 자료로 답할 수 없을 때만 조회 이력과 부족한 이유를 검증한 뒤 원문을 읽으며, 미검토 원문 근거로 표시합니다. 문서 제목의 일반적 정의나 법률적 효력까지 자료에 없는데 보충하지는 않습니다. 일반 정의가 필요하면 그 정의를 설명하는 참고 문서를 함께 등록하세요.

문서 검색은 기본적으로 제목·파일명만 NFC/casefold로 비교합니다. 본문 검색은 특정 문서에 대한 원문 보충 조건을 통과한 경우에만 허용합니다. 검색 결과는 문서를 찾는 용도이며 인용 근거가 아닙니다. 모델은 승인 위키 또는 허용된 원문을 실제로 읽어 인용합니다. 읽기 범위와 남은 분량을 전달하여 부분 읽기를 문서 전체 확인으로 혼동하지 않도록 합니다. 정규화 전용 본문 일치의 읽기 시작점은 0이며 정확한 일치 위치를 뜻하지 않습니다. 긴 문서는 도구·문맥 한도 안에서 추가 읽기가 필요할 수 있습니다. 같은 제목의 문서는 파일명·버전으로 구분해 질문하면 좋습니다.

추출 사전과 품질

llmwiki-demos/llmwiki-wirelog는 미리 준비한 개체·별칭·관계 사전과 승인 스냅샷으로 질의하는 데모입니다. 실행 중 임의 문서를 같은 수준으로 추출하는 비교 기준은 아닙니다. 기존 verinote는 짧은 자유 형식 프롬프트로 관계를 생성해 calls/depends_on, managed_by/owned_by처럼 어휘가 달라지고, 명시된 서비스 ID 대신 여러 표기를 사용했습니다. 원문 인용의 존재만 검사하므로 이 차이를 걸러내지 못했습니다.

이제 문서 버전별 사전을 사람이 먼저 승인합니다. 정규 개체 ID와 승인된 별칭만 허용하고, 관계 ID 및 주어·목적어 타입을 검사합니다. 사전에 없는 관계를 자동으로 추가하지 않습니다. 예를 들어 내부 서비스의 직접 호출을 depends_on: Service → Service, 운영 책임을 owned_by: Service → Team으로 정의하면 문서 담당을 서비스 소유 관계로 저장할 수 없습니다. 두 끝점의 타입이 같은 관계의 방향 오류나 인용의 의미까지 자동 증명하지는 않으므로 사람의 검토가 필요합니다.

  • 사전은 개체 200개, 별칭 400개, 관계 40개, 검증된 인용을 포함해 UTF-8 24 MiB까지입니다. 인용은 사전 항목마다 반복될 수 있어 전체 저장 한도와 별도로, 인용을 제외한 정의 문맥은 60,000바이트까지로 제한합니다. 개체는 id/name/type/quote, 별칭은 alias/entity/quote, 관계는 id/description/subject_types/object_types/quote로 편집합니다. name은 인용에 있어야 하고 별칭 인용에는 해당 별칭과 개체 name이 함께 있어야 합니다. 관계 설명에는 의미·포함·제외 기준을 적습니다.
  • 개체 ID에는 order 같은 공식 ID나 문서 간에도 의미 있는 정규 명칭을 사용하세요. e1 같은 임의 번호는 피하고, 서로 다른 FSM의 같은 상태명은 주체 FSM:활성 상태처럼 구분하세요. 그래프는 ID 문자열로 연결하므로 문서 간 동일 ID의 다른 의미·동일 개체의 다른 ID는 사람이 맞춰야 합니다. 전역 사전 병합 기능은 제공하지 않습니다.
  • 사전 생성은 기존 사전의 ID·명칭·타입·별칭·관계 정의를 보내되 이미 검증한 인용문은 문맥에서 제외합니다. 모델은 이번 원문의 구간 ID로 인용 범위를 지정하고, 앱이 원문을 정확히 복원한 뒤 이름·별칭·타입·충돌을 검증합니다. 검토 화면과 저장 사전은 기존처럼 실제 인용문을 표시합니다.
  • 사전 원문은 문장·줄 경계를 우선하는 최대 4,000자 구간으로 나누며 누락·중복 없이 최대 64개까지 처리합니다. 작은 구간은 호출 횟수를 늘릴 수 있고, 경계를 가로지르는 문맥·별칭의 한계는 남습니다. 이름·타입·별칭 대상·관계 설명/방향이 다르면 실제 정의 충돌로 처리합니다. 동일 정의에 유효한 인용만 다르면 검증 후 첫 인용을 유지하며 중복을 합칩니다. 자기 자신을 가리키는 별칭은 대상 개체의 선언과 해당 ID를 포함한 원문 근거를 확인한 뒤 제외합니다. 실제 별칭에는 별칭과 정규 명칭이 함께 있는 근거가 계속 필요합니다. 잘못된 근거·타입·크기 초과는 그대로 실패합니다. 오류에는 이번 응답 내부인지 기존 사전과의 충돌인지, 항목 위치와 다른 필드를 표시합니다.
  • 각 구간 검증이 끝나면 실행 폴더에 복구 기록을 저장합니다. 실패 후 같은 문서 버전·에이전트·모델로 사전 생성을 다시 누르면 호환되는 최근 실패/중단 기록을 재검증하고 완료 구간부터 이어갑니다. 모델 ID가 비어 있으면 같은 ‘기본 모델’ 설정으로 간주하므로 제공자가 기본 모델을 바꾸었는지까지 보장하지 않습니다. 소스·프롬프트·처리 방식이 바뀌거나 기록이 손상됐으면 새로 시작하며 이유를 실행 상세에 표시합니다.
  • 복구 기록은 검토 대상이나 승인이 아닙니다. 모든 구간이 성공해야 하나의 사전이 검토 대기로 저장됩니다. 실행 상세에 완료 글자 수, 재사용한 실행 ID와 새 호출 수를 표시합니다. 진행 저장 실패는 유효한 결과 저장을 막지 않지만 재시도 시 재작업이 필요할 수 있습니다. 문서/버전 삭제 시 해당 실행과 복구 기록도 정리됩니다.
  • 재사용한 구간의 비용은 이전 실행에 남고 새 실행에 중복 집계하지 않습니다. 전체 완료 기록을 재사용하면 새 호출은 0회입니다. 복구·사용량 파일이 없을 때는 0회로 추정하지 않고 미확인으로 표시합니다.
  • 관계 추출은 청크당 주장 12개·사실 80개, 프롬프트당 UTF-8 120,000바이트까지입니다. 조건·부정·시점을 지우면 의미가 바뀌는 내용은 위키 설명으로 남기도록 요청합니다. 상태·구성요소 나열은 각 항목을 검토하도록 요청하지만 누락이 없음을 보장하지는 않습니다.
  • 사전 수정은 다시 검토 대기가 됩니다. 추출 중 사전이 바뀌거나 승인이 철회되면 결과를 저장하지 않습니다. 새 문서 버전은 자체 사전 승인이 필요합니다.
  • 기존 추출 문서에도 사전을 만들고 다시 추출할 수 있습니다. 같은 승인 사전 revision·추출 방식 버전의 성공한 추출은 한 번만 허용하며, 실패·중단은 재시도할 수 있습니다. 이전 방식의 성공 결과는 같은 승인 사전으로 개선된 방식의 재추출을 한 번 할 수 있습니다. 수정·재승인 또는 승인 철회·재승인으로 새 revision이 되면 다시 추출할 수 있습니다. 기존 결과와 승인 이력은 보존하고 새 후보를 추가합니다. 중복 후보와 오래된 승인은 검토자가 판정하세요. 사전 승인 철회는 이미 별도로 승인한 사실을 자동 철회하지 않습니다.
  • 새 후보의 수동 사실 수정도 당시 사전으로 검증합니다. 관계 어휘를 바꾸려면 사전을 수정·재승인하고 새 후보를 추출하세요. 사전 도입 전의 기존 사실은 종전 수정 계약을 유지합니다.

업데이트 전 서버를 종료하고 데이터 폴더 전체를 백업하세요. 시작 시 runs.stage와 runs.ontology 열을 추가하며 기존 실행은 legacy로 보존합니다. 마이그레이션은 재실행 가능하지만 이전 프로그램의 위치 기반 INSERT는 확장된 스키마와 호환되지 않습니다. 이전 버전으로 되돌리려면 프로그램과 함께 업데이트 전 DB 백업을 복원해야 합니다. 기존 데이터에 사전 승인을 소급 생성하지 않습니다.

OpenRouter 실행과 비용

설정 화면에서 OpenRouter를 기본으로 고를 때는 공백이 아닌 모델 ID를 입력하세요. 모델은 제공자별로 저장하고 추출·질문에서 작업별로 바꿀 수 있습니다. 키가 없어도 설정은 저장되지만 실행은 작업 등록 전에 거부됩니다. 키 설정됨은 파일의 값 존재 여부일 뿐 인증·잔액·모델 접근 검사가 아닙니다. macOS에서도 ~/.config/verinote/config.toml처럼 다른 위치를 쓰려면 python -m verinote --config ~/.config/verinote/config.toml로 명시하세요. 파일 편집 후에는 서버를 재시작해야 합니다.

원문·사전·질문 등 프롬프트는 OpenRouter와 라우팅된 모델 제공자에게 전달되며 과금될 수 있습니다. 앱은 고정 HTTPS endpoint에 stream: false와 초기 max_tokens: 16384를 보냅니다. 이 상한은 모델별 지원 한도나 충분한 응답 길이를 보장하지 않습니다. 서버 관리자는 생성자의 ExecutionOptions로 조정할 수 있고 UI 상한 설정은 제공하지 않습니다. 작업 등록 당시 agent/model/상한/단계별 timeout을 고정합니다. 기본 deadline은 사전 호출당 600초, 추출 청크당 360초, 질문 호출당 180초입니다. 명시적 override가 우선하되 추출은 360초를 넘기지 않습니다. 응답 본문은 기본 1 MiB, 메타데이터는 256 KiB로 제한합니다. JSON 텍스트 지시와 기존 로컬 검증을 사용하며 native tool calling이나 구조화 출력 옵션을 추가하지 않습니다.

앱은 자동 재시도·모델 교체를 하지 않습니다. OpenRouter 자체의 기본 upstream 라우팅은 유지되며 실제 응답 모델은 요청 모델과 별도로 기록합니다. 잘림(length)·모델 한도 오류는 실패합니다. 모델 ID나 서버 상한을 수동 조정한 뒤 새 작업을 등록하세요. timeout·연결 단절은 원격 생성 취소나 미과금을 뜻하지 않고 수동 재실행에는 추가 과금될 수 있습니다. 사전 재개는 검증된 구간 재사용이며 출력 재현성 보장이 아닙니다. OpenRouter 계약 버전·상한·timeout이 바뀌면 checkpoint를 재사용하지 않고, 재사용한 과거 호출의 비용은 새 작업에 중복 계상하지 않습니다.

사용량은 모델 content가 아닌 API envelope를 근거로 합니다. 입력에는 캐시가, 출력에는 reasoning이 포함됩니다. 보고 비용은 OpenRouter credits, 설정 단가의 추정 비용은 USD로 구분하며 합산하지 않습니다. 미확인은 0이 아닙니다. 실패한 호출도 안전하게 확인한 사용량을 보존하며 계정 잔액·실제 청구액과 다를 수 있습니다. 원문과 안전 검사한 응답은 로컬 데이터/로그에 남습니다. 알려진 키의 일반·JSON escape 에코는 저장 전에 거부하지만 임의 인코딩, 같은 사용자·관리자·백업 접근까지 모두 보호하지는 않습니다.

실 API 검사는 기본 테스트/CI에서 수행하지 않습니다. 명시적으로 한 번의 합성 요청과 과금 가능성을 허용할 때만 저장소 루트에서 다음을 실행하세요. 키를 인자로 넘기지 않습니다. 이 절차는 max_tokens=256, 전체 60초, 고정 JSON 프롬프트 한 번이며 자동 재전송하지 않습니다.

python -m scripts.openrouter_smoke --allow-network --config ~/.config/verinote/config.toml --model openrouter/free

모델 ID의 사용 가능 여부와 가격은 제공자 상태에 따릅니다. 스크립트 성공은 작은 요청의 연결·응답 검증이며 16,384 상한이나 장문 추출 품질 검증이 아닙니다. 검증 기록과 한계를 참고하세요.

에이전트 설정에서 CLI 제공자의 이름이나 선택 버튼을 클릭하면 설치된 CLI가 안내하는 모델 목록을 불러옵니다. 모델 ID 옆의 사용 가능한 모델에서 고르면 ID 입력란에 반영되며, 설정 저장을 눌러 저장합니다. 빈 ID는 CLI 기본 모델입니다. 같은 제공자를 다시 클릭하면 목록을 갱신합니다. 목록에 없는 ID도 직접 입력할 수 있으며 조회 실패가 기존 입력을 지우지 않습니다. 목록은 CLI 버전·로그인 상태에 따라 달라지고 실제 실행 권한을 보장하지 않습니다. OpenRouter는 기존처럼 모델 ID를 직접 입력합니다. 모델 조회는 프롬프트를 전송하지 않으며, 설치된 CLI 제공자 모두 Windows와 POSIX에서 지원합니다.

About

Honest knowledge base: an LLM extracts source-backed facts, the wirelog logic engine verifies them. Local web app.

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages