Metadata-Version: 2.4
Name: fullstack-rag-ai
Version: 0.1.5
Summary: Lightweight RAG library for internal knowledge systems
Author: fullstack-solutions
Description-Content-Type: text/markdown
Requires-Dist: langchain
Requires-Dist: langchain-community
Requires-Dist: langchain-huggingface
Requires-Dist: langchain-ollama
Requires-Dist: faiss-cpu
Requires-Dist: sentence-transformers
Requires-Dist: pypdf

# Fullstack RAG AI

Lightweight **Retrieval-Augmented Generation (RAG)** library for building internal knowledge systems using local documents and LLMs.

This library allows you to:

- Load documents from **PDFs or raw text**
- Automatically **chunk and embed documents**
- Store embeddings in a **FAISS vector database**
- Ask questions against the knowledge base
- Use **deterministic caching** to avoid repeated LLM calls
- Automatically **detect document updates, additions, and deletions**

It is designed to use:

- **Ollama LLMs**
- **HuggingFace embeddings**
- **FAISS vector database**

---

# Installation

```bash
pip install fullstack-rag-ai
```

# Default Configuration

The library uses a default configuration, but all parameters can be overridden by the user.

```Python
DEFAULT_CONFIG = {
    "embedding_model": "sentence-transformers/all-MiniLM-L6-v2",
    "llm_model": "llama3",
    "chunk_size": 5000,
    "chunk_overlap": 500,
    "k": 15
}
```
# Core Workflow

Typical usage flow:

- Load documents
- Build or update vector database
- Ask questions against the database

```
Documents → Chunking → Embeddings → FAISS → Retrieval → LLM → Answer
```
# Loading Documents

Documents can be loaded either from PDF files or from a list of text strings.

## Load From PDFs
```Python
from fullstack_rag_lib.ingestion import load_documents

docs = load_documents(path="documents/")
```
## Load From Text List
```Python
from fullstack_rag_lib.ingestion import load_documents

texts = [
    "Python is a programming language",
    "FAISS is used for vector similarity search"
]

docs = load_documents(texts=texts)
```
## Function
```Python
load_documents(path=None, texts=None)
```
| Parameter | Type      | Description                 |
| --------- | --------- | --------------------------- |
| path      | str       | Folder containing PDF files |
| texts     | List[str] | List of raw text strings    |


Returns: List[Document]

# Updating the Vector Database

This function builds or updates the FAISS vector database.

It automatically handles:
- New documents
- Updated documents
- Deleted documents

Only the necessary parts of the database are rebuilt.

```Python
from fullstack_rag_lib.vector_db import sync_vector_db

sync_vector_db(
    documents_path="./data",
    index_path="./vector_db",
)
```

## Function

```Python
sync_vector_db(documents_path, index_path, embedding_model=embedding_model, chunk_size=chunk_size, chunk_overlap=chunk_overlap)
```
| Parameter       | Type | Description                           |
| --------------- | ---- | ------------------------------------- |
| documents_path  | str  | Directory containing PDF files        |
| index_path      | str  | Directory where FAISS index is stored |
| embedding_model | str  | HuggingFace embedding model           |
| chunk_size      | int  | Size of one chunk                     |
| chunk_overlap   | int  | Sentences Overlap                     |

This function maintains the following internal files:
index.faiss
index.pkl
documents.bin
metadata.bin
qa_cache.bin

# Asking Questions

Once the vector database exists, you can query it using an LLM.

The system retrieves the most relevant chunks and sends them to the LLM as context.

```Python
from fullstack_rag_lib.qa import ask_question

answer = ask_question(
    question="What is FAISS used for?",
    index_path="./vector_db"
)

print(answer)
```
## Function

```Python
ask_question(question, index_path, model=model, embedding_model=embedding_model, k=k, debug=False)
```

| Parameter       | Type | Description                 |
| --------------- | ---- | --------------------------- |
| question        | str  | User question               |
| index_path      | str  | Path to vector database     |
| model           | str  | Ollama LLM model            |
| embedding_model | str  | HuggingFace embedding model |
| k               | int  | Number of chunks retrieved  |
| debug           | bool | Print retrieved chunks      |

Returns: str

# Deterministic QA Cache

The library includes a smart cache system that prevents unnecessary LLM calls.

Cache keys are generated using: question + retrieved context hash

If:
- the question is the same

- the retrieved documents have not changed

The answer is returned directly from cache.

## Cache File

qa_cache.bin

# Helper Functions

## load_binary

Loads a binary pickle file.
```Python
load_binary(path)
```

Returns empty dictionary if file does not exist.

## save_binary

Stores data as a binary pickle file.

```Python
save_binary(path, data)
```

## compute_cache_key

Creates a deterministic key for caching LLM responses.

```Python
compute_cache_key(question, docs)
```

Uses:
- Question text
- Retrieved document content

# Example Full Pipeline

```Python
from fullstack_rag_lib.vector_db import sync_vector_db
from fullstack_rag_lib.qa import ask_question

# Step 1: Build / Update Vector DB
sync_vector_db(
    documents_path="./data",
    index_path="./vector_db",
)

# Step 2: Ask Questions
answer = ask_question(
    question="Summarize the company onboarding process",
    index_path="./vector_db",
)

print(answer.content)
```

# Changing the Embedding Model

Any HuggingFace embedding model supported by sentence-transformers can be used.

Example:
```Python
sync_vector_db(
    documents_path="./data",
    index_path="./vector_db",
    embedding_model="sentence-transformers/all-mpnet-base-v2"
)
```
The library will automatically download the model through HuggingFace if it is not already installed.

# Changing the LLM Model

The LLM model can be changed to any model available in Ollama.

Example:
```Python
answer = ask_question(
    question="Explain the onboarding process",
    index_path="./vector_db",
    model="llama3:8b",
    embedding_model="sentence-transformers/all-MiniLM-L6-v2"
)
```
Other examples:
- model="mistral"
- model="phi3"
- model="llama3:70b"

The only requirement is that the model must be available locally in Ollama.

To install a model:
```bash
ollama pull llama3
ollama pull llama3:8b
ollama pull llama3:70b
ollama pull phi3
ollama pull mistral
```

# Important: Rebuilding the Vector Database

If the embedding model changes, the vector database must be rebuilt.

This is because embeddings from different models are not compatible.

Example workflow:
```Python
sync_vector_db(
    documents_path="./data",
    index_path="./vector_new_db",
    embedding_model="BAAI/bge-base-en"
)
```
Alternatively, delete the existing index and rebuild.


# Dependencies

- langchain
- langchain-community
- langchain-huggingface
- langchain-ollama
- faiss-cpu
- sentence-transformers
- pypdf

These libraries allow dynamic usage of:
- Any HuggingFace embedding model
- Any Ollama LLM model

Therefore, users do not need to install additional dependencies when switching models.

When changing models:
| Change          | Required Action         |
| --------------- | ----------------------- |
| LLM model       | No rebuild needed       |
| Embedding model | Rebuild vector database |
| Chunk size      | Rebuild vector database |

# License
MIT License

# Author
Fullstack Solutions
