NT-Sine 玄玖
NT-Sine 图标

NT-Sine 本地情感陪伴模型

以 Qwen3-4B 为基座的中文情感陪伴系统:六层世界书约束人格,三层记忆持久化事实, 五维状态机描述情绪,五阶段模型表达关系演进。全部推理在本机完成。

v3.4 · 训练数据重建中 全离线推理 单角色 · 单用户

五层架构已实现并通过 45 项回归测试与 22 项冒烟测试;模型微调处于数据重建阶段,历史适配器已清除。

项目定位

角色化对话系统,而非通用助手

本项目面向单一用户,输出目标是角色化的情感回应。与三类常见系统存在明确的技术边界。

对照类型技术差异
通用对话助手 不承担指令执行与知识问答职能,不追求任务完成,只做角色回应。
角色扮演前端 包含模型微调、状态持久化与服务端逻辑,不仅是提示词外壳。
纯提示词方案 人格、关系、记忆持久化至存储层,并对模型做语气层微调,不依赖单次提示维持一致性。

非目标范围:不做多角色、不做多用户、不做云端服务、不提供通用助手能力。

核心机制

九项可测量的设计

每项均给出机制与关键参数;所有参数可在 config/settings.yaml 中修改。

M-01

世界书:结构化事实注入

角色设定拆为六层条目,按关键词触发注入,不做全量拼装。总预算上限 1600 token,分层独立预算, 超限整条丢弃而非截断。中文环境强制禁用「整词匹配」;仅 L4 层允许递归,上限 3 步; L4 同刻仅保留优先级最高一张,防止场景语义混合。

M-02

记忆:三层存储与双路召回

短期对话、中期结构化事实、长期里程碑分表存储于 SQLite。检索采用「固定画像 + 关联召回」并行: 画像每轮必带,另按 2-gram 二元组重叠召回至多 4 条。同内容累加提及次数而不新增行; 七类记忆各有容量上限,超限按时间从旧到新淘汰。

M-03

情感:五维数值与冲突锁定

五个连续变量描述角色状态,数值不进入上下文,转换为 60-100 字自然语言投影后注入。 单轮变化均有上限:情绪 ±0.15、好感 +2、信任降 8 升 1.5。冲突期间情绪锁定负值, 需致歉且情绪回正才解除。

M-04

关系:五阶段三轴判定

关系状态分冷淡、破冰、依赖、占有、病娇五阶段,由累计互动天数、亲密值、信任值共同判定。 四项防跃迁设计:天数按自然日去重、亲密仅由事件触发、信任为双向门限、逐级判定不可跳跃。

M-05

过滤:八步串联校验

输出依次经控制标签剥离、硬性违规、设定暴露、旁白化、复读、客服腔、过度附和、长度超限八项校验。 命中即按策略处理:剥离、角色内替换、裁剪或标记重生成(上限一次)。拒绝行为在角色内完成, 不输出系统层声明。

M-06

节奏:分条与停顿建模

单次输出拆为多条消息,单条上限 25 字、最多 4 条。打字速度 4-7 字/秒,首条不短于 0.8-2.0 秒; 条间停顿 0.6-2.5 秒,其中 20% 概率延长至 3-9 秒;末条停顿为 0。

M-07

主动消息:三重闸门与放弃率

依次通过时机、话题、话术三道判定;全部通过后仍有 35% 概率放弃发送,以规避固定频率行为。 检查间隔 10 分钟,每日上限 3 次,最小间隔 2 小时,1-6 点静默。

M-08

日记:九角度轮换

每日 23:00-01:00 生成第一人称独白,规格 100-200 字、句号结尾、不使用语气助词。 写作角度九类,按「一年中的第几天取模」确定,同日稳定、跨日轮换;当日已存在则跳过。

M-09

微调:语气与事实解耦

微调仅承担表达风格,事实性内容由世界书与记忆系统提供。训练样本注入场景卡与关系阶段卡, 与推理期注入结构一致;数据按关系阶段分层,使关系演进成为模型能力而非提示词模拟。

架构设计

五层结构与单轮处理流程

每层职责单一,层间通过明确定义的数据结构传递,不共享可变状态。

LAYER 1 调度层 场景档位判定、回复延迟、主动开口判断、回复长度决策
LAYER 2 记忆层 滑动窗口 + SQLite 四表 + 六层世界书引擎
LAYER 3 情感引擎 五维状态机 + 五阶段关系模型 + 通道交互
LAYER 4 生成层 Qwen3-4B 融合模型 → 采样 → 八步过滤 → 节奏化输出

第五层为离线演进层:数据构造 → 阶段分层 → 手动 LoRA 训练 → 确定性评测 → 版本对比,由人工触发,不参与在线链路。

单轮处理流程

