Skip to content
代码片段 群组 项目
未验证 提交 e43fd749 编辑于 作者: Manoj M J's avatar Manoj M J 提交者: GitLab
浏览文件

Add dynamic model identifier

上级 4a34a4f9
No related branches found
No related tags found
无相关合并请求
......@@ -15,7 +15,12 @@ import { visitUrlWithAlerts } from '~/lib/utils/url_utility';
import { s__, __, sprintf } from '~/locale';
import { createAlert } from '~/alert';
import InputCopyToggleVisibility from '~/vue_shared/components/input_copy_toggle_visibility/input_copy_toggle_visibility.vue';
import { SELF_HOSTED_MODEL_PLATFORMS, BEDROCK_DUMMY_ENDPOINT, RELEASE_STATES } from '../constants';
import {
SELF_HOSTED_MODEL_PLATFORMS,
BEDROCK_DUMMY_ENDPOINT,
RELEASE_STATES,
CLOUD_PROVIDER_MODELS,
} from '../constants';
import ModelSelectDropdown from '../../duo_self_hosted/shared/model_select_dropdown.vue';
import TestConnectionButton from './test_connection_button.vue';
......@@ -84,9 +89,6 @@ const bedrockFormFields = {
groupAttrs: {
class: baseFormFieldClasses,
},
inputAttrs: {
placeholder: bedrockIdentifierPrefix,
},
},
};
......@@ -214,11 +216,16 @@ export default {
},
formFields() {
const platformFields = this.isApiPlatform ? apiFormFields : bedrockFormFields;
return {
const fields = {
...baseFormFields,
...platformFields,
};
fields.identifier.inputAttrs = {
placeholder: this.identifierPlaceholder,
};
return fields;
},
hasValidInput() {
const { name, model, endpoint, identifier } = this.baseFormValues;
......@@ -264,6 +271,29 @@ export default {
...this.baseFormValues,
};
},
identifierPlaceholder() {
if (this.platform === SELF_HOSTED_MODEL_PLATFORMS.BEDROCK) {
return 'bedrock/';
}
const model = this.selectedModel?.modelValue;
if (model && !Object.values(CLOUD_PROVIDER_MODELS).includes(model)) {
return 'custom_openai/';
}
return '';
},
identifierLabelDescription() {
let identifierLabel = 'provider/model-name';
if (this.identifierPlaceholder.length > 0) {
identifierLabel = `${this.identifierPlaceholder}model-name`;
}
return sprintf(
s__('AdminSelfHostedModels|Provide the model identifier in the form of %{identifierLabel}'),
{ identifierLabel },
);
},
},
methods: {
async onSubmit() {
......@@ -428,11 +458,7 @@ export default {
</template>
<template #group(identifier)-label-description>
{{
s__(
'AdminSelfHostedModels|Provide the model identifier in the form of provider/model-name',
)
}}
{{ identifierLabelDescription }}
</template>
</gl-form-fields>
<div :class="[...$options.baseFormFieldClasses, 'gl-pb-6']">
......
......@@ -15,3 +15,11 @@ export const RELEASE_STATES = {
GA: 'GA',
BETA: 'BETA',
};
// These are model identifiers that should not be translated as they are proper names
/* eslint-disable @gitlab/require-i18n-strings */
export const CLOUD_PROVIDER_MODELS = {
GPT: 'GPT',
CLAUDE_3: 'CLAUDE_3',
};
/* eslint-enable @gitlab/require-i18n-strings */
......@@ -88,4 +88,6 @@ export const SELF_HOSTED_MODEL_OPTIONS = [
{ modelValue: 'MISTRAL', modelName: 'Mistral', releaseState: 'GA' },
{ modelValue: 'DEEPSEEKCODER', modelName: 'Deepseek Coder', releaseState: 'BETA' },
{ modelValue: 'LLAMA3', modelName: 'Llama 3', releaseState: 'BETA' },
{ modelValue: 'GPT', modelName: 'GPT', releaseState: 'GA' },
{ modelValue: 'CLAUDE_3', modelName: 'Claude 3', releaseState: 'GA' },
];
......@@ -95,6 +95,9 @@ describe('SelfHostedModelForm', () => {
const findTestConnectionButton = () => wrapper.findComponent(TestConnectionButton);
const findBetaAlert = () => wrapper.findComponent(GlAlert);
const findDuoConfigurationLink = () => wrapper.findByTestId('duo-configuration-link');
const findIdentifierInput = () => wrapper.findByLabelText('Model identifier', { exact: false });
const findIdentifierLabelDescription = () =>
wrapper.findByText(/Provide the model identifier/, { exact: false });
// Find validation messages
const findNameValidationMessage = () => wrapper.findByText('Please enter a deployment name.');
......@@ -150,6 +153,8 @@ describe('SelfHostedModelForm', () => {
expect(modelOptions.map(({ text, releaseState }) => [text, releaseState])).toEqual([
['Codestral', 'GA'],
['Mistral', 'GA'],
['GPT', 'GA'],
['Claude 3', 'GA'],
['CodeGemma', 'BETA'],
['Code-Llama', 'BETA'],
['Deepseek Coder', 'BETA'],
......@@ -167,6 +172,42 @@ describe('SelfHostedModelForm', () => {
it('renders the optional API token input field', () => {
expect(findApiKeyInputField().exists()).toBe(true);
});
describe('identifier placeholder', () => {
it('shows custom_openai/ placeholder for non-cloud provider models', async () => {
await findModelDropDownSelector().vm.$emit('select', 'MISTRAL');
expect(findIdentifierInput().attributes('placeholder')).toBe('custom_openai/');
});
it('shows no placeholder for cloud provider models', async () => {
await findModelDropDownSelector().vm.$emit('select', 'GPT');
expect(findIdentifierInput().attributes('placeholder')).toBe('');
await findModelDropDownSelector().vm.$emit('select', 'CLAUDE_3');
expect(findIdentifierInput().attributes('placeholder')).toBe('');
});
});
describe('identifier label description', () => {
it('shows custom_openai/ format for non-cloud provider models', async () => {
await findModelDropDownSelector().vm.$emit('select', 'MISTRAL');
expect(findIdentifierLabelDescription().text()).toContain('custom_openai/model-name');
});
it('shows provider/ format for cloud provider models', async () => {
await findModelDropDownSelector().vm.$emit('select', 'GPT');
expect(findIdentifierLabelDescription().text()).toContain('provider/model-name');
await findModelDropDownSelector().vm.$emit('select', 'CLAUDE_3');
expect(findIdentifierLabelDescription().text()).toContain('provider/model-name');
});
});
});
describe('Bedrock platform', () => {
......@@ -187,6 +228,26 @@ describe('SelfHostedModelForm', () => {
'To fully set up AWS credentials for this model please refer to the AWS Bedrock Configuration Guide',
);
});
describe('identifier placeholder', () => {
it('always shows bedrock/ placeholder regardless of model', async () => {
await findModelDropDownSelector().vm.$emit('select', 'MISTRAL');
expect(findIdentifierInput().attributes('placeholder')).toBe('bedrock/');
await findModelDropDownSelector().vm.$emit('select', 'GPT');
expect(findIdentifierInput().attributes('placeholder')).toBe('bedrock/');
});
});
describe('identifier label description', () => {
it('shows bedrock/ format regardless of model', async () => {
await findModelDropDownSelector().vm.$emit('select', 'MISTRAL');
expect(findIdentifierLabelDescription().text()).toContain('bedrock/model-name');
await findModelDropDownSelector().vm.$emit('select', 'GPT');
expect(findIdentifierLabelDescription().text()).toContain('bedrock/model-name');
});
});
});
});
......
......@@ -4167,7 +4167,7 @@ msgstr ""
msgid "AdminSelfHostedModels|Please select a model."
msgstr ""
 
msgid "AdminSelfHostedModels|Provide the model identifier in the form of provider/model-name"
msgid "AdminSelfHostedModels|Provide the model identifier in the form of %{identifierLabel}"
msgstr ""
 
msgid "AdminSelfHostedModels|Select an appropriate model family from the list of approved GitLab models."
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册