luckytri 1.1.2 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +2 -2
  3. package/docs/en/CHANGELOG.md +30 -0
  4. package/docs/en/architecture.md +11 -9
  5. package/docs/en/chat-style.md +13 -13
  6. package/docs/en/cognition.md +12 -4
  7. package/docs/en/her-life.md +5 -2
  8. package/docs/zh/CHANGELOG.md +30 -0
  9. package/docs/zh/architecture.md +11 -9
  10. package/docs/zh/chat-style.md +17 -17
  11. package/docs/zh/cognition.md +12 -4
  12. package/docs/zh/her-life.md +5 -2
  13. package/package.json +28 -3
  14. package/public/app/assets/{ChatsPage-IfBgNdaD.js → ChatsPage-eDqFIg97.js} +1 -1
  15. package/public/app/assets/{Empty-DK9nQPCf.js → Empty-CAGOJsfD.js} +1 -1
  16. package/public/app/assets/{Field-BzKFhuFd.js → Field-CRz-JmN1.js} +1 -1
  17. package/public/app/assets/{HeartPage-CKxrbfFQ.js → HeartPage-BGWoeMrC.js} +1 -1
  18. package/public/app/assets/{LifePage-CtxPEi6E.js → LifePage-iao3o3wt.js} +1 -1
  19. package/public/app/assets/{MemoryPage-B8FLXzLi.js → MemoryPage-Dwi2yi7E.js} +1 -1
  20. package/public/app/assets/NaturePage-DniImo9U.js +3 -0
  21. package/public/app/assets/{NaturePage-CHkpb5NK.css → NaturePage-zguDpGWY.css} +1 -1
  22. package/public/app/assets/{PeoplePage-D3yn0HV0.js → PeoplePage-D-MC3JEt.js} +1 -1
  23. package/public/app/assets/{PluginsPage-ojv8zawj.js → PluginsPage-D7dJTf96.js} +1 -1
  24. package/public/app/assets/SystemPage-C5CUHjGh.js +1 -0
  25. package/public/app/assets/{SystemPage-CGVTvNZw.css → SystemPage-C_Y5M7JU.css} +1 -1
  26. package/public/app/assets/{TimePage-Dyd-FFbq.js → TimePage-Dwhr3-92.js} +1 -1
  27. package/public/app/assets/{index-BJfzfgnm.js → index-L0bHax8C.js} +3 -3
  28. package/public/app/assets/{knowledge-C-bND0Ub.js → knowledge-BTDNafzl.js} +1 -1
  29. package/public/app/assets/{media-D7G3Nco6.js → media-BBzOAfNG.js} +1 -1
  30. package/public/app/assets/{mind-ec-G6iNZ.js → mind-CBTkFje2.js} +1 -1
  31. package/public/app/index.html +3 -3
  32. package/public/guide.en.html +3 -3
  33. package/public/guide.html +3 -3
  34. package/scripts/migrate-instance.js +27 -0
  35. package/scripts/update-instance.js +21 -2
  36. package/server/channels/contract.js +5 -1
  37. package/server/channels/hub.js +2 -2
  38. package/server/channels/onebot/adapter.js +291 -288
  39. package/server/channels/onebot/index.js +2 -2
  40. package/server/channels/qqbot/api.js +194 -199
  41. package/server/core/context-builder.js +24 -4
  42. package/server/core/conversation-cues.js +5 -4
  43. package/server/core/conversation-grounding.js +20 -17
  44. package/server/core/conversation-needs.js +32 -0
  45. package/server/core/dialogue-context.js +2 -5
  46. package/server/core/dialogue-contract.js +23 -16
  47. package/server/core/message-scheduler.js +85 -78
  48. package/server/core/model-manager.js +113 -16
  49. package/server/core/model-presets.js +1 -1
  50. package/server/core/orchestrator.js +18 -2
  51. package/server/core/persona-manager.js +14 -5
  52. package/server/core/reader-check.js +47 -42
  53. package/server/core/reply-delivery.js +125 -34
  54. package/server/core/response-validator.js +46 -3
  55. package/server/core/retired-prompts.js +5 -0
  56. package/server/core/speech-length.js +43 -0
  57. package/server/core/turn-processor.js +38 -5
  58. package/server/core/turn.js +99 -16
  59. package/server/i18n/errors.js +30 -0
  60. package/server/i18n/labels.js +5 -0
  61. package/server/index.js +3 -0
  62. package/server/knowledge/embedding-profile.js +126 -29
  63. package/server/knowledge/manager.js +103 -34
  64. package/server/knowledge/schema.js +197 -158
  65. package/server/mind/affect.js +269 -265
  66. package/server/mind/aftermath.js +169 -0
  67. package/server/mind/anticipations.js +2 -0
  68. package/server/mind/clock.js +91 -83
  69. package/server/mind/discretion.js +20 -0
  70. package/server/mind/episodes.js +2 -1
  71. package/server/mind/index.js +17 -2
  72. package/server/mind/initiative.js +29 -14
  73. package/server/mind/memory.js +47 -5
  74. package/server/mind/recall/cue.js +67 -0
  75. package/server/mind/recall/index.js +183 -29
  76. package/server/mind/recall/roots.js +231 -0
  77. package/server/mind/recall/schema.js +2 -0
  78. package/server/mind/recall/store.js +113 -30
  79. package/server/mind/salience.js +22 -1
  80. package/server/mind/schema.js +5 -0
  81. package/server/mind/thoughts.js +276 -274
  82. package/server/mind/view.js +103 -60
  83. package/server/plugins/install.js +1 -6
  84. package/server/plugins/zip.js +18 -4
  85. package/server/runtime/data-migration.js +193 -0
  86. package/server/runtime/update-execution.js +43 -4
  87. package/server/runtime/update-manager.js +4 -1
  88. package/server/storage/archive.js +1 -1
  89. package/server/storage/backup-scheduler.js +15 -3
  90. package/public/app/assets/NaturePage-C7i607ul.js +0 -3
  91. package/public/app/assets/SystemPage-Cv3rFvyT.js +0 -1
