EVALUATION REPORT — TURBOFAN MAINTENANCE DIAGNOSTIC REASONING

GraphRAG found the evidence naive RAG missed. The metric that scored them couldn't see it.

A 45-item, jury-verified evaluation of naive RAG vs. GraphRAG diagnostic reasoning over turbofan engine maintenance documentation — built, benchmarked, and audited end to end.

45
gold-set items
0.744
GraphRAG context recall
1.0
edge authenticity
7
question categories

What AeroOps Is

AeroOps is a diagnostic reasoning system for turbofan engine maintenance — it traces fault chains, cross-references procedures, and synthesizes answers across 260 pages of failure-mode, deterioration, and maintenance documentation, the same way an experienced engineer would work a diagnosis across multiple manuals. GraphRAG was built to test whether representing that documentation as a knowledge graph produces more reliable multi-hop and cross-document reasoning than standard vector-similarity retrieval. Maintenance decisions in this domain carry real safety and cost consequences, which is why this evaluation holds both systems to a hard standard: not just whether an answer sounds right, but whether it's actually traceable to the evidence.

260 PAGES · 7 DOCUMENTS Failure modes Procedures Symptoms/params Naive RAG vector top-k GraphRAG graph traversal Answer + citations engineer
Both systems read the same source documents — only the retrieval path differs.

Evaluation Methodology

Gemini
generates expected answer
3-way jury
Qwen3.8 · GPT-5.6 · Opus 5
44/45
unanimous, 1 resolved by human review
Frozen set
45 items, 7 categories

Every item in this set is either machine-verified by independent consensus or personally checked by hand. Nothing in the gold set is unverified.[1](opens the full frozen gold set on GitHub, in a new tab)

multi_hop_causal
8
operational_scenario
8
cross_document
8
aggregation_fanout
6
disambiguation
6
factual_single_hop
6
provenance
3

Is the judge itself reliable?

The same 45 GraphRAG answers were re-scored 3 times by the RAGAS judge, with nothing regenerated between runs. The aggregate mean held tight. Individual items didn't.

Faithfulness
mean spread 0.027
Run 1: 0.589  ·  Run 2: 0.577  ·  Run 3: 0.562
Context Recall
mean spread 0.017
Run 1: 0.778  ·  Run 2: 0.772  ·  Run 3: 0.761
AF03
single item, 3 runs
Run 1: 0.0  ·  Run 2: 0.667  ·  Run 3: 0.0
Run 1 Run 2 Run 3
The aggregate mean is stable enough to trust for system-level comparisons (±0.03). A single item's score is not — AF03 alone swung the full 0.0–0.667 range on identical input. This stability check ran on an earlier snapshot, before this session's final retrieval fixes; what carries forward is the property that the judge disagrees with itself on identical input, not the exact spread number.

Naive RAG

Query
Hybrid search
dense + BM25
top-k = 5
gpt-oss-20b

Dense vector search (MiniLM embeddings, ChromaDB) merged with BM25 keyword search[3](opens naive_rag.py on GitHub, in a new tab), deduplicated and truncated to the top 5 chunks per query. A keyword metadata filter narrows retrieval to the relevant document before search runs.[2](opens the naive RAG RAGAS evaluation results on GitHub, in a new tab)

0.765
Faithfulness, overall
0.470
Context Recall, overall
factual_single_hop
0.833
cross_document
0.521
multi_hop_causal
0.188
aggregation_fanout
0.583
disambiguation
0.500
operational_scenario
0.375
provenance
0.333

GraphRAG

Path traversal
real edges only — CAUSES / LEADS_TO / MANIFESTS_AS / DEGRADES / MITIGATES / INDICATES
Star retrieval
single-entity, capped at 16 chunks
No-path fallback
independent stars, no connecting edge

Retrieval dispatches into one of two main paths depending on the query[5](opens graphretriever_v5.py on GitHub, in a new tab), both restricted to real semantic edge types — never structural co-occurrence. Generation runs under a 15-rule grounding prompt[7](opens answer_generator_groq.py on GitHub, in a new tab), including a rule that preserves the source's own cause→effect direction rather than inverting it.

0.627
Faithfulness, overall
factual_single_hop
0.833
cross_document
0.688
multi_hop_causal
0.750
aggregation_fanout
0.667
disambiguation
0.583
operational_scenario
0.812
provenance
1.000

Naive vs. GraphRAG: Why Graph "Lost"

RAGAS Faithfulness checks whether each claim in an answer can be traced to a single literal passage of retrieved text. It gives no credit for combining several separately-true passages into one synthesized, correct conclusion — which is exactly what GraphRAG is built to do.

