// Canonical example for the book: enterprise RAG pipeline.

person = kind "Person"
system = kind "System"
container = kind "Container"
component = kind "Component"
database = kind "Database"
queue = kind "Queue"

overview {
  summary "Retrieval-Augmented Generation (RAG) pipeline for enterprise knowledge management"
  audience "Data Engineers, AI Architects, Compliance Officers"
  scope "Document ingestion, embedding generation, vector retrieval, and llm answer generation"
  goals ["Provide accurate answers from internal docs", "Ensure data freshness < 1hr", "Enforce access controls"]
  nonGoals ["General purpose chatbot", "Creative writing"]
  risks ["Hallucinations", "Leaking sensitive document data to unauthorized users"]
}

employee = person "Employee" {
  description "Knowledge worker seeking internal information"
}

dataAdmin = person "Data Administrator" {
  description "Manages document sources and access policies"
}

ragPlatform = system "RAG Platform" {
  description "End-to-end RAG system"
  metadata { tags ["R1"] }

  ui = container "Chat Interface" {
    technology "React/Tailwind"
    description "Chatbot UI with citation support"
    chatWindow = component "Chat Window" {
      description "Message stream"
      technology "React Component"
      metadata { tags ["R4"] }
    }
    citationViewer = component "Citation Viewer" {
      description "Source document preview"
      technology "PDF.js"
      metadata { tags ["R4"] }
    }
  }

  gateway = container "API Gateway" {
    technology "Python/FastAPI"
    description "Orchestrates retrieval and generation"
    metadata { tags ["R1"] }
    slo { latency { p95 "2s" p99 "5s" } }
    queryPreprocessor = component "Query Preprocessor" {
      description "Rewrites queries for better retrieval"
      technology "LangChain"
      metadata { tags ["R1"] }
    }
    guardrails = component "Guardrails" {
      description "Input/Output safety checks"
      technology "NeMo Guardrails"
      metadata { tags ["R3"] }
    }
  }

  ingestion = container "Ingestion Service" {
    technology "Python/LangChain"
    description "Processes documents into vectors"
    metadata { tags ["R2"] }
    pdfLoader = component "PDF Loader" {
      description "Parses PDFs"
      technology "PyMuPDF"
      metadata { tags ["R2"] }
    }
    chunker = component "Chunker" {
      description "Splits text"
      technology "RecursiveCharacterTextSplitter"
      metadata { tags ["R2"] }
    }
    embedder = component "Embedder" {
      description "Generates embeddings"
      technology "OpenAI Ada"
      metadata { tags ["R1"] }
    }
  }

  retrieval = container "Retrieval Service" {
    technology "Python"
    description "Semantic search and reranking"
    metadata { tags ["R1"] }
    hybridSearch = component "Hybrid Search" {
      description "Keyword + Vector search"
      technology "Pinecone"
      metadata { tags ["R1"] }
    }
    reranker = component "Reranker" {
      description "Cross-encoder reranking"
      technology "Cohere Rerank"
      metadata { tags ["R1"] }
    }
  }

  vectorDb = database "Vector Database" {
    technology "Qdrant / Milvus"
    description "Stores document embeddings and metadata"
    scale { min 3 max 5 metric "memory > 80%" }
  }

  docStore = database "Document Store" {
    technology "S3 / MinIO"
    description "Raw document storage"
  }

  cache = database "Semantic Cache" {
    technology "Redis"
    description "Caches frequent queries and answers"
  }

  ingestionQueue = queue "Ingestion Queue" {
    technology "RabbitMQ"
    description "Decouples upload from processing"
  }

  gateway.queryPreprocessor -> retrieval.hybridSearch "Search"
  retrieval.hybridSearch -> vectorDb "KNN Search"
  retrieval.reranker -> retrieval.hybridSearch "Re-rank results"
  gateway -> cache "Check hit"
  ingestion.chunker -> ingestion.embedder "Embed chunks"
  ingestion.embedder -> vectorDb "Upsert vectors"
  ingestion.pdfLoader -> docStore "Fetch raw"

  gateway -> llmProvider "Generate answer"
  ingestion.embedder -> llmProvider "Get embeddings"
}

