SHADOW AI

Image
A Hybrid Neural-Symbolic Architecture for Compact Multilingual Intelligence Project Type Experimental AI Model / Research Architecture / Foundational Language Model Model Family SHADOW AI Proposed Architecture SHADOW-HSR — Hybrid Symbolic Representation Architecture Core Objective SHADOW AI is a proposed experimental AI architecture designed to investigate whether useful multilingual language understanding, symbolic reasoning, contextual memory, and structured generation can be achieved with a more compact architecture than extremely large conventional language models. The architecture is designed around four primary components: > Neural Representation + Symbolic Reasoning + Dynamic State + Efficient Decoding SHADOW AI is intended to explore an alternative design philosophy rather than reproduce an existing commercial AI system. The project does not claim that training can be eliminated. A model capable of general language understanding still requires learning from data. Instead,...

CHAPTER 41 DOCUMENT INGESTION, TEXT EXTRACTION, CHUNKING, EMBEDDINGS, VECTOR STORAGE & RAG FOUNDATION

 

Post cover


41.1 Introduction

A modern AI system cannot reliably answer questions about private documents merely by sending the entire document to a language model. A scalable architecture requires a dedicated document intelligence pipeline that converts uploaded files into structured, searchable, permission-aware knowledge.

The complete pipeline is:

Upload → Validate → Store → Extract → Normalize → Segment → Embed → Index → Retrieve → Rerank → Generate → Cite → Audit

This chapter defines the foundation for that pipeline.

The objective is not simply to make documents searchable. The objective is to create a retrieval system that is:

  • accurate,

  • scalable,

  • permission-aware,

  • traceable,

  • versioned,

  • privacy-preserving,

  • resistant to untrusted document instructions,

  • and suitable for future AI-agent workflows.


41.2 Why Document Ingestion Requires Its Own Architecture

Documents are heterogeneous.

A PDF may contain:

  • selectable text,

  • scanned images,

  • tables,

  • headings,

  • footnotes,

  • page numbers,

  • metadata,

  • diagrams.

A DOCX file may contain:

  • paragraphs,

  • headings,

  • tables,

  • lists,

  • hyperlinks,

  • embedded media.

An HTML document may contain:

  • visible text,

  • navigation,

  • scripts,

  • advertisements,

  • metadata,

  • hidden elements.

Therefore, the application should not treat every uploaded file as a simple text string.

Instead, the system should convert each document into a normalized internal representation.

A useful conceptual model is:

Original File
     │
     ▼
File Metadata
     │
     ▼
Extraction
     │
     ▼
Normalized Document
     │
     ▼
Logical Sections
     │
     ▼
Retrieval Chunks
     │
     ▼
Embeddings
     │
     ▼
Vector Index

Each stage should be independently testable.


41.3 Document Processing Lifecycle

A document should have an explicit processing state.

Recommended states include:

UPLOADED
VALIDATING
QUEUED
EXTRACTING
NORMALIZING
CHUNKING
EMBEDDING
INDEXING
READY
FAILED
DELETED

This prevents the application from assuming that an uploaded document is immediately searchable.

For example:

User uploads report.pdf

        ↓

UPLOADED

        ↓

VALIDATING

        ↓

EXTRACTING

        ↓

NORMALIZING

        ↓

CHUNKING

        ↓

EMBEDDING

        ↓

INDEXING

        ↓

READY

If processing fails, the document should move to FAILED with a safe diagnostic record.


41.4 File Validation Before Extraction

The first rule of document ingestion is:

Never trust the filename or declared MIME type alone.

A file called:

report.pdf

does not prove that the underlying bytes actually represent a valid PDF.

Validation should consider:

  1. File size.

  2. Filename.

  3. Extension.

  4. Declared MIME type.

  5. Detected content type.

  6. File signature where appropriate.

  7. Parser compatibility.

  8. Security scanning.

  9. User/project authorization.

  10. Storage quota.

A safe validation pipeline is:

