Skip to content

Commit

Permalink
Merge pull request #88 from BESSER-PEARL/ui
Browse files Browse the repository at this point in the history
v1.5.0
  • Loading branch information
mgv99 authored Nov 13, 2024
2 parents 49d35aa + 2bc3508 commit ff4b657
Show file tree
Hide file tree
Showing 36 changed files with 1,281 additions and 317 deletions.
1 change: 1 addition & 0 deletions besser/bot/core/entity/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def to_json(self) -> dict:
"""
entity_json = {
'base_entity': self.base_entity,
'description': self.description,
'entries': []
}
if not self.base_entity:
Expand Down
2 changes: 2 additions & 0 deletions besser/bot/core/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class MessageType(Enum):
"""Enumeration of the different message types in :class:`Message`."""

STR = 'str'
MARKDOWN = 'markdown'
HTML = 'html'
FILE = 'file'
IMAGE = 'image'
DATAFRAME = 'dataframe'
Expand Down
2 changes: 1 addition & 1 deletion besser/bot/core/processors/user_adaptation_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def process(self, session: 'Session', message: str) -> str:
def add_user_model(self, session: 'Session', user_model: dict) -> None:
"""Method to store the user model internally.
The user model shall be stored stored internally.
The user model shall be stored internally.
Args:
session (Session): the current session
Expand Down
7 changes: 7 additions & 0 deletions besser/bot/core/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ def go_to(self, dest: 'State') -> None:
Args:
dest (State): the destination state
"""
if dest not in self._bot.states:
raise StateNotFound(self._bot, dest)
if self.transitions:
raise ConflictingAutoTransitionError(self._bot, self)
self.transitions.append(Transition(name=self._t_name(), source=self, dest=dest, event=auto, event_params={}))
Expand Down Expand Up @@ -265,6 +267,11 @@ def when_variable_matches_operation_go_to(
target (Any): the target value to which will be used in the operation with the stored value
dest (State): the destination state
"""
if dest not in self._bot.states:
raise StateNotFound(self._bot, dest)
for transition in self.transitions:
if transition.is_auto():
raise ConflictingAutoTransitionError(self._bot, self)
event_params = {'var_name': var_name, 'operation': operation, 'target': target}

