Back to .md Directory

arXiv Knowledge Base — Specification

Defines a complete arXiv paper ingestion pipeline with hierarchical chunking, entity extraction, vector search, REST API, and Claude MCP integration.

May 2, 2026
0 downloads
2 views
ai rag mcp claude
View source

What this file does

Defines a complete arXiv paper ingestion pipeline with hierarchical chunking, entity extraction, vector search, REST API, and Claude MCP integration.

When to use it

  • Building a searchable knowledge base from arXiv papers
  • Need structured extraction of models, benchmarks, and metrics from PDFs
  • Want to serve paper data via FastAPI and Claude MCP tools
  • Migrating from flat chunks to enriched hierarchical chunks

Assumes this stack

Python >=3.10FastAPILanceDBSQLite + FTS5DoclingSentence-Transformers

arXiv Knowledge Base — Specification

Version: 0.1.0 Last updated: 2026-01-31 Python: >=3.10


Current Status

MetricValue
Total Papers9,500
Legacy Chunks (v1)12,443
Enriched Chunks (v2)1,035
Extraction: completed4,612
Extraction: pending4,886
Extraction: failed2
Embedding: completed185
Embedding: pending9,315
V2 Chunks by levelsummary: 407, section: 628
V2 Contribution typescore: 664, comparison: 134, citation: 237
V2 Key results97
V2 Embedding statuscompleted: 966, pending: 69

Top categories: cs.LG (2,791), cs.CL (1,655), cs.AI (1,242), cs.CV (1,107), cs.CR (305), stat.ML (224)


Architecture

arxiv_data/
├── config/
│   └── settings.py              # Pydantic Settings (env: ARXIV_KB_*)
├── src/
│   ├── cli.py                   # Typer CLI
│   ├── api/main.py              # FastAPI REST endpoints
│   ├── mcp/server.py            # FastMCP server for Claude
│   ├── collectors/
│   │   └── arxiv_fetcher.py     # arXiv API + PDF downloads
│   ├── extractors/
│   │   ├── pdf_extractor.py     # Docling PDF→Markdown + chunking
│   │   └── entity_extractor.py  # Hybrid entity extraction
│   ├── embedders/
│   │   └── embedder.py          # Sentence-transformers embeddings
│   └── storage/
│       ├── database.py          # SQLite (metadata + FTS5 + chunks)
│       └── vector_store.py      # LanceDB (vector search)
├── scripts/
│   └── migrate_to_v2.py         # v1→v2 migration tool
└── data/
    ├── arxiv.db                 # SQLite (82.8 MB)
    ├── lancedb/                 # Vector database
    ├── pdfs/{YYYY-MM}/          # Downloaded PDFs
    └── markdown/{YYYY-MM}/      # Extracted markdown + JSON metadata

Stack

ComponentTechnology
Collectionarxiv (pip) — official wrapper, rate-limiting
PDF ExtractionDocling (IBM) — GPU-accelerated, Markdown output
Metadata DBSQLite + FTS5 — full-text search on titles/abstracts
Vector DBLanceDB — serverless, cosine metric, IVF index
EmbeddingsQwen3-Embedding-0.6B (configurable, 1024-dim)
REST APIFastAPI
MCP ServerFastMCP — Claude integration
CLITyper + Rich
ConfigPydantic Settings (env prefix: ARXIV_KB_)

Configuration

Path Settings

SettingDefault
data_dir{base_dir}/data
pdf_dir{data_dir}/pdfs
markdown_dir{data_dir}/markdown
sqlite_path{data_dir}/arxiv.db
lancedb_path{data_dir}/lancedb

arXiv Settings

SettingDefault
arxiv_categories["cs.LG", "cs.CL", "cs.AI", "stat.ML"]
arxiv_delay_seconds3.0
arxiv_page_size500
arxiv_num_retries5

Embedding Settings

