OpenKB는 PDF·Office·Markdown·HTML·CSV·URL 등의 원문을 LLM으로 요약·개념·엔티티·교차 링크가 있는 Markdown 위키로 컴파일하고, 그 위키를 질의·채팅·스킬·슬라이드·그래프 출력의 기반으로 사용하는 오픈소스 Python 프로젝트다.[5]

한눈에 보기

  • 저장소: VectifyAI/OpenKB, Python, Apache-2.0, 기본 브랜치 main이다.[1]
  • 고정 snapshot: 조사 기준 main의 commit은 ff54396e575ee6feb0113b631a34caa082b441cc이며, subject는 Workbench의 전역·KB별 entity_types 설정이다.[2]
  • 버전 경계: 이 checkout의 동적 패키지 버전은 0.5.0rc2.dev3+gff54396e5로 관찰됐지만, 최신 정식 release는 v0.4.5, 최신 published prerelease는 v0.5.0-rc1이다.[2][4]
  • 구조: commit-pinned recursive tree API는 340 entries(파일 293, 디렉터리 47, truncated: false)를 보고했고, checkout에는 Python package·62개 테스트 파일·120개 frontend 파일이 포함돼 있다.[3][unverified]
  • 핵심 축: markitdown/trafilatura 입력 계층, 짧은 문서용 전체 텍스트 컴파일러, 20페이지 이상 PDF의 PageIndex 트리 인덱싱, persistent Markdown wiki, OpenAI Agents SDK + LiteLLM 기반 질의·생성기다.[5][6][12]
  • 검증 경계: 이 환경에서 Python 전체 테스트·정적 품질·frontend build·CLI/API smoke는 실행했지만, LLM API 호출과 실제 문서 컴파일 품질·PageIndex Cloud·production exposure는 검증하지 않았다.[unverified]

OpenKB가 만드는 것

OpenKB README는 전통적인 RAG가 질의마다 지식을 다시 찾는 반면, OpenKB는 문서를 한 번 위키로 컴파일해 요약·개념·엔티티·링크를 축적하는 접근을 취한다고 설명한다.[5] 이 framing은 검색 결과를 매번 조합하는 retrieval layer보다, 사람이 읽고 다시 에이전트가 읽을 수 있는 파일 기반 knowledge substrate를 먼저 만든다는 데 의미가 있다.[5][7]

저장되는 기본 지식 구조는 wiki/summaries/, wiki/concepts/, wiki/entities/, wiki/sources/, wiki/index.md, wiki/log.md이며, 사용자 질의 결과는 wiki/explorations/에 보존할 수 있다.[7][14] README는 Google Open Knowledge Format(OKF)과 Obsidian 호환 Markdown·[[wikilinks]]를 주요 호환성 방향으로 제시한다.[5]

저장소의 기능 표면은 두 층이다.[5]

  1. Wiki foundation: init, add, list, status, watch, lint, remove, recompile로 자료를 ingest하고 유지한다.[5]
  2. Generators: query, chat, skill new, visualize, deck new로 축적된 위키를 답변·대화·이식 가능한 스킬·그래프·단일 HTML deck으로 변환한다.[5]

처리 파이프라인

1. 입력 수집과 변환

openkb add는 파일·디렉터리·HTTP(S) URL을 입력으로 받으며, 지원 확장자에는 PDF·Markdown·Word·PowerPoint·Excel·HTML·텍스트·CSV가 포함된다.[5][6]

URL 수집기는 서버의 Content-Type만 믿지 않고 %PDF- magic byte와 HTML 시작 바이트를 우선 검사한다.[10] PDF 응답은 chunk 단위로 raw/에 저장하고, HTML은 trafilatura로 본문 Markdown을 추출한 뒤 일반 파일 ingest 경로로 넘긴다.[10]

변환기는 파일 hash registry를 먼저 검사해 이미 처리한 입력을 건너뛰고, 원문을 raw/에 보존한 뒤 Markdown·PDF·기타 문서별 변환을 수행한다.[9] PDF 페이지 수가 설정된 pageindex_threshold 이상이면 긴 문서 경로로 분기하며 기본 threshold는 20페이지다.[6][9]

2. 짧은 문서와 긴 PDF의 분기

짧은 문서는 MarkItDown 또는 PDF 변환기를 통해 Markdown과 이미지 참조를 만들고, LLM이 전체 텍스트를 문맥으로 읽는다.[5][9]

긴 PDF는 PageIndex의 계층형 tree index와 페이지별 content를 사용한다.[5][11] PageIndex Cloud API key가 있으면 cloud 구조·OCR content를 가져올 수 있고, 없거나 cloud content가 비어 있으면 로컬 PDF 페이지 추출로 fallback하는 코드가 있다.[11]

