PHP Classes

How to use a PHP RAG AI Library to Improve a Chatbot Application Using the Package PHP Nano RAG: Learn and ask questions using AI with RAG

Recommend this page to a friend!
     
  Info   Example   View files Files   Install with Composer Install with Composer   Download Download   Reputation   Support forum   Blog    
Last Updated Ratings Unique User Downloads Download Rankings
2025-12-17 (2 days ago) RSS 2.0 feedNot yet rated by the usersTotal: Not yet counted Not yet ranked
Version License PHP version Categories
php-nano-rag 1MIT/X Consortium ...8Databases, Chat, Artificial intelligence, P...
Description 

Author

This package implements an application that can learn and let users ask questions using artificial intelligence improved using Retrieval-Augmented Generation (RAG).

It provides a Web application that lets users ask questions using chat prompts and answers using Ollama artificial client improved with knowledge also provided by the users.

The knowledge database uses files with data stored in the JSON format.

The application also allows users:

- Clear the knowledge database

- Clear the user chat session

- Upload a new knowledge database file

In Portuguese:

Este componente pode servir para criar um sistema de recomendação de produtos ou um chatbot inteligente no seu site PHP sem instalar nada no servidor.

Nano RAG é uma biblioteca PHP de código aberto que implementa uma arquitetura de Geração Aumentada por Recuperação (RAG - Retrieval-Augmented Generation) utilizando puramente PHP e armazenamento em arquivos locais (JSON).

O projeto foi desenhado para ambientes onde bancos de dados vetoriais complexos (como Pinecone ou Milvus) não estão disponíveis.

Picture of Rodrigo Faustino
  Performance   Level  
Name: Rodrigo Faustino <contact>
Classes: 43 packages by
Country: Brazil Brazil
Age: 42
All time rank: 2330158 in Brazil Brazil
Week rank: 1 Up
Innovation award
Innovation award
Nominee: 25x

Winner: 6x

Instructions

Example

<?php
require_once __DIR__ . '/vendor/autoload.php';

use
NanoRag\LlmClient\OllamaClient;
use
NanoRag\VectorDb\Memory;
use
NanoRag\RagEngine\ShortTermMemory;
use
NanoRag\RagEngine\Brain;

set_time_limit(300);

$dbFile = 'knowledge_base.json';

$llm = new OllamaClient(embedModel: 'nomic-embed-text', chatModel: 'llama3.2');
$longTerm = new Memory($dbFile);
$shortTerm = new ShortTermMemory();
$brain = new Brain($llm, $longTerm, $shortTerm);

$message = '';
$answer = '';

if (isset(
$_POST['action'])) {
    if (
$_POST['action'] === 'clear_db') {
        if (
file_exists($dbFile)) unlink($dbFile);
       
$message = '<div class="alert alert-danger">Memória de Longo Prazo (Arquivos) apagada.</div>';
       
header("Refresh:1; url=index.php");
    }
    if (
$_POST['action'] === 'clear_chat') {
       
$shortTerm->clear(); // Limpa apenas a sessão
       
$message = '<div class="alert alert-info">Memória de Curto Prazo (Chat) reiniciada.</div>';
    }
}

if (isset(
$_FILES['txt_file']) && $_FILES['txt_file']['error'] === UPLOAD_ERR_OK) {

   
$content = file_get_contents($_FILES['txt_file']['tmp_name']);
   
$chunks = preg_split('/\n\s*\n/', $content);
    foreach (
$chunks as $chunk) {
        if (
strlen(trim($chunk)) > 20) {
           
$brain->learn($chunk, ['source' => $_FILES['txt_file']['name']]);
        }
    }
   
$message = '<div class="alert alert-success">Arquivo aprendido!</div>';
}

if (isset(
$_POST['question']) && !empty($_POST['question'])) {
   
$answer = $brain->ask($_POST['question']);
}

