Spaces:
Paused
Paused
Commit
·
89511c3
1
Parent(s):
ce7ced7
chatbot updated
Browse files- app.py +30 -24
- backend/templates/base.html +39 -13
- requirements.txt +0 -3
app.py
CHANGED
@@ -34,13 +34,14 @@ import json
|
|
34 |
# -----------------------------------------------------------------------------
|
35 |
# Chatbot setup
|
36 |
#
|
37 |
-
# The chatbot
|
38 |
-
# ``chatbot/chatbot.txt`` knowledge base
|
39 |
-
#
|
40 |
-
#
|
41 |
-
#
|
42 |
-
#
|
43 |
-
#
|
|
|
44 |
|
45 |
# Paths for the chatbot knowledge base and persistent vector store. We
|
46 |
# compute these relative to the current file so that the app can be deployed
|
@@ -56,42 +57,47 @@ CHATBOT_DB_DIR = "/tmp/chroma_db"
|
|
56 |
# -----------------------------------------------------------------------------
|
57 |
# Hugging Face model configuration
|
58 |
#
|
59 |
-
# The
|
60 |
-
#
|
61 |
-
#
|
62 |
-
#
|
63 |
-
#
|
64 |
-
|
65 |
-
# another conversational model (e.g. ``microsoft/DialoGPT-medium``), update
|
66 |
-
# this constant accordingly. The model and tokenizer are loaded lazily in
|
67 |
-
# ``init_hf_model()`` to avoid impacting application startup time.
|
68 |
-
HF_MODEL_NAME = "facebook/blenderbot-400M-distill"
|
69 |
|
70 |
# Global Hugging Face model and tokenizer. These variables remain ``None``
|
71 |
# until ``init_hf_model()`` is called. They are reused across all chatbot
|
72 |
# requests to prevent repeatedly loading the large model into memory.
|
73 |
-
_hf_model = None
|
74 |
-
_hf_tokenizer = None
|
75 |
|
76 |
def init_hf_model() -> None:
|
77 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
global _hf_model, _hf_tokenizer
|
79 |
if _hf_model is not None and _hf_tokenizer is not None:
|
80 |
return
|
81 |
|
82 |
-
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
|
83 |
import torch
|
84 |
|
85 |
-
model_name =
|
86 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
87 |
|
|
|
|
|
|
|
|
|
88 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
89 |
model = AutoModelForSeq2SeqLM.from_pretrained(model_name).to(device)
|
90 |
|
91 |
_hf_model = model
|
92 |
_hf_tokenizer = tokenizer
|
93 |
-
|
94 |
-
HF_MODEL_NAME = "facebook/blenderbot-400M-distill"
|
95 |
_chatbot_embedder = None
|
96 |
_chatbot_collection = None
|
97 |
|
|
|
34 |
# -----------------------------------------------------------------------------
|
35 |
# Chatbot setup
|
36 |
#
|
37 |
+
# The chatbot uses a local vector database (Chroma) to search the
|
38 |
+
# ``chatbot/chatbot.txt`` knowledge base. Retrieved passages are fed to
|
39 |
+
# a lightweight conversational model from Hugging Face (see
|
40 |
+
# ``init_hf_model`` below). To avoid the expensive model and database
|
41 |
+
# initialisation on every request, embeddings and the vector collection are
|
42 |
+
# loaded lazily the first time a chat query is processed. Subsequent
|
43 |
+
# requests reuse the same global objects. See ``init_chatbot`` and
|
44 |
+
# ``get_chatbot_response`` for implementation details.
|
45 |
|
46 |
# Paths for the chatbot knowledge base and persistent vector store. We
|
47 |
# compute these relative to the current file so that the app can be deployed
|
|
|
57 |
# -----------------------------------------------------------------------------
|
58 |
# Hugging Face model configuration
|
59 |
#
|
60 |
+
# The chatbot uses a small conversational model hosted on Hugging Face. To
|
61 |
+
# allow easy experimentation, the model name can be overridden via the
|
62 |
+
# ``HF_CHATBOT_MODEL`` environment variable. If unset, we fall back to
|
63 |
+
# ``facebook/blenderbot-400M-distill`` which provides a good balance of
|
64 |
+
# quality and resource usage and is freely available without authentication.
|
65 |
+
HF_MODEL_NAME = os.getenv("HF_CHATBOT_MODEL", "facebook/blenderbot-400M-distill")
|
|
|
|
|
|
|
|
|
66 |
|
67 |
# Global Hugging Face model and tokenizer. These variables remain ``None``
|
68 |
# until ``init_hf_model()`` is called. They are reused across all chatbot
|
69 |
# requests to prevent repeatedly loading the large model into memory.
|
70 |
+
_hf_model: 'AutoModelForSeq2SeqLM | None' = None # type: ignore[type-arg]
|
71 |
+
_hf_tokenizer: 'AutoTokenizer | None' = None # type: ignore[type-arg]
|
72 |
|
73 |
def init_hf_model() -> None:
|
74 |
+
"""
|
75 |
+
Initialise the Hugging Face conversational model and tokenizer.
|
76 |
+
|
77 |
+
This function loads the specified ``HF_MODEL_NAME`` model and its
|
78 |
+
corresponding tokenizer. The model is moved to GPU if available,
|
79 |
+
otherwise it runs on CPU. Subsequent calls return immediately if
|
80 |
+
the model and tokenizer have already been instantiated.
|
81 |
+
"""
|
82 |
global _hf_model, _hf_tokenizer
|
83 |
if _hf_model is not None and _hf_tokenizer is not None:
|
84 |
return
|
85 |
|
86 |
+
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer # type: ignore
|
87 |
import torch
|
88 |
|
89 |
+
model_name = HF_MODEL_NAME
|
90 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
91 |
|
92 |
+
# Load tokenizer and model from Hugging Face. We deliberately avoid
|
93 |
+
# specifying ``use_auth_token`` here since the default models are
|
94 |
+
# publicly accessible. Should you wish to use a private model, set
|
95 |
+
# HF_HOME/HF_TOKEN environment variables accordingly.
|
96 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
97 |
model = AutoModelForSeq2SeqLM.from_pretrained(model_name).to(device)
|
98 |
|
99 |
_hf_model = model
|
100 |
_hf_tokenizer = tokenizer
|
|
|
|
|
101 |
_chatbot_embedder = None
|
102 |
_chatbot_collection = None
|
103 |
|
backend/templates/base.html
CHANGED
@@ -778,7 +778,13 @@
|
|
778 |
|
779 |
#CHATBOT START
|
780 |
<!-- Chatbot Toggle Button -->
|
781 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
782 |
|
783 |
<!-- Chatbox Popup -->
|
784 |
<div id="chatbot-box">
|
@@ -790,29 +796,41 @@
|
|
790 |
<style>
|
791 |
#chatbot-toggle {
|
792 |
position: fixed;
|
793 |
-
bottom:
|
794 |
-
right:
|
795 |
background-color: #4caf50;
|
796 |
color: white;
|
797 |
-
padding:
|
798 |
border-radius: 30px;
|
799 |
cursor: pointer;
|
800 |
z-index: 1000;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
801 |
}
|
802 |
|
803 |
#chatbot-box {
|
804 |
position: fixed;
|
805 |
-
bottom:
|
806 |
-
right:
|
807 |
/* Default dimensions for larger screens */
|
808 |
-
width:
|
809 |
-
height:
|
810 |
background: white;
|
811 |
border: 2px solid #ccc;
|
812 |
border-radius: 10px;
|
813 |
display: none;
|
814 |
flex-direction: column;
|
815 |
z-index: 1000;
|
|
|
816 |
}
|
817 |
|
818 |
#chat-header {
|
@@ -835,18 +853,26 @@
|
|
835 |
#chatbot-box {
|
836 |
width: 90vw;
|
837 |
height: 60vh;
|
838 |
-
bottom:
|
839 |
right: 5vw;
|
840 |
}
|
841 |
#chat-messages {
|
842 |
-
max-height: calc(60vh -
|
|
|
|
|
|
|
|
|
|
|
|
|
843 |
}
|
844 |
}
|
|
|
845 |
@media (max-width: 400px) {
|
846 |
#chatbot-toggle {
|
847 |
-
bottom:
|
848 |
-
right:
|
849 |
-
padding:
|
|
|
850 |
}
|
851 |
}
|
852 |
|
|
|
778 |
|
779 |
#CHATBOT START
|
780 |
<!-- Chatbot Toggle Button -->
|
781 |
+
<!--
|
782 |
+
The floating chat button toggles the visibility of the chat window.
|
783 |
+
We use a flex container here to ensure the emoji and text remain
|
784 |
+
centred on all screen sizes. Additional media queries adjust the
|
785 |
+
button's position and padding for very small viewports.
|
786 |
+
-->
|
787 |
+
<div id="chatbot-toggle" onclick="toggleChatbot()">💬 Chat</div>
|
788 |
|
789 |
<!-- Chatbox Popup -->
|
790 |
<div id="chatbot-box">
|
|
|
796 |
<style>
|
797 |
#chatbot-toggle {
|
798 |
position: fixed;
|
799 |
+
bottom: 1rem;
|
800 |
+
right: 1rem;
|
801 |
background-color: #4caf50;
|
802 |
color: white;
|
803 |
+
padding: 0.75rem 1rem;
|
804 |
border-radius: 30px;
|
805 |
cursor: pointer;
|
806 |
z-index: 1000;
|
807 |
+
display: flex;
|
808 |
+
align-items: center;
|
809 |
+
justify-content: center;
|
810 |
+
font-size: 1rem;
|
811 |
+
line-height: 1;
|
812 |
+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
|
813 |
+
transition: background-color 0.2s ease;
|
814 |
+
}
|
815 |
+
|
816 |
+
#chatbot-toggle:hover {
|
817 |
+
background-color: #43a047; /* slightly darker green on hover */
|
818 |
}
|
819 |
|
820 |
#chatbot-box {
|
821 |
position: fixed;
|
822 |
+
bottom: calc(1rem + 3.5rem); /* sit above the toggle on desktop */
|
823 |
+
right: 1rem;
|
824 |
/* Default dimensions for larger screens */
|
825 |
+
width: 20rem;
|
826 |
+
height: 25rem;
|
827 |
background: white;
|
828 |
border: 2px solid #ccc;
|
829 |
border-radius: 10px;
|
830 |
display: none;
|
831 |
flex-direction: column;
|
832 |
z-index: 1000;
|
833 |
+
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
|
834 |
}
|
835 |
|
836 |
#chat-header {
|
|
|
853 |
#chatbot-box {
|
854 |
width: 90vw;
|
855 |
height: 60vh;
|
856 |
+
bottom: calc(1rem + 3rem);
|
857 |
right: 5vw;
|
858 |
}
|
859 |
#chat-messages {
|
860 |
+
max-height: calc(60vh - 5.5rem);
|
861 |
+
}
|
862 |
+
#chatbot-toggle {
|
863 |
+
bottom: 1rem;
|
864 |
+
right: 1rem;
|
865 |
+
padding: 0.65rem 0.9rem;
|
866 |
+
font-size: 0.9rem;
|
867 |
}
|
868 |
}
|
869 |
+
|
870 |
@media (max-width: 400px) {
|
871 |
#chatbot-toggle {
|
872 |
+
bottom: 0.75rem;
|
873 |
+
right: 0.75rem;
|
874 |
+
padding: 0.6rem 0.8rem;
|
875 |
+
font-size: 0.85rem;
|
876 |
}
|
877 |
}
|
878 |
|
requirements.txt
CHANGED
@@ -1,6 +1,3 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
flask
|
5 |
flask_login
|
6 |
flask_sqlalchemy
|
|
|
|
|
|
|
|
|
1 |
flask
|
2 |
flask_login
|
3 |
flask_sqlalchemy
|