Spaces:
Sleeping
Sleeping
| <mxfile host="app.diagrams.net" version="21.0.0"> | |
| <diagram name="CitationEdge Architecture" id="arch1"> | |
| <mxGraphModel dx="1800" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="2400" pageHeight="2200" math="0" shadow="0"> | |
| <root> | |
| <mxCell id="0" /> | |
| <mxCell id="1" parent="0" /> | |
| <!-- TITLE --> | |
| <mxCell id="title" value="CitationEdge β Agentic Academic Paper Analysis System" style="text;strokeColor=none;fillColor=none;align=center;fontSize=22;fontStyle=1;" vertex="1" parent="1"> | |
| <mxGeometry x="200" y="16" width="1900" height="40" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ LAYER 1: PRESENTATION βββ --> | |
| <mxCell id="L1" value="LAYER 1 β PRESENTATION" style="swimlane;startSize=30;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=13;fontStyle=1;fontColor=#6c8ebf;" vertex="1" parent="1"> | |
| <mxGeometry x="20" y="70" width="2160" height="225" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="user" value="User / Browser" style="rounded=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;fontSize=12;fontStyle=1;" vertex="1" parent="L1"> | |
| <mxGeometry x="20" y="65" width="150" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="react" value="React 18 + Vite 5
Port 5173 (dev)
Why: component model, hot-reload, ESM bundling, built-in proxy" style="rounded=1;whiteSpace=wrap;fillColor=#ffffff;strokeColor=#6c8ebf;strokeWidth=2;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="200" y="40" width="300" height="75" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="p-upload" value="Upload Page
drag-and-drop PDF" style="rounded=1;whiteSpace=wrap;fillColor=#cfe2ff;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="200" y="130" width="140" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="p-jobs" value="Jobs Page
list + delete jobs" style="rounded=1;whiteSpace=wrap;fillColor=#cfe2ff;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="350" y="130" width="140" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="p-results" value="Results Page
scores, claims, gaps" style="rounded=1;whiteSpace=wrap;fillColor=#cfe2ff;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="500" y="130" width="140" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="p-graph" value="Graph Page
D3 force-graph viz" style="rounded=1;whiteSpace=wrap;fillColor=#cfe2ff;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="650" y="130" width="140" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="p-docs" value="Docs Page
API reference" style="rounded=1;whiteSpace=wrap;fillColor=#cfe2ff;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="800" y="130" width="140" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="p-login" value="Login Page
Firebase Auth UI" style="rounded=1;whiteSpace=wrap;fillColor=#cfe2ff;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="950" y="130" width="140" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="vite-proxy" value="Vite Dev Proxy
Routes: /analyze /jobs /reports
/graph /ws β localhost:8004
Why: no CORS in dev" style="rounded=1;whiteSpace=wrap;fillColor=#e8f5e9;strokeColor=#2e7d32;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="1130" y="50" width="240" height="90" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="tailwind" value="TailwindCSS + CSS Variables
Dark glassmorphism theme
Why: utility-first, zero runtime" style="rounded=1;whiteSpace=wrap;fillColor=#f3e5f5;strokeColor=#6a1b9a;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="1390" y="55" width="240" height="75" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="d3" value="D3.js (Graph Page)
Force-directed Neo4j viz
Why: best interactive graph lib" style="rounded=1;whiteSpace=wrap;fillColor=#e3f2fd;strokeColor=#1565c0;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="1650" y="55" width="240" height="75" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="firebase-fe" value="Firebase Auth
Google OAuth + Email/Password
JWT β React AuthContext
Why: managed auth, free tier" style="rounded=1;whiteSpace=wrap;fillColor=#fff3e0;strokeColor=#e65100;fontSize=11;" vertex="1" parent="L1"> | |
| <mxGeometry x="1910" y="50" width="220" height="90" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ LAYER 2: API GATEWAY βββ --> | |
| <mxCell id="L2" value="LAYER 2 β API GATEWAY" style="swimlane;startSize=30;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=13;fontStyle=1;fontColor=#82b366;" vertex="1" parent="1"> | |
| <mxGeometry x="20" y="315" width="2160" height="200" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="fastapi" value="FastAPI β Port 8004
Why: async/await, auto OpenAPI docs,
Pydantic validation, WebSocket support" style="rounded=1;whiteSpace=wrap;fillColor=#ffffff;strokeColor=#82b366;strokeWidth=2;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="20" y="45" width="290" height="75" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="uvicorn" value="Uvicorn ASGI
Non-blocking I/O
Why: pipeline runs fully async" style="rounded=1;whiteSpace=wrap;fillColor=#e8f5e9;strokeColor=#82b366;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="330" y="45" width="220" height="75" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="pydantic" value="Pydantic Settings
config.py reads .env
lru_cache singleton" style="rounded=1;whiteSpace=wrap;fillColor=#e8f5e9;strokeColor=#82b366;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="570" y="45" width="200" height="75" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep1" value="POST /analyze
Upload PDF β job_id" style="rounded=1;whiteSpace=wrap;fillColor=#c8e6c9;strokeColor=#388e3c;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="800" y="40" width="175" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep2" value="GET /jobs/{id}
status + per-agent progress" style="rounded=1;whiteSpace=wrap;fillColor=#c8e6c9;strokeColor=#388e3c;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="985" y="40" width="185" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep3" value="GET /reports/{id}/json,pdf
scores, claims, gaps + PDF" style="rounded=1;whiteSpace=wrap;fillColor=#c8e6c9;strokeColor=#388e3c;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="1180" y="40" width="195" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep4" value="GET /reports/{id}/graph
Neo4j subgraph as JSON" style="rounded=1;whiteSpace=wrap;fillColor=#c8e6c9;strokeColor=#388e3c;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="1385" y="40" width="185" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep5" value="WS /ws/progress/{id}
live push every ~1 second" style="rounded=1;whiteSpace=wrap;fillColor=#fff9c4;strokeColor=#f57f17;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="1580" y="40" width="185" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep6" value="GET /health/ready
Neo4j + MongoDB liveness" style="rounded=1;whiteSpace=wrap;fillColor=#c8e6c9;strokeColor=#388e3c;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="1775" y="40" width="185" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep-del" value="DELETE /jobs/{id}
soft-delete job record" style="rounded=1;whiteSpace=wrap;fillColor=#ffd7d7;strokeColor=#c0392b;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="800" y="110" width="175" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep-graph2" value="GET /graph/stats
POST /graph/query (Cypher)" style="rounded=1;whiteSpace=wrap;fillColor=#c8e6c9;strokeColor=#388e3c;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="985" y="110" width="210" height="55" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="ep-fig" value="GET /reports/{id}/figures
extracted figure descriptions" style="rounded=1;whiteSpace=wrap;fillColor=#c8e6c9;strokeColor=#388e3c;fontSize=11;" vertex="1" parent="L2"> | |
| <mxGeometry x="1205" y="110" width="210" height="55" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ LAYER 3: AGENT PIPELINE βββ --> | |
| <mxCell id="L3" value="LAYER 3 β ASYNC AGENT PIPELINE" style="swimlane;startSize=30;fillColor=#ffe6cc;strokeColor=#d6b656;fontSize=13;fontStyle=1;fontColor=#d6b656;" vertex="1" parent="1"> | |
| <mxGeometry x="20" y="535" width="2160" height="930" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="orch" value="Async Orchestrator

