中途改进

This commit is contained in:
2025-07-27 21:39:34 +08:00
parent d27d353374
commit 5d3c354d8f
11 changed files with 396 additions and 20 deletions

5
.gitignore vendored
View File

@@ -1,2 +1,5 @@
.vscode
__pycache__/
.directory
__pycache__/
scripts/
.idea

View File

@@ -3,13 +3,17 @@
## 概述
"潜进" (HeurAMS, 中文含义: 启发式辅助记忆软件) 是一款为古诗词设计的记忆辅助软件, 集成记忆拟合算法、自然语音技术与生成式人工智能, 提供科学的记忆训练解决方案
"潜进" (HeurAMS, 中文含义: 启发式辅助记忆软件) 是为习题册, 古诗词, 及其他问答/记忆/理解型题目设计的记忆辅助软件, 集成记忆拟合算法、自然语音技术与生成式人工智能, 提供优化的
## 核心特性
### 科学记忆拟合算法
- 采用经实证的 SM-2 间隔重复算法
- 采用经实证的 SM-2 间隔重复算法, 此算法亦用作 Anki 闪卡记忆软件的默认闪卡调度器
> TODO: 将添加 FSRS 算法 (Anki 的新可选闪卡调度器) 与一种 SM-15 变体算法作为后续替代
> 参考 https://github.com/slaypni/SM-15
> 为什么使用 SM-15 的变体?
> SM-2 后续算法仅有论文, 无具体方程, SM-15 是基于 SM-15 描述实现的变体算法
- 动态优化每首诗词的记忆间隔时间表
- 实时跟踪记忆曲线,最大化长期记忆保留率与稳定性

View File

