Skip to content

Commit 3ebe1b8

Browse files
committed
feat: Enhance AI completion capabilities with new model support and improved context handling
1 parent 1bfa61d commit 3ebe1b8

14 files changed

Lines changed: 683 additions & 425 deletions

File tree

packages/plugins/robot/src/components/header-extension/robot-setting/RobotSetting.vue

Lines changed: 83 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
快速模型
4343
<tiny-tooltip
4444
effect="light"
45-
content="用于代码补全、话题命名等快速响应场景。推荐选择带「代码」标签的模型以获得更好的代码补全效果"
45+
content="用于代码补全、话题命名等场景。建议选择轻量模型以实现更快的响应速度,例如flash类型或8b/14b模型"
4646
placement="top"
4747
>
4848
<svg-icon class="help-link" name="plugin-icon-plugin-help"></svg-icon>
@@ -51,25 +51,11 @@
5151
<tiny-select
5252
clearable
5353
v-model="state.modelSelection.quickModel"
54+
:options="compactModelOptions"
5455
filterable
5556
placeholder="请选择"
5657
@change="handleCompactModelChange"
57-
popper-class="model-select-popper"
58-
>
59-
<template v-for="item in compactModelOptions" :key="item.value">
60-
<tiny-option :label="item.label" :value="item.value">
61-
<span class="left">{{ item.label }}</span>
62-
<div>
63-
<tiny-tag v-if="item.capabilities?.codeCompletion" type="success" effect="light" size="small"
64-
>代码</tiny-tag
65-
>
66-
<tiny-tag v-if="item.capabilities?.compact" type="info" effect="light" size="small"
67-
>轻量</tiny-tag
68-
>
69-
</div>
70-
</tiny-option>
71-
</template>
72-
</tiny-select>
58+
></tiny-select>
7359
</tiny-form-item>
7460