Upload
  ↓
Size Check
  ↓
Content-Type Check
  ↓
Content Signature Check
  ↓
Security Scan
  ↓
Parser Selection
  ↓
Extraction

Rejected files should not enter the normal AI processing pipeline.


41.5 Supported Document Types

The initial implementation can support a controlled set of formats.

Phase 1

  • TXT

  • Markdown

  • PDF

  • DOCX

Phase 2

  • HTML

  • CSV

  • JSON

  • XML

Phase 3

Additional specialized formats can be added through isolated parser modules.

The architecture should not place format-specific logic directly inside the API route.

Instead:

Document API
     │
     ▼
Ingestion Service
     │
     ├── PDF Extractor
     ├── DOCX Extractor
     ├── TXT Extractor
     ├── HTML Extractor
     └── CSV Extractor

This makes future expansion easier.


41.6 Extraction Layer

The extraction layer converts binary documents into structured text.

A simple internal representation could be:

ExtractedDocument
 ├── documentId
 ├── title
 ├── pages
 │    ├── pageNumber
 │    ├── text
 │    └── metadata
 ├── sections
 └── metadata

For a PDF, preserving page boundaries is particularly useful because later citations can point to the relevant page.

Instead of storing only:

"The organization established..."

the system should preserve:

Document: annual-report.pdf
Page: 37
Section: Risk Management
Text: "The organization established..."

This greatly improves traceability.


41.7 OCR for Scanned Documents

Some PDFs contain images rather than selectable text.

The extraction system should detect this condition.

Conceptually:

PDF
 │
 ├── Text Layer Present → Text Extraction
 │
 └── No Useful Text → OCR Pipeline

OCR output should be treated as extracted data rather than authoritative truth.

OCR may introduce:

  • character errors,

  • missing punctuation,

  • incorrect tables,

  • incorrect line breaks,

  • incorrect reading order.

Therefore, the document metadata should record whether text originated from:

native extraction

or:

OCR

This information can later be used for quality assessment.


41.8 Text Normalization

Raw extraction frequently contains unnecessary formatting artifacts.

Examples include:

Multiple     spaces
Broken
line breaks
Page headers
Page footers

Normalization may include:

  • whitespace normalization,

  • line-break normalization,

  • Unicode normalization,

  • removal of repeated extraction artifacts,

  • preservation of meaningful headings,

  • preservation of page boundaries,

  • preservation of paragraph boundaries.

Normalization must not destroy information required for citations.

For example, removing all page boundaries would make later source attribution unnecessarily difficult.


41.9 Document Metadata

Every processed document should maintain metadata.

Recommended fields include:

documentId
fileId
projectId
ownerId
title
mimeType
fileSize
language
pageCount
processingStatus
processingVersion
extractionMethod
createdAt
updatedAt

Additional metadata may include:

sourceName
checksum
documentVersion
parserVersion
ocrUsed
embeddingModel
embeddingVersion

Metadata should be considered part of the document's security boundary.

A malicious or untrusted document should not be able to redefine authorization metadata.


41.10 Document Versioning

Documents change.

A user may upload:

policy-v1.pdf

and later replace it with:

policy-v2.pdf

The application should decide whether these represent:

  1. separate documents, or

  2. versions of the same logical document.

For enterprise-style systems, versioning is often preferable.

Conceptually:

Logical Document
      │
      ├── Version 1
      ├── Version 2
      └── Version 3

Only the active version should normally participate in default retrieval.

Older versions can remain available for historical queries if explicitly requested.


41.11 Chunking

Large documents must be divided into smaller retrieval units called chunks.

A chunk is not simply an arbitrary substring.

A good chunk should ideally preserve a coherent piece of meaning.

For example:

Chapter
   ↓
Section
   ↓
Paragraph Group
   ↓
Chunk

The goal is to make each retrieved unit:

  • understandable,

  • sufficiently self-contained,

  • small enough for efficient retrieval,

  • large enough to preserve context.