@@ -0,0 +1,251 @@
["臣密言:臣以险衅, 夙遭闵凶."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["生孩六月, 慈父见背;行年四岁, 舅夺母志."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["祖母刘愍臣孤弱, 躬亲抚养."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["臣少多疾病, 九岁不行, 零丁孤苦, 至于成立."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["既无伯叔, 终鲜兄弟, 门衰祚薄, 晚有儿息."]
efactor = 2.5
real_rept = 11
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["外无期功强近之亲, 内无应门五尺之僮, 茕茕孑立, 形影相吊."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["而刘夙婴疾病, 常在床蓐, 臣侍汤药, 未曾废离."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["逮奉圣朝, 沐浴清化."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["前太守臣逵察臣孝廉;后刺史臣荣举臣秀才."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["臣以供养无主, 辞不赴命."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["诏书特下, 拜臣郎中, 寻蒙国恩, 除臣洗马."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["猥以微贱, 当侍东宫, 非臣陨首所能上报."]
efactor = 2.5
real_rept = 2
rept = 0
interval = 1
last_date = 11
next_date = 12
is_activated = 1
["臣具以表闻, 辞不就职."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["诏书切峻, 责臣逋慢;郡县逼迫, 催臣上道;州司临门, 急于星火."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["臣欲奉诏奔驰, 则刘病日笃, 欲苟顺私情, 则告诉不许."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["臣之进退, 实为狼狈."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["伏惟圣朝以孝治天下, 凡在故老, 犹蒙矜育, 况臣孤苦, 特为尤甚."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["且臣少仕伪朝, 历职郎署, 本图宦达, 不矜名节."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["今臣亡国贱俘, 至微至陋, 过蒙拔擢, 宠命优渥, 岂敢盘桓, 有所希冀!"]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["但以刘日薄西山, 气息奄奄, 人命危浅, 朝不虑夕."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["臣无祖母, 无以至今日, 祖母无臣, 无以终余年."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["母孙二人, 更相为命, 是以区区不能废远."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["臣密今年四十有四, 祖母今年九十有六, 是臣尽节于陛下之日长, 报养刘之日短."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["乌鸟私情, 愿乞终养."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["臣之辛苦, 非独蜀之人士及二州牧伯所见明知, 皇天后土, 实所共鉴."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["愿陛下矜悯愚诚, 听臣微志, 庶刘侥幸, 保卒余年."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["臣生当陨首, 死当结草."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0
["臣不胜犬马怖惧之情, 谨拜表以闻."]
efactor = 2.5
real_rept = 0
rept = 0
interval = 0
last_date = 0
next_date = 0
is_activated = 0

15
main.py
View File

@@ -12,7 +12,7 @@ import particles as pt
from reactor import Reactor
import auxiliary as aux
ver = '0.2.6'
ver = '0.3.0'
config = aux.ConfigFile("config.toml")
@@ -57,12 +57,13 @@ class MemScreen(Screen):
yield Static("", id="feedback") # 用于显示反馈
yield Label(self._get_progress_text(), id="progress")
with Container(id="button_container"):
self.btn['5'] = Button("完美回想", variant="success", id="q5", classes="choice")
self.btn['4'] = Button("犹豫后正确", variant="success", id="q4", classes="choice")
self.btn['3'] = Button("困难地正确", variant="warning", id="q3", classes="choice")
self.btn['2'] = Button("错误但熟悉", variant="warning", id="q2", classes="choice")
self.btn['1'] = Button("错误且不熟", variant="error", id="q1", classes="choice")
self.btn['0'] = Button("完全空白", variant="error", id="q0", classes="choice")
if 1:
self.btn['5'] = Button("完美回想", variant="success", id="q5", classes="choice")
self.btn['4'] = Button("犹豫后正确", variant="success", id="q4", classes="choice")
self.btn['3'] = Button("困难地正确", variant="warning", id="q3", classes="choice")
self.btn['2'] = Button("错误但熟悉", variant="warning", id="q2", classes="choice")
self.btn['1'] = Button("错误且不熟", variant="error", id="q1", classes="choice")
self.btn['0'] = Button("完全空白", variant="error", id="q0", classes="choice")
yield Horizontal(self.btn['5'], self.btn['4'])
yield Horizontal(self.btn['3'], self.btn['2'])
yield Horizontal(self.btn['1'], self.btn['0'])

View File

@@ -1,3 +1,18 @@
# 散列表的键翻译
["keydata"]
note = "笔记"
keyword_note = "关键词翻译"
translation = "语句翻译"
# 测试项目元数据
["testdata"]
# 记忆时显示的额外信息
additional_inf = ["translation", "note"]
# 填空测试
fill_blank = ["translation"]
# 选择题测试
draw_card = ["keyword_note"]
["臣密言:臣以险衅, 夙遭闵凶."]
note = []
translation = "臣子李密陈言:我因命运不好,小时候遭遇到了不幸"

View File

@@ -122,16 +122,7 @@ class Nucleon():
def __init__(self, content: str, data: dict):
self.metadata = data
self.content = content
@staticmethod
def import_from_file(path: pathlib.Path):
name = path.name.replace(path.suffix, "")
with open(path, 'r') as f:
all = toml.load(f)
lst = list()
for i in all.keys():
lst.append(Nucleon(i, all[i]))
return (name, lst)
@staticmethod
def save_to_file(nucleon_dictized, path: pathlib.Path):
@@ -142,6 +133,24 @@ class Nucleon():
def placeholder():
return Nucleon("核子对象样例内容", {})
class NucleonUnion():
"取代原有 NucleonFile 类, 以支持复杂逻辑"
def __init__(self, path):
name = path.name.replace(path.suffix, "")
with open(path, 'r') as f:
all = toml.load(f)
lst = list()
for i in all.keys():
if "data" in i:
continue
lst.append(Nucleon(i, all[i]))
self.keydata = all["keydata"]
self.testdata = all["testdata"]
self.nucleons = lst
self.nucleons_dict =
def query(content):
class AtomicFile():
def __init__(self, path, type_="unknown"):
self.path = path

0
puzzlemarkers.py Normal file
View File

45
testfield/blank_maker.py Normal file
View File

@@ -0,0 +1,45 @@
import random
class BlankPuzzle():
"""填空题谜题生成器
Args:
text: 原始字符串(需要 "/" 分割句子, 末尾应有 "/")
min_denominator: 最小概率倒数(如占所有可生成填空数的 1/7 中的 7, 若期望值小于 1, 则取 1)
"""
def __init__(self, text, min_denominator):
self.text = text
self.min_denominator = min_denominator
self.wording = "填空题 - 尚未刷新谜题"
self.answer = ["填空题 - 尚未刷新谜题"]
def refresh(self): # 刷新谜题
placeholder = "___SLASH___"
tmp_text = self.text.replace("/", placeholder)
words = tmp_text.split(placeholder)
if not words:
return ""
words = [word for word in words if word]
num_blanks = min(max(1, len(words) // self.min_denominator), len(words))
indices_to_blank = random.sample(range(len(words)), num_blanks)
indices_to_blank.sort()
blanked_words = list(words)
answer = list()
for index in indices_to_blank:
blanked_words[index] = "__" * len(words[index])
answer.append(words[index])
result = []
for word in blanked_words:
result.append(word)
self.answer = answer
self.wording = "".join(result)
def __str__(self):
return f"{self.wording}\n{str(self.answer)}"
# demo
text = """我联合国人民/同兹/决心/: /欲免/后世/再遭/今代人类/两度/身历/惨不堪言/之战祸/.../"""
riddle = BlankPuzzle(text, 3)
print(riddle)
riddle.refresh()
print(riddle)

View File

@@ -0,0 +1,45 @@
import random
class SelectionPuzzle():
"""选择题谜题生成器
Args:
text: 原始字符串(需要 "/" 分割句子, 末尾应有 "/")
min_denominator: 最小概率倒数(如占所有可生成填空数的 1/7 中的 7, 若期望值小于 1, 则取 1)
"""
def __init__(self, prefix_text, origin_dict, min_denominator):
self.text = text
self.min_denominator = min_denominator
self.wording = "填空题 - 尚未刷新谜题"
self.answer = ["填空题 - 尚未刷新谜题"]
def refresh(self): # 刷新谜题
placeholder = "___SLASH___"
tmp_text = self.text.replace("/", placeholder)
words = tmp_text.split(placeholder)
if not words:
return ""
words = [word for word in words if word]
num_blanks = min(max(1, len(words) // self.min_denominator), len(words))
indices_to_blank = random.sample(range(len(words)), num_blanks)
indices_to_blank.sort()
blanked_words = list(words)
answer = list()
for index in indices_to_blank:
blanked_words[index] = "__" * len(words[index])
answer.append(words[index])
result = []
for word in blanked_words:
result.append(word)
self.answer = answer
self.wording = "".join(result)
def __str__(self):
return f"{self.wording}\n{str(self.answer)}"
# demo
text = """我联合国人民/同兹/决心/: /欲免/后世/再遭/今代人类/两度/身历/惨不堪言/之战祸/.../"""
riddle = BlankPuzzle(text, 3)
print(riddle)
riddle.refresh()
print(riddle)

3
todo.md Normal file
View File

@@ -0,0 +1,3 @@
- [] 基于释义的评估
> 使用 EFACTOR 取最低值方法
- [] 附加属性