asyncio.gather() per wave
Critical fail β abort pipeline
Optional fail β partial result
Writes progress β MongoDB β WS

Injects one shared
A2AProtocol into AgentContext" style="rounded=1;whiteSpace=wrap;fillColor=#ffffff;strokeColor=#d6b656;strokeWidth=2;fontSize=11;" vertex="1" parent="L3"> | |
| <mxGeometry x="20" y="55" width="230" height="145" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ Wave 1 βββ --> | |
| <mxCell id="W1" value="WAVE 1 β asyncio.gather()" style="swimlane;startSize=25;fillColor=#fff3e0;strokeColor=#e65100;fontSize=11;fontStyle=1;fontColor=#e65100;" vertex="1" parent="L3"> | |
| <mxGeometry x="280" y="40" width="1020" height="155" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-parser" value="ParserAgent β CRITICAL

PyMuPDF: extract text,
sections, paragraphs, refs
β writes Doc/Section/Para β Neo4j" style="rounded=1;whiteSpace=wrap;fillColor=#fff3e0;strokeColor=#e65100;strokeWidth=2;fontSize=11;" vertex="1" parent="W1"> | |
| <mxGeometry x="20" y="35" width="290" height="100" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-enhanced" value="EnhancedParserAgent β CRITICAL

Layout metadata, tables,
structured section detection
β SciBERT embed (768-dim)
β paragraphs β LanceDB" style="rounded=1;whiteSpace=wrap;fillColor=#fff3e0;strokeColor=#e65100;strokeWidth=2;fontSize=11;" vertex="1" parent="W1"> | |
| <mxGeometry x="330" y="35" width="310" height="100" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-visual" value="VisualParserAgent (optional)

