跳到正文
DEV Community· Muhammad Arslan·· 4 小時前AI 評分47

RAG、CAG 與 KAG:如何為 NodeJS 選擇合適的上下文層

RAG vs CAG vs KAG: Choosing the Right Context Layer in NodeJS

AI 導讀

HazelJS 將 RAG、CAG、KAG 與 Memory 視為互補的上下文層,並比較它們在 NodeJS 中的用途與取捨。RAG 用於檢索相關內容,CAG 快取可重用的穩定上下文,KAG 管理具來源資訊的結構化知識,Memory 則維持用戶或工作階段的連貫性。HazelJS 提供各層套件及無需 API keys 的離線實驗。

正文

Retrieval-Augmented Generation (RAG) solved a real problem: LLMs alone don't know your documents. But not every agent question is “find the right passage.” Sometimes you need stable context reused across thousands of requests. Sometimes you need structured entities, facts, and relationships with provenance. That is why HazelJS treats context as four complementary layers — RAG, CAG, KAG, and Memory — and ships first-class packages for each.

This post is a practical cross-comparison: what each layer is for, when it wins or loses, how we built @hazeljs/rag, @hazeljs/cag, and @hazeljs/kag, and real use cases you can run offline in hazeljs-meridian-ops.


Packages & Links

Runnable labs (no API keys): meridian-ops/examples — example:rag · example:cag · example:kag · example:context


One Picture

                 HazelJS Agent
                      │
                      ▼
              Context / Reasoning
                      │
        ┌─────────────┼─────────────┐
        │             │             │
        ▼             ▼             ▼
       RAG           CAG           KAG
        │             │             │
        └─────────────┼─────────────┘
                      │
                    Memory
                      │
                      ▼
                     LLM
Layer Core question Typical answer shape
RAG What information should I retrieve for this query? Ranked passages + citations
CAG What context can I preload, reuse, and cache? Fingerprinted policy / schema blobs
KAG What entities, facts, and relationships do I know? Evidence path + provenance
Memory What has this agent learned or experienced with this user? Preferences, session facts

They are complementary. CAG is not a RAG wrapper. KAG is not “GraphRAG renamed.” Memory is not a knowledge graph.


What Each Layer Is

RAG — Retrieval-Augmented Generation

Idea: At request time, embed the question, search a vector (and optionally keyword) index, optionally rerank, then stuff passages into the prompt.

Request → Embedding → Vector / hybrid search → Documents → LLM

HazelJS surface: @hazeljs/rag — loaders, chunking, embeddings, vector stores, hybrid search, GraphRAG for document-derived graphs, RAGService / RAGPipeline. Meridian’s helpdesk agent uses the same mental model with an in-memory KB (no Qdrant required to learn the pattern).

Best when: answers live in a large, changing corpus and relevance depends on the query.

Lab: examples/rag-helpdesk-agent → npm run example:rag

CAG — Cache-Augmented Generation

Idea: Relatively stable knowledge is prepared once, fingerprinted, cached (memory / Redis / provider prompt-cache hints), then reused — without embedding + search on every request.

Knowledge sources → Prepare → Context cache → Request → Cached context → LLM

HazelJS surface: @hazeljs/cag — CagModule / CagService, sources, fingerprints, TTL / version invalidation, token budgets, optional compression, multi-tenant keys.

Best when: the same policies, schemas, catalogs, or tenant config are needed on almost every turn.

Lab: examples/cag-support-agent → npm run example:cag

KAG — Knowledge-Augmented Generation

Idea: Domain knowledge as typed entities, relations, and time-scoped facts — with provenance, confidence, contradictions, and traversable evidence — then optional LLM phrasing of that evidence.

Data → Extract / ingest → Knowledge graph → Traverse / plan → Evidence → LLM

HazelJS surface: @hazeljs/kag — KnowledgeGraph / KagService, in-memory tenant store, entity resolution, temporal facts, heuristic (industry-pluggable) query planner, ask({ explain: true }), GraphRAG import adapters (not a GraphRAG fork).

Best when: the question is multi-hop, causal, or “why did X change?” over structured domain state — not “which PDF page mentions X?”

Lab: examples/kag-commerce-agent → npm run example:kag

Memory — continuity (not knowledge)

Memory answers “what do we already know about this user / this run?” It is orthogonal to RAG/CAG/KAG. Promote a preference into KAG only when it becomes validated domain truth.


Cross Comparison

Capability matrix

