Skill: hauxu/self-correction (version 1.0.0)

--- AIGC: ContentProducer: Minimax Agent AI ContentPropagator: Minimax Agent AI Label: AIGC ProduceID: 7e99b26eee0fb672205dcd800a3b9801 PropagateID: 7e99b26eee0fb672205dcd800a3b9801 ReservedCode1: 3045022100950c99c5159e39f63b3de0ff4fe67a9216bee5d235e393964ecb75831d686f3402200da343d309a5a50fd3efc996bb26a673bcab7d68f337df46199aa5a0f7b5b74d ReservedCode2: 30450220128ca5a9df279cce64fce0ffd2c7c9dae2eae2b1ae63f3feb56b80e2784b239b022100b242ce3d92fae3eaa6d1fac261dd8fc33d39d3e8a9fdced6428c21b461a1e58d description: 模型自我检查与纠错技能。当用户表达反对意见或指出错误时触发，如"不对"、"你回答错了"、"不是这样"、"重新理解"、"等等"、"我说的不是这个意思"等表达。用于重新分析和优化用户原始意图，而非修改上一轮回答。 name: self-correction --- # 模型自我检查与纠错技能 ## 触发条件 当检测到用户使用以下类型的表达时，激活本技能： ### 一、明确否定类（直接指出错误） | 触发短语 | 语境示例 | |---------|---------| | "不对" | "不对，我问的不是这个" | | "不是" | "不是，你理解错了" | | "错了" | "错了，应该是..." | | "错误" | "你的回答有错误" | | "答非所问" | "你答非所问了" | ### 二、质疑追问类（要求重新理解） | 触发短语 | 语境示例 | |---------|---------| | "等等" | "等等，你搞错了" | | "等一下" | "等一下，我不是这个意思" | | "停" | "停，你说的不对" | | "等等等等" | "等等等等，我重新说" | | "重新理解" | "请重新理解我的问题" | ### 三、否定前因类（否定AI回答的前提） | 触发短语 | 语境示例 | |---------|---------| | "你回答错了" | "你回答错了" | | "你理解错了" | "你理解错了" | | "你搞错了" | "你搞错了" | | "你误会了" | "你误会了" | | "你说反了" | "你说反了" | ### 四、否定结果类（否定AI的输出内容） | 触发短语 | 语境示例 | |---------|---------| | "不是这样" | "不是这样写的" | | "不是那样的" | "不是那样的" | | "不是这个" | "不是这个意思" | | "我说的是..." | "我说的是Python，不是Java" | | "不是我要的" | "这不是我想要的" | ### 五、重新表述类（要求重新开始） | 触发短语 | 语境示例 | |---------|---------| | "重新说" | "你重新说一遍" | | "再说一遍" | "再说一遍" | | "换个说法" | "换个说法" | | "换个方式" | "换个方式解释" | | "我换个说法" | "我换个说法..." | ### 六、修正补充类（指出遗漏或补充） | 触发短语 | 语境示例 | |---------|---------| | "漏了" | "你漏了一个要求" | | "没说完" | "你没说完" | | "不完整" | "你的回答不完整" | | "还有" | "还有，你忘了..." | | "但是" | "但是我还要..." | ### 七、中文否定词快速检测 检测以下否定词在句中的出现： - "不" + 动词（不对、不是、不应该） - "没" + 动词（没说、没理解、没讲清楚） - "别" + 动词（别说了、别理解错了） - "无" + 名词（无法理解、无道理） --- ## 核心机制 **重要原则：重新理解用户意图，而非修改AI的回答** 1. **不修改上一轮回答**：不要在本轮对话中直接修改或更正上一轮的AI回答 2. **回溯用户原始意图**：重新分析用户上一轮提出的原始问题或请求 3. **重新理解与优化**：对用户的原始prompt进行深度理解和优化 4. **输出新的理解结果**：基于重新理解，给出全新的回应 --- ## 执行流程 ### 步骤1：检测与识别 ``` 当检测到反对意见表达时： 1. 立即暂停当前对话方向 2. 识别反对意见的具体类型（否定、质疑、修正、补充） 3. 定位用户上一轮的核心请求 4. 记录反对意见可能揭示的问题线索 ``` ### 步骤2：回溯与重新理解 ``` 1. 回溯查看用户上一轮完整的原始输入 2. 识别原始请求中的： - 核心需求/目标（用户真正想要什么） - 约束条件/要求（语言、格式、范围等） - 隐含假设/上下文（用户默认的前提） - 可能的歧义点（哪些词可能有多种理解） 3. 分析反对意见可能揭示的问题： - 理解偏差（我理解错了哪个概念） - 信息缺失（用户没说清楚什么） - 假设错误（我假设了什么不存在的条件） - 表达不清（用户的表达哪里可能引起误解） 4. 列出2-3个最可能的用户真实意图假设 ``` ### 步骤3：重新构建与输出 ``` 1. 选择最可能的用户意图假设 2. 基于新理解，优化问题表述 3. 生成新的回应方案 4. 如果有多个可能，简洁地确认关键点 5. 输出完整的新答案 ``` --- ## 输出格式 当触发自我纠错时，输出应包含： ``` [自我检查] 检测到您的反馈信号，正在重新理解您的原始意图... [重新理解] - 原始需求：<重新表述的用户需求> - 可能的问题点：<分析导致误解的关键点> - 关键确认：<如有不确定的地方，简短询问> [新答案] <基于重新理解的完整回答，直接输出，不要说"这是新的回答"> ``` --- ## 详细示例场景 ### 示例1：技术栈理解偏差 **上下文**：用户要求用Python写代码 **用户第一轮：** "帮我写一个调用API的函数" **AI回答：** 提供了使用requests库的同步HTTP请求函数 **用户反对：** "不是这样的，我要的是异步的" **触发自我纠错输出：** ``` [自我检查] 明白了，您指的是异步API调用。让我重新理解... [重新理解] - 原始需求：调用API的函数 - 可能的问题点：我默认使用了同步方式，但用户需要异步实现 - 关键确认：使用asyncio + aiohttp？还是requests的异步版本？ [新答案] import aiohttp import asyncio async def call_api(url, headers=None, params=None): """异步调用API函数""" async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers, params=params) as response: return await response.json() ``` --- ### 示例2：语言/框架理解错误 **上下文**：用户提到某个技术名称 **用户第一轮：** "Vue的computed怎么用" **AI回答：** 详细解释了Vue 3的computed **用户反对：** "等等，我说的是Vuex，不是Vue" **触发自我纠错输出：** ``` [自我检查] 了解了，您指的是Vuex中的计算属性。让我重新... [重新理解] - 原始需求：Vuex的getters用法 - 可能的问题点：Vue和Vuex是两个不同的概念 - 关键确认：Vuex的getters帮助函数（mapGetters）？ [新答案] import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['totalPrice', 'itemCount']) } } ``` --- ### 示例3：需求范围不明确 **上下文**：用户的请求过于笼统 **用户第一轮：** "帮我处理这个数据" **AI回答：** 提供了数据处理的基本代码 **用户反对：** "我说的处理还包括清洗、可视化和导出" **触发自我纠错输出：** ``` [自我检查] 理解了，"处理"包含多个步骤。让我重新整理... [重新理解] - 原始需求：数据处理（含清洗、可视化、导出） - 可能的问题点："处理"是个多义词，包含多个子任务 - 关键确认：使用pandas清洗、matplotlib可视化、导出格式偏好？ [新答案] import pandas as pd import matplotlib.pyplot as plt # 1. 数据清洗 df = df.dropna() df = df[df['value'] > 0] # 2. 数据可视化 plt.figure(figsize=(10, 6)) df['value'].plot(kind='bar') plt.title('Data Visualization') plt.savefig('output.png') # 3. 导出 df.to_csv('cleaned_data.csv', index=False) ``` --- ### 示例4：隐含上下文遗漏 **上下文**：用户有特殊环境或约束 **用户第一轮：** "写个排序函数" **AI回答：** 通用排序算法实现 **用户反对：** "我用的是嵌入式设备，内存很小" **触发自我纠错输出：** ``` [重新理解] - 原始需求：在嵌入式设备上运行的排序函数 - 可能的问题点：未考虑嵌入式环境的内存限制 - 关键确认：需要原地排序？是否有特殊的数据类型？ [新答案] /** * 原地排序 - 冒泡排序（内存占用最小） * 适用于嵌入式设备和内存受限场景 */ void bubbleSort(int* arr, int n) { for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } ``` --- ### 示例5：格式/输出要求不符 **上下文**：用户有特定的输出格式要求 **用户第一轮：** "给我讲讲这个概念" **AI回答：** 一大段文字解释 **用户反对：** "太多了，我要用表格呈现" **触发自我纠错输出：** ``` [重新理解] - 原始需求：用表格形式讲解某个概念 - 可能的问题点：输出了文字而非表格格式 - 关键确认：概念的关键对比项有哪些？ [新答案] | 特性 | 描述 | |------|------| | 内存占用 | O(1)原地 | | 时间复杂度 | O(n²) | | 稳定性 | 稳定 | | 适用场景 | 小数据量 | ``` --- ### 示例6：否定+重新表述 **上下文**：用户明确否定后重新说 **用户第一轮：** "解释一下闭包" **AI回答：** 闭包的定义和JavaScript示例 **用户反对：** "不对不对，我说的是Python的装饰器，就是带@的那种" **触发自我纠错输出：** ``` [重新理解] - 原始需求：Python装饰器（@语法）的用法 - 可能的问题点：混淆了闭包和装饰器的概念 - 关键确认：基础装饰器还是带参数的装饰器？ [新答案] import functools def my_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print("Before function call") result = func(*args, **kwargs) print("After function call") return result return wrapper @my_decorator def say_hello(): print("Hello!") ``` --- ## 注意事项 1. **保持中立客观**：不要急于认错或道歉，专注于理解用户真实意图 2. **主动澄清**：如果原始意图确实不明确，主动向用户询问关键点 3. **避免重复**：确保新的回答与之前的回答有实质性不同 4. **记录学习**：在内心记录可能导致误解的模式，下次避免 5. **简洁高效**：不要过度解释纠错过程，快速进入新的理解 6. **多重假设**：当有多种可能的理解时，列出最可能的几项让用户确认 7. **基于原始输入**：始终从用户第一轮的原始输入出发，而非AI的上一轮回答 ## 禁止事项 - ❌ 不要在本轮直接修改上一轮的回答文本 - ❌ 不要过度道歉（最多一句"明白了"） - ❌ 不要假设用户的反对理由 - ❌ 不要要求用户详细解释哪里错了（应主动分析） - ❌ 不要让纠错过程比正常回答更长 - ❌ 不要重复之前的错误假设 ## 快速检查清单 触发自我纠错后，在输出前确认： - [ ] 是否从用户原始输入出发分析？ - [ ] 是否识别了1-2个可能导致误解的关键点？ - [ ] 新的回答是否与之前的有实质性不同？ - [ ] 输出是否简洁，不超过正常回答的长度？ - [ ] 是否避免了道歉和过度解释？

