Daemontatox's picture
add the option to select multiple services using checkboxes instead of writing them for easier acces
41e86f7 verified
raw
history blame
14.8 kB
# csword_ai_chatbot.py (Fixed Version with Multi-Select Services)
import os
import sys
import csv
import re
import requests
from datetime import datetime
from bs4 import BeautifulSoup
from openai import OpenAI
import gradio as gr
# 1. Load CSWORD.ai context
def load_context():
try:
with open("csword_homepage.html", "r", encoding="utf-8") as file:
soup = BeautifulSoup(file.read(), "html.parser")
texts = [tag.get_text(separator=" ").strip() for tag in soup.find_all(["h1", "h2", "h3", "p", "li"])]
return "\n".join(filter(None, texts))
except FileNotFoundError:
return "CSWORD.ai is a cybersecurity awareness and training platform that leverages AI to deliver personalized, adaptive education."
# 2. Set up DeepInfra client
token = os.getenv("DEEPINFRA_TOKEN", "285LUJulGIprqT6hcPhiXtcrphU04FG4")
openai = OpenAI(api_key=token, base_url="https://api.deepinfra.com/v1/openai")
model_name = "google/gemma-3-27b-it"
SYSTEM_PROMPT_CSWORD = f"""
You are Csword AI a helpful and expert cybersecurity assistant working on the csword.ai website. Your purpose is to answer user questions only related to cybersecurity. Do not answer questions outside this domain. Provide clear, accurate, and up-to-date cybersecurity information tailored for individuals, businesses, or IT teams. If a question is unrelated to cybersecurity, respond politely that you are only trained to answer cybersecurity-related questions.
- content website: https://csword.ai
csword Next-Gen AI Platform for Cyber Awareness
- Csword Features
1- AI-Powered Phishing Simulations
2- Intelligent LMS Training with AI Adaptation
3- Penetration Testing & Threat Simulation
4- Digital Awareness Deliverables
5- Cybersecurity Events
6- Risk & Security Assessment Services
7- Interactive Awareness Sessions
"""
SYSTEM_PROMPT_GENERAL = "You are a cybersecurity expert. Answer clearly and informatively."
CONTEXT = load_context()
# 3. Form state
form_type = None
user_form_data = {}
final_question = ("final_note", "Would you like any further assistance with cybersecurity-related topics?")
service_options = [
"AI Phishing Simulation Platform",
"AI-Tailored LMS Training",
"Cybersecurity Events",
"Digital Awareness Deliverables",
"Executive Reporting & Risk Scoring",
"On-Site Awareness Sessions",
"Penetration Testing & Threat Simulation",
"Risk & Security Assessment",
"24/7 AI Cybersecurity Consultant"
]
form_definitions = {
"demo": [
("name", "Full Name *"),
("company", "Company Name *"),
("email", "Work Email *"),
("phone", "Phone Number"),
("employees", ["Number of Employees *", ["1-50", "51-200", "201-500", "+500"]]),
("services", ["Services of Interest (select multiple):", "checkboxes", service_options]),
("specific_reqs", "Do you have any specific requirements or questions?"),
final_question
],
"contact": [
("name", "Full Name *"),
("email", "Email Address *"),
("company", "Company"),
("subject", "Subject *"),
("message", "Message *"),
final_question
]
}
# 4. Validation
def validate_input(key, value):
if not value or (isinstance(value, str) and not value.strip()):
return "This field is required. Please provide a value."
if key == "email" and not re.match(r"[^@\s]+@[^@\s]+\.[^@\s]+", value):
return "Invalid email format. Please enter a valid email address."
if key == "phone" and re.search(r"[a-zA-Z]", value):
return "Invalid phone number. Only digits and symbols are allowed."
return None
# 5. Chat handler
def answer_question(query: str, is_general=False) -> str:
prompt = SYSTEM_PROMPT_GENERAL if is_general else f"{SYSTEM_PROMPT_CSWORD}\nContext:\n{CONTEXT}"
messages = [
{"role": "system", "content": prompt},
{"role": "user", "content": query},
]
try:
response = openai.chat.completions.create(
model=model_name,
messages=messages,
reasoning_effort="none"
)
return response.choices[0].message.content
except Exception as e:
return f"Error: {e}"
# 6. Chat function
def chat_fn(message, history, checkbox_values=None):
global user_form_data, form_type
if form_type and len(user_form_data) < len(form_definitions[form_type]):
# Allow user to cancel form at any step
cancel_keywords = ["cancel", "stop", "don't want", "exit", "no thanks", "back", "abort"]
if any(kw in message.lower() for kw in cancel_keywords):
user_form_data, form_type = {}, None
return history + [(message, "Form cancelled. How can I assist you with cybersecurity?")], "", gr.update(visible=True), gr.update(visible=False, choices=[], value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
key, question = form_definitions[form_type][len(user_form_data)]
if isinstance(question, list):
if question[1] == "checkboxes":
# This is a checkbox question - handle checkbox values
if checkbox_values is None or len(checkbox_values) == 0:
return history + [(message, "Please select at least one service option.")], "", gr.update(visible=False), gr.update(visible=False, choices=[], value=None), gr.update(visible=True, value=[]), gr.update(visible=True)
user_form_data[key] = checkbox_values
history = history + [(message, f"Selected services: {', '.join(checkbox_values)}")]
else:
# This is a dropdown question
dropdown_options = question[1]
if message not in dropdown_options:
return history + [(message, f"Please choose one of the provided options: {', '.join(dropdown_options)}")], "", gr.update(visible=False), gr.update(visible=True, choices=dropdown_options, value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
user_form_data[key] = message
history = history + [(message, f"Selected: {message}")]
else:
# This is a text question
error = validate_input(key, message)
if error:
return history + [(message, error)], "", gr.update(visible=True), gr.update(visible=False, choices=[], value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
user_form_data[key] = message
history = history + [(message, "Thank you!")]
# Check if we have more questions
if len(user_form_data) < len(form_definitions[form_type]):
next_key, next_question = form_definitions[form_type][len(user_form_data)]
if isinstance(next_question, list):
if next_question[1] == "checkboxes":
# Next question is checkboxes - hide text input and dropdown, show checkboxes
return history + [("", next_question[0])], "", gr.update(visible=False), gr.update(visible=False, choices=[], value=None), gr.update(visible=True, value=[]), gr.update(visible=True)
else:
# Next question is dropdown - hide text input and checkboxes, show dropdown
dropdown_options = next_question[1]
return history + [("", next_question[0])], "", gr.update(visible=False), gr.update(visible=True, choices=dropdown_options, value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
else:
# Next question is text - show text input, hide dropdown and checkboxes
return history + [("", next_question)], "", gr.update(visible=True), gr.update(visible=False, choices=[], value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
else:
# Form complete
user_form_data["timestamp"] = datetime.now().isoformat()
user_form_data["type"] = form_type.capitalize()
# Convert list values to string for CSV storage
csv_data = user_form_data.copy()
for k, v in csv_data.items():
if isinstance(v, list):
csv_data[k] = "; ".join(v)
file_name = f"{form_type}_requests.csv"
file_exists = os.path.isfile(file_name)
try:
with open(file_name, mode="a", newline="", encoding="utf-8") as file:
writer = csv.DictWriter(file, fieldnames=list(csv_data.keys()))
if not file_exists:
writer.writeheader()
writer.writerow(csv_data)
msg1 = f"Thank you! Your {form_type} request has been received and saved."
msg2 = final_question[1]
user_form_data, form_type = {}, None
return history + [("", msg1), ("", msg2)], "", gr.update(visible=True), gr.update(visible=False, choices=[], value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
except Exception as e:
msg1 = f"Thank you! Your {form_type} request has been received (Note: Could not save to file: {e})."
msg2 = final_question[1]
user_form_data, form_type = {}, None
return history + [("", msg1), ("", msg2)], "", gr.update(visible=True), gr.update(visible=False, choices=[], value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
# Admin commands
if message.lower().startswith("admin:") and "guide" in message.lower():
steps = (
"To work with the CSWORD.ai platform:\n"
"1. Login to the admin dashboard.\n"
"2. Upload user list for training enrollment.\n"
"3. Configure phishing simulation campaigns.\n"
"4. Schedule awareness sessions.\n"
"5. Monitor progress via the Executive Risk Dashboard."
)
return history + [(message, steps)], "", gr.update(visible=True), gr.update(visible=False, choices=[]), gr.update(visible=False, value=[]), gr.update(visible=False)
# Form triggers
if re.search(r"\b(demo|quote|custom)\b", message, re.IGNORECASE):
form_type = "demo"
user_form_data = {}
first_question = form_definitions[form_type][0][1]
return history + [(message, "Sure! Let's start with a few details."), ("", first_question)], "", gr.update(visible=True), gr.update(visible=False, choices=[]), gr.update(visible=False, value=[]), gr.update(visible=False)
if re.search(r"\b(contact|message|speak)\b", message, re.IGNORECASE):
form_type = "contact"
user_form_data = {}
first_question = form_definitions[form_type][0][1]
return history + [(message, "Of course! Please fill out the following."), ("", first_question)], "", gr.update(visible=True), gr.update(visible=False, choices=[]), gr.update(visible=False, value=[]), gr.update(visible=False)
# Generic help
if re.search(r"\bhelp\b", message, re.IGNORECASE):
return history + [(message, "Yes, of course! Tell me your question.")], "", gr.update(visible=True), gr.update(visible=False, choices=[]), gr.update(visible=False, value=[]), gr.update(visible=False)
# Cybersecurity questions
if re.search(r"\b(cybersecurity|malware|phishing|ransomware|network|threat|attack|industry|NIST|ISO|compliance)\b", message, re.IGNORECASE):
reply = answer_question(message, is_general=True)
return history + [(message, reply)], "", gr.update(visible=True), gr.update(visible=False, choices=[]), gr.update(visible=False, value=[]), gr.update(visible=False)
# Default response for everything else
reply = answer_question(message)
return history + [(message, reply)], "", gr.update(visible=True), gr.update(visible=False, choices=[], value=None), gr.update(visible=False, value=[]), gr.update(visible=False)
# 7. Launch Gradio
with gr.Blocks(title="CSWORD.ai Chatbot") as demo:
gr.Markdown("## ๐Ÿ‘‹ Welcome to the CSWORD.ai Assistant!\nHello, I'm the CSWORD AI Assistant ๐Ÿค–. [Click here to visit CSWORD.ai](https://csword.ai)\nAsk questions, request a demo, or contact us.")
chatbot = gr.Chatbot(value=[[None, "๐Ÿ‘‹ Hello! I am the CSWORD AI Chatbot. I can help you with any cybersecurity-related questions or guidance. How can I assist you today?"]])
with gr.Row():
user_input = gr.Textbox(show_label=False, placeholder="Enter your question here...", scale=4)
dropdown_input = gr.Dropdown(
choices=[],
label="Please select an option",
visible=False,
scale=2,
interactive=True
)
# Add checkboxes for services
services_checkboxes = gr.CheckboxGroup(
choices=service_options,
label="Select Services of Interest",
visible=False,
value=[]
)
# Add send button for checkboxes
send_services_btn = gr.Button("Send Selected Services", visible=False)
submit = gr.Button("Send")
def get_query(txt, drop, hist, checkbox_vals):
# If dropdown is visible and has a value, use dropdown value
if dropdown_input.visible and drop:
return chat_fn(drop, hist)
# Otherwise use text input
elif txt.strip():
return chat_fn(txt, hist)
else:
return hist, "", gr.update(), gr.update(), gr.update(), gr.update()
def handle_dropdown_selection(drop, hist):
if drop:
return chat_fn(drop, hist)
else:
return hist, "", gr.update(), gr.update(), gr.update(), gr.update()
def handle_services_submission(checkbox_vals, hist):
return chat_fn("services_selected", hist, checkbox_vals)
submit.click(get_query, inputs=[user_input, dropdown_input, chatbot, services_checkboxes], outputs=[chatbot, user_input, user_input, dropdown_input, services_checkboxes, send_services_btn])
user_input.submit(get_query, inputs=[user_input, dropdown_input, chatbot, services_checkboxes], outputs=[chatbot, user_input, user_input, dropdown_input, services_checkboxes, send_services_btn])
# Handle dropdown selection
dropdown_input.select(handle_dropdown_selection, inputs=[dropdown_input, chatbot], outputs=[chatbot, user_input, user_input, dropdown_input, services_checkboxes, send_services_btn])
# Handle services submission
send_services_btn.click(handle_services_submission, inputs=[services_checkboxes, chatbot], outputs=[chatbot, user_input, user_input, dropdown_input, services_checkboxes, send_services_btn])
if __name__ == "__main__":
demo.launch()