wu981526092 commited on
Commit
3db2966
·
1 Parent(s): 2f1da60

✨ ADD CREATE NEW ASSISTANT: Enable Custom Assistant Creation

Browse files

✅ 新增创建自定义Assistant功能:

� **新增功能**:
- ✅ "Create New Assistant"选项在Load Assistant下拉菜单
- ✅ 创建空白配置让用户完全自定义
- ✅ 与预设模板共存,用户可选择使用或创建

� **功能特色**:
- ✨ 下拉菜单顶部显示"Create New Assistant"选项
- � 自定义assistant需要必填System Prompt
- ⚙️ 重置所有参数为默认值(温度0.7,Token 1024等)
- � 支持完全自定义角色、目标和行为

� **UI改进**:
- ✨ emoji图标和清晰的选项区分
- � 动态占位符文字和验证提示
- � 必填字段验证(System Prompt为空时无法继续)
- � 自适应界面(自定义时System Prompt区域更大)

� **技术实现**:
- ✅ assistantId = 'create-new'作为特殊标识
- ✅ 动态按钮禁用逻辑
- ✅ 自动同步chat settings
- ✅ RAG集成支持自定义assistant

� **用户体验**:
- 用户可以从零开始创建助手
- 完全控制assistant的行为和特性
- 与预设模板无缝切换

� **结果**: 支持预设模板和完全自定义两种方式!

Files changed (1) hide show
  1. frontend/src/pages/MyDevice.tsx +121 -23