Dimension RAG CAG KAG Memory
Unit of context Passages / chunks Assembled stable text blocks Entities, relations, facts Episodes / preferences
Hot path Embed + search every request Cache hit → assemble Graph traverse / plan Lookup by user/session
Data freshness Great for frequently updated docs Great for slowly changing knowledge Great for operational / transactional truth Great for conversational state
Latency profile Search + embed cost Near-instant on hit Traversal (cheap at small/medium scale) Near-instant
Explainability Citations to passages Source id + version / fingerprint Evidence path + provenance “You said X earlier”
Multi-tenancy Namespaces / metadata filters Cache keys include tenantId Store partitioned by tenantId Scoped by user / agent
Failure mode Wrong or missing passage Stale cache if invalidation is wrong Weak graph / low confidence Stale or over-trusted preference
Typical cost driver Embeddings + vector DB Prompt tokens (mitigated by cache) Ingestion + occasional LLM phrasing Storage + retrieval of history
Update cadence Continuous ingest Version bump / TTL / invalidate Event-driven graph writes Per turn / session
HazelJS package @hazeljs/rag @hazeljs/cag @hazeljs/kag @hazeljs/memory

Same question, four wrong tools

User asks If you only use… What goes wrong
“What’s our return policy?” RAG You pay embed+search every time for text that never changes per tenant version.
“How do I rotate staging API keys?” CAG You either miss the right runbook or stuff the entire handbook into every prompt.
“Why was settlement €1,420 short?” RAG Passages mention refunds; they don’t reconstruct merchant→order→payment→refund→settlement with sources.
“Remember I exclude VAT.” KAG You pollute the domain graph with a personal preference that isn’t operational truth.
Mix of policy + ledger + preference Any single layer Incomplete answer — needs @hazeljs/context.

Pros and cons (short)

Wins Loses when
RAG Large unstructured corpora; query-dependent relevance; mature tooling Multi-hop structured “why”; always-on policy paragraphs
CAG Latency/cost for stable tenant context; fingerprints; priority budgets Query-specific doc lookup; forgotten invalidation
KAG Causal paths, contradictions, provenance, industry profiles Free-form prose; “drop PDFs and go”
Memory Continuity and personalization Treating preferences as ledger truth

How HazelJS Built These Packages

We did not invent three parallel frameworks. We extended the Agent OS context substrate with clear boundaries and heavy reuse.

  1. Composition over duplication — CAG reuses RAG loaders for files/URLs when present; it does not reimplement vector search. KAG can import GraphRAG graphs; it does not own community detection or embeddings.
  2. Native HazelJS shape — @HazelModule, forRoot / forRootAsync, @Service(), typed XxxError + codes, Jest, peer @hazeljs/core.
  3. Multi-tenant by default where it matters — CAG cache keys and KAG store scopes always include tenantId.
  4. Agent OS ports, not hard couples — AgentRuntimeConfig takes duck-typed ragService / cagService / kagService / contextService. DNA declares intent; apps inject services.
  5. Toward a unified planner — @hazeljs/context calls the same contributor shape (contribute) so auto strategy can pick CAG / RAG / KAG / Memory per query.

Real-World Use Cases

Each scenario below maps to a Meridian lab (or live Meridian route). Run the lab after reading the section.

1) Help center / FAQ over a large handbook → RAG

Industries: SaaS support, internal IT, compliance Q&A, product docs.

Problem: Hundreds of docs, changelogs, and runbooks. The right answer depends on the question wording and may live in an obscure page updated last week.

// Pattern (production: @hazeljs/rag ingest + vector store)
const docs = await rag.search('How do I rotate API keys on staging?', { topK: 3 });

Why not CAG? You cannot sensibly preload the entire doc set into every prompt.

Why not KAG? The knowledge is narrative procedure text, not a fact graph (unless you later extract entities).

Lab / live: Offline rag-helpdesk-agent mirrors Meridian’s helpdesk KB. In the running app: POST /api/helpdesk/chat.

npm run example:rag
# ask: "What is the refund SLA?" → hits refund-sla doc, not the whole policy blob

2) Multi-merchant support: always-on return policy → CAG

Industries: Marketplaces, payment platforms, white-label SaaS, any multi-tenant agent.

Problem: Every merchant chat asks about returns, hours, and fee schedules. Running RAG every time burns embeddings and latency for text that rarely changes — and tenant A must never see tenant B’s policy.

cag.register(
  {
    id: 'return-policy',
    priority: 100,
    compressible: false,
    version: '2026-10',
    source: { type: 'text', content: loadMerchantPolicy(tenantId) },
  },
  'support'
);

const { context, hit } = await cag.getContext({
  namespace: 'support',
  tenantId: 'merchant-123',
});

Why not RAG? The answer is not “find a similar paragraph” — it is “always include this policy.”

Why not KAG? There is no multi-hop entity reasoning; it is static prose.

Lab: cag-support-agent — cold miss → warm hit, tenant isolation, version bump invalidates cache.

npm run example:cag
# firstHit: false, secondHit: true, otherTenantHit: false, afterVersionBumpHit: false

Other CAG fits: OpenAPI / tool schemas stuck in every tool-calling turn; compliance disclaimers; product catalog summaries that change weekly under a version key.


3) Ops / finance: “Why was settlement short?” → KAG