$chatHistory = $shortTerm->getFullHistory();
?>

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Nano RAG - Agente Conversacional</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .chat-container { height: 500px; overflow-y: auto; background: #f8f9fa; padding: 20px; border: 1px solid #ddd; border-radius: 8px; }
        .msg { margin-bottom: 15px; padding: 10px 15px; border-radius: 15px; max-width: 80%; }
        .msg-user { background-color: #0d6efd; color: white; margin-left: auto; text-align: right; border-bottom-right-radius: 2px; }
        .msg-assistant { background-color: #e9ecef; color: #333; margin-right: auto; text-align: left; border-bottom-left-radius: 2px; }
        .source-tag { font-size: 0.7em; color: #ccc; display: block; margin-top: 5px; }
#rag-loader-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(10, 25, 47, 0.85);
    backdrop-filter: blur(5px);
    z-index: 9999;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}

.neural-orbit-loader {
    position: absolute;
    top: 28%;
    left: 45%;
    width: 120px;
    height: 120px;
}

.brain-core {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 40px;
    height: 40px;
    background: radial-gradient(circle, #00f2fe 0%, #4facfe 100%);
    border-radius: 50%;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 30px #00f2fe, 0 0 50px #4facfe;
    animation: corePulse 2s ease-in-out infinite;
}

.orbit-ring {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 2px solid rgba(0, 242, 254, 0.1);
    animation: ringRotate 3s linear infinite;
}

.data-node {
    position: absolute;
    width: 15px;
    height: 15px;
    background: #a855f7;
    border-radius: 50%;
    box-shadow: 0 0 15px #a855f7;
}
.node-1 { top: 0; left: 50%; transform: translate(-50%, -50%); }
.node-2 { bottom: 0; left: 50%; transform: translate(-50%, 50%); background: #ff0080; box-shadow: 0 0 15px #ff0080; } /* Rosa */
.node-3 { left: 0; top: 50%; transform: translate(-50%, -50%); }
.loading-text {
    position: absolute;
    top: 18%;
    left: 43%;
    margin-top: 30px;
    color: #fff;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    font-weight: 300;
    letter-spacing: 2px;
    animation: textFade 2s ease-in-out infinite;
}
@keyframes corePulse {
    0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
    50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.8; }
}

@keyframes ringRotate {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
@keyframes textFade {
    0%, 100% { opacity: 0.7; }
    50% { opacity: 1; }
}
    </style>
</head>

<body class="p-4">


<div class="container">
    <div class="row">
        <div class="col-md-4">
            <h3>? Nano Brain</h3>
            <div class="card mb-3">
                <div class="card-body">
                    <h6>Status da Memória</h6>
                    <ul>
                        <li><strong>Longo Prazo:</strong> <?php echo $brain->getLongTermMemorySize(); ?> vetores</li>
                        <li><strong>Curto Prazo:</strong> <?php echo $brain->getShortTermMemoryCount(); ?> mensagens</li>
                    </ul>
                </div>
            </div>

            <form method="post" enctype="multipart/form-data" class="mb-3">
                <label>Adicionar Conhecimento (.txt)</label>
                <input type="file" name="txt_file" class="form-control mb-2" required>
                <button type="submit" class="btn btn-sm btn-primary w-100">Ensinar</button>
            </form>

            <hr>
           
            <form method="post" class="d-flex gap-2">
                <button type="submit" name="action" value="clear_chat" class="btn btn-sm btn-outline-secondary flex-fill">Limpar Chat</button>
                <button type="submit" name="action" value="clear_db" class="btn btn-sm btn-outline-danger flex-fill">Apagar Arquivos</button>
            </form>
            <?php echo $message; ?>
</div>

        <div class="col-md-8">
            <div class="chat-container mb-3" id="chatBox">
                <?php if (empty($chatHistory)): ?>
<p class="text-center text-muted mt-5">Inicie a conversa...</p>
                <?php else: ?>
<?php foreach ($chatHistory as $msg): ?>
<div class="msg msg-<?php echo $msg['role']; ?>">
                            <strong><?php echo $msg['role'] === 'user' ? 'Você' : 'Nano AI'; ?>:</strong><br>
                            <?php echo nl2br(htmlspecialchars($msg['content'])); ?>
</div>
                    <?php endforeach; ?>
<?php endif; ?>
</div>

            <form method="post">
                <div class="input-group">
                    <input type="text" name="question" class="form-control" placeholder="Pergunte algo ou peça um resumo..." autofocus>
                    <button class="btn btn-success">Enviar</button>
                </div>
            </form>
        </div>
    </div>
</div>
<div id="rag-loader-overlay">
    <div class="neural-orbit-loader">
        <div class="brain-core"></div>
        <div class="orbit-ring">
            <div class="data-node node-1"></div>
            <div class="data-node node-2"></div>
            <div class="data-node node-3"></div>
        </div>
    </div>
    <div class="loading-text">PROCESSANDO RAG...</div>
</div>
<script>
  
    var chatBox = document.getElementById("chatBox");
    if(chatBox) {
        chatBox.scrollTop = chatBox.scrollHeight;
    }
    const loader = document.getElementById('rag-loader-overlay');
    const loadingText = loader.querySelector('.loading-text');

    function showLoader(text) {
        loadingText.innerText = text;
        loader.style.display = 'flex';
    }

    const uploadForm = document.querySelector('form[enctype="multipart/form-data"]');
    if (uploadForm) {
        uploadForm.addEventListener('submit', function() {
            showLoader('ASSIMILANDO CONHECIMENTO...');
        });
    }

    const questionInput = document.querySelector('input[name="question"]');
    if (questionInput) {
        const chatForm = questionInput.closest('form');
        if (chatForm) {
            chatForm.addEventListener('submit', function() {
                if (questionInput.value.trim() !== '') {
                    showLoader('ACESSANDO MEMÓRIA & GERANDO RESPOSTA...');
                }
            });
        }
    }
   
    const clearForms = document.querySelectorAll('form:not([enctype])');
    clearForms.forEach(form => {
        form.addEventListener('submit', function(e) {
            if (e.submitter && e.submitter.name === 'action') {
                 showLoader('LIMPANDO DADOS...');
            }
        });
    })
setTimeout(() => {
    loader.style.display = 'none';
}, 2000);
</script>
</body>
</html>


Details

Nano RAG for PHP

Nano RAG é uma biblioteca PHP de código aberto que implementa uma arquitetura de Geração Aumentada por Recuperação (RAG - Retrieval-Augmented Generation) utilizando puramente PHP e armazenamento em arquivos locais (JSON).

O projeto foi desenhado para ambientes onde bancos de dados vetoriais complexos (como Pinecone ou Milvus) não estão disponíveis, permitindo a criação de Agentes de IA com memória persistente e contextual em servidores de hospedagem compartilhada.

Parte 1: Guia de Instalação e Uso

Pré-requisitos do Sistema

  1. PHP 8.2 ou superior.
  2. Composer para gerenciamento de dependências.
  3. Ollama rodando localmente ou em um servidor acessível via rede.

Configuração do Ollama

O Nano RAG depende do Ollama para processamento de linguagem natural. Você precisa instalar o servidor e dois modelos específicos: um para gerar vetores (Embeddings) e outro para o chat (LLM).

  1. Baixe e instale o Ollama em ollama.com.
  2. Abra seu terminal e execute os seguintes comandos para baixar os modelos necessários:

    ollama pull nomic-embed-text ollama pull llama3.2

Nota: Você pode utilizar outros modelos, mas deve atualizar a configuração na instanciação da classe OllamaClient.

Instalação da Biblioteca

Na raiz do seu projeto, execute a instalação das dependências (atualmente configurado para autoload PSR-4):

composer install

Para iniciar a interface web de demonstração:

  1. Inicie um servidor PHP local: php -S localhost:8000
  2. Acesse no navegador: http://localhost:8000

Como Utilizar

O sistema opera através de um fluxo de ingestão (aprendizado) e consulta (chat).

1. Ingestão de Dados (Aprendizado)

Para que a IA responda sobre seus dados, você deve "ensinar" o sistema enviando arquivos de texto (.txt). * O sistema lê o arquivo. * O texto é dividido em fragmentos menores (chunks). Cada fragmento é convertido em um vetor matemático e salvo naMemória de Longo Prazo*.

2. Realizando Consultas

Ao fazer uma pergunta, o sistema utiliza uma Camada de Atenção para decidir se deve buscar a resposta nos arquivos que você enviou ou no histórico da conversa atual.

Parte 2: Aspectos Técnicos e Arquitetura

O Nano RAG diferencia-se por sua arquitetura modular inspirada em processos cognitivos, dividida em três pilares principais gerenciados por um orquestrador central.

1. O Cérebro (Brain Class)

A classe Brain atua como o controlador central. Ela não armazena dados, mas orquestra o fluxo de informações entre o cliente LLM (Ollama), as memórias e a camada de decisão. É responsável por receber o input do usuário e devolver a resposta final processada.

2. Memória de Longo Prazo (Long-Term Memory)

  • Função: Armazenamento persistente de fatos e conhecimento "cristalizado".
  • Implementação: Utiliza arquivos JSON locais (`knowledge_base.json`).
  • Técnica: Armazena o texto original junto com seu Embedding Vector.
  • Recuperação: Utiliza o algoritmo de Similaridade de Cosseno para encontrar matematicamente qual texto no banco de dados é mais próximo da pergunta do usuário. Funciona como uma biblioteca estática.

3. Memória de Curto Prazo (Short-Term Memory)

  • Função: Manter o contexto da conversa atual (sessão), permitindo que a IA entenda referências como "ele", "aquilo" ou "a resposta anterior".
  • Implementação: Baseada em sessões PHP (`$_SESSION`), mas enriquecida com vetores.
  • Diferencial: Diferente de arrays simples, esta memória armazena o vetor de cada mensagem trocada. Isso permite que o sistema busque no histórico não apenas por ordem cronológica, mas por relevância semântica.

4. Camada de Atenção (Attention Layer)

Este é o componente mais complexo do sistema, atuando como um filtro lógico (Gatekeeper) antes de acionar a Inteligência Artificial. Ela resolve o problema de alucinação evitando enviar contexto irrelevante para o modelo.

A camada de atenção decide dinamicamente a estratégia de resposta: Estratégia Retrieval:* Se a pergunta do usuário tem alta similaridade matemática com dados do JSON, a atenção foca na Memória de Longo Prazo. Estratégia Contextual:* Se a pergunta se conecta semanticamente com a frase anterior, a atenção foca na Memória de Curto Prazo. Estratégia Meta-Analysis:* Se o usuário pergunta sobre a própria conversa (ex: "O que eu perguntei antes?", "Resuma o chat"), a camada ignora a matemática e recupera o histórico linear bruto, simulando uma memória sequencial.

Conceitos Fundamentais: Vetores e Embeddings

Para que o PHP realize buscas semânticas sem um banco de dados externo, utilizamos o conceito de Embeddings.

  • O que é um Embedding? É uma representação numérica de um texto. O modelo `nomic-embed-text` transforma uma frase como "O PHP é uma linguagem de script" em uma lista de 768 números flutuantes (ex: `[0.123, -0.542, 0.991, ...]`).
  • Por que isso é necessário? Computadores não entendem significado, apenas números. Ao transformar texto em números, podemos calcular a distância geométrica entre duas frases. * A frase "Eu gosto de maçã" terá um vetor matematicamente muito próximo de "Adoro frutas". * A frase "Eu gosto de maçã" terá um vetor distante de "O servidor caiu".

O Nano RAG calcula essas distâncias nativamente em PHP para determinar o que é relevante para responder ao usuário.


  Files folder image Files (15)  
File Role Description
Files folder imagesrc (3 directories)
Files folder imagetests (5 files)
Accessible without login Plain text file composer.json Data Auxiliary data
Accessible without login Plain text file index.php Example Example script
Accessible without login Plain text file knowledge_base.json Data Auxiliary data
Accessible without login Plain text file README.md Doc. Documentation

  Files folder image Files (15)  /  src  
File Role Description
Files folder imageLlmClient (1 file)
Files folder imageRagEngine (3 files)
Files folder imageVectorDb (2 files)

  Files folder image Files (15)  /  src  /  LlmClient  
File Role Description
  Plain text file OllamaClient.php Class Class source

  Files folder image Files (15)  /  src  /  RagEngine  
File Role Description
  Plain text file AttentionLayer.php Class Class source
  Plain text file Brain.php Class Class source
  Plain text file ShortTermMemory.php Class Class source

  Files folder image Files (15)  /  src  /  VectorDb  
File Role Description
  Plain text file MathUtils.php Class Class source
  Plain text file Memory.php Class Class source

  Files folder image Files (15)  /  tests  
File Role Description
  Accessible without login Plain text file test_phase2.php Example Example script
  Accessible without login Plain text file test_phase3.php Example Example script
  Accessible without login Plain text file test_phase4.php Example Example script
  Accessible without login Plain text file texto sobre php para upload.txt Doc. Documentation
  Accessible without login Plain text file texto sobre psicologia para upload.txt Doc. Documentation

The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page.
Install with Composer Install with Composer
 Version Control Unique User Downloads  
 100%
Total:0
This week:0