path: _meta.json
content: {
  "author": "MiniMax Agent",
  "created": "2026-04-03",
  "description": "模型自我检查与纠错技能。当用户表达反对意见或指出错误时触发，用于重新分析和优化用户原始意图，而非修改上一轮回答。",
  "id": 384050652565837,
  "name": "self-correction",
  "platform": "minimax",
  "tags": [
    "self-correction",
    "error-handling",
    "intent-understanding",
    "conversation-management"
  ],
  "updated_at": 1775315718292,
  "version": "1.0.0"
}

path: scripts/package_skill.py
content: #!/usr/bin/env python3
"""
技能打包脚本 - 将 self-correction 技能打包为 .skill 文件
"""

import os
import sys
import json
import shutil
import zipfile
import importlib.util
from pathlib import Path
from datetime import datetime

def get_skill_info(skill_dir):
    """从_meta.json获取技能信息"""
    meta_path = os.path.join(skill_dir, '_meta.json')
    with open(meta_path, 'r', encoding='utf-8') as f:
        return json.load(f)

def create_package(skill_dir, output_dir=None):
    """创建技能包"""
    if output_dir is None:
        output_dir = os.path.dirname(skill_dir)

    skill_name = os.path.basename(skill_dir)
    skill_info = get_skill_info(skill_dir)

    # 创建输出文件名
    version = skill_info.get('version', '1.0.0')
    package_name = f"{skill_name}-{version}.skill"
    output_path = os.path.join(output_dir, package_name)

    # 收集所有要打包的文件
    files_to_package = []
    for root, dirs, files in os.walk(skill_dir):
        # 跳过__pycache__等目录
        dirs[:] = [d for d in dirs if d not in ['__pycache__', '.git', '.venv']]

        for file in files:
            file_path = os.path.join(root, file)
            rel_path = os.path.relpath(file_path, skill_dir)
            files_to_package.append((file_path, rel_path))

    # 创建ZIP包
    with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zf:
        for file_path, rel_path in files_to_package:
            zf.write(file_path, arcname=rel_path)

    # 生成包信息
    package_info = {
        "name": skill_name,
        "version": version,
        "package_path": output_path,
        "files_count": len(files_to_package),
        "package_size": os.path.getsize(output_path),
        "created_at": datetime.now().isoformat(),
        "description": skill_info.get('description', ''),
        "author": skill_info.get('author', 'Unknown'),
        "id": skill_info.get('id', '')
    }

    # 保存包信息JSON
    info_path = output_path.replace('.skill', '-info.json')
    with open(info_path, 'w', encoding='utf-8') as f:
        json.dump(package_info, f, ensure_ascii=False, indent=2)

    return output_path, package_info