Naive RAG (solid)GraphRAG (striped)

Three representative examples follow. Every answer below links directly to its full raw record — GraphRAG's to the exact graph edges backing its claim[9](opens the full GraphRAG raw evaluation outputs on GitHub, in a new tab), naive RAG's to its retrieved context and generated answer[10](opens the full naive RAG raw evaluation outputs on GitHub, in a new tab).

EXAMPLE 1 — MH03
How could the failure of a single fuel tank boost pump potentially cause a multiple-engine flameout?
GOLD: The boost pump failure can generate debris that clogs the fuel filter. Once clogged, disrupted fuel flow or contamination bypassing the filter introduces the potential for a multiple-engine flameout.
Naive RAG
"The provided context does not contain information on how a single fuel tank boost pump failure could cause a multiple-engine flameout."[10](opens raw evaluation record for MH03 on GitHub, in a new tab)
Faithful.1.0
Recall0.0
GraphRAG
"A failure of one fuel-tank boost pump can generate debris that clogs the fuel filter, which in turn can cause fuel starvation and lead to flameout. Because the filter feeds multiple engines, a single pump failure can precipitate a flameout in more than one engine." CAUSES · claim CL051 · conf 0.8 · D3_c29 → LEADS_TO · claim CL052 · conf 0.75 · D3_c30 (opens raw evaluation record for MH03 on GitHub, in a new tab)
Faithful.0.0
Recall0.5
Naive refused to answer and scored a perfect 1.0 — a refusal contains no claims, so nothing can be unfaithful. GraphRAG gave the substantively correct answer, backed by two real, individually-sourced graph edges, and scored 0.0 because no single passage states the full chain in one sentence.
EXAMPLE 2 — OS08
In flight, the pilot notices brief fluctuations in EPR and EGT, but the engine continues running normally because the continuous ignition system activated automatically. What event did the ignition system prevent?
GOLD: It prevented a total flameout by automatically restarting combustion after unstable engine operation or a temporary fuel interruption.
Naive RAG
"The provided context does not contain information about the continuous ignition system or the event it prevented."[10](opens raw evaluation record for OS08 on GitHub, in a new tab)
Faithful.1.0
Recall0.0
Same pattern, narrower cause: GraphRAG retrieved 100% of the needed evidence (Recall = 1.0) but the judge wouldn't accept "prevented a flameout" as entailed by a source stating combustion "will restart automatically" — a legitimate paraphrase, rejected on strict literalism.
EXAMPLE 3 — OS01
A pilot reports a loud bang and heavy vibration during takeoff, but notes the engine recovered immediately after they pulled back the thrust lever. What fault happened and what corrected it?
GOLD: The engine experienced a compressor surge; retarding the thrust lever allowed the engine to recover airflow stability.
Naive RAG
"The loud bang and heavy vibration were caused by a compressor surge in the turbofan engine. Pulling back the thrust lever reduced the airflow and stopped the surge, allowing the engine to recover immediately."[10](opens raw evaluation record for OS01 on GitHub, in a new tab)
Faithful.0.0
Recall0.5
GraphRAG
"The fault was a compressor surge / stall, which manifested as a loud bang and heavy vibration. The engine recovered when the pilot retarded the thrust lever, which is the prescribed mitigation for a compressor surge." MANIFESTS_AS · claim CL024 · conf 0.95 · D3_c03 · LEADS_TO · claim CL028 · conf 0.85 · D3_c07 (opens raw evaluation record for OS01 on GitHub, in a new tab)
Faithful.0.25
Recall1.0
Here both systems answer correctly and both score low — the one case of the three where naive RAG's own faithfulness collapses too. This isn't purely a "GraphRAG is disadvantaged" story: the judge is broadly harsh on causal-attribution language regardless of backend, just harsher and more often on GraphRAG's multi-hop phrasing.

GraphRAG-only Mechanical Metrics

Seven metrics computed directly against the graph and the gold set[11](opens the GraphRAG mechanical scores on GitHub, in a new tab) — no judge, no subjectivity. For the first six columns, darker amber = weaker score. Overfetch uses a separate blue-gray scale (darker = more over-retrieval) since higher is worse there, the opposite direction of every other column — values are printed in every cell either way, so the color is a supplement, not the only signal.

Node RecallOf the entities the gold answer needs, what fraction did the system find?
Node PrecisionOf everything the system found, what fraction was actually needed?
Citation RecallDid the answer cite every source passage it needed to?
Citation PrecisionOf the sources cited, how many were necessary?
Chain CoverageFor multi-step questions, how much of the expected reasoning sequence did the system reconstruct, in order?
Edge AuthenticityOf every causal link the answer relies on, what fraction traces to a real, document-sourced graph edge — not two facts that just happened to sit near each other?
OverfetchHow many source passages were retrieved versus how many the gold answer actually needed.
Edge Authenticity is 1.0 everywhere a reasoning chain exists — every causal link GraphRAG narrates in this evaluation traces to a real, claim-backed relationship. It never fabricates a cause it can't source.

