π€ Contributing to AI Cortex#
AI Cortex is an open-source project and we welcome contributions of all kinds β bug fixes, new features, documentation improvements, model additions, and more. This guide walks you through everything you need to get started.
π Table of Contents#
π Before You Start#
Find Something to Work On#
Browse the Issues page and look for:
Label |
Meaning |
|---|---|
|
Great for newcomers β well-scoped with clear requirements |
|
Maintainers are actively seeking contributions here |
|
Something is broken and needs a fix |
|
New feature or improvement to existing behavior |
|
Docs-only change, no code needed |
If you have an idea that isnβt tracked yet, open an issue to discuss it before building β this avoids duplicate work and ensures alignment with project goals.
π οΈ Setting Up Your Environment#
Prerequisites#
Python 3.8+ (3.11 recommended)
Git
Ollama β for running integration tests against a real server
Clone and Install#
# 1. Fork the repo on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/aicortex.git
cd aicortex
# 2. Create a virtual environment
python -m venv venv
source venv/bin/activate # macOS/Linux
# venv\Scripts\activate # Windows
# 3. Install in editable mode with all dev dependencies
pip install -e .[dev,server]
# 4. (Optional) Install pre-commit hooks for automatic quality checks
pip install pre-commit
pre-commit install
Verify Your Setup#
# Run the test suite β all tests should pass
pytest
# Check types
mypy aicortex
# Check formatting
black --check aicortex tests
# Run everything via tox
tox
If everything passes, youβre ready to contribute.
π Development Workflow#
1. πΏ Create a Branch#
Branch names should be descriptive and follow this convention:
# New feature
git checkout -b feature/async-chat-support
# Bug fix (reference the issue number)
git checkout -b fix/123-streaming-timeout
# Documentation update
git checkout -b docs/update-quickstart
2. βοΈ Make Your Changes#
Write your code following the Code Standards below. As you work:
Keep commits small and focused β one logical change per commit
Write tests alongside new code, not after
Update documentation if your change affects public behavior
3. π§ͺ Run Quality Checks#
Before committing, run the full quality suite:
# Format code (auto-fixes in place)
black aicortex tests
# Static type checking
mypy aicortex
# Lint for common issues
flake8 aicortex tests
# Run tests with coverage
pytest --cov=aicortex --cov-report=term-missing
All checks must pass before submitting a PR.
4. π Commit Your Changes#
Use Conventional Commits format:
git commit -m "feat: add async support for chat()"
git commit -m "fix: resolve streaming timeout on slow connections"
git commit -m "docs: add examples for tool pipeline usage"
git commit -m "test: add unit tests for resolve_models edge cases"
git commit -m "refactor: extract server discovery into helper"
git commit -m "chore: bump ollama dependency to 0.3.0"
Prefix reference:
Prefix |
Use for |
|---|---|
|
New features |
|
Bug fixes |
|
Documentation only |
|
Formatting, no logic changes |
|
Code restructuring without behavior change |
|
Adding or updating tests |
|
Maintenance tasks, dependency updates |
5. π Push and Open a PR#
git push origin feature/your-feature-name
Then open a Pull Request on GitHub against the main branch.
π Code Standards#
Python Style#
Follow PEP 8 β enforced by
blackandflake8Maximum line length: 88 characters (Black default)
Type hints required for all function parameters and return values
Docstrings required for all public functions, classes, and methods
Naming Conventions#
Thing |
Convention |
Example |
|---|---|---|
Functions & methods |
|
|
Classes |
|
|
Constants |
|
|
Private members |
|
|
Modules |
|
|
Import Order#
# 1. Standard library
import os
import json
from pathlib import Path
from typing import Iterator, List
# 2. Third-party
import ollama
from pydantic import BaseModel
# 3. Local imports
from .api import _OllamaAPI
from .chat import Stream, StreamEvent
Docstring Format#
Use Google-style docstrings:
def chat(prompt: str, *, model: str = "llama3.2:3b", stream: bool = False) -> str:
"""Send a prompt to a model and return its response.
A high-level convenience function that handles model selection,
server discovery, and response parsing automatically.
Args:
prompt: The text prompt to send to the model.
model: Model identifier in ``family:size`` format.
Defaults to ``"llama3.2:3b"``.
stream: If ``True``, returns a :class:`Stream` object instead
of a plain string. Defaults to ``False``.
Returns:
The model's response as a plain string, or a :class:`Stream`
object if ``stream=True``.
Raises:
ModelNotFoundError: If the specified model is not available
on any configured server.
ServerError: If all servers are unreachable.
Example:
>>> response = chat("What is machine learning?")
>>> print(response)
'Machine learning is a subset of artificial intelligence...'
"""
π§ͺ Testing#
Test Structure#
tests/
βββ __init__.py
βββ conftest.py # Shared fixtures and mock setup
βββ test_chat.py # chat() function tests
βββ test_api.py # _OllamaAPI class tests
βββ test_models.py # Model loading and metadata tests
βββ test_tools.py # Tool pipeline tests
βββ test_server.py # FastAPI server endpoint tests
βββ fixtures/
βββ mock_responses.json # Pre-recorded API responses
βββ test_models.json # Minimal model metadata for tests
Writing Tests#
import pytest
from unittest.mock import Mock, patch
from aicortex import chat, families, models
class TestChat:
"""Tests for the chat() function."""
def test_chat_returns_string(self, mock_ollama_client):
"""chat() should return a non-empty string for valid prompts."""
response = chat("Hello")
assert isinstance(response, str)
assert len(response) > 0
def test_chat_with_explicit_model(self, mock_ollama_client):
"""chat() should accept a model parameter."""
response = chat("Hello", model="mistral:7b")
assert isinstance(response, str)
def test_chat_raises_on_invalid_model(self, mock_ollama_client):
"""chat() should raise ModelNotFoundError for unknown models."""
from aicortex.exceptions import ModelNotFoundError
with pytest.raises(ModelNotFoundError):
chat("Hello", model="nonexistent:model")
Mocking Ollama#
Tests must not require a live Ollama server. Use the shared fixture from conftest.py:
@pytest.fixture
def mock_ollama_client():
"""Patch ollama.Client with a pre-configured mock."""
with patch("ollama.Client") as mock_class:
instance = Mock()
instance.chat.return_value = {
"message": {"content": "Mocked response"},
"done": True,
}
instance.list.return_value = {
"models": [{"name": "llama3.2:3b"}, {"name": "mistral:7b"}]
}
mock_class.return_value = instance
yield instance
Coverage Requirements#
Aim for 90%+ coverage on all new code
Check your coverage before submitting:
pytest --cov=aicortex --cov-report=term-missing --cov-fail-under=90
π Documentation#
If your change affects user-facing behavior, update the relevant docs in docs/.
Changed |
Update |
|---|---|
Public function signature or behavior |
|
Streaming behavior |
|
Installation or dependencies |
|
Model metadata schema |
|
Tool pipeline |
|
Server endpoints |
|
Also update any relevant code examples in examples/ to reflect the change.
Building the Docs Locally#
# Install Sphinx dependencies
pip install -e .[dev]
# Build HTML docs
tox -e docs
# Open in browser (macOS)
open docs/_build/html/index.html
π¬ Pull Request Process#
PR Checklist#
Before submitting, confirm:
All tests pass:
pytestTypes check:
mypy aicortexCode is formatted:
black --check aicortex testsNo new lint errors:
flake8 aicortex testsNew code has tests with adequate coverage
Documentation updated for any public API changes
Commit messages follow Conventional Commits format
PR description clearly explains the change and its motivation
PR Description Template#
## Summary
Brief description of what this PR does and why.
## Type of Change
- [ ] Bug fix (non-breaking)
- [ ] New feature (non-breaking)
- [ ] Breaking change (existing functionality changes)
- [ ] Documentation update
- [ ] Refactor / internal improvement
## Testing
Describe how you tested the changes:
- Unit tests added/updated: yes/no
- Tested against live Ollama server: yes/no
- Coverage delta: +X%
## Related Issues
Closes #123
Review Process#
β Automated CI β Tests, types, formatting, and linting run automatically
π Code review β A maintainer reviews your changes within a few days
π¬ Address feedback β Respond to comments and push updates as needed
β Approval & merge β Once approved, a maintainer merges the PR
π Reporting Issues#
Bug Reports#
When reporting a bug, include:
**Describe the bug**
A clear description of what is happening vs. what you expected.
**To Reproduce**
Minimal code to reproduce the issue:
import aicortex
response = aicortex.chat("Hello", model="llama3.2:3b")
# -> Error: ...
**Environment**
- OS: macOS 14.3 / Ubuntu 22.04 / Windows 11
- Python: 3.11.2
- AI Cortex: 1.0.3
- Ollama: 0.3.1
**Full traceback**
Paste the complete error output here.
Feature Requests#
When requesting a feature:
**Problem**
What are you trying to do that you can't currently do?
**Proposed Solution**
What API or behavior would solve it?
response = aicortex.chat("Hello", timeout=30) # example
**Alternatives Considered**
What workarounds have you tried?
β Adding Models & Features#
Adding a New Model Family#
Create a new JSON file in
aicortex/models/β seellama.jsonfor the schemaFollow the existing field structure:
name,family,size,parameters,serversAdd at least one server entry to make the model immediately usable
Test model loading:
from aicortex import models; print(models("yourfamily"))Update
docs/models.mdwith the new family
Adding a New Tool#
Create a new module in
aicortex/tools/Export it in
aicortex/tools/__init__.pyAdd type stubs in
aicortex/stubs/tools/if itβs part of the public APIAdd CLI entry point in
setup.pyif the tool should be runnable from the command lineWrite tests in
tests/test_tools.pyDocument it in
docs/tools.md
Adding a New Public Function#
Implement in the appropriate module (
api.py,chat.py, etc.)Export from
aicortex/__init__.pyAdd type stub to
aicortex/stubs/__init__.pyiWrite tests
Document in
docs/api.mdwith full parameter table and example
π Community#
Getting Help#
Documentation β Start at aicortex.readthedocs.io
Issues β For bugs and feature requests: github.com/eirasmx/aicortex/issues
Discussions β For questions and ideas: github.com/eirasmx/aicortex/discussions
Code of Conduct#
We are committed to a welcoming, inclusive community. In all interactions:
Be respectful and patient β people are here to learn and help
Give constructive, specific feedback rather than vague criticism
Assume good intent unless clearly demonstrated otherwise
Help newcomers get oriented rather than dismissing their questions
Recognition#
All contributors are recognized in release notes and the GitHub contributor graph. Significant contributions may be highlighted in the CHANGELOG.md.
Thank you for helping make AI Cortex better. Every contribution β no matter how small β is valued. π