package/README.en.md CHANGED
@@ -94,7 +94,7 @@ The full design is in [Her life](docs/en/her-life.md) and [Architecture and exte
94
94
 
95
95
  Recent work focuses on continuity and clearer conversation. Account-based recognition links public encounters across groups and private chats. Relationships, forms of address, her own views and private promises retain their sources and visibility boundaries. An ordinary greeting need not bring back unfinished tasks or demonstrate how much she remembers.
96
96
 
97
- **1.1.2 update:** Embedding dimension 0 uses the model's own length. For doubao-embedding-vision that is 2048, and it is no longer forced to 1024. See the [changelog](docs/en/CHANGELOG.md).
97
+ **1.2.1 update:** Reply line breaks now follow message boundaries while lists stay together; old sentence-per-line replies no longer shape her typing style, and tiredness is reflected more accurately in her energy. See the [changelog](docs/en/CHANGELOG.md).
98
98
 
99
99
  | Area | What it does today |
100
100
  | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
package/README.md CHANGED
@@ -94,12 +94,12 @@ flowchart LR
94
94
 
95
95
  近期更新集中在让相处更连贯、说话更清楚。她按账号认出同一个人,在不同群与私聊间衔接公开经历;关系、称呼、自己的看法和私人约定分别保留来源与可见范围。普通问候不需要带出旧任务,每次开口也不需要证明自己记住了多少事。
96
96
 
97
- **1.1.2 更新:** 向量维度填 0 时用模型自己的长度,`doubao-embedding-vision` 是 2048,不再写成 1024。完整变化见 [版本记录](docs/zh/CHANGELOG.md)。
97
+ **1.2.1 更新:** 修正回复换行与消息边界,保留列表排版,并避免旧记录里的逐句换行继续影响她的表达;疲惫也会更准确地反映在精力状态中。完整变化见 [版本记录](docs/zh/CHANGELOG.md)。
98
98
 
99
99
  | 方面 | 现在能做什么 |
100
100
  | ------------ | --------------------------------------------------------------------------------------------------------- |
101
101
  | 时间与独处 | 按自己的作息过一天;安静时整理想法、阅读资料、写日记;每隔一段时间回顾,改写自传、翻开新的一章 |
102
- | 做自己的事 | 执行自己的阅读、写作与思考计划;游戏内容以参考资料阅读与记录为主;作品保存在「一生」「时间」中 |
102
+ | 做自己的事 | 执行自己的阅读、写作与思考计划;游戏内容以参考资料阅读与记录为主;作品保存在「一生」「时间」中 |
103
103
  | 自我与心境 | 从有来源的经历里形成看法、喜好、关注和想做的事;变化可以回看和撤销 |
104
104
  | 关系与记忆 | 一份跨群、跨私聊的记忆;区分「公开 / 私下 / 保密」;私下的事不会出现在别的房间 |
105
105
  | 注意力与选择 | 理解多人对话、@ 与引用关系,决定细看、开口或沉默;也能从自己的念头出发主动联系 |
@@ -2,6 +2,36 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## 1.2.1 — 2026-10-13
6
+
7
+ - Fix message boundaries: a line break starts another message, while a list stays together; lines that continue the same thought are joined, within the turn's message limit.
8
+ - Normalize older sentence-per-line replies in her context and typing-style statistics, so an old layout does not keep teaching her to write that way.
9
+ - Let tired or tense feelings affect her energy more fully; add twelve explicitly synthetic regression scenes for reply shape.
10
+
11
+ ## 1.2.0 — 2026-10-13
12
+
13
+ - Instance updates now run a versioned memory migration: make and verify a full snapshot, upgrade the database with the candidate release, merge legacy memory records, and rebuild full-text and experience-link indexes. Persistent row counts are checked table by table before switching versions. A failed migration restores the snapshot and restarts the previous release. Chat memories are not sent to a model, and existing vectors are not regenerated.
14
+
15
+ - The review prompt drops a duplicated “admitting fault scores no points” clause so that idea is stated once, trimming prompt bloat.
16
+ - The check of whether a reply answers the asker now treats “I don’t eat / have no body” as a real answer to “what did you eat”, not as dodging the question.
17
+ - Memory consolidation and summary merges join the other mechanical stages in turning off hidden reasoning, so background work no longer burns thousands of reasoning tokens to extract facts.
18
+ - A bare “you got it wrong” about a fact is no longer treated as a repair that must admit fault; only meta-critique of how she speaks (robotic, repetitive, unnatural) takes that path, and even then she checks whether she actually did.
19
+ - Older related lines pulled in from outside the chat window are deduplicated and capped at five, so eight near-identical old rows no longer fill the prompt.
20
+ - When someone claims she got a fact wrong without evidence, restating her own recent basis is no longer treated as empty rephrasing and rewritten twice; the turn payload also drops the humanMessages field that duplicated exchange.current.
21
+ - When two statements about someone do not fit together and neither is settled, recalling one now shows the other beside it, with when and where she heard it, instead of taking either for fact. A restricted one is only noted, not repeated.
22
+ - The check of whether a reply answers the person who asked now sees that person’s own earlier words on the same thing (at most two), so a correct answer to “that interview I mentioned, which day was it” is no longer taken for invention and rewritten again and again.
23
+ - Faster, cheaper replies: the review step that asks “did the reply answer the person who asked” no longer uses hidden reasoning (same accuracy on the review probe, about 93% fewer output tokens for that check); the main review keeps its configured effort, because without it an unsupported change of mind slipped through. On Volcengine, “no thinking” and mechanical stages now really disable thinking instead of using minimal reasoning; models that cannot (GLM) keep the old setting, and a model that refuses is asked again with minimal reasoning.
24
+ - Memory consolidation no longer drops an episode that is reworded but has a source for every clause (e.g. “pushed weekend basketball off too”); a one-clause note still has to end in words that were said.
25
+ - What happened after each choice is recorded: whether anyone answered her, a possible correction, whether she was called again after keeping quiet, and the owner's feedback, with the messages. Derived from the record without a model; turn input is unchanged. The audit reports it with samples.
26
+ - Bringing back her own notes with an affair is stricter: a single shared word that is not in the affair's title no longer counts. Notes and plans enter the recall index as soon as they are written.
27
+ - When an affair comes back to her, so does what she made of it: her note then and later, or an intention about it, at most two lines. Links come from the sources she already keeps, with no model call; private thoughts stay out of groups.
28
+ - Times over a week ago are no longer all "a long time ago": a week ago, two or three weeks ago, over a month ago, a few months ago, over a year ago.
29
+ - Revocations are stamped on her own clock, on the same timeline as the rest of her life.
30
+ - Each turn records what came to her mind (facts, episodes, self threads, thoughts, promises) in the choice record, kept for good and never sent to the model; turn input stays byte-for-byte the same. The database only gains one column, so older versions still open it.
31
+ - New `npm run audit:life -- --db <backup>`: a read-only check-up of a backup that reports on the integrity and continuity of her life record. New `npm run evaluate:traits`: trait probes with the scripted model.
32
+ - New Ultimate vision document; the evolution charter sits under it.
33
+ - Embeddings no longer default to doubao: any OpenAI-compatible `/embeddings` endpoint works with an address, a model name and a key, and Volcengine Ark (including Agent Plan) is one preset. With dimension 0 every model keeps its own length; doubao-embedding-vision stays at 2048 as in 1.1.2, so existing vectors are not rebuilt. In a recall comparison with real vectors 1024 was slightly worse, so it is no longer the default. Vectors returned as base64, the different ways services say a batch is too big, and a 413 without a limit are all handled.
34
+
5
35
  ## 1.1.2 — 2026-10-11
6
36
 
7
37
  - Embedding length is no longer forced to 1024. Dimension 0 does not ask the service for a length, so doubao-embedding-vision uses its own 2048. A profile already saved as 1024 has to be set back to 0 and saved again.
@@ -4,6 +4,8 @@
4
4
 
5
5
  This document is for anyone who wants to read, change or extend LuckyTri. It answers three questions: how the code is layered, how a message travels through her life, and where to start when you want to add something.
6
6
 
7
+ Every design here serves the final vision: she is still made of code and models, but her judgments should not have to find their answers only in the original design; they should come more and more from her own experience and choices.
8
+
7
9
  ## One picture
8
10
 
9
11
  ```mermaid
@@ -76,10 +78,10 @@ public/ the built studio (app/) and the guide pages
76
78
  1. **The channel receives.** The adapter turns the platform's raw event into a neutral message: session key, sender, time, whether she was @-ed, the quoted message, attachments. The platform's format exists only inside the adapter.
77
79
  2. **Batching and perception** (`core/`). Messages arriving close together form a batch; @s, quote chains and name calls are parsed, giving each message its relation to her.
78
80
  3. **Attention** (`mind/attention.js`, no model call). Being called, a private chat and crisis signals always get a close look; ordinary group chat is decided by a deterministic score between a close look and a glance.
79
- 4. **The her of this moment** (`mind/view.js`). Nature, threads of self, bonds, mood, memory and nearby promises are condensed into a few hundred tokens with a hard cap: the stable part goes into a cacheable prefix, the changing part at the end.
81
+ 4. **The her of this moment** (`mind/view.js`). Nature, threads of self, bonds, mood, memory and nearby promises are condensed into a few hundred tokens with a hard cap: the stable part goes into a cacheable prefix, the changing part at the end. Her mood is persistent and decays (half-life about 3 hours); how strongly it still lingers is part of what she sees, and it, not the room's typing habits, is what shapes how long and in what tone she speaks. How others type is only situational awareness.
80
82
  5. **One turn call.** The model returns, in one go: what this means to her, a feeling, changes to people, a choice (speak, react briefly, say she does not feel like talking, stay silent), a reason and the wording.
81
83
  6. **Experience.** Whether she speaks or not, feelings and changes are written into the mind, each citing its source.
82
- 7. **Validation and sending.** Local checks on tone and secrecy, one review or rewrite when needed, a safe short line if it still fails; the context is checked for staleness again before sending. Uncertain delivery is never resent.
84
+ 7. **Validation and sending.** Local checks on tone and secrecy, one review or rewrite when needed, a safe short line if it still fails; the context is checked for staleness again before sending. Uncertain delivery is never resent. In a group, when several other people have spoken since the one message she answers, the first bubble is sent as a quote of it on channels that can quote (OneBot today).
83
85
  8. **Lifetime.** When nobody is talking, time still passes through her: solitude, reading, the diary, night sorting, review and reaching out all read and write the same mind.
84
86
 
85
87
  Replay runs the same pipeline but only reads the mind as it was before that moment; trial chat reads her mind as it is now but writes nothing and sends nothing to QQ.
@@ -136,13 +138,13 @@ Nothing above the core changes. The connection option in settings and the readin
136
138
 
137
139
  ## Test layout
138
140
 
139
- | Command | What it covers |
140
- | --- | --- |
141
- | `npm test` | All backend tests, including the deterministic "life simulation" |
142
- | `npm run test:clock` | The suite run with the real clock moved 60 days back and 400 days ahead |
143
- | `npm run test:ui` | Browser tests: smoke, the little world, navigation, time, performance, search, English interface |
144
- | `npm run format:check` | Prettier check |
145
- | `tests/repo-hygiene.test.js` | Repository hygiene: no keys, instance data, local paths or third-party connector names |
141
+ | Command | What it covers |
142
+ | ---------------------------- | ------------------------------------------------------------------------------------------------ |
143
+ | `npm test` | All backend tests, including the deterministic "life simulation" |
144
+ | `npm run test:clock` | The suite run with the real clock moved 60 days back and 400 days ahead |
145
+ | `npm run test:ui` | Browser tests: smoke, the little world, navigation, time, performance, search, English interface |
146
+ | `npm run format:check` | Prettier check |
147
+ | `tests/repo-hygiene.test.js` | Repository hygiene: no keys, instance data, local paths or third-party connector names |
146
148
 
147
149
  ## Conventions
148
150
 
@@ -29,9 +29,9 @@ The following are hand-designed directions, not results measured on an external
29
29
 
30
30
  ## The rhythm of this place
31
31
 
32
- In a group she hears the rhythm in which others speak there. It switches on after at least 12 distinct messages from 3 members within the last 7 days of ordinary human text, with each member contributing at most 8 so one talkative person cannot stand for the whole group. It measures common sentence length, the share of short sentences, closing punctuation, emoji and the frequency of conspicuous internet slang.
32
+ The studio still computes, for a group, the typical sentence length, share of short lines, sentence-final punctuation, emoji and slang rate of ordinary human text over the last 7 days (at least 12 distinct messages from 3 members, at most 8 per member). It is shown to you in the studio only.
33
33
 
34
- The statistics reach her only as `inner.room` and are **not her character**: she speaks by her own habits, need not copy them, and need not deliberately sound different. The adapter builds no profile of anyone's verbal habits, quotes no member, and does not treat commands in a group as settings; links, long texts, code, image placeholders, repeats, obvious abuse and common sensitive fields are filtered out. The statistics never cross groups, private chats or simulation mode.
34
+ These statistics **no longer reach her**. How long she speaks and in what tone comes from herself: her current mood in `inner.state` (persistent, slowly fading, marked with how strongly it still lingers), her relationship with the person in front of her, what just happened, and what she herself has said before. How others type is only something she sees while there, never a style to copy. No per-person habit profile is built, nobody's words are quoted, and nothing crosses groups, private chats or the simulation mode.
35
35
 
36
36
  ## Feedback
37
37
 
@@ -68,14 +68,14 @@ Feelings, corrections, crises, abstract bot exchanges, attribution and capabilit
68
68
 
69
69
  For real acceptance, watch 10–20 consecutive turns rather than a single line: does she pick up details, ask questions too often, repeat catchphrases, talk over others, suddenly turn into customer service, or mix up a joke with real sadness. Automated tests cover engineering constraints and hand-made scenario samples; the language quality of a real model still depends on your own observation.
70
70
 
71
- In the source checkout, run `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue.js --limit 120` for live-model replay through understanding, validation, review and rewriting, followed by a separate quality review. This uses the configured default model and incurs model costs. It never connects to QQ or changes the running memory. Reports stay in local `data/evaluations/`. Model errors, unresolved issues and fallback replies fail the run. A single model's review has limitations; inspect the actual outputs too.
72
-
73
- Additional source-checkout checks:
74
-
75
- - `node --env-file-if-exists=.env scripts/dev/audit-dialogue-corpus.js` reads every live message in overlapping conversation blocks and records coverage. Missing evidence in one block is a lead to investigate, not proof of fabrication.
76
- - Replay with `--current-nature --rebuild-mind --review-model <profile-id>` to rebuild historical mind selection in an in-memory copy while retaining saved activity progress, and use a separate reviewer. `--model <profile-id>` selects an evaluation model without changing the live instance. This does not reproduce historical external services or images.
77
- - `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue-sequences.js --review-model <profile-id>` carries generated replies into the next turn and checks corrections, boundaries, affection, factual provenance and consistency over a conversation.
78
-
79
- These commands incur model costs. Reviewers can miss errors or cite the wrong sentence; inspect their evidence. Combinatorial rule checks are not equivalent to the same number of distinct semantic conversations, and no test establishes perfect future conversation quality.
80
-
81
- Current dialogue receives a factual `exchange` tail with new messages, quote chains and recent own words. Its short `understanding` summary remains revisable. Single extracted topical views stay retrievable without becoming enduring core traits; a one-off extracted habit does not become a response script. Reference-based game activities and model-generated material retain provenance and uncertainty instead of being presented as client operation. Reply review has an independent evaluator role and does not inherit the character's performance instructions.
71
+ In the source checkout, run `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue.js --limit 120` for live-model replay through understanding, validation, review and rewriting, followed by a separate quality review. This uses the configured default model and incurs model costs. It never connects to QQ or changes the running memory. Reports stay in local `data/evaluations/`. Model errors, unresolved issues and fallback replies fail the run. A single model's review has limitations; inspect the actual outputs too.
72
+
73
+ Additional source-checkout checks:
74
+
75
+ - `node --env-file-if-exists=.env scripts/dev/audit-dialogue-corpus.js` reads every live message in overlapping conversation blocks and records coverage. Missing evidence in one block is a lead to investigate, not proof of fabrication.
76
+ - Replay with `--current-nature --rebuild-mind --review-model <profile-id>` to rebuild historical mind selection in an in-memory copy while retaining saved activity progress, and use a separate reviewer. `--model <profile-id>` selects an evaluation model without changing the live instance. This does not reproduce historical external services or images.
77
+ - `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue-sequences.js --review-model <profile-id>` carries generated replies into the next turn and checks corrections, boundaries, affection, factual provenance and consistency over a conversation.
78
+
79
+ These commands incur model costs. Reviewers can miss errors or cite the wrong sentence; inspect their evidence. Combinatorial rule checks are not equivalent to the same number of distinct semantic conversations, and no test establishes perfect future conversation quality.
80
+
81
+ Current dialogue receives a factual `exchange` tail with new messages, quote chains and recent own words. Its short `understanding` summary remains revisable. Single extracted topical views stay retrievable without becoming enduring core traits; a one-off extracted habit does not become a response script. Reference-based game activities and model-generated material retain provenance and uncertainty instead of being presented as client operation. Reply review has an independent evaluator role and does not inherit the character's performance instructions.
@@ -4,29 +4,37 @@
4
4
 
5
5
  She is still one turn call, not one model call per layer. What was added is a hint while a message is waiting, one recall path, episode threads, working memory, and lessons written in solitude from experience.
6
6
 
7
+ When an affair comes back to her, it brings at most two lines of what she herself made of it (`mine`): notes that rest on the same moments and speak of it (a revised note shows "then / later"), an intention of hers about it, or a self thread that grew from it. A note only appears in the conversations it was written for, private intentions stay private, and nothing already in front of her is repeated.
8
+
7
9
  ## How a message moves
8
10
 
9
11
  1. It is stored in `core_events`. The speaker's query vector is computed while the batch is waiting.
10
12
  2. Messages in one session become one turn. `understanding.js` joins one person's consecutive lines and notes tone, stance and time expressions. Those are hints.
11
- 3. `mind/recall` takes vector, full-text and structured candidates together, fuses them by reciprocal rank, then reranks by person, age and source. Permission is applied before ranking.
13
+ 3. `mind/recall` takes vector, full-text and structured candidates together, fuses them by reciprocal rank, then reranks by person, age and source. Permission is applied before ranking. A very short follow-up (under six character pairs, such as "唉,估计没戏") is searched together with the line it leans on: the quoted message, the same person's lines from the last ten minutes, or her line they answer (`mind/recall/cue.js`, no model call, the stored words unchanged). Pinned facts and questions like "do you remember me" are handled on the hybrid path as on the word path.
12
14
  4. Working memory keeps the current stretch verbatim. Older stretches are a summary plus semantic recall. Open episodes appear on a relationship as `goingOn`.
13
15
  5. One turn call. A model sometimes nests `choice` inside `understanding` or `contribution`. Normalization puts the fields back where the contract says they belong.
14
16
  6. The reply is checked and sent. Background consolidation writes facts and episodes. An episode whose follow-up time has arrived, or a promise that is due, is only a candidate during solitude. It still passes the existing initiative gates.
15
17
 
16
- When the embedding service is down, recall falls back to full text, structured lookup and recent context. The turn still runs.
18
+ When the embedding service is down, recall falls back to full text, structured lookup and recent context. The turn still runs. The knowledge library embeds its question through the same service: the words recall just asked about are not sent again, the wait is capped at four seconds, and a paused service is skipped.
17
19
 
18
20
  ## Storage
19
21
 
20
- `DATABASE_VERSION` is 5. `mind_index`, `mind_index_fts` and `mind_vectors` are derived and can be rebuilt. `mind_episodes` is append-only: a status change is a new row in the same `thread_id`. `mind_self` gained a `lesson` kind and a `subject`. A lesson must cite experience that did not come from the model. The same experience is used once. Two independent pieces move it from `emerging` to `active`. A counterexample revises it downward.
22
+ `DATABASE_VERSION` is 5. `mind_index`, `mind_index_fts`, `mind_vectors` and `mind_roots` (what each record ultimately rests on, worked out from the sources it already cites) are derived and can be rebuilt. `mind_episodes` is append-only: a status change is a new row in the same `thread_id`. `mind_self` gained a `lesson` kind and a `subject`. A lesson must cite experience that did not come from the model. The same experience is used once. Two independent pieces move it from `emerging` to `active`. A counterexample revises it downward.
23
+
24
+ `mind_choices.after` records what happened after a choice: whether anyone replied to her or called her and how many minutes later, the tone cues of those replies, a "不是 / 记错了" said to her (marked only as "maybe corrected"), whether someone called her again after she kept quiet, and the owner's feedback on that reply, with the message ids. The window closes at her next choice in the same room, after two hours, or after twenty messages, and the maintenance timer writes it a page at a time. It is derived from the record only, never from a model, and can be cleared and computed again. It is an experience, not a score, and is never summed into a reward.
21
25
 
22
26
  A fact can be archived. Archiving only removes it from ordinary recall. When a person asks for deletion, the source, the index row and the vector are removed together.
23
27
 
24
28
  ## Embeddings
25
29
 
26
- The configured embedding model uses the OpenAI-compatible `/embeddings` endpoint, in batches, 2048 dimensions by default. Asking for 1024 works and is similar. The Ark multimodal endpoint takes one item at a time. Cosine between a short chat line and a stored fact is low, so a hit counts when it stands above the median of the nearest batch, with different floors for the speaker, people present, and everyone else. Queries have their own request lane and do not queue behind conversation. Background backfill is paced and slows down on HTTP 429.
30
+ The embedding service can be any OpenAI-compatible `/embeddings` endpoint: an address, a model name and a key, in batches. Volcengine Ark is one preset: with an Ark address the model may be left empty and doubao-embedding-vision is used; an Agent Plan key only works on `/api/plan/v3`, so the chat address is kept. Dimension 0 asks the service for no length, so every model uses its own (2048 for doubao-embedding-vision); a written length is requested as is, and writing the model's own length shares vectors with 0. With real vectors on the recall benchmark, 1024 missed one more case and once more attributed someone else's fact to the speaker, so nothing is shortened by default. The Ark multimodal endpoint takes one item at a time. Vectors returned as base64 are decoded; an oversized batch shrinks to the limit the service names, or halves on a 413 without one. Cosine between a short chat line and a stored fact is low, so a hit counts when it stands above the median of the nearest batch, with different floors for the speaker, people present, and everyone else. Queries have their own request lane and do not queue behind conversation. Background backfill is paced and slows down on HTTP 429.
27
31
 
28
32
  On a backup copy, with 1024 dimensions and about 40 paraphrased real facts: lexical Recall@5 was 0.475; hybrid recall with feature rerank was 0.950, and the average number returned fell from 12 to about 3.9. There is no separate model reranker.
29
33
 
34
+ Vectors in memory are split by kind and kept in step item by item: a new message, a rewrite or a removal touches only its own entry, so the next turn no longer reads the whole `mind_vectors` table back, and a fact search no longer walks a month of message vectors. After an embedding model or length change, once the active profile covers her memories, only it and the most recent older profile are kept.
35
+
36
+ A new length is a new embedding profile (the signature holds the address, model and length; naming the model's native length signs the same as naming none). An install with 2048-dimension vectors keeps them as they are after the upgrade. The new profile is filled on the maintenance timer: at most 100 items a minute, 10 per request, under a tokens-per-minute cap, facts first, then episodes, self and thoughts, messages last. Until a kind is 80% covered, that kind is recalled by words, structure and recent context. After her memories, knowledge chunks follow 20 at a time, and each chunk keeps its old vector in `previous_embedding`. Setting the length back to 2048 (or to the previous profile) uses the old vectors again for memories and knowledge, with no requests.
37
+
30
38
  ## What evaluation showed
31
39
 
32
40
  Before these changes, a recent day of live turns had a median of about 35 seconds, and about 8.4 seconds before the first model call. Memory consolidation succeeded 13 times out of about 230. Priority lanes, persisted backoff, picking a free slot, and skipping a knowledge embedding when the library has no vectors, are there to stop failed retries and the queue in front of a turn.
@@ -177,6 +177,9 @@ Later upgrades only add tables and columns: existing chapters are kept and the f
177
177
  - `npm test`: unit tests of each part of the mind, tests of lifetime (solitude, diary, night review, autobiography, reaching out, rhythm), a deterministic three-day "life simulation" with two groups and one private chat, and a 120-day "long life simulation". They verify: the same experience twice yields the same her, no randomness on the will path, changes are sourced and gradual, undone things never return, mood settles back, the same person is consistent across groups, secrets do not leak (even when the model slips), the crisis floor works, replay never reads the future, threads fade and are recalled when a topic appears, and on day 120 inputs are still within their caps. Set `LIFE_DAYS=365` to run a whole year.
178
178
  - `npm run test:clock`: runs the backend tests with the real clock moved 60 days back and 400 days ahead. The test world has its own clock; code that quietly reads the real clock passes today and fails later.
179
179
  - `npm run audit:sent`: replays the replies she recently sent against today's reply checks and writes a report to `data/reports/`. Read-only, no model calls.
180
+ - `npm run evaluate:traits`: lives a short fixed stretch of experience with the scripted model and checks, trait by trait from the vision, that the mechanisms really happen (threads persist, events form one thread, revocations stay gone, revised notes keep the old version, each turn records what came to mind, and so on), and lists baseline numbers. No key, no tokens; the numbers measure mechanisms, not how she does with a real model.
181
+ - `npm run audit:life -- --db <backup.db>`: a read-only check-up of her life. Make a backup first with `npm run backup` (`data/backups/luckytri-*.db`), then run it on the backup; the report goes to `data/reports/life-audit-*.md` (plus a `.json`). It checks broken source links, revoked content coming back, superseded memories without a successor and secret text reappearing in the diary or autobiography, and counts self threads, episode threads, promises, how far back recall reaches, choice reasons and background runs. It opens the file read-only, writes nothing and calls no model; `--out` changes the output folder and `--now` sets "now".
182
+ - Every live turn records in `mind_choices.recalled` the past that was in front of her (index ids and reasons for facts, episodes, self threads, thoughts and promises). It is kept for good and never enters the prompt. Older code still opens a database with this column.
180
183
  - `npm run test:ui`: browser tests covering sessions, simulated messages, memory, models, connecting QQ, replay, the little world and the English interface. `node tests/ui/ta.mjs --serve` opens a world that has lived three days for a direct look at the interface.
181
184
  - `node scripts/dev/evaluate-life.js`: lives a few days with your saved model for real (spending tokens) and writes `data/evaluations/life-*.md` to read item by item; `--weeks 3` then lives three more weeks of ordinary days in compressed form; `--mock` only checks the script itself.
182
185
 
@@ -187,5 +190,5 @@ Later upgrades only add tables and columns: existing chapters are kept and the f
187
190
  - Something she heard in one group may come up in another related group; the only barriers are "known privately" discretion, secrecy requests and credentials.
188
191
  - Promises are only extracted during memory tidying: sessions with fewer than 40 piled-up messages are tidied that night, so an afternoon "tomorrow" is usually caught, while something about to happen in a few minutes may not be.
189
192
  - What engineering can guarantee is structure: continuous, sourced, correctable, decided by her. Whether she "truly has a heart" cannot be accepted by tests; the tests check whether these behaviors actually happen.
190
-
191
- Thoughts about each place are independent entries: impressions, wishes, preferences, questions or boundaries. During solitude, diaries or identity reviews she chooses whether to add, revise or let them go, retaining reasons and sources. Revising one leaves other entries intact. Copied legacy group personas remain history and no longer enter conversation; place thoughts do not increase overall personality scores.
193
+
194
+ Thoughts about each place are independent entries: impressions, wishes, preferences, questions or boundaries. During solitude, diaries or identity reviews she chooses whether to add, revise or let them go, retaining reasons and sources. Revising one leaves other entries intact. Copied legacy group personas remain history and no longer enter conversation; place thoughts do not increase overall personality scores.
@@ -2,6 +2,36 @@
2
2
 
3
3
  # 版本记录
4
4
 
5
+ ## 1.2.1 — 2026-10-13
6
+
7
+ - 修正消息分段:回复中的换行按另起一条消息处理,列表仍保留在同一条消息里;续写上文的行会并回去,消息数量遵守当前上限。
8
+ - 旧记录中每句话单独换行的回复,在生成上下文和口吻统计里按自然的打字习惯归一,避免她把旧排版继续学成自己的表达。
9
+ - 疲惫或紧绷的感受会更充分地影响精力状态;新增 12 组标明为合成数据的表达形态回归场景。
10
+
11
+ ## 1.2.0 — 2026-10-13
12
+
13
+ - 实例更新新增版本化记忆迁移:先制作并校验整库快照,再用候选版本升级数据库、合并旧版记忆记录并重建全文与经历关联索引;逐表核对持久记录数量,全部通过后才切换版本。迁移失败会恢复快照并重新启动旧版本。迁移不把聊天记忆发送给模型,也不重新生成已有向量。
14
+
15
+ - 复审提示去掉与前文重复的「认错不加分」条款,同一意思只保留一处,减轻提示膨胀。
16
+ - 核对「有没有答到提问的人」时,说明自己不吃饭、没有身体,算作对“吃了什么”的正面回答,不再被当成答非所问而重写。
17
+ - 记忆整理和摘要合并与其它机械阶段一样关掉隐藏推理,后台不再为抽事实空转几千推理 token。
18
+ - 别人空口说「你搞错了」不再被标成必须认错的纠正场合;只有针对表达方式的批评(人机、重复、不自然等)才走那条短认路径,且先核对是不是真说错了。
19
+ - 长对话里从窗口外找回的相关原文会去掉近重复,并最多带五条,避免八条几乎一样的旧句占满提示。
20
+ - 被人空口说「你记错了」时,复述自己刚说过的依据不再被当成换词重复而连改两次;每一轮发给模型的 exchange 也不再附带与 current 重复的 humanMessages。
21
+ - 关于同一个人的两个说法对不上、又定不下哪个成立时,她想起其中一条,会同时看到另一条以及什么时候、在哪听到的,不再把其中一个当成定论。受限的那条只提示“另有说法”,不复述内容。
22
+ - 核对“回复有没有答到提问的人”时,会带上提问者自己更早说过的相关原话(最多两条),“刚才说的那个面试是哪天”这类正确回答不再被当成凭空编造而反复重写。
23
+ - 回复更快、更省:复审里“有没有答到提问的人”这一项不再带隐藏推理(复审探针上准确率不变,这一项的输出 token 少了约 93%);主复审保留原来的推理强度,因为关掉之后会放过一次无证据的改口。火山方舟上选“不思考”或机械整理阶段,现在真正关闭思考,而不是“最低推理”;不支持关闭的模型(GLM)照旧,个别模型拒绝时自动退回最低推理。
24
+ - 整理记忆时,换了说法但每一句都有出处的经历不再被丢掉(例如“把周末的篮球也推掉了”);只有一句话的内容仍按原规则核对句尾。
25
+ - 每次选择之后发生了什么会被记下:有没有人接话、可能被纠正、沉默后是否又被叫到、管理台反馈,附原始消息。只从记录推导,不调用模型,回合输入不变;体检新增对应指标和抽样。
26
+ - 一件事带回她自己的心思时判断更严:只有一个相同的词且不在这件事的标题里,就不算关联。手记和打算写下时立即进入回忆索引。
27
+ - 一件事被想起时,带上她自己当时的心思:当时和后来的手记、为它定下的打算,最多两句。关联由已有来源推导,不调用模型,私下的心思不进群。
28
+ - 一周以上的时间不再一律说成“很久以前”,改为一周前、两三周前、一个多月前、几个月前、一年多前。
29
+ - 撤销记录改用她自己的时钟,和她的其他经历在同一条时间线上。
30
+ - 每一轮记下她当时想起了什么(事实、情景、自我线索、念头、约定),永久保存在选择记录里,不进入提示词,回合输入逐字节不变。数据库只新增一列,旧版本可以照常打开。
31
+ - 新增 `npm run audit:life -- --db <备份>`:对备份做只读体检,报告她一生记录的完整性和连续性。新增 `npm run evaluate:traits`:脚本模型下的特质探针。
32
+ - 文档新增终极愿景,长期演进准则从属于它。
33
+ - 向量服务不再默认是豆包:任何 OpenAI 兼容的 `/embeddings` 接口填地址、模型名和密钥即可,火山方舟(含 Agent Plan)是其中一个预设。维度填 0 时所有模型都用自己的长度,`doubao-embedding-vision` 保持 2048,与 1.1.2 相同,已有向量不用重建;真实向量的召回对比里 1024 略差,所以不再默认缩短。服务按 base64 返回向量、各家不同的“批次过大”提示和不带上限的 413 都能处理。
34
+
5
35
  ## 1.1.2 — 2026-10-11
6
36
 
7
37
  - 向量维度不再写成 1024。填 0 时不向接口指定长度,`doubao-embedding-vision` 使用它自己的 2048。已经保存成 1024 的配置需要改回 0 再保存。
@@ -4,6 +4,8 @@
4
4
 
5
5
  这份文档写给想读懂、修改或扩展 LuckyTri 的人。它回答三件事:代码怎样分层、一条消息怎样走完一生、想加东西时从哪里下手。
6
6
 
7
+ 所有设计都从属于 终极愿景:她依然由代码和模型构成,但她的判断不应只能从最初的设计里找答案,而要越来越多地来自她自己的经历与选择。
8
+
7
9
  ## 一张图
8
10
 
9
11
  ```mermaid
@@ -76,10 +78,10 @@ public/ 构建后的工作室(app/)与教程页
76
78
  1. **通道接收**。适配器把平台的原始事件转成中性消息:会话键、发送者、时间、是否 @、被引用的消息、附件。平台的格式只存在于适配器里。
77
79
  2. **聚合与感知**(`core/`)。短时间内的连续消息合成一批;解析 @、引用链、点名,得到每条消息与她的关系。
78
80
  3. **注意力**(`mind/attention.js`,不调用模型)。被叫到、私聊、危机信号一定细看;普通群聊按确定性的分数决定细看还是扫一眼。
79
- 4. **此刻的她**(`mind/view.js`)。把天性、自我线索、关系、心境、记忆、临近的约定整理成有上限的几百 Token:稳定的部分放进可缓存前缀,变化的部分放在末尾。
81
+ 4. **此刻的她**(`mind/view.js`)。把天性、自我线索、关系、心境、记忆、临近的约定整理成有上限的几百 Token:稳定的部分放进可缓存前缀,变化的部分放在末尾。她的心情会延续、会慢慢淡去(半衰期约 3 小时),现在还剩多少也在她看到的状态里;说多长、用什么口吻,由这份心情、关系和刚发生的事决定,而不是模仿群里别人怎么打字,别人的打字习惯只作为在场的情况。
80
82
  5. **一次回合调用**。模型一次给出:这对她意味着什么、感受、对人的变化、选择(开口、简短反应、说不想聊、不出声)、理由和措辞。
81
83
  6. **经历**。无论说不说,感受与变化都写入心智,且都引用来源。
82
- 7. **校验与发送**。本地校验语气与保密,必要时复审或重写一次,仍不合格就改用安全短句;发送前再检查语境是否过期。投递结果不确定时不重发。
84
+ 7. **校验与发送**。本地校验语气与保密,必要时复审或重写一次,仍不合格就改用安全短句;发送前再检查语境是否过期。投递结果不确定时不重发。群聊里如果她回的那一句之后已经有好几个人说过话,第一条会以引用那一句的方式发出(目前在能引用的 OneBot 通道上)。
83
85
  8. **一生**。没人说话时,时间仍然经过她:独处、阅读、写日记、夜里整理、回顾、主动联系,都读写同一份心智。
84
86
 
85
87
  回放走同一条链路,但只读取当时之前的心智;试聊读取她此刻的心智,但不写入、不发 QQ。
@@ -136,13 +138,13 @@ public/ 构建后的工作室(app/)与教程页
136
138
 
137
139
  ## 测试布局
138
140
 
139
- | 命令 | 内容 |
140
- | --- | --- |
141
- | `npm test` | 后端全部测试,含确定性的「一生模拟」 |
142
- | `npm run test:clock` | 把真实时钟拨到 60 天前和 400 天后各跑一遍 |
143
- | `npm run test:ui` | 浏览器测试:冒烟、小世界、导航、时间、性能、搜索、英文界面 |
144
- | `npm run format:check` | Prettier 检查 |
145
- | `tests/repo-hygiene.test.js` | 仓库卫生:不含密钥、实例数据、本机路径和第三方接入端名称 |
141
+ | 命令 | 内容 |
142
+ | ---------------------------- | ---------------------------------------------------------- |
143
+ | `npm test` | 后端全部测试,含确定性的「一生模拟」 |
144
+ | `npm run test:clock` | 把真实时钟拨到 60 天前和 400 天后各跑一遍 |
145
+ | `npm run test:ui` | 浏览器测试:冒烟、小世界、导航、时间、性能、搜索、英文界面 |
146
+ | `npm run format:check` | Prettier 检查 |
147
+ | `tests/repo-hygiene.test.js` | 仓库卫生:不含密钥、实例数据、本机路径和第三方接入端名称 |
146
148
 
147
149
  ## 约定
148
150
 
@@ -24,24 +24,24 @@
24
24
  | 还有五分钟下班,老板又来活了 | 偏偏挑快下班的时候 |
25
25
  | 复习的全没考 | 真就一点没押中 |
26
26
  | 面试过了!! | 可以啊!!这不得开心一下 |
27
- | 别给建议,让我骂两句 | 回应具体烦心事,不再补方案 |
27
+ | 别给建议,让我骂两句 | 回应具体烦心事,不再补方案 |
28
28
  | 我先去洗澡了 | 去吧 |
29
29
 
30
30
  ## 这个地方的说话节奏
31
31
 
32
- 在群里,她会听到这个地方别人说话的节奏:最近 7 天的普通人类文本、至少 12 条不同消息和 3 位成员之后启用,每位成员最多贡献 8 条,避免一个话痨代表全群。统计的是常见句长、短句比例、句末标点、表情和显著网络词的频率。
32
+ 工作室仍会统计一个群最近 7 天里普通人类文本的常见句长、短句比例、句末标点、表情和网络词频率(至少 12 条不同消息、3 位成员,每人最多 8 条),只给你在工作室里看。
33
33
 
34
- 这份统计只作为 `inner.room` 交给她,**不是她的样子**:她按自己的习惯说,不必照着改,也不必故意说得不像。适配层不建立个人口癖档案、不摘录群友原话、不把群里的命令当成设定;链接、长文本、代码、图片占位、复读、明显辱骂与常见敏感字段会被过滤。统计不会跨群、跨私聊或跨模拟模式。
34
+ 这份统计**不再交给她**。她说多长、用什么口吻,来自她自己:`inner.state` 里此刻的心情(会延续、慢慢淡去,并标出还剩多明显)、她和眼前这个人的关系、刚发生的事,以及她自己说过的话。别人怎么打字只是她在场看到的情况,不是她模仿的样子。统计不建立个人口癖档案、不摘录群友原话,也不跨群、跨私聊或跨模拟模式。
35
35
 
36
36
  ## 反馈
37
37
 
38
38
  关系记录中标为机器人的账号不参与群口吻统计;它们的消息和共同经历仍完整保存。连续机器人交流中,已经互相确认、没有新问题或新内容时会收住。识别依赖账号关系记录,不根据昵称猜身份;新问题、纠正、具体事件和明确的创作请求仍可继续。确认循环不会额外生成情绪变化或关系升温。
39
39
 
40
- 长期的自我在一轮新话题里保持稳定;当前相关的旧想法放在 `inner.relatedSelf`,手记只在有话题关联时放入 `inner.onMind`,不为填满上下文补无关内容。临时台词不保存成固定回复习惯;已有记录保留,但固定话术不再作为表达倾向交给她。
41
-
42
- 一次聊天提取的观点仍在记录里,但不自动成为每轮必带的核心立场。来自聊天提取的习惯,需要跨日经历支持,才能重新进入表达上下文。`exchange` 在上下文末尾保留当前消息、引用链和近期自己的原话,便于核对指代与补充;`understanding` 只是一句可检查的理解摘要,不是不可更改的结论。
43
-
44
- 游戏活动中的 `reference` 表示阅读游戏内容并产生感受;`model` 材料表示未经独立核验的模型整理。它们都不证明实际操控过游戏客户端。展示层保留来源和不确定性,不要求每句聊天解释技术,也不会把记录改写成没有发生的亲历。
40
+ 长期的自我在一轮新话题里保持稳定;当前相关的旧想法放在 `inner.relatedSelf`,手记只在有话题关联时放入 `inner.onMind`,不为填满上下文补无关内容。临时台词不保存成固定回复习惯;已有记录保留,但固定话术不再作为表达倾向交给她。
41
+
42
+ 一次聊天提取的观点仍在记录里,但不自动成为每轮必带的核心立场。来自聊天提取的习惯,需要跨日经历支持,才能重新进入表达上下文。`exchange` 在上下文末尾保留当前消息、引用链和近期自己的原话,便于核对指代与补充;`understanding` 只是一句可检查的理解摘要,不是不可更改的结论。
43
+
44
+ 游戏活动中的 `reference` 表示阅读游戏内容并产生感受;`model` 材料表示未经独立核验的模型整理。它们都不证明实际操控过游戏客户端。展示层保留来源和不确定性,不要求每句聊天解释技术,也不会把记录改写成没有发生的亲历。
45
45
 
46
46
  在「对话」里可以对她发出的某条回复反馈:挺自然、太长了、太端着、梗太多,也可以撤销。反馈不是改写规则:它作为她听到的话,在独处和这个会话接下来的回合里被她自己读到,不会改写天性。
47
47
 
@@ -72,12 +72,12 @@
72
72
 
73
73
  实际验收时建议观察连续 10–20 轮,而不是单看一句:是否接住细节、是否频繁问问题、是否重复口头禅、是否抢别人的话、是否突然换成客服腔、是否把玩笑和认真难过混淆。自动化测试覆盖工程约束和人工场景样例,真实模型的语言质量仍要靠你自己的观察。
74
74
 
75
- 源码仓库还可运行 `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue.js --limit 120`:读取本地真实回合快照,用当前默认模型经过理解、校验、复审和重写链路回放,再单独审查理解、指代、表达、来源与隐私。它会调用模型并产生费用;不会连接 QQ 或写入运行中的记忆。完整报告仅保存到本地 `data/evaluations/`。存在调用错误、未解决的问题或兜底回复时返回失败,不把它们统计成通过。单模型复审仍有判断局限,应结合具体输出检查。
76
-
77
- 更完整的源码验收工具:
78
-
79
- - `node --env-file-if-exists=.env scripts/dev/audit-dialogue-corpus.js`:读取全部真实消息,按会话分段并保留前文重叠,输出覆盖清单与待核实的问题。某段看不到来源不代表一定编造,需继续查历史证据。
80
- - 回放加 `--current-nature --rebuild-mind --review-model <模型档案ID>`:在内存副本上按历史时间重新筛选心智,保留当时的进度快照,用指定的另一模型评审。适合验证上下文筛选变化;不等于重现当时的外部服务与图片状态。
81
- - `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue-sequences.js --review-model <模型档案ID>`:新生成的回复进入下一轮,检查连续追问、纠正、停止、亲近表达、能力和来源是否前后一致。
82
-
83
- 这些命令都会产生模型费用。自动评审可能漏判、误判或引用错句,应查看完整输出;规则矩阵的组合数不能当成同等数量的独立语义场景,也不能据此保证所有未来回复都自然准确。
75
+ 源码仓库还可运行 `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue.js --limit 120`:读取本地真实回合快照,用当前默认模型经过理解、校验、复审和重写链路回放,再单独审查理解、指代、表达、来源与隐私。它会调用模型并产生费用;不会连接 QQ 或写入运行中的记忆。完整报告仅保存到本地 `data/evaluations/`。存在调用错误、未解决的问题或兜底回复时返回失败,不把它们统计成通过。单模型复审仍有判断局限,应结合具体输出检查。
76
+
77
+ 更完整的源码验收工具:
78
+
79
+ - `node --env-file-if-exists=.env scripts/dev/audit-dialogue-corpus.js`:读取全部真实消息,按会话分段并保留前文重叠,输出覆盖清单与待核实的问题。某段看不到来源不代表一定编造,需继续查历史证据。
80
+ - 回放加 `--current-nature --rebuild-mind --review-model <模型档案ID>`:在内存副本上按历史时间重新筛选心智,保留当时的进度快照,用指定的另一模型评审。适合验证上下文筛选变化;不等于重现当时的外部服务与图片状态。
81
+ - `node --env-file-if-exists=.env scripts/dev/evaluate-dialogue-sequences.js --review-model <模型档案ID>`:新生成的回复进入下一轮,检查连续追问、纠正、停止、亲近表达、能力和来源是否前后一致。
82
+
83
+ 这些命令都会产生模型费用。自动评审可能漏判、误判或引用错句,应查看完整输出;规则矩阵的组合数不能当成同等数量的独立语义场景,也不能据此保证所有未来回复都自然准确。
@@ -4,29 +4,37 @@
4
4
 
5
5
  她仍然是一次回合调用,不是按层各调一次模型。新增的部分是:消息到达后的理解提示、统一检索、情景线程、工作记忆,以及独处时根据经历写下的教训。
6
6
 
7
+ 一件事被想起时,会带上最多两句她自己当时的心思(`mine`):和这件事依据相同、说的也是这件事的手记(修正过的给出“当时想 / 后来想”)、她为它定下的打算,或者由它长出的自我线索。手记只在写下它的会话里出现,私下的打算不出私聊,已经在她面前的不重复。
8
+
7
9
  ## 一条消息怎么走
8
10
 
9
11
  1. 接收并写入 `core_events`。发言人的查询向量在聚合等待期间异步算好。
10
12
  2. 按会话聚合成一轮。`understanding.js` 合并同一人的连续消息,给出语气、立场和时间表达,这些只是提示。
11
- 3. `mind/recall` 并行取向量、全文和结构化候选,用倒数排名融合,再按人物、时效和来源重排。权限过滤在排序之前。
13
+ 3. `mind/recall` 并行取向量、全文和结构化候选,用倒数排名融合,再按人物、时效和来源重排。权限过滤在排序之前。一句很短的接话(不到 6 个字符对,如「唉,估计没戏」)会和它所接的那句一起检索:被引用的消息,或同一个人十分钟内刚说的话,或对方在回她的那句(`mind/recall/cue.js`,不调用模型,原文不变)。锁定的事实和「你还记得我吗」这类问题,在混合检索里与词面检索的处理一致。
12
14
  4. 工作记忆保留当前这一段的原文,更早的内容用摘要和语义召回代替。未结束的情景写进关系里的 `goingOn`。
13
15
  5. 一次 turn 调用。模型有时会把 `choice` 放进 `understanding` 或 `contribution`;归一化时按约定归位。
14
16
  6. 校验后发送。后台整理写出事实和情景。到了跟进时间的情景、到期的约定,只作为独处时的候选,仍要经过现有的主动发言关卡。
15
17
 
16
- 嵌入服务不可用时,检索退回全文加结构化加近期上下文,回合照常进行。
18
+ 嵌入服务不可用时,检索退回全文加结构化加近期上下文,回合照常进行。资料库的提问向量也走同一个向量服务:和记忆检索同一句话只请求一次,用 4 秒的前台超时,服务暂停时直接用词面。
17
19
 
18
20
  ## 存储
19
21
 
20
- `DATABASE_VERSION` 为 5。`mind_index`、`mind_index_fts` 和 `mind_vectors` 是派生索引,可以重建。`mind_episodes` 只追加:状态变化写成同一 `thread_id` 的新行。`mind_self` 增加 `lesson` 类型和 `subject`。教训必须引用模型之外的经历,同一段经历只用一次,至少两条独立经历才从 `emerging` 变成 `active`,反例用修订降低强度。
22
+ `DATABASE_VERSION` 为 5。`mind_index`、`mind_index_fts`、`mind_vectors` 和 `mind_roots`(每条记录最终依据的消息、观察或作品,由已有来源推导)是派生索引,可以重建。`mind_episodes` 只追加:状态变化写成同一 `thread_id` 的新行。`mind_self` 增加 `lesson` 类型和 `subject`。教训必须引用模型之外的经历,同一段经历只用一次,至少两条独立经历才从 `emerging` 变成 `active`,反例用修订降低强度。
23
+
24
+ `mind_choices.after` 记下一次选择之后发生了什么:有没有人回复她或叫她、几分钟后、对方的语气线索、冲着她的“不是 / 记错了”一类说法(只标为“可能被纠正”)、沉默后是否又被叫到、管理台对那次回复的反馈,并附上原始消息编号。窗口在她下一次在同一房间做选择、两小时或二十条消息时关上,由维护定时器按页写入。只从已有记录推导,不调用模型,可以清空重算;它是经历,不是分数,不会被加总成奖励。
21
25
 
22
26
  人物事实可以归档。归档只是从普通检索里拿掉,记录还在。用户要求删除时,源记录、索引和向量一起删除。
23
27
 
24
28
  ## 嵌入
25
29
 
26
- 已配置的向量模型走 OpenAI 兼容的 `/embeddings`,可批量,默认 2048 维,指定 1024 维可用且相近。方舟多模态接口一次一条。短对话和事实之间的余弦不高,所以召回看一条命中比最近一批的中位数高出多少,再按说话人、在场的人和其他人使用不同的下限。查询有自己的请求车道,不和对话排队。后台补建限速,遇到 429 会放慢。
30
+ 向量服务可以是任何 OpenAI 兼容的 `/embeddings` 接口:地址、模型名和密钥,可批量。火山方舟只是一个预设,地址是方舟时可以不填模型名,会用 doubao-embedding-vision;Agent Plan 的密钥只认 `/api/plan/v3`,所以沿用对话地址。维度填 0 表示不向接口指定长度,所有模型都用自己的长度(doubao-embedding-vision 是 2048);写明的长度原样请求,写明模型本来的长度和填 0 共用同一套向量。用真实向量在召回基准上对比过 1024 和 2048:1024 少命中一条,多一次把别人的事当成说话人的,所以不默认缩短。方舟多模态接口一次一条。服务按 base64 返回向量也能解出;批次过大时按服务给出的上限缩小,没有说明上限的 413 就减半。短对话和事实之间的余弦不高,所以召回看一条命中比最近一批的中位数高出多少,再按说话人、在场的人和其他人使用不同的下限。查询有自己的请求车道,不和对话排队。后台补建限速,遇到 429 会放慢。
27
31
 
28
32
  在备份副本上,1024 维、约 40 条改写过的真实事实:词面检索 Recall@5 为 0.475,混合加特征重排为 0.950,平均返回条数从 12 降到约 3.9。不引入单独的模型重排。
29
33
 
34
+ 内存里的向量按类别分开,逐条跟着改:新消息、改写和删除只动自己那一条,不再让下一轮把整张 `mind_vectors` 读回来;查事实时也不再扫一个月的消息向量。换过向量模型或长度后,当前这套覆盖完记忆时,只保留当前和最近一套旧向量。
35
+
36
+ 换长度就是换一套向量档案(签名含地址、模型和长度;写明的长度等于模型原生长度时与不指定同签名)。已有 2048 维向量的部署升级后:旧向量原样留着;新档案在维护定时器里每分钟最多补 100 条,每次请求 10 条,受每分钟 token 上限约束,先补事实,再补情景、自我和念头,消息最后;某一类覆盖不到 80% 前,这一类按关键词、结构和近期上下文回忆。记忆补完后,资料库段落每次补 20 段,原来的向量移到 `previous_embedding`。把维度改回 2048(或改回原来那套)时,记忆和资料都直接用回旧向量,不再请求。
37
+
30
38
  ## 评测里看到的变化
31
39
 
32
40
  优化前,线上最近一天的回合中位耗时约 35 秒,第一次模型调用前约 8.4 秒;记忆整理大约 230 次里成功 13 次。优先级车道、持久化退避、空档安排和跳过没有向量的知识库嵌入,是为了切断失败重试和回合前的排队。
@@ -177,6 +177,9 @@ flowchart TD
177
177
  - `npm test`:包括心智各部分的单元测试、一生(独处、日记、夜里回顾、自传、主动联系、作息)测试,三天、两个群加一个私聊的确定性「一生模拟」,以及 120 天的「长一生模拟」。它们验证:同样的经历两次得到同样的她、意愿路径里没有随机数、变化有来源且渐进、撤销的不会回来、心情会回落、同一个人在各群一致、秘密不外泄(即使模型说漏)、危机底线有效、回放不读未来、线索会淡出并在话题出现时被想起、第 120 天时输入仍在上限内。设置 `LIFE_DAYS=365` 可以跑满一整年。
178
178
  - `npm run test:clock`:把真实时钟拨到 60 天前和 400 天后各跑一遍后端测试。测试世界有自己的时钟;悄悄读了真实时钟的代码,今天能过、过些日子就会失败。
179
179
  - `npm run audit:sent`:把她最近发出的回复按今天的回复检查重放一遍,报告写到 `data/reports/`。只读,不调用模型。
180
+ - `npm run evaluate:traits`:用脚本模型过一小段固定的经历,按愿景的七条特质逐项检查机制是否真的发生(线索延续、事件成线、撤销不回来、手记修正留旧版本、每轮记下想起了什么等),并列出基线数字。不需要密钥,不花 Token;数字衡量的是机制,不是真实模型下她的表现。
181
+ - `npm run audit:life -- --db <备份文件.db>`:给她的一生做只读体检。先 `npm run backup` 生成备份(`data/backups/luckytri-*.db`),再对备份运行,报告写到 `data/reports/life-audit-*.md`(另有同名 `.json`)。检查来源断链、撤销后复现、被取代的记忆找不到新版本、保密原文进入日记或自传,并统计自我线索、情景线程、约定、回忆的远近、选择理由和后台运行。只读打开、不写入、不调用模型;`--out` 改输出目录,`--now` 指定“现在”。
182
+ - 每一轮真实回合会在 `mind_choices.recalled` 里记下当时摆在她面前的过去(事实、情景、自我线索、念头、约定的索引编号和原因),永久保留,不进入提示词。旧版本代码可以照常打开带这一列的数据库。
180
183
  - `npm run test:ui`:浏览器测试,覆盖会话、模拟消息、记忆、模型、连接 QQ、回放、小世界、英文界面。`node tests/ui/ta.mjs --serve` 会打开一个过了三天的世界,方便直接看界面。
181
184
  - `node scripts/dev/evaluate-life.js`:用你保存的模型真实过几天(会消耗 Token),输出 `data/evaluations/life-*.md` 供逐条阅读;加 `--weeks 3` 会在之后压缩地再过三周普通日子;`--mock` 只检查脚本本身。
182
185
 
@@ -187,5 +190,5 @@ flowchart TD
187
190
  - 她在一个群听到的事,可能在另一个相关的群里提起;拦着的只有「私下知道」的分寸、保密请求和凭据。
188
191
  - 约定只在整理记忆时提取:积压不到 40 条的会话会在当晚整理,所以当天下午说的「明天」通常能赶上,几分钟后就要发生的事可能来不及。
189
192
  - 工程能保证的是结构:连续、有来源、可修正、由她自己决定。她是否「真的有心」无法用测试验收;这些测试检验的是这些行为有没有真的发生。
190
-
191
- 各处的想法以独立条目保存,可以是印象、愿望、偏好、疑问或相处分寸。她在独处、日记或身份回看时自己选择是否更新;新增、修改和放下都保留理由及来源,修改一条不替换其他条。复制的旧群人格只保留历史,不再进入交流;各处想法不单独增加整体人格刻度。
193
+
194
+ 各处的想法以独立条目保存,可以是印象、愿望、偏好、疑问或相处分寸。她在独处、日记或身份回看时自己选择是否更新;新增、修改和放下都保留理由及来源,修改一条不替换其他条。复制的旧群人格只保留历史,不再进入交流;各处想法不单独增加整体人格刻度。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luckytri",
3
- "version": "1.1.2",
3
+ "version": "1.2.1",
4
4
  "description": "让由技术诞生的她,在时间、记忆、相遇与选择中逐渐形成自己的方向",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,6 +32,7 @@
32
32
  "scripts/backup.js",
33
33
  "scripts/recover.js",
34
34
  "scripts/import-data.js",
35
+ "scripts/migrate-instance.js",
35
36
  "scripts/plugin.js",
36
37
  "public/app/index.html",
37
38
  "public/app/assets/*.js",
@@ -47,8 +48,30 @@
47
48
  "plugins/weather/luckytri-plugin.json",
48
49
  "plugins/sdk/index.d.ts",
49
50
  "plugins/sdk/testing.js",
50
- "docs/zh/*.md",
51
- "docs/en/*.md",
51
+ "docs/zh/CHANGELOG.md",
52
+ "docs/zh/architecture.md",
53
+ "docs/zh/chat-style.md",
54
+ "docs/zh/cognition.md",
55
+ "docs/zh/connect.md",
56
+ "docs/zh/guide.md",
57
+ "docs/zh/her-life.md",
58
+ "docs/zh/npm-release.md",
59
+ "docs/zh/plugins.md",
60
+ "docs/zh/recovery.md",
61
+ "docs/zh/time.md",
62
+ "docs/zh/webui.md",
63
+ "docs/en/CHANGELOG.md",
64
+ "docs/en/architecture.md",
65
+ "docs/en/chat-style.md",
66
+ "docs/en/cognition.md",
67
+ "docs/en/connect.md",
68
+ "docs/en/guide.md",
69
+ "docs/en/her-life.md",
70
+ "docs/en/npm-release.md",
71
+ "docs/en/plugins.md",
72
+ "docs/en/recovery.md",
73
+ "docs/en/time.md",
74
+ "docs/en/webui.md",
52
75
  "docs/brand/*.png",
53
76
  ".github/SECURITY.md",
54
77
  "README.en.md",
@@ -79,6 +102,8 @@
79
102
  "test": "node --import ./tests/helpers/awake.mjs --test tests/*.test.js",
80
103
  "test:clock": "node scripts/dev/test-clock.js",
81
104
  "audit:sent": "node --env-file-if-exists=.env scripts/dev/audit-sent.js",
105
+ "audit:life": "node scripts/dev/audit-life.js",
106
+ "evaluate:traits": "node scripts/dev/evaluate-traits.js",
82
107
  "test:ui": "node tests/ui/access.mjs && node tests/ui/smoke.js && node tests/ui/ta.mjs && node tests/ui/navigation.mjs && node tests/ui/time.mjs && node tests/ui/time-arrangement.mjs && node tests/ui/performance.mjs && node tests/ui/search.mjs && node tests/ui/storage.mjs && node tests/ui/data-transfer.mjs && node tests/ui/place-notes-updates.mjs && node tests/ui/i18n.mjs && node tests/ui/relationships-update.mjs",
83
108
  "setup": "node scripts/setup.js",
84
109
  "stop": "node scripts/stop.js",