Takeaway

GraphRAG finds the right evidence nearly 60% more often than naive RAG — 0.744 vs. 0.470 Context Recall[8](opens the GraphRAG RAGAS evaluation results on GitHub, in a new tab), a win in almost every category — and it never fabricates a causal relationship that isn't in the documentation. Naive RAG's higher blended Faithfulness score (0.765 vs. 0.627)[2](opens the naive RAG RAGAS evaluation results on GitHub, in a new tab) isn't a system failure on GraphRAG's part. It's a metric that rewards saying nothing over reasoning correctly across real, verified evidence — proven directly, with the receipts, in Section 4.

Known limitations — stated plainly

OPEN
Overfetch, ~7.3x average. A direct test confirmed shrinking the retrieval cap is unsafe — it breaks evidence coverage on hard questions before it meaningfully cuts overfetch on easy ones. The right fix is an adaptive, per-query budget; scoped, not built.[11](opens the GraphRAG mechanical scores on GitHub, in a new tab)
OPEN
Node precision is low (0.369). The recall-heavy design means a meaningful fraction of what's retrieved per query isn't needed — the flip side of overfetch.
OPEN
cross_document is the weakest category on nearly every mechanical metric. Flagged, not yet root-caused.
OPEN
Chain Coverage is low (0.189). Even correct entity/edge identification frequently doesn't reconstruct the gold answer's full reasoning sequence in order.
PARTIAL
The Faithfulness metric-blindness has no clean fix. Prompt-engineering fixed a genuine directional-inversion bug[7](opens answer_generator_groq.py on GitHub, in a new tab), but can't close the gap on genuinely multi-hop synthesized claims — a mismatch between the metric and what GraphRAG is designed to do, not a system defect.

References

Every numbered citation in this report links to a real file in the public repository — full raw output, not a summary of it.

  1. [1] Frozen gold set45 items, 7 categories, jury-verified (Gemini-generated, cross-checked by Qwen3.8/GPT-5.6/Opus 5).
    evaluation/gold_set/aeroops_goldset_v1_frozen.json(opens on GitHub, in a new tab)
  2. [2] Naive RAG — RAGAS evaluation resultsFaithfulness and Context Recall, scored per item and by category.
    evaluation/naive_rag/aeroops_naive_rag_ragas_results.json(opens on GitHub, in a new tab)
  3. [3] naive_rag.pyHybrid BM25 + dense-vector retrieval and generation implementation.
    naive_rag.py(opens on GitHub, in a new tab)
  4. [4] query_understanding_v3.pyQueryRouter: rule-based entity extraction, hop-count and intent classification.
    query_understanding_v3.py(opens on GitHub, in a new tab)
  5. [5] graphretriever_v5.pyGraphRetriever: path-traversal, star retrieval, and no-path fallback logic.
    graphretriever_v5.py(opens on GitHub, in a new tab)
  6. [6] context_builder.pyContextBuilder: formats retrieved graph facts with inline chunk-level provenance.
    context_builder.py(opens on GitHub, in a new tab)
  7. [7] answer_generator_groq.pyAnswerGenerator: the 15-rule grounding prompt, including the directional-inversion fix.
    answer_generator_groq.py(opens on GitHub, in a new tab)
  8. [8] GraphRAG — RAGAS evaluation resultsFaithfulness and Context Recall, scored per item and by category.
    evaluation/graphrag/aeroops_graphrag_ragas_results.json(opens on GitHub, in a new tab)
  9. [9] GraphRAG — raw retrieval/generation outputsAll 45 items: model answers, retrieved contexts, matched entities, reasoning chains with edge claim IDs and confidence. Source for every worked-example citation in Section 4.
    evaluation/graphrag/graphrag_ragas_inputs.json(opens on GitHub, in a new tab)
  10. [10] Naive RAG — raw retrieval/generation outputsAll 45 items: model answers and retrieved contexts.
    evaluation/naive_rag/naive_rag_ragas_inputs.json(opens on GitHub, in a new tab)
  11. [11] GraphRAG — mechanical scoresDeterministic, no-LLM-judge metrics: node/citation recall & precision, chain coverage, edge authenticity, overfetch.
    evaluation/graphrag/aeroops_graphrag_mechanical_scores.json(opens on GitHub, in a new tab)