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

feat(desktop): moonshot llm api support on copilot #1707

Merged
merged 2 commits into from
Jun 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 111 additions & 34 deletions src/views/settings/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -293,29 +293,30 @@
<el-divider></el-divider>

<el-row class="settings-item" type="flex" justify="space-between" align="middle">
<el-col :span="20">
<label>OpenAI API Host</label>
<el-col :span="18">
<label>API Host</label>
</el-col>
<el-col :span="4">
<el-input
<el-col :span="6">
<el-autocomplete
size="mini"
v-model.trim="aiConfig.openAIAPIHost"
placeholder="https://api.openai.com/v1"
type="text"
clearable
v-model.trim="aiConfig.openAIAPIHost"
:fetch-suggestions="queryAIAPIHost"
:disabled="!enableCopilot"
@clear="handleAIConfigChanged('host')"
@blur="handleAIConfigChanged('host')"
></el-input>
placeholder="https://api.openai.com/v1"
@select="handleAIConfigHostSelected"
@change="handleAIConfigChanged('host')"
></el-autocomplete>
</el-col>
</el-row>
<el-divider></el-divider>

<el-row class="settings-item" type="flex" justify="space-between" align="middle">
<el-col :span="20">
<label>OpenAI API Key</label>
<el-col :span="18">
<label>API Key</label>
</el-col>
<el-col :span="4">
<el-col :span="6">
<el-input
size="mini"
v-model.trim="aiConfig.openAIAPIKey"
Expand All @@ -331,21 +332,32 @@
<el-divider></el-divider>

<el-row class="settings-item" type="flex" justify="space-between" align="middle">
<el-col :span="20">
<el-col :span="18">
<label>{{ $t('settings.model') }}</label>
</el-col>
<el-col :span="4">
<el-autocomplete
<el-col :span="6" v-click-outside="handleClickPresetOutside">
<transition name="el-zoom-in-bottom">
<el-cascader-panel
v-if="showAIModelsSelect"
class="ai-models-select"
:options="AImodelsOptions"
:props="{ emitPath: false, label: 'value' }"
:value="aiConfig.model"
@change="handleAIConfigModelSelected"
></el-cascader-panel>
</transition>
<el-input
size="mini"
v-model.trim="aiConfig.model"
placeholder="gpt-3.5-turbo"
type="text"
clearable
v-model.trim="aiConfig.model"
:fetch-suggestions="queryAImodels"
:disabled="!enableCopilot"
placeholder="gpt-3.5-turbo"
@select="handleAIConfigModelSelected"
@change="handleAIConfigChanged('model')"
></el-autocomplete>
@clear="handleAIConfigChanged('model')"
@blur="handleAIConfigChanged('model')"
@focus="showAIModelsSelect = true"
@input="showAIModelsSelect = false"
></el-input>
</el-col>
</el-row>
<el-divider></el-divider>
Expand All @@ -362,9 +374,13 @@ import ExportData from '@/components/ExportData.vue'
import ClearUpHistoryData from '@/components/ClearUpHistoryData.vue'
import CryptoJS from 'crypto-js'
import { ENCRYPT_KEY } from '@/utils/idGenerator'
import ClickOutside from 'vue-click-outside'

@Component({
components: { ImportData, ExportData, ClearUpHistoryData },
directives: {
ClickOutside,
},
})
export default class Settings extends Vue {
@Action('TOGGLE_THEME') private actionTheme!: (payload: { currentTheme: string }) => void
Expand Down Expand Up @@ -394,6 +410,9 @@ export default class Settings extends Vue {
@Getter('openAIAPIKey') private openAIAPIKey!: string
@Getter('model') private model!: AIModel
@Getter('logLevel') private logLevel!: LogLevel

private showAIModelsSelect = false

private langOptions: Options[] = [
{ label: '简体中文', value: 'zh' },
{ label: 'English', value: 'en' },
Expand All @@ -407,16 +426,33 @@ export default class Settings extends Vue {
{ label: 'Night', value: 'night' },
]
private AImodelsOptions = [
{ value: 'gpt-3.5-turbo' },
{ value: 'gpt-3.5-turbo-0125' },
{ value: 'gpt-3.5-turbo-1106' },
{ value: 'gpt-3.5-turbo-16k' },
{ value: 'gpt-4' },
{ value: 'gpt-4-32k' },
{ value: 'gpt-4-0613' },
{ value: 'gpt-4-32k-0613' },
{ value: 'gpt-4-turbo' },
{ value: 'gpt-4o' },
{
value: 'OpenAI',
children: [
{ value: 'gpt-3.5-turbo' },
{ value: 'gpt-3.5-turbo-0125' },
{ value: 'gpt-3.5-turbo-1106' },
{ value: 'gpt-3.5-turbo-16k' },
{ value: 'gpt-4' },
{ value: 'gpt-4-32k' },
{ value: 'gpt-4-0613' },
{ value: 'gpt-4-32k-0613' },
{ value: 'gpt-4-turbo' },
{ value: 'gpt-4o' },
],
},
{
value: 'Moonshot',
children: [{ value: 'moonshot-v1-8k' }, { value: 'moonshot-v1-32k' }, { value: 'moonshot-v1-128k' }],
},
]
private AIAPIHostOptions = [
{
value: 'https://api.openai.com/v1',
},
{
value: 'https://api.moonshot.cn/v1',
},
]
private showImportData = false
private showExportData = false
Expand Down Expand Up @@ -503,13 +539,15 @@ export default class Settings extends Vue {
}
}

private handleAIConfigModelSelected({ value }: { value: string }) {
private handleAIConfigModelSelected(value: AIModel) {
this.aiConfig.model = value
this.actionSetModel({ model: value })
this.showAIModelsSelect = false
}

private queryAImodels(queryString: AIModel, cb: (r: any[]) => {}) {
cb(queryString ? this.AImodelsOptions.filter((item) => item.value.includes(queryString)) : this.AImodelsOptions)
private handleAIConfigHostSelected({ value }: { value: string }) {
this.aiConfig.openAIAPIHost = value
this.actionSetOpenAIAPIHost({ openAIAPIHost: value })
}

private getAIConfigs() {
Expand All @@ -526,6 +564,14 @@ export default class Settings extends Vue {
})
}

private handleClickPresetOutside() {
this.showAIModelsSelect = false
}

private queryAIAPIHost(queryString: string, cb: (r: any[]) => {}) {
cb(queryString ? this.AIAPIHostOptions.filter((item) => item.value.includes(queryString)) : this.AIAPIHostOptions)
}

private created() {
this.getAIConfigs()
}
Expand Down Expand Up @@ -616,5 +662,36 @@ export default class Settings extends Vue {
left: 5px;
color: var(--color-text-default);
}
.ai-models-select {
position: absolute;
bottom: 36px;
right: 0px;
box-shadow: #00000014 0px 4px 12px;
background: var(--color-bg-normal);
border: 1px solid var(--color-border-default);
.el-cascader-menu:last-child {
width: 100%;
}
.el-cascader-menu,
i {
color: var(--color-text-default);
}
.el-cascader-menu {
border-right: 1px solid var(--color-border-default);
&:last-child {
border-right: none;
}
}
.el-cascader-node.is-active {
.el-icon-check.el-cascader-node__prefix {
color: var(--color-main-green);
}
}
.el-cascader-node:not(.is-disabled):hover,
.el-cascader-node:not(.is-disabled):focus {
background-color: transparent;
color: var(--color-main-green);
}
}
}
</style>