이 분기는 “모든 문서를 embedding chunk로 잘라 vector DB에 넣는다”는 구조가 아니라, 문서 길이에 따라 전체 텍스트 또는 계층형 문서 구조를 LLM context에 제공하는 설계다.[5][11] 다만 실제 장문 PDF에서 retrieval 정확도·비용·지연을 이 조사에서 측정하지 않았으므로 README의 정확성·확장성 표현은 source-reported claim으로 남겨둔다.[5][unverified]

3. LLM wiki compiler

짧은 문서 compiler는 먼저 JSON 형태의 summary와 description을 만들고, 이후 concept plan을 생성한 다음 concept 생성·갱신과 entity 생성·갱신을 semaphore 아래에서 병렬 수행한다.[12]

각 생성 결과는 기존 파일과 이번 라운드에서 허용된 wikilink target whitelist에 맞춰 ghost link를 제거한 뒤 summary·concept·entity 파일로 쓴다.[12] 마지막으로 관련 페이지 backlink와 index.md를 코드로 갱신하며, summary rewrite가 실패하면 v1 summary를 fallback으로 보존한다.[12]

긴 문서 compiler는 indexer가 먼저 쓴 summary와 PageIndex document tree를 context로 사용해 overview와 concept/entity 페이지를 생성한다.[11][12] 이 설계는 한 문서의 고립된 요약을 만드는 것이 아니라, 기존 concept·entity 페이지를 읽어 여러 문서의 지식을 누적하는 것을 목표로 한다.[5]

OpenKB의 wiki/AGENTS.md는 summary·concept·entity·exploration 페이지의 역할과 frontmatter·index·log 규칙을 런타임에 LLM에게 전달한다.[7] 즉 지식 구조의 일부가 Python 코드에만 고정되지 않고, 사용자가 편집할 수 있는 Markdown instruction layer로 노출된다.[7][12]

질의·채팅·멀티모달 도구

Query agent는 먼저 index.md를 읽고 관련 summary·concept·entity를 좁힌 뒤, 짧은 문서는 read_file, PageIndex 문서는 필요한 page range만 get_page_content로 읽도록 지시받는다.[13]

이미지 질문에는 wiki 이미지 파일을 data URL로 반환하는 get_image 도구를 사용할 수 있다.[13][14] 따라서 문서가 텍스트만이 아니라 figure·table·image를 포함한다는 README의 multi-modality 방향이 agent tool surface에도 반영돼 있다.[5]

