Puzzle 谜题对象规范
Puzzle 是 HeurAMS 中用于生成具体复习题目的对象. 它将记忆内容转化为可交互的练习题目, 支持多种题型和自定义配置.
谜题类型概览
HeurAMS 目前支持三种谜题类型:
| 类型 | 类名 | 描述 | 适用场景 |
|---|---|---|---|
| MCQ | MCQPuzzle | 多项选择题 | 含义选择、语法判断、概念区分 |
| Cloze | ClozePuzzle | 填空题(完形填空) | 句子补全、单词填空、短语填空 |
| Recognition | RecognitionPuzzle | 识别题(占位符) | 单词识别、概念识别、简单回忆 |
通用接口
所有谜题类型都继承自 BasePuzzle 基类, 实现以下接口:
python
class BasePuzzle:
def refresh(self) -> None:
"""刷新谜题, 生成新的题目"""
raise NotImplementedError
def __str__(self) -> str:
"""返回谜题的字符串表示"""
return f"谜题: {type(self).__name__}"公共属性
每个谜题实例都有以下公共属性:
| 属性 | 类型 | 描述 |
|---|---|---|
wording | Union[str, List[str]] | 题目文本 |
answer | Union[str, List[str]] | 正确答案 |
options | List[List[str]] | 选项列表(仅 MCQ) |
MCQ(选择题)
类定义
python
class MCQPuzzle(BasePuzzle):
def __init__(
self,
mapping: Dict[str, str],
jammer: List[str],
max_riddles_num: int = 2,
prefix: str = "",
) -> None:构造函数参数
| 参数 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
mapping | Dict[str, str] | 是 | - | 问题到正确答案的映射字典 |
jammer | List[str] | 是 | - | 干扰项列表 |
max_riddles_num | int | 否 | 2 | 最大题目数量(范围 1-5) |
prefix | str | 否 | "" | 题目前缀文本 |
配置示例(TOML)
在 Orbital 中配置 MCQ:
toml
"VocabularyQuiz" = {
__origin__ = "mcq",
__hint__ = "选择单词的正确含义",
mapping = "eval:nucleon['word_meaning_pairs']",
jammer = "eval:nucleon['distractor_words']",
max_riddles_num = "eval:default['mcq']['max_riddles_num']",
prefix = "词汇测试: "
}谜题生成逻辑
- 题目选择:从
mapping中随机选择max_riddles_num个问题 - 选项生成:为每个问题生成 4 个选项(1 个正确答案 + 3 个干扰项)
- 干扰项来源:从
jammer列表中选取, 排除正确答案 - 选项随机化:打乱选项顺序
- 格式输出:添加前缀和编号
示例输出
词汇测试:
1. "Ubiquitous" 的含义是?
A) 稀有的
B) 普通的
C) 无处不在的 ✓
D) 暂时的
2. "Ephemeral" 的含义是?
A) 短暂的 ✓
B) 永恒的
C) 复杂的
D) 简单的额外方法
| 方法 | 返回类型 | 描述 |
|---|---|---|
get_question_count() | int | 获取当前题目数量 |
get_correct_answer_for_question(question_index) | Optional[str] | 获取指定题目的正确答案 |
get_options_for_question(question_index) | Optional[List[str]] | 获取指定题目的选项列表 |
Cloze(填空题)
类定义
python
class ClozePuzzle(BasePuzzle):
def __init__(self, text: str, min_denominator: int, delimiter: str = "/") -> None:构造函数参数
| 参数 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
text | str | 是 | - | 原始文本(用分隔符分割) |
min_denominator | int | 是 | - | 最小概率倒数(控制填空密度) |
delimiter | str | 否 | "/" | 文本分隔符 |
配置示例(TOML)
在 Orbital 中配置 Cloze:
toml
"SentenceCompletion" = {
__origin__ = "cloze",
__hint__ = "完成句子填空",
text = "eval:nucleon['sentence']",
delimiter = "eval:metadata['formation']['delimiter']",
min_denominator = "eval:default['cloze']['min_denominator']"
}谜题生成逻辑
- 文本分割:使用
delimiter将文本分割成单词/短语列表 - 填空数量计算:
填空数 = max(1, 总词数 // min_denominator) - 填空位置选择:随机选择填空位置
- 答案记录:记录被替换的原始内容
- 填空生成:用下划线替换选中位置的内容
示例输出
原始文本: "The/quick/brown/fox/jumps/over/the/lazy/dog/"
生成填空: "The quick brown ______ jumps over the ______ dog"
正确答案: ["fox", "lazy"]参数说明
min_denominator:控制填空密度值 = 2:大约 1/2 的内容会被填空值 = 5:大约 1/5 的内容会被填空值 ≥ 总词数:只填空 1 个位置
delimiter:文本分隔符- 常用:
"/"、" "(空格)、"|" - 确保文本末尾也有分隔符
- 常用:
Recognition(识别题)
类定义
python
class RecognitionPuzzle(BasePuzzle):
def __init__(self) -> None:配置示例(TOML)
在 Orbital 中配置 Recognition:
toml
"WordRecognition" = {
__origin__ = "recognition",
__hint__ = "",
primary = "eval:nucleon['word']",
secondary = ["eval:nucleon['definition']", "eval:nucleon['example']"],
top_dim = ["eval:nucleon['translation']"]
}参数说明
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
primary | str | 是 | 主要识别内容 |
secondary | List[str] | 否 | 次要识别内容列表 |
top_dim | List[str] | 否 | 顶部维度内容列表 |
谜题生成逻辑
Recognition 是占位符谜题, 当前版本仅用于内容展示, 不生成交互式题目.
使用场景
- 单词识别:显示单词, 要求回忆含义
- 概念识别:显示概念, 要求回忆定义
- 简单回忆:显示提示, 要求回忆完整内容
谜题生命周期
1. 配置解析
从 Orbital 配置中解析参数, 创建谜题实例.
python
# 伪代码示例
puzzle_config = orbital["puzzles"]["VocabularyQuiz"]
if puzzle_config["__origin__"] == "mcq":
puzzle = MCQPuzzle(
mapping=parse_macro(puzzle_config["mapping"], nucleon),
jammer=parse_macro(puzzle_config["jammer"], nucleon),
max_riddles_num=int(parse_macro(puzzle_config["max_riddles_num"], nucleon)),
prefix=parse_macro(puzzle_config["prefix"], nucleon)
)2. 谜题刷新
调用 refresh() 方法生成新题目.
python
puzzle.refresh() # 生成新的题目和答案3. 题目展示
通过 wording 属性获取题目文本.
python
question_text = puzzle.wording
if isinstance(question_text, list):
for i, q in enumerate(question_text):
print(f"{i+1}. {q}")
else:
print(question_text)4. 答案验证
通过 answer 属性验证用户回答.
python
user_answer = get_user_input()
correct_answer = puzzle.answer
if isinstance(correct_answer, list):
is_correct = user_answer in correct_answer
else:
is_correct = user_answer == correct_answer宏表达式支持
谜题配置支持宏表达式, 用于动态生成内容.
常用宏模式
直接引用 Nucleon 字段
tomltext = "eval:nucleon['sentence']"处理嵌套结构
tomlmapping = "eval:{pair.split(':')[0]: pair.split(':')[1] for pair in nucleon['word_pairs'].split(';')}"数组处理
tomljammer = "eval:nucleon['distractors'].split(',')"条件逻辑
tomltext = "eval:nucleon.get('sentence_en', nucleon.get('sentence', ''))"
宏执行上下文
| 变量 | 类型 | 可用字段 |
|---|---|---|
nucleon | Nucleon | Nucleon 的所有字段 |
metadata | dict | [__metadata__] 内容 |
default | dict | 系统默认配置 |
自定义谜题开发
创建新谜题类型
- 继承
BasePuzzle基类 - 实现
refresh()方法 - 定义构造函数参数
- 注册到谜题注册器(如果支持)
python
from heurams.kernel.puzzles.base import BasePuzzle
class NewPuzzle(BasePuzzle):
def __init__(self, param1: str, param2: int):
self.param1 = param1
self.param2 = param2
self.wording = "新谜题 - 尚未刷新"
self.answer = ["未设置"]
def refresh(self):
# 生成新题目的逻辑
self.wording = f"问题: {self.param1}"
self.answer = [f"答案: {self.param2}"]配置集成
在 Orbital 配置中添加新类型:
toml
"CustomPuzzle" = {
__origin__ = "newpuzzle", # 需要注册的标识符
__hint__ = "自定义谜题",
param1 = "eval:nucleon['content']",
param2 = "eval:42"
}最佳实践
1. 谜题设计原则
- 难度适中:避免过于简单或复杂的题目
- 多样性:混合使用不同谜题类型
- 相关性:谜题内容与学习目标紧密相关
- 反馈明确:提供清晰的正确答案和解释
2. 参数调优建议
- MCQ:
max_riddles_num建议 2-3, 避免认知负荷 - Cloze:
min_denominator建议 3-5, 平衡挑战性和完成度 - 干扰项:确保与正确答案相似但可区分
3. 性能考虑
- 预生成:可以在后台提前生成谜题
- 缓存:对相同内容缓存生成的谜题
- 懒加载:需要时才调用
refresh()
版本历史
- v1 (当前版本):支持三种谜题类型, 宏表达式系统
- v0:基础谜题框架(已弃用)
相关文档
- Nucleon 规范 - 记忆内容文件
- Orbital 规范 - 学习策略文件
- Algorithm 规范 - 算法对象定义