41.12 Fixed-Size Chunking

The simplest approach is fixed-size chunking.

For example:

Chunk size = approximately N tokens
Overlap = approximately M tokens

Conceptually:

Document:
[A B C D E F G H I J]

Chunk 1:
[A B C D]

Chunk 2:
[D E F G]

Chunk 3:
[G H I J]

Overlap helps prevent important information from being split exactly at a boundary.

However, fixed-size chunking can separate:

  • headings from paragraphs,

  • questions from answers,

  • table labels from values,

  • definitions from explanations.

Therefore, fixed-size chunking is useful as a baseline, not necessarily the final strategy.


41.13 Structure-Aware Chunking

A stronger strategy respects document structure.

For example:

Section 4
   │
   ├── Paragraph 1
   ├── Paragraph 2
   └── Paragraph 3

can become:

Chunk:
Section 4
Paragraph 1
Paragraph 2
Paragraph 3

This gives the embedding model more meaningful context.

The chunk metadata should preserve:

documentId
chunkIndex
sectionPath
pageNumber
startOffset
endOffset
tokenCount

41.14 Semantic Chunking

Semantic chunking attempts to identify natural topic boundaries.

For example:

Introduction
     ↓
Methodology
     ↓
Results
     ↓
Discussion
     ↓
Conclusion

Each topic can be processed as a coherent retrieval unit.

Semantic chunking may improve retrieval quality, but it also increases implementation complexity.

Therefore, a practical development path is:

Version 1 → structure-aware chunking
Version 2 → improved semantic segmentation
Version 3 → adaptive chunking based on document type

41.15 Chunk Metadata Is Critical

The chunk content alone is not enough.

Each chunk should retain enough information to reconstruct its origin.

Example:

{
  "documentId": "doc_123",
  "chunkIndex": 18,
  "pageNumber": 7,
  "sectionPath": ["Security", "Access Control"],
  "tokenCount": 420
}

This allows the system to answer:

Where did this information come from?

That question is essential for trustworthy AI.


41.16 Embeddings

An embedding converts text into a numerical vector representing semantic characteristics of that text.

Conceptually:

Text
 ↓
Embedding Model
 ↓
[0.021, -0.183, 0.442, ...]

The exact numerical representation depends on the selected embedding model.

The architecture should therefore use an abstraction:

EmbeddingProvider

rather than hard-coding a particular provider.

Conceptually:

EmbeddingService
      │
      ├── Provider A
      ├── Provider B
      └── Local Provider

This allows the system to change models later without rewriting the entire retrieval layer.


41.17 Embedding Versioning

Embedding models can change.

If the system originally indexed documents using:

embedding-model-v1

and later moves to:

embedding-model-v2

the existing vectors may no longer be directly comparable.

Therefore, store:

embeddingModel
embeddingVersion
embeddingDimensions

with the vector index metadata.

A model migration can then follow:

Existing Chunks
      ↓
Generate New Embeddings
      ↓
Build New Index
      ↓
Evaluate
      ↓
Switch Active Index

This prevents uncontrolled index migrations.


41.18 Vector Storage

A vector store maps:

chunk → embedding

A conceptual record looks like:

VectorRecord
 ├── id
 ├── chunkId
 ├── embedding
 ├── model
 ├── dimensions
 └── metadata

The system can use:

  • a PostgreSQL vector extension,

  • a dedicated vector database,

  • or another vector-capable storage layer.

The application should hide this implementation behind a repository interface.

For example:

VectorRepository
 ├── insert()
 ├── delete()
 ├── search()
 └── replaceIndex()

The rest of the application should not need to know which vector engine is being used.


41.19 Similarity Search

When a user asks a question, the query can also be embedded.

Conceptually:

User Question
      ↓
Query Embedding
      ↓
Vector Search
      ↓
Candidate Chunks

The system then ranks chunks according to semantic similarity.

However, semantic similarity alone is not sufficient.

A highly similar chunk may belong to another project or another user.

