Skip to content

Commit

Permalink
feat(chat): refactoring of QuickApps (Issue #2936) (#2946)
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaBondar authored Jan 17, 2025
1 parent dccd56d commit 1eb79f1
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 75 deletions.
1 change: 1 addition & 0 deletions apps/chat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ AI DIAL Chat uses environment variables for configuration. All environment varia
| `RECENT_ADDONS_IDS` | No | A list of IDs for recently-used addons | Any string | |
| `THEMES_CONFIG_HOST` | No | The host URL for a custom themes configuration.<br />Can lead to public and private resource.<br />Refer to [Theme Customization](../../docs/THEME-CUSTOMIZATION.md) to learn more. | Any string | |
| `QUICK_APPS_HOST` | No | The host URL for a Quick Apps Completion URLs.<br />Can lead to public and private resource. more. | Any string | |
| `QUICK_APPS_SCHEMA_ID` | No | `applicationTypeSchemaId` value for QuickApp application type | Any string | |
| `QUICK_APPS_MODEL` | No | A model that will be used in Quick Apps | Any string | |
| `FOOTER_HTML_MESSAGE` | No | A message that will be displayed in the application's footer.<br />Specify in HTML format. | Any string | |
| `ANNOUNCEMENT_HTML_MESSAGE` | No | A message of the announcement banner.<br />Specify in HTML format. | Any string | |
Expand Down
1 change: 1 addition & 0 deletions apps/chat/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare global {

QUICK_APPS_HOST?: string;
QUICK_APPS_MODEL?: string;
QUICK_APPS_SCHEMA_ID?: string;

DIAL_API_VERSION?: string;
APP_BASE_PATH?: string;
Expand Down
21 changes: 12 additions & 9 deletions apps/chat/src/components/Common/ApplicationWizard/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ import {
} from '@/src/constants/default-ui-settings';
import { MIME_FORMAT_REGEX } from '@/src/constants/file';
import { DEFAULT_VERSION } from '@/src/constants/public';
import { DEFAULT_QUICK_APPS_HOST } from '@/src/constants/quick-apps';
import {
DEFAULT_QUICK_APPS_HOST,
DEFAULT_QUICK_APPS_SCHEMA_ID,
} from '@/src/constants/quick-apps';

import { DynamicField } from '@/src/components/Common/Forms/DynamicFormFields';

Expand Down Expand Up @@ -313,11 +316,9 @@ export const getDefaultValues = ({
maxInputAttachments: String(app?.maxInputAttachments ?? ''),
completionUrl: app?.completionUrl ?? '',
features: safeStringify(app?.features),
instructions: app ? getQuickAppConfig(app).config.instructions : '',
temperature: app
? getQuickAppConfig(app).config.temperature
: DEFAULT_TEMPERATURE,
toolset: app ? getToolsetStr(getQuickAppConfig(app).config) : '',
instructions: app ? getQuickAppConfig(app).instructions : '',
temperature: app ? getQuickAppConfig(app).temperature : DEFAULT_TEMPERATURE,
toolset: app ? getToolsetStr(getQuickAppConfig(app)) : '',
sources: app?.function?.sourceFolder ?? '',
endpoints: app?.function?.mapping
? Object.entries(app.function.mapping).map(([key, value]) => ({
Expand Down Expand Up @@ -376,12 +377,14 @@ export const getApplicationData = (
: null;
}
if (type === ApplicationType.QUICK_APP) {
preparedData.description = createQuickAppConfig({
description: formData.description ?? '',
preparedData.applicationTypeSchemaId = DefaultsService.get(
'quickAppsSchemaId',
DEFAULT_QUICK_APPS_SCHEMA_ID,
);
preparedData.applicationProperties = createQuickAppConfig({
config: formData.toolset,
instructions: formData.instructions ?? '',
temperature: formData.temperature,
name: formData.name.trim(),
});
preparedData.completionUrl = constructPath(
DefaultsService.get('quickAppsHost', DEFAULT_QUICK_APPS_HOST),
Expand Down
5 changes: 3 additions & 2 deletions apps/chat/src/constants/quick-apps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const QUICK_APP_CONFIG_DIVIDER = '>>>>>>>>>>';

export const DEFAULT_QUICK_APPS_MODEL = 'gpt-4o';

export const DEFAULT_QUICK_APPS_HOST =
'http://quickapps.dial-development.svc.cluster.local';

export const DEFAULT_QUICK_APPS_SCHEMA_ID =
'https://mydial.epam.com/custom_application_schemas/quickapps';
10 changes: 10 additions & 0 deletions apps/chat/src/store/settings/settings.reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FALLBACK_ASSISTANT_SUBMODEL_ID } from '@/src/constants/default-ui-setti
import {
DEFAULT_QUICK_APPS_HOST,
DEFAULT_QUICK_APPS_MODEL,
DEFAULT_QUICK_APPS_SCHEMA_ID,
} from '@/src/constants/quick-apps';

import { RootState } from '..';
Expand Down Expand Up @@ -45,6 +46,7 @@ export interface SettingsState {
codeEditorPythonVersions: string[];
quickAppsHost?: string;
quickAppsModel?: string;
quickAppsSchemaId?: string;
dialApiHost?: string;
defaultSystemPrompt?: string;
}
Expand Down Expand Up @@ -337,6 +339,11 @@ const selectQuickAppsModel = createSelector(
(state) => state.quickAppsModel ?? DEFAULT_QUICK_APPS_MODEL,
);

const selectQuickAppsSchemaId = createSelector(
[rootSelector],
(state) => state.quickAppsSchemaId ?? DEFAULT_QUICK_APPS_SCHEMA_ID,
);

const selectDialApiHost = createSelector(
[rootSelector],
(state) => state.dialApiHost ?? '',
Expand All @@ -352,20 +359,23 @@ const selectDefaults = createSelector(
selectDefaultAssistantSubmodelId,
selectQuickAppsHost,
selectQuickAppsModel,
selectQuickAppsSchemaId,
selectDialApiHost,
selectDefaultSystemPrompt,
],
(
assistantSubmodelId,
quickAppsHost,
quickAppsModel,
quickAppsSchemaId,
dialApiHost,
defaultSystemPrompt,
) =>
({
assistantSubmodelId,
quickAppsHost,
quickAppsModel,
quickAppsSchemaId,
dialApiHost,
defaultSystemPrompt,
}) as Defaults,
Expand Down
14 changes: 13 additions & 1 deletion apps/chat/src/types/applications.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DialAIEntityFeatures, DialAIEntityModel } from './models';
import { QuickAppConfig } from './quick-apps';

import { Entity } from '@epam/ai-dial-shared';

Expand Down Expand Up @@ -39,6 +40,8 @@ export interface ApiApplicationResponseBase {
description_keywords?: string[];
endpoint: string;
function?: ApiApplicationFunctionType;
application_type_schema_id?: string;
application_properties?: QuickAppConfig | Record<string, unknown>;
}

export interface ApiApplicationResponsePublication
Expand Down Expand Up @@ -67,21 +70,29 @@ export interface ApiApplicationModelBase {
url?: string;
reference?: string;
description_keywords?: string[];
applicationTypeSchemaId?: string;
applicationProperties?: QuickAppConfig | Record<string, unknown>;
}

export interface ApiApplicationModelRegular extends ApiApplicationModelBase {
endpoint: string;
function?: never;
}

export interface ApiApplicationModelSchema extends ApiApplicationModelBase {
endpoint?: never;
applicationTypeSchemaId: string;
}

export interface ApiApplicationModelFunction extends ApiApplicationModelBase {
endpoint?: never;
function: Omit<ApiApplicationFunctionType, 'status'>;
}

export type ApiApplicationModel =
| ApiApplicationModelRegular
| ApiApplicationModelFunction;
| ApiApplicationModelFunction
| ApiApplicationModelSchema;

export interface ApplicationInfo extends Entity {
version: string;
Expand All @@ -98,6 +109,7 @@ export interface CustomApplicationModel
env?: Record<string, string>;
};
version: string;
applicationProperties?: QuickAppConfig | Record<string, unknown>;
}

export interface ApplicationLogsType {
Expand Down
2 changes: 2 additions & 0 deletions apps/chat/src/types/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface CoreAIEntity<T = EntityType.Model> {
function?: {
status: ApplicationStatus;
};
application_type_schema_id?: string;
}

export interface DialAIEntityFeatures {
Expand Down Expand Up @@ -91,6 +92,7 @@ export interface DialAIEntityModel extends Omit<DialAIEntity, 'type'> {
topics?: string[];

functionStatus?: ApplicationStatus;
applicationTypeSchemaId?: string;
}

export interface DialAIEntityAddon extends Omit<DialAIEntity, 'type'> {
Expand Down
2 changes: 0 additions & 2 deletions apps/chat/src/types/quick-apps.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
export interface QuickAppConfig {
description: string;
instructions: string;
model: string;
name: string;
temperature: number;
web_api_toolset: object;
}
92 changes: 31 additions & 61 deletions apps/chat/src/utils/app/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { getTopicColors } from '@/src/utils/app/style-helpers';

import {
ApiApplicationModel,
ApiApplicationModelBase,
ApiApplicationModelSchema,
ApiApplicationResponse,
ApplicationInfo,
ApplicationStatus,
Expand All @@ -18,7 +20,7 @@ import { DESCRIPTION_DELIMITER_REGEX } from '@/src/constants/chat';
import { DEFAULT_TEMPERATURE } from '@/src/constants/default-ui-settings';
import {
DEFAULT_QUICK_APPS_MODEL,
QUICK_APP_CONFIG_DIVIDER,
DEFAULT_QUICK_APPS_SCHEMA_ID,
} from '@/src/constants/quick-apps';

import { ApiUtils, getApplicationApiKey } from '../server/api';
Expand Down Expand Up @@ -53,17 +55,18 @@ export const regenerateApplicationId = <T extends ApplicationInfo>(
export const convertApplicationToApi = (
applicationData: Omit<CustomApplicationModel, 'id'>,
): ApiApplicationModel => {
const commonData = {
const commonData: ApiApplicationModelBase = {
display_name: applicationData.name,
display_version: applicationData.version,
icon_url: ApiUtils.encodeApiUrl(applicationData.iconUrl ?? ''),
description: applicationData.description,
features: applicationData.features,
input_attachment_types: applicationData.inputAttachmentTypes,
max_input_attachments: applicationData.maxInputAttachments,
defaults: {},
reference: applicationData.reference || undefined,
description_keywords: applicationData.topics,
applicationTypeSchemaId: applicationData.applicationTypeSchemaId,
applicationProperties: applicationData.applicationProperties,
};

if (applicationData.function) {
Expand All @@ -80,6 +83,9 @@ export const convertApplicationToApi = (
};
}

if (commonData.applicationTypeSchemaId) {
return commonData as ApiApplicationModelSchema;
}
return {
...commonData,
endpoint: applicationData.completionUrl,
Expand Down Expand Up @@ -113,88 +119,52 @@ export const convertApplicationFromApi = (
completionUrl: application.endpoint ?? '',
folderId: getFolderIdFromEntityId(id),
topics: application.description_keywords,
applicationTypeSchemaId: application.application_type_schema_id,
applicationProperties: application.application_properties,
...(appFunction && {
function: appFunction,
functionStatus: appFunction.status,
}),
};
};

export const isQuickApp = (entity: DialAIEntityModel) => {
const { description } = entity;

return !!description?.includes(QUICK_APP_CONFIG_DIVIDER);
};
export const isQuickApp = (entity: DialAIEntityModel) =>
entity.applicationTypeSchemaId === DEFAULT_QUICK_APPS_SCHEMA_ID;

export const getModelDescription = (entity: DialAIEntityModel) => {
return entity.description
? entity.description.split(QUICK_APP_CONFIG_DIVIDER)[0]
: '';
return entity.description ?? '';
};

export const getModelShortDescription = (entity: DialAIEntityModel) =>
getModelDescription(entity).split(DESCRIPTION_DELIMITER_REGEX)[0];

export const parseQuickAppDescription = (desc: string) => {
const [description, config] = desc.split(QUICK_APP_CONFIG_DIVIDER);

return {
description,
config,
};
};

export const getQuickAppConfig = (entity: DialAIEntityModel) => {
const { description, config } = parseQuickAppDescription(
entity.description ?? QUICK_APP_CONFIG_DIVIDER,
);

let parsedConfig: QuickAppConfig;
try {
parsedConfig = JSON.parse(config);
} catch {
parsedConfig = {
description: getModelDescription(entity),
instructions: '',
model: DefaultsService.get('quickAppsModel', DEFAULT_QUICK_APPS_MODEL),
name: entity.name,
temperature: DEFAULT_TEMPERATURE,
web_api_toolset: {},
};
}

return {
description,
config: parsedConfig,
};
export const getQuickAppConfig = (
entity: CustomApplicationModel,
): QuickAppConfig => {
return (entity.applicationProperties as QuickAppConfig)?.web_api_toolset
? (entity.applicationProperties as QuickAppConfig)
: {
instructions: '',
model: DefaultsService.get('quickAppsModel', DEFAULT_QUICK_APPS_MODEL),
temperature: DEFAULT_TEMPERATURE,
web_api_toolset: {},
};
};

export const createQuickAppConfig = ({
description,
instructions,
name,
temperature,
config,
}: {
description: string;
instructions: string;
name: string;
temperature: number;
config: string;
}) => {
const preparedConfig: QuickAppConfig = {
description,
instructions,
name,
temperature,
web_api_toolset: JSON.parse(config ?? '{}'),
model: DefaultsService.get('quickAppsModel', DEFAULT_QUICK_APPS_MODEL),
};

return [description.trim(), JSON.stringify(preparedConfig)].join(
QUICK_APP_CONFIG_DIVIDER,
);
};
}): QuickAppConfig => ({
instructions,
temperature,
web_api_toolset: JSON.parse(config ?? '{}'),
model: DefaultsService.get('quickAppsModel', DEFAULT_QUICK_APPS_MODEL),
});

export const topicToOption = (topic: string) => ({
value: topic,
Expand Down
1 change: 1 addition & 0 deletions apps/chat/src/utils/app/data/defaults-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface Defaults {
assistantSubmodelId: string;
quickAppsHost: string;
quickAppsModel: string;
quickAppsSchemaId: string;
dialApiHost: string;
defaultSystemPrompt: string;
}
Expand Down
3 changes: 3 additions & 0 deletions apps/chat/src/utils/server/get-common-page-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import {
DEFAULT_QUICK_APPS_HOST,
DEFAULT_QUICK_APPS_MODEL,
DEFAULT_QUICK_APPS_SCHEMA_ID,
} from '@/src/constants/quick-apps';

import { authOptions } from '@/src/pages/api/auth/[...nextauth]';
Expand Down Expand Up @@ -142,6 +143,8 @@ export const getCommonPageProps: GetServerSideProps = async ({
).split(','),
quickAppsHost: process.env.QUICK_APPS_HOST || DEFAULT_QUICK_APPS_HOST,
quickAppsModel: process.env.QUICK_APPS_MODEL || DEFAULT_QUICK_APPS_MODEL,
quickAppsSchemaId:
process.env.QUICK_APPS_SCHEMA_ID || DEFAULT_QUICK_APPS_SCHEMA_ID,
dialApiHost: process.env.DIAL_API_HOST || '',
defaultSystemPrompt: process.env.NEXT_PUBLIC_DEFAULT_SYSTEM_PROMPT || '',
};
Expand Down
1 change: 1 addition & 0 deletions apps/chat/src/utils/server/get-sorted-entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export const getSortedEntities = async (token: JWT | null) => {
...(entity.function && {
functionStatus: entity.function?.status,
}),
applicationTypeSchemaId: entity.application_type_schema_id,
});
}

Expand Down

0 comments on commit 1eb79f1

Please sign in to comment.