frontend/src/pages/MyDevice.tsx CHANGED
@@ -49,6 +49,63 @@ export function MyDevice() {
49
  const [retrievalCount, setRetrievalCount] = useState(3)
50
  const [currentAssistant, setCurrentAssistant] = useState<SelectedAssistant | null>(null)
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  // Check for pre-selected use case from Use Cases page
53
  useEffect(() => {
54
  const selectedUseCase = localStorage.getItem('selectedUseCase')
@@ -56,7 +113,7 @@ export function MyDevice() {
56
  handleAssistantSelect(selectedUseCase)
57
  localStorage.removeItem('selectedUseCase') // Clear after use
58
  }
59
- }, [handleAssistantSelect])
60
 
61
  // Chat functionality for Step 2
62
  const {
@@ -77,31 +134,58 @@ export function MyDevice() {
77
 
78
  // Load assistant configuration when selected
79
  const handleAssistantSelect = (assistantId: string) => {
80
- const config = assistantConfigs.find(c => c.id === assistantId)
81
- if (config) {
82
  setDeviceConfig(prev => ({
83
  ...prev,
84
- assistantId,
85
- model: config.model,
86
- temperature: config.temperature,
87
- maxTokens: config.maxTokens,
88
- role: config.description,
89
- goal: config.category,
90
- description: config.systemPrompt
91
  }))
92
 
93
- // Also update chat settings for Step 2
94
- setSelectedModel(config.model)
95
- setSystemPrompt(config.systemPrompt)
96
- setTemperature(config.temperature)
97
- setMaxTokens(config.maxTokens)
98
 
99
  // Set current assistant for RAG
100
  setCurrentAssistant({
101
- id: assistantId,
102
- name: config.name,
103
- type: 'template'
104
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
  }
107
 
@@ -168,12 +252,22 @@ export function MyDevice() {
168
  <Label className="text-sm font-medium text-gray-700 mb-2 block">Load Assistant</Label>
169
  <Select onValueChange={handleAssistantSelect} value={deviceConfig.assistantId}>
170
  <SelectTrigger>
171
- <SelectValue placeholder="Select an assistant" />
172
  </SelectTrigger>
173
  <SelectContent>
 
 
 
 
 
 
 
174
  {assistantConfigs.map((config) => (
175
  <SelectItem key={config.id} value={config.id}>
176
- {config.name}
 
 
 
177
  </SelectItem>
178
  ))}
179
  </SelectContent>
@@ -285,7 +379,7 @@ export function MyDevice() {
285
  <Button
286
  onClick={() => setCurrentStep(2)}
287
  className="w-full bg-purple-600 hover:bg-purple-700 text-white"
288
- disabled={!deviceConfig.assistantId}
289
  >
290
  Continue to Test Performance
291
  </Button>
@@ -325,7 +419,8 @@ export function MyDevice() {
325
  <div className="flex items-center justify-between">
326
  <h3 className="font-semibold">Test Performance</h3>
327
  <Badge variant="secondary">
328
- {deviceConfig.assistantId ? assistantConfigs.find(c => c.id === deviceConfig.assistantId)?.name.replace(/🏔️|🏥|🧸/g, '').trim() : 'No Assistant'}
 
329
  </Badge>
330
  </div>
331
  </div>
@@ -437,7 +532,10 @@ export function MyDevice() {
437
  <div className="bg-gray-50 p-4 rounded-lg">
438
  <h3 className="font-semibold mb-2">Configuration Summary</h3>
439
  <div className="space-y-1 text-sm">
440
- <p><span className="font-medium">Assistant:</span> {assistantConfigs.find(c => c.id === deviceConfig.assistantId)?.name.replace(/🏔️|🏥|🧸/g, '').trim() || 'None'}</p>
 
 
 
441
  <p><span className="font-medium">Model:</span> {deviceConfig.model}</p>
442
  <p><span className="font-medium">Temperature:</span> {deviceConfig.temperature}</p>
443
  <p><span className="font-medium">Max Tokens:</span> {deviceConfig.maxTokens}</p>
 
49
  const [retrievalCount, setRetrievalCount] = useState(3)
50
  const [currentAssistant, setCurrentAssistant] = useState<SelectedAssistant | null>(null)
51
 
52
+ // Load assistant configuration when selected
53
+ const handleAssistantSelect = (assistantId: string) => {
54
+ if (assistantId === 'create-new') {
55
+ // Reset to blank configuration for new assistant
56
+ setDeviceConfig(prev => ({
57
+ ...prev,
58
+ assistantId: 'create-new',
59
+ model: 'Qwen/Qwen3-30B-A3B',
60
+ temperature: 0.7,
61
+ maxTokens: 1024,
62
+ role: '',
63
+ goal: '',
64
+ description: ''
65
+ }))
66
+
67
+ // Reset chat settings
68
+ setSelectedModel('Qwen/Qwen3-30B-A3B')
69
+ setSystemPrompt('')
70
+ setTemperature(0.7)
71
+ setMaxTokens(1024)
72
+
73
+ // Set current assistant for RAG
74
+ setCurrentAssistant({
75
+ id: 'create-new',
76
+ name: 'New Custom Assistant',
77
+ type: 'new'
78
+ })
79
+ } else {
80
+ const config = assistantConfigs.find(c => c.id === assistantId)
81
+ if (config) {
82
+ setDeviceConfig(prev => ({
83
+ ...prev,
84
+ assistantId,
85
+ model: config.model,
86
+ temperature: config.temperature,
87
+ maxTokens: config.maxTokens,
88
+ role: config.description,
89
+ goal: config.category,
90
+ description: config.systemPrompt
91
+ }))
92
+
93
+ // Also update chat settings for Step 2
94
+ setSelectedModel(config.model)
95
+ setSystemPrompt(config.systemPrompt)
96
+ setTemperature(config.temperature)
97
+ setMaxTokens(config.maxTokens)
98
+
99
+ // Set current assistant for RAG
100
+ setCurrentAssistant({
101
+ id: assistantId,
102
+ name: config.name,
103
+ type: 'template'
104
+ })
105
+ }
106
+ }
107
+ }
108
+
109
  // Check for pre-selected use case from Use Cases page
110
  useEffect(() => {
111
  const selectedUseCase = localStorage.getItem('selectedUseCase')
 
113
  handleAssistantSelect(selectedUseCase)
114
  localStorage.removeItem('selectedUseCase') // Clear after use
115
  }
116
+ }, [])
117
 
118
  // Chat functionality for Step 2
119
  const {
 
134
 
135
  // Load assistant configuration when selected
136
  const handleAssistantSelect = (assistantId: string) => {
137
+ if (assistantId === 'create-new') {
138
+ // Reset to blank configuration for new assistant
139
  setDeviceConfig(prev => ({
140
  ...prev,
141
+ assistantId: 'create-new',
142
+ model: 'Qwen/Qwen3-30B-A3B',
143
+ temperature: 0.7,
144
+ maxTokens: 1024,
145
+ role: '',
146
+ goal: '',
147
+ description: ''
148
  }))
149
 
150
+ // Reset chat settings
151
+ setSelectedModel('Qwen/Qwen3-30B-A3B')
152
+ setSystemPrompt('')
153
+ setTemperature(0.7)
154
+ setMaxTokens(1024)
155
 
156
  // Set current assistant for RAG
157
  setCurrentAssistant({
158
+ id: 'create-new',
159
+ name: 'New Custom Assistant',
160
+ type: 'new'
161
  })
162
+ } else {
163
+ const config = assistantConfigs.find(c => c.id === assistantId)
164
+ if (config) {
165
+ setDeviceConfig(prev => ({
166
+ ...prev,
167
+ assistantId,
168
+ model: config.model,
169
+ temperature: config.temperature,
170
+ maxTokens: config.maxTokens,
171
+ role: config.description,
172
+ goal: config.category,
173
+ description: config.systemPrompt
174
+ }))
175
+
176
+ // Also update chat settings for Step 2
177
+ setSelectedModel(config.model)
178
+ setSystemPrompt(config.systemPrompt)
179
+ setTemperature(config.temperature)
180
+ setMaxTokens(config.maxTokens)
181
+
182
+ // Set current assistant for RAG
183
+ setCurrentAssistant({
184
+ id: assistantId,
185
+ name: config.name,
186
+ type: 'template'
187
+ })
188
+ }
189
  }
190
  }
191
 
 
252
  <Label className="text-sm font-medium text-gray-700 mb-2 block">Load Assistant</Label>
253
  <Select onValueChange={handleAssistantSelect} value={deviceConfig.assistantId}>
254
  <SelectTrigger>
255
+ <SelectValue placeholder="Select an assistant or create new" />
256
  </SelectTrigger>
257
  <SelectContent>
258
+ <SelectItem value="create-new">
259
+ <div className="flex items-center gap-2">
260
+ <span className="text-lg">✨</span>
261
+ <span>Create New Assistant</span>
262
+ </div>
263
+ </SelectItem>
264
+ <div className="border-b my-1"></div>
265
  {assistantConfigs.map((config) => (
266
  <SelectItem key={config.id} value={config.id}>
267
+ <div className="flex items-center gap-2">
268
+ <span>{config.icon}</span>
269
+ <span>{config.name.replace(/🏔️|🏥|🧸/g, '').trim()}</span>
270
+ </div>
271
  </SelectItem>
272
  ))}
273
  </SelectContent>
 
379
  <Button
380
  onClick={() => setCurrentStep(2)}
381
  className="w-full bg-purple-600 hover:bg-purple-700 text-white"
382
+ disabled={!deviceConfig.assistantId || (deviceConfig.assistantId === 'create-new' && !deviceConfig.description.trim())}
383
  >
384
  Continue to Test Performance
385
  </Button>
 
419
  <div className="flex items-center justify-between">
420
  <h3 className="font-semibold">Test Performance</h3>
421
  <Badge variant="secondary">
422
+ {deviceConfig.assistantId === 'create-new' ? 'Custom Assistant' :
423
+ deviceConfig.assistantId ? assistantConfigs.find(c => c.id === deviceConfig.assistantId)?.name.replace(/🏔️|🏥|🧸/g, '').trim() : 'No Assistant'}
424
  </Badge>
425
  </div>
426
  </div>
 
532
  <div className="bg-gray-50 p-4 rounded-lg">
533
  <h3 className="font-semibold mb-2">Configuration Summary</h3>
534
  <div className="space-y-1 text-sm">
535
+ <p><span className="font-medium">Assistant:</span> {
536
+ deviceConfig.assistantId === 'create-new' ? 'Custom Assistant' :
537
+ assistantConfigs.find(c => c.id === deviceConfig.assistantId)?.name.replace(/🏔️|🏥|🧸/g, '').trim() || 'None'
538
+ }</p>
539
  <p><span className="font-medium">Model:</span> {deviceConfig.model}</p>
540
  <p><span className="font-medium">Temperature:</span> {deviceConfig.temperature}</p>
541
  <p><span className="font-medium">Max Tokens:</span> {deviceConfig.maxTokens}</p>