SettingDefault
embedding_modelQwen/Qwen3-Embedding-0.6B
embedding_dimension1024
embedding_batch_size32

Chunking Settings (v1 — Legacy)

SettingDefault
chunk_size1024 tokens
chunk_overlap100 tokens
min_chunk_size100 tokens

Hierarchical Chunking Settings (v2)

SettingDefault
enable_hierarchical_chunkingTrue
summary_chunk_max_tokens512
section_chunk_max_tokens1024
atomic_chunk_max_tokens256
atomic_chunk_min_tokens50

Entity Extraction Settings

SettingDefault
enable_entity_extractionTrue
use_llm_for_classificationFalse
entity_extraction_llmQwen/Qwen2.5-3B-Instruct
extract_atomic_factsTrue

API & Scheduler

SettingDefault
api_host0.0.0.0
api_port8000
sync_hour6
sync_minute0

Database Schema

papers

ColumnTypeDescription
idTEXT PKarXiv ID (e.g. 2401.12345)
titleTEXT NOT NULL
abstractTEXT
authorsTEXTJSON array
categoriesTEXTJSON array
primary_categoryTEXT
published_dateTEXTISO format
updated_dateTEXTISO format
doiTEXT
journal_refTEXT
pdf_urlTEXT
pdf_pathTEXTLocal path
markdown_pathTEXTLocal path
extraction_statusTEXTpending / completed / failed
embedding_statusTEXTpending / completed / failed
versionINTEGERPaper version number
created_atTEXT
updated_atTEXT

Indexes: published_date, primary_category, extraction_status, embedding_status FTS5: Virtual table on id, title, abstract, authors with auto-sync triggers

chunks (v1 — Legacy)

ColumnTypeDescription
idINTEGER PK AUTO
paper_idTEXT FK→ papers.id
chunk_indexINTEGERPosition in sequence
chunk_typeTEXTabstract, introduction, methodology, results, etc.
contentTEXT NOT NULL
token_countINTEGER
embedding_idTEXTVector store reference

chunks_v2 (Enriched — Hierarchical)

ColumnTypeDescription
idTEXT PK{paper_id}_{chunk_level}_{index}
paper_idTEXT FK→ papers.id
chunk_levelTEXT NOT NULLsummary / section / atomic
section_typeTEXTabstract, introduction, methodology, results, etc.
contentTEXT NOT NULL
token_countINTEGER
techniquesTEXTJSON array: ["MoE", "attention"]
models_mentionedTEXTJSON array: ["BERT", "GPT-4"]
benchmarksTEXTJSON array: ["GLUE", "MMLU"]
metricsTEXTJSON object: {"accuracy": 85.3}
contribution_typeTEXTcore / comparison / baseline / citation
is_key_resultBOOLEAN
embedding_statusTEXTpending / completed / failed
embedding_idTEXT
created_atTEXT
updated_atTEXT

Indexes: paper_id, chunk_level, contribution_type, is_key_result, embedding_status

sync_state

Single-row table tracking last sync date, last paper ID, papers fetched count, and status (idle/in_progress/completed/failed).


Vector Store (LanceDB)

paper_chunks (v1 — Legacy)

FieldType
idstr ({paper_id}_{chunk_index})
paper_idstr
chunk_indexint
chunk_typestr
contentstr
titlestr
authorsstr
primary_categorystr
published_datestr
vectorVector(1024)

enriched_paper_chunks (v2)

FieldType
idstr ({paper_id}_{chunk_level}_{index})
paper_idstr
chunk_levelstr
section_typestr
contentstr
titlestr
authorsstr
primary_categorystr
published_datestr
techniquesstr (JSON)
models_mentionedstr (JSON)
benchmarksstr (JSON)
metricsstr (JSON)
contribution_typestr
is_key_resultbool
vectorVector(1024)

Index config: Cosine metric, 256 partitions, 96 sub-vectors (IVF)


Data Pipeline