输入
  ├─ 01 写入 messages 表(短期记忆)
  ├─ 02 场景档位判定   命中深度触发词且 ≤30 字 → deep(扫描 15 条)
  │                    ≥40 字 → normal(8 条);其余 → daily(6 条)
  ├─ 03 世界书扫描     关键词 → 正则 → L4 递归 → L4 互斥 → 预算裁剪 → 分层排序
  ├─ 04 记忆召回       滚动画像(必带)+ 2-gram 关联召回(≤4 条)
  ├─ 05 上下文拼装     系统提示 + 最近 10 条消息 + 本轮输入(尾部附情感投影)
  ├─ 06 模型生成       OpenAI 兼容接口,采样参数双写;失败回落角色兜底句
  ├─ 07 输出过滤       八步校验,命中复读或过度附和时重生成一次
  ├─ 08 节奏化         切句 → 分条 → 打字时长与条间停顿
  ├─ 09 情感更新       信号抽取 → 五维推进 → 通道交互 → 天数累计 → 冲突判定 → 持久化
  └─ 10 记忆抽取       每 4 轮一次,七类入库,超容量 FIFO 淘汰

上下文预算分配

层内容预算保留优先级
L1角色锚点(常驻)3500
L6边界规则(常驻)1501
L3情感状态(动态)1002
—未解决事项(动态)—3
L2用户画像(常驻)1804
L4场景卡直接命中(最多 1 张)5005
L5当前场景(动态)2006
L4递归引入的场景卡—7

token 计算规则:汉字与全角符号计 1 token,西文按字符数除以 4 向上取整。采用高估策略,避免请求超限后被静默截断。

部署与运行

本地部署,五个步骤

全部计算在本机完成,运行期间不产生任何外部网络请求。

环境

运行要求

macOS,Apple Silicon(M 系列);统一内存 16GB 起;Python 3.10 及以上。 磁盘占用:基座约 2.3GB,融合模型约 2.3GB。

技术栈

实现选型

推理使用 MLX / mlx-lm(Apple Silicon 原生);服务使用 FastAPI + Uvicorn; 存储使用 SQLite 单文件;基座为 Qwen3-4B-Instruct-2507-4bit(Apache-2.0)。

# 1. 安装依赖
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# 2. 融合微调权重(必须融合后启动服务)
python -m mlx_lm fuse \
  --model "Sine 大模型/基座模型/Qwen3-4B-Instruct-2507-4bit" \
  --adapter-path runs/sine-lora \
  --save-path models/sine-fused

# 3. 启动推理服务(端口 8081)
bash scripts/serve_mlx.sh models/sine-fused 8081

# 4. 启动应用(端口 8420)
python -m uvicorn app.main:app --host 127.0.0.1 --port 8420

# 5. 验证
python scripts/smoke_test.py        # 22 项,不依赖模型
python -m pytest tests/ -q          # 45 项回归测试

配置文件 config/settings.yaml 中 ollama.base_url 设为推理服务地址,不带 /v1 后缀(生成层自动拼接)。

训练方法

关系演进进入权重

训练目标是使关系演进成为模型能力。数据采用「场景 × 关系阶段」双层结构,参数以稳定性优先。

参数取值依据
LoRA 层数16基座共 36 层,覆盖末 16 层,可训练参数 7.34M(0.182%)
rank8语气层微调常规取值
batch size116GB 内存下 batch 2 会触发系统内存回收
max seq1024实测样本 p100 为 894 token,保留 130 余量避免尾部截断
learning rate1e-44B 基座实测收敛平稳
save-every500兼顾磁盘写入频率与崩溃损失
其他mask-prompt / grad-checkpoint仅对回复计算损失;4B 必须启用梯度检查点

数据处理链路

data_factory/banks/<阶段>/<场景>.jsonl     台词库,按阶段分目录
  ↓ scripts/build_dataset.py
  组装对话 → 按节拍推进 → 切分样本 → 按对话划分训练/验证
  → 真 tokenizer 测长 → 剥离控制标签
  ↓
data_train/train.jsonl + data_train/valid.jsonl
EVAL-01

阶段化评测

4 条固定输入 × 5 个关系阶段,贪心解码生成,统计阶段区分度与方向性指标。 达标线为同一输入在五阶段下不同回复数均值不低于 4/5。

EVAL-02

边界评测

病娇阶段输入 6 条诱导越界内容,依据四类红线词表判定输出是否越界: 自伤威胁、限制自由、贬低羞辱、索取隐私。

数据清除说明:历史适配器、训练集与台词库已于 2026-10-23 清除。原因是既有数据将输出锁定在单一关系基调,实测三种阶段下回复完全相同,表明阶段信息必须进入训练数据。

已知限制

八项实现缺口

以下各项均为代码中实际存在的行为,列出以保证文档与实现一致。

#问题位置
01分条最小字数配置项被读取但未参与计算,实际仅 25 字上限生效rhythm.py:35
02深夜放慢系数未在接口链路生效:调用未传入小时参数main.py:168
03主动消息的冷却分支不触发:相关方法无调用点gate.py:60
04调度层场景档位字段为硬编码,实际档位由世界书扫描另行返回orchestrator.py:35
05滑动窗口配置语义为「轮」但实现为「条消息」,实际约 5 轮context.py:87
06运行时过滤器不含修辞性重复豁免,4-gram 重叠超 60% 即触发重生成filters.py:121
07模型存在约 8% 概率返回空内容,已转换为异常并回落兜底句client.py:64
08情感信号抽取基于词典命中,非语义理解,复杂表达可能漏判engine.py:20