Adds the `bigbrain` optional dependency group (airllm>=2.9.0) and a
complete second inference path that runs 8B / 70B / 405B Llama models
locally via layer-by-layer loading — no GPU required, no cloud, fully
sovereign.
Key changes:
- src/timmy/backends.py — TimmyAirLLMAgent (same print_response interface
as Agno Agent); auto-selects AirLLMMLX on Apple
Silicon, AutoModel (PyTorch) everywhere else
- src/timmy/agent.py — _resolve_backend() routing with explicit override,
env-config, and 'auto' Apple-Silicon detection
- src/timmy/cli.py — --backend / --model-size flags on all commands
- src/config.py — timmy_model_backend + airllm_model_size settings
- src/timmy/prompts.py — mentions AirLLM "even bigger brains, still fully
sovereign"
- pyproject.toml — bigbrain optional dep; wheel includes updated
- .env.example — TIMMY_MODEL_BACKEND + AIRLLM_MODEL_SIZE docs
- tests/conftest.py — stubs 'airllm' module so tests run without GPU
- tests/test_backends.py — 13 new tests covering helpers + TimmyAirLLMAgent
- tests/test_agent.py — 7 new tests for backend routing
- README.md — Big Brain section with one-line install
- activate_self_tdd.sh — bootstrap script (venv + install + tests +
watchdog + dashboard); --big-brain flag
All 61 tests pass. Self-TDD watchdog unaffected.
https://claude.ai/code/session_01DMjQ5qMZ8iHeyix1j3GS7c
38 lines
984 B
Python
38 lines
984 B
Python
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
# ── Stub heavy optional dependencies so tests run without them installed ──────
|
|
# Uses setdefault: real module is used if already installed, mock otherwise.
|
|
for _mod in [
|
|
"agno",
|
|
"agno.agent",
|
|
"agno.models",
|
|
"agno.models.ollama",
|
|
"agno.db",
|
|
"agno.db.sqlite",
|
|
# AirLLM is optional (bigbrain extra) — stub it so backend tests can
|
|
# import timmy.backends and instantiate TimmyAirLLMAgent without a GPU.
|
|
"airllm",
|
|
]:
|
|
sys.modules.setdefault(_mod, MagicMock())
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def reset_message_log():
|
|
"""Clear the in-memory chat log before and after every test."""
|
|
from dashboard.store import message_log
|
|
message_log.clear()
|
|
yield
|
|
message_log.clear()
|
|
|
|
|
|
@pytest.fixture
|
|
def client():
|
|
from dashboard.app import app
|
|
with TestClient(app) as c:
|
|
yield c
|