An LLM agent that diagnoses vehicle faults by reasoning over decoded CAN bus signals — not by chatting with documents.
Companion project: can-telemetry-dashboard — a real-time async dashboard for watching CAN signals live as they happen, versus this project's after-the-fact diagnostic Q&A over a completed log.
Ask a question in plain English ("why did the controller overheat fault occur?") and the model calls real signal-lookup tools to retrieve actual decoded values and DTC (Diagnostic Trouble Code) events, then explains the fault grounded in that data.
CAN bus data is structured, high-frequency time-series — not documents. A
vector-search/RAG pipeline (the common "chat with your PDF" pattern) is the
wrong tool here: there's nothing to semantically embed, and naive retrieval
can't answer "what was ControllerTemp doing in the 10 seconds before this
fault?" Instead, the LLM is given a small set of typed tools
(search_signals, get_signal_trace, get_signal_stats, get_dtc_faults)
and decides which to call based on the question, then reasons over the
structured result it gets back. Every number the model cites was actually
retrieved from the log, never hallucinated.
CAN log (.log) + DBC file
│
▼
decoder.py -- parses candump-style log against the DBC,
│ produces a long-format pandas DataFrame
│ (timestamp, message, signal, value)
▼
tools.py -- typed query functions over that DataFrame
│ (signal search, time-windowed stats/traces,
│ DTC fault extraction)
▼
agent.py -- provider-agnostic function-calling loop
│ (Anthropic or OpenAI -- picked via env var)
▼
app.py / cli.py -- Streamlit chat UI or terminal chat loop
pip install -r requirements.txt
# Generate the bundled synthetic demo log (already included, but regenerate with:)
python data/generate_demo_log.py
# Set ONE of these depending on which provider you want to use
export GROQ_API_KEY=gsk_... # free, no credit card -- console.groq.com
# or
export ANTHROPIC_API_KEY=sk-ant-...
# or
export OPENAI_API_KEY=sk-...Groq is the free option -- console.groq.com, sign up with email/Google, no payment method required, generate a key under "API Keys". It runs Llama 3.3 70B (which supports tool-calling) on Groq's own hardware, completely free within generous rate limits. Anthropic/OpenAI are paid, pay-as-you-go.
# Quick terminal chat
python cli.py
# Full chat UI
streamlit run app.pyThe bundled data/demo_drive.log is synthetic data (generated by
data/generate_demo_log.py, not real vehicle data) simulating ~60 seconds of
driving where sustained high throttle causes the motor controller to overheat:
ControllerTemp climbs steadily from ~45°C, crosses the 145°C thermal limit
at t≈41.6s, trips a P0C31_CONTROLLER_OVERTEMP DTC, and the drivetrain enters
a derate state (reduced torque) while the controller cools.
Try asking:
- "Why did the controller overheat fault occur?"
- "What was the throttle position doing in the 20 seconds before the fault?"
- "How long did it take to cool down after the derate kicked in?"
- "Were there any battery-related faults?"
To use your own real CAN logs/DBC instead: uncheck "use bundled demo data" in
the Streamlit sidebar and upload your own .dbc and .log files, or point
cli.py's DBC_PATH/LOG_PATH at them directly.
pytest tests/The test suite covers the decoder and tools layer end-to-end (no API key needed) — including a sanity check that the synthetic fault scenario itself is coherent (temperature genuinely rises before the fault, not a scripted jump).
dbc/ DBC file(s) defining the CAN bus signal layout
data/ Synthetic log generator + generated demo log
src/
decoder.py Log parsing + DBC decoding -> pandas DataFrame
tools.py Typed query functions exposed to the LLM agent
agent.py Provider-agnostic tool-calling agent loop
tests/ pytest suite for decoder + tools
app.py Streamlit chat UI
cli.py Terminal chat loop