AquaGPT - AI Assistant
AI-powered conversational assistant that provides natural language insights about water consumption, trends, alerts, and analytics. Ask questions in plain English and get instant, intelligent responses about your water data.
Overview
AquaGPT is an intelligent chatbot interface that leverages AI to help users understand their water data without complex dashboards or reports. It supports conversation history, like/dislike feedback, and provides contextual responses based on your organization's real-time and historical water data.
Location: libs/aquagpt/
Route: /aquagpt
Permission Required: AQUAGPT
Key Features
1. Natural Language Queries
Ask questions in plain English:
Example Queries:
- "Tell me about summary data of today"
- "Give me insights on yesterday's data"
- "What is my yesterday's water balance?"
- "Show me consumption trends for the past week"
- "Which units had leakage alerts today?"
- "What was my total water usage last month?"
2. Conversation Starters (FAQ)
Pre-defined quick-start prompts for common queries:
const conversationStarters = [
{
icon: <FeedOutlinedIcon />,
label: 'Tell me about summary data of today',
prompt: 'Tell me about summary data of today'
},
{
icon: <WaterDropOutlinedIcon />,
label: "Give me insights on yesterday's data",
prompt: "Give me insights on yesterday's data"
},
{
icon: <LegendToggleOutlinedIcon />,
label: "What is my yesterday's water balance",
prompt: "What is my yesterday's water balance"
}
];
3. Chat History & Session Management
Features:
- Session-Based Conversations - Each chat session has a unique ID
- Persistent History - View past conversations (Today, Yesterday, Past 4 Days)
- Chat Sidebar - Browse previous chats organized by date
- Continue Conversations - Click on old chats to view and continue
Session ID Format:
const sessionId = `${userId}_${timestamp}`;
// Example: "user123_1709123456789"
4. Interactive Responses
Response Features:
- Typing Animation - Character-by-character streaming effect
- HTML Rendering - Supports formatted responses with links, lists, tables
- Copy Functionality - One-click copy of AI responses
- Like/Dislike - Provide feedback on response quality
5. Real-Time Data Integration
AquaGPT queries your live water data:
- Current consumption and stock levels
- Recent alerts and anomalies
- Water quality readings
- Flow rates and trends
- Historical patterns
Architecture
Data Flow
Key Components
1. AquaGptContextProvider
- Purpose: Global state management for AquaGPT
- Location:
libs/aquagpt/src/store/AquaGptStore.js - State Variables:
previousChatData- Historical chats (today, yesterday, past 4 days)currentChatArray- Active conversation messageschatResponse- Latest AI responseisLoading- Initial loading stateisGettingResponse- Response generation in progressselectedChat- Currently viewing old chatsessionId- Unique conversation identifier
Context Value:
{
previousChatData: {
today: [...],
yesterday: [...],
past4Days: [...]
},
currentChatArray: [
{ prompt: "...", type: "prompt", sessionId: "..." },
{ response: "...", type: "response", id: "...", showLikedComponent: true }
],
chatResponse: { id, prompt, response, date, showLikedComponent },
isLoading: false,
isGettingResponse: false,
selectedChat: null,
sessionId: "user123_1709123456789",
getGptResponse: (prompt) => {},
patchReplyLikeStatus: (messageId, isLiked, prompt) => {}
}
2. AquaGpt (Main Component)
- Purpose: Main AquaGPT page layout
- Location:
libs/aquagpt/src/AquaGpt.jsx - Features:
- Sidebar with chat history
- Main chat area
- Responsive drawer for mobile
- New chat button
3. AquaGptChat
- Purpose: Current conversation interface
- Location:
libs/aquagpt/src/components/AquaGptChat.jsx - Features:
- Conversation starter cards (FAQ)
- Message list with auto-scroll
- Input field with send button
- Typing animation for responses
4. OldChatComponent
- Purpose: Display previous conversations
- Location:
libs/aquagpt/src/components/OldChatComponent.jsx - Features:
- Read-only chat view
- Like/dislike feedback
- Copy functionality
5. AiSideBar
- Purpose: Chat history sidebar
- Location:
libs/aquagpt/src/components/AiSideBar.jsx - Features:
- New chat button
- Chat grouping by date (Today, Yesterday, Past 4 Days)
- Click to load old conversations
- Responsive collapse/expand
6. TypingAnimation
- Purpose: Animate AI response character-by-character
- Location:
libs/aquagpt/src/components/TypingAnimation.jsx - Features:
- Streaming text effect
- Auto-scroll as text appears
- HTML content rendering
7. EmojiComponent
- Purpose: Like/dislike feedback and copy buttons
- Location:
libs/aquagpt/src/components/EmojiComponent.jsx - Features:
- Thumbs up/down icons
- Copy to clipboard button
- Feedback submission to backend
API Integration
Get GPT Response
POST /gpt/aqua
Request Body: {
prompt: "Tell me about summary data of today",
sessionId: "user123_1709123456789",
baseURL: "https://aquagen.example.com"
}
Response: {
data: {
id: "gpt_msg_12345",
date: "25/02/2026",
prompt: "Tell me about summary data of today",
response: "<p>Here's today's water summary...</p>",
showLikedComponent: true
}
}
Response Types:
Success:
{
id: "gpt_msg_12345",
date: "25/02/2026",
prompt: "What is my water usage?",
response: "<p>Your total water usage today is <strong>1,234 kL</strong>...</p>",
showLikedComponent: true
}
Connection Error:
{
id: "generated_id",
date: "25/02/2026",
prompt: "...",
response: "Failed to connect to the server!",
showLikedComponent: false
}
Understanding Error:
{
id: "generated_id",
date: "25/02/2026",
prompt: "...",
response: "I was unable to understand. I can help you with understanding of your consumption trend, stock usage etc.",
showLikedComponent: false
}
Get Past Responses
GET /getGptPastResponse
Params: {
numberOfDays: 3
}
Response: {
data: [
{
today: [
{
id: "msg1",
date: "25/02/2026",
prompt: "Today's summary",
response: "...",
isLiked: true
}
],
yesterday: [...],
past4Days: [...]
}
]
}
Submit Like/Dislike Feedback
PATCH /patchLikeStatus
Request Body: {
id: "gpt_msg_12345",
isLiked: true, // or false
prompt: "Tell me about summary data of today"
}
Response: {
status: 200,
message: "Feedback submitted successfully"
}
Usage Examples
1. Initialize AquaGPT
import AquaGpt from '@aquagen-mf-webapp/aquagpt';
function AquaGPTPage() {
return <AquaGpt />;
}
2. Access AquaGPT Context
import { useContext } from 'react';
import { AquaGptContext } from '@aquagen-mf-webapp/aquagpt';
function CustomAIComponent() {
const aiStore = useContext(AquaGptContext);
const handleAskQuestion = () => {
aiStore.getGptResponse("What is my water consumption today?");
};
return (
<div>
<button onClick={handleAskQuestion}>Ask AI</button>
{aiStore.isGettingResponse && <Loader />}
</div>
);
}
3. Submit User Query
const handleGetResponse = (e) => {
e.preventDefault();
if (!question.trim()) return;
// Send question to AI
aiStore.getGptResponse(question);
// Clear input
setQuestion('');
};
4. Use Conversation Starters
const handleStarterClick = (starterPrompt) => {
// Send predefined question
aiStore.getGptResponse(starterPrompt);
// Update input field
setQuestion(starterPrompt);
};
<ButtonBase onClick={() => handleStarterClick("Tell me about summary data of today")}>
<FeedOutlinedIcon />
<Typography>Tell me about summary data of today</Typography>
</ButtonBase>
5. Provide Feedback
const handleLikeFeedback = async (messageId, isLiked, prompt) => {
const response = await aiStore.patchReplyLikeStatus(
messageId,
isLiked,
prompt
);
if (response.status === 200) {
console.log('Feedback submitted successfully');
}
};
// Like
<IconButton onClick={() => handleLikeFeedback(message.id, true, message.prompt)}>
<ThumbUpIcon />
</IconButton>
// Dislike
<IconButton onClick={() => handleLikeFeedback(message.id, false, message.prompt)}>
<ThumbDownIcon />
</IconButton>
6. View Old Conversations
const handleViewOldChat = (chat) => {
// Set selected chat to view mode
aiStore.setSelectedChat(chat);
// Clear current conversation
aiStore.setCurrentChatArray([]);
aiStore.setChatResponse(null);
};
7. Start New Chat
import { GptHelper } from '@aquagen-mf-webapp/aquagpt/helper/gptHelper';
const handleNewChat = () => {
GptHelper.openNewChat(aiStore);
// This will:
// - Clear current conversation
// - Reset selected chat
// - Generate new session ID
};
Message Format
User Prompt Message
{
prompt: "What is my water usage today?",
sessionId: "user123_1709123456789",
type: "prompt"
}
AI Response Message
{
id: "gpt_msg_12345",
date: "25/02/2026",
prompt: "What is my water usage today?",
response: "<p>Your total water usage today is <strong>1,234 kL</strong>...</p>",
type: "response",
showLikedComponent: true,
isLiked: null // or true/false after feedback
}
Chat History Grouping
Date Types:
AquaGptEnum.DateType = {
today: 'Today',
yesterday: 'Yesterday',
ndays: 'Past 4 Days'
};
Sidebar Structure:
├── Today
│ ├── Chat 1 (10:30 AM)
│ ├── Chat 2 (02:15 PM)
│ └── Chat 3 (04:45 PM)
├── Yesterday
│ ├── Chat 1 (09:00 AM)
│ └── Chat 2 (05:30 PM)
└── Past 4 Days
├── Chat 1 (Feb 23)
└── Chat 2 (Feb 22)
Responsive Design
Desktop (md+):
- Sidebar visible by default
- Main chat area 80% width
- Menu button hidden when sidebar open
Mobile (xs-sm):
- Sidebar collapsed by default
- Menu button visible
- Full-width chat area
- Drawer overlay for sidebar
Breakpoint Logic:
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
useEffect(() => {
if (isMobile) {
setOpenSideBar(false);
} else {
setOpenSideBar(true);
}
}, [isMobile]);
Auto-Scroll Behavior
Auto-Scroll Logic:
const [isAutoScroll, setIsAutoScroll] = useState(true);
const scrollToBottom = () => {
if (!isAutoScroll) return;
chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;
};
const handleScroll = () => {
const container = chatContainerRef.current;
const isUserNearBottom =
container.scrollHeight - container.scrollTop <= container.clientHeight;
setIsAutoScroll(isUserNearBottom);
};
Features:
- Auto-scrolls when new messages arrive
- Disables auto-scroll if user scrolls up
- Re-enables when user scrolls to bottom
Error Handling
1. Connection Failure
if (!gptResponse || gptResponse.status !== 200) {
return {
data: {
id: generateId(),
date: today(),
prompt: params.prompt,
response: 'Failed to connect to the server!',
showLikedComponent: false
}
};
}
2. Empty or Invalid Response
if (!gptResponse.data || gptResponse.data.data.response.length === 0) {
return {
data: {
id: generateId(),
date: today(),
prompt: params.prompt,
response: 'I was unable to understand. I can help you with understanding of your consumption trend, stock usage etc.',
showLikedComponent: false
}
};
}
3. Graceful Degradation
- Shows error message in chat interface
- Allows user to retry with different question
- Maintains chat history even with errors
Analytics Integration
Track User Interactions:
// Page view
AnalyticsService.sendEvent(AnalyticEvents.PAGE_VIEW, {}, true);
// Question sent
AnalyticsService.sendEvent(AnalyticEvents.AQUAGPT_SEND, {
prompt: prompt
});
// Feedback submitted
AnalyticsService.sendEvent(AnalyticEvents.AQUAGPT_LIKE, {
isLiked: isLiked,
prompt: prompt
});
Best Practices
1. Always Use Context Provider
<AquaGptContextProvider>
<YourComponent />
</AquaGptContextProvider>
2. Handle Loading States
const { isLoading, isGettingResponse } = useContext(AquaGptContext);
if (isLoading) return <Loader />;
<button disabled={isGettingResponse || !question}>
Send
</button>
3. Sanitize HTML Responses
Responses are rendered using dangerouslySetInnerHTML - ensure backend sanitizes HTML to prevent XSS attacks.
<div dangerouslySetInnerHTML={{ __html: message.response }} />
4. Clear Input After Sending
const handleSubmit = (e) => {
e.preventDefault();
aiStore.getGptResponse(question);
setQuestion(''); // Clear input
};
5. Provide Conversation Starters
Help users understand what questions they can ask:
const starters = [
"Today's water summary",
"Yesterday's consumption trends",
"Water balance analysis"
];
Troubleshooting
Chat History Not Loading
Cause: API error or missing numberOfDays param Solution: Check console and verify API response
const response = await AquagptController.getGptPastResponse({ numberOfDays: 3 });
Response Not Streaming
Cause: TypingAnimation not mounted or chatResponse not set Solution: Ensure chatResponse is set after getGptResponse
setChatResponse(gptResponse.data);
Sidebar Not Opening
Cause: Responsive breakpoint issue Solution: Check isMobile state and openSideBar toggle
Related Documentation
- Routes - AquaGPT route configuration
- Permissions - AQUAGPT permission required
- API & Services - API client integration
- Analytics - Analytics event tracking
Last Updated: February 2026
Module Location: libs/aquagpt/