PyMuPDF: β₯8 paths OR image = figure
Rasterize at 1.8Γ zoom β base64
β Groq LLaMA 4 Scout Vision API" style="rounded=1;whiteSpace=wrap;fillColor=#fff8e1;strokeColor=#f9a825;fontSize=11;" vertex="1" parent="W1"> | |
| <mxGeometry x="660" y="35" width="340" height="100" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ Wave 2 βββ --> | |
| <mxCell id="W2" value="WAVE 2 β asyncio.gather() | both agents register handlers on A2A after completing" style="swimlane;startSize=25;fillColor=#fff3e0;strokeColor=#e65100;fontSize=11;fontStyle=1;fontColor=#e65100;" vertex="1" parent="L3"> | |
| <mxGeometry x="280" y="225" width="840" height="340" as="geometry" /> | |
| </mxCell> | |
| <!-- KeywordAgent β full technical flow --> | |
| <mxCell id="a-kw" value="KeywordAgent β CRITICAL

β Routing: regex intent detect + cosine sim
 (query_emb vs intent_embeddings β argmax)
β‘ KBIR (ml6team/keyphrase-extraction-kbir-semeval2017)
 RoBERTa BIO token classification β phrase + confidence
 Threshold: score β₯ 0.65, len > 2 chars
β’ POS filter (spaCy): keep NOUN / PROPN / ADJ
 drops verbs, adverbs, false-positive adj-only phrases
β£ SciBERT dedup: cosine > 0.85 β drop lower-scored
 (allenai/scibert_scivocab_uncased, 768-dim)
β€ Groq LLaMA 3.3-70B β type labels
 (method / dataset / metric / concept)

Output: [{term, type, score}] β Keyword nodes β Neo4j
β registers A2A: get_keywords()

Significance: removes ~40% duplicate near-synonyms
before CitationGapAgent runs Semantic Scholar search" style="rounded=1;whiteSpace=wrap;fillColor=#fff3e0;strokeColor=#e65100;strokeWidth=2;fontSize=11;" vertex="1" parent="W2"> | |
| <mxGeometry x="20" y="40" width="400" height="280" as="geometry" /> | |
| </mxCell> | |
| <!-- ClaimAgent --> | |
| <mxCell id="a-claim" value="ClaimAgent β CRITICAL

Graph-RAG: query Neo4j subgraph
 (~3β6k tokens, 86% less than full paper)
β Groq LLaMA 3.3-70B
 extract factual assertions with
 confidence + novelty scores
β Claim nodes β Neo4j
β registers A2A: get_claims()" style="rounded=1;whiteSpace=wrap;fillColor=#fff3e0;strokeColor=#e65100;strokeWidth=2;fontSize=11;" vertex="1" parent="W2"> | |
| <mxGeometry x="440" y="40" width="370" height="160" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ A2A Protocol Registry βββ --> | |
| <mxCell id="a2a-box" value="A2A Protocol Registry
(protocols/a2a_protocol.py)

Shared singleton on AgentContext
In-memory dict: name β handler

Registered after Wave 2 completes:
 "keyword" β KeywordAgent._a2a_handler
 "claim" β ClaimAgent._a2a_handler

Wave 3 agents call:
 ctx.a2a.call(target, method)
 β direct async Python call
 β no DB round-trip (~1ms vs ~300ms)