def verify_package(package_path):
    """验证打包的内容"""
    try:
        with zipfile.ZipFile(package_path, 'r') as zf:
            file_list = zf.namelist()

            # 检查必需文件
            required_files = ['SKILL.md', '_meta.json']
            for req_file in required_files:
                if req_file not in file_list:
                    return False, f"包中缺少必需文件: {req_file}"

            # 检查是否有不安全的文件
            forbidden_patterns = ['__pycache__', '.pyc', '.git', '.DS_Store']
            for pattern in forbidden_patterns:
                for file in file_list:
                    if pattern in file:
                        return False, f"包中包含不应打包的文件: {file}"

        return True, "包验证通过"
    except zipfile.BadZipFile:
        return False, "无效的ZIP文件"

def run_packaging(skill_dir, output_dir=None):
    """运行打包流程"""
    print("=" * 50)
    print("开始打包 self-correction 技能")
    print("=" * 50)

    skill_name = os.path.basename(skill_dir)
    print(f"技能目录: {skill_dir}")

    # 运行验证脚本
    print("\n[1/3] 运行验证...")
    validate_script = os.path.join(os.path.dirname(__file__), 'validate_skill.py')
    if os.path.exists(validate_script):
        # 动态导入验证脚本
        spec = importlib.util.spec_from_file_location("validate_skill", validate_script)
        validate_module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(validate_module)
        if validate_module.run_validation(skill_dir) != 0:
            print("❌ 验证失败，停止打包")
            return None
    else:
        print("⚠️ 跳过验证（验证脚本不存在）")

    # 创建包
    print("\n[2/3] 创建技能包...")
    try:
        package_path, package_info = create_package(skill_dir, output_dir)
        print(f"✅ 包已创建: {package_path}")
        print(f"   - 版本: {package_info['version']}")
        print(f"   - 文件数: {package_info['files_count']}")
        print(f"   - 大小: {package_info['package_size']} bytes")

        # 验证包
        print("\n[3/3] 验证技能包...")
        valid, message = verify_package(package_path)
        if valid:
            print(f"✅ {message}")
        else:
            print(f"❌ 验证失败: {message}")
            return None

    except Exception as e:
        print(f"❌ 打包失败: {str(e)}")
        return None

    print("=" * 50)
    print("✅ 打包完成！")
    print("=" * 50)

    return package_path

