Case 1. Internal corporate assistant for regulations and policies

A pure PHP RAG example for answering employee questions from approved internal documents

In this case, we build a simple corporate knowledge assistant with chunking, embeddings, retrieval, access filtering, and controlled context building before answer generation.

 
<?php

include 'code-en.php';

$userRole 'employee';
$queryText 'How many days do we have to report a data leak?';
$topK 3;

$chunks splitIntoChunks($documents1);
$chunksById = [];
$chunkEmbeddings = [];

foreach (
$chunks as $chunk) {
    
$chunkId = (int)$chunk['id'];
    
$chunksById[$chunkId] = $chunk;
    
$chunkEmbeddings[$chunkId] = embedChunkText((string)$chunk['content']);
}

$queryEmbedding embedChunkText($queryText);
$scores = [];
foreach (
$chunkEmbeddings as $chunkId => $vector) {
    
$scores[$chunkId] = cosineSimilarity($queryEmbedding$vector);
}

arsort($scores);
$rankedChunks = [];
foreach (
$scores as $chunkId => $score) {
    
$chunk $chunksById[$chunkId];

    
$rankedChunks[] = [
        
'chunk_id'         => $chunkId,
        
'score'            => $score,
        
'document'         => $chunk['document'],
        
'section'          => $chunk['section'],
        
'access'           => $chunk['access'],
        
'allowed_for_user' => canUserAccessChunk($userRole, (string)$chunk['access'], $roleToScopes),
        
'content'          => $chunk['content'],
    ];
}

$topRetrievedRows array_slice($rankedChunks0$topK);
$contextChunks = [];
foreach (
$topRetrievedRows as $row) {
    if (
$row['allowed_for_user']) {
        
$contextChunks[] = $chunksById[(int)$row['chunk_id']];
    }
}

$contextBlocks = [];
foreach (
$contextChunks as $chunk) {
    
$contextBlocks[] = '[' $chunk['document'] . ', section ' $chunk['section'] . "]\n" $chunk['content'];
}

$contextText implode("\n\n"$contextBlocks);

$systemInstruction 'Use only approved context chunks. Do not invent facts. If context is missing, refuse to answer and say what source is required.';
$answerPayload buildAnswerFromContext($queryText$contextChunks);


echo 
'Case goal:' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
'Build a simple corporate RAG assistant in pure PHP for questions over approved internal policies.' PHP_EOL;
echo 
PHP_EOL;

echo 
'Scenario:' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
'Question: ' $queryText PHP_EOL;
echo 
'User role: ' $userRole PHP_EOL;
echo 
PHP_EOL;

echo 
'Stage 1. Chunking:' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
array_to_matrix($chunkswithHeaderstruewithPaddingtruewithCommasfalseshowRowNumberstrue);
echo 
PHP_EOL PHP_EOL;

echo 
'Stage 2. Chunk embeddings:' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
array_to_matrix($chunkEmbeddingsshowRowNumberstrue);
echo 
PHP_EOL PHP_EOL;

echo 
'Stage 3. Retrieval (cosine similarity, Top-K=' $topK '):' PHP_EOL;
echo 
'-----------' PHP_EOL;
foreach (
$topRetrievedRows as $row) {
    
$score number_format((float) $row['score'], 6'.''');
    
$access $row['allowed_for_user'] ? 'allowed' 'blocked';

    echo 
'chunk_' $row['chunk_id'] . ' | score=' $score ' | ' $row['document'] . ' | access=' $access PHP_EOL;
}
echo 
PHP_EOL;

echo 
'Optional stage. Access filtering:' PHP_EOL;
echo 
'-----------' PHP_EOL;
foreach (
$topRetrievedRows as $row) {
    if (
$row['allowed_for_user']) {
        continue;
    }

    echo 
'Excluded chunk_' $row['chunk_id'] . ' (' $row['document'] . ') due to access policy.' PHP_EOL;
}
echo 
PHP_EOL;

echo 
'Stage 4. Controlled context building:' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
'Instruction:' PHP_EOL;
echo 
$systemInstruction PHP_EOL PHP_EOL;
echo 
'Context:' PHP_EOL;
echo 
$contextText PHP_EOL PHP_EOL;

echo 
'Stage 5. Answer generation:' PHP_EOL;
echo 
'-----------' PHP_EOL;
echo 
'Answer: ' $answerPayload['answer'] . PHP_EOL;
echo 
'Source: ' $answerPayload['source'] . PHP_EOL;
Result: Memory: 0.033 Mb Time running: 0.001 sec.
Case goal:
-----------
Build a simple corporate RAG assistant in pure PHP for questions over approved internal policies.

Scenario:
-----------
Question: How many days do we have to report a data leak?
User role: employee

Stage 1. Chunking:
-----------
#: [id document_id document                section access content                                                                                         ]
1: [1  1           HR Policy v3            4.2     all    Remote work from another country is possible only after approval from HR and the direct manager.]
2: [2  1           HR Policy v3            4.2     all    The request must be submitted before travel and include the planned location and period.        ]
3: [3  2           Security Policy v2      2.1     all    Security incidents must be reported within 24 hours after discovery.                            ]
4: [4  2           Security Policy v2      2.1     all    The report must include incident type, affected systems, and initial mitigation steps.          ]
5: [5  3           Legal Incident Playbook 7.3     legal  Notification to external legal parties must be prepared within 72 hours after data leakage.     ]
6: [6  3           Legal Incident Playbook 7.3     legal  All communication drafts require legal department approval before sending.                      ]

Stage 2. Chunk embeddings:
-----------
1: [1.001, 1.001, 1.001, 0.001, 0.001, 0.001, 0.48]
2: [0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.44]
3: [0.001, 0.001, 0.001, 1.001, 1.001, 1.001, 0.34]
4: [0.001, 0.001, 0.001, 1.001, 1.001, 0.001, 0.43]
5: [0.001, 0.001, 0.001, 1.001, 0.001, 1.001, 0.455]
6: [0.001, 0.001, 1.001, 0.001, 0.001, 0.001, 0.37]

Stage 3. Retrieval (cosine similarity, Top-K=3):
-----------
chunk_3 | score=0.998264 | Security Policy v2 | access=allowed
chunk_4 | score=0.813595 | Security Policy v2 | access=allowed
chunk_5 | score=0.811772 | Legal Incident Playbook | access=blocked

Optional stage. Access filtering:
-----------
Excluded chunk_5 (Legal Incident Playbook) due to access policy.

Stage 4. Controlled context building:
-----------
Instruction:
Use only approved context chunks. Do not invent facts. If context is missing, refuse to answer and say what source is required.

Context:
[Security Policy v2, section 2.1]
Security incidents must be reported within 24 hours after discovery.

[Security Policy v2, section 2.1]
The report must include incident type, affected systems, and initial mitigation steps.

Stage 5. Answer generation:
-----------
Answer: According to Security Policy v2, incidents must be reported within 24 hours after discovery.
Source: Security Policy v2, section 2.1