dev #1

Merged
caoxiaozhu merged 8 commits from dev into main 2026-07-14 11:26:14 +08:00
5 changed files with 86 additions and 280 deletions
Showing only changes of commit c9ddc3b652 - Show all commits

View File

@@ -92,7 +92,7 @@ function formatDateTime(value?: string) {
:data="dataList" :data="dataList"
searchable searchable
:search-fields="['name']" :search-fields="['name']"
create-text="新建数据处理任务" create-text="新建数据处理"
create-to="/data-process/create" create-to="/data-process/create"
row-key="id" row-key="id"
:page-size="10" :page-size="10"

View File

@@ -10,8 +10,6 @@ const props = defineProps<{
validationMessage?: string validationMessage?: string
}>() }>()
const advancedModelSettingsOpen = ref(false)
const emit = defineEmits<{ const emit = defineEmits<{
'update:options': [value: GenerationControlOptions] 'update:options': [value: GenerationControlOptions]
}>() }>()
@@ -99,64 +97,49 @@ function sectionValidationMessage() {
</div> </div>
</div> </div>
<button <div class="advanced-settings-grid">
type="button" <label class="config-field">
class="advanced-settings-toggle" <span class="config-field-label">生成温度 (Temperature)</span>
:aria-expanded="advancedModelSettingsOpen" <el-slider
@click="advancedModelSettingsOpen = !advancedModelSettingsOpen" :model-value="options.temperature"
> :min="0"
<span> :max="1"
<strong>高级设置</strong> :step="0.1"
<small>温度最大输出长度与格式约束</small> show-input
</span> @update:model-value="updateField('temperature', Number($event) || 0)"
<i class="fa" :class="advancedModelSettingsOpen ? 'fa-chevron-up' : 'fa-chevron-down'" />
</button>
<div v-if="advancedModelSettingsOpen" class="advanced-settings-panel">
<div class="advanced-settings-grid">
<label class="config-field">
<span class="config-field-label">生成温度 (Temperature)</span>
<el-slider
:model-value="options.temperature"
:min="0"
:max="1"
:step="0.1"
show-input
@update:model-value="updateField('temperature', Number($event) || 0)"
/>
<small>较低值输出更确定保守较高值输出更多样有创造性</small>
</label>
<label class="config-field">
<span class="config-field-label">最大输出长度 (Max Tokens)</span>
<span class="unit-input">
<el-input-number
:model-value="options.maxTokens"
:min="100"
:max="8192"
:step="256"
controls-position="right"
@update:model-value="updateField('maxTokens', Number($event) || 1024)"
/>
<span>Token</span>
</span>
<small>限制单次生成的最大内容长度防止过度发散</small>
</label>
</div>
<div class="json-mode-row">
<div class="field-copy">
<strong>强制 JSON 格式输出</strong>
<small>要求大模型返回纯 JSON 对象有助于提高下游结构化提取的稳定性</small>
</div>
<el-switch
:model-value="options.jsonMode"
inline-prompt
active-text=""
inactive-text=""
@update:model-value="updateField('jsonMode', Boolean($event))"
/> />
<small>较低值输出更确定保守较高值输出更多样有创造性</small>
</label>
<label class="config-field">
<span class="config-field-label">最大输出长度 (Max Tokens)</span>
<span class="unit-input">
<el-input-number
:model-value="options.maxTokens"
:min="100"
:max="8192"
:step="256"
controls-position="right"
@update:model-value="updateField('maxTokens', Number($event) || 1024)"
/>
<span>Token</span>
</span>
<small>限制单次生成的最大内容长度防止过度发散</small>
</label>
</div>
<div class="json-mode-row">
<div class="field-copy">
<strong>强制 JSON 格式输出</strong>
<small>要求大模型返回纯 JSON 对象有助于提高下游结构化提取的稳定性</small>
</div> </div>
<el-switch
:model-value="options.jsonMode"
inline-prompt
active-text=""
inactive-text=""
@update:model-value="updateField('jsonMode', Boolean($event))"
/>
</div> </div>
<p v-if="sectionValidationMessage()" class="generation-validation-message" role="alert"> <p v-if="sectionValidationMessage()" class="generation-validation-message" role="alert">
@@ -297,61 +280,6 @@ function sectionValidationMessage() {
} }
} }
.advanced-settings-toggle {
display: flex;
width: 100%;
min-height: 48px;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-top: 4px;
padding: 10px 14px;
color: #344054;
text-align: left;
background: #fff;
border: 1px solid #e2e5ec;
border-radius: 8px;
cursor: pointer;
transition: border-color 0.18s ease, background-color 0.18s ease;
&:hover {
background: #f8f7ff;
border-color: #b7b2f7;
}
> span {
display: grid;
gap: 3px;
}
strong {
font-size: 13px;
font-weight: 600;
}
small {
color: #8a93a3;
font-size: 12px;
line-height: 1.5;
}
i {
flex: 0 0 auto;
color: #7b8495;
font-size: 12px;
}
}
.advanced-settings-panel {
display: grid;
gap: 16px;
margin-top: -8px;
padding: 16px;
background: #fff;
border: 1px solid #e2e5ec;
border-radius: 8px;
}
.advanced-settings-grid { .advanced-settings-grid {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -401,8 +329,8 @@ function sectionValidationMessage() {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 20px; gap: 16px;
padding: 14px; padding: 12px 14px;
background: #fff; background: #fff;
border: 1px solid #e2e5ec; border: 1px solid #e2e5ec;
border-radius: 8px; border-radius: 8px;

View File

@@ -94,19 +94,7 @@ function updatePreprocessOptions(value: Array<string | number | boolean>) {
:validation-message="validationAttempted ? generationValidationMessage : ''" :validation-message="validationAttempted ? generationValidationMessage : ''"
@update:options="updateGenerationOptions" @update:options="updateGenerationOptions"
/> />
<div class="generation-option-row">
<div class="generation-option-copy">
<strong>语义丰富表达</strong>
<small>使用大模型将问答表述得更自然柔和</small>
</div>
<el-switch
:model-value="options.semanticEnrichment"
inline-prompt
active-text=""
inactive-text=""
@update:model-value="updateField('semanticEnrichment', Boolean($event))"
/>
</div>
<div class="generation-option-row"> <div class="generation-option-row">
<div class="generation-option-copy"> <div class="generation-option-copy">
<strong>每行生成数量</strong> <strong>每行生成数量</strong>
@@ -192,6 +180,7 @@ function updatePreprocessOptions(value: Array<string | number | boolean>) {
.preprocess-option { .preprocess-option {
display: flex; display: flex;
gap: 10px;
width: 100%; width: 100%;
min-height: 64px; min-height: 64px;
margin-right: 0; margin-right: 0;

View File

@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus' import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import type { ModelItem } from '@/types' import type { ModelItem } from '@/types'
import type { import type {
GenerationControlOptions, GenerationControlOptions,
@@ -97,17 +97,28 @@ async function validate() {
if (!formRef.value) return false if (!formRef.value) return false
try { try {
await formRef.value.validate() await formRef.value.validate()
if (props.processType === 'structured' && splitTotal.value !== 100) return false if (props.processType === 'structured' && splitTotal.value !== 100) {
ElMessage.error('结构化数据处理:数据集划分比例总和必须为 100%')
return false
}
if (props.processType === 'unstructured') { if (props.processType === 'unstructured') {
if (unstructuredSplitTotal.value !== 100) return false if (unstructuredSplitTotal.value !== 100) {
ElMessage.error('非结构化数据处理:数据集划分比例总和必须为 100%')
return false
}
if (chunkValidationMessage.value) { if (chunkValidationMessage.value) {
unstructuredOptionsPanelRef.value?.revealValidation() unstructuredOptionsPanelRef.value?.revealValidation()
ElMessage.error(chunkValidationMessage.value)
return false return false
} }
} }
if (generationValidationMessage.value) return false if (generationValidationMessage.value) {
ElMessage.error(generationValidationMessage.value)
return false
}
return true return true
} catch { } catch {
ElMessage.error('请完善标红的必填项')
return false return false
} }
} }
@@ -117,7 +128,7 @@ defineExpose({ validate })
<template> <template>
<section class="task-setup-step"> <section class="task-setup-step">
<el-form ref="formRef" :model="formModel" :rules="rules" label-position="top"> <el-form ref="formRef" :model="formModel" :rules="rules" label-position="top" scroll-to-error>
<div class="form-section"> <div class="form-section">
<h3>基本信息</h3> <h3>基本信息</h3>
<div class="basic-grid"> <div class="basic-grid">

View File

@@ -47,8 +47,6 @@ const UNSTRUCTURED_NUMBER_LIMITS = {
type UnstructuredNumberField = keyof typeof UNSTRUCTURED_NUMBER_LIMITS type UnstructuredNumberField = keyof typeof UNSTRUCTURED_NUMBER_LIMITS
const advancedChunkSettingsOpen = ref(props.options.chunkMethod === 'custom')
const smartPreprocessEnabled = computed(() => SMART_PREPROCESS_OPTIONS.every( const smartPreprocessEnabled = computed(() => SMART_PREPROCESS_OPTIONS.every(
(option) => props.options.preprocessOptions.includes(option), (option) => props.options.preprocessOptions.includes(option),
)) ))
@@ -61,14 +59,6 @@ const preserveSpecialContentEnabled = computed(() => (
&& props.options.preserveLists && props.options.preserveLists
)) ))
watch(() => props.options.chunkMethod, (method) => {
if (method === 'custom') advancedChunkSettingsOpen.value = true
})
watch(() => props.chunkValidationMessage, (message) => {
if (message) advancedChunkSettingsOpen.value = true
})
function updateField<K extends keyof UnstructuredProcessOptions>( function updateField<K extends keyof UnstructuredProcessOptions>(
field: K, field: K,
value: UnstructuredProcessOptions[K], value: UnstructuredProcessOptions[K],
@@ -117,7 +107,7 @@ function updateUnstructuredNumber(field: UnstructuredNumberField, value: number
} }
function revealValidation() { function revealValidation() {
advancedChunkSettingsOpen.value = true // Advanced settings are now flattened, no need to open toggle
} }
defineExpose({ revealValidation }) defineExpose({ revealValidation })
@@ -153,6 +143,17 @@ defineExpose({ revealValidation })
<small>处理姓名手机号等隐私信息</small> <small>处理姓名手机号等隐私信息</small>
</span> </span>
</label> </label>
<label class="preprocess-option" :class="{ 'is-checked': preserveSpecialContentEnabled }">
<el-checkbox
:model-value="preserveSpecialContentEnabled"
@update:model-value="updateSpecialContentProtection"
/>
<span class="preprocess-option-copy">
<strong>保护表格代码和列表</strong>
<small>避免切分点破坏特殊内容块的完整性</small>
</span>
</label>
</div> </div>
</div> </div>
@@ -217,36 +218,6 @@ defineExpose({ revealValidation })
</span> </span>
<small>在相邻切片中最多重复保留的上下文默认 100 Token</small> <small>在相邻切片中最多重复保留的上下文默认 100 Token</small>
</label> </label>
</div>
<p class="chunk-estimation-note">
Token 数为轻量估算值实际长度以训练使用的模型分词器为准
</p>
<p v-if="chunkValidationMessage" class="option-validation-message" role="alert">
{{ chunkValidationMessage }}
</p>
<button
type="button"
class="advanced-settings-toggle"
:aria-expanded="advancedChunkSettingsOpen"
aria-controls="unstructured-advanced-settings"
@click="advancedChunkSettingsOpen = !advancedChunkSettingsOpen"
>
<span>
<strong>高级设置</strong>
<small>最小切片长度自定义分隔符和特殊内容保护</small>
</span>
<i class="fa" :class="advancedChunkSettingsOpen ? 'fa-chevron-up' : 'fa-chevron-down'" />
</button>
<div
v-if="advancedChunkSettingsOpen"
id="unstructured-advanced-settings"
class="advanced-settings-panel"
>
<div class="advanced-settings-grid">
<label class="config-field"> <label class="config-field">
<span class="config-field-label">最小切片长度</span> <span class="config-field-label">最小切片长度</span>
<span class="unit-input"> <span class="unit-input">
@@ -277,23 +248,15 @@ defineExpose({ revealValidation })
/> />
<small>系统会优先在分隔符位置结束当前切片</small> <small>系统会优先在分隔符位置结束当前切片</small>
</label> </label>
</div>
<div class="generation-option-row advanced-protection-row">
<div class="generation-option-copy">
<strong>保护表格代码和列表</strong>
<small>避免切分点破坏特殊内容块的完整性</small>
</div>
<el-switch
:model-value="preserveSpecialContentEnabled"
aria-label="保护表格代码和列表"
inline-prompt
active-text=""
inactive-text=""
@update:model-value="updateSpecialContentProtection"
/>
</div>
</div> </div>
<p class="chunk-estimation-note">
Token 数为轻量估算值实际长度以训练使用的模型分词器为准
</p>
<p v-if="chunkValidationMessage" class="option-validation-message" role="alert">
{{ chunkValidationMessage }}
</p>
</div> </div>
<div class="form-section generation-options-section"> <div class="form-section generation-options-section">
@@ -311,20 +274,7 @@ defineExpose({ revealValidation })
:validation-message="validationAttempted ? generationValidationMessage : ''" :validation-message="validationAttempted ? generationValidationMessage : ''"
@update:options="updateGenerationOptions" @update:options="updateGenerationOptions"
/> />
<div class="generation-option-row">
<div class="generation-option-copy">
<strong>语义丰富表达</strong>
<small>使用大模型将问答表述得更自然柔和</small>
</div>
<el-switch
:model-value="options.semanticEnrichment"
aria-label="非结构化语义丰富表达"
inline-prompt
active-text=""
inactive-text=""
@update:model-value="updateField('semanticEnrichment', Boolean($event))"
/>
</div>
<div class="generation-option-row"> <div class="generation-option-row">
<div class="generation-option-copy"> <div class="generation-option-copy">
@@ -421,6 +371,7 @@ defineExpose({ revealValidation })
.preprocess-option { .preprocess-option {
display: flex; display: flex;
gap: 10px;
width: 100%; width: 100%;
min-height: 64px; min-height: 64px;
margin-right: 0; margin-right: 0;
@@ -559,75 +510,8 @@ defineExpose({ revealValidation })
line-height: 1.5; line-height: 1.5;
} }
.advanced-settings-toggle {
display: flex;
width: 100%;
min-height: 48px;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-top: 12px;
padding: 10px 14px;
color: #344054;
text-align: left;
background: #fff;
border: 1px solid #e2e5ec;
border-radius: 8px;
cursor: pointer;
transition: border-color 0.18s ease, background-color 0.18s ease;
&:hover {
background: #f8f7ff;
border-color: #b7b2f7;
}
&:focus-visible {
outline: 2px solid #5b50f2;
outline-offset: 2px;
}
> span {
display: grid;
gap: 3px;
}
strong {
font-size: 13px;
font-weight: 600;
}
small {
color: #8a93a3;
font-size: 12px;
line-height: 1.5;
}
i {
flex: 0 0 auto;
color: #7b8495;
font-size: 12px;
}
}
.advanced-settings-panel {
display: grid;
gap: 12px;
margin-top: 8px;
padding: 12px;
background: #fff;
border: 1px solid #e2e5ec;
border-radius: 8px;
}
.advanced-settings-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
@media (max-width: 900px) { @media (max-width: 900px) {
.chunk-settings-grid, .chunk-settings-grid {
.advanced-settings-grid {
grid-template-columns: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr);
} }
@@ -636,17 +520,11 @@ defineExpose({ revealValidation })
flex-direction: column; flex-direction: column;
} }
.compact-option-list .generation-option-row, .compact-option-list .generation-option-row {
.advanced-protection-row {
align-items: center; align-items: center;
flex-direction: row; flex-direction: row;
} }
.advanced-protection-row {
align-items: flex-start;
flex-direction: column;
}
.preprocess-option-grid { .preprocess-option-grid {
grid-template-columns: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr);
} }