diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts
index 48eb5b8..e96a8ee 100644
--- a/frontend/src/constants/index.ts
+++ b/frontend/src/constants/index.ts
@@ -76,6 +76,29 @@ export const LR_SCHEDULER_OPTIONS = [
{ label: 'constant', value: 'constant' },
]
+/** 训练时量化位数(QLoRA) */
+export const QUANTIZATION_BIT_OPTIONS = [
+ { label: '不量化', value: 0 },
+ { label: '8 bit', value: 8 },
+ { label: '4 bit (QLoRA)', value: 4 },
+]
+
+/** 训练后导出量化方法 */
+export const QUANT_METHOD_OPTIONS = [
+ { label: 'bitsandbytes', value: 'bnb' },
+ { label: 'GPTQ', value: 'gptq' },
+ { label: 'AWQ', value: 'awq' },
+ { label: 'GGUF (llama.cpp)', value: 'gguf' },
+]
+
+/** GGUF 量化格式 */
+export const GGUF_FORMAT_OPTIONS = [
+ { label: 'Q4_K_M(推荐)', value: 'Q4_K_M' },
+ { label: 'Q5_K_M', value: 'Q5_K_M' },
+ { label: 'Q8_0', value: 'Q8_0' },
+ { label: 'F16(不量化)', value: 'F16' },
+]
+
/** 训练模板分组(按模型系列) */
export const TEMPLATE_GROUPS: { label: string; options: { label: string; value: string }[] }[] = [
{
diff --git a/frontend/src/views/fine-tune/FineTuneCreateView.vue b/frontend/src/views/fine-tune/FineTuneCreateView.vue
index b8cae4f..1462606 100644
--- a/frontend/src/views/fine-tune/FineTuneCreateView.vue
+++ b/frontend/src/views/fine-tune/FineTuneCreateView.vue
@@ -13,7 +13,7 @@ import {
import { getModelList } from '@/api/modules/model'
import { getDatasetList } from '@/api/modules/dataset'
import { getSystemInfo } from '@/api/modules/system'
-import { TEMPLATE_GROUPS, LR_SCHEDULER_OPTIONS } from '@/constants'
+import { TEMPLATE_GROUPS, LR_SCHEDULER_OPTIONS, QUANTIZATION_BIT_OPTIONS, QUANT_METHOD_OPTIONS, GGUF_FORMAT_OPTIONS } from '@/constants'
import type { ModelItem, DatasetItem, GpuInfo } from '@/types'
const router = useRouter()
@@ -48,6 +48,13 @@ const form = reactive({
lora_alpha: 16, // 修复原项目 lora_alpha 默认值不一致 bug
lora_dropout: 0.1,
lora_rank: 8,
+ // 量化参数
+ quantization_bit: 0, // 训练时量化(QLoRA):0=不量化
+ export_quantized: false, // 训练后是否导出量化模型
+ quant_method: 'bnb', // 导出量化方法
+ quant_bits: 4, // 导出量化位数
+ quant_group_size: 128, // 分组大小(GPTQ/AWQ)
+ export_format: 'Q4_K_M', // GGUF 导出格式
})
const rules: FormRules = {
@@ -95,6 +102,19 @@ const commandPreview = computed(() => {
cmd += ` \\\n --lora_dropout ${form.lora_dropout}`
cmd += ` \\\n --lora_rank ${form.lora_rank}`
}
+ if (showLoraParams.value && form.quantization_bit) {
+ cmd += ` \\\n --quantization_bit ${form.quantization_bit}`
+ }
+ if (form.export_quantized) {
+ const method = form.quant_method
+ const bits = form.quant_bits
+ cmd += ` \\\n # 训练后导出量化模型:${method} ${bits}bit`
+ if (method === 'gguf') {
+ cmd += ` \\\n # export_format=${form.export_format}`
+ } else if (method === 'gptq' || method === 'awq') {
+ cmd += ` \\\n # group_size=${form.quant_group_size}`
+ }
+ }
return cmd
})
@@ -132,6 +152,12 @@ function resetParams() {
lora_alpha: 16,
lora_dropout: 0.1,
lora_rank: 8,
+ quantization_bit: 0,
+ export_quantized: false,
+ quant_method: 'bnb',
+ quant_bits: 4,
+ quant_group_size: 128,
+ export_format: 'Q4_K_M',
})
}
@@ -230,6 +256,12 @@ async function handleSubmit() {
lora_alpha: form.lora_alpha,
lora_dropout: form.lora_dropout,
lora_rank: form.lora_rank,
+ quantization_bit: form.train_method === 'lora' ? form.quantization_bit : 0,
+ export_quantized: form.export_quantized,
+ quant_method: form.export_quantized ? form.quant_method : '',
+ quant_bits: form.export_quantized ? form.quant_bits : 0,
+ quant_group_size: form.export_quantized ? form.quant_group_size : 0,
+ export_format: form.export_quantized && form.quant_method === 'gguf' ? form.export_format : '',
status: 'pending',
progress: 0,
}
@@ -260,6 +292,12 @@ async function handleSubmit() {
lora_alpha: form.lora_alpha,
lora_dropout: form.lora_dropout,
lora_rank: form.lora_rank,
+ quantization_bit: form.train_method === 'lora' ? form.quantization_bit : 0,
+ export_quantized: form.export_quantized,
+ quant_method: form.export_quantized ? form.quant_method : '',
+ quant_bits: form.export_quantized ? form.quant_bits : 0,
+ quant_group_size: form.export_quantized ? form.quant_group_size : 0,
+ export_format: form.export_quantized && form.quant_method === 'gguf' ? form.export_format : '',
})
ElMessage.success('训练任务已创建并启动')
} catch (e) {
@@ -437,6 +475,74 @@ onMounted(() => {
+
+