1. SYNC (arxiv_fetcher.py)
   arXiv API → papers table + PDFs to data/pdfs/{YYYY-MM}/
   Status: extraction_status = "pending"

2. EXTRACT (pdf_extractor.py)
   PDF → Docling → Markdown → Sections → Chunks
   Saves: data/markdown/{YYYY-MM}/{id}.md + {id}.json
   v1: chunks table (flat)
   v2: chunks_v2 table (hierarchical + entities)
   Status: extraction_status = "completed"

3. EMBED (embedder.py)
   Chunks → Qwen3-Embedding-0.6B → LanceDB
   v1: paper_chunks table
   v2: enriched_paper_chunks table
   Status: embedding_status = "completed"

4. SEARCH
   Query → Embed → Vector similarity + metadata filters → Results

Hierarchical Chunking Strategy (v2)

Level 1: Summary (1 per paper)

  • Abstract + first paragraph of introduction
  • Entities extracted from abstract
  • Always classified as core contribution
  • Used for overview/discovery queries

Level 2: Section (variable per paper)

  • Split by semantic boundaries (tables, figures, subsections, bold headers)
  • Each section chunk gets independent entity extraction
  • Contribution type classified per chunk
  • Results sections split by experiment/benchmark
  • Methodology sections split by component/step

Level 3: Atomic (variable per paper)

  • Fine-grained facts: "DeltaNet achieves 85.3% on GLUE"
  • Only generated from results/methodology sections
  • Only when entities (models, benchmarks, metrics) are present
  • Each fact links model + benchmark + metric

Entity Extraction

Approach: Hybrid (Rules + Patterns + Optional LLM)

  1. Known entities — curated lists matched via compiled regex:

    • 100+ benchmarks (GLUE, ImageNet, MMLU, ...)
    • 150+ models (BERT, GPT-4, LLaMA, ...)
    • 100+ techniques (attention, MoE, LoRA, ...)
  2. Metrics — regex patterns for 20+ metric types:

    • accuracy, F1, BLEU, ROUGE, perplexity, mAP, WER, FLOPs, etc.
  3. Contribution classification — rule-based (optional LLM):

    • core: "we propose", "our method", "novel", methodology sections
    • comparison: "compared to", "outperforms", "baseline"
    • baseline: baseline references
    • citation: related work, default
  4. Key result detection:

    • "state-of-the-art", "SOTA", "new record"
    • Chunks with metrics + core/comparison type

CLI Commands

CommandDescription
arxiv-kb sync [--days N] [--incremental]Fetch papers from arXiv
arxiv-kb extract [PAPER_ID] [--all] [--limit N]Extract text from PDFs
arxiv-kb embed [PAPER_ID] [--all] [--limit N]Generate embeddings
arxiv-kb search QUERY [--fulltext] [--cat CS.LG]Search papers
arxiv-kb statsShow database statistics
arxiv-kb paper PAPER_IDShow paper details
arxiv-kb serve [--port 8000]Start FastAPI server
arxiv-kb mcpStart MCP server
arxiv-kb pipeline [--days 7] [--limit 100]Full sync→extract→embed

REST API Endpoints

Search

MethodPathDescription
POST/searchSemantic search (query, categories, date range, limit)
POST/search/hybridHybrid semantic + FTS (vector_weight: 0-1)
GET/search/fulltext?query=...Full-text search on titles/abstracts

Papers

MethodPathDescription
GET/papers/{id}Paper metadata
GET/papers/{id}/chunksAll text chunks
GET/papers/{id}/markdownExtracted markdown text
GET/papers/{id}/pdfDownload PDF file
GET/papers/{id}/similar?limit=10Find similar papers
POST/papers/filterFilter by categories, authors, dates

Browse

MethodPathDescription
GET/recent?days=7&categories=cs.LGRecent papers
GET/authors/{name}Papers by author

Metadata

MethodPathDescription
GET/API info
GET/healthHealth check
GET/statsDatabase statistics

