Skip to content

Architecture Overview

Raw to Knowledge is a domain-driven, layered FastAPI service that converts raw conversation transcripts into structured, validated, governed knowledge objects. It enforces privacy protection, semantic typing, human review authority, and full provenance at every stage of the pipeline.


1. Four-Layer Architecture

Every request in Raw to Knowledge travels through four layers. Dependencies point inward only — the domain layer has zero knowledge of infrastructure.

flowchart TD
    subgraph API["① API Layer  ·  FastAPI routers"]
        R1["/v1/artifacts\nIntake"]
        R1C["/v1/connectors\nSource Connectors"]
        R2["/v1/classification\nClassification"]
        R3["/v1/validation\nValidation"]
        R4["/v1/registry\nRegistry"]
        R5["/v1/generation\nGeneration"]
        R6["/v1/trends\nTrend Path"]
        R7["/v1/graph · /v1/retrieval\n/v1/readouts · /v1/dashboard"]
    end

    subgraph APP["② Application Layer  ·  Use-case orchestrators"]
        IS[IntakeService]
        CNS[ConnectorService\nConnectorRegistry]
        CS[ClassificationService]
        VS[ValidationService]
        RS[RegistryService]
        GS[GenerationService / AGWMPService]
        TS[TrendReportService\nCanonicalizationService]
        GRS[GraphService]
        RTS[RetrievalService]
    end

    subgraph DOM["③ Domain Layer  ·  Pure business logic"]
        subgraph models["Domain Models (frozen Pydantic)"]
            M1[SourceArtifact\nTranscriptSegment\nCandidateQuestion]
            M2[ClassificationRecord\nAssertionGrammar]
            M3[ValidationRecord\nApprovedAnswer]
            M4[TranscriptLine\nRawMention\nLineSentiment\nCanonicalEntity]
        end
        subgraph services["Domain Services (no I/O)"]
            DS1[TranscriptSegmenter\nPrivacyTagger\nCandidateExtractor]
            DS2[Classifier\nSubtypeClassifier\nGrammarExtractor]
            DS3[StateMachine\nConflictDetector\nContradictionDetector]
            DS4[LineNormalizer\nMentionExtractor\nSentimentScorer\nCanonicalizationSvc]
        end
        PROTO[Repository Protocols\nGraph Protocol\nLLM Protocol\nSourceConnector Protocol]
    end

    subgraph INFRA["④ Infrastructure Layer  ·  Adapters"]
        PG[(PostgreSQL\nAlembic ORM)]
        REDIS[(Redis\nCelery)]
        WV[(Weaviate\nVector index)]
        N4[(Neo4j\nProperty graph)]
        LLM[OpenAI Adapter]
        CF[Confluence Adapter]
        JR[Jira Adapter]
        TGP[TrendGraphProjector]
        FCN[FellowConnector\nFellow API v2]
        GCN[GongConnector\nGong API v2]
    end

    API --> APP --> DOM
    DOM --> PROTO --> INFRA
    R1C --> CNS
    CNS --> IS

Rule: Application services call domain services and repository protocols. Domain services call nothing — they receive data, return data. Infrastructure implementations are injected at startup via api/dependencies.py.


2. Component Map

graph LR
    subgraph connector_grp["Source Connectors"]
        CREG[ConnectorRegistry\nsource_system → connector]
        FCNC[FellowConnector\nmeeting notes]
        GCNC[GongConnector\ncall transcripts]
    end

    subgraph intake_grp["Intake"]
        SEG[TranscriptSegmenter\nVTT · SRT · TXT · JSON]
        TAG[PrivacyTagger\nNLTK NER + Regex]
        EXT[CandidateExtractor\nFlow A / Flow B]
        LNZ[TranscriptLineNormalizer\nUtterance-level lines]
    end

    subgraph trend_grp["Trend Path"]
        MX[MentionExtractor\nNLTK NP chunker]
        SS[LineSentimentScorer\nVADER]
        QML[QuestionMentionLinker\nProximity window]
        CAN[CanonicalizationService\nFrequency + Similarity]
        TRS[TrendReportService\nJSON · CSV aggregation]
        TGP2[TrendGraphProjector\nNeo4j write]
    end

    subgraph classif_grp["Classification"]
        CLS[HornTypeClassifier\n9 types]
        SUB[SubtypeClassifier\n6 FACT subtypes]
        GRM[GrammarExtractor\nS·P·O·Scope]
    end

    subgraph valid_grp["Validation"]
        SM[StateMachine\n9 states]
        AUTH[AuthorityChecker\nRole × HornType]
        CD[ConflictDetector\nGrammar overlap]
    end

    subgraph reg_grp["Registry"]
        RT[RegistryTransform\nProvenance enforcement]
        SC[SupersessionChain]
        RCO[RegistryConflictRecord]
    end

    subgraph gen_grp["Generation (Flow B)"]
        RAG[RAGContextBuilder\nToken-limited · 4-tier ranking]
        CB[CircuitBreaker\nLLM failure guard]
        F2[F2Scorer\nβ=2 recall-weighted]
        AGWMP[AGWMPService\nKnown-answer detection]
    end

    subgraph out_grp["Output Surfaces"]
        RDB[ReadoutBuilder]
        ANE[MarkdownExporter\nJSONLDExporter]
        RET[RetrievalService\nWeaviate + PG FTS]
        GRS2[GraphService\nContradiction · Supersession]
        DSH[DashboardService\nPrometheus metrics]
    end

    FCNC --> CREG
    GCNC --> CREG
    CREG --> SEG
    SEG --> TAG --> EXT
    EXT --> LNZ
    LNZ --> MX --> SS
    MX --> QML
    CAN --> TRS --> TGP2
    EXT --> CLS --> SUB --> GRM --> SM --> AUTH --> RT
    RT --> RDB & ANE & RET & GRS2 & DSH
    AGWMP --> RAG --> CB --> F2 --> CLS

