The Automotive LLM System is built with a modular, event-driven architecture designed for real-time automotive applications. The system emphasizes safety, reliability, and extensibility.
- Safety First: Multiple validation layers prevent unsafe operations
- Modularity: Components can be developed and tested independently
- Async/Await: Non-blocking operations for real-time performance
- Mock Development: Full functionality without hardware dependencies
- Graceful Degradation: System continues operating with failed components
┌─────────────────────────────────────────────────────────┐
│ Main Controller │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ Voice Mgr │ │ LLM Control │ │ Safety Monitor │ │
│ └─────────────┘ └──────────────┘ └─────────────────┘ │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ HVAC Ctrl │ │ Vehicle Mgr │ │ Config System │ │
│ └─────────────┘ └──────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
┌─────────────┐
│ Hardware │
│ OBD │ CAN │
│ MIC │ GPIO │
└─────────────┘
- Python 3.11+
- Git
- Virtual environment capability
- IDE with Python support (VS Code recommended)
git clone https://github.com/yourusername/automotive-llm-system.git
cd automotive-llm-system
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
pip install -r requirements-dev.txt # Development dependenciesCreate requirements-dev.txt:
pytest>=7.4.0
pytest-asyncio>=0.21.0
pytest-cov>=4.1.0
black>=23.7.0
flake8>=6.0.0
mypy>=1.5.0
pre-commit>=3.3.0
pytest-mock>=3.11.0
pre-commit installVS Code Settings (.vscode/settings.json):
{
"python.defaultInterpreterPath": "./venv/bin/python",
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.mypyEnabled": true,
"python.formatting.provider": "black",
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": ["tests/"],
"files.exclude": {
"**/__pycache__": true,
"**/*.pyc": true
}
}All components support mock mode for development without hardware:
# Environment variables for mock mode
export AUTOMOTIVE_LLM_MOCK_MODE=true
export AUTOMOTIVE_LLM_OBD_MOCK=true
export AUTOMOTIVE_LLM_CAN_MOCK=true
export AUTOMOTIVE_LLM_VOICE_MOCK=true# src/controllers/example_controller.py
import asyncio
import logging
from typing import Dict, Any, Optional
from dataclasses import dataclass
@dataclass
class ExampleState:
"""State data for the example controller."""
active: bool = False
value: float = 0.0
timestamp: float = 0.0
class ExampleController:
"""Example controller template."""
def __init__(self, vehicle_manager):
self.vehicle_manager = vehicle_manager
self.logger = logging.getLogger(__name__)
self.state = ExampleState()
self.stats = {"commands_executed": 0}
async def initialize(self) -> bool:
"""Initialize the controller."""
try:
self.logger.info("🔧 Initializing Example Controller...")
# Initialization logic here
self.logger.info("✅ Example Controller initialized")
return True
except Exception as e:
self.logger.error(f"Example Controller initialization failed: {e}")
return False
async def execute_command(self, command: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
"""Execute a controller command."""
try:
# Command execution logic
self.stats["commands_executed"] += 1
return {"success": True, "result": "Command executed"}
except Exception as e:
self.logger.error(f"Command execution failed: {e}")
return {"success": False, "error": str(e)}
def get_status(self) -> Dict[str, Any]:
"""Get current controller status."""
return {
"state": self.state.__dict__,
"stats": self.stats.copy()
}
async def shutdown(self) -> None:
"""Shutdown the controller."""
self.logger.info("🛑 Shutting down Example Controller...")
# Cleanup logic here
self.logger.info("✅ Example Controller shutdown complete")Add to SystemController._execute_command():
elif intent.intent_type.value == "example_control":
return await self._execute_example_command(intent)Add command handler:
async def _execute_example_command(self, intent) -> bool:
"""Execute example controller commands."""
if not self.example_controller:
return False
result = await self.example_controller.execute_command(
intent.action,
{"target": intent.target, "value": intent.value}
)
return result.get("success", False)# src/interfaces/custom_interface.py
from interfaces.vehicle import VehicleInterface, VehicleParameter
class CustomInterface(VehicleInterface):
"""Custom vehicle interface implementation."""
def __init__(self, config_params):
self.config = config_params
self.connected = False
self.logger = logging.getLogger(__name__)
async def connect(self) -> bool:
"""Connect to custom interface."""
try:
# Connection logic here
self.connected = True
self.logger.info("✅ Custom interface connected")
return True
except Exception as e:
self.logger.error(f"Custom interface connection failed: {e}")
return False
async def get_parameter(self, parameter_name: str) -> Optional[VehicleParameter]:
"""Get parameter from custom interface."""
if not self.connected:
return None
# Parameter retrieval logic
return VehicleParameter(
name=parameter_name,
value=0.0, # Actual value
unit="unit",
timestamp=time.time(),
system_type=VehicleSystemType.ENGINE,
source="custom"
)
async def set_parameter(self, parameter_name: str, value: Any) -> bool:
"""Set parameter via custom interface."""
if not self.connected:
return False
# Parameter setting logic
return True# In VehicleManager.__init__()
self.custom_interface = CustomInterface(custom_config)
# In VehicleManager.initialize()
custom_connected = await self.custom_interface.connect()
if custom_connected:
self.logger.info("✅ Custom interface ready")# Add to controllers/llm_controller.py
class IntentType(Enum):
# Existing intents...
CUSTOM_CONTROL = "custom_control"
NAVIGATION = "navigation"
DIAGNOSTICS = "diagnostics"CUSTOM_SYSTEM_PROMPT = """You are specialized in [specific domain].
Your capabilities:
- Custom function 1
- Custom function 2
Respond with JSON containing:
- "intent": the intent type
- "custom_field": domain-specific data
"""
# Add to LLMController
def _get_system_prompt(self, domain: str) -> str:
"""Get domain-specific system prompt."""
if domain == "custom":
return CUSTOM_SYSTEM_PROMPT
return AutomotivePromptTemplate.SYSTEM_PROMPTdef extract_custom_entities(self, text: str) -> List[Entity]:
"""Extract domain-specific entities."""
entities = []
# Custom extraction logic
# Example: Extract coordinates, addresses, etc.
return entities# Add to safety/monitor.py
def _initialize_custom_safety_rules(self) -> List[SafetyRule]:
"""Initialize custom safety rules."""
return [
SafetyRule(
name="custom_parameter_limit",
parameter="custom_param",
min_value=0.0,
max_value=100.0,
safety_level=SafetyLevel.WARNING,
violation_type=SafetyViolationType.SYSTEM_INTEGRITY,
action_required=False,
description="Custom parameter out of range"
)
]async def validate_custom_command(self, command_data: Dict[str, Any]) -> CommandValidationResult:
"""Custom command validation logic."""
# Domain-specific validation
if command_data.get("risk_level", 0) > 5:
return CommandValidationResult(
allowed=False,
safety_level=SafetyLevel.CRITICAL,
warnings=[],
required_confirmations=[],
blocked_reason="Risk level too high"
)
return CommandValidationResult(
allowed=True,
safety_level=SafetyLevel.SAFE,
warnings=[],
required_confirmations=[]
)tests/
├── unit/
│ ├── test_voice_manager.py
│ ├── test_llm_controller.py
│ ├── test_vehicle_interface.py
│ ├── test_hvac_controller.py
│ └── test_safety_monitor.py
├── integration/
│ ├── test_system_integration.py
│ └── test_voice_to_action.py
├── fixtures/
│ ├── audio_samples/
│ └── vehicle_data/
└── conftest.py
# tests/unit/test_hvac_controller.py
import pytest
import asyncio
from unittest.mock import Mock, AsyncMock
from controllers.hvac_controller import HVACController, HVACMode
@pytest.fixture
def mock_vehicle_manager():
"""Mock vehicle manager for testing."""
mock = Mock()
mock.get_parameter = AsyncMock(return_value=None)
mock.set_parameter = AsyncMock(return_value=True)
return mock
@pytest.fixture
async def hvac_controller(mock_vehicle_manager):
"""HVAC controller fixture."""
controller = HVACController(mock_vehicle_manager)
await controller.initialize()
return controller
@pytest.mark.asyncio
async def test_set_temperature_celsius(hvac_controller):
"""Test setting temperature in Celsius."""
result = await hvac_controller.set_temperature(22.0, "both", "celsius")
assert result["success"] is True
assert result["temperature_celsius"] == 22.0
assert result["temperature_fahrenheit"] == 71.6
@pytest.mark.asyncio
async def test_temperature_limits(hvac_controller):
"""Test temperature limit enforcement."""
# Test upper limit
result = await hvac_controller.set_temperature(50.0, "both", "celsius")
assert result["success"] is False
assert "outside safe range" in result["error"]
# Test lower limit
result = await hvac_controller.set_temperature(10.0, "both", "celsius")
assert result["success"] is False
@pytest.mark.asyncio
async def test_fan_speed_control(hvac_controller):
"""Test fan speed control."""
result = await hvac_controller.set_fan_speed(5)
assert result["success"] is True
assert result["fan_speed"] == 5# tests/integration/test_voice_to_action.py
import pytest
from src.main import AutomotiveLLMSystem
@pytest.mark.asyncio
async def test_voice_command_pipeline():
"""Test complete voice command pipeline."""
# Setup system in mock mode
system = AutomotiveLLMSystem()
system.settings.mock_mode = True
assert await system.initialize()
# Simulate voice command
await system._handle_voice_command(
VoiceCommand(
text="set temperature to 72 degrees",
confidence=0.95,
timestamp=time.time(),
wake_word="hey-car",
processing_time=0.2
)
)
# Verify system state
hvac_status = await system.hvac_controller.get_status()
assert hvac_status["driver_temp_celsius"] == 22.2 # 72°F in Celsius# tests/fixtures/mock_vehicle.py
class MockVehicleData:
"""Provides realistic mock vehicle data."""
@staticmethod
def get_engine_parameters():
return {
"engine_rpm": 850.0,
"engine_temp": 95.0,
"oil_pressure": 45.0,
"throttle_pos": 0.0
}
@staticmethod
def get_hvac_status():
return {
"driver_temp": 22.0,
"fan_speed": 3,
"mode": "auto"
}# tests/fixtures/audio_helpers.py
import numpy as np
def generate_test_audio(duration: float, sample_rate: int = 16000) -> np.ndarray:
"""Generate test audio signal."""
t = np.linspace(0, duration, int(sample_rate * duration))
# Generate simple sine wave
frequency = 440 # A4 note
return np.sin(2 * np.pi * frequency * t).astype(np.float32)
def load_test_wake_word() -> np.ndarray:
"""Load pre-recorded wake word for testing."""
# In real implementation, would load actual audio file
return generate_test_audio(1.0) # 1 second of test audioconfig/
├── development.yaml
├── testing.yaml
├── production.yaml
└── vehicle-profiles/
├── ford-mustang-1970.yaml
├── chevrolet-camaro-1969.yaml
└── generic-classic.yaml
# config/vehicle-profiles/ford-mustang-1970.yaml
vehicle:
make: "ford"
model: "mustang"
year: 1970
engine_type: "v8"
safety:
max_boost_pressure: 8.0 # Conservative for classic engine
engine_temp_warning: 100.0
engine_temp_critical: 105.0
max_rpm: 6000.0
hvac:
# Classic car may not have advanced HVAC
min_temperature: 18.0
max_temperature: 30.0
max_fan_speed: 4
dual_zone: false
can_messages:
# Vehicle-specific CAN message definitions
hvac_temp_set:
id: 0x3F1
dlc: 8
encoding: "temp_celsius_offset_40_scale_2"def load_vehicle_profile(make: str, model: str, year: int) -> Dict[str, Any]:
"""Load vehicle-specific configuration."""
profile_name = f"{make}-{model}-{year}.yaml"
profile_path = f"config/vehicle-profiles/{profile_name}"
if os.path.exists(profile_path):
with open(profile_path, 'r') as f:
return yaml.safe_load(f)
# Fallback to generic profile
with open("config/vehicle-profiles/generic-classic.yaml", 'r') as f:
return yaml.safe_load(f)# Quick development start
python src/main.py --debug --config config/development.yaml# Systemd service for production
sudo systemctl start automotive-llm.service
sudo systemctl enable automotive-llm.service# Dockerfile
FROM python:3.11-slim
# Install system dependencies
RUN apt-get update && apt-get install -y \
portaudio19-dev \
can-utils \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src/ ./src/
COPY config.yaml .
CMD ["python", "src/main.py"]- Follow PEP 8
- Use Black for formatting
- Maximum line length: 88 characters
- Use type hints for all functions
- Document all public methods
# Classes: PascalCase
class VehicleManager:
# Functions and methods: snake_case
def get_engine_temperature():
# Constants: UPPER_CASE
MAX_BOOST_PRESSURE = 20.0
# Private methods: _leading_underscore
def _internal_method():def calculate_fuel_economy(distance: float, fuel_used: float) -> float:
"""Calculate fuel economy in miles per gallon.
Args:
distance: Distance traveled in miles
fuel_used: Fuel consumed in gallons
Returns:
Fuel economy in miles per gallon
Raises:
ValueError: If fuel_used is zero or negative
"""
if fuel_used <= 0:
raise ValueError("Fuel used must be positive")
return distance / fuel_usedfeature/description- New featuresbugfix/description- Bug fixeshotfix/description- Critical fixesdocs/description- Documentation updates
type(scope): Short description
Longer description if needed
- Bullet points for multiple changes
- Reference issues: Fixes #123
Co-authored-by: Name <email>
- Create feature branch from
main - Implement changes with tests
- Update documentation
- Run full test suite
- Create pull request with description
- Address review feedback
- Merge after approval
- Never commit secrets or API keys
- Use environment variables for sensitive data
- Validate all external inputs
- Implement proper error handling
- Always implement safety checks
- Test thoroughly before vehicle integration
- Document all safety assumptions
- Review changes affecting vehicle control
- Minimize data collection
- Encrypt sensitive data
- Provide data deletion capabilities
- Document data handling practices
import time
import psutil
from dataclasses import dataclass
@dataclass
class PerformanceMetrics:
cpu_usage: float
memory_usage: float
response_time: float
async def monitor_performance():
"""Monitor system performance metrics."""
start_time = time.time()
# Your code here
response_time = time.time() - start_time
cpu_usage = psutil.cpu_percent()
memory_usage = psutil.virtual_memory().percent
return PerformanceMetrics(cpu_usage, memory_usage, response_time)# Good: Concurrent operations
async def process_multiple_commands(commands):
tasks = [process_command(cmd) for cmd in commands]
results = await asyncio.gather(*tasks)
return results
# Bad: Sequential operations
async def process_multiple_commands_slow(commands):
results = []
for cmd in commands:
result = await process_command(cmd)
results.append(result)
return resultsclass ResourceManager:
def __init__(self):
self.resources = []
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
for resource in self.resources:
await resource.cleanup()def monitor_memory_usage():
"""Monitor and log memory usage."""
process = psutil.Process()
memory_info = process.memory_info()
logging.info(f"Memory usage: {memory_info.rss / 1024 / 1024:.1f} MB")
if memory_info.rss > 1024 * 1024 * 1024: # 1GB
logging.warning("High memory usage detected")import structlog
logger = structlog.get_logger()
logger.info(
"Command executed",
command_type="temperature_set",
target_temp=72,
zone="driver",
processing_time=0.156
)# Enable debug logging
logging.getLogger().setLevel(logging.DEBUG)
# Add performance timing
@functools.wraps(func)
def timed_execution(func):
async def wrapper(*args, **kwargs):
start = time.time()
result = await func(*args, **kwargs)
duration = time.time() - start
logger.debug(f"{func.__name__} took {duration:.3f}s")
return result
return wrapper# Problem: Blocking operations in async functions
def bad_async_function():
time.sleep(1) # Blocks event loop
# Solution: Use async alternatives
async def good_async_function():
await asyncio.sleep(1) # Non-blocking# Problem: Unclosed resources
stream = await create_stream()
# ... use stream
# Missing: await stream.close()
# Solution: Use context managers
async with create_stream() as stream:
# ... use stream
pass # Automatically closedThis developer guide provides the foundation for extending and maintaining the Automotive LLM System. Always prioritize safety and testing when making changes that affect vehicle control systems.