diff --git a/config/agent_submit_template.txt b/config/agent_submit_template.txt new file mode 100644 index 0000000..ee41402 --- /dev/null +++ b/config/agent_submit_template.txt @@ -0,0 +1,58 @@ +## 任务背景 + +### 产品基本信息 +- **产品名称:** {{product_name}} +- **产品类别:** {{category}} +- **子类别:** {{subcategory}} + +### 待提交的产品数据 +上一步已通过格式检查,生成了以下产品数据: +```json +{{product_data}} +``` + +## 任务要求 + +请将上述产品数据提交到 ParamHub 审核系统。 + +### 1. 确定提交接口 +根据产品类别({{category}})选择对应的 API 接口: +- AI模型 → `POST /api/models` +- GPU → `POST /api/gpus` +- CPU → `POST /api/cpus` +- 其他动态分类 → `POST /api/items/{category_id}` + +### 2. 提交数据 +使用以下命令提交数据: + +```bash +# 先登录获取cookie +curl -c /tmp/paramhub_cookie.txt -X POST "http://localhost:16041/login" \ + -H "Content-Type: application/json" \ + -d '{"password": "admin123"}' + +# 提交产品数据(根据类别选择对应的API) +curl -b /tmp/paramhub_cookie.txt -X POST "http://localhost:16041/api/{对应类别API}" \ + -H "Content-Type: application/json" \ + -d '{{product_data}}' +``` + +### 3. 输出要求 +请以JSON格式输出提交结果: +```json +{ + "success": true, + "review_id": "审核ID", + "message": "提交说明", + "submitted_data": { + "name": "产品名称", + "field1": "值1", + "field2": "值2" + } +} +``` + +**注意:** +- 确保提交的数据格式正确 +- 记录返回的 review_id +- 如果提交失败,说明错误原因 diff --git a/routes/process_monitor.py b/routes/process_monitor.py index d14e12e..5d3f990 100644 --- a/routes/process_monitor.py +++ b/routes/process_monitor.py @@ -338,3 +338,84 @@ def preview_fill_fields_template(): except Exception as e: logger.error(f"预览填充字段模板失败: {e}") return jsonify({'success': False, 'error': str(e)}), 500 + + +# ===== 步骤6提交审核模板 API ===== + +SUBMIT_TEMPLATE_FILE = os.path.join(TEMPLATE_DIR, 'agent_submit_template.txt') + + +@bp.route('/submit-template', methods=['GET']) +def get_submit_template(): + """获取步骤6提交审核任务文本模板""" + try: + if os.path.exists(SUBMIT_TEMPLATE_FILE): + with open(SUBMIT_TEMPLATE_FILE, 'r', encoding='utf-8') as f: + template = f.read() + return jsonify({ + 'success': True, + 'template': template + }) + else: + return jsonify({ + 'success': False, + 'error': '模板文件不存在' + }), 404 + except Exception as e: + logger.error(f"获取提交模板失败: {e}") + return jsonify({'success': False, 'error': str(e)}), 500 + + +@bp.route('/submit-template', methods=['POST']) +def save_submit_template(): + """保存步骤6提交审核任务文本模板""" + try: + data = request.get_json() + template = data.get('template', '') + + if not template: + return jsonify({'success': False, 'error': '模板内容不能为空'}), 400 + + os.makedirs(TEMPLATE_DIR, exist_ok=True) + with open(SUBMIT_TEMPLATE_FILE, 'w', encoding='utf-8') as f: + f.write(template) + + return jsonify({ + 'success': True, + 'message': '模板已保存' + }) + except Exception as e: + logger.error(f"保存提交模板失败: {e}") + return jsonify({'success': False, 'error': str(e)}), 500 + + +@bp.route('/submit-template/preview', methods=['POST']) +def preview_submit_template(): + """预览填充后的步骤6任务文本""" + try: + data = request.get_json() + product_name = data.get('product_name', '示例产品') + category = data.get('category', '示例类别') + subcategory = data.get('subcategory', '示例子类别') + product_data = data.get('product_data', '{"name": "示例产品", "visible": true}') + + # 读取模板 + if os.path.exists(SUBMIT_TEMPLATE_FILE): + with open(SUBMIT_TEMPLATE_FILE, 'r', encoding='utf-8') as f: + template = f.read() + else: + return jsonify({'success': False, 'error': '模板文件不存在'}), 404 + + # 填充示例数据 + filled = template.replace('{{product_name}}', product_name) + filled = filled.replace('{{category}}', category) + filled = filled.replace('{{subcategory}}', subcategory or '无') + filled = filled.replace('{{product_data}}', product_data) + + return jsonify({ + 'success': True, + 'preview': filled + }) + except Exception as e: + logger.error(f"预览提交模板失败: {e}") + return jsonify({'success': False, 'error': str(e)}), 500 diff --git a/services/process_monitor.py b/services/process_monitor.py index 36a5bb3..5ec41fb 100644 --- a/services/process_monitor.py +++ b/services/process_monitor.py @@ -22,7 +22,7 @@ PROCESS_STEPS = [ {'num': 3, 'name': '抓取网页内容', 'description': '抓取搜索结果网页的详细内容'}, {'num': 4, 'name': '提取产品数据(智能体)', 'description': '调用hz4th_editor智能体提取产品相关内容'}, {'num': 5, 'name': '填充字段(智能体)', 'description': '调用智能体生成产品数据并检查格式'}, - {'num': 6, 'name': '提交审核', 'description': '提交到ParamHub待审核区'}, + {'num': 6, 'name': '提交审核(智能体)', 'description': '调用智能体将产品数据提交到ParamHub审核系统'}, ] class ProcessMonitor: @@ -276,38 +276,59 @@ class ProcessMonitor: except Exception as e: self._fail_step(session_id, 5, str(e)) - # 步骤6: 提交审核 + # 步骤6: 提交审核(调用智能体执行) if not self._check_pause(session_id) and all_data['filled_data']: - self._start_step(session_id, product_name, 6, '提交审核') + self._start_step(session_id, product_name, 6, '提交审核(智能体)') try: - category_type = self._get_category_type(category) - success, review_id_or_error = paramhub_client.submit_for_review( - category_type, - all_data['filled_data'], - subcategory + # 构建任务文本 + submit_task_text = self._build_submit_task( + product_name, category, subcategory, all_data['filled_data'] ) - if success: - self._complete_step(session_id, 6, {'review_id': review_id_or_error}) - result['success'] = True - result['review_id'] = review_id_or_error + # 调用智能体 + submit_agent_result = self._call_agent(submit_task_text) + + if submit_agent_result.get('success'): + submit_parsed = self._parse_submit_agent_response(submit_agent_result.get('output', '')) - db.update_session_status(session_id, 'completed', - review_id=review_id_or_error, - result=json.dumps(result, ensure_ascii=False)) - - db.add_process_history( - product_name=product_name, - category=category, - subcategory=subcategory, - status='submitted', - review_id=review_id_or_error, - details=all_data - ) - logger.info(f"[{session_id}] 步骤6完成: 提交成功") + if submit_parsed and submit_parsed.get('success'): + review_id = submit_parsed.get('review_id') + + if review_id: + self._complete_step(session_id, 6, { + 'submitted': True, + 'agent': 'hz4th_editor', + 'task_text': submit_task_text, + 'review_id': review_id, + 'agent_output': submit_agent_result.get('output', '')[:2000] + }) + + result['success'] = True + result['review_id'] = review_id + + db.update_session_status(session_id, 'completed', + review_id=review_id, + result=json.dumps(result, ensure_ascii=False)) + + db.add_process_history( + product_name=product_name, + category=category, + subcategory=subcategory, + status='submitted', + review_id=review_id, + details=all_data + ) + logger.info(f"[{session_id}] 步骤6完成: 智能体提交成功, review_id={review_id}") + else: + self._fail_step(session_id, 6, '智能体未返回review_id') + result['message'] = '智能体提交成功但未获取到review_id' + else: + error_msg = submit_parsed.get('message', '未知错误') if submit_parsed else '解析失败' + self._fail_step(session_id, 6, f"智能体提交失败: {error_msg}") + result['message'] = f'智能体提交失败: {error_msg}' else: - self._fail_step(session_id, 6, review_id_or_error) - db.update_session_status(session_id, 'failed') + self._fail_step(session_id, 6, f"智能体调用失败: {submit_agent_result.get('error', '未知错误')}") + result['message'] = f'智能体调用失败: {submit_agent_result.get("error")}' except Exception as e: self._fail_step(session_id, 6, str(e)) @@ -685,6 +706,80 @@ class ProcessMonitor: 'warnings': warnings } + def _build_submit_task(self, product_name, category, subcategory, product_data): + """构建步骤6提交审核的智能体任务文本""" + # 读取模板 + template_file = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + 'config', 'agent_submit_template.txt' + ) + + if os.path.exists(template_file): + with open(template_file, 'r', encoding='utf-8') as f: + template = f.read() + else: + # 默认模板 + template = ( + "请将以下产品数据提交到ParamHub审核系统。\n" + "产品名称: {{product_name}}\n" + "类别: {{category}} / {{subcategory}}\n\n" + "产品数据:\n{{product_data}}\n\n" + "使用curl命令提交,并记录返回的review_id。" + ) + + # 填充模板 + task = template.replace('{{product_name}}', product_name or '未知') + task = task.replace('{{category}}', category or '未分类') + task = task.replace('{{subcategory}}', subcategory or '无') + task = task.replace('{{product_data}}', json.dumps(product_data, ensure_ascii=False, indent=2)) + + return task + + def _parse_submit_agent_response(self, output): + """解析步骤6智能体返回的结果""" + if not output: + return None + + import re + + parsed_data = None + + # 查找JSON块 + json_match = re.search(r'```(?:json)?\s*(\{.*?\})\s*```', output, re.DOTALL) + if json_match: + try: + parsed_data = json.loads(json_match.group(1)) + except json.JSONDecodeError: + pass + + # 尝试直接解析整个输出为JSON + if not parsed_data: + try: + parsed_data = json.loads(output) + except json.JSONDecodeError: + pass + + if parsed_data: + return { + 'success': parsed_data.get('success', False), + 'review_id': parsed_data.get('review_id'), + 'message': parsed_data.get('message', ''), + 'submitted_data': parsed_data.get('submitted_data', {}), + 'raw_output': output + } + + # 尝试从文本中提取review_id + review_match = re.search(r'review[_-]?id[\s:]*([\w-]+)', output, re.I) + if review_match: + return { + 'success': True, + 'review_id': review_match.group(1), + 'message': '从输出中提取到review_id', + 'raw_output': output + } + + return None + def _extract_data(self, product_name, all_data): """提取产品数据(备用,已被智能体替代)""" all_content = [] diff --git a/static/js/process.js b/static/js/process.js index d6ba85a..6d3e6fd 100644 --- a/static/js/process.js +++ b/static/js/process.js @@ -11,6 +11,7 @@ document.addEventListener('DOMContentLoaded', () => { loadHistory(); loadAgentTemplate(); loadFillFieldsTemplate(); + loadSubmitTemplate(); // 启动自动刷新(每2秒) startAutoRefresh(); @@ -588,3 +589,90 @@ async function doFillFieldsPreview() { document.getElementById('template-preview-content').textContent = '预览失败: ' + error.message; } } + +// ===== 步骤6提交审核模板 ===== + +// 加载步骤6模板 +async function loadSubmitTemplate() { + try { + const response = await fetch(`${API_BASE}/api/process/submit-template`); + const data = await response.json(); + + if (data.success) { + document.getElementById('submit-template-editor').value = data.template; + } else { + document.getElementById('submit-template-editor').value = '// 模板加载失败: ' + (data.error || '未知错误'); + } + } catch (error) { + console.error('加载提交模板失败:', error); + document.getElementById('submit-template-editor').value = '// 加载模板失败: ' + error.message; + } +} + +// 保存步骤6模板 +async function saveSubmitTemplate() { + const template = document.getElementById('submit-template-editor').value; + + if (!template.trim()) { + showToast('模板内容不能为空', 'error'); + return; + } + + try { + const response = await fetch(`${API_BASE}/api/process/submit-template`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ template }) + }); + const data = await response.json(); + + if (data.success) { + showToast('步骤6模板已保存 ✓', 'success'); + } else { + showToast('保存失败: ' + data.error, 'error'); + } + } catch (error) { + showToast('保存失败: ' + error.message, 'error'); + } +} + +// 预览步骤6模板 +function previewSubmitTemplate() { + document.getElementById('template-preview-modal').classList.add('active'); + doSubmitPreview(); +} + +// 执行步骤6预览 +async function doSubmitPreview() { + const product = document.getElementById('preview-product').value || '示例产品'; + const category = document.getElementById('preview-category').value || 'AI模型'; + + try { + const response = await fetch(`${API_BASE}/api/process/submit-template/preview`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + product_name: product, + category: category, + subcategory: '', + product_data: JSON.stringify({ + "name": product, + "organization": "示例组织", + "parameters": "70B", + "context_length": 4096, + "visible": true, + "is_pinned": false + }, null, 2) + }) + }); + const data = await response.json(); + + if (data.success) { + document.getElementById('template-preview-content').textContent = data.preview; + } else { + document.getElementById('template-preview-content').textContent = '预览失败: ' + data.error; + } + } catch (error) { + document.getElementById('template-preview-content').textContent = '预览失败: ' + error.message; + } +} diff --git a/templates/process.html b/templates/process.html index a4b3fd5..1681219 100644 --- a/templates/process.html +++ b/templates/process.html @@ -81,7 +81,7 @@
-

步骤5:填充字段并提交 - 智能体任务模板

+

步骤5:填充字段 - 智能体任务模板

-

说明:此模板用于步骤5「填充字段并提交审核」中调用智能体 hz4th_editor 的任务文本。

+

说明:此模板用于步骤5「填充字段」中调用智能体 hz4th_editor 的任务文本。

可用变量: {{product_name}} 产品名称、 {{category}} 类别、 {{subcategory}} 子类别、 {{relevant_content_ids}} 上一步筛选的相关内容数据ID

-

任务目标:智能体根据API文档获取字段定义,整理产品参数,并通过API提交到ParamHub审核系统。

+

任务目标:智能体根据API文档获取字段定义,整理产品参数,并进行格式检查。

+ +
+
+

步骤6:提交审核 - 智能体任务模板

+
+ + +
+
+
+
+

说明:此模板用于步骤6「提交审核」中调用智能体 hz4th_editor 的任务文本。

+

可用变量: + {{product_name}} 产品名称、 + {{category}} 类别、 + {{subcategory}} 子类别、 + {{product_data}} 上一步生成的产品数据(JSON格式) +

+

任务目标:智能体将产品数据提交到ParamHub审核系统,获取review_id。

+
+ +
+
+