Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(overlay)!: fix setting model id in overlay (Issue #2297) #2604

Open
wants to merge 10 commits into
base: development
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion apps/chat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ AI DIAL Chat uses environment variables for configuration. All environment varia
| `NEXT_PUBLIC_APP_NAME` | No | Application name | Any string | `AI Dial` |
| `NEXT_PUBLIC_DEFAULT_SYSTEM_PROMPT` | No | Default system prompt | Any string | |
| `NEXT_PUBLIC_DEFAULT_TEMPERATURE` | No | Default temperature | 0 to 1 | |
| `DEFAULT_MODEL` | No | A model that is pre-selected for a new conversation.<br />If not defined, the recently-used model or (if not available) a model from the local storage will be used. If none of the above is available - the first model from the AI DIAL Core config will be used as a pre-selected conversation model. | Any string | First available model from [AI DIAL Core](https://github.com/epam/ai-dial-core?tab=readme-ov-file#dynamic-settings) config listing |
| `DEFAULT_MODEL` | No | A model that will be used for the new conversation if the recently-used models or recently-used models from local storage are not available. If none of the above is available - the first model from the AI DIAL Core config will be used as a pre-selected conversation model. | Any string | First available model from [AI DIAL Core](https://github.com/epam/ai-dial-core?tab=readme-ov-file#dynamic-settings) config listing |
| `NEXT_PUBLIC_DEFAULT_ASSISTANT_SUB_MODEL` | No | A default pre-selected model for any assistant | Any string | `gpt-4` |
| `RECENT_MODELS_IDS` | No | A list of IDs for recently-used models | Any string | |
| `RECENT_ADDONS_IDS` | No | A list of IDs for recently-used addons | Any string | |
Expand Down
41 changes: 29 additions & 12 deletions apps/chat/src/store/conversations/conversations.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
addPausedError,
getConversationInfoFromId,
getConversationModelParams,
getDefaultModelReference,
getGeneratedConversationId,
getNewConversationName,
isChosenConversationValidForCompare,
Expand Down Expand Up @@ -143,18 +144,23 @@ const initSelectedConversationsEpic: AppEpic = (action$, state$) =>
// use getSelectedConversations to load selected conversations, we can unsubscribe from this action if we try to accept a share link
switchMap(() => {
const isOverlay = SettingsSelectors.selectIsOverlay(state$.value);
const optionsReceived = OverlaySelectors.selectOptionsReceived(
const isOverlayOptionsReceived = OverlaySelectors.selectOptionsReceived(
state$.value,
);
const isOverlayConversationId =
!!SettingsSelectors.selectOverlayConversationId(state$.value);

const previousRoute = UISelectors.selectPreviousRoute(state$.value);

return iif(
() => !isOverlay || !!optionsReceived,
() => !isOverlay || !!isOverlayOptionsReceived,
of(
ConversationsActions.getSelectedConversations({
createNew: !previousRoute?.includes(
`?${MarketplaceQueryParams.fromConversation}=`,
),
createNew:
!isOverlayConversationId &&
!previousRoute?.includes(
`?${MarketplaceQueryParams.fromConversation}=`,
),
}),
),
EMPTY,
Expand Down Expand Up @@ -434,15 +440,26 @@ const createNewConversationsEpic: AppEpic = (action$, state$) =>
ModelsSelectors.selectRecentWithInstalledModelsIds(state).filter(
(reference) => modelReferences.includes(reference),
);

const overlayDefaultModel =
SettingsSelectors.selectOverlayDefaultModelId(state);
const isOverlay = SettingsSelectors.selectIsOverlay(state);

if (isOverlay && overlayDefaultModel) {
return getDefaultModelReference({
recentModelReferences,
modelReferences,
defaultModelId: overlayDefaultModel,
});
}

if (lastConversation?.model.id) {
const lastModelId = lastConversation.model.id;
return [
...modelReferences.filter(
(reference) => reference === lastModelId,
),
...recentModelReferences,
...modelReferences,
][0];
return getDefaultModelReference({
recentModelReferences,
modelReferences,
defaultModelId: lastModelId,
});
}

return [...recentModelReferences, ...modelReferences][0];
Expand Down
10 changes: 9 additions & 1 deletion apps/chat/src/store/models/models.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,18 @@ const updateRecentModelsEpic: AppEpic = (action$, state$) =>
ignoreElements(),
);

const getModelsSuccessEpic: AppEpic = (action$) =>
const getModelsSuccessEpic: AppEpic = (action$, state$) =>
action$.pipe(
filter(ModelsActions.getModelsSuccess.match),
switchMap(({ payload }) => {
const isOverlay = SettingsSelectors.selectIsOverlay(state$.value);
const overlayDefaultModelId =
SettingsSelectors.selectOverlayDefaultModelId(state$.value);

if (isOverlay && overlayDefaultModelId) {
return EMPTY;
}

const defaultModelId = payload.models.find(
(model) => model.isDefault,
)?.id;
Expand Down
70 changes: 6 additions & 64 deletions apps/chat/src/store/overlay/overlay.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {

import { combineEpics } from 'redux-observable';

import { DefaultsService } from '@/src/utils/app/data/defaults-service';
import { constructPath } from '@/src/utils/app/file';
import { splitEntityId } from '@/src/utils/app/folders';
import { getConversationRootId } from '@/src/utils/app/id';
Expand All @@ -30,14 +29,9 @@ import {
sendPMResponse,
} from '@/src/utils/app/overlay';

import { EntityType } from '@/src/types/common';
import { DialAIEntityModel } from '@/src/types/models';
import { AppEpic } from '@/src/types/store';

import {
DEFAULT_CONVERSATION_NAME,
FALLBACK_ASSISTANT_SUBMODEL_ID,
} from '@/src/constants/default-ui-settings';
import { DEFAULT_CONVERSATION_NAME } from '@/src/constants/default-ui-settings';

import { AuthSelectors } from '../auth/auth.reducers';
import {
Expand Down Expand Up @@ -342,18 +336,15 @@ const setOverlayOptionsEpic: AppEpic = (action$, state$) =>
action$.pipe(
filter(OverlayActions.setOverlayOptions.match),
map(({ payload: { ...options } }) => {
const currentConversation =
ConversationsSelectors.selectFirstSelectedConversation(state$.value);
const availableThemes = UISelectors.selectAvailableThemes(state$.value);

return { ...options, currentConversation, availableThemes };
return { ...options, availableThemes };
}),
switchMap(
({
theme,
availableThemes,
hostDomain,
currentConversation,
modelId,
requestId,
enabledFeatures,
Expand Down Expand Up @@ -424,65 +415,16 @@ const setOverlayOptionsEpic: AppEpic = (action$, state$) =>
}
}

const defaultModelId = SettingsSelectors.selectDefaultModelId(
state$.value,
);
const finalModelId = modelId || defaultModelId;

if (finalModelId) {
actions.push(
of(ModelsActions.updateRecentModels({ modelId: finalModelId })),
);
if (modelId) {
actions.push(of(ModelsActions.updateRecentModels({ modelId })));

actions.push(
of(
SettingsActions.setDefaultModelId({
defaultModelId: finalModelId,
SettingsActions.setOverlayDefaultModelId({
overlayDefaultModelId: modelId,
}),
),
);

// if there is active conversation -> should update model for this conversation
if (currentConversation) {
const models = ModelsSelectors.selectModels(state$.value);

const newAiEntity = models.find(
({ reference, id }) =>
id === finalModelId || reference === finalModelId,
) as DialAIEntityModel | undefined;

actions.push(
of(
ConversationsActions.updateConversation({
id: currentConversation.id,
values: {
model: {
id: newAiEntity?.reference ?? finalModelId,
},
},
}),
),
);

if (newAiEntity) {
actions.push(
of(
ConversationsActions.updateConversation({
id: currentConversation.id,
values: {
assistantModelId:
newAiEntity.type === EntityType.Assistant
? DefaultsService.get(
'assistantSubmodelId',
FALLBACK_ASSISTANT_SUBMODEL_ID,
)
: undefined,
},
}),
),
);
}
}
}
if (overlayConversationId) {
actions.push(
Expand Down
12 changes: 12 additions & 0 deletions apps/chat/src/store/settings/settings.reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface SettingsState {
codeWarning: string;
announcement: string;
defaultModelId: string | undefined;
overlayDefaultModelId?: string | undefined;
defaultAssistantSubmodelId: string;
defaultRecentModelsIds: string[];
defaultRecentAddonsIds: string[];
Expand Down Expand Up @@ -112,6 +113,12 @@ export const settingsSlice = createSlice({
) => {
state.defaultModelId = payload.defaultModelId;
},
setOverlayDefaultModelId: (
state,
{ payload }: PayloadAction<{ overlayDefaultModelId: string | undefined }>,
) => {
state.overlayDefaultModelId = payload.overlayDefaultModelId;
},
setDefaultRecentModelsIds: (
state,
{ payload }: PayloadAction<{ defaultRecentModelsIds: string[] }>,
Expand Down Expand Up @@ -314,6 +321,10 @@ const selectCodeEditorPythonVersions = createSelector(
},
);

const selectOverlayDefaultModelId = createSelector([rootSelector], (state) => {
return state.overlayDefaultModelId;
});

export const SettingsActions = settingsSlice.actions;
export const SettingsSelectors = {
selectAppName,
Expand Down Expand Up @@ -343,4 +354,5 @@ export const SettingsSelectors = {
selectAllowVisualizerSendMessages,
selectTopics,
selectCodeEditorPythonVersions,
selectOverlayDefaultModelId,
};
16 changes: 16 additions & 0 deletions apps/chat/src/utils/app/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,19 @@ export const getConversationModelParams = (
selectedAddons: updatedAddons,
};
};

export const getDefaultModelReference = ({
recentModelReferences,
modelReferences,
defaultModelId,
}: {
recentModelReferences: string[];
modelReferences: string[];
defaultModelId: string;
}) => {
return [
...modelReferences.filter((reference) => reference === defaultModelId),
...recentModelReferences,
...modelReferences,
][0];
};
Loading