272 lines
9.5 KiB
Python
Executable File
272 lines
9.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
从教程信息快速生成任务定义
|
||
用法:
|
||
python scripts/tools/extract_task_from_tutorial.py
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
# 添加项目根目录到路径
|
||
project_root = Path(__file__).parent.parent.parent
|
||
sys.path.insert(0, str(project_root))
|
||
|
||
from scripts.tools.init_task import init_task
|
||
|
||
|
||
# 任务类别和难度映射
|
||
CATEGORY_MAP = {
|
||
"1": "basic_processing",
|
||
"2": "peak_analysis",
|
||
"3": "phase_identification",
|
||
"4": "crystal_parameters",
|
||
"5": "calibration",
|
||
"6": "advanced_analysis",
|
||
}
|
||
|
||
DIFFICULTY_MAP = {
|
||
"1": "easy",
|
||
"2": "medium",
|
||
"3": "hard",
|
||
}
|
||
|
||
# 常见任务模板
|
||
TASK_TEMPLATES = {
|
||
"basic_processing": {
|
||
"open_file": "请打开桌面上的 {filename} 文件。",
|
||
"smooth": "请打开桌面上的 {filename} 文件,进行平滑处理 (Smoothing),然后将处理后的曲线导出为 ASCII (.txt) 文件并命名为 {output}。",
|
||
"background": "请打开桌面上的 {filename} 文件,进行背景扣除 (Background Removal),然后将处理后的曲线导出为 ASCII (.txt) 文件并命名为 {output}。",
|
||
"export": "请打开桌面上的 {filename} 文件,将当前曲线导出为 ASCII (.txt) 文件并命名为 {output}。",
|
||
},
|
||
"peak_analysis": {
|
||
"peak_search": "请打开桌面上的 {filename} 文件,进行寻峰操作 (Peak Search),并导出寻峰结果文件 {output}。",
|
||
"peak_separation": "请打开桌面上的 {filename} 文件,进行多峰分离操作 (Peak Separation),并导出结果文件 {output}。",
|
||
"peak_fitting": "请打开桌面上的 {filename} 文件,进行峰形拟合 (Peak Fitting),并导出结果文件 {output}。",
|
||
},
|
||
"phase_identification": {
|
||
"phase_search": "请打开桌面上的 {filename} 文件,进行物相检索 (Phase Search),并导出检索结果文件 {output}。",
|
||
"quantitative": "请打开桌面上的 {filename} 文件,进行物相定量分析 (Quantitative Analysis),并导出结果文件 {output}。",
|
||
},
|
||
"crystal_parameters": {
|
||
"lattice_constant": "请打开桌面上的 {filename} 文件,精确测定晶格常数 (Lattice Constant),并导出结果文件 {output}。",
|
||
"crystal_size": "请打开桌面上的 {filename} 文件,使用Scherrer公式计算晶粒大小 (Crystal Size),并导出结果文件 {output}。",
|
||
"stress": "请打开桌面上的 {filename} 文件,进行残余应力分析 (Stress Analysis),并导出结果文件 {output}。",
|
||
"crystallinity": "请打开桌面上的 {filename} 文件,计算结晶化度 (Crystallinity),并导出结果文件 {output}。",
|
||
},
|
||
}
|
||
|
||
|
||
def print_category_menu():
|
||
"""打印类别菜单"""
|
||
print("\n📚 任务类别:")
|
||
print(" 1. basic_processing (基础处理)")
|
||
print(" 2. peak_analysis (峰分析)")
|
||
print(" 3. phase_identification (物相检索)")
|
||
print(" 4. crystal_parameters (晶体参数)")
|
||
print(" 5. calibration (校正)")
|
||
print(" 6. advanced_analysis (高级分析)")
|
||
|
||
|
||
def print_difficulty_menu():
|
||
"""打印难度菜单"""
|
||
print("\n📊 难度等级:")
|
||
print(" 1. easy (简单,3-5步操作)")
|
||
print(" 2. medium (中等,5-10步操作)")
|
||
print(" 3. hard (困难,10+步操作)")
|
||
|
||
|
||
def get_user_input():
|
||
"""交互式获取用户输入"""
|
||
print("=" * 60)
|
||
print("🎯 从教程提取任务 - 快速生成工具")
|
||
print("=" * 60)
|
||
|
||
# 任务ID
|
||
task_id = input("\n📝 任务ID (例如: peak_search_001): ").strip()
|
||
if not task_id:
|
||
print("❌ 任务ID不能为空")
|
||
return None
|
||
|
||
# 类别
|
||
print_category_menu()
|
||
category_choice = input("\n选择类别 (1-6): ").strip()
|
||
category = CATEGORY_MAP.get(category_choice)
|
||
if not category:
|
||
print("❌ 无效的类别选择")
|
||
return None
|
||
|
||
# 难度
|
||
print_difficulty_menu()
|
||
difficulty_choice = input("\n选择难度 (1-3): ").strip()
|
||
difficulty = DIFFICULTY_MAP.get(difficulty_choice)
|
||
if not difficulty:
|
||
print("❌ 无效的难度选择")
|
||
return None
|
||
|
||
# 输入文件
|
||
print("\n📁 输入文件配置:")
|
||
source_file = input(" 源文件路径 (相对于data/source/, 例如: DEMO01.MDI): ").strip()
|
||
if not source_file:
|
||
source_file = "DEMO01.MDI"
|
||
|
||
# 输出文件
|
||
print("\n📤 输出文件配置:")
|
||
output_filename = input(" 输出文件名 (例如: result.txt): ").strip()
|
||
if not output_filename:
|
||
output_filename = "result.txt"
|
||
|
||
# 任务类型(如果类别有模板)
|
||
task_type = None
|
||
if category in TASK_TEMPLATES:
|
||
templates = TASK_TEMPLATES[category]
|
||
print(f"\n📋 可用任务模板 ({category}):")
|
||
for i, (key, template) in enumerate(templates.items(), 1):
|
||
print(f" {i}. {key}")
|
||
|
||
use_template = input("\n使用模板? (y/n, 默认n): ").strip().lower()
|
||
if use_template == 'y':
|
||
template_choice = input(f"选择模板 (1-{len(templates)}): ").strip()
|
||
try:
|
||
template_key = list(templates.keys())[int(template_choice) - 1]
|
||
task_type = template_key
|
||
except (ValueError, IndexError):
|
||
print("⚠️ 无效的模板选择,将使用自定义指令")
|
||
|
||
# 指令
|
||
if task_type and category in TASK_TEMPLATES:
|
||
# 使用模板
|
||
template = TASK_TEMPLATES[category][task_type]
|
||
instruction = template.format(
|
||
filename=os.path.basename(source_file),
|
||
output=output_filename
|
||
)
|
||
print(f"\n✅ 生成的指令 (模板): {instruction}")
|
||
confirm = input("使用此指令? (y/n, 默认y): ").strip().lower()
|
||
if confirm == 'n':
|
||
instruction = input("\n📝 自定义指令: ").strip()
|
||
else:
|
||
# 自定义指令
|
||
instruction = input("\n📝 任务指令 (中文描述): ").strip()
|
||
|
||
if not instruction:
|
||
print("❌ 指令不能为空")
|
||
return None
|
||
|
||
# 教程来源(可选)
|
||
tutorial_source = input("\n📚 教程来源 (可选,例如: 教程(1)): ").strip()
|
||
|
||
return {
|
||
"task_id": task_id,
|
||
"category": category,
|
||
"difficulty": difficulty,
|
||
"instruction": instruction,
|
||
"source_file": source_file,
|
||
"output_filename": output_filename,
|
||
"tutorial_source": tutorial_source,
|
||
}
|
||
|
||
|
||
def create_task_from_info(info):
|
||
"""根据信息创建任务"""
|
||
task_id = info["task_id"]
|
||
category = info["category"]
|
||
difficulty = info["difficulty"]
|
||
instruction = info["instruction"]
|
||
|
||
# 构建源文件路径
|
||
source_file = info["source_file"]
|
||
if not os.path.isabs(source_file):
|
||
# 相对路径,假设在 data/source/ 下
|
||
source_file = f"../../data/source/{source_file}"
|
||
|
||
# 构建VM路径
|
||
filename = os.path.basename(source_file)
|
||
inject_to = f"C:\\Users\\lzy\\Desktop\\{filename}"
|
||
|
||
# 输出文件路径
|
||
output_filename = info["output_filename"]
|
||
collect_from = f"C:\\Users\\lzy\\Desktop\\{output_filename}"
|
||
|
||
print(f"\n🚀 正在创建任务: {task_id}")
|
||
print(f" 类别: {category}")
|
||
print(f" 难度: {difficulty}")
|
||
print(f" 源文件: {source_file}")
|
||
print(f" 输出文件: {output_filename}")
|
||
|
||
# 调用 init_task
|
||
try:
|
||
init_task(
|
||
task_id=task_id,
|
||
category=category,
|
||
difficulty=difficulty,
|
||
instruction=instruction,
|
||
project_root=str(project_root)
|
||
)
|
||
|
||
# 更新 task.json
|
||
task_json_path = project_root / "tasks" / task_id / "task.json"
|
||
if task_json_path.exists():
|
||
with open(task_json_path, 'r', encoding='utf-8') as f:
|
||
task_config = json.load(f)
|
||
|
||
# 更新输入输出配置
|
||
task_config["input"] = {
|
||
"source_file": source_file,
|
||
"inject_to": inject_to
|
||
}
|
||
task_config["output"] = {
|
||
"expected_file": output_filename,
|
||
"collect_from": collect_from
|
||
}
|
||
|
||
# 添加教程来源(如果有)
|
||
if info.get("tutorial_source"):
|
||
task_config["tutorial_source"] = info["tutorial_source"]
|
||
|
||
# 保存
|
||
with open(task_json_path, 'w', encoding='utf-8') as f:
|
||
json.dump(task_config, f, ensure_ascii=False, indent=2)
|
||
|
||
print(f"\n✅ 任务创建成功!")
|
||
print(f" 任务目录: tasks/{task_id}/")
|
||
print(f" 配置文件: tasks/{task_id}/task.json")
|
||
print(f"\n📝 下一步:")
|
||
print(f" 1. 检查并完善 task.json")
|
||
print(f" 2. 运行: python scripts/tools/collect_task.py {task_id} --mode full")
|
||
|
||
return True
|
||
else:
|
||
print(f"❌ 任务目录创建失败: {task_json_path}")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"❌ 创建任务时出错: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
try:
|
||
info = get_user_input()
|
||
if info:
|
||
create_task_from_info(info)
|
||
else:
|
||
print("\n❌ 任务创建取消")
|
||
except KeyboardInterrupt:
|
||
print("\n\n⚠️ 用户取消操作")
|
||
except Exception as e:
|
||
print(f"\n❌ 发生错误: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
|