리서치 볼트: 오픈 소스 에이전틱 AI 연구 어시스턴트
Source: Dev.to
위에 제공된 텍스트를 한국어로 번역해 주세요. (번역할 실제 내용이 필요합니다.)
아무도 말하지 않는 문제
나는 연구 논문에 빠져 있었어요. 은유적인 것이 아니라—50개 이상의 PDF, 수십 개의 기사, 그리고 전담 업무가 된 필기 시스템을 가지고 있었습니다.
- 에이전트 메모리 제한에 관한 중요한 내용을 읽었지만, 어느 논문인지 잊어버려 PDF를 한 시간 동안 검색해야 했습니다.
- 서로 상충되는 내용을 말하는 세 개의 출처를 찾았지만, 이를 체계적으로 비교할 방법이 없었습니다.
기존 도구들은 이를 해결하지 못했습니다.
- 필기 앱은 수동적인 정리를 요구합니다.
- NotebookLM 같은 도구는 Q&A에는 뛰어나지만, 나중에 조회할 수 있는 구조화된 패턴을 추출하지는 못합니다.
- 전통적인 RAG 시스템은 텍스트를 청크로 나누어 검색할 뿐이며, 출처 간에 통합하지 못합니다.
The blind spot: 우리는 연구 소비를 읽기 문제로만 생각합니다. 그렇지 않습니다. 이것은 knowledge‑architecture 문제입니다.
내가 만든 것
Research Vault는 비정형 논문을 쿼리 가능한 지식 베이스로 변환하는 에이전시 AI 연구 보조 도구입니다.
- 논문을 업로드하면 Claim → Evidence → Context 스키마를 사용해 구조화된 패턴을 추출합니다.
- 패턴을 의미적으로 임베딩합니다.
- 자연어로 전체 라이브러리를 넘나들며 쿼리할 수 있게 합니다.
접근 방식: 텍스트를 단순히 청크로 나누는 대신 구조화된 발견(Claim → Evidence → Context)을 추출합니다. 새로운 아이디어는 아니지만, 테스트와 오류 처리를 잘 구현한 점이 돋보입니다.
Note: 이것은 제가 개인적으로 사용하는 보다 전문화된 연구 보조 도구의 단순화된 일반 버전입니다. 복잡성을 제거하고 핵심인 구조화된 추출 + 하이브리드 검색 + 자연어 쿼리만 남겼습니다.
아키텍처 스택
| 레이어 | 기술 | 이유 |
|---|---|---|
| 오케스트레이션 | LangGraph 1.0 | 사이클이 있는 상태 저장 워크플로우 |
| LLM | Claude (Anthropic) | 추출 + 합성 |
| 임베딩 | OpenAI text-embedding-3-small | 시맨틱 검색 |
| 벡터 DB | Qdrant | 로컬‑우선, 프로덕션 준비 |
| 백엔드 | FastAPI + SQLAlchemy | 전반적으로 비동기 |
| 프론트엔드 | Next.js 16 + React 19 | 현대적이며 타입‑안전 |
표시되지 않음: 641개의 백엔드 테스트, 23개의 프론트엔드 테스트, 포괄적인 문서, Docker 배포, CI/CD 파이프라인.
추출 아키텍처
많은 RAG 시스템은 문서를 청크로 나눕니다. 일부는 구조화된 추출을 수행합니다. Research Vault는 3‑패스 파이프라인을 사용하는 구조화된 접근 방식을 따릅니다:
Pass 1: Evidence Inventory (Haiku)
- 논문에서 구체적인 주장, 데이터, 예시를 스캔합니다.
- 이후 모든 내용이 실제 논문 내용에 기반하도록 합니다.
Pass 2: Pattern Extraction (Sonnet)
[E#]표기법을 사용하여 증거를 인용하는 패턴을 추출합니다.- 각 패턴은 여러 증거 항목을 인용할 수 있습니다.
- 1:1 매핑이 아니라, 패턴은 증거들을 종합하여 생성됩니다.
- 분류를 위해 태그를 지정합니다.
Pass 3: Verification (Haiku)
- 인용이 정확한지 확인합니다.
- 패턴이 논문 내용에 근거하고 있는지 검증합니다.
- 최종 상태를 계산합니다.
왜 세 번의 패스가 필요한가?
- 증거 앵커링은 환상을 줄여줍니다.
- 검증 단계는 추출 오류를 잡아냅니다.
- 구조화된 스키마는 문서 간 쿼리를 가능하게 합니다.
패턴 스키마
전통적인 RAG:
"Context window overflow causes..."
— 단순 텍스트 청크.
Research Vault 패턴:
{
"name": "Context Overflow Collapse",
"claim": "When context windows fill, agents compress state...",
"evidence": "[E3] 'Performance degraded sharply after 15 reasoning steps' (Table 2)",
"context": "Authors suggest explicit state architecture, not larger windows.",
"tags": ["state-management", "failure-mode"],
"paper_id": "uuid-of-paper"
}
이 구조는 다음과 같은 질의를 가능하게 합니다:
- “저자들이 에이전트 메모리에 대해 의견이 다른 부분은 어디인가?”
- “멀티‑에이전트 시스템 전반에 걸쳐 반복되는 패턴은 무엇인가?”
- “도구 사용에 대해 내가 배운 것을 종합해라.”
내가 이것을 만들면서 배운 점
교훈 1: 워크플로우를 테스트하라, 구성 요소만이 아니라
- 초기 단위 테스트는 뛰어난 커버리지를 제공했지만, 전체 파이프라인은 미묘한 방식으로 계속 깨졌습니다.
- 해결: 외부 서비스(LLM, 임베딩, Qdrant)를 모킹한 채 전체 워크플로우를 엔드‑투‑엔드로 실행하는 통합 테스트. 실제 버그의 약 90 %를 잡아냈습니다.
- 교훈: 오케스트레이션된 시스템에서는 구성 요소 테스트가 필수이지만 충분하지 않습니다. 실패 모드는 구성 요소 사이의 간극에서 나타납니다.
교훈 2: 코딩 전에 문서화하기
구현 코드를 한 줄도 작성하기 전에 여섯 개의 포괄적인 문서 파일을 작성했습니다:
REQUIREMENTS.mdDOMAIN_MODEL.mdAPI_SPEC.mdARCHITECTURE.mdOPERATIONS.mdPLAN.md
왜 중요한가:
- 설계 모순을 초기에 발견했습니다.
- 구현이 명확해졌습니다(모호함이 없음).
- 프론트엔드와 백엔드 작업을 병렬로 진행할 수 있었습니다.
- 기여자를 위한 온보딩 경로를 만들었습니다.
교훈: 사양‑주도 개발은 느린 것이 아니라, 잘못된 것을 만들지 않기 때문에 더 빠릅니다.
교훈 3: LLM은 JSON에 대해 거짓말을 한다
이 코드베이스의 모든 LLM 응답 파서는 방어적인 파싱을 사용합니다, 예시:
# verification.py
status_str = response.get("verification_status", "pass")
try:
status = VerificationStatus(status_str)
except ValueError:
status = VerificationStatus.passed # Fallback
LLM이 자주 하는 일:
- 유효한 JSON 뒤에 주석을 추가한다(“Here are my observations…”)
- 스키마에 없는 필드를 만들어낸다
- 열거형 대신 문자열을 반환한다
- 객체 중간에서 출력을 잘라낸다
해결: 방어적으로 파싱하고, 스키마에 대해 검증하며, 안전한 기본값으로 폴백합니다.
교훈 4: 로컬‑우선은 기능이다
LLM API 호출을 제외하고 완전히 로컬에서 실행하는 것은 처음에 MVP를 위한 단순화였지만, 곧 차별화 포인트가 되었습니다.
사용자가 원하는 것
- 연구 데이터에 대한 클라우드 의존성 없기
- 오프라인(대부분) 작업 가능
- 구독에 얽매이지 않기
- 데이터 완전 소유권
교훈: 제한적으로 보였던 제약이 차별화 요소가 될 수 있습니다.
아무도 보여주지 않는 프로덕션 현실
실제로 작동하는 테스트 피라미드
43 Integration Tests (full pipeline)
├─ 641 Backend Unit Tests (services, workflows, API)
└─ 23 Frontend Tests (components, hooks)
왜 이런 배분인가
- 통합 테스트는 워크플로우 중단을 잡아냅니다
- 단위 테스트는 논리 오류를 잡아냅니다
- 프론트엔드 테스트는 UI 회귀를 잡아냅니다
실제로 도움이 되는 문서
대부분의 프로젝트는 README만 가지고 끝냅니다. Research Vault는 다음을 제공합니다:
- 사용자 가이드 (
GETTING_STARTED.md) – “이걸 어떻게 쓰나요?” - 운영 가이드 (
OPERATIONS.md) – “배포/문제 해결은 어떻게 하나요?” - 아키텍처 가이드 (
ARCHITECTURE.md) – “어떻게 동작하나요?” - 도메인 모델 (
DOMAIN_MODEL.md) – “엔티티는 무엇인가요?” - API 사양 (
API_SPEC.md) – “엔드포인트는 무엇인가요?”
각 문서는 서로 다른 대상과 질문에 답합니다.
아무도 보지 못하는 오류 처리
우아한 감소가 내장되어 있습니다:
- LLM 추출 실패 → 부분 성공 (문서는 저장되고, 패턴은 재시도)
- 임베딩 생성 실패 → 우아한 감소 (패턴은 저장되고, 임베딩은 재시도)
- Qdrant 연결 실패 → 관계형 데이터만 사용해 계속 진행
- 쿼리 중 컨텍스트 초과 → 경고와 함께 우아하게 잘라냄
교훈: 프로덕션‑레디란 1가지 작동 방식이 아니라 20가지 실패 방식을 처리하는 것을 의미합니다.
Source: …
왜 오픈 소스인가
나는 이것을 나 자신을 위해 만들었다. 연구 혼란을 해결해 주었다. 기술 자체가 새롭지는 않다—구조화된 추출, 하이브리드 스토리지, 다중 패스 검증은 다른 RAG 시스템에서도 이미 존재한다.
OSS(오픈 소스)로 만들기
- 내가 프로덕션 시스템에 접근하는 방식을 보여준다
- 같은 문제를 겪는 다른 사람들에게 도움이 될 수 있다
- 아키텍처 결정에 대한 피드백을 초대한다
- 기여 기회를 연다
이 프로젝트가 보여주는 것
- 에이전시 워크플로우를 테스트하는 방법 (641개의 테스트)
- 오류를 우아하게 처리하는 방법 (부분 성공, 재시도)
- 다양한 청중을 위한 문서화 방법 (6개의 문서)
- 단순 프로토타입이 아니라 실제 배포 방법
중요한 건축 선택
| 결정 | 대안 | 왜 이 선택이 승리했는가 |
|---|---|---|
| 구조화된 추출 | 텍스트 청킹 | 논문 간 종합을 가능하게 함 |
| 3‑단계 검증 | 단일 단계 추출 | 환각을 90 % 감소시킴 |
| 주장/증거/맥락 | SRAL 구성 요소 | 일반적이며 광범위하게 적용 가능 |
| 전반적인 비동기 | 동기 + 스레딩 | 코드가 더 깔끔하고 자원 사용 효율 향상 |
| SQLite → Postgres 경로 | 처음부터 Postgres | 로컬 설정이 간단하고 마이그레이션이 명확함 |
| 로컬 우선 | 클라우드 네이티브 | 데이터 소유권 보장, 벤더 종속 없음 |
| FastAPI + Next.js | Streamlit/Gradio | 분리되어 있으며 프로덕션 준비 완료 |
모든 선택은 다음을 최적화했습니다: 기능보다 신뢰성, 영리함보다 명확성, 도구보다 아키텍처.
다음 단계
Research Vault은 베타 준비가 완료되었습니다. 핵심 워크플로우—업로드, 추출, 검토, 쿼리—는 안정적으로 작동합니다. 하지만 구축할 것이 더 있습니다:
단기
- 패턴 관계 감지 (충돌, 합의)
- 다중 문서 종합 보고서
- Obsidian/Notion으로 내보내기
장기
- 다중 사용자 지원
- 클라우드 배포 옵션
- 로컬 LLM 지원 (완전 오프라인)
- 시간에 따른 패턴 진화
하지만 먼저: 다른 사람들의 손에 넘겨 보세요. 무엇이 깨지는지 확인하고, 무엇이 중요한지 배우세요.
사용해 보기
레포가 라이브 상태입니다:
시작하기 (≈5 분)
git clone https://github.com/aakashsharan/research-vault.git
cd research-vault
cp .env.example .env # Add your API keys
docker compose up --build
앱을 열고 첫 번째 논문을 업로드하세요.
요약
RAG 시스템이 존재합니다. 구조화된 추출이 존재합니다. LangGraph 프로젝트가 존재합니다.
중요한 것은 실행입니다: 테스트되고, 문서화되며, 오류를 처리하고, 실제로 작동합니다.
- 이것은 혁신적인 것이 아닙니다. 단지 잘 만들어졌을 뿐입니다.
- 도구는 변하지만, 실행이 중요합니다.
작동하는 것을 배포하세요. 배운 것을 문서화하세요. 도움이 되는 것을 공유하세요.
관련 읽을거리
- SRAL Framework Paper – (에이전트형 AI를 위한 평가 프레임워크)
- SRAL Github –
- Architecture Documentation –
- API Specification –