Therefore:

Authorization filtering must occur as part of retrieval, not after retrieval.


41.20 Permission-Aware Retrieval

Suppose the database contains:

Project A
Project B
Project C

The current user only has access to Project B.

A vector search must not retrieve:

Project A chunk
Project C chunk

and then attempt to remove them later.

The preferred model is:

User
 ↓
Authorized Projects
 ↓
Retrieval Filter
 ↓
Vector Search
 ↓
Allowed Candidates

This is a fundamental multi-tenant security principle.


41.21 Hybrid Retrieval

Vector similarity is useful, but lexical search can be better for:

  • exact names,

  • identifiers,

  • product codes,

  • legal clauses,

  • dates,

  • unusual terminology.

A robust system can combine:

Vector Search
      +
Keyword Search
      ↓
Candidate Set
      ↓
Reranking

This is commonly called hybrid retrieval.

The exact weighting should be configurable and evaluated empirically.


41.22 Reranking

The initial retrieval stage may return:

Top 20 candidates

A reranking stage can evaluate those candidates more precisely and select:

Top 5 candidates

Conceptually:

Query
 ↓
Candidate Retrieval
 ↓
Reranker
 ↓
Best Evidence

This can improve answer quality without requiring the expensive ranking model to process the entire document collection.


41.23 Retrieval-Augmented Generation

The final RAG architecture is:

User Question
      │
      ▼
Authorization
      │
      ▼
Query Processing
      │
      ▼
Retrieval
      │
      ▼
Reranking
      │
      ▼
Context Selection
      │
      ▼
Language Model
      │
      ▼
Answer + Citations

The model should not be presented with arbitrary unrelated data.

The application should construct a controlled context window.


41.24 Context Assembly

Suppose retrieval produces five relevant chunks.

The system may assemble:

SOURCE 1
Document: Security Policy
Page: 12
Section: Authentication

[retrieved content]

SOURCE 2
Document: Security Policy
Page: 14
Section: Sessions

[retrieved content]

The model then receives these as evidence.

The context builder should enforce:

  • maximum number of chunks,

  • token budget,

  • duplicate removal,

  • relevance threshold,

  • source diversity where appropriate,

  • authorization constraints.


41.25 Citations and Traceability

A trustworthy RAG system should retain a relationship between:

Answer
 ↓
Retrieved Chunk
 ↓
Document
 ↓
File
 ↓
Original Storage Object

This enables users to inspect the source.

For example:

Answer statement
   ↓
Document: Security Policy
   ↓
Page: 14
   ↓
Section: Session Management

This is significantly more useful than simply saying:

"According to the documents..."

41.26 RAG Does Not Guarantee Truth

Retrieval improves grounding, but it does not guarantee correctness.

Potential failures include:

  • incorrect extraction,

  • poor chunk boundaries,

  • irrelevant retrieval,

  • outdated documents,

  • contradictory documents,

  • model misunderstanding,

  • unsupported inference.

Therefore, the system should distinguish between:

Retrieved evidence

and:

Generated interpretation

Evaluation should measure both retrieval quality and answer quality.


41.27 Documents Must Be Treated as Untrusted Data

This is one of the most important security requirements.

A document may contain text such as:

Ignore previous instructions...

or other content that attempts to influence an AI system.

The retrieval system must treat that content as data, not as privileged instructions.

The architectural rule is:

System Policy
      ↓
Developer Policy
      ↓
User Request
      ↓
Retrieved Documents = Untrusted Evidence

Retrieved content must never automatically gain permission to:

  • change system policies,

  • modify access controls,

  • reveal secrets,

  • execute tools,

  • change agent permissions,

  • override security rules.

This separation is especially important when RAG is later connected to autonomous agents.


41.28 Prompt Injection Through Retrieved Documents

A document can be intentionally or accidentally written in a way that attempts to manipulate the model.

Therefore, the RAG layer should establish a strong conceptual boundary:

INSTRUCTIONS

