Minimal RAG in PHP

A simplified Retrieval-Augmented Generation example without an external vector DB

A minimal educational RAG pipeline in pure PHP: keep precomputed document embeddings in arrays, score them with cosine similarity, retrieve Top-K documents, build context, and pass this context to an LLM API.

 
<?php

include 'code-en.php';

echo 
'Embeddings storage:' PHP_EOL;
echo 
'-----------' PHP_EOL;
print_r($documents);
print_r($embeddings);
echo 
PHP_EOL;

echo 
'Query text:' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
$queryText PHP_EOL;
echo 
PHP_EOL;

echo 
'Cosine similarity:' PHP_EOL;
echo 
'-----------' PHP_EOL;
arsort($scores);
$topIds array_slice(array_keys($scores), 01);
foreach (
$scores as $id => $score) {
    echo 
'doc_' $id ' => ' number_format($score6'.''') . PHP_EOL;
}
echo 
PHP_EOL;

echo 
'Top-K search (k=1):' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
implode(', 'array_map(static fn ($id): string => (string) $id$topIds)) . PHP_EOL PHP_EOL;

echo 
'Context:' PHP_EOL;
echo 
'-----------' PHP_EOL;
$context '';
foreach (
$topIds as $id) {
    
$context .= $documents[$id 1]['text'] . "\n";
}
echo 
$context;
echo 
PHP_EOL;

echo 
'This context is then sent to an LLM API.' PHP_EOL;
Result: Memory: 0.006 Mb Time running: 0.001 sec.
Embeddings storage:
-----------
Array
(
    [0] => Array
        (
            [id] => 1
            [text] => Contract termination is possible by agreement of the parties
        )

    [1] => Array
        (
            [id] => 2
            [text] => The contract may be terminated unilaterally
        )

)
Array
(
    [1] => Array
        (
            [0] => 0.12
            [1] => 0.88
            [2] => 0.44
        )

    [2] => Array
        (
            [0] => 0.1
            [1] => 0.9
            [2] => 0.4
        )

)

Query text:
-----------
Is it possible to terminate a contract unilaterally?

Cosine similarity:
-----------
doc_1 => 0.999695
doc_2 => 0.999694

Top-K search (k=1):
-----------
1

Context:
-----------
Contract termination is possible by agreement of the parties

This context is then sent to an LLM API.