LLM Vision for Home Assistant

repository·main·Indexed 23 days ago

https://github.com/valentinfrlch/ha-llmvision

A Home Assistant integration that provides visual intelligence using multimodal LLMs to analyze images, video files, live camera feeds, and Frigate events. It supports multiple providers including OpenAI, Anthropic, Google Gemini, AWS Bedrock, Azure, Groq, Ollama, LocalAI, and OpenRouter. Key features include visual analysis, memory for people and pets, a camera event timeline, and sensor automation.

Tokens
3.5K
Snippets
10
Records
14
Agent score
30%

What's inside LLM Vision

  1. Overview of LLM Vision features

    main

    LLM Vision is a Home Assistant integration that enables visual intelligence by using multimodal large language models (LLMs) to analyze:

    • Images
    • Video files
    • Live camera feeds
    • Frigate events

    Key Capabilities:

    • Multi-provider support: Works with OpenRouter, OpenAI, Anthropic, Google Gemini, AWS Bedrock, Azure, Groq, Ollama, Open WebUI, LocalAI, and any OpenAI-compatible endpoint.
    • Visual Analysis: Answers questions and provides descriptions of visual media based on your prompts.
    • Memory: Can remember people, pets, and objects.
    • Timeline: Maintains a timeline of analyzed camera events, which can be displayed on a dashboard or queried via Home Assistant Assist.
    • Sensor Automation: Seamlessly updates Home Assistant sensors based on data extracted from camera streams, images, or videos.
  2. Set up the LLM Vision testing environment

    main

    To set up a local testing environment, follow these steps to create a virtual environment and install the necessary dependencies.

    Prerequisites

    • Python 3.13
    • pip
    • Git

    1. Create and Activate a Virtual Environment

    Navigate to the project root and create a .venv directory.

    macOS/Linux:

    cd ha-llmvision
    python -m venv .venv
    source .venv/bin/activate

    Windows:

    cd ha-llmvision
    python -m venv .venv
    .venv\Scripts\activate

    2. Install Test Dependencies

    Upgrade pip and install the dependencies listed in requirements-test.txt (which includes pytest, Home Assistant utilities, mocking libraries, and coverage tools).

    pip install --upgrade pip
    pip install -r requirements-test.txt

    3. Verify Installation

    You can verify the setup by checking the pytest version and running a simple test.

    pytest --version
    python -c "import sys; print('custom_components' in str(sys.path))"
    pytest tests/test_const.py::TestConstants::test_domain -v
    # Navigate to the project root directory
    cd ha-llmvision
    
    # Create a virtual environment
    python -m venv .venv
    
    # Activate (macOS/Linux)
    source .venv/bin/activate
    
    # Upgrade pip and install dependencies
    pip install --upgrade pip
    pip install -r requirements-test.txt
  3. Run tests in LLM Vision

    main

    Use pytest to execute different types of tests. The project uses markers to distinguish between unit and integration tests.

    Unit Tests

    Run all unit tests (excluding integration tests):

    pytest tests/ -m "not integration" -v

    Integration Tests

    Integration tests in tests/test_api.py require a running Home Assistant instance and specific configuration files.

    1. Create tests/.instance containing your HA URL (e.g., http://localhost:8123).
    2. Create tests/.token containing a long-lived access token.
    3. Run:
    pytest tests/test_api.py -v

    Running Specific Tests

    • Specific file: pytest tests/test_memory.py -v
    • Specific class: pytest tests/test_memory.py::TestMemory -v
    • Specific function: pytest tests/test_memory.py::TestMemory::test_init_without_entry -v

    Test Output Options

    • Quiet mode: -q
    • Show print statements: -v -s
    • Stop on first failure: -x
    • Show local variables on failure: -l
    # Run all unit tests
    pytest tests/ -v
    
    # Run only unit tests
    pytest tests/ -m "not integration" -v
    
    # Run ALL tests including integration tests
    pytest tests/ -v --run-integration
  4. Generate coverage reports

    main

    To check code coverage for the custom_components/llmvision package, use pytest-cov.

    Terminal Reports

    Show missing lines in the terminal:

    pytest tests/ --ignore=tests/test_api.py --cov=custom_components/llmvision --cov-report=term-missing

    HTML Reports

    Generate an interactive HTML report:

    pytest tests/ --ignore=tests/test_api.py --cov=custom_components/llmvision --cov-report=html

    Then open it:

    • macOS: open htmlcov/index.html
    • Linux: xdg-open htmlcov/index.html
    • Windows: start htmlcov/index.html

    Coverage Thresholds

    Fail the test suite if coverage falls below a certain percentage (e.g., 50%):

    pytest tests/ --cov=custom_components/llmvision --cov-fail-under=50
    # Generate HTML coverage report
    pytest tests/ --ignore=tests/test_api.py --cov=custom_components/llmvision --cov-report=html
  5. Maintain and clean up the testing environment

    main

    Updating Dependencies

    • Update all test dependencies: pip install --upgrade -r requirements-test.txt
    • Update a specific package: pip install --upgrade pytest
    • Check for outdated packages: pip list --outdated
    • Freeze current versions: pip freeze > requirements-test-frozen.txt

    Cleaning Up

    • Remove virtual environment: deactivate then rm -rf .venv
    • Remove coverage files: rm -rf .coverage htmlcov/
    • Remove Python cache files:
    find . -type d -name "__pycache__" -exec rm -rf {} +
    find . -type f -name "*.pyc" -delete
  6. Write new tests for LLM Vision

    main

    When writing new tests, follow the Arrange, Act, Assert (AAA) pattern and use pytest fixtures for setup.

    import pytest
    from unittest.mock import Mock, patch, AsyncMock
    
    class TestClassName:
        @pytest.fixture
        def mock_dependency(self):
            return Mock()
    
        def test_method_name(self, mock_dependency):
            # Arrange
            instance = ClassName(mock_dependency)
            
            # Act
            result = instance.method_name()
            
            # Assert
            assert result == expected_value
    
        @pytest.mark.asyncio
        async def test_async_method(self):
            result = await async_function()
            assert result is not None

    Best Practices

    1. Descriptive Names: Use test_method_name_when_condition_then_expected_result.
    2. Mocking: Always mock external dependencies like API calls or file systems.
    3. Async Tests: Use the @pytest.mark.asyncio decorator for asynchronous functions.
    4. Fixtures: Use fixtures for common setup. Available fixtures in tests/conftest.py include mock_hass and mock_config_entry.
    5. Independence: Ensure tests do not share state.

    Common Pitfalls

    • Async Warnings: If you see RuntimeWarning: coroutine was never awaited, ensure you added @pytest.mark.asyncio.
    • Mocking Errors: Ensure you patch the location where the function is used, not where it is defined.
    • Shared State: If tests pass individually but fail together, use scope="function" in your fixtures to ensure a fresh instance per test.
    """Unit tests for module_name.py module."""
    import pytest
    from unittest.mock import Mock, patch, AsyncMock
    
    
    class TestClassName:
        """Test ClassName class."""
    
        @pytest.fixture
        def mock_dependency(self):
            """Create a mock dependency."""
            return Mock()
    
        def test_method_name(self, mock_dependency):
            """Test method_name does something."""
            # Arrange
            instance = ClassName(mock_dependency)
            
            # Act
            result = instance.method_name()
            
            # Assert
            assert result == expected_value
    
        @pytest.mark.asyncio
        async def test_async_method(self):
            """Test async method."""
            result = await async_function()
            assert result is not None
  7. Install LLM Vision via HACS

    main

    LLM Vision is available in the default Home Assistant Community Store (HACS) repository. Follow these steps to install and set up the integration:

    1. Install LLM Vision from HACS.
    2. Restart Home Assistant.
    3. Search for LLM Vision in Home Assistant Settings > Devices & services.
    4. Press submit to continue setup with default settings.
    5. Set up the media folder: LLM Vision uses the /media folder for storing snapshots. If you are running Home Assistant Container, you may need to mount a folder to /media in your container settings.
    6. Return to the LLM Vision Integration Page.
    7. Press 'Add Entry' to add your first AI Provider.
  8. Debug tests in LLM Vision

    main

    If tests fail, you can use several debugging methods.

    pytest Debugging

    • Drop into debugger on failure: pytest tests/ --pdb
    • Drop into debugger at start of each test: pytest tests/ --trace
    • Show all log output (DEBUG level): pytest tests/ -v --log-cli-level=DEBUG

    Manual Breakpoints

    Insert import pdb; pdb.set_trace() in your test code to pause execution.

    VS Code Integration

    Create a .vscode/launch.json file to debug specific test files using the VS Code debugger:

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Python: Pytest Current File",
                "type": "python",
                "request": "launch",
                "module": "pytest",
                "args": [
                    "${file}",
                    "-v",
                    "-s"
                ],
                "console": "integratedTerminal",
                "justMyCode": false
            }
        ]
    }
  9. Quick Start Guide for Testing LLM Vision

    main

    To set up the testing environment and run tests for the first time, follow these steps:

    1. Clone the repository and navigate to the root directory.
    2. Create and activate a virtual environment using python -m venv .venv.
    3. Install test dependencies using pip install -r requirements-test.txt.
    4. Run tests using the provided convenience script ./run_tests.sh or directly via pytest.
    # 1. Clone the repository
    git clone <repository-url>
    cd ha-llmvision
    
    # 2. Create and activate virtual environment
    python -m venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    
    # 3. Install all test dependencies
    pip install -r requirements-test.txt
    
    # 4. Run tests using the convenience script
    ./run_tests.sh
  10. Check code coverage

    main

    To measure how much of the custom_components/llmvision module is covered by tests, use the following pytest commands:

    • Basic coverage: pytest tests/ --cov=custom_components/llmvision
    • HTML report: pytest tests/ --cov=custom_components/llmvision --cov-report=html (generates an htmlcov/ directory).
    • Missing lines report: pytest tests/ --cov=custom_components/llmvision --cov-report=term-missing (shows specific lines not covered in the terminal).

    To view the HTML report, run open htmlcov/index.html.

    pytest tests/ --cov=custom_components/llmvision --cov-report=html
  11. Debug failing tests

    main

    If tests are failing, use these commands to investigate:

    • Debugger: pytest tests/ --pdb (drops into the debugger on failure).
    • Verbose output: pytest tests/ -vv -s (very verbose with print output).
    • Debug logs: pytest tests/ --log-cli-level=DEBUG (shows debug-level logs).
    • Local variables: pytest tests/ -l (shows local variables on failure).
    pytest tests/ --pdb