共享类型系统文档
概述
本目录包含项目的完整类型系统,采用双格式兼容设计:
- SillyTavern 原生格式 - 用于导入导出兼容
- 扩展内部格式 - 用于增强功能和自定义特性
目录结构
shared/types/
├── sillytavern/ # SillyTavern 原生格式(从官方文档读取)
│ ├── character.types.ts # 角色卡 V2 规范
│ ├── chat.types.ts # 聊天记录(JSONL)
│ ├── world.types.ts # 世界书 / Lorebook
│ └── preset.types.ts # 生成预设
│
├── extended/ # 您的自定义扩展
│ ├── chat-ext.types.ts # 扩展聊天(动态表头)
│ ├── preset-ext.types.ts # 扩展预设(位置锚点)
│ └── world-ext.types.ts # 统一触发器系统
│
├── adapters/ # 导入导出适配器
│ └── import-export.types.ts # 适配器接口
│
├── common.types.ts # 通用工具类型
└── index.ts # 主导出文件
核心设计原则
1. 双格式系统
每个数据实体都有两种表示形式:
- ST 格式:精确的 SillyTavern 规范(用于兼容性)
- 扩展格式:增强了您的自定义功能
示例:
// SillyTavern 格式(导入/导出)
interface STChatMessage {
name: string;
is_user: boolean;
mes: string;
// ... ST 字段
}
// 扩展格式(内部使用)
interface ExtendedChatMessage {
senderName: string;
senderRole: 'user' | 'assistant';
mes: string;
reasoning?: string; // 您的自定义字段
image?: string; // 您的自定义字段
audio?: string; // 您的自定义字段
dynamicData?: Record<string, any>; // 动态表头
}
2. 适配器模式
适配器处理格式之间的转换:
interface ChatAdapter {
importFromST(jsonlContent: string): InternalChatSession;
exportToST(chat: InternalChatSession): string;
}
3. 保留原始数据
内部模型保留原始 ST 数据:
interface InternalCharacter {
// ... 您的字段
stData?: STCharacterCardV2; // 保留原始数据
}
Data Models
Chat History (JSONL)
Metadata (First line):
characterName: Character namedynamicHeaders: User-defined dynamic table headerscharacterDescription: Character descriptionsystemPrompt: System promptfirstMessages: Alternate first messages
Messages (Subsequent lines):
senderName: Who sent the messagesenderRole: user/assistant/system/narratormes: Message contentswipes: Alternative responsesreasoning: Chain of thoughtimage/audio: Media attachmentsdynamicData: Custom dynamic header values
预设系统
固定占位符位置(顺序必须保持):
system- 系统提示词(来自角色卡)world_info_before- 世界书(前置)persona_description- 角色设定描述char_description- 角色详细描述world_info_after- 世界书(后置)history- 聊天记录(对话历史)user_input- 用户当前输入
核心参数:
temperature: 温度(创造性)maxReplyLength: 最大回复长度topP,topK: 采样参数repetitionPenalty: 重复惩罚系数entryOrder: 预设条目名称的有序列表maxContextTokens: 最大上下文 token 数streaming: 是否流式传输
API 配置:
interface ApiConfig {
apiUrl: string; // API 地址
apiKey: string; // API 密钥
apiType: 'primary' | 'secondary' | 'image_gen' | 'rag'; // API 类型
model: string; // 模型名称
}
世界书(统一触发器系统)
将原有的 key 和 constant 整合为统一的四元素字典:
interface TriggerConfig {
permanent: PermanentTrigger; // 永久激活(无需触发器)
keyword: KeywordTrigger; // 关键词触发
rag: RagTrigger; // RAG/数据库触发
variable: VariableTrigger; // 变量比较触发
}
触发器类型详解:
-
永久触发器 (
permanent)enabled: 是否永久激活- 无其他条件,始终生效
-
关键词触发器 (
keyword)enabled: 是否启用keywords: 关键词数组useRegex: 是否使用正则表达式matchWholeWords: 是否匹配完整单词caseSensitive: 是否区分大小写
-
RAG 触发器 (
rag)enabled: 是否启用databaseName: 关联的数据库/集合名称threshold: 相似度阈值(0-1)topK: 检索的相似条目数量
-
变量触发器 (
variable)enabled: 是否启用variableA: 变量 Aoperator: 运算符(>,<,=,contains,<=,>=,!=)variableB: 变量 B(可选)constantA: 常量值(可选,替代 variableB)
其他字段:
content: 条目内容position: 插入位置(before_char/after_char)scanDepth: 扫描深度(扫描多少条消息)priority: 优先级(同位置的先后顺序)
使用示例
导入角色卡
import { CharacterAdapter, STCharacterCardV2 } from '@shared/types';
const adapter: CharacterAdapter = new CharacterAdapterImpl();
// 从 ST 格式导入
const stCard: STCharacterCardV2 = parsePNG('character.png');
const internalChar = adapter.importFromST(stCard);
// 导出为 ST 格式
const stExport = adapter.exportToST(internalChar);
聊天会话管理
import { ChatAdapter } from '@shared/types';
const adapter: ChatAdapter = new ChatAdapterImpl();
// 导入 JSONL
const jsonlContent = await readFile('chat.jsonl');
const chat = adapter.importFromST(jsonlContent);
// 添加带自定义字段的消息
chat.messages.push({
senderName: '用户',
senderRole: 'user',
mes: '你好!',
reasoning: undefined,
dynamicData: { mood: 'happy' }
});
// 导出回 JSONL
const exported = adapter.exportToST(chat);
世界书统一触发器
import { ExtendedWorldInfoEntry, TriggerConfig } from '@shared/types';
const entry: ExtendedWorldInfoEntry = {
id: '1',
content: '魔法剑发出蓝色光芒。',
position: 'after_char',
scanDepth: 5,
priority: 1,
triggers: {
permanent: { enabled: false },
keyword: {
enabled: true,
keywords: ['剑', '武器'],
useRegex: false,
matchWholeWords: true,
caseSensitive: false
},
rag: { enabled: false },
variable: { enabled: false }
},
enabled: true
};
兼容性说明
SillyTavern V2 规范
- 完全兼容 Character Card V2
- 支持 PNG 嵌入(tEXt 数据块)
- 支持 JSON 格式
聊天记录
- JSONL 格式(每行一个 JSON 对象)
- 第一行:元数据
- 后续行:消息
- 支持完整性哈希校验
世界书
- 兼容 ST Lorebook 格式
- 扩展触发器系统可转换为
keys+constant
预设
- 支持所有标准 ST 参数
- 固定占位符位置用于提示词构建
- 保留条目顺序
迁移指南
从 SillyTavern 到内部格式
- 解析 ST 格式(PNG/JSON/JSONL)
- 使用适配器转换为内部格式
- 原始 ST 数据保存在
stData字段中 - 根据需要添加自定义字段
从内部格式到 SillyTavern 格式
- 使用适配器将内部格式转换为 ST 格式
- 不在 ST 规范中的自定义字段会被排除
- 如果可用,使用原始 ST 数据
- 以所需格式导出(PNG/JSON/JSONL)
类型安全
所有类型都使用 TypeScript 完整定义:
- 核心模型中不使用
any类型 - 严格的空值检查
- 基于枚举的常量
- 全面的接口定义
下一步计划
- 实现适配器类
- 创建验证函数
- 为转换逻辑添加单元测试
- 构建导入导出 UI 组件