MCP Tools (Claude Integration)

Legacy Tools (v1)

ToolArgsDescription
search_papersquery, categories?, limitSemantic search
get_paper_detailspaper_id, include_full_text?Paper metadata + optional text
find_similar_paperspaper_id, limitSimilar papers
search_by_authorauthor_name, limitPapers by author
get_recent_papersdays, categories?, limitRecent papers
fulltext_searchquery, limitKeyword-based search
get_paper_chunkspaper_idAll chunks for a paper
get_knowledge_base_statsDB statistics

Enriched Tools (v2)

ToolArgsDescription
search_model_resultsmodel_name, benchmark?, include_baselinesFind benchmark results for a model
find_innovationstopic, techniques?, days, limitCore contributions on a topic
compare_modelsmodels (comma-sep), benchmark?Compare model performance
search_by_techniquetechnique, contribution_type, limitPapers by technique
get_key_resultsquery, limitSOTA / significant results
get_paper_entitiespaper_idAggregated entities for a paper
advanced_searchquery, models?, benchmarks?, techniques?, contribution_type?, chunk_level?Multi-filter search

Migration (v1 → v2)

python scripts/migrate_to_v2.py status           # Check progress
python scripts/migrate_to_v2.py init              # Create v2 tables
python scripts/migrate_to_v2.py migrate           # Migrate all papers
python scripts/migrate_to_v2.py migrate --limit 100
python scripts/migrate_to_v2.py migrate --paper-id 2401.12345
python scripts/migrate_to_v2.py migrate --no-skip # Re-migrate existing

The migration re-reads existing markdown files (no re-extraction needed), applies hierarchical chunking + entity extraction, generates new embeddings, and stores in both SQLite chunks_v2 and LanceDB enriched_paper_chunks.


Dependencies

[project]
dependencies = [
    "arxiv>=2.1.0",
    "httpx>=0.27.0",
    "aiofiles>=24.1.0",
    "marker-pdf>=1.0.0",
    "lancedb>=0.10.0",
    "sentence-transformers>=3.0.0",
    "fastapi>=0.115.0",
    "uvicorn>=0.30.0",
    "fastmcp>=0.3.0",
    "apscheduler>=3.10.0",
    "typer>=0.12.0",
    "rich>=13.0.0",
    "pydantic-settings>=2.0.0",
    "python-dotenv>=1.0.0",
]

File Storage Layout

data/
├── arxiv.db                          # SQLite (82.8 MB)
│   ├── papers (9,500 rows)
│   ├── chunks (12,443 rows)
│   ├── chunks_v2 (1,035 rows)
│   ├── papers_fts (FTS5 index)
│   └── sync_state (1 row)
├── lancedb/
│   ├── paper_chunks/                 # v1 embeddings (521 vectors)
│   └── enriched_paper_chunks/        # v2 embeddings (966 vectors)
├── pdfs/{YYYY-MM}/{paper_id}.pdf     # Original PDFs
└── markdown/{YYYY-MM}/
    ├── {paper_id}.md                 # Extracted text
    └── {paper_id}.json               # Section metadata

What's inside

12 sections covering architecture, stack, config, schema, pipeline, CLI, REST API, MCP tools, migration, and dependencies

Change this for your project

  • Replace Qwen/Qwen3-Embedding-0.6B with your embedding model
  • Replace Qwen/Qwen2.5-3B-Instruct with your LLM for entity classification
  • Replace arxiv_data in paths and module names with your project name
  • Replace cs.LG, cs.CL, cs.AI, stat.ML with your target arXiv categories

Where it goes

Keep in docs/ or alongside the feature. Agents read it to implement against a defined contract.

Worth borrowing

  • Hierarchical chunking (summary, section, atomic) with entity extraction per level
  • Hybrid entity extraction using regex for known entities and optional LLM for classification
  • Dual storage: SQLite for metadata and FTS, LanceDB for vector search

Related Documents