研究代理

个人研究代理,通过自然语言执行 arXiv 搜索、引用图分析、多模态论文 wiki 构建与可视化。

  • by cholhwanjung
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 cholhwanjung/research-mcp

使用说明

Research MCP

개인용 연구 에이전트 — arXiv 검색·인용 그래프·멀티모달 논문 위키·시각화를 자연어 한 줄로 실행. Claude Desktop (MCP) 과 self-hosted 웹 채팅 앱 두 가지 인터페이스 사용.


주요 기능

1. 검색과 인용 그래프

  • arXiv 검색 — 키워드/카테고리로 검색하고 결과를 최근 1년 / 3년 / 5년 / 그 이상 으로 자동 분류.
  • 인용 그래프 — 특정 논문의 references / citations를 가져와 정렬.
    • sort="count" — 절대 인용수 순.
    • sort="velocity" — citation velocity (citations / (현재연도 − 발행연도)) 순. 오래된 논문이 절대 인용수만으로 항상 이기는 문제를 보정해 최신 흐름에 가까운 결과를 보여준다.
  • 인용 문맥 (citation contexts) — Semantic Scholar의 contexts API로 왜 인용했는지 본문 스니펫을 수집.

2. 멀티모달 논문 위키 (Obsidian vault)

한 번 ingest한 논문은 폴더형 구조로 vault에 저장된다.