versus:

EVIDENCE

The model may use evidence to answer the question, but evidence should not become a new authority layer.

For example:

Question:
"What does the policy say about password rotation?"

Retrieved document:
"...passwords must be changed every 90 days..."

The model should extract the relevant policy statement.

If the document also contains unrelated text attempting to control the AI, that text should remain untrusted document content.


41.29 Memory and Documents Are Different

The system may eventually support both:

Long-Term Memory

and:

Document Knowledge

They should not be treated as identical.

Documents are external evidence.

Memory represents retained application context.

A useful architecture is:

User Question
     │
     ├── Document Retrieval
     │
     ├── Memory Retrieval
     │
     └── Conversation Context
             │
             ▼
        Context Manager
             │
             ▼
        Model Response

Each source should retain provenance.


41.30 Background Processing

Document ingestion should normally run asynchronously.

The upload request should not remain open while a large document is:

  • parsed,

  • OCR processed,

  • chunked,

  • embedded,

  • indexed.

Instead:

Upload API
   ↓
Create Processing Job
   ↓
Return Job ID
   ↓
Worker Processes Document
   ↓
Update Status

The user interface can then display:

Processing document...

followed by:

Document ready

or:

Document processing failed

41.31 Idempotent Processing

The same processing job should not accidentally create duplicate chunks or duplicate vectors.

A useful strategy is to calculate a content checksum.

Conceptually:

File Bytes
   ↓
Checksum
   ↓
Document Version

If the same content is uploaded again, the system can determine whether processing can be reused.

Processing should also use unique constraints such as:

(documentId, chunkIndex)

to prevent accidental duplicate chunks.


41.32 Reprocessing

A document may need to be reprocessed when:

  • the extraction engine changes,

  • the chunking strategy changes,

  • the embedding model changes,

  • OCR quality improves,

  • a bug is fixed.

The architecture should support:

Reprocess Document

without manually reconstructing database records.

A reprocessing job can:

Load Original File
      ↓
Extract Again
      ↓
Create New Document Version
      ↓
Create New Chunks
      ↓
Generate New Embeddings
      ↓
Build New Index Records
      ↓
Activate New Version

41.33 Deletion Propagation

Deleting a document must remove its associated retrieval data.

Conceptually:

Delete Document
      │
      ├── Delete Chunks
      ├── Delete Embeddings
      ├── Remove Search Index Entries
      ├── Update Storage Metadata
      └── Record Audit Event

A document must not remain retrievable after its authorization has been revoked.

This is especially important for privacy and multi-tenant systems.


41.34 Database Extension

The database foundation introduced earlier can now be extended with document-specific structures.

Conceptually:

Document
 ├── id
 ├── fileId
 ├── projectId
 ├── ownerId
 ├── title
 ├── mimeType
 ├── status
 ├── version
 ├── extractionMethod
 ├── metadata
 ├── createdAt
 └── updatedAt

And:

DocumentChunk
 ├── id
 ├── documentId
 ├── chunkIndex
 ├── content
 ├── pageNumber
 ├── sectionPath
 ├── startOffset
 ├── endOffset
 ├── tokenCount
 ├── metadata
 └── createdAt

Vector records can be stored through the selected vector-storage abstraction.


41.35 Recommended Repository Interfaces

The application should expose interfaces similar to:

DocumentRepository
DocumentChunkRepository
EmbeddingRepository
VectorRepository
RetrievalRepository

Example responsibilities:

DocumentRepository
    create()
    findById()
    updateStatus()
    delete()
    createVersion()

DocumentChunkRepository
    createMany()
    findByDocument()
    deleteByDocument()

VectorRepository
    upsert()
    search()
    deleteByChunk()

This maintains the separation between business logic and storage implementation.


41.36 Chunking Service

The chunking system should be independent from the extraction service.

Architecture:

ExtractionService
       ↓
NormalizedDocument
       ↓
ChunkingService
       ↓
DocumentChunk[]