Industries: Commerce / payments, logistics (shipment→exception→claim), healthcare ops (patient→encounter→claim), ITSM (incident→change→outage).

Problem: The answer is a path through merchant → orders → payments → refunds → fees → settlement, with source systems and confidence — not a single handbook paragraph.

const knowledge = new KnowledgeGraph({
  tenantId: 'merchant-123',
  industry: COMMERCE_INDUSTRY_PROFILE, // opt-in vocabulary
});

await knowledge.relate({ from: 'payment-1', to: 'refund-1', type: 'HAS_REFUND' });
await knowledge.fact({
  subject: 'refund-1',
  predicate: 'amount',
  object: 1420,
  confidence: 0.98,
  source: { type: 'database', id: 'refund-456', authority: 90 },
});

const result = await knowledge.ask(question, { explain: true });
// result.evidence + result.sources — auditable, not hidden CoT

Why not RAG alone? Passages might mention refunds but won’t reliably reconstruct the causal path with provenance.

Why not CAG alone? The graph changes with every day’s ledger; caching a frozen narrative goes stale immediately.

Lab: kag-commerce-agent — builds the graph, asks the settlement question, prints evidence + contradiction handling.

npm run example:kag
# explanation includes merchant → order → payment → refund → settlement + sources

4) Hybrid desk: policy + ledger + handbook + preference → @hazeljs/context

Industries: Any production support desk that already has RAG and needs policy + ops truth.

Problem: “Why was settlement impacted by a refund, given our refund policy and my VAT preference?”

Slice of the question Layer
Stable refund policy CAG
Relational “why” on the ledger KAG
Optional handbook passage RAG
“exclude VAT” preference Memory
const context = new ContextService({
  strategy: 'auto',
  sources: ['cache', 'rag', 'knowledge', 'memory'],
  cag,
  kag,
  rag,
  memory,
});

const assembled = await context.assemble({
  query,
  tenantId: 'merchant-123',
  userId: 'ops-1',
});
// assembled.plan.rationale explains which layers fired

Lab: context-auto-agent — auto-plans all four contributors and prints labeled assembly.

npm run example:context
# plan.sources: cag, rag, kag, memory — with per-layer rationale

5) Industry cheat sheet

Domain Prefer RAG Prefer CAG Prefer KAG
E‑commerce / payments Help center, shipping FAQs Merchant return/fee policy Settlement, chargeback, refund causality
SaaS / developer platforms API docs, changelogs Per-tenant feature flags / schemas in prompt Entitlement → usage → invoice disputes
Healthcare ops Clinical guidelines PDFs Facility policy snippets Encounter → claim → denial paths
Logistics Carrier manuals Lane / SLA templates Shipment → exception → claim chains
Internal IT Runbooks, wiki Org security policy always-on Asset → ticket → change → outage

When two columns apply in one utterance, reach for @hazeljs/context.

6) Quick decision matrix

If the user asks… Prefer Lab
“What’s in the docs / handbook about X?” RAG example:rag
“What is our always-on policy / schema / catalog?” CAG example:cag
“Why did entity A’s metric change given related entities?” KAG example:kag
“Remember that I prefer…” Memory (wired inside example:context)
A mix of the above @hazeljs/context auto example:context

Common Mistakes

  1. Using RAG for static policies — you pay retrieval forever for text that should be CAG.
  2. Using CAG for the whole knowledge base — prompts explode; retrieval exists for a reason.
  3. Treating GraphRAG as KAG — GraphRAG is document-extraction RAG; KAG is operational knowledge with facts, time, and contradictions.
  4. Auto-merging uncertain entities — HazelJS KAG keeps candidates below threshold; don’t turn that off casually.
  5. Skipping tenant in cache/graph keys — never acceptable for multi-merchant agents.
  6. Exposing raw model chain-of-thought as “explanation” — KAG explanations are evidence (entities, relations, sources).
  7. Putting user preferences only in Memory forever — promote to KAG when they become validated domain rules; keep Memory for soft personalization.

Where This Is Going

HazelJS is moving from “we have RAG, and also CAG, and also KAG” to a single context substrate:

Query → ContextPlanner → CAG | RAG | KAG | Memory → Assembly → LLM

@hazeljs/context is the first cut of that planner. Each package remains independently useful for teams that only need one layer. Meridian Ops is the teaching app: DNA + Skillgate + HITL in the live server, and offline context labs under examples/.


Try It

# from hazeljs-meridian-ops/
npm run example:install
npm run example:rag      # handbook retrieval
npm run example:cag      # cached policy + tenant isolation
npm run example:kag      # settlement evidence path
npm run example:context  # auto planner over all four

Docs: RAG · CAG · KAG · Context


RAG optimizes retrieval. CAG optimizes reuse. KAG optimizes structured knowledge. Memory optimizes continuity. Together they are the context engine of HazelJS Agent OS.

來源:DEV Community · dev.to