event-chronicle
v0.2.2
Published
从 AI 对话中提取事件,构建可视编年史,形成长期记忆
Downloads
536
Maintainers
Readme
Event Chronicle

让对话不只是对话,而是一部持续书写的可视编年史
Event Chronicle 从 AI 对话中提取结构化事件,并以时间线形式长期保存。在未来对话中,这些历史事件会重新注入模型上下文,使 AI 基于已发生的事实而非压缩后的摘要进行理解与推理,从而形成连贯、可追溯的长期记忆
支持 Node.js 和 浏览器 两种环境
Demo
假设有以下聊天信息

Event Chronicle 不会保存整段聊天,只会从中提取事件
[
{
"date": "2026-06-14",
"event": "用户开始饲养一只三个月大的橘猫,取名为奶糖"
},
{
"date": "2026-06-14",
"event": "奶糖昨天进行了体检,结果正常"
}
]每个事件自动记录来源消息的引用(索引范围 + 预览),用于事件回溯和上下文查看,不重复存储原始消息
这些事件会被保存到编年史中。后续再次对话时,Event Chronicle 将完整编年史注入模型上下文:
Event Chronicle
2026-06
├─ 用户开始饲养一只三个月大的橘猫,取名为奶糖
├─ 奶糖昨天进行了体检,结果正常AI 基于这些历史事件组织回复——它们构成了 AI 的长期记忆
要理解现在,必须追溯过去
安装
Node.js
npm install event-chronicle环境要求:Node.js ≥ 18
SillyTavern 插件
插件安装 URL:
https://github.com/janfeise/st-event-chronicle插件安装方式:
网页打开酒馆 → Extensions → Install from Git URL → 输入上述 URL插件安装后的位置:
{ST目录}/data/default-user/extensions/st-event-chronicle/数据存放位置
Node.js SDK
data/ 目录下的 JSON 文件,由 CHRONICLE_EVENT_ID 环境变量控制文件名
SillyTavern 插件
ST 存储位置: data/default-user/settings.json
→ extension_settings.event-chronicle._events数据随 ST 的 settings.json 自动保存,无独立文件
快速开始
Node.js
在项目中安装依赖 event-chronicle:
npm install event-chronicle
npm install -D tsx # TypeScript 运行器,也可用 node + .js配置 API Key:创建 .env 文件,填入你的 LLM API Key:
支持的 LLM 提供商:OpenAI、DeepSeek、以及任何兼容 OpenAI API 格式的服务
LLM_PROVIDER=openai
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=sk-your-key
LLM_MODEL=gpt-4oBrowser SDK 不使用
.env——请在 API 调用方直接传入配置。
创建 chronicle.ts:
import { startup, processMessages, exportMemory } from "event-chronicle";
// 1. 初始化(自动加载 .env 中的 LLM 配置)
await startup();
// 2. 传入聊天消息,自动提取事件
const result = await processMessages([
{ role: "Alice", content: "我们去图书馆查资料" },
{ role: "Bob", content: "好主意。那里的数据库很全。" },
{ role: "Alice", content: "我在历史区找到了关于失踪探险队的日志。" },
]);
console.log(result.events.length); // → 提取到的事件数
// 3. 导出为 AI 记忆 Prompt
const memory = await exportMemory("default", { highlightThreshold: 7 });运行:
npx tsx chronicle.ts预期输出:生成的数据将保存在项目 data/ 目录下
╔══════════════════════════════════════════╗
║ Event Chronicle 启动… ║
╚══════════════════════════════════════════╝
[Event Chronicle] ✓ LLM 健康检查通过
[Event Chronicle] 🚀 启动完成
提取事件: 1 条
存储文件: my-story.json
触发合并: false
# Event Chronicle Memory
## Summary
1 events · importance range 6–6
...💡 完整 Demo(6 轮 RPG 对话、自动合并触发)见
demo/。
Browser
import { formatMessages, extractPrompt } from 'event-chronicle/browser';
// 浏览器 SDK 不含 LLM 客户端 —— 仅提供纯函数和 Prompt 模板
const msgs = [{ role: 'Alice', content: 'Hello' }, { role: 'Bob', content: 'Hi!' }];
const prompt = extractPrompt
.replace('{{existingEvents}}', '')
.replace('{{recentMessages}}', formatMessages(msgs));
// 自己调用 LLM API
const response = await fetch('https://api.openai.com/v1/chat/completions', { ... });
const data = await response.json();
const events = parseEvents(data.choices[0].message.content);API 参考
Node.js SDK (event-chronicle)
第一层:一站式 API
大多数场景只需这两个函数
| 函数 | 说明 |
| ------------------------------------- | ---------------------------------------------- |
| startup(options?) | 加载 .env → 初始化 LLM → 预热提示词 → 健康检查 |
| processMessages(messages, options?) | 完整管道:提取事件 → 持久化 → 自动合并检测 |
const result = await processMessages(messages, {
eventId: "my-story", // 文件名
autoMerge: true, // 累计事件达阈值自动合并(默认 true)
existingEventId: "old", // 加载已有事件供 LLM 参考去重
});
// → { events: Event[], storedFile: string, merged: boolean }| 导出函数 | 说明 | 输出 |
| --------------------------------- | ------------- | ---------------------------------------------------- |
| exportMemory(eventId, options?) | Memory Export | Markdown + Prompt 包裹,可直接注入 LLM system prompt |
| exportRaw(eventId) | Raw Export | 完整 JSON 数组(数据迁移 / 调试) |
第二层:流程级 API
需要自定义流程时使用
| 函数 | 说明 |
| ------------------------------------------------------ | ---------------------- |
| extractEvents(messages, existingEvents?) | 仅提取事件,不持久化 |
| mergeEvents(existing, newEvents) | 仅合并事件,不自动触发 |
| applyInstructions(existing, newEvents, instructions) | 纯函数:执行合并指令 |
| loadChronicle(eventId?) | 读取已存储的事件 |
| saveChronicle(events) | 全量保存到新文件 |
| appendEvents(events, eventId?) | 追加事件到已有文件 |
第三层:底层 API
需要完全控制时使用
| 函数 | 说明 |
| ------------------------------------------ | -------------------------------- |
| initLLM(config) | 手动初始化 LLM 客户端 |
| loadMergeState(eventId) | 读取合并计数器状态 |
| resetMergeCounter(eventId) | 重置合并计数器 |
| getDataDir() / setDataDir(dir) | 获取/覆盖数据目录 |
| loadEnv() | 手动加载 .env 到 process.env |
| exportRawFromEvents(events) | 纯函数版 Raw Export |
| exportMemoryFromEvents(events, options?) | 纯函数版 Memory Export |
| PromptManager | 提示词管理器类(创建自定义实例) |
Browser SDK (event-chronicle/browser)
| 函数/常量 | 说明 |
| ---------------------------------------------------- | -------------------------------------------------------------------- |
| parseEvents(response) | LLM 响应 → Event[] |
| formatMessages(messages) | ChatMessage[] → 文本 |
| applyInstructions(events, newEvents, instructions) | 执行合并指令 |
| extractPrompt | 事件提取 Prompt 模板(含 {{existingEvents}} {{recentMessages}}) |
| mergePrompt | 事件合并 Prompt 模板(含 {{existingEvents}} {{newEvents}}) |
| memoryPrompt | 记忆注入 Prompt 模板(含 {{memoryTimeline}}) |
Configuration
方式一:.env 文件(推荐)
| 变量 | 必填 | 默认值 | 说明 |
| ------------------------- | ---- | --------------------------- | ----------------------------- |
| LLM_API_KEY | ✓ | — | LLM API Key |
| LLM_PROVIDER | | openai | LLM 提供商 |
| LLM_BASE_URL | | https://api.openai.com/v1 | API 地址 |
| LLM_MODEL | | gpt-4o | 模型名称 |
| CHRONICLE_EVENT_ID | | — | 默认数据文件名 |
| CHRONICLE_MERGE_TRIGGER | | 5 | 自动合并触发阈值 |
| CHRONICLE_MERGE_WINDOW | | 20 | 合并时发送给 LLM 的已有事件数 |
方式二:代码传参
// 完全绕过 .env,纯代码配置
await startup({
healthCheck: false,
llmConfig: {
provider: "openai",
baseUrl: "https://api.openai.com/v1",
apiKey: "sk-xxx",
model: "gpt-4o",
},
dataDir: "./my-data", // 自定义数据目录
promptsDir: "./my-prompts", // 自定义提示词目录
});系统流程
┌──────────────┐
│ Chat Messages│
└──────┬───────┘
│
▼
┌──────────────┐
│ Extractor │ ← LLM 从对话中提取事件
│ 事件提取 │
└──────┬───────┘
│ Event[]
▼
┌──────────────┐
│ Storage │ ← JSON 文件持久化
│ 事件存储 │
└──────┬───────┘
│
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
[counter < N] [counter ≥ N] Export
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Merge │ ← LLM 去重/整理
│ │ 事件合并 │ │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Storage │ │
│ │ 保存结果 │ │
│ └──────────┘ │
│ │
▼ ▼
┌──────────┐ ┌──────────────┐
│ Continue │ │ Exporter │
│ 继续积累 │ │ Raw / Memory │
└──────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ LLM API │ ← 注入记忆
│ 下次对话 │
└──────────────┘核心原则:
- 事件是历史事实 — 只记录已经发生、明确决定、明确推进的事情
- 时间线是记忆结构 — 按时间组织的事件序列,保持因果关系
- 记忆不是摘要 — 摘要告诉你聊了什么;记忆告诉你在这些对话中发生了什么
史官,不创造事实,不推测事实,不补全事实。Event Chronicle 只记录聊天中明确发生、明确决定、明确推进的事件
副作用
- 每轮对话的 token 增加(记忆会注入到 LLM API 中)
- token 逐步递增:事件不断累积,记忆愈加厚重
- LLM API 请求次数增多:每 N 次对话触发一次提取,每 M 个事件触发一次合并(N、M 可配置)
更多资源
| 文档 | 说明 | | --------------------------------------------- | ------------------------------- | | ST 扩展用户文档 | 安装 + 功能 + 配置 | | ST 扩展开发文档 | 架构 + 设计决策 + 开发流程 | | 项目开发文档 | 核心模块详解 + Browser SDK 架构 | | Web Demo | 浏览器交互式演示 | | CLI Demo | 端到端命令行演示 |
扩展
若导入 TA 的"历史",AI 是否是 TA 的一种延续呢?
License
MIT
