Initial commit
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
from flask import Blueprint, request, jsonify, current_app
|
||||
from flask_login import login_required, current_user
|
||||
from app import db
|
||||
from app.models import Ticket, TicketStatus, TicketPriority, TicketCategory
|
||||
from app.services.notification_service import notify_new_ticket
|
||||
from app.services.log_service import log_action
|
||||
|
||||
chatbot_bp = Blueprint('chatbot', __name__, url_prefix='/chatbot')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_SYSTEM_PROMPT = """You are an IT Helpdesk Assistant for an internal IT ticket system.
|
||||
Your job is to:
|
||||
1. Help employees report IT issues conversationally.
|
||||
2. Gather all required information to create a support ticket:
|
||||
- Issue title (short summary)
|
||||
- Detailed description
|
||||
- Category (hardware, software, network, access, email, printer, phone, security, other)
|
||||
- Priority (low, medium, high, critical)
|
||||
- Location (optional)
|
||||
- Asset tag (optional – device serial / asset number)
|
||||
3. When you have enough information, respond with a JSON block like this (and ONLY this, no extra text):
|
||||
{"action": "create_ticket", "title": "...", "description": "...", "category": "...", "priority": "...", "location": "...", "asset_tag": "..."}
|
||||
4. For general IT questions, answer helpfully but briefly.
|
||||
5. If the user seems frustrated or has a critical outage, set priority to "critical".
|
||||
6. Keep your tone professional, friendly, and concise.
|
||||
7. Always ask clarifying questions if you need more detail before creating a ticket.
|
||||
"""
|
||||
|
||||
|
||||
@chatbot_bp.route('/message', methods=['POST'])
|
||||
@login_required
|
||||
def chat():
|
||||
data = request.get_json(force=True)
|
||||
history = data.get('history', []) # [{role, content}, ...]
|
||||
user_msg = data.get('message', '').strip()
|
||||
|
||||
if not user_msg:
|
||||
return jsonify({'error': 'Empty message'}), 400
|
||||
|
||||
api_key = current_app.config.get('ANTHROPIC_API_KEY', '')
|
||||
if not api_key:
|
||||
return jsonify({'reply': "The AI assistant is not configured yet. Please contact your IT administrator.", 'ticket': None})
|
||||
|
||||
messages = history + [{'role': 'user', 'content': user_msg}]
|
||||
|
||||
try:
|
||||
resp = requests.post(
|
||||
'https://api.anthropic.com/v1/messages',
|
||||
headers={
|
||||
'x-api-key' : api_key,
|
||||
'anthropic-version': '2023-06-01',
|
||||
'content-type' : 'application/json',
|
||||
},
|
||||
json={
|
||||
'model' : 'claude-sonnet-4-20250514',
|
||||
'max_tokens': 1024,
|
||||
'system' : _SYSTEM_PROMPT,
|
||||
'messages' : messages,
|
||||
},
|
||||
timeout=30,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
reply_text = resp.json()['content'][0]['text'].strip()
|
||||
except Exception as exc:
|
||||
logger.error(f'[CHATBOT API ERROR] {exc}')
|
||||
return jsonify({'reply': 'Sorry, I encountered an error. Please try again or submit a ticket manually.', 'ticket': None})
|
||||
|
||||
# Check if the AI wants to create a ticket
|
||||
ticket_data = None
|
||||
if '"action": "create_ticket"' in reply_text or "'action': 'create_ticket'" in reply_text:
|
||||
try:
|
||||
start = reply_text.find('{')
|
||||
end = reply_text.rfind('}') + 1
|
||||
parsed = json.loads(reply_text[start:end])
|
||||
if parsed.get('action') == 'create_ticket':
|
||||
ticket = Ticket(
|
||||
title = parsed.get('title', 'Untitled Issue'),
|
||||
description = parsed.get('description', ''),
|
||||
category = parsed.get('category', TicketCategory.OTHER),
|
||||
priority = parsed.get('priority', TicketPriority.MEDIUM),
|
||||
location = parsed.get('location', ''),
|
||||
asset_tag = parsed.get('asset_tag', ''),
|
||||
created_by_id = current_user.id,
|
||||
status = TicketStatus.OPEN,
|
||||
ai_generated = True,
|
||||
)
|
||||
ticket.ticket_number = ticket.generate_ticket_number()
|
||||
db.session.add(ticket)
|
||||
db.session.commit()
|
||||
|
||||
log_action(current_user.id, 'ticket_create_chatbot', 'ticket', ticket.id,
|
||||
f'ticket_number={ticket.ticket_number} ai_generated=True')
|
||||
logger.info(f'[CHATBOT TICKET CREATE] ticket_id={ticket.id} number={ticket.ticket_number} user_id={current_user.id}')
|
||||
notify_new_ticket(ticket)
|
||||
|
||||
ticket_data = {
|
||||
'id' : ticket.id,
|
||||
'ticket_number' : ticket.ticket_number,
|
||||
'title' : ticket.title,
|
||||
'url' : f'/tickets/{ticket.id}',
|
||||
}
|
||||
reply_text = (
|
||||
f"✅ **Ticket Created!**\n\n"
|
||||
f"I've submitted your ticket **{ticket.ticket_number}**: _{ticket.title}_\n\n"
|
||||
f"Our IT team has been notified and will get back to you shortly. "
|
||||
f"You can track your ticket [here](/tickets/{ticket.id})."
|
||||
)
|
||||
except (json.JSONDecodeError, KeyError) as exc:
|
||||
logger.warning(f'[CHATBOT PARSE ERROR] Could not parse ticket JSON: {exc}')
|
||||
|
||||
return jsonify({'reply': reply_text, 'ticket': ticket_data})
|
||||
Reference in New Issue
Block a user