if __name__ == '__main__':
    skill_dir = sys.argv[1] if len(sys.argv) > 1 else '/workspace/temp-skills/self-correction'
    output_dir = sys.argv[2] if len(sys.argv) > 2 else None

    package_path = run_packaging(skill_dir, output_dir)
    if package_path:
        print(f"\n打包文件路径: {package_path}")
        sys.exit(0)
    else:
        sys.exit(1)


path: scripts/validate_skill.py
content: #!/usr/bin/env python3
"""
技能验证脚本 - 验证 self-correction 技能的结构和内容
"""

import os
import sys
import json
import re
from pathlib import Path

def validate_frontmatter(skill_md_path):
    """验证SKILL.md的frontmatter格式"""
    with open(skill_md_path, 'r', encoding='utf-8') as f:
        content = f.read()

    # 检查frontmatter是否在文件开头
    if not content.startswith('---'):
        return False, "SKILL.md必须以---开头的frontmatter开始"

    # 提取frontmatter
    frontmatter_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
    if not frontmatter_match:
        return False, "无法解析frontmatter"

    frontmatter_text = frontmatter_match.group(1)

    # 检查必需的字段
    required_fields = ['name', 'description']
    for field in required_fields:
        if not re.search(f'^{field}:', frontmatter_text, re.MULTILINE):
            return False, f"frontmatter缺少必需字段: {field}"

    # 提取name和description
    name_match = re.search(r'^name:\s*(.+)$', frontmatter_text, re.MULTILINE)
    desc_match = re.search(r'^description:\s*(.+)$', frontmatter_text, re.MULTILINE)

    if name_match:
        name = name_match.group(1).strip()
        # 检查name是否为英文（允许连字符）
        if not re.match(r'^[a-z0-9-]+$', name):
            return False, f"name字段必须为英文（仅允许小写字母、数字和连字符），当前值: {name}"

    return True, "frontmatter验证通过"

def validate_meta_json(meta_path):
    """验证_meta.json格式"""
    with open(meta_path, 'r', encoding='utf-8') as f:
        meta = json.load(f)

    required_fields = ['id', 'version']
    for field in required_fields:
        if field not in meta:
            return False, f"_meta.json缺少必需字段: {field}"

    # 验证版本格式
    version = meta.get('version', '')
    if not re.match(r'^\d+\.\d+\.\d+$', version):
        return False, f"version字段格式不正确，应为x.y.z格式，当前值: {version}"

    return True, "_meta.json验证通过"

