agentic-rag / docs /Dataset Field Mapping.md
vksepm
Checkpoint
de262f8
|
Raw
History Blame Contribute Delete
12 kB

Dataset β†’ Database Field Mapping

Maps every field from the HuggingFace dataset jamescalam/ai-arxiv2-chunks to its destination in the PostgreSQL schema.


Quick Reference

HF Dataset Field Type β†’ DB Table DB Column Transform
doi string β†’ documents arxiv_id direct copy
id string β†’ documents arxiv_id fallback if doi absent
title string β†’ documents title direct copy
doi + title string β†’ documents full_citation computed: "{title}. arXiv:{doi}"
doi string β†’ documents source_url computed: "https://arxiv.org/abs/{doi}"
source string β†’ documents metadata["source"] stored in JSONB
source string β†’ chunks metadata["source"] stored in JSONB
chunk string β†’ chunks content direct copy
chunk-id int64 ⚠️ chunks chunk_index field name mismatch β€” always 0
(computed) float[384] β†’ chunks embedding encoded locally via all-MiniLM-L6-v2
summary string βœ— β€” β€” not stored
authors string βœ— β€” β€” not stored
categories string βœ— β€” β€” not stored
primary_category string βœ— β€” β€” not stored
published string βœ— β€” β€” not stored
updated string βœ— β€” β€” not stored
comment string? βœ— β€” β€” not stored
journal_ref string? βœ— β€” β€” not stored
references list βœ— β€” β€” not stored

Detailed Mapping

documents table

DB Column HF Field(s) Ingest Code Example
id β€” gen_random_uuid() auto-generated 235692e6-67ae-...
arxiv_id doi (primary), id (fallback) row.get("doi", row.get("arxiv_id", uuid4())) 2401.09350
title title row.get("title") Foundations of Vector Retrieval
source_url derived from doi f"https://arxiv.org/abs/{doi}" https://arxiv.org/abs/2401.09350
full_citation title + doi f"{title}. arXiv:{doi}" Foundations of Vector Retrieval. arXiv:2401.09350
metadata source {"source": row.get("source", "")} {"source": "http://arxiv.org/pdf/2401.09350"}
created_at β€” NOW() (DB default) 2026-03-20T15:04:19Z

Note on source_url: The dataset's source field contains the PDF URL (http://arxiv.org/pdf/...). The ingest script ignores this and instead constructs an abstract URL (https://arxiv.org/abs/...) from doi. The raw PDF URL is preserved only inside metadata["source"].


chunks table

DB Column HF Field(s) Ingest Code Example
id β€” gen_random_uuid() auto-generated a1b2c3d4-...
document_id β€” FK from documents.id upsert 235692e6-...
content chunk (primary), text (fallback) row.get("chunk", row.get("text", "")) "Sebastian Bruch # Foundations of Vector Retrieval..."
embedding β€” SentenceTransformer.encode(content) [0.012, -0.034, ..., 0.091] (384 floats)
chunk_index ⚠️ chunk-id row.get("chunk_index", 0) Always 0 β€” see bug below
metadata source {"source": row.get("source", "")} {"source": "http://arxiv.org/pdf/2401.09350"}

Known Issues

⚠️ Bug 1 β€” chunk_index always 0 (field name mismatch)

Root cause: The HuggingFace dataset names the field chunk-id (with a hyphen), but the ingest script looks up chunk_index (with an underscore):

# ingest_data.py line 178 β€” CURRENT (broken)
chunk_index = row.get("chunk_index", 0)   # 'chunk_index' never exists β†’ always 0

# CORRECT
chunk_index = row.get("chunk-id", row.get("chunk_index", 0))

Impact:

  • All chunks have chunk_index = 0
  • The unique constraint UNIQUE(document_id, chunk_index) means only one chunk per document is stored β€” all subsequent chunks of the same document are silently skipped as duplicates
  • 55 documents Γ— 1 chunk each = 55 rows instead of the expected ~5 000 unique chunks

Fix: See ingest_data.py β€” the lookup key must be chunk-id.


βœ— Fields Not Stored (9 dataset fields dropped)

Nine dataset fields are read during ingestion but discarded without being written to any DB column:

HF Field Content Why Useful Suggested Destination
summary Full paper abstract (228–1 920 chars) Richer context for retrieval; could be searchable documents.metadata["summary"]
authors Comma-separated author names Citation display; author-based filtering documents.metadata["authors"]
categories All arXiv categories (cs.LG, cs.AI, ...) Category-based RBAC or filtering documents.metadata["categories"]
primary_category Primary arXiv category UI display; query routing documents.metadata["primary_category"]
published Publication date (YYYYMMDD) Temporal filtering; freshness ranking documents.metadata["published"]
updated Last update date (YYYYMMDD) Detect revised papers documents.metadata["updated"]
comment Author comments (nullable) Version notes, e.g. "Published in NeurIPS 2023" documents.metadata["comment"]
journal_ref Journal reference (nullable) Peer-review status indicator documents.metadata["journal_ref"]
references List of cited paper IDs Citation graph; could link documents documents.metadata["references"]

All nine fields can be preserved by expanding the _get_or_create_document call in ingest_data.py to write them into documents.metadata:

# Expanded metadata β€” stores all dropped fields
psycopg2.extras.Json({
    "source":           row.get("source", ""),
    "summary":          row.get("summary"),
    "authors":          row.get("authors"),
    "categories":       row.get("categories"),
    "primary_category": row.get("primary_category"),
    "published":        row.get("published"),
    "updated":          row.get("updated"),
    "comment":          row.get("comment"),
    "journal_ref":      row.get("journal_ref"),
    "references":       row.get("references", []),
})

Full Dataset Schema (for reference)

All 15 fields available in jamescalam/ai-arxiv2-chunks (train split, 241k rows):

Field Type Nullable Range / Notes
doi string no 10 chars β€” arXiv ID (e.g. 2401.09350)
id string no 12–14 chars β€” same arXiv ID, alternate field
chunk-id int64 no 0–936 β€” position of this chunk within the paper
chunk string no 401–2 020 chars β€” the actual text passage
title string no 8–162 chars
summary string no 228–1 920 chars β€” full abstract
source string no 31 chars β€” PDF URL (http://arxiv.org/pdf/{id})
authors string no 7–6 970 chars β€” comma-separated
categories string no 5–107 chars β€” space-separated arXiv tags
primary_category string no 5–17 chars β€” e.g. cs.LG
published string no 8 chars β€” YYYYMMDD
updated string no 8 chars β€” YYYYMMDD
comment string yes 4–398 chars β€” nullable
journal_ref string yes 8–194 chars β€” nullable
references list[{id}] no Nested list of {"id": "..."} objects

Re-ingestion After Fixes

After applying the chunk-id field fix and expanding metadata, clear existing data and re-ingest:

# Remove only the ingested content (preserves users/roles/logs)
docker exec agentic-rag-db-1 psql -U postgres -d agentic_rag -c "
TRUNCATE chunks, role_document_access, documents RESTART IDENTITY CASCADE;"

# Re-ingest with correct field mapping
docker-compose run --rm backend python -m scripts.ingest_data --limit 5000

After fixing chunk-id, a --limit 5000 run will produce ~5 000 unique chunks (instead of 55) because each document now contributes multiple chunk positions.