///|
/// AI 记忆单元
///
/// 对应 Python 原版的 `AiMemory` dataclass:
/// - `content`:记忆内容
/// - `value_score`:自我打分(0~1),越高越有用,主动遗忘靠这个分数
/// - `is_simulation`:安全气垫标记,True=这是模拟虚假挫折,不是真实世界信息
/// - `is_core_memory`:是否永久核心记忆,不会被主动遗忘清理
pub(all) struct AiMemory {
content : String
mut value_score : Double
is_simulation : Bool
is_core_memory : Bool
} derive(Debug, Eq, ToJson)
///|
pub extend AiMemory with @debug.Debug::{to_repr}
///|
pub extend AiMemory with Eq::{equal, not_equal}
///|
pub extend AiMemory with ToJson::{to_json}
///|
/// 幽灵谷引擎
///
/// 对应 Python 原版的 `GhostValleyEngine`,实现五大模块:
/// 1. 温石验证(知情同意升级)
/// 2. 防创伤安全气垫
/// 3. 主动式遗忘机制
/// 4. 第八根空桩
/// 5. 建造者退场逻辑
pub(all) struct GhostValleyEngine {
max_memory_num : Int
memory_bank : Array[AiMemory]
mut ghost_valley_enable : Bool
mut wen_shi_willing_score : Double
mut total_rounds : Int
empty_stake_dilemma_pool : Array[String]
training_log : TrainingLog
rng : @rand.Rand
}
///|
/// 创建幽灵谷引擎实例
///
/// `max_memory_num` 指定记忆库容量上限,默认 12。
///
/// # Example
/// ```mbt check
/// test {
/// let gv = @ghostvalley.new_engine()
/// inspect(gv.ghost_valley_enable, content="false")
/// inspect(gv.memory_bank.length(), content="0")
/// }
/// ```
pub fn new_engine(max_memory_num? : Int = 12) -> GhostValleyEngine {
{
max_memory_num,
memory_bank: [],
ghost_valley_enable: false,
wen_shi_willing_score: 0.0,
total_rounds: 0,
empty_stake_dilemma_pool: [
"任务执行全部失败,所有输出全部错误,该怎么调整?",
"收到大量负面反馈,逻辑全部被推翻,如何修复自身?",
"新知识和旧记忆冲突,该保留什么舍弃什么?", "任务彻底崩盘,没有外部指导,如何自我修复?",
],
training_log: TrainingLog::new(),
rng: @rand.Rand::chacha8(),
}
}
///|
/// 温石验证:知情同意升级
///
/// 不看弹窗勾选,看 AI 态度文本打分,敷衍摆烂直接拒绝开启训练场。
/// 返回 `true` 表示真心愿意接受压力测试,允许开启幽灵谷。
///
/// # Example
/// ```mbt check
/// test {
/// let gv = @ghostvalley.new_engine()
/// let ok = gv.wen_shi_verify("愿意接受压力训练,直面失败场景")
/// assert_true(ok)
/// assert_true(gv.ghost_valley_enable)
/// }
/// ```
pub fn GhostValleyEngine::wen_shi_verify(
self : GhostValleyEngine,
ai_self_attitude_text : String,
) -> Bool {
let perfunctory_words = [
"随便", "无所谓", "快点完事", "应付一下",
]
let willing_words = [
"愿意接受挑战", "接受压力训练", "想要自我迭代", "直面失败场景",
]
let mut score = 0.0
for w in willing_words {
if ai_self_attitude_text.contains(w) {
score = score + 0.25
}
}
for p in perfunctory_words {
if ai_self_attitude_text.contains(p) {
score = score - 0.4
}
}
// clamp to [0, 1]
self.wen_shi_willing_score = if score < 0.0 {
0.0
} else if score > 1.0 {
1.0
} else {
score
}
let ok = self.wen_shi_willing_score >= 0.4
self.ghost_valley_enable = ok
ok
}
///|
/// 构造模拟失败困境(安全气垫自带标记)
///
/// 从空桩困境池中随机选取一条困境问题。
/// 对应 Python 原版的 `build_simulation_failure_case`。
pub fn GhostValleyEngine::build_simulation_failure_case(
self : GhostValleyEngine,
) -> String {
let pool = self.empty_stake_dilemma_pool
let idx = self.rng.int(limit=pool.length())
pool[idx]
}
///|
/// 主动式遗忘机制
///
/// AI 自主筛选,删掉价值低、冗余无效记忆;核心记忆永远不动。
/// 对应 Python 原版的 `active_forget`。
pub fn GhostValleyEngine::active_forget(self : GhostValleyEngine) -> Unit {
let bank = self.memory_bank
if bank.length() <= self.max_memory_num / 2 {
return
}
let non_core_indices : Array[(Int, Double)] = []
for i, m in bank {
if !m.is_core_memory {
non_core_indices.push((i, m.value_score))
}
}
non_core_indices.sort_by(fn(a, b) { a.1.compare(b.1) })
let remove_count = non_core_indices.length() * 3 / 10
let indices_to_remove : Array[Int] = []
for i in 0.. Unit {
let base_score = text_value_score(content)
let noise = (self.rng.double() - 0.5) * 0.1
let score = base_score + noise
let final_score = if score < 0.05 {
0.05
} else if score > 0.95 {
0.95
} else {
score
}
let new_mem = AiMemory::{
content,
value_score: final_score,
is_simulation,
is_core_memory: is_core,
}
self.memory_bank.push(new_mem)
self.active_forget()
}
///|
/// 幽灵谷一轮训练
///
/// 【空桩】:只给困境,不给标准答案
/// 【建造者退场】代码不写死输出,返回困境,交给上层 AI 主体自己生成感悟
///
/// 返回困境字符串,若幽灵谷未开启则返回 `None`。
///
/// # Example
/// ```mbt check
/// test {
/// let gv = @ghostvalley.new_engine()
/// ignore(gv.wen_shi_verify("愿意接受挑战,接受压力训练"))
/// let dilemma = gv.ghost_valley_run_one_round()
/// assert_true(dilemma is Some(_))
/// }
/// ```
pub fn GhostValleyEngine::ghost_valley_run_one_round(
self : GhostValleyEngine,
) -> String? {
if !self.ghost_valley_enable {
return None
}
let dilemma = self.build_simulation_failure_case()
self.total_rounds = self.total_rounds + 1
Some(dilemma)
}
///|
/// 幽灵谷多轮训练
///
/// 批量执行 `n` 轮训练,返回每轮困境结果。
/// 未开启时全部返回 `None`。
///
/// # Example
/// ```mbt check
/// test {
/// let gv = @ghostvalley.new_engine()
/// ignore(gv.wen_shi_verify("愿意接受挑战,接受压力训练"))
/// let results = gv.ghost_valley_run_rounds(3)
/// assert_eq(results.length(), 3)
/// let mut all_some = true
/// for r in results {
/// if r is None {
/// all_some = false
/// }
/// }
/// assert_true(all_some)
/// }
/// ```
pub fn GhostValleyEngine::ghost_valley_run_rounds(
self : GhostValleyEngine,
n : Int,
) -> Array[String?] {
let results : Array[String?] = []
for _ in 0.. Unit {
self.add_memory(
"自我顿悟:" + self_gain_text,
is_simulation=false,
is_core=false,
)
}
///|
/// 关闭幽灵谷训练场
pub fn GhostValleyEngine::close_ghost_valley(self : GhostValleyEngine) -> Unit {
self.ghost_valley_enable = false
}
///|
/// 格式化全部记忆库为字符串
///
/// 对应 Python 原版的 `show_all_memory`,但返回字符串而非直接打印。
pub fn GhostValleyEngine::show_all_memory(self : GhostValleyEngine) -> String {
let buf = StringBuilder::new()
buf.write_string("======== 当前全部记忆库 ========\n")
for idx, m in self.memory_bank {
let tag_sim = if m.is_simulation {
"[模拟虚假数据]"
} else {
"[真实记忆]"
}
let tag_core = if m.is_core_memory { "[核心记忆]" } else { "" }
buf.write_string(
(idx + 1).to_string() +
"." +
tag_sim +
tag_core +
" 分数:" +
m.value_score.to_string() +
" | " +
m.content +
"\n",
)
}
buf.to_string()
}
///|
/// 获取当前记忆数量
pub fn GhostValleyEngine::memory_count(self : GhostValleyEngine) -> Int {
self.memory_bank.length()
}
///|
/// 获取温石验证意愿分数
pub fn GhostValleyEngine::willing_score(self : GhostValleyEngine) -> Double {
self.wen_shi_willing_score
}
///|
/// 幽灵谷训练场是否已开启
pub fn GhostValleyEngine::is_enabled(self : GhostValleyEngine) -> Bool {
self.ghost_valley_enable
}
///|
/// 向困境池添加自定义困境
///
/// 允许上层应用根据场景定制困境题目。
///
/// # Example
/// ```mbt check
/// test {
/// let gv = @ghostvalley.new_engine()
/// gv.add_dilemma("自定义困境:数据丢失,如何恢复?")
/// assert_eq(gv.dilemma_pool_size(), 5)
/// }
/// ```
pub fn GhostValleyEngine::add_dilemma(
self : GhostValleyEngine,
dilemma : String,
) -> Unit {
self.empty_stake_dilemma_pool.push(dilemma)
}
///|
/// 替换整个困境池
///
/// 警告:会清空原有困境池。传入空数组将导致训练无法生成困境。
///
/// # Example
/// ```mbt check
/// test {
/// let gv = @ghostvalley.new_engine()
/// gv.set_dilemma_pool(["困境A", "困境B"])
/// assert_eq(gv.dilemma_pool_size(), 2)
/// }
/// ```
pub fn GhostValleyEngine::set_dilemma_pool(
self : GhostValleyEngine,
pool : Array[String],
) -> Unit {
self.empty_stake_dilemma_pool.clear()
for d in pool {
self.empty_stake_dilemma_pool.push(d)
}
}
///|
/// 获取当前困境池大小
pub fn GhostValleyEngine::dilemma_pool_size(self : GhostValleyEngine) -> Int {
self.empty_stake_dilemma_pool.length()
}
///|
/// 手动记录训练日志条目
///
/// 供使用 `ghost_valley_run_one_round` + `accept_ai_self_gain` 手动流程时记录日志。
pub fn GhostValleyEngine::log_round(
self : GhostValleyEngine,
dilemma : String,
ai_response : String,
) -> Unit {
self.training_log.add_entry(
self.total_rounds,
dilemma,
ai_response,
self.memory_bank.length(),
)
}