7561
<div v-if="selectedDefaultModelInfo" class="model-info">
@@ -186,8 +172,8 @@ const emit = defineEmits(['close'])
186172
const {
187173
robotSettingState,
188174
saveRobotSettingState,
175+
getAllAvailableModels,
189176
getCompactModels,
190-
getNonCodeCompletionModels,
191177
addCustomService,
192178
updateService,
193179
deleteService,
@@ -200,6 +186,15 @@ const getModelValue = (serviceId: string, modelName: string) => {
200186
return serviceId && modelName ? `${serviceId}::${modelName}` : ''
201187
}
202188
189+
const parseModelValue = (value = '') => {
190+
const [serviceId = '', modelName = ''] = value.split('::')
191+
192+
return {
193+
serviceId,
194+
modelName
195+
}
196+
}
197+
203198
const state = reactive({
204199
activeTab: 'model-selection',
205200
modelSelection: {
@@ -210,9 +205,28 @@ const state = reactive({
210205
editingService: undefined as ModelService | undefined
211206
})
212207
213-
// 获取所有可用模型选项(排除代码补全专用模型)
208+
const syncModelSelection = () => {
209+
state.modelSelection.defaultModel = getModelValue(
210+
robotSettingState.defaultModel.serviceId,
211+
robotSettingState.defaultModel.modelName
212+
)
213+
state.modelSelection.quickModel = getModelValue(
214+
robotSettingState.quickModel.serviceId,
215+
robotSettingState.quickModel.modelName
216+
)
217+
}
218+
219+
const notifyMissingApiKey = (service: ModelService) => {
220+
useNotify({
221+
type: 'warning',
222+
title: '未配置API Key',
223+
message: `请先为 ${service.label} 配置API Key`
224+
})
225+
}
226+
227+
// 获取所有可用模型选项
214228
const allModelOptions = computed(() => {
215-
return getNonCodeCompletionModels().map((model) => ({
229+
return getAllAvailableModels().map((model) => ({
216230
label: model.displayLabel,
217231
value: model.value,
218232
capabilities: model.capabilities
@@ -221,14 +235,10 @@ const allModelOptions = computed(() => {
221235
222236
// 获取快速模型选项
223237
const compactModelOptions = computed(() => {
224-
const models = getCompactModels().map((model) => ({
238+
return getCompactModels().map((model) => ({
225239
label: model.displayLabel,
226-
value: model.value,
227-
capabilities: model.capabilities,
228-
serviceName: model.serviceName
240+
value: model.value
229241
}))
230-
231-
return models.sort((a, b) => a.serviceName.localeCompare(b.serviceName, 'zh-CN'))
232242
})
233243
234244
// 获取当前选择的默认模型信息
@@ -249,16 +259,15 @@ const handleBack = () => {
249259
}
250260
251261
const handleModelChange = () => {
252-
const [defaultServiceId, defaultModelName] = state.modelSelection.defaultModel.split('::')
262+
const { serviceId: defaultServiceId, modelName: defaultModelName } = parseModelValue(
263+
state.modelSelection.defaultModel
264+
)
253265
254266
// 检查API Key
255267
const defaultService = getServiceById(defaultServiceId)
256268
if (defaultService && !defaultService.apiKey && !defaultService.allowEmptyApiKey) {
257-
useNotify({
258-
type: 'warning',
259-
title: '未配置API Key',
260-
message: `请先为 ${defaultService.label} 配置API Key`
261-
})
269+
notifyMissingApiKey(defaultService)
270+
syncModelSelection()
262271
state.activeTab = 'services'
263272
return
264273
}
@@ -273,7 +282,16 @@ const handleModelChange = () => {
273282
}
274283
275284
const handleCompactModelChange = () => {
276-
const [quickServiceId = '', quickModelName = ''] = (state.modelSelection.quickModel || '').split('::')
285+
const { serviceId: quickServiceId, modelName: quickModelName } = parseModelValue(state.modelSelection.quickModel)
286+
const quickService = getServiceById(quickServiceId)
287+
288+
if (quickService && !quickService.apiKey && !quickService.allowEmptyApiKey) {
289+
notifyMissingApiKey(quickService)
290+
syncModelSelection()
291+
state.activeTab = 'services'
292+
return
293+
}
294+
277295
const updatedState = {
278296
quickModel: {
279297
serviceId: quickServiceId,
@@ -289,22 +307,50 @@ const addService = () => {
289307
}
290308
291309
const editService = (service: any) => {
292-
state.editingService = JSON.parse(JSON.stringify(service)) as ModelService
310+
state.editingService = JSON.parse(JSON.stringify(service))
293311
state.showServiceDialog = true
294312
}
295313
296314
const handleDeleteService = (serviceId: string) => {
297315
deleteService(serviceId)
316+
317+
const shouldResetDefaultModel = robotSettingState.defaultModel.serviceId === serviceId
318+
const shouldResetQuickModel = robotSettingState.quickModel.serviceId === serviceId
319+
320+
if (shouldResetDefaultModel || shouldResetQuickModel) {
321+
saveRobotSettingState({
322+
...(shouldResetDefaultModel
323+
? {
324+
defaultModel: {
325+
serviceId: '',
326+
modelName: ''
327+
}
328+
}
329+
: {}),
330+
...(shouldResetQuickModel
331+
? {
332+
quickModel: {
333+
serviceId: '',
334+
modelName: ''
335+
}
336+
}
337+
: {})
338+
})
339+
}
340+
341+
syncModelSelection()
298342
}
299343
300-
const handleServiceConfirm = (serviceData: Partial<ModelService>) => {
344+
const handleServiceConfirm = async (serviceData: Partial<ModelService>) => {
301345
if (serviceData.id) {
302346
// 更新现有服务
303-
updateService(serviceData.id, serviceData)
347+
await updateService(serviceData.id, serviceData)
304348
} else {
305349
// 添加新服务
306-
addCustomService(serviceData as any)
350+
await addCustomService(serviceData as any)
307351
}
352+
353+
syncModelSelection()
308354
}
309355
</script>
310356

packages/plugins/robot/src/composables/core/useConfig.ts

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ import { reactive, readonly } from 'vue'
1515
import { DEFAULT_LLM_MODELS } from '../../constants'
1616
import { getRobotServiceOptions } from '../../utils'
1717
import { ChatMode } from '../../types/mode.types'
18-
import type { ModelConfig, ModelService, RobotSettings, SelectedModelInfo } from '../../types/setting.types'
18+
import type {
19+
CompletionProtocol,
20+
ModelConfig,
21+
ModelService,
22+
RobotSettings,
23+
SelectedModelInfo
24+
} from '../../types/setting.types'
1925
import apiService from '../../services/api'
2026

2127
const SETTING_STORAGE_KEY = 'tiny-engine-robot-settings'
@@ -44,6 +50,48 @@ const getAIModelOptions = () => {
4450
return mergeAIModelOptions(DEFAULT_LLM_MODELS, customAIModels) // eslint-disable-line
4551
}
4652

53+
const inferCompletionProtocol = ({
54+
provider = '',
55+
baseUrl = '',
56+
modelName = '',
57+
capabilities = {}
58+
}: {
59+
provider?: string
60+
baseUrl?: string
61+
modelName?: string
62+
capabilities?: ModelConfig['capabilities']
63+
}): CompletionProtocol | null => {
64+
if (capabilities?.completionProtocol) {
65+
return capabilities.completionProtocol
66+
}
67+
68+
const normalizedProvider = provider.toLowerCase()
69+
if (normalizedProvider === 'bailian') {
70+
return 'qwen'
71+
}
72+
if (normalizedProvider === 'deepseek') {
73+
return 'deepseek'
74+
}
75+
76+
const normalizedBaseUrl = baseUrl.toLowerCase()
77+
if (normalizedBaseUrl.includes('dashscope.aliyuncs.com')) {
78+
return 'qwen'
79+
}
80+
if (normalizedBaseUrl.includes('deepseek.com')) {
81+
return 'deepseek'
82+
}
83+
84+
const normalizedModelName = modelName.toLowerCase()
85+
if (normalizedModelName.includes('qwen')) {
86+
return 'qwen'
87+
}
88+
if (normalizedModelName.includes('deepseek')) {
89+
return 'deepseek'
90+
}
91+
92+
return null
93+
}
94+
4795
// 初始化内置服务
4896
const initBuiltInServices = (): ModelService[] => {
4997
return getAIModelOptions().map((service: any) => ({
@@ -120,7 +168,9 @@ const migrateOldSettings = (oldSettings: any): RobotSettings | null => {
120168
customService.models.push({
121169
name: customizeModel.completeModel,
122170
label: customizeModel.completeModel,
123-
capabilities: { compact: true }
171+
capabilities: {
172+
compact: true
173+
}
124174
})
125175
}
126176
services.push(customService)
@@ -318,19 +368,9 @@ const getAllAvailableModels = () => {
318368
)
319369
}
320370

321-
// 获取快速模型列表(包含 compact 或 codeCompletion 的模型)
371+
// 获取快速模型列表
322372
const getCompactModels = () => {
323-
return getAllAvailableModels().filter((model) => model.capabilities?.compact || model.capabilities?.codeCompletion)
324-
}
325-
326-
// 获取代码补全优化模型列表
327-
const getCodeCompletionModels = () => {
328-
return getAllAvailableModels().filter((model) => model.capabilities?.codeCompletion)
329-
}
330-
331-
// 获取非代码补全模型列表(用于默认助手模型)
332-
const getNonCodeCompletionModels = () => {
333-
return getAllAvailableModels().filter((model) => !model.capabilities?.codeCompletion)
373+
return getAllAvailableModels().filter((model) => model.capabilities?.compact)
334374
}
335375

336376
const updateThinkingState = (value: boolean) => {
@@ -430,6 +470,13 @@ const getSelectedQuickModelInfo = (): SelectedModelInfo => {
430470
(m) => m.name === robotSettingState.quickModel.modelName
431471
)
432472
const { name = '', label = '', capabilities = {} } = currentModel || {}
473+
const completionProtocol =
474+
inferCompletionProtocol({
475+
provider: currentService?.provider,
476+
baseUrl: currentService?.baseUrl,
477+
modelName: name,
478+
capabilities
479+
}) || null
433480

434481
const { models, ...service } = currentService ?? ({} as Partial<ModelService>)
435482

@@ -444,6 +491,7 @@ const getSelectedQuickModelInfo = (): SelectedModelInfo => {
444491
// 模型兼容字段
445492
model: robotSettingState.quickModel.modelName,
446493
completeModel: robotSettingState.quickModel.modelName || '',
494+
completionProtocol,
447495
// 服务兼容字段
448496
baseUrl: currentService?.baseUrl || '',
449497
apiKey: currentService?.apiKey || ''
@@ -466,8 +514,6 @@ export default () => {
466514
getModelCapabilities,
467515
getAllAvailableModels,
468516
getCompactModels,
469-
getCodeCompletionModels, // 代码补全模型列表
470-
getNonCodeCompletionModels, // 非代码补全模型列表
471517
getSelectedModelInfo, // 对话模型信息
472518
getSelectedQuickModelInfo, // 快速模型信息
473519

packages/plugins/robot/src/constants/model-config.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ export const DEFAULT_LLM_MODELS = [
5757
name: 'qwen3-coder-plus',
5858
capabilities: {
5959
toolCalling: true,
60-
codeCompletion: true,
6160
reasoning: reasoningExtraBody,
6261
jsonOutput: bailianJsonOutputExtraBody
6362
}
@@ -82,24 +81,23 @@ export const DEFAULT_LLM_MODELS = [
8281
}
8382
},
8483
{
85-
label: 'Qwen2.5 Coder编程模型-最快响应',
86-
name: 'qwen-coder-turbo-latest',
84+
label: 'Qwen Coder编程模型(Flash)',
85+
name: 'qwen3-coder-flash',
8786
capabilities: {
8887
toolCalling: true,
8988
compact: true,
90-
codeCompletion: true,
9189
jsonOutput: bailianJsonOutputExtraBody
9290
}
9391
},
9492
{
95-
label: 'Qwen2.5 Coder编程模型(32B)',
96-
name: 'qwen2.5-coder-32b-instruct',
97-
capabilities: {
98-
toolCalling: true,
99-
compact: true,
100-
codeCompletion: true,
101-
jsonOutput: bailianJsonOutputExtraBody
102-
}
93+
label: 'Qwen3(14b)',
94+
name: 'qwen3-14b',
95+
capabilities: { compact: true, toolCalling: true, jsonOutput: bailianJsonOutputExtraBody }
96+
},
97+
{
98+
label: 'Qwen3(8b)',
99+
name: 'qwen3-8b',
100+
capabilities: { compact: true, toolCalling: true, jsonOutput: bailianJsonOutputExtraBody }
103101
}
104102
]
105103
},
@@ -122,16 +120,6 @@ export const DEFAULT_LLM_MODELS = [
122120
},
123121
jsonOutput: jsonOutputExtraBody
124122
}
125-
},
126-
{
127-
label: 'Deepseek Coder编程模型',
128-
name: 'deepseek-coder',
129-
capabilities: {
130-
toolCalling: true,
131-
compact: true,
132-
codeCompletion: true,
133-
jsonOutput: jsonOutputExtraBody
134-
}
135123
}
136124
]
137125
}

0 commit comments

Comments
 (0)