Skip to content

Commit 0e2cd5b

Browse files
Aliaksei VavilauAliaksei Vavilau
authored andcommitted
Merge branch 'development' into release-0.1
2 parents cbda33e + f559f08 commit 0e2cd5b

87 files changed

Lines changed: 2757 additions & 375 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.development

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ OPENAI_API_HOST=""
33
OPENAI_API_KEY=""
44
OPENAI_API_VERSION="2023-03-15-preview"
55

6+
# App Settings
7+
APP_BASE_PATH=""
8+
69
# AUTH
710
AUTH_DISABLED="false"
811

@@ -83,4 +86,7 @@ AZURE_FUNCTIONS_API_HOST=""
8386
REPORT_ISSUE_CODE=""
8487

8588
## Request API Key code
86-
REQUEST_API_KEY_CODE=""
89+
REQUEST_API_KEY_CODE=""
90+
91+
## Warning regarding code generation
92+
CODE_GENERATION_WARNING="Full responsibility for code correctness, security and licensing lies solely with the user, not with DIAL platform or LLM vendor."

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# DIAL Chat
22

3-
This is a default UI for [AI DIAL](https://epam-rail.com). AI DIAL can be used as headless system, but UI is recommended to learn the capability.
3+
This is a default UI for [AI DIAL](https://epam-rail.com). AI DIAL can be used as headless system, but UI is recommended to learn the capability.
44

5-
Originally forked from [chatbot-ui](https://github.com/mckaywrigley/chatbot-ui) and then completely reworked and published under [apache 2.0 license](./LICENSE), while code taken from original repository is still subject to [original MIT license](./license-original). Due to rework we introduced lots of new features such as varios IDP support, model side-by-side compare, [DIAL extensions](https://epam-rail.com/extension-framework) support, conversation replays, branding and many more.
5+
Originally forked from [chatbot-ui](https://github.com/mckaywrigley/chatbot-ui) and then completely reworked and published under [apache 2.0 license](./LICENSE), while code taken from original repository is still subject to [original MIT license](./license-original). Due to rework we introduced lots of new features such as varios IDP support, model side-by-side compare, [DIAL extensions](https://epam-rail.com/extension-framework) support, conversation replays, branding and many more.
66

77
![ai-dial-chat](./docs/ai-dial-chat.png)
88

@@ -107,6 +107,7 @@ This project leverages environment variables for configuration:
107107
| OPENAI_API_HOST | OpenAI API Host | | true |
108108
| OPENAI_API_KEY | OpenAI API Key | | true |
109109
| OPENAI_API_VERSION | OpenAI API Version | 2023-03-15-preview | true |
110+
| APP_BASE_PATH | Application base path | | |
110111
| ALLOWED_IFRAME_ORIGINS | Allowed iFrame Origins | | |
111112
| IS_IFRAME | Is iFrame | false | |
112113
| ENABLED_FEATURES | Enabled Features | conversations-section,prompts-section,top-settings,top-clear-conversation,top-chat-info,top-chat-model-settings,empty-chat-settings,header,footer,request-api-key,report-an-issue,likes | |
@@ -127,6 +128,7 @@ This project leverages environment variables for configuration:
127128
| AZURE_FUNCTIONS_API_HOST | Azure Functions API Host | | |
128129
| REPORT_ISSUE_CODE | Report Issue Code | | |
129130
| REQUEST_API_KEY_CODE | Request API Key Code | | |
131+
| CODE_GENERATION_WARNING | Warning text regarding code generation | Full responsibility for code correctness, security and licensing lies solely with the user, not with DIAL platform or LLM vendor. | |
130132

131133
The .env file contains environment variables that can be used to configure your app's settings and behavior. These values can be changed as needed to suit your specific requirements.
132134

e2e/src/core/fixtures.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { LocalStorageManager } from '../core/localStorageManager ';
21
import { DialHomePage } from '../ui/pages';
32
import { LoginPage } from '../ui/pages';
43
import {
@@ -15,13 +14,15 @@ import {
1514
} from '../ui/webElements';
1615
import { ChatBar } from '../ui/webElements';
1716
import { PromptBar } from '../ui/webElements';
17+
import { LocalStorageManager } from './localStorageManager';
1818

1919
import { ConversationData } from '@/e2e/src/testData';
2020
import { ApiHelper } from '@/e2e/src/testData/api/apiHelper';
2121
import { PromptData } from '@/e2e/src/testData/prompts/promptData';
2222
import { Addons } from '@/e2e/src/ui/webElements/addons';
2323
import { AddonsDialog } from '@/e2e/src/ui/webElements/addonsDialog';
2424
import { ChatInfoTooltip } from '@/e2e/src/ui/webElements/chatInfoTooltip';
25+
import { Compare } from '@/e2e/src/ui/webElements/compare';
2526
import { ConfirmationDialog } from '@/e2e/src/ui/webElements/confirmationDialog';
2627
import { DropdownMenu } from '@/e2e/src/ui/webElements/dropdownMenu';
2728
import { EntitySettings } from '@/e2e/src/ui/webElements/entitySettings';
@@ -75,6 +76,12 @@ const test = base.extend<
7576
moreInfo: MoreInfo;
7677
apiHelper: ApiHelper;
7778
chatInfoTooltip: ChatInfoTooltip;
79+
compare: Compare;
80+
compareConversationSelector: ModelSelector;
81+
rightConversationSettings: ConversationSettings;
82+
leftConversationSettings: ConversationSettings;
83+
rightChatHeader: ChatHeader;
84+
leftChatHeader: ChatHeader;
7885
}
7986
>({
8087
// eslint-disable-next-line no-empty-pattern
@@ -204,8 +211,8 @@ const test = base.extend<
204211
const moreInfo = entitySettings.getMoreInfo();
205212
await use(moreInfo);
206213
},
207-
chatHeader: async ({ page }, use) => {
208-
const chatHeader = new ChatHeader(page);
214+
chatHeader: async ({ chat }, use) => {
215+
const chatHeader = chat.getChatHeader();
209216
await use(chatHeader);
210217
},
211218
// eslint-disable-next-line no-empty-pattern
@@ -230,6 +237,32 @@ const test = base.extend<
230237
const chatInfoTooltip = new ChatInfoTooltip(page);
231238
await use(chatInfoTooltip);
232239
},
240+
compare: async ({ chat }, use) => {
241+
const compare = chat.getCompare();
242+
await use(compare);
243+
},
244+
compareConversationSelector: async ({ compare }, use) => {
245+
const compareConversationSelector = compare
246+
.getConversationToCompare()
247+
.getConversationSelector();
248+
await use(compareConversationSelector);
249+
},
250+
rightConversationSettings: async ({ compare }, use) => {
251+
const rightConversationSettings = compare.getRightConversationSettings();
252+
await use(rightConversationSettings);
253+
},
254+
leftConversationSettings: async ({ compare }, use) => {
255+
const leftConversationSettings = compare.getLeftConversationSettings();
256+
await use(leftConversationSettings);
257+
},
258+
rightChatHeader: async ({ compare }, use) => {
259+
const rightChatHeader = compare.getRightChatHeader();
260+
await use(rightChatHeader);
261+
},
262+
leftChatHeader: async ({ compare }, use) => {
263+
const leftChatHeader = compare.getLeftChatHeader();
264+
await use(leftChatHeader);
265+
},
233266
});
234267

235268
export default test;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { Conversation } from '@/src/types/chat';
2+
import { FolderInterface } from '@/src/types/folder';
3+
import { Prompt } from '@/src/types/prompt';
4+
5+
import { Page } from '@playwright/test';
6+
7+
export class LocalStorageManager {
8+
private page: Page;
9+
10+
constructor(page: Page) {
11+
this.page = page;
12+
}
13+
14+
setFoldersKey = () => (folders: string) => {
15+
window.localStorage.setItem('folders', folders);
16+
};
17+
18+
setConversationHistoryKey = () => (history: string) => {
19+
window.localStorage.setItem('conversationHistory', history);
20+
};
21+
22+
setPromptsKey = () => (prompt: string) => {
23+
window.localStorage.setItem('prompts', prompt);
24+
};
25+
26+
setSelectedConversationKey = () => (selected: string) => {
27+
window.localStorage.setItem('selectedConversationIds', selected);
28+
};
29+
30+
async setConversationHistory(...conversation: Conversation[]) {
31+
await this.page.addInitScript(
32+
this.setConversationHistoryKey(),
33+
JSON.stringify(conversation),
34+
);
35+
}
36+
37+
async updateConversationHistory(...conversation: Conversation[]) {
38+
await this.page.evaluate(
39+
this.setConversationHistoryKey(),
40+
JSON.stringify(conversation),
41+
);
42+
}
43+
44+
async setSelectedConversation(...conversation: Conversation[]) {
45+
await this.page.addInitScript(
46+
this.setSelectedConversationKey(),
47+
JSON.stringify(conversation.map((c) => c.id)),
48+
);
49+
}
50+
51+
async updateSelectedConversation(...conversation: Conversation[]) {
52+
await this.page.evaluate(
53+
this.setSelectedConversationKey(),
54+
JSON.stringify(conversation.map((c) => c.id)),
55+
);
56+
}
57+
58+
async setFolders(...folders: FolderInterface[]) {
59+
await this.page.addInitScript(
60+
this.setFoldersKey(),
61+
JSON.stringify(folders),
62+
);
63+
}
64+
65+
async updateFolders(...folders: FolderInterface[]) {
66+
await this.page.evaluate(this.setFoldersKey(), JSON.stringify(folders));
67+
}
68+
69+
async setPrompts(...prompt: Prompt[]) {
70+
await this.page.addInitScript(this.setPromptsKey(), JSON.stringify(prompt));
71+
}
72+
73+
async updatePrompts(...prompt: Prompt[]) {
74+
await this.page.evaluate(this.setPromptsKey(), JSON.stringify(prompt));
75+
}
76+
}

e2e/src/testData/api/apiHelper.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { OpenAIEntityAddon, OpenAIEntityModel } from '@/src/types/openai';
22

3+
import { API } from '@/e2e/src/testData';
34
import { APIRequestContext } from '@playwright/test';
45

56
export class ApiHelper {
@@ -12,38 +13,43 @@ export class ApiHelper {
1213

1314
public async getModelNames() {
1415
const allEntities = await this.getModels();
15-
return allEntities.filter((e) => e.type === 'model').map((m) => m.name);
16+
return allEntities.map((m) => m.name);
1617
}
1718

1819
public async getEntity(entity: OpenAIEntityModel) {
19-
const allEntities = await this.getModels();
20+
const allEntities = await this.getModelEntities();
2021
return allEntities.find((e) => e.id === entity.id);
2122
}
2223

2324
public async getApplicationNames() {
24-
const allEntities = await this.getModels();
25+
const allEntities = await this.getModelEntities();
2526
return allEntities
2627
.filter((e) => e.type === 'application')
2728
.map((app) => app.name);
2829
}
2930

30-
public async getAddonNameById(addonId: string) {
31+
public async getAddonById(addonId: string) {
3132
const allEntities = await this.getAddons();
3233
return allEntities.find((e) => e.type === 'addon' && e.id === addonId);
3334
}
3435

3536
public async getAssistant(assistant: string) {
36-
const allEntities = await this.getModels();
37+
const allEntities = await this.getModelEntities();
3738
return allEntities.find(
3839
(e) => e.type === 'assistant' && e.name === assistant,
3940
);
4041
}
4142

4243
public async getApplication(app: string) {
43-
const allEntities = await this.getModels();
44+
const allEntities = await this.getModelEntities();
4445
return allEntities.find((e) => e.type === 'application' && e.name === app);
4546
}
4647

48+
public async getModel(model: string) {
49+
const allEntities = await this.getModels();
50+
return allEntities.find((e) => e.name === model);
51+
}
52+
4753
public async getApplicationDescription(app: string) {
4854
const application = await this.getApplication(app);
4955
const description = application!.description;
@@ -86,7 +92,7 @@ export class ApiHelper {
8692
}
8793

8894
public async getEntitySelectedAddons(entity: string) {
89-
const allEntities = await this.getModels();
95+
const allEntities = await this.getModelEntities();
9096
const entityObject = allEntities.find((e) => e.name === entity);
9197
const selectedAddons: string[] = [];
9298
const entityAddonObjects = entityObject!.selectedAddons;
@@ -100,7 +106,12 @@ export class ApiHelper {
100106
}
101107

102108
public async getModels() {
103-
const response = await this.request.get('/api/models', {
109+
const modelEntities = await this.getModelEntities();
110+
return modelEntities.filter((e) => e.type === 'model');
111+
}
112+
113+
public async getModelEntities() {
114+
const response = await this.request.get(API.modelsHost, {
104115
failOnStatusCode: true,
105116
timeout: ApiHelper.requestTimeout,
106117
});
@@ -109,7 +120,7 @@ export class ApiHelper {
109120
}
110121

111122
public async getAddons() {
112-
const response = await this.request.get('/api/addons', {
123+
const response = await this.request.get(API.addonsHost, {
113124
failOnStatusCode: true,
114125
timeout: ApiHelper.requestTimeout,
115126
});

0 commit comments

Comments
 (0)