uOttaChat is a chatbot service built by the uOttaHack team (the University of Ottawa's hackathon) and released as an open-source project for the hackathon community. It enables participants to ask questions about the event and receive real-time, context-aware responses through live sites & Discord integration.
Note: Anyone implementing this service should include a disclaimer stating that LLMs can make mistakes and that critical information should be double-checked.
- Features
- Architecture
- Local Development & Setup
- Usage
- Configuration
- Prompt Engineering & Customization
- Frontend Integration
- Contributing
- License
- Real-Time Information: Dynamic event details, FAQs, and schedules
- Context-Aware Responses: Intelligent handling of follow-up questions
- Custom Chained Prompts: Two-step response system for accuracy
- Reference Data Injection: Dynamic event data integration
- Discord Integration: Native Discord bot functionality
- NGINX & SSL Support: Production-ready deployment scripts
-
FastAPI Chat API:
/chat
endpoint for query processing- In-memory session store with TTL
- Cohere API integration with reflection step
-
Discord Bot:
- WebSocket-based Discord integration
- Mention/command listening
- Synchronized responses with API
- Clone the repository:
git clone https://github.com/uOttaHack/uotta-chatbot.git
cd uotta-chatbot
- Set up Python virtual environment:
python3 -m venv venv
source venv/bin/activate # On Windows, use: venv\Scripts\activate
- Install dependencies:
pip install -r requirements.txt
- Configure environment variables:
cp .env.example .env
# Open .env file and update with your credentials
- Start the server:
uvicorn app:app --reload
POST /chat
{
"userMessage": "What time does opening ceremonies start?"
}
Mention the bot in your specified server: @uOttaHack_bot your question here
Key environment variables:
PORT=8000
COHERE_API_KEY_TRIAL=your_key_here
REF_DATA_API_URL=your_hackathon_api_data_reference_url
ALLOWED_ORIGIN=your_hackathon_live_site_url (any front-end url using the chatbot)
The chatbot uses a two-step prompting system with dynamic reference data injection:
# Fetch your hackathon's "source of truth"
reference_data = {
"schedule": [...],
"faq": [...],
"venue": {...}
}
- Initial Response:
{
"messages": [
{
"role": "system",
"content": "You are the official hackathon assistant..."
},
{
"role": "user",
"content": user_message
}
],
"documents": [reference_data]
}
- Reflection Step:
{
"messages": [
# Previous context
{
"role": "system",
"content": "Review and improve the previous response..."
}
],
"documents": [reference_data]
}
Here's an example React component we built and integrated into our live site (live.uottahack.ca/chat):
import React, { useState } from 'react';
import axios from 'axios';
interface Message {
text: string;
from: 'user' | 'chatbot';
}
const Chat: React.FC = () => {
const [message, setMessage] = useState('');
const [messages, setMessages] = useState<Message[]>([]);
const [isSending, setIsSending] = useState(false);
const sendMessage = async (e: React.FormEvent) => {
e.preventDefault();
if (message.trim()) {
// Add user message to chat
setMessages(prev => [...prev, { text: message, from: 'user' }]);
setMessage('');
setIsSending(true);
try {
// Send message to API
const response = await axios.post('https://api.uottahack.ca/chat', {
userMessage: message
});
// Add bot response to chat
if (response.data.botMessage) {
setMessages(prev => [...prev, {
text: response.data.botMessage,
from: 'chatbot'
}]);
}
} catch (error) {
console.error('Error:', error);
setMessages(prev => [...prev, {
text: 'Sorry, something went wrong. Please try again.',
from: 'chatbot'
}]);
}
setIsSending(false);
}
};
return (
<div className="chat-container">
{/* Messages Display */}
<div className="messages-list">
{messages.map((msg, index) => (
<div key={index} className={`message ${msg.from}`}>
{msg.text}
</div>
))}
</div>
{/* Message Input Form */}
<form onSubmit={sendMessage}>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Message uOttaChat"
disabled={isSending}
/>
<button type="submit" disabled={isSending}>
Send
</button>
</form>
</div>
);
};
export default Chat;
- Fork the repository
- Create your feature branch
- Commit your changes
- Open a pull request
MIT License - see LICENSE for details.
Join our uOttaHack general community Discord, feel free to ask us questions about uOttaChat! Join Discord