Codebase (2026-06-27): this engine now lives in meno-gaokao-counsellor (
core/…), extracted from reflection-game — see gaokao-standalone-plan. Module paths below use the newcore/layout.
当前实现(2026-06-24)— 画像是 load-bearing 且逐幕更新
画像(
profile.narrative,point-form)是生成器真正读的模型:传入unified_turn/chat_reply/update_narrative/user_report。流程:开局build_narrative(v4-pro)生成初始 point-form 画像 → 每站「最想听你说」的回答经update_narrative(v4-pro)增量并进画像、并修正不再贴切的旧要点 → 🪞 面板可手动编辑;另有结尾多轮对话(chat_reply)也每轮并进画像。不再是开局生成一次定死。 维度走法是动态的(按不确定性/决策相关性/未检视选维度),非固定FACTORS[stage]。8 极数值层仍是弱信号/基本死代码。
画像 本身就是一段提示词——准确说,是注入生成上下文的
PLAYER PROFILE文本块。本页忠实地讲清楚它由哪些来源拼成、那段文本长什么样、以及那 8 个「人格极」到底怎么被用(以及没被用)。The profile is a prompt — specifically the
PLAYER PROFILEtext block injected into the generation context. This page documents, faithfully, what sources assemble it, what that text literally looks like, and exactly how the 8 “personality poles” are used (and not used).
这段提示词长什么样 / What the prompt literally is
中文。 排名模式(/rank_start)下,一个学生填完入场信息、走了两步之后,serialize_for_prompt() 产出的真实文本块就是下面这段——这就是注入给场景种子和调查员的”画像”:
PLAYER PROFILE (use ONLY to make scenes relevant to this person — NEVER to make any option look correct):
self-description: 我是云南理科生,纠结要不要为了名校放弃喜欢的专业;想做点真正有意义的事
理想毕业去向(从最想到最不想,影响每一步该看什么): 创业 > 就业 > 出国留学
salient value leanings (pole: strength): AGENCY:+0.75, RIGOR:+0.67, PROCESS:+0.63, TRUTH:+0.60, VOICE:+0.55就这四行。 没有别的。第一行是护栏,后三行分别来自三个来源(见下)。
English. In the ranked mode (/rank_start), after a student fills the intake and takes two steps, the actual text block from serialize_for_prompt() is the one above — this is the “profile” injected into the scene seed and the investigator. Four lines, nothing more. Line 1 is the guardrail; the next three each come from one source (below).
由哪些来源拼成 / What assembles it (faithful to the code)
中文。 排名模式里画像有三个活跃来源(web.py 的 _handle_rank_start + profile.py):
| 提示词里的行 | 来源 | 怎么进去的 |
|---|---|---|
self-description | 入场自我描述文本框 | 原样存入 free_text(截断 600 字) |
理想毕业去向 | 开场的去向排序(保研/考研/出国/就业/考公考编/创业) | 存入 destination_pref(最多 6) |
salient value leanings | ① 入场 6 道选择题 + ② 游戏中每次选择/重排 | 每个选项带几个「人格极」权重 → update_from_choice() 以滑动平均折叠进 observed;输出时取 |强度| 最大的前 5 个 |
关键的忠实修正:入场问卷不是写进一个单独的 prior,而是和游戏中的选择一起折叠进 observed。排名模式下 prior 始终是空的——它只在 A/B 模式(/start,可接语音画像)里才被赋值。所以排名游戏里,人格极信号全部来自 observed(问卷 + 选择)。
English. In ranked mode the profile has three live sources (_handle_rank_start in web.py + profile.py):
| line in the prompt | source | how it gets there |
|---|---|---|
self-description | intake free-text box | stored verbatim in free_text (truncated to 600 chars) |
理想毕业去向 | opening 毕业去向 ranking (保研/考研/出国/就业/考公考编/创业) | stored in destination_pref (≤6) |
salient value leanings | ① the 6 intake MCQs + ② every in-game choice/reorder | each option carries a few pole weights → update_from_choice() folds them into observed as a running mean; the top-5 by |strength| are emitted |
The faithful correction: the intake quiz does not write a separate prior — it folds into observed, together with in-game choices. In ranked mode prior is always empty — it’s only populated in the A/B mode (/start, which can take a voice profile). So in the ranked game all pole signal comes from observed (quiz + choices).
为什么是 8 个「人格极」,又怎么被用 / Why 8 poles, and how they’re used
中文。 8 对极(TRUTH↔PROTECTION、PRINCIPLE↔LOYALTY、VOICE↔SILENCE、AGENCY↔OBSERVATION、PROCESS↔OUTCOME、NOW↔LATER、SELF↔OTHER、RIGOR↔MERCY)来自 reflection-game 主线的人格模型(human_modeling.personality)。
为什么不直接用”喜欢 CS”? 因为志愿的本质是价值取舍,不是专业标签。把答案编码成「更看重 RIGOR 还是 MERCY、PROCESS 还是 OUTCOME」这样与专业无关的价值向量,画像就能跨任意专业迁移,让生成器按这个人的价值(而非仅仅他选的专业)来写场景。每道选择题的每个选项,都手工标注了它命中哪几个极、各多重(如”做我真正热爱的事”→PROCESS:0.8, TRUTH:0.5)。
它们到底怎么被”考量”? 诚实地说:只有一种方式——上面那行 salient value leanings,把 |强度| 最大的 5 个极当作一句软提示喂给 LLM。它不驱动任何结构化逻辑(不挑因子、不排顺序、不选原型分支)。所以它的实际影响是弱的,这正对应测试者”画像在后面基本没体现”的反馈。
English. The 8 pole-pairs (TRUTH↔PROTECTION, PRINCIPLE↔LOYALTY, VOICE↔SILENCE, AGENCY↔OBSERVATION, PROCESS↔OUTCOME, NOW↔LATER, SELF↔OTHER, RIGOR↔MERCY) come from the main reflection-game human model (human_modeling.personality).
Why not just “likes CS”? Because a 志愿 decision is fundamentally about value trade-offs, not a major label. Encoding answers as a topic-agnostic value vector (“weights RIGOR over MERCY, PROCESS over OUTCOME”) lets the profile transfer across any major, so the generator writes scenes around the person’s values, not merely their chosen major. Each quiz option is hand-annotated with which poles it hits and how strongly (e.g. “做我真正热爱的事” → PROCESS:0.8, TRUTH:0.5).
How are they actually “considered”? Honestly: in exactly one way — the salient value leanings line, which feeds the top-5 poles to the LLM as a soft hint. They drive no structured logic (they don’t pick factors, order stages, or select archetype branches). So their real influence is weak — which is exactly the tester feedback that “the profile barely shows up later.”
护栏 / The guardrail
中文。 文本块首行写死:“只用于让场景相关,绝不让任何选项显得正确。” 设计意图是:画像决定你遇到哪些岔路,不决定哪条更好——否则就成了回音室,破坏”偏好没有标准答案”的原则。它注入到 build_gaokao_seed(场景种子)和 investigate() / frame_test()(ranked.py)。
English. The block’s first line is hard-coded: “use ONLY to make scenes relevant — NEVER to make any option look correct.” Intent: the profile steers which forks you face, not which looks better — otherwise it’s an echo chamber and breaks the no-right-answer principle. It’s injected into build_gaokao_seed (scene seed) and investigate() / frame_test() (ranked.py).
当前局限 / Current limitations (honest)
中文。
- 极信号弱:8 极只作为一行软提示出现,不进任何结构化决策。
- 排名模式
prior恒空:价值信号全靠 6 道题 + 游戏内选择的observed,样本很小。 - 因子序列固定:
ranked.py的FACTORS[stage]是固定 7 步,画像只给小场景上色,不改”出现哪些因子/如何加权”(测试者 Tianyi/Zhilin 的核心反馈)。→ P0 修复方向:让因子选择/排序/加权由destination_pref + observed + 专业内路径驱动。
English.
- Weak pole signal: the 8 poles appear only as a one-line soft hint, entering no structured decision.
prioralways empty in ranked: value signal rests entirely on the 6 MCQs + in-game choices inobserved— a small sample.- Now surfaced + editable (2026-06-17): the synthesized narrative is shown in the in-game 🪞「你和AI共同理解的你」panel in a large extensible box; editing it stores the edited version as the profile, and the investigator reads it to choose each stage’s person-specific question — so the profile is now visible and load-bearing.
- Fixed factor sequence:
FACTORS[stage]inranked.pyis a fixed 7-step walk; the profile only colors the vignette, it doesn’t change which factors appear or how they’re weighted (the core Tianyi/Zhilin feedback). → the P0 fix: make factor selection/ordering/weighting driven bydestination_pref + observed + within-major path.
Related
- grounding-layer — the per-major knowledge the scenes draw on
- reflective-equilibrium-algorithm — how the推演 uses the profile to work the least-examined dimension
- log — the tester feedback that surfaced these limitations