Skip to content

Commit e4a5b15

Browse files
hotfix: patch in rls-0.4 (#142)
1 parent 4dfd433 commit e4a5b15

File tree

5 files changed

+160
-49
lines changed

5 files changed

+160
-49
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
'use client';
2+
3+
import classNames from 'classnames';
4+
import { FC } from 'react';
5+
6+
import Input, { InputProps } from './Input';
7+
import Field from '@/src/components/Common/Field/Field';
8+
import { IconCopy } from '@tabler/icons-react';
9+
import Button from '@/src/components/Common/Button/Button';
10+
import { ButtonsI18nKey } from '@/src/constants/i18n';
11+
import { useI18n } from '@/src/locales/client';
12+
13+
interface Props extends InputProps {
14+
title: string;
15+
fullValue?: string;
16+
prefixPart?: string;
17+
postfixPart?: string;
18+
}
19+
20+
const InputWithReadonlyParts: FC<Props> = ({ prefixPart, fullValue, postfixPart, cssClass, title, ...props }) => {
21+
const t = useI18n();
22+
23+
return (
24+
<div className="flex flex-col">
25+
<Field fieldTitle={title} htmlFor={props.inputId} />
26+
<div className="flex flex-row ">
27+
<div
28+
className={classNames(
29+
'input-field flex flex-row items-center p-0 input max-w-full',
30+
postfixPart ? 'pr-2' : '',
31+
)}
32+
>
33+
<Input
34+
cssClass={classNames('border-0 border-r rounded-none h-full')}
35+
value={prefixPart}
36+
disabled={true}
37+
inputId={prefixPart + 'prefix'}
38+
/>
39+
<Input cssClass={classNames('border-0 bg-transparent', cssClass)} {...props} />
40+
<p className="text-secondary small"> {postfixPart}</p>
41+
</div>
42+
<Button
43+
cssClass="secondary ml-2 h-[34px]"
44+
iconBefore={<IconCopy />}
45+
title={t(ButtonsI18nKey.Copy)}
46+
onClick={() => navigator.clipboard.writeText(fullValue || '')}
47+
/>
48+
</div>
49+
</div>
50+
);
51+
};
52+
export default InputWithReadonlyParts;

apps/ai-dial-admin/src/components/ModelView/ModelProperties/ModelProperties.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,20 @@ const ModelProperties: FC<Props> = ({ model, modelsNames, updateModel }) => {
2727

2828
return (
2929
<div className="h-full flex flex-col pt-3 divide-y divide-primary">
30-
<div className="flex flex-col gap-6 lg:w-[35%]">
31-
<EntityMainProperties
32-
view={ApplicationRoute.Models}
33-
entity={model}
34-
onChangeEntity={updateModel}
35-
names={modelsNames}
36-
isEntityImmutable={true}
37-
/>
38-
<ModelTypeProperties model={model} onChangeModel={updateModel} />
30+
<div className="flex flex-col gap-6">
31+
<div className="lg:w-[35%]">
32+
<EntityMainProperties
33+
view={ApplicationRoute.Models}
34+
entity={model}
35+
onChangeEntity={updateModel}
36+
names={modelsNames}
37+
isEntityImmutable={true}
38+
/>
39+
</div>
40+
41+
<div className="lg:w-[75%]">
42+
<ModelTypeProperties model={model} onChangeModel={updateModel} />
43+
</div>
3944
</div>
4045

4146
<div className="flex flex-col gap-6 mt-4 pt-4">

apps/ai-dial-admin/src/components/ModelView/ModelProperties/ModelTypeProperties.tsx

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
'use client';
22

3-
import { FC, useCallback } from 'react';
3+
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
44

55
import { getModelsTopics } from '@/src/app/[lang]/models/actions';
66
import { TextInputField } from '@/src/components/Common/InputField/InputField';
77
import Multiselect from '@/src/components/Common/Multiselect/Multiselect';
88
import RadioField from '@/src/components/Common/RadioField/RadioField';
9-
import ReadonlyField from '@/src/components/Common/ReadonlyField/ReadonlyField';
109
import EntityAttachments from '@/src/components/EntityView/Properties/EntityAttachments';
1110
import EntityIcon from '@/src/components/EntityView/Properties/EntityIcon';
1211
import { EntitiesI18nKey, ModelViewI18nKey, TopicsI18nKey } from '@/src/constants/i18n';
1312
import { RadioFieldOrientation } from '@/src/types/radio-orientation';
13+
import { getModelsAdapters } from '@/src/app/[lang]/models/actions';
1414
import { useI18n } from '@/src/locales/client';
1515
import { DialModel, DialModelType } from '@/src/models/dial/model';
1616
import { RadioButtonModel } from '@/src/models/radio-button';
17+
import InputWithReadonlyParts from '@/src/components/Common/Input/InputWithReadonlyParts';
18+
import { splitEndpoint } from '@/src/components/ModelView/ModelProperties/utils';
19+
import { DialAdapter } from '@/src/models/dial/adapter';
20+
import { useNotification } from '@/src/context/NotificationContext';
21+
import { getErrorNotification } from '@/src/utils/notification';
1722

1823
interface Props {
1924
model: DialModel;
@@ -22,12 +27,30 @@ interface Props {
2227

2328
const ModelTypeProperties: FC<Props> = ({ model, onChangeModel }) => {
2429
const t = useI18n();
30+
const { showNotification } = useNotification();
31+
const showNotificationRef = useRef(showNotification);
32+
33+
const [adapters, setAdapters] = useState<DialAdapter[]>([]);
34+
35+
const [prefixPart, postfixPart] = useMemo(() => {
36+
return splitEndpoint(model, adapters);
37+
}, [model, adapters]);
2538

2639
const modelTypeRadio: RadioButtonModel[] = [
2740
{ id: DialModelType.Chat, name: t(ModelViewI18nKey.Chat) },
2841
{ id: DialModelType.Embedding, name: t(ModelViewI18nKey.Embedding) },
2942
];
3043

44+
useEffect(() => {
45+
getModelsAdapters().then((res) => {
46+
if (res.success) {
47+
setAdapters((res.response as DialAdapter[]) || []);
48+
} else {
49+
showNotificationRef.current(getErrorNotification(res.errorHeader, res.errorMessage));
50+
}
51+
});
52+
}, [setAdapters]);
53+
3154
const onChangeType = useCallback(
3255
(type: string) => {
3356
onChangeModel({ ...model, type: type as DialModelType });
@@ -49,47 +72,67 @@ const ModelTypeProperties: FC<Props> = ({ model, onChangeModel }) => {
4972
[model, onChangeModel],
5073
);
5174

75+
const onChangeEndpoint = useCallback(
76+
(value: string) => {
77+
onChangeModel({ ...model, endpointDeploymentName: value });
78+
},
79+
[model, onChangeModel],
80+
);
81+
5282
return (
5383
<div className="w-full flex flex-col gap-5">
54-
<RadioField
55-
radioButtons={modelTypeRadio}
56-
activeRadioButton={model.type as string}
57-
elementId="type"
58-
fieldTitle={t(ModelViewI18nKey.Type)}
59-
orientation={RadioFieldOrientation.Row}
60-
onChange={onChangeType}
61-
/>
62-
<ReadonlyField value={model.endpoint} title={t(EntitiesI18nKey.Endpoint)} />
63-
<TextInputField
64-
elementId="overrideName"
65-
fieldTitle={t(ModelViewI18nKey.OverrideName)}
66-
placeholder={t(ModelViewI18nKey.OverrideNamePlaceholder)}
67-
value={model.overrideName}
68-
onChange={onChangeOverrideName}
69-
optional={true}
84+
<div className="w-full lg:w-[35%]">
85+
<RadioField
86+
radioButtons={modelTypeRadio}
87+
activeRadioButton={model.type as string}
88+
elementId="type"
89+
fieldTitle={t(ModelViewI18nKey.Type)}
90+
orientation={RadioFieldOrientation.Row}
91+
onChange={onChangeType}
92+
/>
93+
</div>
94+
95+
<InputWithReadonlyParts
96+
inputId="endpoint"
97+
value={model.endpointDeploymentName}
98+
fullValue={model.endpoint}
99+
title={t(EntitiesI18nKey.Endpoint)}
100+
postfixPart={postfixPart}
101+
prefixPart={prefixPart}
102+
onChange={onChangeEndpoint}
70103
/>
71-
{model.type === DialModelType.Chat && (
72-
<>
73-
<EntityIcon
74-
fieldTitle={t(EntitiesI18nKey.Icon)}
75-
elementId="icon"
76-
entity={model}
77-
onChangeEntity={onChangeModel}
78-
/>
79-
<Multiselect
80-
elementId="topics"
81-
selectedItems={model.topics}
82-
getItems={getModelsTopics}
83-
allItems={model.topics}
84-
onChangeItems={onChangeItems}
85-
heading={t(TopicsI18nKey.Topics)}
86-
title={t(TopicsI18nKey.Topics)}
87-
addPlaceholder={t(TopicsI18nKey.AddTopicPlaceholder)}
88-
addTitle={t(TopicsI18nKey.AddTopic)}
89-
/>
90-
<EntityAttachments entity={model} onChangeEntity={onChangeModel} />
91-
</>
92-
)}
104+
<div className="w-full flex flex-col gap-5 lg:w-[35%]">
105+
<TextInputField
106+
elementId="overrideName"
107+
fieldTitle={t(ModelViewI18nKey.OverrideName)}
108+
placeholder={t(ModelViewI18nKey.OverrideNamePlaceholder)}
109+
value={model.overrideName}
110+
onChange={onChangeOverrideName}
111+
optional={true}
112+
/>
113+
{model.type === DialModelType.Chat && (
114+
<>
115+
<EntityIcon
116+
fieldTitle={t(EntitiesI18nKey.Icon)}
117+
elementId="icon"
118+
entity={model}
119+
onChangeEntity={onChangeModel}
120+
/>
121+
<Multiselect
122+
elementId="topics"
123+
selectedItems={model.topics}
124+
getItems={getModelsTopics}
125+
allItems={model.topics}
126+
onChangeItems={onChangeItems}
127+
heading={t(TopicsI18nKey.Topics)}
128+
title={t(TopicsI18nKey.Topics)}
129+
addPlaceholder={t(TopicsI18nKey.AddTopicPlaceholder)}
130+
addTitle={t(TopicsI18nKey.AddTopic)}
131+
/>
132+
<EntityAttachments entity={model} onChangeEntity={onChangeModel} />
133+
</>
134+
)}
135+
</div>
93136
</div>
94137
);
95138
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { DialModel, DialModelType } from '@/src/models/dial/model';
2+
import { DialAdapter } from '@/src/models/dial/adapter';
3+
4+
export const splitEndpoint = (model: DialModel, adapters: DialAdapter[]): [string, string] => {
5+
const postfix = model.type === DialModelType.Chat ? '/chat/completions' : '/embeddings';
6+
const endpoint = model.endpoint?.split(postfix)[0];
7+
const adapter = adapters.find((a) => endpoint?.startsWith(a.baseEndpoint || ''));
8+
9+
return [adapter?.baseEndpoint || '', postfix];
10+
};

apps/ai-dial-admin/src/models/dial/model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { DialBaseEntity } from './base-entity';
22

33
export interface DialModel extends DialBaseEntity {
44
type?: DialModelType;
5+
endpointDeploymentName?: string;
56
upstreams?: DialModelEndpoint[];
67
tokenizerModel?: string;
78
overrideName?: string;

0 commit comments

Comments
 (0)