Cooee: AI Chatbot for Energy Analytics
Natural-language access to a billion-point, 200+ table live energy data space, for both internal engineers and the public, without writing a query
A chatbot for a university energy analytics platform that grew from a single NLU/generative pipeline into a multi-agent RAG architecture serving both an internal, database-connected assistant and a public one over open documentation.
- LLM agents
- Text-to-SQL
- RAG
- Contextualized QA
- Vector databases
- Prompt engineering
- OpenAI ChatGPT
- Python
- ReactJS
- Flask
- Azure
Problem
La Trobe’s Energy Analytics Platform (LEAP) held a genuinely large, live data space: over a billion data points across electricity consumption, gas consumption and solar generation, streamed every 15 minutes across more than 200 tables. Getting a straight answer out of it meant knowing the schema and writing SQL, which ruled out almost everyone who might actually want to ask “why did the library use so much power last Tuesday.” A conventional chatbot wasn’t going to close that gap either: hardwired routines and FAQ-style string matching only work when the question set is small and fixed, and this one wasn’t.
The audience also split in two. Developers needed to resolve questions about specific measures at specific times, wired to the live database. Everyone else needed general answers from open, unstructured material, without ever touching the internal data space.
Approach
The first version, Cooee, was structured as three modules rather than one opaque model:
- NLU module: intent classification, pattern matching, text-to-SQL and entity extraction, plus a contextualized question-answering component that resolves ambiguity, rectifies incomplete questions and does coreference resolution against the user’s own chat history. “Can you visualize that on Nov 17” only works if the system remembers what “that” refers to.
- Insight generation module: locates the relevant slice of the dynamic data space and extracts the actual insight, whether that’s an anomaly, a comparison or a trend, not just a raw number.
- NLG module: turns the result back into a response, including unit extraction so figures come back with the right units attached.
A generative model (ChatGPT) sat alongside this pipeline for the parts that structured processing alone can’t do well: language inference, open-ended elucidation, and generating suggestions or conclusions from what the earlier stages surfaced.
The architecture then split into two deployments over shared retrieval infrastructure: an internal assistant wired to the live database for precise, time-specific questions, and a public assistant with retrieval-augmented generation over a vector store of open documentation. Pattern matching on the query routed each question to the right combination of structured lookup and retrieval. Keeping the two deployments separate was a deliberate boundary: a single assistant with permission checks would have been one prompt-injection away from leaking internal measures into public answers.
Result
Deployed and evaluated against LEAP’s live data space: explaining consumption anomalies, comparing expected against actual usage with an on-the-fly chart, and answering open questions about specific infrastructure projects, from both the internal, database-connected assistant and the public one. The original chatbot was published as Cooee: An Artificial Intelligence Chatbot for Complex Energy Environments at IEEE HSI 2022, with the ChatGPT integration described in Augmenting Industrial Chatbots in Energy Systems using ChatGPT Generative AI at IEEE ISIE 2023. The later multi-agent RAG architecture was published as Multi-Agent RAG Chatbot Architecture for Decision Support in Net-Zero Emission Energy Systems at IEEE ICIT 2024, and the platform it was built into won a TEFMA Clever Campus Innovation Award.
What I’d do differently
Early versions leaned on pattern matching for routing before ambiguity resolution and coreference handling existed, and the rules accumulated until intent classification would clearly have been simpler to maintain. I’d build that handling in from the start rather than growing a pattern set until its limits became the thing actually blocking progress.