Fallback: Neo4j query if A2A
registry is unavailable" style="rounded=1;whiteSpace=wrap;fillColor=#e8f4fd;strokeColor=#1565c0;strokeWidth=2;fontSize=11;" vertex="1" parent="L3"> | |
| <mxGeometry x="1140" y="225" width="350" height="340" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ Wave 3 βββ --> | |
| <mxCell id="W3" value="WAVE 3 β asyncio.gather() | uses A2A to call Wave 2 agents directly (no Neo4j re-query)" style="swimlane;startSize=25;fillColor=#fff3e0;strokeColor=#e65100;fontSize=11;fontStyle=1;fontColor=#e65100;" vertex="1" parent="L3"> | |
| <mxGeometry x="280" y="600" width="1400" height="165" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-cit" value="CitationGapAgent (optional)

A2A β get_keywords() [no Neo4j query]
Fallback: Neo4j if A2A unavailable
β Semantic Scholar API (retry 3Γ)
β CitationGap + SuggestedPaper β Neo4j" style="rounded=1;whiteSpace=wrap;fillColor=#fff8e1;strokeColor=#f9a825;strokeWidth=2;fontSize=11;" vertex="1" parent="W3"> | |
| <mxGeometry x="20" y="35" width="320" height="110" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-arg" value="ArgumentationAgent (optional)

A2A β get_claims() [structured dicts]
Richer than graph_memory text blob:
confidence + novelty per claim
β ArgumentAnalysis β Neo4j" style="rounded=1;whiteSpace=wrap;fillColor=#fff8e1;strokeColor=#f9a825;strokeWidth=2;fontSize=11;" vertex="1" parent="W3"> | |
| <mxGeometry x="360" y="35" width="320" height="110" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-claimverif" value="ClaimVerifierAgent (optional)

Verify claims vs external sources
(Tavily / Semantic Scholar)
β verdict + confidence β Neo4j" style="rounded=1;whiteSpace=wrap;fillColor=#fff8e1;strokeColor=#f9a825;fontSize=11;" vertex="1" parent="W3"> | |
| <mxGeometry x="700" y="35" width="310" height="110" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-evidground" value="EvidenceGroundingAgent (optional)

Ground claims in paper evidence
Link Claim β Section spans
β grounding score β Neo4j" style="rounded=1;whiteSpace=wrap;fillColor=#fff8e1;strokeColor=#f9a825;fontSize=11;" vertex="1" parent="W3"> | |
| <mxGeometry x="1030" y="35" width="340" height="110" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ Wave 4 βββ --> | |
| <mxCell id="W4" value="WAVE 4 β Sequential" style="swimlane;startSize=25;fillColor=#fff3e0;strokeColor=#e65100;fontSize=11;fontStyle=1;fontColor=#e65100;" vertex="1" parent="L3"> | |
| <mxGeometry x="280" y="800" width="1050" height="80" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-score" value="ScoringAgent β CRITICAL β Pure math, no LLM call β literary = claimsΓ0.4 + argΓ0.4 + citationsΓ0.2 | citation_score = max(0, 10 β highΓ2 β mediumΓ1) β Score node β Neo4j" style="rounded=1;whiteSpace=wrap;fillColor=#fff3e0;strokeColor=#e65100;strokeWidth=2;fontSize=11;" vertex="1" parent="W4"> | |
| <mxGeometry x="20" y="15" width="610" height="50" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="a-report" value="ReportAgent (optional) β ReportLab β rich PDF with scores, claims, gaps, figures β reports/{job_id}.pdf" style="rounded=1;whiteSpace=wrap;fillColor=#fff8e1;strokeColor=#f9a825;fontSize=11;" vertex="1" parent="W4"> | |
| <mxGeometry x="650" y="15" width="370" height="50" as="geometry" /> | |
| </mxCell> | |
| <!-- Graph-RAG note --> | |
| <mxCell id="graphrag" value="Graph-RAG Strategy

Each agent queries only its own
Neo4j subgraph (~3β6k tokens)
vs 30k for full paper = 86% savings

Retrieval methods:
β Cypher (structured, primary)
β‘ Hybrid: 0.6Γkeyword + 0.4ΓANN
β’ Substring fallback