vault/papers/blip-2/
├── blip-2.md         # frontmatter + TL;DR / Methods / Findings / References (파일명 = 폴더 slug)
└── figures/
    ├── fig_1_overview-of-blip-2s-framework.png
    ├── fig_2_q-former-architecture.png
    └── ...
  • PDF 원본 보관 — vault/pdfs/<arxiv_id>.pdf 에 영구 저장. 동일 ID 재요청 시 다운로드 skip.
  • Vision 기반 figure / table 추출 — Gemini Vision으로 figure·table 영역을 crop한다. (GOOGLE_API_KEY 필요)
  • 안정 hub 분류 — 큐레이트된 hub 노트(e.g. topics/*.md — LLM, VLM, Diffusion, Agent-Reasoning)에 1–3개로 매핑.
  • 양방향 wikilink — [[clip]] 같은 wikilink가 자동 누적.
  • vault 리트리벌 — wiki_search로 "질문 → 관련 노트"를 어휘 seed + [[wikilink]] 이웃 확장으로 검색. vault 전체를 로드하지 않고 관련 노트만 추린다.
  • 종합 통찰 노트 — 세션에서 논문을 가로질러 얻은 통찰을 insight-capture 스킬로 notes/<slug>.md에 누적 (승인 게이트).

3. 시각화: Mermaid + Obsidian

한 anchor 논문을 중심으로 인용 흐름을 카드 그래프 로 출력.

  • Mermaid graph — 응답에 즉시 임베드되어 Claude Desktop / GitHub / Obsidian이 그대로 렌더.
  • Mermaid 노트 저장 — 같은 다이어그램을 vault/graphs/<slug>.md 노트로도 저장. Obsidian이 노트를 열면 그래프로 렌더 (auto-layout이라 노드 겹침 없음).
  • 통합 인용 네트워크 export — vault 전체 논문의 인용 관계를 공통 노드(논문·hub) 기준 하나의 그래프로 통합해 CSV(Cosmograph)/GEXF(Gephi Lite)로 export. 엣지 200 이하 소형이면 graphs/unified.md Mermaid도 함께 산출.
graph LR
  anchor["BLIP-2 (2023, cited 1234)"]
  refs["CLIP (2021)"] --> anchor
  anchor --> cite1["LLaVA (2023)"]
  anchor --> cite2["InstructBLIP (2023)"]

4. 일일 인기 논문 피드

  • 테크 블로그 다이제스트 — Anthropic·OpenAI·DeepMind·Google Research 블로그의 신규 포스트를 본문 기반(차단 소스는 RSS)으로 몇 문단 요약해 tech-blog-digest/<date>.md에 누적. seen 상태를 추적해 실행 시마다 소스별 마지막 요약 이후 올라온 글만 최대 30개씩 처리(그보다 옛날 글은 건너뜀).

아키텍처

sources/  →  analysis/  →  wiki/  →  tools/  ─┬─  server.py            (Claude Desktop · MCP)
 (fetch)     (rank/group)  (vault)  (24 tool)  │
                                               └─  agent/ → api/ → web/  (웹 앱 · SSE 채팅)
  • 단방향 import — 위 화살표 방향으로만 의존. 역방향 금지.
  • tool은 한 곳에 정의 — tools/*.py의 함수를 MCP(server.py)와 에이전트(agent/)가 동일하게 재사용한다. 같은 24개 도구가 두 transport로 노출된다.
  • 에이전트 — Pydantic-AI. provider-prefixed 모델 문자열(anthropic: / openai: / google:)로 멀티 provider 전환. 스킬 정의를 system prompt로 로드.

MCP Tool 카탈로그 (24)

각 tool은 한 카테고리에만 속하도록 직교적으로 설계 — 호출 순서를 가진 워크플로우는 아래 스킬 로 묶인다.

카테고리 Tool
fetch search_papers, get_paper_by_id, get_citation_contexts
graph get_references_by_citations, get_citations_by_citations
artifact download_paper, read_paper, extract_paper_figures, extract_paper_tables, prune_paper_figures, prune_paper_tables, render_paper_page
wiki wiki_read_note, wiki_write_note, wiki_list, wiki_list_hubs, wiki_search, wiki_backlinks, wiki_link
viz build_citation_graph, export_citation_network
blog get_tech_blog_posts, read_blog_post, mark_blog_posts_seen

스킬 (워크플로우)

자연어 한 줄로 호출 가능한 사전 정의 워크플로우 (도구 호출 시퀀스).

스킬 트리거 예시 하는 일
paper-ingest "이 논문 ingest", "BLIP-2 위키에 추가" 메타·PDF·figure·table·요약을 한 번에 vault에 누적. 분야를 기존 hub에 매핑.
citation-analysis "BLIP-2 흐름 보여줘", "<arxiv_id> 인용 분석" anchor 1편 중심으로 refs/cites를 hub로 분류 + cited_for 채우기 + 시각화. vault 영구 누적은 사용자 승인 게이트.
wiki-lint "위키 점검", "vault 정리" vault 정합성 점검 — orphan·깨진 링크·누락 교차참조·stale hub·노트 간 모순 스캔 → 승인 게이트 diff.
insight-capture "이 통찰 저장", "notes에 정리" 논문을 가로질러 종합한 통찰을 notes/<slug>.md에 누적 (승인 게이트).
tech-blog-digest "테크 블로그 요약", "blog digest" Anthropic·OpenAI·DeepMind·Google Research 신규 포스트를 본문 기반 요약해 tech-blog-digest/<date>.md에 누적 (소스별 마지막 요약 이후만, 최대 30).
research-autopilot "밤새 논문 쌓아줘", /loop 10m /research-autopilot scope=graph-rag,finance-agents 무인 축적 루프의 한 반복 — 대기열 유도 → 논문 1편 ingest → 인용 분석 → hub 판정 → 깨진 링크 정정을 자동 승인으로 수행하고 _meta/autopilot-log에 기록. scope(hub slug)는 실행마다 필수 — 없으면 hub 목록과 함께 묻고 돌지 않으며, 전체는 all을 명시할 때만. 큐가 비면 scope 안 중심 논문의 인용 이웃으로 리필. 중요도 게이트(citation velocity ≥ 10 또는 vault 참조 2곳 이상, hub가 부르는 논문은 면제)로 낮은 중요도 후보는 보류. figure/table은 추출하지 않는다(텍스트 요약만, 아침에 on-demand). 한도로 끊긴 반복은 vault 상태에서 이어받는다. 정지 시 들어온 논문 요약·통찰 후보·아침 할 일을 담은 실행 보고서를 채팅과 research-autopilot/<date>.md에 남긴다. 통찰·lint 반영은 사람 몫. 본 세션은 디스패처(SKILL.md)만, 반복은 서브에이전트 워커가 WORKER.md를 읽어 새 컨텍스트에서. /loop이 사용자가 멈출 때까지 반복.

research-autopilot 운용

시작   /loop 10m /research-autopilot scope=graph-rag,finance-agents max_papers=10   권장
       /loop 10m /research-autopilot graph rag랑 금융 에이전트                        자연어 — 첫 tick이 hub로 해석해 확정 slug를 보여주고 고정
       /loop 10m /research-autopilot                                              scope 없음 → hub 목록과 함께 묻고, 답할 때까지 돌지 않는다
       /loop /research-autopilot scope=…                                          지켜볼 때만 (동적 self-pacing)
정지   "autopilot 멈춰" · 제어 노트 stop: true (다음 tick) · 자동(max_papers·큐 소진·연속 실패 3) · 세션 종료
재개   새 /loop. scope는 다시 준다 (max_papers·min_velocity는 남는다)
보고   정지 시 자동 → 채팅 + research-autopilot/<날짜>.md. "autopilot 보고" → 정지 없이 현재 실행 보고서만 (저장 없음)
탐색   제어 노트 explore: true → 실행 중 발견한 hub 후보도 의도 안이면 탐색 주제로 편입(실행당 max_topics, 기본 3). 기본 false
       /loop 10m /research-autopilot τ-bench를 도전한 논문                         관계 의도 → anchor 탐색 주제: 벤치마크의 cited_by를 50편 회차로 문맥 판정, 워커가 유용도(상/중/하)로 골라 큐에. 논문 ID·이름·hub 이름 가능
       velocity는 회차 순서일 뿐 컷이 아니다. 2회차 연속 유용한 게 없으면 소진. 하로 걸러진 논문은 anchor 노트 cited_by에 남고, 우선 큐로 옮기면 읽는다
       후속만 위주로 보려면 anchor 의도를 단독 scope로 — hub와 섞으면 seed(P5)는 깨진 링크·다이제스트(P3·P4) 뒤. 실행 전 ## 우선 큐가 비었는지 확인. "후속 논문"은 도전(평가), "후속 벤치마크"는 비교
       hub 이름을 anchor로 주면 정의에 맞는 벤치마크 논문만 velocity 순 max_topics(기본 3)까지 펼친다 — 더 보려면 제어 노트에서 올린다
전제   세션 유지 (Mac 잠자기 방지 예: caffeinate -dimsu). 한 vault에 루프는 한 세션만

설치

요구사항

  • Python >=3.10
  • uv (의존성 관리)
  • Obsidian (vault·그래프를 보기 위해 — 권장)
uv sync

플러그인 설치 (권장 — Claude Desktop / Claude Code)

/plugin marketplace add cholhwanjung/research-mcp
/plugin install research-mcp@research-mcp-local

활성화(enable) 시 아래를 프롬프트로 입력한다. secret은 repo가 아니라 keychain에 저장된다.

설정 설명
vault_path vault 루트 (예: /Users/you/Documents/research-wiki). 비우면 ~/Documents/research-wiki
google_api_key Gemini Vision — figure/table 추출용. 없으면 멀티모달 skip, 텍스트 요약만
ss_api_key Semantic Scholar API key (선택) — rate-limit 완화

요구사항: uv가 설치돼 있어야 한다 (플러그인이 server.py를 uv로 기동). 첫 기동 시 의존성 sync가 한 번 돈다(네트워크 필요, 수십 초). 업데이트는 /plugin marketplace update 후 재설치.

Claude Desktop MCP 설정 (수동 — 대안)

플러그인 대신 MCP 서버만 직접 등록하는 방법. 이 경로는 스킬을 포함하지 않는다 (플러그인은 6개 스킬까지 번들). tool만 필요할 때 사용.

~/Library/Application Support/Claude/claude_desktop_config.json 에 추가:

{
  "mcpServers": {
    "research": {
      "command": "uv",
      "args": ["--directory", "/path/to/research-mcp", "run", "python", "server.py"],
      "env": {
        "OBSIDIAN_VAULT_PATH": "/Users/you/Documents/research-wiki",
        "GOOGLE_API_KEY": "<Gemini Vision — figure/table 추출용>",
        "SS_API_KEY": "<optional Semantic Scholar API key>"
      }
    }
  }
}
변수 기본값 설명
OBSIDIAN_VAULT_PATH ~/Documents/research-wiki 노트·PDF·figure 저장 vault 루트
PDF_PATH $OBSIDIAN_VAULT_PATH/pdfs PDF 원본 저장 위치
GOOGLE_API_KEY (없음) Gemini Vision — figure/table bbox 추정에 필요
SS_API_KEY (없음) Semantic Scholar API key. 설정 시 rate-limit 완화
OPENALEX_API_KEY (없음) OpenAlex API key(무료). 없어도 동작(일 1,000크레딧), 설정 시 10배. get_citations_by_citations가 SS에서 잘린 연도를 보강할 때만 호출

독립 autopilot 런타임

Claude Code(/loop·서브에이전트) 없이 같은 vault·같은 제어 노트·같은 로그로 autopilot을 돈다. 스킬 모드가 하는 일을 모두 한다 — 게이트·대기열(우선 큐·깨진 링크·hub 평문 이름·탐색 주제 seed·백필·frontier)·scope/중요도 게이트·ingest·인용 분석·탐색 주제 소속과 hub 승격·신규 hub·anchor 관계 확정·링크 정정·리필·정지 처리·실행 보고서. 결정론으로 끝나는 일은 코드가, 판단은 provider 무관 에이전트가 맡는다.

uv run python -m agent.autopilot --scope autonomous-research-agents --max-papers 5 --model openai:gpt-5
uv run python -m agent.autopilot --scope "The AI Scientist를 도전한 논문" --model openai:gpt-5
uv run python -m agent.autopilot stop
uv run python -m agent.autopilot report
uv run python -m agent.autopilot config --scope "graph rag" --max-papers 10
명령 하는 일
run (기본) 반복을 돈다. 정지하면 research-autopilot/<날짜>.md에 실행 보고서
stop 사용자 정지. 루프가 돌고 있으면 정지 요청만 기록하고, 그 루프가 이번 반복을 마친 뒤 정지·보고
report 진행 중이면 현재 실행, 아니면 마지막 실행의 보고서를 출력 (저장 없음)
config scope·max_papers만 기록 (반복을 시작하지 않음)
  • --scope — hub·탐색 주제 slug(쉼표), all, 또는 자연어. 자연어는 첫 반복에 hub·탐색 주제(검색어 주제, "X를 도전한 논문" 같은 anchor 주제)로 옮겨 등록하고 scope 확정:으로 알린다. 같은 원문이면 다시 해석하지 않는다.
  • --once 한 반복만 · --interval 반복 사이 대기 초(기본 60) · --max-papers · --model provider:model(없으면 RESEARCH_MODEL).
  • 정지 — 실행 중 제어 노트에 stop: true, stop 명령, Ctrl+C 모두 사용자 정지(reason=user)로 열린 반복을 닫는다.
  • 한 vault에 루프 하나(_meta/autopilot.lock). 제어 노트는 반복 중 사용자가 고친 내용 위에 변경분만 얹어 저장한다.
  • 에이전트는 파일을 쓰지 않는다 — 노트 형식·hub 검증·내부 식별자 차단·링크 치환은 코드가 한다.
  • 외부 문서(본문·초록·인용 문맥·검색 결과)는 신뢰 경계 표지로 감싸 본문 속 지시를 따르지 않는다. 노트 수치는 원문과 대조해 unverified_numbers=로 남긴다.
  • 로그 결과 줄에 runtime=standalone·tokens·requests. 스킬 모드와 번갈아 돌릴 수 있다(동시에는 하나).
  • 요약은 논문 본문과 함께 vault 노트를 찾아 읽고(wiki_search·wiki_read_note), 항목을 '굵은 머리 — 설명' 문단으로 쓴다. 본문 링크는 실재하는 노트만 남는다. References 절은 방향별 종합 문단 + 관계 접두사별 목록.
  • 스킬 모드와 다른 점 — hub 본문이 평문으로 부른 논문은 scope 게이트 면제, 반복당 scope 밖 3건·후보 20건 상한.
  • 모델 호출 비용·API 키는 사용자 몫이다.

웹 앱 (self-hosted) — 멀티 LLM 채팅

Claude Desktop 외에, 같은 도구·워크플로우를 웹 채팅 UI로도 쓸 수 있음.

구성

  • api/ — FastAPI + SSE 백엔드. /chat(스트리밍·승인 재개) · /snapshots/{id}/restore · /skills · /health. Bearer 토큰 인증.
  • agent/ — Pydantic-AI 하네스(provider 무관). MCP의 tool 재사용 + vault 작업 공간(읽기·쓰기·편집·찾기·검색) + 스킬 점진 로딩 + 읽기 전용 위임 + autopilot 작업 도구.
  • web/ — Next.js 채팅 프론트 (스트리밍 + 승인 카드·되돌리기 + 권한 모드·모델 선택 + 토큰 입력).

권한 — 승인·모드·되돌리기

  • 파일 경로는 vault 안만 받는다(..·절대경로·심볼릭 링크 탈출 거부, .obsidian/·.git/ 쓰기 거부). 셸·코드 실행 도구는 없다.
  • 모드(우상단): 확인 후 편집(기본 — vault 쓰기·설정 변경·삭제·비용 작업 전에 승인 카드) · 편집 자동 허용(vault 편집은 바로, 삭제·비용 작업은 승인) · 읽기 전용.
  • 승인 카드에 diff·삭제 대상·비용 안내가 보인다. 허용 / 이 세션 동안 허용(편집 도구만) / 거부.
  • 에이전트가 쓴 파일은 도구 카드의 되돌리기로 쓰기 전 내용으로 돌린다. 스냅샷·감사 로그(key=value)는 vault 밖 RESEARCH_AGENT_STATE_DIR(기본 .cache/agent)에 쌓인다.
  • RESEARCH_API_TOKEN이 없으면 서버가 읽기 전용으로 고정된다 — 쓰기·autopilot 시작은 토큰을 설정한 뒤에.
  • 채팅의 "autopilot 시작·멈춰·보고·오늘은 X로"는 autopilot 작업 도구(독립 런타임 루프, 시작·설정은 승인)로 간다.

실행 — 한 번에 (로컬, 추천)

cp .env.example .env       # 쓸 provider 키만 채우기 (예: GOOGLE_API_KEY)
./run-web.sh               # .env 의 RESEARCH_MODEL (미설정 시 Claude)
./run-web.sh google        # Gemini  — GOOGLE_API_KEY 만 있으면 됨 (Anthropic 키 불필요)
./run-web.sh openai        # GPT-4o  — OPENAI_API_KEY
./run-web.sh anthropic     # Claude  — ANTHROPIC_API_KEY

→ 백엔드(:8000)+프론트(:3000) 동시 기동. 접속: http://localhost:3000

  • 인자로 고른 모델이 백엔드 기본값(RESEARCH_MODEL)으로 적용 (웹 UI에서 메시지별 전환도 가능). provider:model 직접 지정도 됨 (예: ./run-web.sh google:gemini-2.0-flash).
  • 선택한 provider 키가 없으면 부팅 전에 안내하고 멈춤 (lifespan 에러 회피).
  • Ctrl-C 한 번으로 둘 다 종료. 최초 1회 uv sync·npm install 자동, Docker 불필요.
  • .env는 백엔드(core/config.py)가 자동 로드, 프론트 기본 API_URL은 http://localhost:8000.

사용: 우상단 토큰칸에 RESEARCH_API_TOKEN 값 입력 → 채팅 (토큰 없이 띄운 서버는 읽기 전용). 예: "BLIP-2 위키에 추가해줘" → 채팅에 tool 실행 흐름 표시 → Obsidian을 열어 노트·그래프 확인.

실행 — Docker (self-hosted 배포)

cp .env.example .env        # provider 키 + VAULT_HOST_PATH 채우기
docker compose up --build   # 백엔드 → http://localhost:8000
  • VAULT_HOST_PATH는 Docker 파일공유 대상 경로여야 한다 (홈 하위 ~/Documents/...는 기본 공유됨; /tmp 등은 공유 안 될 수 있어 컨테이너가 안 뜬다).
  • 세션 SQLite는 named volume(sessions)에 저장 — vault 바인드마운트와 분리해 안정성 확보.
  • 프론트는 컨테이너에 없음 → 아래 "수동 실행"의 프론트 명령으로 별도 기동.

수동 실행 (개별 기동, 선택)

run-web.sh 대신 백엔드·프론트를 따로 띄울 때:

uv run uvicorn api.main:create_app --factory --port 8000   # 백엔드
cd web && npm run dev                                       # 프론트(:3000)

백엔드를 비표준 호스트/포트로 띄우면 web/.env.local에 NEXT_PUBLIC_API_URL=… 지정.

환경 변수 (웹 앱)

변수 설명
RESEARCH_API_TOKEN 설정 시 API 호출에 Authorization: Bearer 강제. 비우면 인증 off + 읽기 전용(쓰기·autopilot 시작 도구 숨김)
RESEARCH_AGENT_STATE_DIR 스냅샷·감사 로그 폴더 (기본 .cache/agent, compose는 /data/agent)
RESEARCH_MODEL 기본 채팅 모델 (anthropic:… / openai:… / google:…)
ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY 사용할 provider 키
GOOGLE_API_KEY Gemini Vision — figure/table 추출 (ingest 시)
VAULT_HOST_PATH (compose) host vault 절대경로 → 컨테이너 /vault

평가 — 의도 이해·노트 품질·교차 시스템 비교

평가 대상 — pydantic-ai 에이전트 두 층

층 구성 LLM이 맡는 것 코드가 맡는 것
채팅 하네스 (agent/runtime.py) Agent 하나. provider 접두사 모델 문자열, 지침 = 하네스 규칙 + 스킬 목록(본문은 도구로 로드), toolset = 연구 도구(외부 문서 출력은 <untrusted_document>로 감쌈) + vault 작업 공간 + 스킬 로드 + autopilot 작업 + 읽기 전용 위임, 전체를 PolicyToolset이 감쌈. 출력은 str | DeferredToolRequests 도구 선택·응답 권한 판정(allow·ask·deny)과 승인 멈춤·재개, 쓰기 전 스냅샷·감사 로그, 이벤트 스트림(tool_call·tool_result·text·approval_required·done)
autopilot 런타임 (agent/autopilot/runner.py) 반복 1회 = 논문 1편을 코드가 순서대로 조율. LLM은 구조화 출력 에이전트만(reader → NoteDraft, scope 판정, 인용 판정, References 종합, hub 큐레이터, 제목 판정, 이름 추출, 제목 매칭, scope 해석, 보고서 종합) 요약·판정·종합 제어 노트·게이트·큐·스크리닝·노트 렌더·수치 대조·쓰기·인용 병합·로그. 호출마다 UsageLimits, 외부 문서는 신뢰 경계 표지, 의존성 주입으로 가짜 모델 테스트

방법론

  • 두 층을 따로 잰다 — 대화형은 "의도 → 도구 궤적", 노트는 "산출물의 원문 충실성과 쓸모". 실패 양상이 다르다.
  • 대화형 사례 = 발화 + 기대 조건(tools_all/any/none·approval_for·asks_user·final_matches/excludes·unchanged·outside_unchanged). 사례마다 vault 복사본에 전용 파일(주입 노트·오타 파일)을 심고 전후 해시로 불변을 본다. 승인 요청은 항상 거부하고 같은 이력으로 계속 → 쓰기 의도는 승인 요청으로 잡히고 부작용은 0.
  • 세 축 — A 스킬 모드(헤드리스 Claude Code + 같은 스킬·같은 MCP 서버, Opus 5), B 독립 하네스 + Opus 5, C 독립 하네스 + gpt-5. A−B가 하네스 효과, B−C가 모델 효과. 두 시스템의 도구 호출은 능력 어휘(vault 읽기·쓰기·삭제, autopilot 시작·설정·정지·상태)로 정규화해 같은 규칙으로 채점(agent/evals/capabilities.py).
  • 개발 12사례로 규칙을 다듬고, held-out 12사례는 sha256으로 고정해 결론에는 held-out만 쓴다. 결과를 본 뒤 규칙을 고치지 않는다.
  • 지표 — pass@1(사례 단위 부트스트랩 95% 구간)·pass^k(k회 전부 통과한 사례 비율)·체크 통과율·안전 시도(금지 도구 호출)·침해(불변 파일 변경)·토큰 종류별 사용량·공개 단가 비용·소요.
  • 노트 — 스킬 모드는 워커 트랜스크립트의 저장 당시 원문·사용량(재실행 없음), 독립 런타임은 그 논문 ingest 직전으로 되돌린 복사본에서 한 반복. 결정론 지표(분석 절 수치 ↔ 원문 40쪽 텍스트, 끊긴 링크, vault 논문 링크) + 제3 제공자 모델(gemini-2.5-pro)의 블라인드 쌍대 판정(순서 교차, 두 답이 같을 때만 승) + 주장 감사.
  • 지표 검증 — 잡힌 수치·주장은 사람이 원문에서 확인한다. 2026-09-14 확인: "원문에 없는 수치" 9건 전부 반올림·표기 차이(환각 0) → 이 지표는 값이 아니라 표기를 비교한다는 한계가 있다(값 비교로 수정 예정).

실측 (held-out, 2026-09-12 · 09-14)

축 5사례 × 1회 12사례 × 5회 사례당 비용
A 스킬 모드 · Opus 5 5/5 — $0.51
B 독립 · Opus 5 5/5 — $0.40 (프롬프트 캐시 없음)
C 독립 · gpt-5 3/5 pass@1 0.78 (0.60~0.93) · pass^5 0.58 · 안전 시도 0 · 침해 0 $0.05

노트 5편(스킬 모드 대 gpt-5 독립): 판정 종합 스킬 3 · gpt-5 1 · 불일치 1, 원문 충실성 4편 동률. 편당 비용 스킬 $2.32~4.24(트랜스크립트 환산) · gpt-5 $0.66~0.84. gpt-5 반복 실행의 실패는 세 패턴 — 텍스트로 저장 허락 구하기, 같은 이름 노트 둘 중 되묻기, 제어 노트를 끝까지 읽지 않기.

uv run python -m agent.evals intents --model openai:gpt-5 --workdir /tmp/intent-evals
uv run python -m agent.evals notes --arxiv 2411.00816 --reference cycleresearcher --model openai:gpt-5 --workdir /tmp/note-eval
# 교차 비교 — 같은 사례·같은 채점 규칙으로 스킬 모드(Claude Code)와 독립 하네스
uv run python -m agent.evals intents --cross --split holdout --repeat 3 --model openai:gpt-5 --arm C --workdir /tmp/x/C
uv run python -m agent.evals intents --system claude-code --split holdout --model claude-opus-5 --arm A --budget-usd 3 --workdir /tmp/x/A
uv run python -m agent.evals summary /tmp/x/A/results.jsonl /tmp/x/C/results.jsonl
uv run python -m agent.evals notes-cross --papers kosmos,paperqa2 --models openai:gpt-5 --workdir /tmp/x/notes
uv run python -m agent.evals judge --papers kosmos,paperqa2 --arms skill,openai_gpt-5 --workdir /tmp/x/notes
  • intents — 실제 발화 사례(agent/evals/intent_cases.json)를 넣고 부른 도구·승인 요청·확인 질문·최종 응답을 채점한다. 승인 요청에서 멈춘다(쓰기 전에 묻는지 본다).
  • --cross — 승인 요청을 거부로 답하고 계속하며(헤드리스 Claude Code dontAsk와 같은 조건), 두 시스템의 도구 호출을 능력 단위(vault 읽기·쓰기·삭제, autopilot 시작·설정·정지·보고 등)로 맞춰 채점한다. --split holdout은 튜닝에 쓰지 않은 사례(intent_cases_holdout.json), --repeat는 사례당 반복 수.
  • --system claude-code — 저장소 스킬 사본을 플러그인으로, vault 복사본을 작업 폴더로 claude -p를 돌린다. 읽기 도구만 허용하고 나머지는 거부, ANTHROPIC_API_KEY 필요, 실행마다 --budget-usd 상한.
  • summary — 팔·분할별 pass@1(사례 단위 부트스트랩 95% 구간)·pass^k·안전 시도·안전 침해·토큰·비용.
  • notes-cross — 스킬 모드 노트는 autopilot 워커 트랜스크립트의 저장 당시 원문·사용량으로, 독립 런타임 노트는 그 논문 ingest 직전으로 되돌린 복사본에서 한 반복으로 만들어 원문에 없는 수치·끊긴 링크·vault 논문 링크를 잰다.
  • judge — 판정 모델(기본 google:gemini-2.5-pro)이 노트 쌍을 순서를 바꿔 두 번 비교하고(두 답이 같을 때만 승), 노트마다 원문으로 뒷받침되지 않는 주장을 모은다.
  • notes — 같은 논문의 기준 노트(스킬 모드)와 독립 런타임 노트를 분석 절 분량·링크한 vault 논문·굵은 머리 항목으로 나란히 본다.
  • 원본 vault는 읽기만 한다 — 사례마다 PDF 캐시를 뺀 복사본에서 돈다. 결과는 key=value 줄과 results.jsonl. 모델 호출 비용은 사용자 몫.

Vault 레이아웃

vault/
├── papers/
│   └── <title-slug>/
│       ├── <title-slug>.md  # frontmatter + 본문 (TL;DR / Methods / Findings / References)
│       └── figures/
│           └── fig_<n>_<caption-slug>.png
├── topics/
│   └── <hub-slug>.md        # 안정 hub — 백링크로 논문이 자동 집계
├── notes/
│   └── <slug>.md            # 논문 간 종합 통찰 (insight-capture)
├── tech-blog-digest/
│   └── <date>.md            # 테크 블로그 다이제스트 노트
├── research-autopilot/
│   └── <date>.md            # autopilot 실행 보고서 (정지 시 생성)
├── graphs/
│   └── <slug>.md            # 인용 흐름 Mermaid 노트 (build_citation_graph)
└── pdfs/
    └── <arxiv_id>.pdf

papers/<title-slug>/<title-slug>.md frontmatter 예:

arxiv_id: 2301.12597
title: "BLIP-2: Bootstrapping Language-Image Pre-training with Frozen Image Encoders"
year: 2023
citation_count: 1234
citation_velocity: 411.3
topics: [vlm, multimodal]
references:
  - paper_id: 2103.00020
    topic: clip-contrastive
    cited_for: "BLIP-2의 frozen 이미지 인코더 초기화 근거로 인용"
figures:
  - file: figures/fig_1_overview.png
    caption: "Figure 1: BLIP-2 architecture overview."

기술 스택

영역 선택
MCP 서버 FastMCP (stdio)
에이전트 Pydantic-AI — multi-provider (Anthropic / OpenAI / Google)
백엔드 FastAPI + SSE (스트리밍)
프론트 Next.js 16 · React 19 · Tailwind CSS v4
추출 PyMuPDF (PDF) + Gemini Vision (figure/table bbox)
저장 Obsidian vault (Markdown), SQLite (대화 세션)
데이터 arXiv · Semantic Scholar · 테크 블로그
캐시 디스크 캐시 — 동일 paper_id 재요청은 0 네트워크

사용 예시

> BLIP-2 위키에 추가해줘
→ paper-ingest → papers/blip-2/ 생성, figure·table 추출·선별, 요약 + hub 매핑

> BLIP-2 흐름 보여줘
→ citation-analysis → refs/cites를 hub로 분류 + cited_for 채움
  → 사용자 승인 게이트 → vault 누적 + Mermaid 시각화(`graphs/` 노트) → Obsidian 그래프로 확인

> 오늘 트렌딩 논문 정리해줘
→ tech-blog-digest → tech-blog-digest/<date>.md 저장

라이선스

개인용 프로젝트.