Contributing
Thank you for your interest in contributing to ragit! This guide will help you get started.
Development Setup
Clone the repository:
git clone https://github.com/rodmena-limited/ragit.git
cd ragit
Create a virtual environment:
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# or
.venv\Scripts\activate # Windows
Install in development mode:
pip install -e ".[dev]"
Verify the installation:
pytest
ruff check .
mypy --strict ragit/
Code Quality Standards
All code must pass these checks before merging:
Linting
# Check for issues
ruff check .
# Auto-fix issues
ruff check --fix .
Formatting
# Check formatting
ruff format --check .
# Apply formatting
ruff format .
Type Checking
# Strict type checking
mypy --strict ragit/
Testing
# Run all tests
pytest
# Run with coverage (minimum 90%)
pytest --cov=ragit --cov-report=term-missing
# Run specific test file
pytest tests/unit/test_assistant.py
# Run integration tests (requires Ollama)
pytest -m integration
Code Style Guidelines
Type hints: All functions must have complete type hints (mypy –strict compliant)
Docstrings: Use NumPy-style docstrings for public API:
def my_function(param1: str, param2: int = 10) -> list[str]:
"""
Short description of the function.
Parameters
----------
param1 : str
Description of param1.
param2 : int, optional
Description of param2 (default: 10).
Returns
-------
list[str]
Description of return value.
Examples
--------
>>> result = my_function("hello", 5)
>>> print(result)
"""
pass
Line length: Maximum 120 characters
Imports: Sorted by ruff (isort compatible)
No emojis/unicode: Keep output ASCII-compatible
Immutability: Prefer tuples over lists for data that shouldn’t change
File Headers
All Python files must include:
#
# Copyright RODMENA LIMITED 2025
# SPDX-License-Identifier: Apache-2.0
#
Testing Guidelines
Test Structure
tests/
├── conftest.py # Shared fixtures
├── unit/ # Unit tests (mocked dependencies)
│ ├── test_assistant.py
│ ├── test_config.py
│ └── ...
└── integration/ # Integration tests (real Ollama)
└── test_highway_rag.py
Writing Tests
import pytest
from ragit import RAGAssistant
class TestRAGAssistant:
"""Tests for RAGAssistant class."""
def test_ask_returns_string(self, mock_provider):
"""ask() should return a string answer."""
assistant = RAGAssistant("docs/")
result = assistant.ask("What is this?")
assert isinstance(result, str)
def test_retrieve_returns_list(self, mock_provider):
"""retrieve() should return list of (chunk, score) tuples."""
assistant = RAGAssistant("docs/")
results = assistant.retrieve("query", top_k=3)
assert isinstance(results, list)
assert len(results) <= 3
Using Fixtures
# In conftest.py
import pytest
from unittest.mock import MagicMock
@pytest.fixture
def mock_provider():
"""Mock OllamaProvider for unit tests."""
provider = MagicMock()
provider.is_available.return_value = True
provider.generate.return_value = MagicMock(text="Test answer")
provider.embed.return_value = MagicMock(
embedding=tuple([0.1] * 1024),
dimensions=1024
)
return provider
Adding New Features
Create an issue first to discuss the feature
Write tests before implementing
Implement the feature following code style guidelines
Update documentation if needed
Submit a pull request
Adding New Providers
To add a new provider (e.g., OpenAI, Anthropic):
Create
ragit/providers/newprovider.pyInherit from
BaseLLMProviderand/orBaseEmbeddingProviderImplement required methods:
from ragit.providers.base import (
BaseLLMProvider,
BaseEmbeddingProvider,
LLMResponse,
EmbeddingResponse
)
class NewProvider(BaseLLMProvider, BaseEmbeddingProvider):
@property
def provider_name(self) -> str:
return "newprovider"
@property
def dimensions(self) -> int:
return self._dimensions
def generate(self, prompt: str, model: str, ...) -> LLMResponse:
# Implementation
pass
def embed(self, text: str, model: str) -> EmbeddingResponse:
# Return tuple for embedding, not list
return EmbeddingResponse(embedding=tuple(embedding), ...)
def embed_batch(self, texts: list[str], model: str) -> list[EmbeddingResponse]:
# Single API call for all texts
pass
def is_available(self) -> bool:
# Health check
pass
Add configuration to
ragit/config.pyExport in
ragit/providers/__init__.pyWrite tests in
tests/unit/test_providers_newprovider.py
Pull Request Process
Fork the repository
Create a feature branch:
git checkout -b feature/my-new-feature
Make your changes
Run all checks:
ruff check .
ruff format .
mypy --strict ragit/
pytest --cov=ragit
Commit with a clear message:
git commit -m "Add feature: description of what it does"
Push and create a pull request:
git push origin feature/my-new-feature
Issue Tracking
This project uses issuedb-cli for issue tracking. See the project’s CLAUDE.md for commands.
# Create an issue
issuedb-cli create -t "Bug: description" --priority high
# Start working on an issue
issuedb-cli start ID
# Close when done
issuedb-cli stop --close
Getting Help
Open an issue on GitHub for bugs or feature requests
Check existing issues before creating new ones
Provide clear reproduction steps for bugs
License
By contributing, you agree that your contributions will be licensed under the Apache-2.0 license.