samlax12 commited on
Commit
3e8f1b2
·
verified ·
1 Parent(s): 4b8af40

Update modules/agent_builder/routes.py

Browse files
Files changed (1) hide show
  1. modules/agent_builder/routes.py +503 -503
modules/agent_builder/routes.py CHANGED
@@ -1,504 +1,504 @@
1
- # modules/agent_builder/routes.py
2
- from flask import Blueprint, request, jsonify
3
- import os
4
- import json
5
- import time
6
- import uuid
7
- import requests
8
- from config import STREAM_API_KEY, STREAM_BASE_URL, DEFAULT_MODEL
9
-
10
- agent_builder_bp = Blueprint('agent_builder', __name__)
11
-
12
- # 确保Agent存储目录存在
13
- AGENTS_DIR = 'agents'
14
- os.makedirs(AGENTS_DIR, exist_ok=True)
15
-
16
- @agent_builder_bp.route('/create', methods=['POST'])
17
- def create_agent():
18
- """创建新的Agent"""
19
- try:
20
- data = request.json
21
- name = data.get('name')
22
- description = data.get('description', '')
23
- subject = data.get('subject', name) # 默认使用名称作为学科
24
- instructor = data.get('instructor', '教师') # 默认使用教师作为指导者
25
- plugins = data.get('plugins', [])
26
- knowledge_bases = data.get('knowledge_bases', [])
27
- workflow = data.get('workflow')
28
-
29
- if not name:
30
- return jsonify({
31
- "success": False,
32
- "message": "Agent名称不能为空"
33
- }), 400
34
-
35
- # 创建Agent ID
36
- agent_id = f"agent_{uuid.uuid4().hex[:8]}_{int(time.time())}"
37
-
38
- # 构建Agent配置
39
- agent_config = {
40
- "id": agent_id,
41
- "name": name,
42
- "description": description,
43
- "subject": subject, # 添加学科
44
- "instructor": instructor, # 添加指导者
45
- "created_at": int(time.time()),
46
- "plugins": plugins,
47
- "knowledge_bases": knowledge_bases,
48
- "workflow": workflow or {
49
- "nodes": [],
50
- "edges": []
51
- },
52
- "distributions": [],
53
- "stats": {
54
- "usage_count": 0,
55
- "last_used": None
56
- }
57
- }
58
-
59
- # 保存Agent配置
60
- with open(os.path.join(AGENTS_DIR, f"{agent_id}.json"), 'w', encoding='utf-8') as f:
61
- json.dump(agent_config, f, ensure_ascii=False, indent=2)
62
-
63
- return jsonify({
64
- "success": True,
65
- "agent_id": agent_id,
66
- "message": f"Agent '{name}' 创建成功"
67
- })
68
-
69
- except Exception as e:
70
- import traceback
71
- traceback.print_exc()
72
- return jsonify({
73
- "success": False,
74
- "message": str(e)
75
- }), 500
76
-
77
- @agent_builder_bp.route('/list', methods=['GET'])
78
- def list_agents():
79
- """获取所有Agent列表"""
80
- try:
81
- agents = []
82
-
83
- for filename in os.listdir(AGENTS_DIR):
84
- if filename.endswith('.json'):
85
- with open(os.path.join(AGENTS_DIR, filename), 'r', encoding='utf-8') as f:
86
- agent_config = json.load(f)
87
-
88
- # 简化版本,只返回关键信息
89
- agents.append({
90
- "id": agent_config.get("id"),
91
- "name": agent_config.get("name"),
92
- "description": agent_config.get("description"),
93
- "subject": agent_config.get("subject", agent_config.get("name")),
94
- "instructor": agent_config.get("instructor", "教师"),
95
- "created_at": agent_config.get("created_at"),
96
- "plugins": agent_config.get("plugins", []),
97
- "knowledge_bases": agent_config.get("knowledge_bases", []),
98
- "usage_count": agent_config.get("stats", {}).get("usage_count", 0),
99
- "distribution_count": len(agent_config.get("distributions", []))
100
- })
101
-
102
- # 按创建时间排序
103
- agents.sort(key=lambda x: x.get("created_at", 0), reverse=True)
104
-
105
- return jsonify({
106
- "success": True,
107
- "agents": agents
108
- })
109
-
110
- except Exception as e:
111
- import traceback
112
- traceback.print_exc()
113
- return jsonify({
114
- "success": False,
115
- "message": str(e)
116
- }), 500
117
-
118
- @agent_builder_bp.route('/<agent_id>', methods=['GET'])
119
- def get_agent(agent_id):
120
- """获取特定Agent的配置"""
121
- try:
122
- agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
123
-
124
- if not os.path.exists(agent_path):
125
- return jsonify({
126
- "success": False,
127
- "message": "Agent不存在"
128
- }), 404
129
-
130
- with open(agent_path, 'r', encoding='utf-8') as f:
131
- agent_config = json.load(f)
132
-
133
- return jsonify({
134
- "success": True,
135
- "agent": agent_config
136
- })
137
-
138
- except Exception as e:
139
- import traceback
140
- traceback.print_exc()
141
- return jsonify({
142
- "success": False,
143
- "message": str(e)
144
- }), 500
145
-
146
- @agent_builder_bp.route('/<agent_id>', methods=['PUT'])
147
- def update_agent(agent_id):
148
- """更新Agent配置"""
149
- try:
150
- data = request.json
151
- agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
152
-
153
- if not os.path.exists(agent_path):
154
- return jsonify({
155
- "success": False,
156
- "message": "Agent不存在"
157
- }), 404
158
-
159
- # 读取现有配置
160
- with open(agent_path, 'r', encoding='utf-8') as f:
161
- agent_config = json.load(f)
162
-
163
- # 更新允许的字段
164
- if 'name' in data:
165
- agent_config['name'] = data['name']
166
-
167
- if 'description' in data:
168
- agent_config['description'] = data['description']
169
-
170
- if 'plugins' in data:
171
- agent_config['plugins'] = data['plugins']
172
-
173
- if 'knowledge_bases' in data:
174
- agent_config['knowledge_bases'] = data['knowledge_bases']
175
-
176
- if 'workflow' in data:
177
- agent_config['workflow'] = data['workflow']
178
-
179
- # 添加更新时间
180
- agent_config['updated_at'] = int(time.time())
181
-
182
- # 保存更新后的配置
183
- with open(agent_path, 'w', encoding='utf-8') as f:
184
- json.dump(agent_config, f, ensure_ascii=False, indent=2)
185
-
186
- return jsonify({
187
- "success": True,
188
- "message": "Agent更新成功"
189
- })
190
-
191
- except Exception as e:
192
- import traceback
193
- traceback.print_exc()
194
- return jsonify({
195
- "success": False,
196
- "message": str(e)
197
- }), 500
198
-
199
- @agent_builder_bp.route('/<agent_id>', methods=['DELETE'])
200
- def delete_agent(agent_id):
201
- """删除Agent"""
202
- try:
203
- agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
204
-
205
- if not os.path.exists(agent_path):
206
- return jsonify({
207
- "success": False,
208
- "message": "Agent不存在"
209
- }), 404
210
-
211
- # 删除Agent配置文件
212
- os.remove(agent_path)
213
-
214
- return jsonify({
215
- "success": True,
216
- "message": "Agent删除成功"
217
- })
218
-
219
- except Exception as e:
220
- import traceback
221
- traceback.print_exc()
222
- return jsonify({
223
- "success": False,
224
- "message": str(e)
225
- }), 500
226
-
227
- @agent_builder_bp.route('/<agent_id>/distribute', methods=['POST'])
228
- def distribute_agent(agent_id):
229
- """为Agent创建分发链接"""
230
- try:
231
- data = request.json
232
- expires_in = data.get('expires_in', 0) # 0表示永不过期
233
-
234
- agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
235
-
236
- if not os.path.exists(agent_path):
237
- return jsonify({
238
- "success": False,
239
- "message": "Agent不存在"
240
- }), 404
241
-
242
- # 读取Agent配置
243
- with open(agent_path, 'r', encoding='utf-8') as f:
244
- agent_config = json.load(f)
245
-
246
- # 创建访问令牌
247
- token = uuid.uuid4().hex
248
-
249
- # 计算过期时间
250
- expiry = int(time.time() + expires_in) if expires_in > 0 else 0
251
-
252
- # 创建分发记录
253
- distribution = {
254
- "id": f"dist_{uuid.uuid4().hex[:6]}",
255
- "created_at": int(time.time()),
256
- "token": token,
257
- "expires_at": expiry,
258
- "usage_count": 0
259
- }
260
-
261
- # 更新Agent配置
262
- if "distributions" not in agent_config:
263
- agent_config["distributions"] = []
264
-
265
- agent_config["distributions"].append(distribution)
266
-
267
- # 保存更新后的配置
268
- with open(agent_path, 'w', encoding='utf-8') as f:
269
- json.dump(agent_config, f, ensure_ascii=False, indent=2)
270
-
271
- # 构建访问链接
272
- access_link = f"/student/{agent_id}?token={token}"
273
-
274
- return jsonify({
275
- "success": True,
276
- "distribution": {
277
- "id": distribution["id"],
278
- "link": access_link,
279
- "token": token,
280
- "expires_at": expiry
281
- },
282
- "message": "分发链接创建成功"
283
- })
284
-
285
- except Exception as e:
286
- import traceback
287
- traceback.print_exc()
288
- return jsonify({
289
- "success": False,
290
- "message": str(e)
291
- }), 500
292
-
293
- @agent_builder_bp.route('/ai-assist', methods=['POST'])
294
- def ai_assisted_workflow():
295
- """使用AI辅助Agent工作流编排"""
296
- try:
297
- data = request.json
298
- description = data.get('description', '')
299
- subject = data.get('subject', '通用学科')
300
- knowledge_bases = data.get('knowledge_bases', [])
301
- plugins = data.get('plugins', [])
302
-
303
- if not description:
304
- return jsonify({
305
- "success": False,
306
- "message": "请提供Agent描述"
307
- }), 400
308
-
309
- # 获取所有可用的知识库
310
- available_knowledge_bases = []
311
- try:
312
- # 获取知识库列表的API调用
313
- kb_response = requests.get("http://localhost:5000/api/knowledge")
314
- if kb_response.status_code == 200:
315
- kb_data = kb_response.json()
316
- if kb_data.get("success"):
317
- for kb in kb_data.get("data", []):
318
- available_knowledge_bases.append(kb["id"])
319
- except:
320
- # 如果API调用失败,使用默认值
321
- pass
322
-
323
- # 可用的插件
324
- available_plugins = ["code", "visualization", "mindmap"]
325
-
326
- # 构建提示
327
- system_prompt = """你是一个专业的AI工作流设计师。你需要根据用户描述,设计一个适合教育场景的Agent工作流。
328
- 你不仅要设计工作流结构,还要推荐合适的知识库和插件。请确保工作流逻辑合理,能够满足用户的需求。
329
-
330
- 工作流应包含以下类型的节点:
331
- 1. 意图识别:识别用户输入的意图
332
- 2. 知识库查询:从指定知识库中检索信息
333
- 3. 插件调用:调用特定插件(如代码执行、3D可视化或思维导图)
334
- 4. 回复生成:生成最终回复
335
-
336
- 用户当前选择的知识库:{knowledge_bases}
337
- 系统中可用的知识库有:{available_knowledge_bases}
338
-
339
- 用户当前选择的插件:{plugins}
340
- 系统中可用的插件有:{available_plugins}
341
-
342
- 这个Agent的主题领域是:{subject}
343
-
344
- 重要:根据Agent描述,推荐最合适的知识库和插件。在推荐时,只能使用系统中真实可用的知识库和插件。
345
-
346
- 请返回三部分内容:
347
- 1. 推荐的知识库列表(只能从可用知识库中选择)
348
- 2. 推荐的插件列表(只能从可用插件中选择)
349
- 3. 完整的工作流JSON结构
350
-
351
- JSON格式示例:
352
- {{
353
- "recommended_knowledge_bases": ["rag_knowledge1", "rag_knowledge2"],
354
- "recommended_plugins": ["code", "visualization"],
355
- "workflow": {{
356
- "nodes": [
357
- {{ "id": "node1", "type": "intent_recognition", "data": {{ "name": "意图识别" }} }},
358
- {{ "id": "node2", "type": "knowledge_query", "data": {{ "name": "知识库查询", "knowledge_base_id": "rag_knowledge1" }} }},
359
- {{ "id": "node3", "type": "plugin_call", "data": {{ "name": "调用代码执行插件", "plugin_id": "code" }} }},
360
- {{ "id": "node4", "type": "generate_response", "data": {{ "name": "生成回复" }} }}
361
- ],
362
- "edges": [
363
- {{ "id": "edge1", "source": "node1", "target": "node2", "condition": "需要知识" }},
364
- {{ "id": "edge2", "source": "node1", "target": "node3", "condition": "需要代码执行" }},
365
- {{ "id": "edge3", "source": "node2", "target": "node4" }},
366
- {{ "id": "edge4", "source": "node3", "target": "node4" }}
367
- ]
368
- }}
369
- }}
370
- """
371
-
372
- system_prompt = system_prompt.format(
373
- knowledge_bases=", ".join(knowledge_bases) if knowledge_bases else "无",
374
- available_knowledge_bases=", ".join(available_knowledge_bases) if available_knowledge_bases else "无可用知识库",
375
- plugins=", ".join(plugins) if plugins else "无",
376
- available_plugins=", ".join(available_plugins),
377
- subject=subject
378
- )
379
-
380
- # 使用流式API
381
- try:
382
- headers = {
383
- "Authorization": f"Bearer {STREAM_API_KEY}",
384
- "Content-Type": "application/json"
385
- }
386
-
387
- response = requests.post(
388
- f"{STREAM_BASE_URL}/chat/completions",
389
- headers=headers,
390
- json={
391
- "model": DEFAULT_MODEL,
392
- "messages": [
393
- {"role": "system", "content": system_prompt},
394
- {"role": "user", "content": f"请为以下描述的教育Agent设计工作流并推荐知识库和插件:\n\n{description}"}
395
- ]
396
- }
397
- )
398
-
399
- if response.status_code != 200:
400
- return jsonify({
401
- "success": False,
402
- "message": f"Error code: {response.status_code} - {response.text}",
403
- "workflow": create_default_workflow(),
404
- "recommended_knowledge_bases": [],
405
- "recommended_plugins": []
406
- }), 200 # 返回200但包含错误信息和备用工作流
407
-
408
- result = response.json()
409
- content = result['choices'][0]['message']['content']
410
-
411
- except Exception as api_error:
412
- return jsonify({
413
- "success": False,
414
- "message": f"无法连接到AI模型服务: {str(api_error)}",
415
- "workflow": create_default_workflow(),
416
- "recommended_knowledge_bases": [],
417
- "recommended_plugins": []
418
- }), 200
419
-
420
- # 查找JSON部分
421
- import re
422
- json_match = re.search(r'```json\n([\s\S]*?)\n```', content)
423
-
424
- if json_match:
425
- workflow_json = json_match.group(1)
426
- else:
427
- # 尝试直接解析整个内容
428
- workflow_json = content
429
-
430
- # 解析JSON
431
- try:
432
- result_data = json.loads(workflow_json)
433
- except:
434
- # 如果解析失败,使用正则表达式清理
435
- workflow_json = re.sub(r'```json\n|\n```', '', content)
436
- try:
437
- result_data = json.loads(workflow_json)
438
- except:
439
- # 如果仍然解析失败,提取标准的JSON结构 { ... }
440
- import re
441
- json_patterns = re.findall(r'\{[\s\S]*?\}', content)
442
- if json_patterns:
443
- try:
444
- # 尝试解析最长的JSON结构
445
- longest_json = max(json_patterns, key=len)
446
- result_data = json.loads(longest_json)
447
- except:
448
- # 仍然失败,返回默认值
449
- return jsonify({
450
- "success": True,
451
- "message": "使用默认工作流(AI生成的JSON无效)",
452
- "workflow": create_default_workflow(),
453
- "recommended_knowledge_bases": [],
454
- "recommended_plugins": []
455
- })
456
- else:
457
- # 没有找到有效的JSON结构
458
- return jsonify({
459
- "success": True,
460
- "message": "使用默认工作流(未找到JSON结构)",
461
- "workflow": create_default_workflow(),
462
- "recommended_knowledge_bases": [],
463
- "recommended_plugins": []
464
- })
465
-
466
- # 提取推荐的知识库和插件
467
- recommended_knowledge_bases = result_data.get("recommended_knowledge_bases", [])
468
- recommended_plugins = result_data.get("recommended_plugins", [])
469
- workflow = result_data.get("workflow", create_default_workflow())
470
-
471
- # 验证推荐的知识库都存在
472
- valid_knowledge_bases = []
473
- for kb in recommended_knowledge_bases:
474
- if kb in available_knowledge_bases:
475
- valid_knowledge_bases.append(kb)
476
-
477
- # 验证推荐的插件都存在
478
- valid_plugins = []
479
- for plugin in recommended_plugins:
480
- if plugin in available_plugins:
481
- valid_plugins.append(plugin)
482
-
483
- return jsonify({
484
- "success": True,
485
- "workflow": workflow,
486
- "recommended_knowledge_bases": valid_knowledge_bases,
487
- "recommended_plugins": valid_plugins,
488
- "message": "已成功创建工作流"
489
- })
490
-
491
- except Exception as e:
492
- import traceback
493
- traceback.print_exc()
494
- return jsonify({
495
- "success": False,
496
- "message": str(e)
497
- }), 500
498
-
499
- def create_default_workflow():
500
- """创建一个默认的空工作流"""
501
- return {
502
- "nodes": [],
503
- "edges": []
504
  }
 
