Skip to content

Commit

Permalink
Merge pull request #116 from subquery/feat/chat-ui3
Browse files Browse the repository at this point in the history
feat: chat ui3
  • Loading branch information
HuberTRoy authored Aug 14, 2024
2 parents 0d12d08 + 5089c75 commit af35e68
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 48 deletions.
16 changes: 8 additions & 8 deletions components/app/header/Header.less
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

&__dropdown-item.@{left}__dropdown-item.@{left}__dropdown-item {
&:hover {
background-color: rgba(67, 136, 221, 0.40);
background-color: var(--sq-primary-card-hover);
}
}
}
Expand All @@ -46,10 +46,10 @@
color: #fff;

&:hover {
color: var(--sq-blue600);
color: var(--sq-primary-link-hover);
}
&--active {
color: var(--sq-blue600);
color: var(--sq-primary-link-hover);
}
}
}
Expand All @@ -71,7 +71,7 @@
border-radius: 0;
&--dark {
&:hover {
background-color: rgba(67, 136, 221, 0.40);
background-color: var(--sq-primary-card-hover);
}
}
}
Expand Down Expand Up @@ -116,11 +116,11 @@

&:hover {
text-decoration: underline;
color: var(--sq-blue600);
color: var(--sq-primary-link-hover);
}

&--active {
color: var(--sq-blue600);
color: var(--sq-primary-link-hover);
}
}

Expand Down Expand Up @@ -262,11 +262,11 @@
color: #fff;
&:hover {
text-decoration: underline;
color: var(--sq-blue600);
color: var(--sq-primary);
}

&--active {
color: var(--sq-blue600);
color: var(--sq-primary);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion components/app/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const LeftHeader = ({ leftElement, dropdownLinks, isMobile }: LeftHeaderProps) =
<div className={clsx(bem(), theme === 'dark' ? bem({ dark: 'dark' }) : '')} id="leftHeader">
<Dropdown
label={dropdownLinks.label}
LeftLabelIcon={<img src="https://static.subquery.network/design/images/appIcon.svg" alt="SubQuery Apps" />}
LeftLabelIcon={<img src="https://static.subquery.network/design/images/app-icon.svg" alt="SubQuery Apps" />}
menuitem={dropdownLinks.links.map((label, key) => ({
key,
label: <MenuWithDesc title={label.label} description={label.description} width={isMobile ? '100%' : 366} />,
Expand Down
19 changes: 13 additions & 6 deletions components/common/chatUi/chatUi.less
Original file line number Diff line number Diff line change
Expand Up @@ -178,19 +178,26 @@
align-items: center;
gap: 12px;
color: rgb(209, 213, 219);

.subql-markdown-preview {
p {
margin-top: 0;
}
}
}

&__assistant {
background: rgb(68,70,84);
position: relative;
&--lastOne&--loading {
.subql-chat-conversation-message__item-span {
&::after {
content: "";
align-self: flex-end;
margin-left: 8px;
animation: pulseCursor 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;

.subql-markdown-preview {
&::after {
content: "";
align-self: flex-end;
margin-left: 8px;
animation: pulseCursor 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
}
}
}
Expand Down
34 changes: 23 additions & 11 deletions components/common/chatUi/chatUi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Typography } from '../typography';
import { v4 as uuidv4 } from 'uuid';
import { cloneDeep, isString } from 'lodash-es';
import Address from '../address';
import Markdown from '../markdown/Markdown';

const indexerName: { [key in string]: string } = {
'0xd0af1919af890cfdd8d12be5cf1b1421224fc29a': 'Mainnet Operator',
Expand All @@ -31,6 +32,7 @@ export interface ChatUiProps {
placeholder?: React.ReactNode;
width?: number;
height?: number;
model?: string;
}

export type AiMessageType = 'text' | 'image_url';
Expand Down Expand Up @@ -127,7 +129,9 @@ export const ConversationMessage = forwardRef<
bem('item'),
bem(message.role, {
[answerStatus]:
index === property.messages.length - 1 && message.role === 'assistant' ? true : undefined,
index === property.messages.length - 1 && message.role === 'assistant' && !message?.content?.length
? true
: undefined,
lastOne: index === property.messages.length - 1 && message.role === 'assistant' ? true : undefined,
}),
)}
Expand All @@ -142,7 +146,9 @@ export const ConversationMessage = forwardRef<
></RiRobot2Line>
)}
{/* TODO: support array */}
<span className={clsx(bem('item-span'))}>{isString(message.content) ? message.content : ''}</span>
<div className={clsx(bem('item-span'))}>
{isString(message.content) ? <Markdown.Preview>{message.content}</Markdown.Preview> : ''}
</div>
</div>
);
})}
Expand All @@ -155,23 +161,24 @@ ConversationMessage.displayName = 'ConversationMessage';
// maybe later support custom workspace name
const workspaceName = 'subql-chat-workspace';

export const chatWithStream = async (url: string, body: { messages: Message[] }) => {
export const chatWithStream = async (url: string, body: { messages: Message[]; model?: string }) => {
const { model = 'gemma2' } = body;
const res = await fetch(url, {
headers: {
accept: 'text/event-stream',
'Content-Type': 'application/json',
},
method: 'POST',
body: JSON.stringify({
model: 'gemma2',
model,
messages: body.messages,
stream: true,
}),
});
return res;
};

export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholder, width, height }) => {
export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholder, width, height, model }) => {
const bem = useBem('subql-chat');
const [chats, setChats] = React.useState<ConversationItemProps['property'][]>([]);
const [currentChat, setCurrentChat] = useState<ConversationItemProps['property']>();
Expand Down Expand Up @@ -206,7 +213,7 @@ export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholde
name: 'New Conversation',
chatUrl,
messages: [],
prompt: prompt || '',
prompt: '',
};