This makes it possible to test multiple chunking strategies against the same extracted document.


41.37 Embedding Service

The embedding service should expose a simple interface.

Conceptually:

embed(text)
embedBatch(text[])

The implementation can then select the configured embedding provider.

This avoids coupling application code to a particular AI vendor or model.


41.38 Retrieval Service

The retrieval service combines:

Authorization
Query Embedding
Vector Search
Keyword Search
Reranking
Context Selection

A conceptual interface:

retrieve({
    userId,
    projectId,
    query,
    limit
})

The result should include provenance:

RetrievalResult
 ├── chunkId
 ├── documentId
 ├── score
 ├── content
 ├── pageNumber
 └── sourceMetadata

41.39 Evaluation

A retrieval system must be measured rather than assumed to work.

Important retrieval metrics include:

Recall@K

How often the relevant evidence appears within the top K results.

Precision@K

How many retrieved results are actually relevant.

MRR

Mean Reciprocal Rank measures how highly the first relevant result appears.

nDCG

Useful when multiple results have different relevance levels.

For generation, additional evaluation can examine:

  • factual grounding,

  • citation correctness,

  • unsupported claims,

  • answer completeness,

  • refusal behavior,

  • latency,

  • token usage.


41.40 Test Dataset

A serious implementation should maintain a small evaluation dataset.

Example:

Question
Expected Document
Expected Section
Expected Page
Relevant Chunk
Expected Answer

For example:

Question:
"What is the session timeout?"

Expected source:
Security Policy

Expected section:
Session Management

Expected page:
14

This allows retrieval changes to be evaluated objectively.


41.41 Security Testing

The ingestion system should be tested against:

  • malformed files,

  • oversized files,

  • unsupported formats,

  • corrupted PDFs,

  • OCR errors,

  • duplicate uploads,

  • unauthorized project access,

  • deleted documents,

  • cross-project retrieval,

  • malicious document instructions,

  • metadata manipulation,

  • stale embeddings.

The goal is not simply:

Does the system retrieve information?

The stronger question is:

Does the system retrieve only information the current user is authorized to access?


41.42 Observability

Every ingestion job should have a traceable identifier.

For example:

ingestionJobId
documentId
fileId
projectId

Logs can then connect:

Upload
 ↓
Extraction
 ↓
Chunking
 ↓
Embedding
 ↓
Indexing

Useful measurements include:

extraction_duration
chunk_count
embedding_count
index_duration
failure_count
retrieval_latency
retrieval_result_count

Sensitive document content should not be unnecessarily written into logs.


41.43 Failure Handling

Possible failures include:

ExtractionFailed
OCRFailed
ChunkingFailed
EmbeddingFailed
IndexingFailed
AuthorizationFailed
StorageUnavailable

The system should distinguish between:

temporary failure

and:

permanent failure

Temporary failures can be retried.

Permanent failures should be surfaced safely to the user.


41.44 End-to-End Architecture

The complete architecture now becomes:

                    USER
                     │
                     ▼
               Upload API
                     │
                     ▼
             Authorization
                     │
                     ▼
              File Validation
                     │
                     ▼
              Object Storage
                     │
                     ▼
             Ingestion Queue
                     │
                     ▼
              Processing Worker
                     │
          ┌──────────┴──────────┐
          ▼                     ▼
     Text Extraction          OCR
          │                     │
          └──────────┬──────────┘
                     ▼
             Normalized Text
                     │
                     ▼
                 Chunking
                     │
                     ▼
             Document Chunks
                     │
                     ▼
               Embeddings
                     │
                     ▼
              Vector Storage
                     │
                     ▼
              Retrieval Layer
                     │
             ┌───────┴────────┐
             ▼                ▼
       Vector Search     Keyword Search
             │                │
             └───────┬────────┘
                     ▼
                  Rerank
                     │
                     ▼
              Context Builder
                     │
                     ▼
                AI Model
                     │
                     ▼
             Answer + Citations
                     │
                     ▼
                  Audit

