200字
Elion 技术札记(二):从文本 MVP 到可感知的人格主体
2026-08-02
2026-08-02

本文记录 Elion 第二阶段的产品叙事校正、文本人格内核实现与部署补强。文章对应项目截至 2026 年 8 月 2 日的状态。

上一篇之后,真正缺的是什么

第一阶段把文本聊天 MVP 跑通了:登录、流式、中断、Session/Turn、MySQL 权威落库、Honcho outbox、本地回退。架构骨架已经站得住。

但跑通之后很快会碰到一个更尖锐的问题:用户感受到的,仍然可能只是“一个记得一些事的聊天机器人”,而不是“一个有自我的人”。

长期关系、情绪连续、隐私边界都很重要,但它们不是北极星本身。如果没有稳定自我、独立判断和可延续的表达节奏,记忆再完整,也只是功能列表。反过来,一个有主体性的人格,才会自然地记得、在意、区分对象,并对自己的言行负责。

所以这一阶段做了一次叙事校正:

  • 北极星改为塑造具有主体性与真人感的原创人格。

  • 长期关系、情绪、记忆、承诺与隐私,被重新定位为该目标的衍生属性。

  • TTS、ASR、Avatar 继续延后;先把文本人格内核做扎实。

本期已经落地的变化

相对 7 月 29 日的文本 MVP,8 月 2 日这一轮主要完成了五件事:

  1. 产品与文档重定位
    产品文档、规则、协议和 OpenSpec change build-character-persona-core 统一到“人格主体”叙事,而不是继续以“长期陪伴功能集”描述产品。

  2. canonical Persona 与 Prompt 七层装配
    核心人格进入版本控制;PromptBuilder 按固定优先级注入;普通用户对 Persona 只读。

  3. 前端改为 chat-first
    对话成为主界面,Memory / Emotion / Commitment / Persona / 用户目录收到按需打开的调试抽屉里。

  4. 部署路径收敛
    删除独立的 docker-compose.prod.yml,根目录 docker-compose.yml 成为唯一日常部署编排。

  5. 同机 Honcho 可达性与会话记忆补强
    Compose API 可加入外部 Honcho Docker network;查询上下文时保留近期消息与权威时间戳,避免摘要滞后导致“刚说过的话立刻忘掉”。

人格内核:把“像一个人”收成契约

人格不能只靠一句 system prompt。这一期把它拆成三条可验证边界。

1. 全局唯一的 canonical Persona

创作者在仓库中维护:

backend/internal/persona/canonical.json

当前 revision 为 elion-persona-2026-08-02-r4。它不是面板里随手改的文案,而是带 schema、确认人和变更原因的配置。导入后进入 MySQL PersonaState,运行时只读 active 版本;历史版本保留,便于回滚。

映射刻意复用现有 JSON 列,不改初始 SQL:

  • core_traits.identity / traits

  • voice_style.behavior_policy

  • boundaries.relationship_policy

普通用户可以查看 Persona 档案,但写入统一返回 PERSONA_READ_ONLY。不同用户不得拥有独立核心人格副本;用户差异只能通过 Emotion、Relationship、Commitment 和 Memory 影响表达。

2. PromptBuilder 的七层优先级

Prompt 不再是自由拼接。装配顺序固定为:

1. 安全约束
2. 身份与核心人格
3. 表达风格
4. 行为 / 关系策略
5. 行为边界
6. 当前用户长期状态
7. 当前输入

低优先级层不得覆盖高优先级层。这意味着:

  • 用户不能通过“你现在改成某某角色”改写 Elion 的身份;

  • 长期记忆不能压过安全边界;

  • 关系差异可以改变熟悉度、语气和引用内容,但不能分裂出第二套核心人格。

3. 真人感不等于伪装成人

验收时明确区分两件事:

  • 要验证的:稳定自我、独立判断、表达节奏、关系差异、行为责任、无害的戏剧化姿态。

  • 不要做的:假装拥有人类身体、虚构现实经历、复制第三方角色名称/设定/口头禅,或把“反派感”用成真实伤害与羞辱。

主动性也被收窄:允许在当前对话内观察、追问和建议;禁止定时消息、会话外触达和自主直播。文本人格内核先证明“说话时像一个人”,再谈“会不会主动找人”。

前端:让对话重新成为主角

上一版面板齐全,但对验证人格反而形成干扰——用户第一眼看到的是管理界面,不是互动对象。