Budget cap: 5 000 tokens max" style="rounded=1;whiteSpace=wrap;fillColor=#e8eaf6;strokeColor=#3949ab;strokeWidth=2;fontSize=11;" vertex="1" parent="L3"> | |
| <mxGeometry x="1650" y="50" width="290" height="230" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ LAYER 4: DATA STORAGE βββ --> | |
| <mxCell id="L4" value="LAYER 4 β DATA STORAGE" style="swimlane;startSize=30;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=13;fontStyle=1;fontColor=#9673a6;" vertex="1" parent="1"> | |
| <mxGeometry x="20" y="1485" width="2160" height="255" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="neo4j" value="Neo4j AuraDB (Cloud)

URI: neo4j+ssc:// (SSL bypass β fixes WinError)
Why: native graph queries, relationship traversal,
shared inter-agent memory, no SQL JOINs needed

Nodes: Document Β· Section Β· Paragraph
 Claim Β· Keyword Β· CitationGap
 SuggestedPaper Β· Score Β· ArgumentNode

Rels: CONTAINS Β· HAS_CLAIM Β· SUPPORTS
 CONTRADICTS Β· CITES Β· HAS_SCORE" style="rounded=1;whiteSpace=wrap;fillColor=#f3e5f5;strokeColor=#9673a6;strokeWidth=2;fontSize=11;" vertex="1" parent="L4"> | |
| <mxGeometry x="20" y="50" width="390" height="180" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="mongo" value="MongoDB (localhost:27017)

DB: citationedge_agentic
Why: flexible schema, no migrations,
nested result documents

Collection: jobs
 status, progress, agent states

Collection: results
 scores, keywords, claims, gaps" style="rounded=1;whiteSpace=wrap;fillColor=#f3e5f5;strokeColor=#9673a6;strokeWidth=2;fontSize=11;" vertex="1" parent="L4"> | |
| <mxGeometry x="430" y="50" width="350" height="180" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="lance" value="LanceDB (./data/vectors)

Embedded columnar vector DB
Why: no server needed, fast ANN search,
paragraph-level semantic retrieval

Embedding model: SciBERT
 allenai/scibert_scivocab_uncased
 768-dim vectors, mean pooling + L2 norm
 Trained on 1.14M scientific papers
 Understands domain vocab: ablation,
 citation gap, transformer, baseline

Hybrid search:
 0.6 Γ keyword score (Cypher)
+ 0.4 Γ ANN vector score (SciBERT)" style="rounded=1;whiteSpace=wrap;fillColor=#f3e5f5;strokeColor=#9673a6;strokeWidth=2;fontSize=11;" vertex="1" parent="L4"> | |
| <mxGeometry x="800" y="50" width="350" height="180" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="fs" value="File System

uploads/
 temp PDFs (auto-cleaned)

reports/
 generated PDF reports

data/vectors/
 LanceDB tables" style="rounded=1;whiteSpace=wrap;fillColor=#f3e5f5;strokeColor=#9673a6;fontSize=11;" vertex="1" parent="L4"> | |
| <mxGeometry x="1170" y="50" width="250" height="180" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ LAYER 5: EXTERNAL SERVICES βββ --> | |
| <mxCell id="L5" value="LAYER 5 β EXTERNAL SERVICES" style="swimlane;startSize=30;fillColor=#f8cecc;strokeColor=#b85450;fontSize=13;fontStyle=1;fontColor=#b85450;" vertex="1" parent="1"> | |
| <mxGeometry x="20" y="1760" width="2160" height="240" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="groq" value="Groq Cloud API

Model 1: LLaMA 3.3-70B-Versatile
 β all text agents

Model 2: LLaMA 4 Scout 17B-16E
 β vision (figures / flowcharts)

Why: free tier 100k tokens/day,
fastest inference vs OpenAI/Anthropic" style="rounded=1;whiteSpace=wrap;fillColor=#ffebee;strokeColor=#b85450;strokeWidth=2;fontSize=11;" vertex="1" parent="L5"> | |
| <mxGeometry x="20" y="50" width="340" height="165" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="semscholar" value="Semantic Scholar API

Endpoint: /graph/v1/paper/search

Returns: title, authors, year,
abstract, citationCount, DOI

