Skip to content

Commit c19009c

Browse files
authored
feat: handle rate limit error case (#132)
1 parent 1b68c40 commit c19009c

File tree

26 files changed

+513
-72
lines changed

26 files changed

+513
-72
lines changed

apps/portals-example/src/components/configs/TextsConfig/TextsConfig.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import {
44
ConversationViewMessages,
55
ConversationViewMessagesProvider,
66
} from '@epam/statgpt-conversation-view';
7-
import { ReactNode, useMemo } from 'react';
7+
import { ReactNode, useCallback, useMemo } from 'react';
88
import { TranslateI18nFn, useI18n } from '../../../locales/client';
99
import { StatusMessagesI18nKeys } from '../../../constants/i18n-keys';
10+
import { ExceededLimit } from '@epam/statgpt-dial-toolkit';
11+
import { getExceededLimitsMessage } from '@statgpt/portals-example/src/utils/rate-limits';
1012

1113
export const TextsConfig = ({
1214
children,
@@ -41,12 +43,28 @@ export const TextsConfig = ({
4143
return t(StatusMessagesI18nKeys.CONTENT_FILTER_ERROR, { link: href });
4244
}, [azureContentManagementPolicyUrl, t]);
4345

46+
const getAssistantRestoreMessage = useCallback(
47+
(date: string, time: string) =>
48+
t(StatusMessagesI18nKeys.ASSISTANT_ACCESS_RESTORE_DATETIME, {
49+
date,
50+
time,
51+
}),
52+
[t],
53+
);
54+
55+
const getLimitsExceededMessage = useCallback(
56+
(limits: ExceededLimit[]) => getExceededLimitsMessage(limits, t),
57+
[t],
58+
);
59+
4460
const conversationViewMessagesCustomConfig: ConversationViewMessages = {
4561
statusMessages: {
4662
contentFilterError,
4763
assistantUnavailable,
4864
serverError: t(StatusMessagesI18nKeys.SERVER_ERROR),
4965
serverOverloaded: t(StatusMessagesI18nKeys.SERVER_OVERLOADED),
66+
getExceededLimitsMessage: getLimitsExceededMessage,
67+
getAssistantRestoreMessage,
5068
},
5169
};
5270

apps/portals-example/src/constants/i18n-keys.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export enum StatusMessagesI18nKeys {
126126
SERVER_ERROR = 'statusMessages.serverError',
127127
SERVER_OVERLOADED = 'statusMessages.serverOverloaded',
128128
CONTENT_FILTER_ERROR = 'statusMessages.contentFilterError',
129+
ASSISTANT_ACCESS_RESTORE_DATETIME = 'statusMessages.rateLimit.assistantAccessRestoreDateTime',
129130
}
130131

131132
export enum AttachmentsI18nKeys {

apps/portals-example/src/locales/en/common.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,25 @@
167167
"contactSupport": "contact Support",
168168
"serverError": "We couldn't process your request due to a server error. Please try again later.",
169169
"serverOverloaded": "The system is currently overloaded. Please try again later.",
170-
"contentFilterError": "This request is blocked in accordance with the Azure OpenAI content management policy {link}"
170+
"contentFilterError": "This request is blocked in accordance with the Azure OpenAI content management policy {link}",
171+
"rateLimit": {
172+
"assistantAccessRestoreDateTime": "Access to the AI Assistant will be restored on {date} at {time}",
173+
"limit": {
174+
"minute": "minute",
175+
"daily": "daily",
176+
"weekly": "weekly",
177+
"monthly": "monthly"
178+
},
179+
"list": {
180+
"two": "{first} and {second}",
181+
"many": "{items}, and {last}"
182+
},
183+
"message": {
184+
"exceeded": {
185+
"one": "The {limits} token limit has been exceeded.",
186+
"many": "The {limits} token limits have been exceeded."
187+
}
188+
}
189+
}
171190
}
172191
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {
2+
EXCEEDED_LIMIT_ORDER,
3+
ExceededLimit,
4+
} from '@epam/statgpt-dial-toolkit';
5+
6+
function uniqExceededLimits(limits: ExceededLimit[]): ExceededLimit[] {
7+
return [...new Set(limits)];
8+
}
9+
10+
function sortExceededLimits(limits: ExceededLimit[]): ExceededLimit[] {
11+
return [...limits].sort(
12+
(a, b) => EXCEEDED_LIMIT_ORDER.indexOf(a) - EXCEEDED_LIMIT_ORDER.indexOf(b),
13+
);
14+
}
15+
16+
function formatExceededLimitsList(
17+
limits: ExceededLimit[],
18+
t: (key: string, params?: Record<string, string>) => string,
19+
): string {
20+
const labels = sortExceededLimits(uniqExceededLimits(limits)).map((limit) =>
21+
t(`statusMessages.rateLimit.limit.${limit}`),
22+
);
23+
24+
if (labels.length === 0) {
25+
return '';
26+
}
27+
28+
if (labels.length === 1) {
29+
return labels[0];
30+
}
31+
32+
if (labels.length === 2) {
33+
return t('statusMessages.rateLimit.list.two', {
34+
first: labels[0],
35+
second: labels[1],
36+
});
37+
}
38+
39+
return t('statusMessages.rateLimit.list.many', {
40+
items: labels.slice(0, -1).join(', '),
41+
last: labels[labels.length - 1],
42+
});
43+
}
44+
45+
export function getExceededLimitsMessage(
46+
limits: ExceededLimit[],
47+
t: (key: string, params?: Record<string, string>) => string,
48+
): string {
49+
const normalizedLimits = sortExceededLimits(uniqExceededLimits(limits));
50+
const formattedLimits = formatExceededLimitsList(normalizedLimits, t);
51+
52+
if (!formattedLimits) {
53+
return '';
54+
}
55+
56+
return t(
57+
normalizedLimits.length === 1
58+
? 'statusMessages.rateLimit.message.exceeded.one'
59+
: 'statusMessages.rateLimit.message.exceeded.many',
60+
{
61+
limits: formattedLimits,
62+
},
63+
);
64+
}

libs/conversation-list/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"license": "MIT",
55
"dependencies": {
66
"@tabler/icons-react": "^3.34.1",
7-
"@epam/ai-dial-shared": "^0.34.0",
7+
"@epam/ai-dial-shared": "^0.43.3",
88
"@epam/statgpt-ui-components": "*",
99
"classnames": "^2.5.1",
1010
"@epam/statgpt-shared-toolkit": "*",

libs/conversation-view/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"license": "MIT",
55
"dependencies": {
66
"classnames": "^2.5.1",
7-
"@epam/ai-dial-shared": "^0.34.0",
7+
"@epam/ai-dial-shared": "^0.43.3",
88
"@tabler/icons-react": "^3.34.1",
99
"@epam/statgpt-shared-toolkit": "*",
1010
"@epam/statgpt-ui-components": "*",

libs/conversation-view/src/components/ChatMessages/ChatMessages.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ import {
2424
InlineAlert,
2525
InlineAlertType,
2626
} from '@epam/statgpt-ui-components';
27-
import { Message as MessageType } from '@epam/statgpt-dial-toolkit';
27+
import {
28+
CustomViewState,
29+
ERROR_CONTEXT_KIND,
30+
Message as MessageType,
31+
} from '@epam/statgpt-dial-toolkit';
2832
import {
2933
DataQuery,
3034
FormatNumbersType,
@@ -72,13 +76,15 @@ interface Props {
7276
isReadOnlyConversation?: boolean;
7377
limitMessages: LimitMessages;
7478
attachmentsConfig?: AttachmentsConfig;
79+
conversationViewState?: CustomViewState;
7580
}
7681

7782
const ChatMessages: FC<Props> = ({
7883
messages,
7984
isStreaming = false,
8085
isReadOnly,
8186
scrollBottomIcon,
87+
conversationViewState,
8288
...props
8389
}) => {
8490
const messagesEndRef = useRef<HTMLDivElement>(null);
@@ -178,8 +184,14 @@ const ChatMessages: FC<Props> = ({
178184
const key = message.id ?? index;
179185

180186
if (message.errorMessage) {
187+
const type =
188+
conversationViewState?.errorContext?.kind ===
189+
ERROR_CONTEXT_KIND.RATE_LIMIT
190+
? InlineAlertType.Warning
191+
: InlineAlertType.Error;
192+
181193
return (
182-
<InlineAlert key={key} type={InlineAlertType.Error}>
194+
<InlineAlert key={key} type={type}>
183195
<div className="flex flex-col">
184196
{processErrorMessage(message.errorMessage)}
185197
</div>

0 commit comments

Comments
 (0)