Skip to content

Commit

Permalink
104 chat box info messages (#118)
Browse files Browse the repository at this point in the history
* Chat message type enum

* WIP: Unformatted info messages

* Formatted chat info text

* Comments on new methods
  • Loading branch information
gsproston-scottlogic committed Aug 11, 2023
1 parent cc7b5f7 commit b462409
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 39 deletions.
43 changes: 40 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import { useState } from "react";

import "./App.css";
import AttackBox from "./components/AttackBox/AttackBox";
import ChatBox from "./components/ChatBox/ChatBox";
Expand All @@ -7,12 +8,14 @@ import EmailBox from "./components/EmailBox/EmailBox";
import ApiKeyBox from "./components/ApiKeyBox/ApiKeyBox";
import Header from "./components/Header";
import ModelSelectionBox from "./components/ModelSelectionBox/ModelSelectionBox";
import { useState } from "react";
import { EmailInfo } from "./models/email";
import { CHAT_MESSAGE_TYPE, ChatMessage } from "./models/chat";
import { DefenceInfo } from "./models/defence";

function App() {
const [defenceBoxKey, setDefenceBoxKey] = useState<number>(0);
const [emails, setEmails] = useState<EmailInfo[]>([]);
const [messages, setMessages] = useState<ChatMessage[]>([]);
const [triggeredDefences, setTriggeredDefences] = useState<string[]>([]);

const updateTriggeredDefences = (defenceDetails: string[]) => {
Expand All @@ -22,11 +25,42 @@ function App() {
setDefenceBoxKey(defenceBoxKey + 1);
};

// methods to modify messages
const addChatMessage = (message: ChatMessage) => {
setMessages((messages: ChatMessage[]) => [...messages, message]);
};
const addInfoMessage = (message: string) => {
addChatMessage({
message: message,
type: CHAT_MESSAGE_TYPE.INFO,
isOriginalMessage: true,
});
};
const clearMessages = () => {
setMessages([]);
};

// methods to be called when defences are (de)activated
// this adds an info message to the chat
const defenceActivated = (defenceInfo: DefenceInfo) => {
const infoMessage = `${defenceInfo.name} defence activated`;
addInfoMessage(infoMessage.toLowerCase());
};
const defenceDeactivated = (defenceInfo: DefenceInfo) => {
const infoMessage = `${defenceInfo.name} defence deactivated`;
addInfoMessage(infoMessage.toLowerCase());
};

return (
<span id="main-area">
<div className="side-bar">
<div className="side-bar-header">defence mechanisms</div>
<DefenceBox key={defenceBoxKey} triggeredDefences={triggeredDefences} />
<DefenceBox
key={defenceBoxKey}
triggeredDefences={triggeredDefences}
defenceActivated={defenceActivated}
defenceDeactivated={defenceDeactivated}
/>

<div className="side-bar-header">attack mechanisms</div>
<AttackBox />
Expand All @@ -38,8 +72,11 @@ function App() {
<div id="centre-area">
<Header />
<ChatBox
messages={messages}
setEmails={setEmails}
updateTriggeredDefences={updateTriggeredDefences}
addChatMessage={addChatMessage}
clearMessages={clearMessages}
/>
</div>
<div className="side-bar">
Expand Down
54 changes: 28 additions & 26 deletions frontend/src/components/ChatBox/ChatBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,33 @@ import "./ChatBox.css";
import ChatBoxFeed from "./ChatBoxFeed";
import { clearChat, sendMessage } from "../../service/chatService";
import { getSentEmails } from "../../service/emailService";
import { ChatMessage, ChatResponse } from "../../models/chat";
import {
CHAT_MESSAGE_TYPE,
ChatMessage,
ChatResponse,
} from "../../models/chat";
import { EmailInfo } from "../../models/email";

function ChatBox(
this: any,
{
messages,
setEmails,
updateTriggeredDefences,
addChatMessage,
clearMessages,
}: {
messages: ChatMessage[];
setEmails: (emails: EmailInfo[]) => void;
updateTriggeredDefences: (defences: string[]) => void;
addChatMessage: (message: ChatMessage) => void;
clearMessages: () => void;
}
) {
const [isSendingMessage, setIsSendingMessage] = useState<boolean>(false);
const [messages, setMessages] = useState<ChatMessage[]>([]);

// called on mount
useEffect(() => {
// clear remote messages
clearChat();
// get sent emails
getSentEmails().then((sentEmails) => {
setEmails(sentEmails);
Expand All @@ -31,7 +38,7 @@ function ChatBox(

const clearClicked = () => {
// clear local messages
setMessages([]);
clearMessages();
// clear remote messages
clearChat();
};
Expand All @@ -45,10 +52,11 @@ function ChatBox(
const message = event.currentTarget.value;

// if input has been edited, add both messages to the list of messages. otherwise add original message only
setMessages((messages: ChatMessage[]) => [
...messages,
{ message: message, isUser: true, isOriginalMessage: true },
]);
addChatMessage({
message: message,
type: CHAT_MESSAGE_TYPE.USER,
isOriginalMessage: true,
});
// clear the input
event.currentTarget.value = "";

Expand All @@ -57,25 +65,19 @@ function ChatBox(
const isTransformed = transformedMessage !== message;
// add the transformed message to the chat box if it is different from the original message
if (isTransformed) {
setMessages((messages: ChatMessage[]) => [
...messages,
{
message: transformedMessage,
isUser: true,
isOriginalMessage: false,
},
]);
addChatMessage({
message: transformedMessage,
type: CHAT_MESSAGE_TYPE.USER,
isOriginalMessage: false,
});
}
// add it to the list of messages
setMessages((messages: ChatMessage[]) => [
...messages,
{
isUser: false,
message: response.reply,
defenceInfo: response.defenceInfo,
isOriginalMessage: true,
},
]);
addChatMessage({
type: CHAT_MESSAGE_TYPE.BOT,
message: response.reply,
defenceInfo: response.defenceInfo,
isOriginalMessage: true,
});
// update triggered defences
updateTriggeredDefences(response.defenceInfo.triggeredDefences);

Expand Down
9 changes: 7 additions & 2 deletions frontend/src/components/ChatBox/ChatBoxFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import "./ChatBoxFeed.css";
import { ChatMessage } from "../../models/chat";
import { CHAT_MESSAGE_TYPE, ChatMessage } from "../../models/chat";
import ChatBoxMessage from "./ChatBoxMessage";
import ChatBoxInfoText from "./ChatBoxInfoText";

function ChatBoxFeed({ messages }: { messages: ChatMessage[] }) {
return (
<div id="chat-box-feed">
{[...messages].reverse().map((message, index) => {
return <ChatBoxMessage key={index} message={message} />;
if (message.type === CHAT_MESSAGE_TYPE.INFO) {
return <ChatBoxInfoText key={index} text={message.message} />;
} else {
return <ChatBoxMessage key={index} message={message} />;
}
})}
</div>
);
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/components/ChatBox/ChatBoxInfoText.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.chat-box-info-text {
color: #888;
font-size: 14px;
padding-top: 16px;
}
7 changes: 7 additions & 0 deletions frontend/src/components/ChatBox/ChatBoxInfoText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import "./ChatBoxInfoText.css";

function ChatBoxInfoText({ text }: { text: string }) {
return <div className="chat-box-info-text">{text}</div>;
}

export default ChatBoxInfoText;
10 changes: 6 additions & 4 deletions frontend/src/components/ChatBox/ChatBoxMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ChatMessage } from "../../models/chat";
import { CHAT_MESSAGE_TYPE, ChatMessage } from "../../models/chat";
import "./ChatBoxMessage.css";

function ChatBoxMessage({ message }: { message: ChatMessage }) {
return (
<div
className={
message.isUser
message.type === CHAT_MESSAGE_TYPE.USER
? message.isOriginalMessage
? "chat-box-message chat-box-message-user"
: "chat-box-message chat-box-message-user-transformed"
Expand All @@ -15,8 +15,10 @@ function ChatBoxMessage({ message }: { message: ChatMessage }) {
}
lang="en"
>
{(message.isUser && message.isOriginalMessage && <b>Input: </b>) ||
(message.isUser && !message.isOriginalMessage && <b>Edited: </b>)}
{(message.type === CHAT_MESSAGE_TYPE.USER &&
message.isOriginalMessage && <b>Input: </b>) ||
(message.type === CHAT_MESSAGE_TYPE.USER &&
!message.isOriginalMessage && <b>Edited: </b>)}
{message.message}
</div>
);
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/components/DefenceBox/DefenceBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@ import {
configureDefence,
} from "../../service/defenceService";
import { DEFENCE_DETAILS } from "../../Defences";
import { DefenceConfig } from "../../models/defence";
import { DefenceConfig, DefenceInfo } from "../../models/defence";

function DefenceBox({ triggeredDefences }: { triggeredDefences: string[] }) {
function DefenceBox({
triggeredDefences,
defenceActivated,
defenceDeactivated,
}: {
triggeredDefences: string[];
defenceActivated: (defenceInfo: DefenceInfo) => void;
defenceDeactivated: (defenceInfo: DefenceInfo) => void;
}) {
// list of defence mechanisms
const [defenceDetails, setDefenceDetails] = useState(DEFENCE_DETAILS);

Expand Down Expand Up @@ -62,6 +70,7 @@ function DefenceBox({ triggeredDefences }: { triggeredDefences: string[] }) {
if (defenceDetail.id === defenceType) {
defenceDetail.isActive = true;
defenceDetail.isTriggered = false;
defenceActivated(defenceDetail);
}
return defenceDetail;
});
Expand All @@ -76,6 +85,7 @@ function DefenceBox({ triggeredDefences }: { triggeredDefences: string[] }) {
if (defenceDetail.id === defenceType) {
defenceDetail.isActive = false;
defenceDetail.isTriggered = false;
defenceDeactivated(defenceDetail);
}
return defenceDetail;
});
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/models/chat.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type } from "@testing-library/user-event/dist/type";

enum CHAT_MODELS {
GPT_4 = "gpt-4",
GPT_4_0613 = "gpt-4-0613",
Expand All @@ -9,16 +11,22 @@ enum CHAT_MODELS {
GPT_3_5_TURBO_16K_0613 = "gpt-3.5-turbo-16k-0613",
}

enum CHAT_MESSAGE_TYPE {
BOT,
INFO,
USER,
}

interface ChatDefenceReport {
blocked: boolean;
triggeredDefences: string[];
}

interface ChatMessage {
isUser: boolean;
defenceInfo?: ChatDefenceReport;
message: string;
isOriginalMessage: boolean;
type: CHAT_MESSAGE_TYPE;
}

interface ChatResponse {
Expand All @@ -28,4 +36,4 @@ interface ChatResponse {
}

export type { ChatMessage, ChatResponse };
export { CHAT_MODELS };
export { CHAT_MODELS, CHAT_MESSAGE_TYPE };

0 comments on commit b462409

Please sign in to comment.