Why: free, no API key required,
comprehensive academic coverage

Used by: CitationGapAgent (retry 3Γ)" style="rounded=1;whiteSpace=wrap;fillColor=#ffebee;strokeColor=#b85450;strokeWidth=2;fontSize=11;" vertex="1" parent="L5"> | |
| <mxGeometry x="380" y="50" width="320" height="165" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="firebase-ext" value="Firebase Authentication

Google OAuth + Email/Password
JWT tokens β React AuthContext
User avatar dropdown in Navbar

Why: fully managed auth service,
free tier, no backend auth code,
built-in token refresh" style="rounded=1;whiteSpace=wrap;fillColor=#fff3e0;strokeColor=#e65100;strokeWidth=2;fontSize=11;" vertex="1" parent="L5"> | |
| <mxGeometry x="720" y="50" width="310" height="165" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="scibert-box" value="SciBERT (Local Model)
allenai/scibert_scivocab_uncased

Loaded via HuggingFace Transformers
Runs on CPU (or CUDA if available)
Lazy-loaded, singleton instance

768-dim embeddings via mean pooling
L2-normalised for cosine ANN search
Max 512 tokens (truncated)

Why: domain-specific vocab from
1.14M Semantic Scholar papers β
outperforms MiniLM on sci text" style="rounded=1;whiteSpace=wrap;fillColor=#e8f5e9;strokeColor=#2e7d32;strokeWidth=2;fontSize=11;" vertex="1" parent="L5"> | |
| <mxGeometry x="1050" y="50" width="320" height="165" as="geometry" /> | |
| </mxCell> | |
| <mxCell id="planned" value="PLANNED β Future Integrations

Tavily Search API
 web + arXiv fallback for claims

arXiv API
 CS/ML paper existence check

DeBERTa NLI (local model)
 contradiction detection

PageIndex Retriever
 LLM-reasoned ToC navigation" style="rounded=1;whiteSpace=wrap;fillColor=#fce4ec;strokeColor=#b85450;strokeDasharray=8;fontSize=11;fontStyle=2;" vertex="1" parent="L5"> | |