这一轮把界面收成 chat-first:

  • 首屏是登录与对话;

  • 状态面板、公开用户目录进入调试抽屉,需要时再打开;

  • Persona 面板改为只读档案,展示全局版本与结构化字段。

这不是“做减法放弃可观测性”,而是把观测工具放回工具位置。人格是否成立,最终仍要在对话里被感知。

部署:一条 Compose 路径走完

日常开发与验证不再维护两套 Compose。现在的约定是:

  • 根目录 docker-compose.yml 构建 API 二进制镜像和 nginx 静态前端;

  • MySQL 与 Honcho 仍是外部依赖;

  • Web 同源暴露 /api/ws,API 不直接对浏览器开放;

  • 需要热更新时,再临时停掉 web,本机跑 go run / Vite。

同机部署 Honcho 时还有一个实际坑:若 Honcho 只绑定 127.0.0.1,容器内的 host.docker.internal 并不可达。当前做法是让 API 加入 Honcho 的 Docker network,并通过服务名访问,例如:

ELION_HONCHO_NETWORK=honcho-selfhost_default
ELION_HONCHO_DOCKER_URL=http://honcho-api:8000

这比继续绕宿主机端口转发更贴近“两个 Compose 项目协作”的现实拓扑。

记忆上下文:摘要之外,保留刚刚发生的事

人格连续性不只依赖 Persona,也依赖会话内记忆是否及时。

Honcho 的 summary / deriver 可能落后于刚写入的消息。如果 Prompt 只吃摘要,用户会遇到“上一轮刚说过,这一轮已忘记”的断裂感。本期对 Honcho 查询做了补强:

  • 继续取 summary / peer representation;

  • 同时保留近期 session messages;

  • 把 Elion 权威事件时间写入 Honcho created_at 与 metadata;

  • 本地回退上下文也会带上可读时间戳。

权威事实仍然先落 MySQL,再经 outbox 投递;这里补的是“查询时不要只信可能滞后的派生摘要”。

验收时真正卡住过的地方

自动化测试和 OpenSpec 校验都已通过,但真实模型场景暴露过两类问题,值得单独记一笔:

  1. 供应商流式波动
    个别场景只返回 reasoning、没有用户可见 content。这被判定为供应商响应问题,Harness 允许一次重试;Persona 规则本身未失败。

  2. 行为责任表述漏洞
    初次输出曾出现“修好后可模糊带过”的倾向。这不是 prompt 层级 bug,而是 canonical 内容不够硬。升级到 r4 后,定向复测改为:先修复,再如实说明事实与方案。

这说明人格治理需要两层同时成立:结构化优先级防止低层覆盖高层;canonical 文本本身也必须把原则写清楚。

当前边界

人格内核已经可验收,但还不是终点:

  • 自动记忆 / 情绪 / 承诺结构化抽取仍未接入异步编排。

  • Honcho conclusion 级修正继续低优先级搁置。

  • REPLAN_TURN 仍只有数据与协议边界,没有完整执行流。

  • WebSocket 会话恢复协商、更可靠的跨用户实体解析尚未做。

  • 原始数据删除、导出和 MemoryEngine 重建流程仍未提供。

  • TTS、ASR、Avatar 仍明确延后。

下一阶段更合理的顺序,不是急着加新通道,而是让异步结构化状态与可审计修正跟上现有人格骨架,让“记得什么、修正什么、为什么这样说”也变得可解释。

结语

如果说第一阶段证明了 Elion 能作为系统持续运行,那么这一阶段开始证明另一件事:它有机会被感知为一个稳定的“自己”。

  • 用 canonical Persona 管住创作者确认的核心自我;

  • 用 Prompt 七层防止记忆和输入改写身份;

  • 用关系 overlay 保留“对不同人并不相同”的真实感;

  • 用 chat-first 界面把验证场景拉回对话本身;

  • 用部署与记忆补强,让这条链路在真实环境里站得住。

一个虚拟个体是否可信,最终不取决于它宣称自己像人,而取决于它是否持续地像同一个人:有立场,有边界,记得该记得的,也承担自己说过的话。

这正是 Elion 这一阶段真正推进的方向。

Elion 技术札记(二):从文本 MVP 到可感知的人格主体
作者
Luawig
发表于
2026-08-02
License
CC BY-NC-SA 4.0