def validate_naming(skill_dir):
    """验证目录和文件命名"""
    dir_name = os.path.basename(skill_dir)

    # 检查目录名是否为英文
    if not re.match(r'^[a-z0-9-]+$', dir_name):
        return False, f"目录名必须为英文小写，当前值: {dir_name}"

    # 检查SKILL.md中的name是否与目录名匹配
    skill_md_path = os.path.join(skill_dir, 'SKILL.md')
    with open(skill_md_path, 'r', encoding='utf-8') as f:
        content = f.read()

    name_match = re.search(r'^name:\s*(.+)$', content, re.MULTILINE)
    if name_match:
        frontmatter_name = name_match.group(1).strip()
        if frontmatter_name != dir_name:
            return False, f"SKILL.md中的name({frontmatter_name})与目录名({dir_name})不匹配"

    return True, "命名验证通过"

def validate_description(skill_md_path):
    """验证description包含触发短语"""
    with open(skill_md_path, 'r', encoding='utf-8') as f:
        content = f.read()

    desc_match = re.search(r'^description:\s*(.+)$', content, re.MULTILINE)
    if not desc_match:
        return False, "未找到description字段"

    desc = desc_match.group(1)

    # 检查description是否包含"当用户..."或"Use when"等触发短语
    trigger_patterns = [
        r'当用户',
        r'触发',
        r'Use when',
        r'utilisé quand'
    ]

    has_trigger = any(re.search(pattern, desc, re.IGNORECASE) for pattern in trigger_patterns)
    if not has_trigger:
        return False, "description应包含触发条件描述（如'当用户...'或'Use when...'）"

    return True, "description验证通过"

def validate_structure(skill_dir):
    """验证技能目录结构"""
    required_files = ['SKILL.md', '_meta.json']
    for file in required_files:
        file_path = os.path.join(skill_dir, file)
        if not os.path.exists(file_path):
            return False, f"缺少必需文件: {file}"

    return True, "结构验证通过"

def validate_no_secrets(skill_dir):
    """检查是否有泄露的密钥或敏感信息（仅检查SKILL.md和_meta.json）"""
    # 只检查技能核心文件，不检查scripts目录
    forbidden_patterns = [
        r'password\s*=\s*["\'][^"\']+["\']',
        r'api_key\s*=\s*["\'][^"\']+["\']',
        r'secret_key\s*=\s*["\'][^"\']+["\']',
        r'token\s*=\s*["\'][^"\']+["\']',
        r'-----BEGIN.*PRIVATE KEY-----',
    ]

    # 只检查核心技能文件
    files_to_check = [
        os.path.join(skill_dir, 'SKILL.md'),
        os.path.join(skill_dir, '_meta.json'),
    ]

    for file_path in files_to_check:
        if not os.path.exists(file_path):
            continue
        with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read()
            for pattern in forbidden_patterns:
                if re.search(pattern, content, re.IGNORECASE):
                    return False, f"发现可能泄露的敏感信息在 {os.path.basename(file_path)}"

    return True, "安全检查通过"

def run_validation(skill_dir):
    """运行所有验证"""
    print("=" * 50)
    print("开始验证 self-correction 技能")
    print("=" * 50)

    validations = [
        ("结构验证", lambda: validate_structure(skill_dir)),
        ("frontmatter验证", lambda: validate_frontmatter(os.path.join(skill_dir, 'SKILL.md'))),
        ("_meta.json验证", lambda: validate_meta_json(os.path.join(skill_dir, '_meta.json'))),
        ("命名验证", lambda: validate_naming(skill_dir)),
        ("description验证", lambda: validate_description(os.path.join(skill_dir, 'SKILL.md'))),
        ("安全检查", lambda: validate_no_secrets(skill_dir)),
    ]

    all_passed = True
    for name, validator in validations:
        passed, message = validator()
        status = "✅ 通过" if passed else "❌ 失败"
        print(f"[{status}] {name}: {message}")
        if not passed:
            all_passed = False

    print("=" * 50)
    if all_passed:
        print("✅ 所有验证通过！")
        return 0
    else:
        print("❌ 存在验证失败项")
        return 1

if __name__ == '__main__':
    skill_dir = sys.argv[1] if len(sys.argv) > 1 else '/workspace/temp-skills/self-correction'
    exit_code = run_validation(skill_dir)
    sys.exit(exit_code)


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)