self.transitions.append(Transition(name=self._t_name(), source=self, dest=dest, event=variable_matches_operation,
Expand Down
12 changes: 12 additions & 0 deletions besser/bot/platforms/payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ class PayloadAction(Enum):
BOT_REPLY_STR = 'bot_reply_str'
"""PayloadAction: Indicates that the payload's purpose is to send a bot reply containing a :class:`str` object."""

BOT_REPLY_MARKDOWN = 'bot_reply_markdown'
"""PayloadAction: Indicates that the payload's purpose is to send a bot reply containing a :class:`str` object
in Markdown format."""

BOT_REPLY_HTML = 'bot_reply_html'
"""PayloadAction: Indicates that the payload's purpose is to send a bot reply containing a :class:`str` object
in HTML format."""

BOT_REPLY_FILE = 'bot_reply_file'
"""PayloadAction: Indicates that the payload's purpose is to send a bot reply containing a :class:`file.File`
object."""
Expand Down Expand Up @@ -52,6 +60,10 @@ class PayloadAction(Enum):
"""

BOT_REPLY_RAG = 'bot_reply_rag'
"""PayloadAction: Indicates that the payload's purpose is to send a bot reply containing a RAG (Retrieval Augmented
Generation) answer, which contains an LLM-generated answer and a set of documents the LLM used as context
(see :class:`besser.bot.nlp.rag.rag.RAGMessage`).
"""


class Payload:
Expand Down
199 changes: 199 additions & 0 deletions besser/bot/platforms/websocket/chat_widget/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/* Chat widget styling */
#chat-window {
position: fixed;
bottom: 90px;
right: 20px;
width: 400px;
height: 600px;
max-height: 90vh;
max-width: 90vw;
border: 1px solid #ccc;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
font-family: Arial, sans-serif;
opacity: 0;
transform: translateY(50px);
transition: opacity 0.3s ease, transform 0.3s ease;
visibility: hidden;
}

#chat-window.visible {
opacity: 1;
transform: translateY(0);
visibility: visible;
}

#chat-header {
background-color: #0078D7;
color: #fff;
padding: 10px;
text-align: center;
cursor: pointer;
}

#chat-messages {
flex: 1;
padding: 10px;
overflow-y: auto;
background-color: #f9f9f9;
}

.user-message {
padding: 8px;
margin-top: 8px;
border-radius: 4px;
width: fit-content;
margin-left: auto;
background-color: #e1ffc7;
}

.bot-message {
padding: 8px;
margin-top: 8px;
border-radius: 4px;
width: fit-content;
margin-right: auto;
background-color: #eee;
}

.markdown-message {
}

.html-message {
}

.image-message {
max-width: 90%;
height: auto;
display: block;
}

.dataframe-message {
border-collapse: collapse;
}

.dataframe-message th, .dataframe-message td {
border: 1px solid #c4c4c4;
padding: 8px;
text-align: left;
}

.dataframe-message th {
background-color: #e1e1e1;
font-weight: bold;
}

.options-message {
background: none;
width: 90%;
}

.location-message {
width: 95%;
height: 300px;
}

.plotly-message {
background: none;
width: 95%;
height: 300px;
}

.button {
background-color: #0078D7;
color: #fff;
font-weight: bold;
text-decoration: none;
padding: 8px;
margin-right: 10px;
margin-top: 20px;
border-radius: 16px;
cursor: pointer;
overflow-wrap: break-word;
line-height: 2.5;
}

/* Full-screen modal style */
.plotly-fullscreen-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
z-index: 9999;
justify-content: center;
align-items: center;
}

/* Full-screen chart container */
.plotly-fullscreen-chart {
width: 90%;
height: 90%;
background-color: #fff;
}

#chat-input {
display: flex;
border-top: 1px solid #eeeeee;
}

#chat-input input {
flex: 1;
padding: 10px;
border: none;
outline: none;
}

#chat-input button {
background-color: #0078D7;
color: #fff;
padding: 10px;
border: none;
cursor: pointer;
}

#chat-input button:hover {
background-color: #005fa3;
}

/* Circle button styling */
#circle-button {
position: fixed;
bottom: 20px;
right: 20px;
width: 50px;
height: 50px;
border-radius: 50%;
transition: transform 0.5s ease;
}

#circle-button img {
width: 50px;/* Adjust size as needed */
height: 50px;
top: 20px;
left: 20px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
cursor: pointer;
border-radius: 50%;
}

/* Rotated class that triggers the spin */
.spin {
transform: rotate(360deg);
}

/* Typing indicator styling */
#typing-indicator {
display: none;
padding: 8px;
width: fit-content;
}

#typing-indicator img {
width: 40px; /* Adjust the size as needed */
}
9 changes: 9 additions & 0 deletions besser/bot/platforms/websocket/chat_widget/data/args.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"userName": "JohnDoe",
"chatbotName": "AmazingBot",
"themeColor": "#34a4bd",
"wsAddress": "ws://localhost:8765",
"messageInputPlaceHolder": "Write something...",
"icon": "img/bot_logo.jpeg",
"typingAnimation": "img/typing_dots.gif"
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions besser/bot/platforms/websocket/chat_widget/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chatbot Widget</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="js/script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<!-- The chatbot UI will be generated here by JavaScript -->
<div id="chat-widget"></div>
<script>
// Fetch the args data from the local JSON file
fetch('./data/args.json')
.then(response => response.json()) // Parse the JSON response
.then(args => {
// Pass the loaded args to the renderChatWidget function
renderChatWidget(args);
})
.catch(error => {
console.error('Error loading args.json:', error);
});
</script>
</body>
</html>
Loading

0 comments on commit ff4b657

Please sign in to comment.