Chat agent는 query agent에 제한된 write tool을 추가한다.[14] 허용된 쓰기 영역은 wiki/explorations/**output/**이며, local skills/, ~/.openkb/skills/, ~/.claude/skills/를 검색해 설치된 SKILL.md를 읽을 수 있다.[14]

질의·채팅은 OpenAI Agents SDK를 사용하지만 모델 이름에는 litellm/ prefix를 붙여 LiteLLM provider/model 형식으로 라우팅한다.[13] openai-agents·LiteLLM·OpenAI 버전은 pyproject.tomluv.lock에 고정돼 있고, 저장소는 공급망 변경을 의도적으로 검토하라는 주석을 둔다.[6][7]

CLI와 설치 흐름

기본 설치 명령은 pip install openkb이며, API·Workbench는 openkb[web] extra를 사용한다.[5][6] 저장소 개발 안내는 uv sync --extra devpytest, ruff, mypy 명령을 제공한다.[7]

pip install openkb
mkdir my-kb && cd my-kb
openkb init
openkb add paper.pdf
openkb query "What are the main findings?"
openkb chat

openkb init.openkb/config.yaml에 model·language·pageindex_threshold를 기록하고 raw/, wiki/, .openkb/hashes.json을 만든다.[5][7] LLM key는 선택적으로 .env에 기록되지만, 이 위키에는 실제 credential 값을 저장하지 않았다.[6]

실제 CLI help에는 init, add, query, chat, list, status, watch, lint, remove, recompile, visualize, skill, deck, delete-kb, feedback, use가 노출됐다.[unverified] recompile은 기존 indexed document를 다시 컴파일하며 manual edit가 덮어써질 수 있고, remove는 wiki page·image·registry·PageIndex state cleanup을 함께 수행한다.[5]

openkb visualize[[wikilink]] 그래프를 self-contained HTML로 만들고, openkb deck new는 단일 HTML slide deck을 생성한다.[5][21] Deck validator는 HTML parse, 최소 slide 수, 외부 link/script/image 참조 여부, 선택적인 skill-declared slide grammar를 검사한다.[21]

FastAPI와 Knowledge Workbench

openkb-web은 FastAPI REST server와 bundled React/Vite Workbench를 같은 프로세스에서 제공한다.[5][15][23]. Frontend bundle은 git에 직접 추적되지 않는 openkb/web/에 build되고, release workflow가 wheel/sdist에 강제로 포함한다.[6]

REST API는 KB 목록·초기화·파일 업로드·query·chat·session 관리·list/status·lint·remove·recompile·watcher·config·페이지/문서 작업을 /api/v1 아래에 노출한다.[15][16] query, chat, remove, recompile, add 일부 경로와 watcher events는 Server-Sent Events로 진행 상황·tool call·delta·final·error를 전달한다.[16]

API 인증은 기본적으로 local-first의 opt-in 방식이며 OPENKB_API_TOKEN이 설정됐을 때만 bearer token을 요구한다.[16] 비 loopback host로 노출할 경우 token을 설정하지 않으면 API와 접근 가능한 KB가 외부에 열릴 수 있으므로, 저장소 문서도 0.0.0.0 같은 bind에서는 token 설정을 요구한다.[16]

Workbench에는 overview·documents upload/delete·streamed query/chat·maintenance lint/recompile·watcher toggle·Inspector timeline이 포함된다.[16] 이번 환경에서는 FastAPI app 생성과 /api/v1/meta, /api/v1/kbs local smoke만 실행했으며, LLM-backed query·upload compile·browser visual rendering은 실행하지 않았다.[unverified]

Skill Factory와 생성기 품질 모델

Skill Factory는 위키 내용을 portable SKILL.md 디렉터리로 증류해 Claude Code·Codex·Gemini CLI 같은 에이전트가 재사용할 수 있는 결과를 만드는 기능이다.[5][14] 생성기는 target skill directory에 제한된 write tool만 사용하고, 완료 전에 SKILL.md가 실제로 생겼는지 확인한다.[14]

Skill evaluator는 skill description만 보고 로드 여부를 판단하는 trigger accuracy와, body·references가 실제 약속된 질문을 지원하는지 보는 body alignment를 별도 metric으로 계산한다.[20] 기본 10개 trigger + 10개 no-trigger prompt를 만들고 grader 동시성을 8로 제한해 rate limit을 완화한다.[20]

이 구조는 “스킬 파일을 생성했다”와 “올바른 질문에서 선택되고 실제로 답할 수 있다”를 분리한다는 점에서, 단순 파일 생성보다 운영 가능한 skill distribution에 가깝다.[20][unverified]

무결성·동시성·보안 경계

저장소의 golden principles는 모든 wiki write를 locks.py/mutation.py를 통과시키고, 진단 log를 전용 logging 경로로 남기도록 규정한다.[8] 파일 크기와 모듈 책임도 CI·테스트로 관리하려 하며, 기본 규칙은 모듈 800라인 미만이다.[8]

locks.py는 portalocker 기반 advisory lock과 프로세스 내부 read/write lock을 제공하고, exclusive lock을 얻을 때 이전 mutation journal recovery를 수행한다.[18] mutation.py는 temp file·os.replace·fsync·snapshot/journal·rollback을 조합해 KB mutation을 crash-safe하게 복구하려는 구조다.[17][18]

Agent file tool은 wiki root 밖으로 탈출하는 path를 거부하고, read zone을 wiki/, output/, skills/로 제한한다.[14] Chat write tool은 더 좁은 wiki/explorations/output/만 허용해 query agent가 임의의 KB 파일을 덮어쓰지 못하게 한다.[14]

YAML frontmatter는 시작·종료 delimiter를 line-anchored로 파싱하고, JSON-quoted scalar/list helper로 lossless round-trip을 지향한다.[19] 이 frontmatter는 OKF page type·description·summary/concept/entity routing의 기반이 된다.[7][19]

의존성은 pyproject.toml에서 exact pin을 사용한다.[6] 이번 checkout의 주요 직접 의존성은 PageIndex 0.3.0.dev3, MarkItDown 0.1.5, trafilatura 2.0.0, LiteLLM 1.87.2, OpenAI Agents 0.17.3, OpenAI 2.44.0, Click 8.4.0, watchdog 6.0.0, PyYAML 6.0.3, portalocker 3.2.0이며 web extra는 FastAPI·uvicorn·python-multipart다.[6]

실제 검증 결과

통과한 bounded checks

  • /tmp/openkb/.venvuv sync --locked --extra dev --extra api --python 3.11을 실행해 lockfile 기준 개발·API 환경을 만들었다.[unverified]
  • python -m compileall -q openkb는 exit 0이었다.[unverified]
  • openkb --helpopenkb --version은 정상 실행됐고 버전은 0.5.0rc2.dev3+gff54396e5였다.[unverified]
  • 빈 API key로 새 /tmp/openkb-smoke KB를 초기화한 뒤 statuslist가 정상 실행됐고 .env는 생성되지 않았다.[unverified]
  • create_app()은 38개 route를 만들었고 /api/v1/meta, /api/v1/kbs는 HTTP 200을 반환했다.[unverified]
  • Python 전체 테스트는 1249 passed, 2 warnings in 27.87s로 exit 0이었다.[unverified] 두 warning은 mock된 async compiler coroutine에 대한 RuntimeWarning이었다.[unverified]
  • ruff check . 통과, ruff format --check .에서 119 files already formatted, mypy openkb에서 56 source files no issues를 확인했다.[unverified]
  • 저장소 CI 정의는 Python 3.12에서 locked install 후 ruff·format·mypy·pytest를 실행하고, 별도 web job에서 Node 20 frontend build를 실행한다.[22]
  • frontend npm ci && npm run build는 i18n guard와 Vite production build를 통과했다.[unverified] npm audit는 7 vulnerabilities(3 moderate, 4 high)를 보고했고, Vite는 500 kB 초과 chunk warning을 출력했다.[unverified]

실행하지 않은 항목

실제 LLM provider 호출, 사용자 문서의 summary/concept/entity 생성, 긴 PDF PageIndex retrieval 품질, PageIndex Cloud OCR, semantic lint의 실제 판정, Skill Factory의 모델 기반 결과, deck 디자인 품질은 실행하지 않았다.[unverified]

API key·AWS credential·PageIndex key·OAuth token·개인 문서·실제 비 loopback server exposure는 사용하지 않았고, 어떤 인증 값도 capture·summary에 보존하지 않았다.[unverified]

따라서 1249 passed는 저장소의 로컬 계약·fixture·API·compiler 테스트가 통과했다는 뜻이지, 외부 LLM을 연결한 end-to-end knowledge compilation 품질이나 장문 검색 품질이 보장됐다는 뜻은 아니다.[unverified]

평가와 실무적 위치

OpenKB의 핵심 선택은 vector DB를 제거했다는 단일 기능보다, 문서 ingest → 파일 기반 위키 compilation → agent query/generator를 하나의 누적 lifecycle로 묶은 것이다.[5][11]. 이 모델은 Obsidian·Git·일반 Markdown tooling과 잘 맞고, 위키를 사람이 검토·수정할 수 있는 중간 산출물로 남긴다.[5][7]

PageIndex tree는 장문 PDF에서 필요한 페이지를 reasoning으로 좁히려는 구조이고, short-doc compiler는 기존 concept/entity를 재사용해 cross-document synthesis를 시도한다.[11][12] 반대로 DB-backed storage, 대규모 nested folder collection, 비-PDF long-document handling은 README roadmap에 남아 있어 현재 구현의 범위를 과장하면 안 된다.[5]

운영 전에는 bearer auth를 켜고, .env·환경 변수·API gateway의 secret 관리, LLM provider 데이터 보존 정책, 문서 prompt injection, 생성된 wikilink와 frontmatter의 사람 검토를 별도 threat model로 다뤄야 한다.[16][18][unverified]

현재 저장소 snapshot은 release보다 앞선 개발 상태이므로, 재현 가능한 설치·배포 문서에는 main HEAD를 최신 안정판처럼 표기하지 말고 v0.4.5·v0.5.0-rc1·고정 commit을 구분해 기록하는 편이 안전하다.[2][4]

관련 위키

고정 snapshot과 provenance

  • 공식 저장소: VectifyAI/OpenKB[1]
  • 고정 commit: ff54396e575ee6feb0113b631a34caa082b441cc[2]
  • README pinned raw: README.md[5]
  • 선택 원문·파일 hash·실행 경계: raw source: github-vectifyai-openkb[unverified]
  • raw body SHA-256: ce59096873e4f11c8e81829a4f5b7a1bd789c2e09271d46645872ff783133a64[unverified]
  • 저장소 전체·node_modules·생성된 frontend bundle·credential 값은 위키에 복제하지 않았다.[unverified]

Sources

[1] https://api.github.com/repos/VectifyAI/OpenKB [2] https://api.github.com/repos/VectifyAI/OpenKB/commits/ff54396e575ee6feb0113b631a34caa082b441cc [3] https://api.github.com/repos/VectifyAI/OpenKB/git/trees/ff54396e575ee6feb0113b631a34caa082b441cc?recursive=1 [4] https://api.github.com/repos/VectifyAI/OpenKB/releases [5] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/README.md [6] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/pyproject.toml [7] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/AGENTS.md [8] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/docs/golden-principles.md [9] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/converter.py [10] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/url_ingest.py [11] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/indexer.py [12] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/agent/compiler.py [13] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/agent/query.py [14] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/agent/tools.py [15] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/api.py [16] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/examples/rest-api/README.md [17] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/mutation.py [18] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/locks.py [19] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/frontmatter.py [20] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/skill/evaluator.py [21] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/openkb/deck/validator.py [22] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/.github/workflows/ci.yml [23] https://raw.githubusercontent.com/VectifyAI/OpenKB/ff54396e575ee6feb0113b631a34caa082b441cc/frontend/package.json