Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ For embeddings models, you can use these providers :
For your vector store, you can use :

- Chroma (`Settings.CHROMA`)
- Postgres (`Settings.POSTGRES`)

## Quick Start 🚀

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies = [
"python-dotenv>=1.1.1",
"pydantic>=2.11.7",
"google-genai>=1.2.0",
"langchain-postgres==0.0.16",
]
[project.scripts]
raglight = "raglight.cli.main:app"
7 changes: 7 additions & 0 deletions src/raglight/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ def setup_logging() -> None:
)

CHROMA = "Chroma"
POSTGRES = "Postgres"
POSTGRES_HOST = os.environ.get("POSTGRES_HOST", "localhost")
POSTGRES_PORT = os.environ.get("POSTGRES_PORT", 5432)
POSTGRES_DATABASE = os.environ.get("POSTGRES_DATABASE", "")
POSTGRES_USER = os.environ.get("POSTGRES_USER", "postgres")
POSTGRES_PASSWORD = os.environ.get("POSTGRES_PASSWORD", "")

OLLAMA = "Ollama"
MISTRAL = "Mistral"
VLLM = "vLLM"
Expand Down
3 changes: 3 additions & 0 deletions src/raglight/rag/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from ..llm.openai_model import OpenAIModel
from ..vectorstore.vector_store import VectorStore
from ..vectorstore.chroma import ChromaVS
from ..vectorstore.postgres import PostgresVS
from ..config.settings import Settings
from .rag import RAG
from ..rat.rat import RAT
Expand Down Expand Up @@ -119,6 +120,8 @@ def with_vector_store(self, type: str, **kwargs) -> Builder:
)
elif type == Settings.CHROMA:
self.vector_store = ChromaVS(embeddings_model=self.embeddings, **kwargs)
elif type == Settings.POSTGRES:
self.vector_store = PostgresVS(embeddings_model=self.embeddings, **kwargs)
else:
raise ValueError(f"Unknown VectorStore type: {type}")
logging.info("✅ VectorStore created")
Expand Down
126 changes: 126 additions & 0 deletions src/raglight/vectorstore/postgres.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import logging
from typing import List, Dict
from typing_extensions import override
from langchain_core.documents import Document

from ..config.settings import Settings

from .vector_store import VectorStore
from ..embeddings.embeddings_model import EmbeddingsModel

from enum import auto
from langchain_postgres import PGVector

class PostgresVS(VectorStore):
"""
Concrete implementation for PostgresVDB.

It inherits the main ingestion logic from the base VectorStore class and
only implements the Postgres-specific methods for adding documents and
performing searches.
"""

def __init__(
self,
collection_name: str,
embeddings_model: EmbeddingsModel,
persist_directory: str = None,
host: str = Settings.POSTGRES_HOST,
port: int = Settings.POSTGRES_PORT,
database: str = Settings.POSTGRES_DATABASE,
user: str = Settings.POSTGRES_USER,
password: str = Settings.POSTGRES_PASSWORD

) -> None:
"""
Initializes a PostgresVS instance.
"""
super().__init__(persist_directory, embeddings_model)

self.persist_directory = persist_directory
self.host = host
self.port = port
self.database = database
connection_string = f"postgresql://{user}:{password}@{host}:{port}/{database}"

if host and port:

self.vector_store = PGVector(
collection_name=collection_name,
connection=connection_string,
embeddings=embeddings_model,
use_jsonb=True,
)

self.vector_store_classes = PGVector(
collection_name=f"{collection_name}_classes",
connection=connection_string,
embeddings=self.embeddings_model,
use_jsonb=True,
)
else:
raise ValueError(
"Invalid configuration for PostgresVS: "
"You must either:\n"
" • Provide both host and port (for PostgresDB), OR\n"
" • Provide both user and password (for PostgreDsB).\n"
" • Provide exist database (for PostgresDB).\n"

f"Received -> host={host}, port={port}, user={user}, password={'*' * len(password) if password else None}, database={database}"
)

@override
def add_documents(self, documents: List[Document]) -> None:
"""
Implements the logic to add documents specifically to the main PostgresDB collection,
using batching for efficiency.
"""
if not documents:
return

# logging.info(
# f"⏳ Adding {len(documents)} document chunks to PostgresDB collection '{self.vector_store._collection_name}'..."
# )
self.vector_store.add_documents(documents=documents)
logging.info("✅ Documents successfully added to the main collection.")

@override
def add_class_documents(self, documents: List[Document]) -> None:
"""
Implements the logic to add class signature documents to the dedicated PostgresDB
collection for classes.
"""
if not documents:
return

logging.info(
f"⏳ Adding {len(documents)} class documents to PostgresDB collection '{self.vector_store_classes._collection_name}'..."
)
self.vector_store_classes.add_documents(documents=documents)
logging.info("✅ Class documents successfully added to the class collection.")

@override
def similarity_search(
self,
question: str,
k: int = 5,
filter: Dict[str, str] = None,
collection_name: str = None,
) -> List[Document]:
"""
Implements similarity search using the main PostgresDB client.
"""
return self.vector_store.similarity_search(question, k=k, filter=filter)

@override
def similarity_search_class(
self,
question: str,
k: int = 5,
filter: Dict[str, str] = None,
collection_name: str = None,
) -> List[Document]:
"""
Implements similarity search using the dedicated class PostgresDB client.
"""
pass
6 changes: 6 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ class TestsConfig:
SYSTEM_PROMPT = "/Users/labess40/dev/RAGLight/systemPrompt.txt"
COLLECTION_NAME = "grece"
DATA_PATH = "/Users/labess40/Desktop/nutrition/grece"
OLLAMA_EMBEDDING_MODEL="nomic-embed-text:v1.5"
POSTGRES_HOST = "192.168.1.103"
POSTGRES_PORT=5432
POSTGRES_DATABASE="ai_db"
POSTGRES_USER=""
POSTGRES_PASSWORD=""
25 changes: 25 additions & 0 deletions tests/tests_vector_store/test_postgres_vector_store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import unittest
from ..test_config import TestsConfig

from ...src.raglight.embeddings.ollama_embeddings import OllamaEmbeddingsModel
from ...src.raglight.vectorstore.postgres import PostgresVS


class TestVectorStore(unittest.TestCase):
def setUp(self):
model_embeddings = TestsConfig.OLLAMA_EMBEDDING_MODEL
collection_name = TestsConfig.COLLECTION_NAME
self.data_path = TestsConfig.DATA_PATH
embeddings = OllamaEmbeddingsModel(model_embeddings)
self.store = PostgresVS(
embeddings_model=embeddings,
collection_name=collection_name,
)

def test_ingest(self):
self.store.ingest(data_path=self.data_path)
self.assertEqual(True, True, "Embedding should be added to the store.")


if __name__ == "__main__":
unittest.main()