3. Deployment Topology

graph TB
    subgraph client_grp["Clients"]
        UC([User / Browser])
        IC([API Integration\nCI/CD · Scripts])
    end

    subgraph service_grp["Raw to Knowledge Service Pod"]
        API2[FastAPI\nUvicorn\n:8000]
        CE1[Celery Worker\nraw_to_knowledge_generation\nconcurrency 4]
        CE2[Celery Worker\nraw_to_knowledge_graph\nconcurrency 2]
    end

    subgraph store_grp["Persistent Stores"]
        PG2[(PostgreSQL\n:5432\nSource of truth)]
        RD2[(Redis\n:6379\nBroker + Queue)]
        WV2[(Weaviate\n:8080\nVector index)]
        N42[(Neo4j\n:7687 Bolt\nProperty graph)]
    end

    subgraph ext_grp["External Services"]
        OAI[OpenAI API\nLLM generation]
        CON[Confluence\nRAG source]
        JRA[Jira\nWork items]
        FEL[Fellow API v2\nMeeting notes]
        GON[Gong API v2\nCall transcripts]
    end

    UC & IC -->|HTTPS| API2
    API2 -->|asyncpg| PG2
    API2 -->|async Redis| RD2
    API2 -->|HTTP| WV2
    API2 -->|Bolt async| N42
    RD2 -->|dispatch| CE1 & CE2
    CE1 -->|write| PG2
    CE1 -->|HTTPS| OAI & CON & JRA
    CE2 -->|sync projection| WV2 & N42
    API2 -->|Bearer HTTPS| FEL
    API2 -->|Basic HTTPS| GON

Scaling notes: - The FastAPI pod and Celery workers are independently scalable horizontally. - raw_to_knowledge_graph workers must run with concurrency ≤ 2 per deployment to avoid Neo4j write contention. - Redis must be reachable by both the API pod and all Celery workers.


4. Core Domain Class Diagram

classDiagram
    class SourceArtifact {
        +str artifact_id
        +str source_system
        +SourceType source_type
        +str source_ref
        +datetime received_at
        +LegalBasis legal_basis
        +str customer_scope
        +str processing_run_id
        +str raw_content
    }

    class TranscriptSegment {
        +str segment_id
        +str artifact_id
        +int sequence
        +str text
        +str start_offset
        +str end_offset
        +str speaker
        +PrivacyClass privacy_class
    }

    class CandidateQuestion {
        +str candidate_id
        +str question_text
        +float confidence
        +FlowType flow_type
        +str source_segment_id
        +str artifact_id
        +str processing_run_id
    }

    class ClassificationRecord {
        +str record_id
        +str candidate_id
        +str answer_text
        +HornType primary_horn_type
        +float primary_confidence
        +str assertion_subtype
        +AssertionGrammar assertion_grammar
        +bool requires_review
        +str model_version
    }

    class AssertionGrammar {
        +str subject
        +str predicate
        +str object_value
        +str scope
        +str condition
        +str temporal_boundary
        +float completeness_score
    }

    class ApprovedAnswer {
        +str answer_id
        +str candidate_id
        +HornType horn_type
        +str answer_text
        +str status
        +int version
        +str owner_role
        +str validation_record_id
        +datetime review_due
        +str supersedes_id
        +str customer_scope
    }

    class TranscriptLine {
        +str line_id
        +str artifact_id
        +str segment_id
        +int sequence
        +int source_index
        +str speaker
        +str text
    }

    class RawMention {
        +str mention_id
        +str line_id
        +str normalized_text
        +MentionType mention_type
        +int start_char
        +int end_char
        +str privacy_class
    }

    class LineSentiment {
        +str line_id
        +float compound
        +float pos
        +float neu
        +float neg
        +SentimentLabel sentiment_label
    }

    class CanonicalEntity {
        +str canonical_entity_id
        +str label
        +str normalized_label
        +CanonicalEntityStatus status
        +ResolutionMode resolution_mode
    }

    SourceArtifact "1" --> "many" TranscriptSegment : segments
    TranscriptSegment "1" --> "many" CandidateQuestion : extracts
    CandidateQuestion "1" --> "1" ClassificationRecord : classifies
    ClassificationRecord "1" --> "1" AssertionGrammar : grammar
    ClassificationRecord "1" --> "1" ApprovedAnswer : approves
    ApprovedAnswer --> ApprovedAnswer : supersedes
    TranscriptSegment "1" --> "many" TranscriptLine : lines
    TranscriptLine "1" --> "many" RawMention : mentions
    TranscriptLine "1" --> "1" LineSentiment : sentiment
    RawMention --> CanonicalEntity : resolves_to

5. Key Design Principles

Principle Application
Immutability All Pydantic domain models are frozen=True. ApprovedAnswer is write-once in the database.
Dependency Inversion Application services depend on protocol interfaces. Adapters are injected at startup.
Privacy by Default PrivacyTagger runs on every segment before anything leaves the CII boundary. NOT_ASSESSED blocks ingestion.
Provenance Enforcement Registry insert requires validation_record_id, owner_role, evidence_links, and review_due.
No Opaque Automation All auto-resolution decisions (canonicalization, known-answer detection) store their score, rule, and mode.
Deterministic Similarity Canonicalization uses Jaccard token overlap, not opaque embeddings, for auditability.
Open/Closed Segmentation Adding a transcript format requires only a new SegmentationStrategy — no changes to TranscriptSegmenter.
Open/Closed Connectors Adding a new transcript source requires only a new SourceConnector implementor, settings, and registration — no changes to IntakeService, domain models, or existing routes.