| <mxGeometry x="1390" y="50" width="330" height="165" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ ARROWS βββ --> | |
| <!-- User β React --> | |
| <mxCell id="e1" value="HTTP" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#6c8ebf;strokeWidth=2;flowAnimation=1;animationDuration=2000;" edge="1" source="user" target="react" parent="L1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- React β FastAPI --> | |
| <mxCell id="e2" value="REST + WebSocket" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#82b366;strokeWidth=2;flowAnimation=1;animationDuration=1500;" edge="1" source="react" target="fastapi" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- FastAPI β Orchestrator --> | |
| <mxCell id="e3" value="spawn job" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#d6b656;strokeWidth=2;flowAnimation=1;animationDuration=800;" edge="1" source="fastapi" target="orch" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- FastAPI β MongoDB --> | |
| <mxCell id="e4" value="job state" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=2;flowAnimation=1;animationDuration=1000;" edge="1" source="fastapi" target="mongo" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Orchestrator β Wave 1 --> | |
| <mxCell id="e5" value="" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#e65100;strokeWidth=2;flowAnimation=1;animationDuration=600;" edge="1" source="orch" target="W1" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Wave 1 β Wave 2 --> | |
| <mxCell id="e6" value="Neo4j ready" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#e65100;strokeWidth=2;dashed=1;flowAnimation=1;animationDuration=1200;" edge="1" source="W1" target="W2" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Wave 2 β Wave 3 --> | |
| <mxCell id="e7" value="Wave 2 done
A2A registered" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#e65100;strokeWidth=2;dashed=1;flowAnimation=1;animationDuration=1200;" edge="1" source="W2" target="W3" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Wave 3 β Wave 4 --> | |
| <mxCell id="e7b" value="all done" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#e65100;strokeWidth=2;dashed=1;flowAnimation=1;animationDuration=1200;" edge="1" source="W3" target="W4" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Parser β Neo4j --> | |
| <mxCell id="e8" value="write nodes" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=2;flowAnimation=1;animationDuration=700;" edge="1" source="a-parser" target="neo4j" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Enhanced β LanceDB --> | |
| <mxCell id="e9" value="SciBERT 768-dim vectors" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=1.5;flowAnimation=1;animationDuration=900;" edge="1" source="a-enhanced" target="lance" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Arg β Neo4j --> | |
| <mxCell id="e10" value="write analysis" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=1.5;flowAnimation=1;animationDuration=1100;" edge="1" source="a-arg" target="neo4j" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Score β Neo4j --> | |
| <mxCell id="e11" value="Score node" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=1.5;flowAnimation=1;animationDuration=700;" edge="1" source="a-score" target="neo4j" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Report β FileSystem --> | |
| <mxCell id="e12" value="write PDF" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=1.5;flowAnimation=1;animationDuration=1800;" edge="1" source="a-report" target="fs" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Keyword β Groq LLM --> | |
| <mxCell id="e13" value="LLM call" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#b85450;strokeWidth=2;flowAnimation=1;animationDuration=2500;" edge="1" source="a-kw" target="groq" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Visual β Groq vision --> | |
| <mxCell id="e14" value="vision API" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#b85450;strokeWidth=1.5;flowAnimation=1;animationDuration=2500;" edge="1" source="a-visual" target="groq" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Claim β Groq LLM --> | |
| <mxCell id="e13b" value="LLM call" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#b85450;strokeWidth=1.5;flowAnimation=1;animationDuration=2500;" edge="1" source="a-claim" target="groq" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Arg β Groq LLM --> | |
| <mxCell id="e13c" value="LLM call" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#b85450;strokeWidth=1.5;flowAnimation=1;animationDuration=2500;" edge="1" source="a-arg" target="groq" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- CitationGap β Semantic Scholar --> | |
| <mxCell id="e15" value="paper search" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#b85450;strokeWidth=2;flowAnimation=1;animationDuration=2000;" edge="1" source="a-cit" target="semscholar" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Login β Firebase --> | |
| <mxCell id="e16" value="OAuth / JWT" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#e65100;strokeWidth=1.5;flowAnimation=1;animationDuration=1800;" edge="1" source="p-login" target="firebase-fe" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Claim β Neo4j --> | |
| <mxCell id="e17" value="write nodes" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=1.5;flowAnimation=1;animationDuration=700;" edge="1" source="a-claim" target="neo4j" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Keyword β Neo4j --> | |
| <mxCell id="e18" value="write nodes" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=1.5;flowAnimation=1;animationDuration=700;" edge="1" source="a-kw" target="neo4j" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- CitationGap β Neo4j --> | |
| <mxCell id="e19" value="write nodes" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#9673a6;strokeWidth=1.5;flowAnimation=1;animationDuration=700;" edge="1" source="a-cit" target="neo4j" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- βββ A2A ARROWS βββ --> | |
| <!-- Keyword β A2A Registry: registers get_keywords --> | |
| <mxCell id="a2a-e1" value="register
get_keywords()" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#1565c0;strokeWidth=2;dashed=1;flowAnimation=1;animationDuration=500;fontStyle=2;fontSize=10;" edge="1" source="a-kw" target="a2a-box" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- Claim β A2A Registry: registers get_claims --> | |
| <mxCell id="a2a-e2" value="register
get_claims()" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#1565c0;strokeWidth=2;dashed=1;flowAnimation=1;animationDuration=500;fontStyle=2;fontSize=10;" edge="1" source="a-claim" target="a2a-box" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- A2A Registry β CitationGapAgent --> | |
| <mxCell id="a2a-e3" value="get_keywords()
in-memory list" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#1565c0;strokeWidth=2;flowAnimation=1;animationDuration=300;fontStyle=1;fontSize=10;" edge="1" source="a2a-box" target="a-cit" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| <!-- A2A Registry β ArgumentationAgent --> | |
| <mxCell id="a2a-e4" value="get_claims()
structured dicts" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#1565c0;strokeWidth=2;flowAnimation=1;animationDuration=300;fontStyle=1;fontSize=10;" edge="1" source="a2a-box" target="a-arg" parent="1"> | |
| <mxGeometry relative="1" as="geometry" /> | |
| </mxCell> | |
| </root> | |
| </mxGraphModel> | |
| </diagram> | |
| </mxfile> | |