Litterae.eu
Humanities & IT


Introducing our PRRS: a minimalist PHP-Based raw RAG system

Abstract
In the rapidly evolving landscape of Artificial Intelligence, Retrieval-Augmented Generation (RAG) has emerged as a critical architecture for grounding Large Language Models (LLMs) in external, verifiable data. While the current ecosystem is dominated by Python-centric frameworks and complex vector databases, there is a significant pedagogical and practical value in implementing these systems from first principles.
This article introduces the PHP Raw RAG System (shortly, PRRS), a lightweight framework designed to bridge the gap between traditional web development and modern AI workflows. By utilising classic Information Retrieval (IR) techniques like TF-IDF and Cosine Similarity, PRRS offers a transparent look under the hood of context-aware text generation.

Premise: The Case for a Native PHP RAG
The utility of RAG stems from its ability to mitigate the inherent limitations of LLMs, specifically their knowledge cutoff dates and the tendency to hallucinate when asked about niche or private datasets. By injecting relevant document snippets into the prompt, RAG ensures the model operates on updated, factual information.
However, the PHP community — despite powering a vast portion of the web — often finds itself sidelined in the AI discourse, which favours Python’s extensive library ecosystem. Developing a RAG tool from scratch in PHP serves two purposes:
1. accessibility: it provides PHP developers with a native way to integrate AI without maintaining a secondary Python micro-service.
2. pedagogy: building a raw system strips away the abstraction layers of high-level libraries, forcing the developer to understand the mathematical mechanics of vector space models and document indexing.

Methodology and Approach
PRRS eschews neural embeddings in favour of a classical Bag-of-Words (BoW) and Term Frequency-Inverse Document Frequency (TF-IDF) plus keywords matching approach. While modern models use dense vectors (embeddings) to capture semantics, the TF-IDF method uses sparse vectors to capture lexical importance, and the keyword matching pinpoints relevant passages. In this model, the vocabulary of the corpus defines the dimensions of our vector space, providing a mathematically rigorous yet computationally accessible way to measure document relevance.

System Architecture and Procedure
The implementation follows a structured pipeline to transform raw text into a searchable mathematical index:
1. pre-processing and normalisation: The first step involves defining a list of stop-words (common terms like the, is, or and) which carry little semantic value. The corpus is then cleaned — converting text to lowercase and removing punctuation — to ensure that Example and example are treated as the same token.
2. vocabulary extraction and chunking: a global vocabulary is extracted by identifying the N most frequent terms across the corpus, excluding stop-words — this means the vocabulary uses real words as tokens. To ensure the LLM receives manageable context windows, the documents are split into chunks of a fixed word count.
3. vectorisation via TF-IDF: Each chunk is converted into a vector where each dimension corresponds to a word in the vocabulary. The value of each dimension is calculated using the TF-IDF formula, where:
a. TF (Term Frequency) tells how many times a word appears in a chunk, and is calculated as: Count of word / Total words in chunk.
b. IDF (Inverse Document Frequency) tells how rare a word is across all chunks, and is calculated as: Log (Total chunks / Chunks with the word).
c. TF-IDF is calculated as TF × IDF.
These vectors, along with their corresponding text chunks, are then persisted in a .csv file or a lightweight SQLite database.

Operational Workflow: The Retrieval Phase
When a user submits a prompt and a keyword, the system executes a four-step retrieval process:
1. prompt vectorisation: The user’s query is normalised and converted into a vector using the same vocabulary and IDF weights used during the indexing phase.
2. similarity measurement: PRRS calculates the Cosine Similarity between the prompt vector and every stored chunk vector. To super-simplify, the cosine similarity can be seen almost as the angular proximity between two vectors; the higher it is the closer they are.
3. keyword matching: PRRS compares the key phrase with every single text chunk on the basis of a direct lexical correspondence alone.
4. context injection: The N chunks with the highest similarity scores and the best keyword matching are retrieved and pre-pended to the user's prompt as Context. This enriched prompt is then sent to the LLM API.

Conclusion
PRRS is admittedly a simplified architecture. It lacks the semantic nuance of transformer-based embeddings (such as BERT or Ada), which can understand synonyms that do not share common words. However, for many domain-specific applications where keyword precision is paramount, PRRS yields surprisingly appreciable results even on large raw corpora.
More importantly, it serves as an invaluable diagnostic tool for developers, demystifying the black box of AI and demonstrating that the core principles of RAG are rooted in foundational computer science and linear algebra rather than mere magic.
For the PHP developer, it represents a robust starting point for sovereign, local-first AI integration.

The verdict?
PRRS is an elegant, hacker-spirit project. It’s the perfect antidote to the just plug in an API culture, providing a deep, functional understanding of how we ground AI in data.
And understanding, when using AI, is the real key magic word.

Puoi leggere questo articolo anche in italiano.

Last updated: 12 April 2026


Site designed by litterae.eu. © 2004-2026. All rights reserved.
Info GDPR EU 2016/679: no cookies used, no personal data collected.
p.iva / vat number: 02757940206