oldWorkspace.unshift(chat);
Expand Down Expand Up @@ -284,6 +291,7 @@ export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholde
name: curChat.messages.length ? curChat.name : currentInput.slice(0, 40),
};
newChat.chatUrl = newChat.messages.length - 1 > 0 ? newChat.chatUrl : chatUrl;
newChat.prompt = newChat.prompt || prompt || '';

const newChats = cloneDeep(curChats).map((chat) => {
if (chat.id === curChat.id) {
Expand All @@ -305,10 +313,12 @@ export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholde
};

await pushNewMsgToChat(newChat, robotAnswer, curChat, curChats);

// set user's message first, then get the response
const res = await chatWithStream(newChat.chatUrl, {
messages: prompt ? [{ role: 'system' as const, content: prompt }, ...newChat.messages] : newChat.messages,
messages: newChat.prompt
? [{ role: 'system' as const, content: newChat.prompt }, ...newChat.messages]
: newChat.messages,
model,
});

if (res.status === 200 && res.body) {
Expand All @@ -326,10 +336,9 @@ export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholde

const parts = chunkValue.split('\n\n');
for (const part of parts) {
const partWithHandle = part.startsWith('data: ') ? part.slice(6, part.length).trim() : part;
if (!part.startsWith('data: ')) {
if (invalidJson) {
try {
invalidJson += partWithHandle;
invalidJson += part;
const parsed: { choices: { delta: { content: string } }[] } = JSON.parse(invalidJson);
robotAnswer.content += parsed?.choices?.[0]?.delta?.content;

Expand All @@ -341,6 +350,8 @@ export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholde
continue;
}

const partWithHandle = part.startsWith('data: ') ? part.slice(6, part.length).trim() : part;

if (partWithHandle) {
try {
const parsed: { choices: { delta: { content: string } }[] } = JSON.parse(partWithHandle);
Expand All @@ -361,6 +372,7 @@ export const ChatUi: FC<ChatUiProps> = ({ chatUrl, prompt, className, placeholde

await pushNewMsgToChat(newChat, robotAnswer, curChat, curChats);
} catch (e) {
console.warn('Reach this code', invalidJson);
// to reach this code, it means the response is not valid or the code have something wrong.
}
}
Expand Down
6 changes: 3 additions & 3 deletions components/common/dropdown/Dropdown.less
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
}

&--active {
color: var(--sq-blue600);
color: var(--sq-primary);
.subql-typography {
color: var(--sq-blue600);
color: var(--sq-primary);
}

.subql-dropdown__icon {
color: var(--sq-blue600);
color: var(--sq-primary);
}
}

Expand Down
34 changes: 15 additions & 19 deletions components/styles.css
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
@font-face {
font-family: 'Inter';
src: local('Inter-Regular'), url('https://static.subquery.network/design/fonts/Inter-Regular.ttf') format('truetype');
font-family: 'PPNeue';
src: local('PPNeueMontreal-Bold'),
url('https://static.subquery.network/design/fonts/PPNeueMontreal-Bold.ttf') format('truetype');
font-display: swap;
font-weight: bold;
}

@font-face {
font-family: 'Inter-SemiBold';
src: local('Inter-SemiBold'),
url('https://static.subquery.network/design/fonts/Inter-SemiBold.ttf') format('truetype');
font-display: swap;
}

@font-face {
font-family: 'Inter-Bold';
src: local('Inter-Bold'), url('https://static.subquery.network/design/fonts/Inter-Bold.ttf') format('truetype');
font-display: swap;
}

@font-face {
font-family: 'Futura';
src: url('https://static.subquery.network/design/fonts/Futura-Medium.ttf') format('truetype');
font-family: 'PPNeue';
src: local('PPNeue-Regular'),
url('https://static.subquery.network/design/fonts/PPNeueMontreal-Regular.ttf') format('truetype');
font-display: swap;
}

:root {
--sq-primary: #e968dd;
--sq-primary-card-hover: #e968dd33;
--sq-primary-card-deephover: #e968dd66;
--sq-primary-link-hover: #d25ec7;

--sq-primary-pink: #ff4581;
--sq-primary-blue: #1677ff;
--sq-gradient: linear-gradient(96.26deg, var(--sq-primary-blue) 13.8%, var(--sq-primary-pink) 82.83%);
Expand All @@ -50,6 +45,7 @@
--sq-pink400: #ff6a9a;
--sq-pink500: #ff588e;
--sq-pink600: #ff4581;
--sq-pink700: #e968dd;

/* Gray */
--sq-gray100: #f9fafb;
Expand Down Expand Up @@ -98,8 +94,8 @@
--sq-border-radius: 8px;

/* Family */
--sq-font-family: 'Inter', Arial, sans-serif;
--sq-font-family-header: 'Futura', Arial, sans-serif;
--sq-font-family: 'PPNeue', Arial, sans-serif;
--sq-font-family-header: 'PPNeue', Arial, sans-serif;
}

body {
Expand Down

0 comments on commit af35e68

Please sign in to comment.