1
+ # modules/agent_builder/routes.py
2
+ from flask import Blueprint, request, jsonify
3
+ import os
4
+ import json
5
+ import time
6
+ import uuid
7
+ import requests
8
+ from config import STREAM_API_KEY, STREAM_BASE_URL, DEFAULT_MODEL
9
+
10
+ agent_builder_bp = Blueprint('agent_builder', __name__)
11
+
12
+ # 确保Agent存储目录存在
13
+ AGENTS_DIR = 'agents'
14
+ os.makedirs(AGENTS_DIR, exist_ok=True)
15
+
16
+ @agent_builder_bp.route('/create', methods=['POST'])
17
+ def create_agent():
18
+ """创建新的Agent"""
19
+ try:
20
+ data = request.json
21
+ name = data.get('name')
22
+ description = data.get('description', '')
23
+ subject = data.get('subject', name) # 默认使用名称作为学科
24
+ instructor = data.get('instructor', '教师') # 默认使用教师作为指导者
25
+ plugins = data.get('plugins', [])
26
+ knowledge_bases = data.get('knowledge_bases', [])
27
+ workflow = data.get('workflow')
28
+
29
+ if not name:
30
+ return jsonify({
31
+ "success": False,
32
+ "message": "Agent名称不能为空"
33
+ }), 400
34
+
35
+ # 创建Agent ID
36
+ agent_id = f"agent_{uuid.uuid4().hex[:8]}_{int(time.time())}"
37
+
38
+ # 构建Agent配置
39
+ agent_config = {
40
+ "id": agent_id,
41
+ "name": name,
42
+ "description": description,
43
+ "subject": subject, # 添加学科
44
+ "instructor": instructor, # 添加指导者
45
+ "created_at": int(time.time()),
46
+ "plugins": plugins,
47
+ "knowledge_bases": knowledge_bases,
48
+ "workflow": workflow or {
49
+ "nodes": [],
50
+ "edges": []
51
+ },
52
+ "distributions": [],
53
+ "stats": {
54
+ "usage_count": 0,
55
+ "last_used": None
56
+ }
57
+ }
58
+
59
+ # 保存Agent配置
60
+ with open(os.path.join(AGENTS_DIR, f"{agent_id}.json"), 'w', encoding='utf-8') as f:
61
+ json.dump(agent_config, f, ensure_ascii=False, indent=2)
62
+
63
+ return jsonify({
64
+ "success": True,
65
+ "agent_id": agent_id,
66
+ "message": f"Agent '{name}' 创建成功"
67
+ })
68
+
69
+ except Exception as e:
70
+ import traceback
71
+ traceback.print_exc()
72
+ return jsonify({
73
+ "success": False,
74
+ "message": str(e)
75
+ }), 500
76
+
77
+ @agent_builder_bp.route('/list', methods=['GET'])
78
+ def list_agents():
79
+ """获取所有Agent列表"""
80
+ try:
81
+ agents = []
82
+
83
+ for filename in os.listdir(AGENTS_DIR):
84
+ if filename.endswith('.json'):
85
+ with open(os.path.join(AGENTS_DIR, filename), 'r', encoding='utf-8') as f:
86
+ agent_config = json.load(f)
87
+
88
+ # 简化版本,只返回关键信息
89
+ agents.append({
90
+ "id": agent_config.get("id"),
91
+ "name": agent_config.get("name"),
92
+ "description": agent_config.get("description"),
93
+ "subject": agent_config.get("subject", agent_config.get("name")),
94
+ "instructor": agent_config.get("instructor", "教师"),
95
+ "created_at": agent_config.get("created_at"),
96
+ "plugins": agent_config.get("plugins", []),
97
+ "knowledge_bases": agent_config.get("knowledge_bases", []),
98
+ "usage_count": agent_config.get("stats", {}).get("usage_count", 0),
99
+ "distribution_count": len(agent_config.get("distributions", []))
100
+ })
101
+
102
+ # 按创建时间排序
103
+ agents.sort(key=lambda x: x.get("created_at", 0), reverse=True)
104
+
105
+ return jsonify({
106
+ "success": True,
107
+ "agents": agents
108
+ })
109
+
110
+ except Exception as e:
111
+ import traceback
112
+ traceback.print_exc()
113
+ return jsonify({
114
+ "success": False,
115
+ "message": str(e)
116
+ }), 500
117
+
118
+ @agent_builder_bp.route('/<agent_id>', methods=['GET'])
119
+ def get_agent(agent_id):
120
+ """获取特定Agent的配置"""
121
+ try:
122
+ agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
123
+
124
+ if not os.path.exists(agent_path):
125
+ return jsonify({
126
+ "success": False,
127
+ "message": "Agent不存在"
128
+ }), 404
129
+
130
+ with open(agent_path, 'r', encoding='utf-8') as f:
131
+ agent_config = json.load(f)
132
+
133
+ return jsonify({
134
+ "success": True,
135
+ "agent": agent_config
136
+ })
137
+
138
+ except Exception as e:
139
+ import traceback
140
+ traceback.print_exc()
141
+ return jsonify({
142
+ "success": False,
143
+ "message": str(e)
144
+ }), 500
145
+
146
+ @agent_builder_bp.route('/<agent_id>', methods=['PUT'])
147
+ def update_agent(agent_id):
148
+ """更新Agent配置"""
149
+ try:
150
+ data = request.json
151
+ agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
152
+
153
+ if not os.path.exists(agent_path):
154
+ return jsonify({
155
+ "success": False,
156
+ "message": "Agent不存在"
157
+ }), 404
158
+
159
+ # 读取现有配置
160
+ with open(agent_path, 'r', encoding='utf-8') as f:
161
+ agent_config = json.load(f)
162
+
163
+ # 更新允许的字段
164
+ if 'name' in data:
165
+ agent_config['name'] = data['name']
166
+
167
+ if 'description' in data:
168
+ agent_config['description'] = data['description']
169
+
170
+ if 'plugins' in data:
171
+ agent_config['plugins'] = data['plugins']
172
+
173
+ if 'knowledge_bases' in data:
174
+ agent_config['knowledge_bases'] = data['knowledge_bases']
175
+
176
+ if 'workflow' in data:
177
+ agent_config['workflow'] = data['workflow']
178
+
179
+ # 添加更新时间
180
+ agent_config['updated_at'] = int(time.time())
181
+
182
+ # 保存更新后的配置
183
+ with open(agent_path, 'w', encoding='utf-8') as f:
184
+ json.dump(agent_config, f, ensure_ascii=False, indent=2)
185
+
186
+ return jsonify({
187
+ "success": True,
188
+ "message": "Agent更新成功"
189
+ })
190
+
191
+ except Exception as e:
192
+ import traceback
193
+ traceback.print_exc()
194
+ return jsonify({
195
+ "success": False,
196
+ "message": str(e)
197
+ }), 500
198
+
199
+ @agent_builder_bp.route('/<agent_id>', methods=['DELETE'])
200
+ def delete_agent(agent_id):
201
+ """删除Agent"""
202
+ try:
203
+ agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
204
+
205
+ if not os.path.exists(agent_path):
206
+ return jsonify({
207
+ "success": False,
208
+ "message": "Agent不存在"
209
+ }), 404
210
+
211
+ # 删除Agent配置文件
212
+ os.remove(agent_path)
213
+
214
+ return jsonify({
215
+ "success": True,
216
+ "message": "Agent删除成功"
217
+ })
218
+
219
+ except Exception as e:
220
+ import traceback
221
+ traceback.print_exc()
222
+ return jsonify({
223
+ "success": False,
224
+ "message": str(e)
225
+ }), 500
226
+
227
+ @agent_builder_bp.route('/<agent_id>/distribute', methods=['POST'])
228
+ def distribute_agent(agent_id):
229
+ """为Agent创建分发链接"""
230
+ try:
231
+ data = request.json
232
+ expires_in = data.get('expires_in', 0) # 0表示永不过期
233
+
234
+ agent_path = os.path.join(AGENTS_DIR, f"{agent_id}.json")
235
+
236
+ if not os.path.exists(agent_path):
237
+ return jsonify({
238
+ "success": False,
239
+ "message": "Agent不存在"
240
+ }), 404
241
+
242
+ # 读取Agent配置
243
+ with open(agent_path, 'r', encoding='utf-8') as f:
244
+ agent_config = json.load(f)
245
+
246
+ # 创建访问令牌
247
+ token = uuid.uuid4().hex
248
+
249
+ # 计算过期时间
250
+ expiry = int(time.time() + expires_in) if expires_in > 0 else 0
251
+
252
+ # 创建分发记录
253
+ distribution = {
254
+ "id": f"dist_{uuid.uuid4().hex[:6]}",
255
+ "created_at": int(time.time()),
256
+ "token": token,
257
+ "expires_at": expiry,
258
+ "usage_count": 0
259
+ }
260
+
261
+ # 更新Agent配置
262
+ if "distributions" not in agent_config:
263
+ agent_config["distributions"] = []
264
+
265
+ agent_config["distributions"].append(distribution)
266
+
267
+ # 保存更新后的配置
268
+ with open(agent_path, 'w', encoding='utf-8') as f:
269
+ json.dump(agent_config, f, ensure_ascii=False, indent=2)
270
+
271
+ # 构建访问链接
272
+ access_link = f"/student/{agent_id}?token={token}"
273
+
274
+ return jsonify({
275
+ "success": True,
276
+ "distribution": {
277
+ "id": distribution["id"],
278
+ "link": access_link,
279
+ "token": token,
280
+ "expires_at": expiry
281
+ },
282
+ "message": "分发链接创建成功"
283
+ })
284
+
285
+ except Exception as e:
286
+ import traceback
287
+ traceback.print_exc()
288
+ return jsonify({
289
+ "success": False,
290
+ "message": str(e)
291
+ }), 500
292
+
293
+ @agent_builder_bp.route('/ai-assist', methods=['POST'])
294
+ def ai_assisted_workflow():
295
+ """使用AI辅助Agent工作流编排"""
296
+ try:
297
+ data = request.json
298
+ description = data.get('description', '')
299
+ subject = data.get('subject', '通用学科')
300
+ knowledge_bases = data.get('knowledge_bases', [])
301
+ plugins = data.get('plugins', [])
302
+
303
+ if not description:
304
+ return jsonify({
305
+ "success": False,
306
+ "message": "请提供Agent描述"
307
+ }), 400
308
+
309
+ # 获取所有可用的知识库
310
+ available_knowledge_bases = []
311
+ try:
312
+ # 获取知识库列表的API调用
313
+ kb_response = requests.get("http://localhost:7860/api/knowledge")
314
+ if kb_response.status_code == 200:
315
+ kb_data = kb_response.json()
316
+ if kb_data.get("success"):
317
+ for kb in kb_data.get("data", []):
318
+ available_knowledge_bases.append(kb["id"])
319
+ except:
320
+ # 如果API调用失败,使用默认值
321
+ pass
322
+
323
+ # 可用的插件
324
+ available_plugins = ["code", "visualization", "mindmap"]
325
+
326
+ # 构建提示
327
+ system_prompt = """你是一个专业的AI工作流设计师。你需要根据用户描述,设计一个适合教育场景的Agent工作流。
328
+ 你不仅要设计工作流结构,还要推荐合适的知识库和插件。请确保工作流逻辑合理,能够满足用户的需求。
329
+
330
+ 工作流应包含以下类型的节点:
331
+ 1. 意图识别:识别用户输入的意图
332
+ 2. 知识库查询:从指定知识库中检索信息
333
+ 3. 插件调用:调用特定插件(如��码执行、3D可视化或思维导图)
334
+ 4. 回复生成:生成最终回复
335
+
336
+ 用户当前选择的知识库:{knowledge_bases}
337
+ 系统中可用的知识库有:{available_knowledge_bases}
338
+
339
+ 用户当前选择的插件:{plugins}
340
+ 系统中可用的插件有:{available_plugins}
341
+
342
+ 这个Agent的主题领域是:{subject}
343
+
344
+ 重要:根据Agent描述,推荐最合适的知识库和插件。在推荐时,只能使用系统中真实可用的知识库和插件。
345
+
346
+ 请返回三部分内容:
347
+ 1. 推荐的知识库列表(只能从可用知识库中选择)
348
+ 2. 推荐的插件列表(只能从可用插件中选择)
349
+ 3. 完整的工作流JSON结构
350
+
351
+ JSON格式示例:
352
+ {{
353
+ "recommended_knowledge_bases": ["rag_knowledge1", "rag_knowledge2"],
354
+ "recommended_plugins": ["code", "visualization"],
355
+ "workflow": {{
356
+ "nodes": [
357
+ {{ "id": "node1", "type": "intent_recognition", "data": {{ "name": "意图识别" }} }},
358
+ {{ "id": "node2", "type": "knowledge_query", "data": {{ "name": "知识库查询", "knowledge_base_id": "rag_knowledge1" }} }},
359
+ {{ "id": "node3", "type": "plugin_call", "data": {{ "name": "调用代码执行插件", "plugin_id": "code" }} }},
360
+ {{ "id": "node4", "type": "generate_response", "data": {{ "name": "生成回复" }} }}
361
+ ],
362
+ "edges": [
363
+ {{ "id": "edge1", "source": "node1", "target": "node2", "condition": "需要知识" }},
364
+ {{ "id": "edge2", "source": "node1", "target": "node3", "condition": "需要代码执行" }},
365
+ {{ "id": "edge3", "source": "node2", "target": "node4" }},
366
+ {{ "id": "edge4", "source": "node3", "target": "node4" }}
367
+ ]
368
+ }}
369
+ }}
370
+ """
371
+
372
+ system_prompt = system_prompt.format(
373
+ knowledge_bases=", ".join(knowledge_bases) if knowledge_bases else "无",
374
+ available_knowledge_bases=", ".join(available_knowledge_bases) if available_knowledge_bases else "无可用知识库",
375
+ plugins=", ".join(plugins) if plugins else "无",
376
+ available_plugins=", ".join(available_plugins),
377
+ subject=subject
378
+ )
379
+
380
+ # 使用流式API
381
+ try:
382
+ headers = {
383
+ "Authorization": f"Bearer {STREAM_API_KEY}",
384
+ "Content-Type": "application/json"
385
+ }
386
+
387
+ response = requests.post(
388
+ f"{STREAM_BASE_URL}/chat/completions",
389
+ headers=headers,
390
+ json={
391
+ "model": DEFAULT_MODEL,
392
+ "messages": [
393
+ {"role": "system", "content": system_prompt},
394
+ {"role": "user", "content": f"请为以下描述的教育Agent设计工作流并推荐知识库和插件:\n\n{description}"}
395
+ ]
396
+ }
397
+ )
398
+
399
+ if response.status_code != 200:
400
+ return jsonify({
401
+ "success": False,
402
+ "message": f"Error code: {response.status_code} - {response.text}",
403
+ "workflow": create_default_workflow(),
404
+ "recommended_knowledge_bases": [],
405
+ "recommended_plugins": []
406
+ }), 200 # 返回200但包含错误信息和备用工作流
407
+
408
+ result = response.json()
409
+ content = result['choices'][0]['message']['content']
410
+
411
+ except Exception as api_error:
412
+ return jsonify({
413
+ "success": False,
414
+ "message": f"无法连接到AI模型服务: {str(api_error)}",
415
+ "workflow": create_default_workflow(),
416
+ "recommended_knowledge_bases": [],
417
+ "recommended_plugins": []
418
+ }), 200
419
+
420
+ # 查找JSON部分
421
+ import re
422
+ json_match = re.search(r'```json\n([\s\S]*?)\n```', content)
423
+
424
+ if json_match:
425
+ workflow_json = json_match.group(1)
426
+ else:
427
+ # 尝试直接解析整个内容
428
+ workflow_json = content
429
+
430
+ # 解析JSON
431
+ try:
432
+ result_data = json.loads(workflow_json)
433
+ except:
434
+ # 如果解析失败,使用正则表达式清理
435
+ workflow_json = re.sub(r'```json\n|\n```', '', content)
436
+ try:
437
+ result_data = json.loads(workflow_json)
438
+ except:
439
+ # 如果仍然解析失败,提取标准的JSON结构 { ... }
440
+ import re
441
+ json_patterns = re.findall(r'\{[\s\S]*?\}', content)
442
+ if json_patterns:
443
+ try:
444
+ # 尝试解析最长的JSON结构
445
+ longest_json = max(json_patterns, key=len)
446
+ result_data = json.loads(longest_json)
447
+ except:
448
+ # 仍然失败,返回默认值
449
+ return jsonify({
450
+ "success": True,
451
+ "message": "使用默认工作流(AI生成的JSON无效)",
452
+ "workflow": create_default_workflow(),
453
+ "recommended_knowledge_bases": [],
454
+ "recommended_plugins": []
455
+ })
456
+ else:
457
+ # 没有找到有效的JSON结构
458
+ return jsonify({
459
+ "success": True,
460
+ "message": "使用默认工作流(未找到JSON结构)",
461
+ "workflow": create_default_workflow(),
462
+ "recommended_knowledge_bases": [],
463
+ "recommended_plugins": []
464
+ })
465
+
466
+ # 提取推荐的知识库和插件
467
+ recommended_knowledge_bases = result_data.get("recommended_knowledge_bases", [])
468
+ recommended_plugins = result_data.get("recommended_plugins", [])
469
+ workflow = result_data.get("workflow", create_default_workflow())
470
+
471
+ # 验证推荐的知识库都存在
472
+ valid_knowledge_bases = []
473
+ for kb in recommended_knowledge_bases:
474
+ if kb in available_knowledge_bases:
475
+ valid_knowledge_bases.append(kb)
476
+
477
+ # 验证推荐的插件都存在
478
+ valid_plugins = []
479
+ for plugin in recommended_plugins:
480
+ if plugin in available_plugins:
481
+ valid_plugins.append(plugin)
482
+
483
+ return jsonify({
484
+ "success": True,
485
+ "workflow": workflow,
486
+ "recommended_knowledge_bases": valid_knowledge_bases,
487
+ "recommended_plugins": valid_plugins,
488
+ "message": "已成功创建工作流"
489
+ })
490
+
491
+ except Exception as e:
492
+ import traceback
493
+ traceback.print_exc()
494
+ return jsonify({
495
+ "success": False,
496
+ "message": str(e)
497
+ }), 500
498
+
499
+ def create_default_workflow():
500
+ """创建一个默认的空工作流"""
501
+ return {
502
+ "nodes": [],
503
+ "edges": []
504
  }