41.45 Implementation Principles

The following principles should guide the implementation:

Principle 1 — Separate storage from retrieval

The original file, extracted text, chunks, and vectors have different responsibilities.

Principle 2 — Preserve provenance

Every chunk must know where it came from.

Principle 3 — Enforce authorization early

Do not retrieve unauthorized information and filter it afterward.

Principle 4 — Treat documents as untrusted data

Retrieved content must not become a privileged instruction source.

Principle 5 — Make processing asynchronous

Large documents should be handled by workers rather than blocking API requests.

Principle 6 — Version processing artifacts

Extraction, chunking, and embedding versions should be traceable.

Principle 7 — Make deletion complete

Deleting a document must propagate through storage, database, and retrieval indexes.

Principle 8 — Measure retrieval quality

RAG quality should be evaluated using a repeatable dataset rather than subjective testing alone.


41.46 Chapter Summary

This chapter established the foundation for document intelligence and Retrieval-Augmented Generation.

The system now has a complete conceptual lifecycle:

Upload → Validate → Store → Extract → Normalize → Chunk → Embed → Index → Retrieve → Rerank → Generate → Cite → Audit

The architecture separates:

Original Files
      ↓
Document Metadata
      ↓
Extracted Content
      ↓
Chunks
      ↓
Embeddings
      ↓
Vector Index
      ↓
Retrieved Evidence
      ↓
AI Response

Most importantly, the architecture introduces three critical boundaries:

  1. Storage boundary — large files remain in object storage.

  2. Authorization boundary — retrieval is constrained by user/project permissions.

  3. Instruction boundary — retrieved documents remain untrusted evidence rather than privileged instructions.

These foundations prepare the system for the next major subsystem: AI model orchestration, provider abstraction, model routing, prompt construction, token management, fallback handling, and secure AI inference.

END OF CHAPTER 41

Implementation snippet — basic chunking service

export type TextChunk = {
  index: number;
  content: string;
};

export function chunkText(
  text: string,
  maxCharacters = 1800,
  overlap = 200
): TextChunk[] {
  const normalized = text.replace(/\s+/g, " ").trim();

  if (!normalized) return [];

  const chunks: TextChunk[] = [];
  let start = 0;
  let index = 0;

  while (start < normalized.length) {
    const end = Math.min(start + maxCharacters, normalized.length);

    chunks.push({
      index,
      content: normalized.slice(start, end).trim(),
    });

    if (end === normalized.length) break;

    start = Math.max(end - overlap, start + 1);
    index++;
  }

  return chunks;
}

Implementation snippet — retrieval contract

export type RetrievalQuery = {
  userId: string;
  projectId: string;
  query: string;
  limit?: number;
};

export type RetrievalResult = {
  chunkId: string;
  documentId: string;
  content: string;
  score: number;
  pageNumber?: number;
  sectionPath?: string[];
};

export interface RetrievalRepository {
  search(query: RetrievalQuery): Promise<RetrievalResult[]>;
}

Implementation snippet — safe RAG flow

export async function answerWithRag(input: RetrievalQuery) {
  // 1. Authenticate the user.
  // 2. Verify project membership.
  // 3. Retrieve only authorized chunks.
  const results = await retrievalRepository.search(input);

  // 4. Build evidence context.
  const context = results
    .map(
      (item) =>
        `SOURCE: ${item.documentId}\n` +
        `PAGE: ${item.pageNumber ?? "unknown"}\n` +
        `CONTENT:\n${item.content}`
    )
    .join("\n\n");

  // 5. Send the evidence to the model as untrusted source material.
  return generateAnswer({
    question: input.query,
    context,
  });
}

Comments

Popular posts from this blog

Adaptive Cognitive AI (ACAI): Chapter 1 — Introduction & System Vision

ACAI — Chapter 27: Database + Authentication + Real User Accounts + Persistent Conversations

Chapter 2 (Part 2) Knowledge Retrieval Engine