llmProvider = system "LLM Provider" {
  description "OpenAI GPT-4 or Azure OpenAI"
  metadata { tags ["external", "cost-sensitive"] }
}

internalSources = system "Internal Data Sources" {
  description "Enterprise knowledge repositories"
  metadata { tags ["external"] }
  sharePoint = container "SharePoint" {
    technology "Microsoft Graph API"
    description "Corporate data source"
    metadata { tags ["R3"] }
  }
  confluence = container "Confluence" {
    technology "Atlassian API"
    description "Wiki data source"
    metadata { tags ["R3"] }
  }
  googleDrive = container "Google Drive" {
    technology "Google Drive API"
    description "File storage"
    metadata { tags ["R3"] }
  }
}

employee -> ragPlatform.ui "Asks question"
ragPlatform.ui -> ragPlatform.gateway "Submit query"

dataAdmin -> ragPlatform.ingestion "Configure sources"
internalSources.sharePoint -> ragPlatform.ingestionQueue "Webhook/Sync"
internalSources.confluence -> ragPlatform.ingestionQueue "Sync"
internalSources.googleDrive -> ragPlatform.ingestionQueue "Sync"
ragPlatform.gateway.guardrails -> ragPlatform.gateway.queryPreprocessor "Safe query"

AnswerQuestion = scenario "Answer Question" {
  step employee -> ragPlatform.ui "What is the travel policy?"
  step ragPlatform.ui -> ragPlatform.gateway "Query"
  step ragPlatform.gateway -> ragPlatform.cache "Check cache"
  // Cache Miss
  step ragPlatform.gateway -> ragPlatform.retrieval "Retrieve context"
  step ragPlatform.retrieval -> ragPlatform.vectorDb "Semantic search"
  step ragPlatform.vectorDb -> ragPlatform.retrieval "Top 20 chunks"
  step ragPlatform.retrieval -> ragPlatform.gateway "Context"
  step ragPlatform.gateway -> llmProvider "Generate(Query + Context)"
  step llmProvider -> ragPlatform.gateway "Answer"
  step ragPlatform.gateway -> ragPlatform.ui "Stream response"
}

ragPlatform.ui.chatWindow -> ragPlatform.ui "part of"
ragPlatform.ui.citationViewer -> ragPlatform.ui "part of"
ragPlatform.retrieval -> ragPlatform "part of"
internalSources -> ragPlatform "provides data to"
ragPlatform -> R1 "satisfies"
ragPlatform.ingestion -> R2 "ensures"
ragPlatform.gateway -> R3 "enforces"
ragPlatform.ui -> R4 "supports"

IngestionFlow = flow "Document Indexing" {
  step internalSources -> ragPlatform.ingestionQueue "New Document Event"
  step ragPlatform.ingestionQueue -> ragPlatform.ingestion.pdfLoader "Process"
  step ragPlatform.ingestion.pdfLoader -> ragPlatform.ingestion.chunker "Text"
  step ragPlatform.ingestion.chunker -> ragPlatform.ingestion.embedder "Chunks"
  step ragPlatform.ingestion.embedder -> ragPlatform.vectorDb "Vectors"
}

R1 = requirement functional "Provide accurate answers from internal docs"
R2 = requirement performance "Ensure data freshness < 1hr"
R3 = requirement security "Enforce access controls"
R4 = requirement compliance "All answers must include citations"

ACLPolicy = policy "Users can only retrieve docs they have access to" {
  category "security"
  enforcement "required"
}
CitationsPolicy = policy "All answers must include citations" {
  category "compliance"
  enforcement "required"
}

constraints {
  "vectorDb must be isolated per tenant"
  "PII must be redacted before embedding"
}

ADR001 = adr "Hybrid Search" {
  status "accepted"
  context "Vector search misses exact keyword matches (e.g., project codes)."
  decision "Implement Hybrid Search (Sparse + Dense vectors)."
  consequences "Higher storage cost, better retrieval accuracy."
}

