Commit ·
d4e8d9b
0
Parent(s):
Deploy chatbot to Hugging Face Space
Browse files- .dockerignore +26 -0
- Dockerfile +17 -0
- README.md +306 -0
- app.py +176 -0
- cli_chat.py +54 -0
- event_service.py +117 -0
- faq.json +373 -0
- intent_classifier.py +105 -0
- requirements.txt +11 -0
.dockerignore
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
| 2 |
+
*.pyc
|
| 3 |
+
*.pyo
|
| 4 |
+
*.pyd
|
| 5 |
+
.Python
|
| 6 |
+
*.so
|
| 7 |
+
*.egg
|
| 8 |
+
*.egg-info
|
| 9 |
+
dist
|
| 10 |
+
build
|
| 11 |
+
.git
|
| 12 |
+
.gitignore
|
| 13 |
+
.env
|
| 14 |
+
.env.local
|
| 15 |
+
*.log
|
| 16 |
+
.DS_Store
|
| 17 |
+
.vscode
|
| 18 |
+
.idea
|
| 19 |
+
*.md
|
| 20 |
+
venv
|
| 21 |
+
env
|
| 22 |
+
.pytest_cache
|
| 23 |
+
.coverage
|
| 24 |
+
htmlcov
|
| 25 |
+
cli_chat.py
|
| 26 |
+
tests
|
Dockerfile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
# Hugging Face Spaces Dockerfile template
|
| 3 |
+
# Read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
|
| 4 |
+
FROM python:3.9
|
| 5 |
+
|
| 6 |
+
RUN useradd -m -u 1000 user
|
| 7 |
+
USER user
|
| 8 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 9 |
+
|
| 10 |
+
WORKDIR /app
|
| 11 |
+
|
| 12 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 13 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 14 |
+
|
| 15 |
+
COPY --chown=user . /app
|
| 16 |
+
|
| 17 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CampVerse Chatbot Microservice
|
| 2 |
+
|
| 3 |
+
## Quick Start for New Users
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
If you're new and want to run this chatbot microservice, you can choose either Docker or Python. Both methods are described below:
|
| 7 |
+
|
| 8 |
+
---
|
| 9 |
+
|
| 10 |
+
### 🚀 Run via Python (Local Development)
|
| 11 |
+
|
| 12 |
+
1. **Clone the Repository**
|
| 13 |
+
```bash
|
| 14 |
+
git clone https://github.com/CcpC-cuj/CampVerse.git
|
| 15 |
+
cd CampVerse/ML/chatbot
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
2. **Install Python & Dependencies**
|
| 19 |
+
Make sure you have Python 3.10+ installed. Then install dependencies:
|
| 20 |
+
```bash
|
| 21 |
+
pip install -r requirements.txt
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
3. **Start the Backend Service**
|
| 25 |
+
```bash
|
| 26 |
+
export BACKEND_URL=http://localhost:5001 # Set backend URL
|
| 27 |
+
uvicorn app:app_socket --host 0.0.0.0 --port 8000
|
| 28 |
+
```4. **Test with CLI Chat Client**
|
| 29 |
+
Open a new terminal and run:
|
| 30 |
+
```bash
|
| 31 |
+
python cli_chat.py
|
| 32 |
+
```
|
| 33 |
+
Type your questions and interact with the bot.
|
| 34 |
+
|
| 35 |
+
---
|
| 36 |
+
|
| 37 |
+
### 🐳 Run via Docker (Containerized)
|
| 38 |
+
|
| 39 |
+
1. **Build the Docker Image**
|
| 40 |
+
```bash
|
| 41 |
+
docker build -t chatbot-service .
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
2. **Run the Docker Container**
|
| 45 |
+
```bash
|
| 46 |
+
docker run -p 8000:8000 -e BACKEND_URL=http://localhost:5001 chatbot-service
|
| 47 |
+
```3. **Test the Service**
|
| 48 |
+
- REST API:
|
| 49 |
+
```bash
|
| 50 |
+
curl -X POST http://localhost:8000/chatbot -H "Content-Type: application/json" -d '{"question":"How do I register?"}'
|
| 51 |
+
```
|
| 52 |
+
- Socket.IO:
|
| 53 |
+
```bash
|
| 54 |
+
python cli_chat.py
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
---
|
| 58 |
+
|
| 59 |
+
### 🌐 Integrate with Your Web App
|
| 60 |
+
Use REST API or Socket.IO as shown below to connect your frontend.
|
| 61 |
+
|
| 62 |
+
---
|
| 63 |
+
|
| 64 |
+
A production-ready chatbot microservice using FastAPI, Socket.IO, and sentence transformers for FAQ-based question answering.
|
| 65 |
+
|
| 66 |
+
## Features
|
| 67 |
+
|
| 68 |
+
- 🚀 **FastAPI REST API**: HTTP endpoint for Q&A
|
| 69 |
+
- 🔌 **Socket.IO Real-time**: WebSocket support for live chat
|
| 70 |
+
- 🤖 **AI-Powered**: Uses sentence transformers and FAISS for semantic search
|
| 71 |
+
- 🎯 **Intent Classification**: Detects greetings, event queries, help requests, and more
|
| 72 |
+
- 🔍 **Dynamic Event Discovery**: Fetches and searches live events from backend API
|
| 73 |
+
- 🐳 **Docker Ready**: Containerized for easy deployment
|
| 74 |
+
- 📝 **Logging**: Comprehensive logging for debugging
|
| 75 |
+
- ✅ **Input Validation**: Validates question length and content
|
| 76 |
+
- 🌐 **CORS Enabled**: Ready for frontend integration
|
| 77 |
+
|
| 78 |
+
## Architecture
|
| 79 |
+
|
| 80 |
+
```
|
| 81 |
+
┌─────────────────┐
|
| 82 |
+
│ Frontend │
|
| 83 |
+
│ (React/Web) │
|
| 84 |
+
└────────┬────────┘
|
| 85 |
+
│
|
| 86 |
+
│ HTTP POST /chatbot
|
| 87 |
+
│ OR Socket.IO
|
| 88 |
+
│
|
| 89 |
+
┌────────▼────────┐
|
| 90 |
+
│ app.py │
|
| 91 |
+
│ FastAPI + │
|
| 92 |
+
│ Socket.IO │
|
| 93 |
+
└────────┬────────┘
|
| 94 |
+
│
|
| 95 |
+
│ Semantic Search
|
| 96 |
+
│
|
| 97 |
+
┌────────▼────────┐
|
| 98 |
+
│ faq.json │
|
| 99 |
+
│ (FAQ Database) │
|
| 100 |
+
└─────────────────┘
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
## API Endpoints
|
| 104 |
+
|
| 105 |
+
### REST API
|
| 106 |
+
|
| 107 |
+
**POST /chatbot**
|
| 108 |
+
```json
|
| 109 |
+
Request:
|
| 110 |
+
{
|
| 111 |
+
"question": "How do I register?"
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
Response:
|
| 115 |
+
{
|
| 116 |
+
"question": "How do I register?",
|
| 117 |
+
"answer": "Click on the Register button..."
|
| 118 |
+
}
|
| 119 |
+
```
|
| 120 |
+
|
| 121 |
+
### Socket.IO Events
|
| 122 |
+
|
| 123 |
+
**Client → Server**
|
| 124 |
+
- `user_question`: Send a question
|
| 125 |
+
```javascript
|
| 126 |
+
socket.emit('user_question', { question: 'How do I login?' });
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
**Server → Client**
|
| 130 |
+
- `bot_answer`: Receive answer
|
| 131 |
+
```javascript
|
| 132 |
+
socket.on('bot_answer', (data) => {
|
| 133 |
+
console.log(data.answer);
|
| 134 |
+
});
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
## Setup & Installation
|
| 138 |
+
|
| 139 |
+
### Local Development
|
| 140 |
+
|
| 141 |
+
1. **Install dependencies:**
|
| 142 |
+
```bash
|
| 143 |
+
pip install -r requirements.txt
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
2. **Run the server:**
|
| 147 |
+
```bash
|
| 148 |
+
uvicorn app:app_socket --host 0.0.0.0 --port 8000
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
3. **Test with CLI client:**
|
| 152 |
+
```bash
|
| 153 |
+
python cli_chat.py
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
### Docker Deployment
|
| 157 |
+
|
| 158 |
+
1. **Build the image:**
|
| 159 |
+
```bash
|
| 160 |
+
docker build -t chatbot-service .
|
| 161 |
+
```
|
| 162 |
+
|
| 163 |
+
2. **Run the container:**
|
| 164 |
+
```bash
|
| 165 |
+
docker run -p 8000:8000 chatbot-service
|
| 166 |
+
```
|
| 167 |
+
|
| 168 |
+
3. **Test the service:**
|
| 169 |
+
- REST API: `curl -X POST http://localhost:8000/chatbot -H "Content-Type: application/json" -d '{"question":"How do I register?"}'`
|
| 170 |
+
- Socket.IO: `python cli_chat.py`
|
| 171 |
+
|
| 172 |
+
## Project Structure
|
| 173 |
+
|
| 174 |
+
```
|
| 175 |
+
chatbot/
|
| 176 |
+
├── app.py # Main backend (FastAPI + Socket.IO)
|
| 177 |
+
├── cli_chat.py # CLI client for testing
|
| 178 |
+
├── Dockerfile # Docker configuration
|
| 179 |
+
├── faq.json # FAQ database
|
| 180 |
+
├── requirements.txt # Python dependencies
|
| 181 |
+
└── README.md # This file
|
| 182 |
+
```
|
| 183 |
+
|
| 184 |
+
## Integration with Frontend
|
| 185 |
+
|
| 186 |
+
### React Example (Socket.IO)
|
| 187 |
+
|
| 188 |
+
```javascript
|
| 189 |
+
import io from 'socket.io-client';
|
| 190 |
+
|
| 191 |
+
const socket = io('http://localhost:8000');
|
| 192 |
+
|
| 193 |
+
socket.on('connect', () => {
|
| 194 |
+
console.log('Connected to chatbot');
|
| 195 |
+
});
|
| 196 |
+
|
| 197 |
+
socket.on('bot_answer', (data) => {
|
| 198 |
+
console.log('Answer:', data.answer);
|
| 199 |
+
});
|
| 200 |
+
|
| 201 |
+
// Send question
|
| 202 |
+
socket.emit('user_question', { question: 'How do I login?' });
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
### React Example (REST API)
|
| 206 |
+
|
| 207 |
+
```javascript
|
| 208 |
+
const response = await fetch('http://localhost:8000/chatbot', {
|
| 209 |
+
method: 'POST',
|
| 210 |
+
headers: { 'Content-Type': 'application/json' },
|
| 211 |
+
body: JSON.stringify({ question: 'How do I login?' })
|
| 212 |
+
});
|
| 213 |
+
|
| 214 |
+
const data = await response.json();
|
| 215 |
+
console.log(data.answer);
|
| 216 |
+
```
|
| 217 |
+
|
| 218 |
+
## Configuration
|
| 219 |
+
|
| 220 |
+
### Environment Variables
|
| 221 |
+
|
| 222 |
+
You can configure the service using environment variables:
|
| 223 |
+
|
| 224 |
+
- `PORT`: Server port (default: 8000)
|
| 225 |
+
- `LOG_LEVEL`: Logging level (default: INFO)
|
| 226 |
+
|
| 227 |
+
### FAQ Management
|
| 228 |
+
|
| 229 |
+
Edit `faq.json` to add/update questions and answers:
|
| 230 |
+
|
| 231 |
+
```json
|
| 232 |
+
[
|
| 233 |
+
{
|
| 234 |
+
"question": "How do I register?",
|
| 235 |
+
"answer": "Click on the Register button on the homepage..."
|
| 236 |
+
}
|
| 237 |
+
]
|
| 238 |
+
```
|
| 239 |
+
|
| 240 |
+
After updating, rebuild the Docker image or restart the server.
|
| 241 |
+
|
| 242 |
+
## Monitoring & Logs
|
| 243 |
+
|
| 244 |
+
The service logs all:
|
| 245 |
+
- Client connections/disconnections
|
| 246 |
+
- Incoming questions
|
| 247 |
+
- Matched FAQ pairs
|
| 248 |
+
- Errors and warnings
|
| 249 |
+
|
| 250 |
+
View logs in Docker:
|
| 251 |
+
```bash
|
| 252 |
+
docker logs -f <container-id>
|
| 253 |
+
```
|
| 254 |
+
|
| 255 |
+
## Security
|
| 256 |
+
|
| 257 |
+
- CORS is enabled for all origins (configure for production)
|
| 258 |
+
- Input validation (max 512 characters)
|
| 259 |
+
- Error handling to prevent crashes
|
| 260 |
+
- No rate limiting (add if needed for production)
|
| 261 |
+
|
| 262 |
+
## Testing
|
| 263 |
+
|
| 264 |
+
### Manual Testing
|
| 265 |
+
|
| 266 |
+
1. Start the service
|
| 267 |
+
2. Run CLI client: `python cli_chat.py`
|
| 268 |
+
3. Type questions and verify responses
|
| 269 |
+
|
| 270 |
+
### Testing REST API
|
| 271 |
+
|
| 272 |
+
```bash
|
| 273 |
+
curl -X POST http://localhost:8000/chatbot \
|
| 274 |
+
-H "Content-Type: application/json" \
|
| 275 |
+
-d '{"question":"How do I register?"}'
|
| 276 |
+
```
|
| 277 |
+
|
| 278 |
+
## Troubleshooting
|
| 279 |
+
|
| 280 |
+
**Service won't start:**
|
| 281 |
+
- Check if port 8000 is available
|
| 282 |
+
- Verify all dependencies are installed
|
| 283 |
+
- Check logs for errors
|
| 284 |
+
|
| 285 |
+
**CLI client can't connect:**
|
| 286 |
+
- Ensure service is running on port 8000
|
| 287 |
+
- Check firewall settings
|
| 288 |
+
- Verify `python-socketio` is installed
|
| 289 |
+
|
| 290 |
+
**No answer returned:**
|
| 291 |
+
- Check if `faq.json` exists and is valid
|
| 292 |
+
- Verify the question exists in FAQ database
|
| 293 |
+
- Check server logs for errors
|
| 294 |
+
|
| 295 |
+
## Future Enhancements
|
| 296 |
+
|
| 297 |
+
- [ ] Add rate limiting for production
|
| 298 |
+
- [ ] Add authentication for Socket.IO
|
| 299 |
+
- [ ] Support multiple languages
|
| 300 |
+
- [ ] Add conversation history
|
| 301 |
+
- [ ] Implement fallback responses
|
| 302 |
+
- [ ] Add metrics and analytics
|
| 303 |
+
|
| 304 |
+
## License
|
| 305 |
+
|
| 306 |
+
Part of the CampVerse project.
|
app.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from sentence_transformers import SentenceTransformer
|
| 3 |
+
import faiss
|
| 4 |
+
import numpy as np
|
| 5 |
+
from fastapi import FastAPI, Request
|
| 6 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 7 |
+
from pydantic import BaseModel
|
| 8 |
+
import socketio
|
| 9 |
+
import logging
|
| 10 |
+
import os
|
| 11 |
+
|
| 12 |
+
# Import custom services
|
| 13 |
+
from event_service import EventService
|
| 14 |
+
from intent_classifier import IntentClassifier
|
| 15 |
+
|
| 16 |
+
# --- Logging setup ---
|
| 17 |
+
logging.basicConfig(level=logging.INFO)
|
| 18 |
+
logger = logging.getLogger("chatbot")
|
| 19 |
+
|
| 20 |
+
# --- Load resources ---
|
| 21 |
+
try:
|
| 22 |
+
df = pd.read_json('faq.json')
|
| 23 |
+
model = SentenceTransformer('all-MiniLM-L6-v2')
|
| 24 |
+
question_embeddings = model.encode(df['question'].tolist(), convert_to_tensor=True)
|
| 25 |
+
index = faiss.IndexFlatL2(question_embeddings.shape[1])
|
| 26 |
+
index.add(question_embeddings.cpu().numpy())
|
| 27 |
+
|
| 28 |
+
# Initialize event service and intent classifier
|
| 29 |
+
backend_url = os.getenv('BACKEND_URL', 'http://localhost:5000')
|
| 30 |
+
event_service = EventService(backend_url, model)
|
| 31 |
+
intent_classifier = IntentClassifier()
|
| 32 |
+
|
| 33 |
+
# Fetch events on startup
|
| 34 |
+
event_service.fetch_events()
|
| 35 |
+
|
| 36 |
+
logger.info("Resources loaded successfully.")
|
| 37 |
+
except Exception as e:
|
| 38 |
+
logger.error(f"Error loading resources: {e}")
|
| 39 |
+
raise
|
| 40 |
+
|
| 41 |
+
# --- FastAPI REST API ---
|
| 42 |
+
app = FastAPI()
|
| 43 |
+
app.add_middleware(
|
| 44 |
+
CORSMiddleware,
|
| 45 |
+
allow_origins=["*"],
|
| 46 |
+
allow_credentials=True,
|
| 47 |
+
allow_methods=["*"],
|
| 48 |
+
allow_headers=["*"],
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
class QuestionRequest(BaseModel):
|
| 52 |
+
question: str
|
| 53 |
+
|
| 54 |
+
@app.post("/chatbot")
|
| 55 |
+
async def chatbot(req: QuestionRequest, request: Request):
|
| 56 |
+
question = req.question.strip()
|
| 57 |
+
if not question:
|
| 58 |
+
logger.warning("Received empty question.")
|
| 59 |
+
return {"error": "Question cannot be empty."}
|
| 60 |
+
if len(question) > 512:
|
| 61 |
+
logger.warning("Question too long.")
|
| 62 |
+
return {"error": "Question too long."}
|
| 63 |
+
try:
|
| 64 |
+
# Classify intent
|
| 65 |
+
intent, confidence = intent_classifier.classify(question)
|
| 66 |
+
logger.info(f"Intent: {intent} (confidence: {confidence})")
|
| 67 |
+
|
| 68 |
+
# Handle specific intents
|
| 69 |
+
if intent in ['greeting', 'farewell', 'thanks', 'help', 'host_help']:
|
| 70 |
+
response = intent_classifier.get_response_for_intent(intent)
|
| 71 |
+
logger.info(f"Response for {intent}: {repr(response)}") # Debug log
|
| 72 |
+
return {
|
| 73 |
+
"question": question,
|
| 74 |
+
"answer": response,
|
| 75 |
+
"intent": intent
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
# Handle event search
|
| 79 |
+
if intent == 'event_search':
|
| 80 |
+
events = event_service.search_events(question, top_k=5)
|
| 81 |
+
response = event_service.format_event_response(events)
|
| 82 |
+
return {
|
| 83 |
+
"question": question,
|
| 84 |
+
"answer": response,
|
| 85 |
+
"intent": intent,
|
| 86 |
+
"events": events
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
# Default: FAQ search
|
| 90 |
+
user_question_embedding = model.encode(question, convert_to_tensor=True)
|
| 91 |
+
user_question_embedding_np = user_question_embedding.cpu().numpy().reshape(1, -1)
|
| 92 |
+
distances, indices = index.search(user_question_embedding_np, k=1)
|
| 93 |
+
best_match_index = indices[0][0]
|
| 94 |
+
retrieved_answer = df.iloc[best_match_index]['answer']
|
| 95 |
+
retrieved_question = df.iloc[best_match_index]['question']
|
| 96 |
+
logger.info(f"Answered question: {question} -> {retrieved_question}")
|
| 97 |
+
return {
|
| 98 |
+
"question": retrieved_question,
|
| 99 |
+
"answer": retrieved_answer,
|
| 100 |
+
"intent": intent
|
| 101 |
+
}
|
| 102 |
+
except Exception as e:
|
| 103 |
+
logger.error(f"Error processing question: {e}")
|
| 104 |
+
return {"error": "Internal server error."}
|
| 105 |
+
|
| 106 |
+
# --- Socket.IO real-time API ---
|
| 107 |
+
sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*')
|
| 108 |
+
app_socket = socketio.ASGIApp(sio, app)
|
| 109 |
+
|
| 110 |
+
@sio.event
|
| 111 |
+
def connect(sid, environ):
|
| 112 |
+
logger.info(f"Client connected: {sid}")
|
| 113 |
+
|
| 114 |
+
@sio.event
|
| 115 |
+
def disconnect(sid):
|
| 116 |
+
logger.info(f"Client disconnected: {sid}")
|
| 117 |
+
|
| 118 |
+
@sio.event
|
| 119 |
+
async def user_question(sid, data):
|
| 120 |
+
question = data.get('question', '').strip()
|
| 121 |
+
if not question:
|
| 122 |
+
await sio.emit('bot_answer', {'error': 'Question cannot be empty.'}, to=sid)
|
| 123 |
+
logger.warning(f"Empty question from {sid}")
|
| 124 |
+
return
|
| 125 |
+
if len(question) > 512:
|
| 126 |
+
await sio.emit('bot_answer', {'error': 'Question too long.'}, to=sid)
|
| 127 |
+
logger.warning(f"Long question from {sid}")
|
| 128 |
+
return
|
| 129 |
+
try:
|
| 130 |
+
# Classify intent
|
| 131 |
+
intent, confidence = intent_classifier.classify(question)
|
| 132 |
+
logger.info(f"Intent: {intent} (confidence: {confidence})")
|
| 133 |
+
|
| 134 |
+
# Handle specific intents
|
| 135 |
+
if intent in ['greeting', 'farewell', 'thanks', 'help', 'host_help']:
|
| 136 |
+
response = intent_classifier.get_response_for_intent(intent)
|
| 137 |
+
await sio.emit('bot_answer', {
|
| 138 |
+
'question': question,
|
| 139 |
+
'answer': response,
|
| 140 |
+
'intent': intent
|
| 141 |
+
}, to=sid)
|
| 142 |
+
return
|
| 143 |
+
|
| 144 |
+
# Handle event search
|
| 145 |
+
if intent == 'event_search':
|
| 146 |
+
events = event_service.search_events(question, top_k=5)
|
| 147 |
+
response = event_service.format_event_response(events)
|
| 148 |
+
await sio.emit('bot_answer', {
|
| 149 |
+
'question': question,
|
| 150 |
+
'answer': response,
|
| 151 |
+
'intent': intent
|
| 152 |
+
}, to=sid)
|
| 153 |
+
logger.info(f"SocketIO event search: {question}")
|
| 154 |
+
return
|
| 155 |
+
|
| 156 |
+
# Default: FAQ search
|
| 157 |
+
user_question_embedding = model.encode(question, convert_to_tensor=True)
|
| 158 |
+
user_question_embedding_np = user_question_embedding.cpu().numpy().reshape(1, -1)
|
| 159 |
+
distances, indices = index.search(user_question_embedding_np, k=1)
|
| 160 |
+
best_match_index = indices[0][0]
|
| 161 |
+
retrieved_answer = df.iloc[best_match_index]['answer']
|
| 162 |
+
retrieved_question = df.iloc[best_match_index]['question']
|
| 163 |
+
await sio.emit('bot_answer', {
|
| 164 |
+
'question': retrieved_question,
|
| 165 |
+
'answer': retrieved_answer,
|
| 166 |
+
'intent': intent
|
| 167 |
+
}, to=sid)
|
| 168 |
+
logger.info(f"SocketIO answered: {question} -> {retrieved_question}")
|
| 169 |
+
except Exception as e:
|
| 170 |
+
await sio.emit('bot_answer', {'error': 'Internal server error.'}, to=sid)
|
| 171 |
+
logger.error(f"SocketIO error for {sid}: {e}")
|
| 172 |
+
|
| 173 |
+
# --- For Uvicorn ---
|
| 174 |
+
if __name__ == "__main__":
|
| 175 |
+
import uvicorn
|
| 176 |
+
uvicorn.run(app_socket, host="0.0.0.0", port=8000)
|
cli_chat.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import socketio
|
| 2 |
+
import sys
|
| 3 |
+
import threading
|
| 4 |
+
import time
|
| 5 |
+
|
| 6 |
+
sio = socketio.Client()
|
| 7 |
+
user_can_input = threading.Event()
|
| 8 |
+
user_can_input.set()
|
| 9 |
+
|
| 10 |
+
@sio.event
|
| 11 |
+
def connect():
|
| 12 |
+
print("\n✅ Connected to CampVerse Chatbot!")
|
| 13 |
+
print("Type your questions below. Press Ctrl+C to exit.\n")
|
| 14 |
+
|
| 15 |
+
@sio.event
|
| 16 |
+
def disconnect():
|
| 17 |
+
print("\n❌ Disconnected from chatbot backend.")
|
| 18 |
+
|
| 19 |
+
@sio.event
|
| 20 |
+
def bot_answer(data):
|
| 21 |
+
print("\n------------------------------")
|
| 22 |
+
if 'error' in data:
|
| 23 |
+
print(f"❌ Error: {data['error']}")
|
| 24 |
+
else:
|
| 25 |
+
print(f"🤖 Bot says: {data['answer']}")
|
| 26 |
+
print(f" (Matched FAQ: {data['question']})")
|
| 27 |
+
print("------------------------------\n")
|
| 28 |
+
time.sleep(2)
|
| 29 |
+
user_can_input.set()
|
| 30 |
+
|
| 31 |
+
def ask_user():
|
| 32 |
+
while True:
|
| 33 |
+
user_can_input.wait()
|
| 34 |
+
question = input("You: ")
|
| 35 |
+
if question.strip():
|
| 36 |
+
sio.emit('user_question', {'question': question})
|
| 37 |
+
else:
|
| 38 |
+
print("⚠️ Please enter a valid question.\n")
|
| 39 |
+
user_can_input.clear()
|
| 40 |
+
|
| 41 |
+
try:
|
| 42 |
+
sio.connect('http://localhost:8000')
|
| 43 |
+
user_thread = threading.Thread(target=ask_user)
|
| 44 |
+
user_thread.daemon = True
|
| 45 |
+
user_thread.start()
|
| 46 |
+
while True:
|
| 47 |
+
pass
|
| 48 |
+
except KeyboardInterrupt:
|
| 49 |
+
print("\n👋 Goodbye!")
|
| 50 |
+
sio.disconnect()
|
| 51 |
+
sys.exit(0)
|
| 52 |
+
except Exception as e:
|
| 53 |
+
print(f"❌ Error: {e}")
|
| 54 |
+
sys.exit(1)
|
event_service.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Event Discovery Service
|
| 3 |
+
Fetches and searches events from the backend API
|
| 4 |
+
"""
|
| 5 |
+
import requests
|
| 6 |
+
import logging
|
| 7 |
+
from typing import List, Dict, Optional
|
| 8 |
+
from sentence_transformers import SentenceTransformer
|
| 9 |
+
import numpy as np
|
| 10 |
+
from sklearn.metrics.pairwise import cosine_similarity
|
| 11 |
+
|
| 12 |
+
logger = logging.getLogger("chatbot.events")
|
| 13 |
+
|
| 14 |
+
class EventService:
|
| 15 |
+
def __init__(self, backend_url: str, model: SentenceTransformer):
|
| 16 |
+
self.backend_url = backend_url
|
| 17 |
+
self.model = model
|
| 18 |
+
self.events_cache = []
|
| 19 |
+
self.events_embeddings = None
|
| 20 |
+
|
| 21 |
+
def fetch_events(self) -> List[Dict]:
|
| 22 |
+
"""Fetch all approved public events from backend"""
|
| 23 |
+
try:
|
| 24 |
+
response = requests.get(f"{self.backend_url}/api/events", timeout=5)
|
| 25 |
+
if response.status_code == 200:
|
| 26 |
+
data = response.json()
|
| 27 |
+
self.events_cache = data.get("data", {}).get("events", [])
|
| 28 |
+
logger.info(f"Fetched {len(self.events_cache)} events from backend")
|
| 29 |
+
|
| 30 |
+
# Pre-compute embeddings for all events
|
| 31 |
+
self._compute_event_embeddings()
|
| 32 |
+
return self.events_cache
|
| 33 |
+
else:
|
| 34 |
+
logger.error(f"Failed to fetch events: {response.status_code}")
|
| 35 |
+
return []
|
| 36 |
+
except Exception as e:
|
| 37 |
+
logger.error(f"Error fetching events: {e}")
|
| 38 |
+
return []
|
| 39 |
+
|
| 40 |
+
def _compute_event_embeddings(self):
|
| 41 |
+
"""Compute embeddings for all events"""
|
| 42 |
+
if not self.events_cache:
|
| 43 |
+
return
|
| 44 |
+
|
| 45 |
+
event_texts = []
|
| 46 |
+
for event in self.events_cache:
|
| 47 |
+
# Combine title, description, and tags for better matching
|
| 48 |
+
text = f"{event.get('title', '')} {event.get('description', '')} {' '.join(event.get('tags', []))}"
|
| 49 |
+
event_texts.append(text)
|
| 50 |
+
|
| 51 |
+
self.events_embeddings = self.model.encode(event_texts, convert_to_tensor=False)
|
| 52 |
+
logger.info(f"Computed embeddings for {len(event_texts)} events")
|
| 53 |
+
|
| 54 |
+
def search_events(self, query: str, top_k: int = 5) -> List[Dict]:
|
| 55 |
+
"""Search events using semantic similarity"""
|
| 56 |
+
if not self.events_cache or self.events_embeddings is None:
|
| 57 |
+
self.fetch_events()
|
| 58 |
+
|
| 59 |
+
if not self.events_cache:
|
| 60 |
+
logger.warning("No events available in cache")
|
| 61 |
+
return []
|
| 62 |
+
|
| 63 |
+
# Encode user query
|
| 64 |
+
query_embedding = self.model.encode([query], convert_to_tensor=False)
|
| 65 |
+
|
| 66 |
+
# Calculate cosine similarity
|
| 67 |
+
similarities = cosine_similarity(query_embedding, self.events_embeddings)[0]
|
| 68 |
+
|
| 69 |
+
# Log similarity scores for debugging
|
| 70 |
+
logger.info(f"Query: {query}")
|
| 71 |
+
logger.info(f"Similarity scores: min={similarities.min():.3f}, max={similarities.max():.3f}, mean={similarities.mean():.3f}")
|
| 72 |
+
|
| 73 |
+
# Get top k indices
|
| 74 |
+
top_indices = np.argsort(similarities)[::-1][:top_k]
|
| 75 |
+
|
| 76 |
+
# Filter events with similarity > threshold (lowered to 0.15 for better recall)
|
| 77 |
+
results = []
|
| 78 |
+
for idx in top_indices:
|
| 79 |
+
score = similarities[idx]
|
| 80 |
+
if score > 0.15: # Lowered threshold
|
| 81 |
+
event = self.events_cache[idx].copy()
|
| 82 |
+
event['similarity_score'] = float(score)
|
| 83 |
+
results.append(event)
|
| 84 |
+
logger.info(f" Event '{event.get('title', 'Untitled')}' matched with score {score:.3f}")
|
| 85 |
+
|
| 86 |
+
logger.info(f"Found {len(results)} matching events for query: {query}")
|
| 87 |
+
return results
|
| 88 |
+
|
| 89 |
+
def format_event_response(self, events: List[Dict]) -> str:
|
| 90 |
+
"""Format events into a conversational response"""
|
| 91 |
+
if not events:
|
| 92 |
+
return "Sorry, I couldn't find any events matching your query. Try searching for something like 'hackathon', 'AI workshop', or 'coding competition'."
|
| 93 |
+
|
| 94 |
+
response = f"I found {len(events)} event(s) for you:\n\n"
|
| 95 |
+
|
| 96 |
+
for i, event in enumerate(events, 1):
|
| 97 |
+
title = event.get('title', 'Untitled Event')
|
| 98 |
+
date = event.get('date', 'TBA')[:10] if event.get('date') else 'TBA'
|
| 99 |
+
description = event.get('description', '')
|
| 100 |
+
|
| 101 |
+
# Truncate description
|
| 102 |
+
if len(description) > 100:
|
| 103 |
+
description = description[:97] + "..."
|
| 104 |
+
|
| 105 |
+
response += f"{i}. **{title}**\n"
|
| 106 |
+
response += f" 📅 Date: {date}\n"
|
| 107 |
+
|
| 108 |
+
if description:
|
| 109 |
+
response += f" 📝 {description}\n"
|
| 110 |
+
|
| 111 |
+
# Add website link if available
|
| 112 |
+
if event.get('socialLinks', {}).get('website'):
|
| 113 |
+
response += f" 🔗 [More Info]({event['socialLinks']['website']})\n"
|
| 114 |
+
|
| 115 |
+
response += "\n"
|
| 116 |
+
|
| 117 |
+
return response.strip()
|
faq.json
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"question": "How do I register for an event?",
|
| 4 |
+
"answer": "Visit the Events section, select your event, and click 'Register.' Complete the required details to finish registration."
|
| 5 |
+
},
|
| 6 |
+
{
|
| 7 |
+
"question": "How do I sign up for CampVerse?",
|
| 8 |
+
"answer": "Welcome! To sign up, just click the 'Register' button on our homepage and fill in your details. We're excited to have you join our community!"
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"question": "Is CampVerse free to use?",
|
| 12 |
+
"answer": "Yes! CampVerse is free for all users. Some events may have entry fees, but browsing and joining the platform is always free."
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"question": "Can I get help if I'm stuck?",
|
| 16 |
+
"answer": "Absolutely! If you ever need help, just reach out via our Support page or chat with us here. We're always happy to assist you!"
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"question": "What should I do if I can't find my certificate?",
|
| 20 |
+
"answer": "No worries! Certificates are usually available in your dashboard after the event. If you can't find yours, contact support and we'll help you out."
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"question": "How do I change my password?",
|
| 24 |
+
"answer": "To change your password, go to your profile settings and select 'Change Password.' If you forgot your password, use the 'Forgot Password' link on the login page."
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"question": "Can I participate if I'm new to coding?",
|
| 28 |
+
"answer": "Of course! CampVerse welcomes everyone, whether you're a beginner or an expert. Many events are designed for all skill levels."
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"question": "How do I contact a team member?",
|
| 32 |
+
"answer": "You can message your team members directly from your dashboard or use the chat feature during events."
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"question": "What happens after I register for an event?",
|
| 36 |
+
"answer": "After registering, you'll receive a confirmation email and see the event in your dashboard. We'll keep you updated with all the important details!"
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"question": "Can I join more than one team?",
|
| 40 |
+
"answer": "You can only join one team per event, but you're welcome to participate in multiple events with different teams!"
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"question": "What are the rules for the upcoming hackathon?",
|
| 44 |
+
"answer": "Rules are available on the event details page or in the official rulebook linked there."
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"question": "When is the deadline for the coding competition?",
|
| 48 |
+
"answer": "Deadlines are listed on each event page under 'Important Dates.'"
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"question": "Where can I find the results of the last event?",
|
| 52 |
+
"answer": "Results are posted on the Results page and sent to registered participants via email."
|
| 53 |
+
},
|
| 54 |
+
{
|
| 55 |
+
"question": "Who is eligible to participate?",
|
| 56 |
+
"answer": "Eligibility criteria are shown on each event’s details page."
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"question": "How do I form a team?",
|
| 60 |
+
"answer": "You can invite users to join your team during registration or from your dashboard."
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"question": "What are the prizes?",
|
| 64 |
+
"answer": "Prize details are available on the event page under 'Prizes.'"
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"question": "How do I reset my password?",
|
| 68 |
+
"answer": "Go to the login page and click 'Forgot Password' to receive reset instructions."
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"question": "How do I contact support?",
|
| 72 |
+
"answer": "Use the Support page or submit a ticket from your dashboard."
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"question": "Can I edit my registration details?",
|
| 76 |
+
"answer": "Yes, you can update your registration from your dashboard before the event deadline."
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"question": "How do I upload required documents?",
|
| 80 |
+
"answer": "Upload documents via the event registration form or your dashboard."
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"question": "Where can I find event schedules?",
|
| 84 |
+
"answer": "Schedules are listed on each event’s details page."
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"question": "How do I verify my participation?",
|
| 88 |
+
"answer": "Verification details are sent via email and shown on your dashboard after the event."
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"question": "What is the process for certificate generation?",
|
| 92 |
+
"answer": "Certificates are generated after event completion and can be downloaded from your dashboard."
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"question": "How do I report a problem or bug?",
|
| 96 |
+
"answer": "Use the Feedback or Support section to report issues."
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"question": "How do I access the leaderboard?",
|
| 100 |
+
"answer": "The leaderboard is available on the Results or event details page."
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"question": "Can I participate in multiple events?",
|
| 104 |
+
"answer": "Yes, you can register for multiple events if eligible."
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
"question": "How do I check my eligibility status?",
|
| 108 |
+
"answer": "Your eligibility status is displayed on your dashboard and event registration page."
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"question": "How do I get notifications about upcoming events?",
|
| 112 |
+
"answer": "Enable notifications in your profile settings or check the Notifications section."
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"question": "How do I use the platform’s storage service?",
|
| 116 |
+
"answer": "Refer to the Storage Service Guide in the documentation section."
|
| 117 |
+
},
|
| 118 |
+
{
|
| 119 |
+
"question": "How do I view my achievements?",
|
| 120 |
+
"answer": "Achievements are listed in your user profile and dashboard."
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"question": "How do I update my profile information?",
|
| 124 |
+
"answer": "Go to your dashboard and select 'Edit Profile' to update your information."
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"question": "How do I join as a host or institution?",
|
| 128 |
+
"answer": "Apply through the Host/Institution registration page and follow the instructions."
|
| 129 |
+
},
|
| 130 |
+
{
|
| 131 |
+
"question": "How do I access event analytics?",
|
| 132 |
+
"answer": "Event analytics are available to hosts and institutions on their dashboard."
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"question": "How do I request a certificate re-issue?",
|
| 136 |
+
"answer": "Submit a request via the Support or Certificate section in your dashboard."
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"question": "How do I view feedback for events?",
|
| 140 |
+
"answer": "Feedback is available on the event details page and your dashboard."
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"question": "How do I manage notifications?",
|
| 144 |
+
"answer": "Notification settings can be managed from your profile page."
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"question": "How do I access secure files?",
|
| 148 |
+
"answer": "Secure files are available to eligible users via the Secure Files section in your dashboard."
|
| 149 |
+
},
|
| 150 |
+
{
|
| 151 |
+
"question": "How do I check event participation logs?",
|
| 152 |
+
"answer": "Participation logs are available in your dashboard under 'Event Participation.'"
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"question": "How do I get help with ML features?",
|
| 156 |
+
"answer": "Refer to the ML Integration documentation or contact support for assistance."
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"question": "How do I use the API?",
|
| 160 |
+
"answer": "API documentation is available in the docs section."
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"question": "How do I view or download certificates?",
|
| 164 |
+
"answer": "Certificates can be viewed and downloaded from your dashboard after event completion."
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"question": "How do I check host eligibility status?",
|
| 168 |
+
"answer": "Host eligibility status is shown on the host dashboard and event registration page."
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"question": "How do I migrate my account or data?",
|
| 172 |
+
"answer": "Migration instructions are available in the documentation or contact support for help."
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"question": "How do I access business analytics?",
|
| 176 |
+
"answer": "Business analytics are available to authorized users in the analytics dashboard."
|
| 177 |
+
},
|
| 178 |
+
{
|
| 179 |
+
"question": "How do I validate event modules?",
|
| 180 |
+
"answer": "Use the validation scripts provided in the scripts folder or contact support."
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"question": "How do I get started as a new user?",
|
| 184 |
+
"answer": "Check the Getting Started guide in the documentation and follow onboarding steps."
|
| 185 |
+
},
|
| 186 |
+
{
|
| 187 |
+
"question": "How do I access the development approach?",
|
| 188 |
+
"answer": "Development approach details are available in the DEVELOPMENT_APPROACH.md file."
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
"question": "How do I check API endpoints?",
|
| 192 |
+
"answer": "API endpoints are documented in the swagger documentation and docs section."
|
| 193 |
+
},
|
| 194 |
+
{
|
| 195 |
+
"question": "How do I use socket features?",
|
| 196 |
+
"answer": "Refer to the socketClient.js example in the examples folder."
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"question": "How do I check system status or downtime?",
|
| 200 |
+
"answer": "System status updates are posted in the Notifications section and via email."
|
| 201 |
+
},
|
| 202 |
+
{
|
| 203 |
+
"question": "How do I access the platform from mobile?",
|
| 204 |
+
"answer": "The platform is mobile-friendly and can be accessed via any browser."
|
| 205 |
+
},
|
| 206 |
+
{
|
| 207 |
+
"question": "How do I get help with frontend issues?",
|
| 208 |
+
"answer": "Refer to the Frontend TODO and error documentation or contact support."
|
| 209 |
+
},
|
| 210 |
+
{
|
| 211 |
+
"question": "How do I check my event certificates?",
|
| 212 |
+
"answer": "Event certificates are listed in your dashboard under 'Certificates.'"
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"question": "How do I get updates about new features?",
|
| 216 |
+
"answer": "Updates are announced in the Notifications section and via email."
|
| 217 |
+
},
|
| 218 |
+
{
|
| 219 |
+
"question": "How do I access storage usage details?",
|
| 220 |
+
"answer": "Storage usage details are available in your dashboard under 'Storage.'"
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"question": "How do I request event verification?",
|
| 224 |
+
"answer": "Submit a verification request from the event details page or your dashboard."
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"question": "How do I access institution features?",
|
| 228 |
+
"answer": "Institution features are available to registered institutions via their dashboard."
|
| 229 |
+
},
|
| 230 |
+
{
|
| 231 |
+
"question": "How do I check notification history?",
|
| 232 |
+
"answer": "Notification history is available in your dashboard under 'Notifications.'"
|
| 233 |
+
},
|
| 234 |
+
{
|
| 235 |
+
"question": "How do I access support tickets?",
|
| 236 |
+
"answer": "Support tickets can be viewed and managed from your dashboard under 'Support.'"
|
| 237 |
+
}
|
| 238 |
+
,
|
| 239 |
+
{
|
| 240 |
+
"question": "hi",
|
| 241 |
+
"answer": "Hi, I'm CampVerseBot! How can I help you today?"
|
| 242 |
+
},
|
| 243 |
+
{
|
| 244 |
+
"question": "hello",
|
| 245 |
+
"answer": "Hello! I'm CampVerseBot, here to assist you. What would you like to know?"
|
| 246 |
+
},
|
| 247 |
+
{
|
| 248 |
+
"question": "hey",
|
| 249 |
+
"answer": "Hey there! How can I help you at CampVerse today?"
|
| 250 |
+
},
|
| 251 |
+
{
|
| 252 |
+
"question": "good morning",
|
| 253 |
+
"answer": "Good morning! How can I help you today at CampVerse?"
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
"question": "good afternoon",
|
| 257 |
+
"answer": "Good afternoon! What can I do for you at CampVerse?"
|
| 258 |
+
},
|
| 259 |
+
{
|
| 260 |
+
"question": "good evening",
|
| 261 |
+
"answer": "Good evening! How can I assist you at CampVerse?"
|
| 262 |
+
},
|
| 263 |
+
{
|
| 264 |
+
"question": "bye",
|
| 265 |
+
"answer": "Goodbye! If you need anything else, just ask. Have a great day!"
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"question": "goodbye",
|
| 269 |
+
"answer": "Goodbye! Thanks for visiting CampVerse. See you next time!"
|
| 270 |
+
},
|
| 271 |
+
{
|
| 272 |
+
"question": "see you",
|
| 273 |
+
"answer": "See you! If you have more questions, come back anytime."
|
| 274 |
+
}
|
| 275 |
+
,
|
| 276 |
+
{
|
| 277 |
+
"question": "How do I create an account on CampVerse?",
|
| 278 |
+
"answer": "Click the 'Create Account' button on the homepage and fill in your details. You’ll receive a confirmation email to activate your account."
|
| 279 |
+
},
|
| 280 |
+
{
|
| 281 |
+
"question": "How do I verify my email address?",
|
| 282 |
+
"answer": "After signing up, check your inbox for a verification email from CampVerse. Click the link in the email to verify your address. If you don’t see it, check your spam folder or request a new verification email from your dashboard."
|
| 283 |
+
},
|
| 284 |
+
{
|
| 285 |
+
"question": "What should I do if I don’t receive a confirmation email?",
|
| 286 |
+
"answer": "First, check your spam or junk folder. If you still can’t find it, use the 'Resend Confirmation Email' option on the login page or contact support for help."
|
| 287 |
+
},
|
| 288 |
+
{
|
| 289 |
+
"question": "How do I browse and filter events?",
|
| 290 |
+
"answer": "Go to the Events section from the main menu. You can use filters to search by category, date, or institution to find events that interest you."
|
| 291 |
+
},
|
| 292 |
+
{
|
| 293 |
+
"question": "How do I join the CampVerse community?",
|
| 294 |
+
"answer": "Sign up with your college email and start participating in events, discussions, and feedback. You can also follow us on social media for updates."
|
| 295 |
+
},
|
| 296 |
+
{
|
| 297 |
+
"question": "How do I use the dashboard?",
|
| 298 |
+
"answer": "After logging in, your dashboard gives you access to your events, teams, certificates, notifications, and more. Use the sidebar to navigate different sections."
|
| 299 |
+
},
|
| 300 |
+
{
|
| 301 |
+
"question": "How do I contact support from the website?",
|
| 302 |
+
"answer": "Click the 'Support' or 'Help' link in the website footer or your dashboard to submit a ticket or chat with our support team."
|
| 303 |
+
},
|
| 304 |
+
{
|
| 305 |
+
"question": "What browsers and devices are supported?",
|
| 306 |
+
"answer": "CampVerse works best on the latest versions of Chrome, Firefox, Edge, and Safari. The platform is mobile-friendly and works on most smartphones and tablets."
|
| 307 |
+
},
|
| 308 |
+
{
|
| 309 |
+
"question": "How do I reset my password from the login page?",
|
| 310 |
+
"answer": "Click 'Forgot Password?' on the login page, enter your email, and follow the instructions sent to your inbox to reset your password."
|
| 311 |
+
},
|
| 312 |
+
{
|
| 313 |
+
"question": "How do I access event details and schedules?",
|
| 314 |
+
"answer": "Click on any event card to view its details, including schedule, rules, and prizes. Important dates are highlighted on the event page."
|
| 315 |
+
},
|
| 316 |
+
{
|
| 317 |
+
"question": "How do I use the Browse Events feature?",
|
| 318 |
+
"answer": "Use the 'Browse Events' button on the homepage or dashboard to see all upcoming and ongoing events. You can filter and sort events as needed."
|
| 319 |
+
},
|
| 320 |
+
{
|
| 321 |
+
"question": "How do I launch my own event on CampVerse?",
|
| 322 |
+
"answer": "If you’re an institution or host, log in to your dashboard and use the 'Create Event' option. Fill in the event details and submit for approval."
|
| 323 |
+
},
|
| 324 |
+
{
|
| 325 |
+
"question": "How do I access the institution dashboard?",
|
| 326 |
+
"answer": "Institution representatives can log in and access the institution dashboard from the main menu. Here you can manage events, view analytics, and more."
|
| 327 |
+
},
|
| 328 |
+
{
|
| 329 |
+
"question": "How do I update my profile or settings from the frontend?",
|
| 330 |
+
"answer": "Go to your dashboard, click on your profile icon, and select 'Edit Profile' to update your information, change your password, or manage notification settings."
|
| 331 |
+
},
|
| 332 |
+
{
|
| 333 |
+
"question": "Why can’t I see some events?",
|
| 334 |
+
"answer": "Some events may be restricted to certain colleges or require approval to join. Check the event’s eligibility criteria or contact support if you think there’s an error."
|
| 335 |
+
},
|
| 336 |
+
{
|
| 337 |
+
"question": "How do I know if an event is open to my college?",
|
| 338 |
+
"answer": "Each event page lists eligibility details. Look for 'Open to All' or check if your college is listed in the eligible institutions."
|
| 339 |
+
},
|
| 340 |
+
{
|
| 341 |
+
"question": "How do I join a team for an event?",
|
| 342 |
+
"answer": "When registering for an event, you can create a new team or join an existing one if the event allows teams. Follow the prompts during registration."
|
| 343 |
+
},
|
| 344 |
+
{
|
| 345 |
+
"question": "How do I leave feedback for an event?",
|
| 346 |
+
"answer": "After the event, go to the event page or your dashboard and look for the 'Leave Feedback' option. Your feedback helps us improve!"
|
| 347 |
+
},
|
| 348 |
+
{
|
| 349 |
+
"question": "How do I report inappropriate content or users?",
|
| 350 |
+
"answer": "Use the 'Report' button on user profiles or event pages, or contact support directly. We take all reports seriously and will investigate promptly."
|
| 351 |
+
},
|
| 352 |
+
{
|
| 353 |
+
"question": "How do I stay safe while using CampVerse?",
|
| 354 |
+
"answer": "Never share your password or sensitive information. Use official communication channels and report any suspicious activity to support."
|
| 355 |
+
}
|
| 356 |
+
,
|
| 357 |
+
{
|
| 358 |
+
"question": "How do I get verified as a host?",
|
| 359 |
+
"answer": "To get verified as a host, register your host account through the dedicated portal. Our team will review your details and may request additional documentation. Once approved, you’ll receive a verification badge and access to host features."
|
| 360 |
+
},
|
| 361 |
+
{
|
| 362 |
+
"question": "What documents are required for host verification?",
|
| 363 |
+
"answer": "Typically, you’ll need to provide a valid ID and official contact information. Specific requirements are listed during the registration process."
|
| 364 |
+
},
|
| 365 |
+
{
|
| 366 |
+
"question": "How long does host verification take?",
|
| 367 |
+
"answer": "Host verification usually takes 2-5 business days after submitting all required documents. You’ll be notified by email once your account is verified."
|
| 368 |
+
},
|
| 369 |
+
{
|
| 370 |
+
"question": "What are the benefits of being a verified host?",
|
| 371 |
+
"answer": "Verified hosts can create and manage events, access advanced analytics, and gain greater visibility on CampVerse. A verification badge also builds trust with participants."
|
| 372 |
+
}
|
| 373 |
+
]
|
intent_classifier.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Intent Classification Service
|
| 3 |
+
Detects user intent: greeting, event_search, help, thanks, farewell, general_question
|
| 4 |
+
"""
|
| 5 |
+
import re
|
| 6 |
+
import logging
|
| 7 |
+
from typing import Tuple
|
| 8 |
+
|
| 9 |
+
logger = logging.getLogger("chatbot.intent")
|
| 10 |
+
|
| 11 |
+
class IntentClassifier:
|
| 12 |
+
def __init__(self):
|
| 13 |
+
# Define intent patterns with priority order
|
| 14 |
+
self.intent_patterns = {
|
| 15 |
+
'greeting': [
|
| 16 |
+
r'^(hi|hello|hey|good morning|good afternoon|good evening|greetings|hii|hiii|helllo)[\s!?.]*$',
|
| 17 |
+
r'\b(hi|hello|hey|good morning|good afternoon|good evening|greetings)\b',
|
| 18 |
+
],
|
| 19 |
+
'farewell': [
|
| 20 |
+
r'\b(bye|goodbye|see you|farewell|take care|good night)\b',
|
| 21 |
+
],
|
| 22 |
+
'thanks': [
|
| 23 |
+
r'\b(thank|thanks|appreciate|grateful|thx)\b',
|
| 24 |
+
],
|
| 25 |
+
'host_help': [
|
| 26 |
+
# Host-specific questions (check before event_search)
|
| 27 |
+
r'\b(register|create|host|organize|add|post|submit|upload)\b.{0,50}\b(my event|an event|event)\b',
|
| 28 |
+
r'\b(how to|how can i|how do i)\b.{0,50}\b(register|create|host|organize|add|post)\b.{0,50}\b(event)\b',
|
| 29 |
+
r'\b(host|organizer|organiser)\b',
|
| 30 |
+
],
|
| 31 |
+
'event_search': [
|
| 32 |
+
# Direct event queries (search/find only)
|
| 33 |
+
r'\b(show|find|search|list|get|display|tell|give|want|need|looking for)\b.{0,50}\b(event|hackathon|workshop|competition|seminar|webinar|conference|meetup|contest|fest|festival)\b',
|
| 34 |
+
# Time-based queries
|
| 35 |
+
r'\b(upcoming|today|tomorrow|this week|this month|next|future|soon|latest|recent)\b.{0,50}\b(event|hackathon|workshop)\b',
|
| 36 |
+
# Location-based queries
|
| 37 |
+
r'\b(at|in|near|on)\b.{0,50}\b(campus|college|university|cuj|ccpc)\b',
|
| 38 |
+
# Category-based
|
| 39 |
+
r'\b(ai|ml|tech|coding|programming|software|web|mobile|data|science)\b.{0,50}\b(event|hackathon|workshop)\b',
|
| 40 |
+
# Simple keywords
|
| 41 |
+
r'^(event|hackathon|workshop|competition|seminar|webinar|conference|meetup)s?\s*$',
|
| 42 |
+
],
|
| 43 |
+
'help': [
|
| 44 |
+
r'\b(help|support|assist|guide|what can you do|how does)\b',
|
| 45 |
+
],
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
def classify(self, text: str) -> Tuple[str, float]:
|
| 49 |
+
"""
|
| 50 |
+
Classify user intent from text
|
| 51 |
+
Returns: (intent, confidence)
|
| 52 |
+
Priority: greeting/farewell/thanks > event_search > help > general_question
|
| 53 |
+
"""
|
| 54 |
+
text_lower = text.lower().strip()
|
| 55 |
+
|
| 56 |
+
# Priority 1: Check for exact greetings (single word)
|
| 57 |
+
if text_lower in ['hi', 'hello', 'hey', 'hii', 'hiii', 'helllo', 'good morning', 'good afternoon', 'good evening']:
|
| 58 |
+
logger.info(f"Detected intent: greeting for text: {text}")
|
| 59 |
+
return 'greeting', 0.95
|
| 60 |
+
|
| 61 |
+
# Priority 2: Check for farewell and thanks
|
| 62 |
+
for intent in ['farewell', 'thanks']:
|
| 63 |
+
for pattern in self.intent_patterns[intent]:
|
| 64 |
+
if re.search(pattern, text_lower, re.IGNORECASE):
|
| 65 |
+
logger.info(f"Detected intent: {intent} for text: {text}")
|
| 66 |
+
return intent, 0.9
|
| 67 |
+
|
| 68 |
+
# Priority 3: Check for host_help (before event_search to avoid false positives)
|
| 69 |
+
for pattern in self.intent_patterns['host_help']:
|
| 70 |
+
if re.search(pattern, text_lower, re.IGNORECASE):
|
| 71 |
+
logger.info(f"Detected intent: host_help for text: {text}")
|
| 72 |
+
return 'host_help', 0.9
|
| 73 |
+
|
| 74 |
+
# Priority 4: Check for event_search
|
| 75 |
+
for pattern in self.intent_patterns['event_search']:
|
| 76 |
+
if re.search(pattern, text_lower, re.IGNORECASE):
|
| 77 |
+
logger.info(f"Detected intent: event_search for text: {text}")
|
| 78 |
+
return 'event_search', 0.85
|
| 79 |
+
|
| 80 |
+
# Priority 5: Check for help
|
| 81 |
+
for pattern in self.intent_patterns['help']:
|
| 82 |
+
if re.search(pattern, text_lower, re.IGNORECASE):
|
| 83 |
+
logger.info(f"Detected intent: help for text: {text}")
|
| 84 |
+
return 'help', 0.8
|
| 85 |
+
|
| 86 |
+
# Priority 5: Check for greeting (broader match)
|
| 87 |
+
for pattern in self.intent_patterns['greeting']:
|
| 88 |
+
if re.search(pattern, text_lower, re.IGNORECASE):
|
| 89 |
+
logger.info(f"Detected intent: greeting for text: {text}")
|
| 90 |
+
return 'greeting', 0.85
|
| 91 |
+
|
| 92 |
+
# Default to general question
|
| 93 |
+
logger.info(f"Detected intent: general_question for text: {text}")
|
| 94 |
+
return 'general_question', 0.5
|
| 95 |
+
|
| 96 |
+
def get_response_for_intent(self, intent: str) -> str:
|
| 97 |
+
"""Get predefined response for specific intents"""
|
| 98 |
+
responses = {
|
| 99 |
+
'greeting': "Hi! I'm CampVerseBot, here to help you discover events and answer your questions. You can ask me about upcoming hackathons, workshops, or any other events!",
|
| 100 |
+
'farewell': "Goodbye! If you need anything else, just ask. Have a great day!",
|
| 101 |
+
'thanks': "You're welcome! If you have more questions, feel free to ask.",
|
| 102 |
+
'help': "I can help you with:\n\n• Finding events (hackathons, workshops, competitions)\n• Answering questions about CampVerse\n• Registration and account help\n\nJust ask me anything!",
|
| 103 |
+
'host_help': "🎯 To register your event as a host:\n\n1️⃣ Sign Up/Login - Create an account or log in\n\n2️⃣ Go to Dashboard - Navigate to your host dashboard\n\n3️⃣ Create Event - Click 'Create Event' button\n\n4️⃣ Fill Details - Add title, description, date, venue, etc.\n\n5️⃣ Submit - Your event will be reviewed and published\n\n💡 Need more help? Check our Host Guide or contact support!",
|
| 104 |
+
}
|
| 105 |
+
return responses.get(intent, "")
|
requirements.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi==0.115.0
|
| 2 |
+
uvicorn[standard]==0.32.0
|
| 3 |
+
sentence-transformers==3.3.1
|
| 4 |
+
faiss-cpu==1.9.0.post1
|
| 5 |
+
pandas==2.2.3
|
| 6 |
+
numpy==2.0.2
|
| 7 |
+
python-socketio==5.11.4
|
| 8 |
+
python-engineio==4.10.1
|
| 9 |
+
python-socketio[client]==5.11.4
|
| 10 |
+
requests==2.32.3
|
| 11 |
+
scikit-learn==1.5.2
|