mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-05-21 13:50:18 +08:00
feat(api): 实现 Import API v1 完整协议与层级数据源管理
This commit is contained in:
@@ -1,389 +0,0 @@
|
||||
# ChatLab 标准化格式规范 v0.0.2
|
||||
|
||||
ChatLab 定义了一套标准的聊天记录数据交换格式,用于支持多平台数据的统一导入和分析。
|
||||
|
||||
只要你将聊天记录转为该格式,那么就可以被 ChatLab 解析并使用其分析能力。
|
||||
|
||||
::: warning 注意该格式规范目前仍处于早期制定阶段,部分字段和结构可能会在后续版本中调整。:::
|
||||
|
||||
## 概述
|
||||
|
||||
### 支持的文件格式
|
||||
|
||||
| 格式 | 扩展名 | 适用场景 |
|
||||
| --------- | -------- | ------------------------------------------------- |
|
||||
| **JSON** | `.json` | 中小型记录(<100 万条),结构清晰,易于阅读 |
|
||||
| **JSONL** | `.jsonl` | 超大规模记录(>100 万条),流式处理,内存占用恒定 |
|
||||
|
||||
### 格式对比
|
||||
|
||||
| 特性 | JSON | JSONL |
|
||||
| ------------ | ---------------------- | ----------------------- |
|
||||
| 内存占用 | 需加载完整结构 | 逐行处理,恒定 (~100MB) |
|
||||
| 文件大小限制 | ~1GB(取决于内存) | 无实际限制 |
|
||||
| 追加写入 | ❌ 需重写整个文件 | ✅ 直接追加行 |
|
||||
| 错误恢复 | 单处错误整文件失效 | 可跳过错误行继续 |
|
||||
| 可读性 | ⭐⭐⭐ 易于阅读 | ⭐⭐ 每行一条记录 |
|
||||
| 推荐场景 | 小中型记录 (<100 万条) | 大型记录 (>100 万条) |
|
||||
|
||||
## 快速说明
|
||||
|
||||
以下是一个**最小化**的 ChatLab 格式示例,只包含必要字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"chatlab": {
|
||||
"version": "0.0.2",
|
||||
"exportedAt": 1703001600
|
||||
},
|
||||
"meta": {
|
||||
"name": "我的群聊",
|
||||
"platform": "qq",
|
||||
"type": "group"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
"platformId": "123456",
|
||||
"accountName": "张三"
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"sender": "123456",
|
||||
"accountName": "张三",
|
||||
"timestamp": 1703001600,
|
||||
"type": 0,
|
||||
"content": "大家好!"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## JSON 格式详细说明
|
||||
|
||||
### 文件头 (chatlab)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| ------------- | ------ | ---- | ---------------------------- |
|
||||
| `version` | string | ✅ | 格式版本号,当前为 `"0.0.2"` |
|
||||
| `exportedAt` | number | ✅ | 导出时间(秒级 Unix 时间戳) |
|
||||
| `generator` | string | - | 生成工具名称 |
|
||||
| `description` | string | - | 描述信息 |
|
||||
|
||||
### 元信息 (meta)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| ------------- | ------------- | ---- | -------------------------------------------------------- |
|
||||
| `name` | string | ✅ | 群名或对话名 |
|
||||
| `platform` | string | ✅ | 平台标识,如 `qq` / `wechat` / `discord` / `whatsapp` 等 |
|
||||
| `type` | string | ✅ | 聊天类型:`group`(群聊)/ `private`(私聊) |
|
||||
| `groupId` | string | - | 群 ID(仅群聊) |
|
||||
| `groupAvatar` | string | - | 群头像(Data URL 格式) |
|
||||
| `ownerId` | string | - | 所有者/导出者的 platformId |
|
||||
| `sources` | MergeSource[] | - | 合并来源(合并工具生成,见下方说明) |
|
||||
|
||||
#### MergeSource 结构(合并来源)
|
||||
|
||||
当使用合并工具合并多个聊天记录文件时,`sources` 字段会记录原始文件的来源信息:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| -------------- | ------ | ---- | -------- |
|
||||
| `filename` | string | ✅ | 原文件名 |
|
||||
| `platform` | string | - | 原平台 |
|
||||
| `messageCount` | number | ✅ | 消息数量 |
|
||||
|
||||
### 成员 (members)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --------------- | ------------ | ---- | ------------------------- |
|
||||
| `platformId` | string | ✅ | 用户唯一标识 |
|
||||
| `accountName` | string | ✅ | 账号名称 |
|
||||
| `groupNickname` | string | - | 群昵称(仅群聊) |
|
||||
| `aliases` | string[] | - | 用户自定义别名 |
|
||||
| `avatar` | string | - | 用户头像(Data URL 格式) |
|
||||
| `roles` | MemberRole[] | - | 成员角色(可多个) |
|
||||
|
||||
#### 角色 (roles)
|
||||
|
||||
成员可以拥有一个或多个角色,用于标识群主、管理员等身份:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| ------ | ------ | ---- | -------------------------------------- |
|
||||
| `id` | string | ✅ | 角色标识:`owner` / `admin` / 自定义ID |
|
||||
| `name` | string | - | 角色显示名称(自定义角色需要) |
|
||||
|
||||
**标准角色 ID:**
|
||||
|
||||
| ID | 说明 |
|
||||
| ------- | ----------- |
|
||||
| `owner` | 群主/创建者 |
|
||||
| `admin` | 管理员 |
|
||||
|
||||
**角色示例:**
|
||||
|
||||
```json
|
||||
// 群主
|
||||
"roles": [{ "id": "owner" }]
|
||||
|
||||
// 管理员
|
||||
"roles": [{ "id": "admin" }]
|
||||
|
||||
// 多角色
|
||||
"roles": [
|
||||
{ "id": "owner" },
|
||||
{ "id": "tech-team", "name": "技术组" },
|
||||
{ "id": "vip", "name": "VIP会员" }
|
||||
]
|
||||
```
|
||||
|
||||
### 消息 (messages)
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| ------------------- | -------------- | ---- | --------------------------------- |
|
||||
| `sender` | string | ✅ | 发送者的 `platformId` |
|
||||
| `accountName` | string | ✅ | 发送时的账号名称 |
|
||||
| `groupNickname` | string | - | 发送时的群昵称 |
|
||||
| `timestamp` | number | ✅ | 秒级 Unix 时间戳 |
|
||||
| `type` | number | ✅ | 消息类型(见下方对照表) |
|
||||
| `content` | string \| null | ✅ | 消息内容(非文本消息可为 `null`) |
|
||||
| `platformMessageId` | string | - | 消息的平台原始 ID |
|
||||
| `replyToMessageId` | string | - | 回复的目标消息 ID |
|
||||
|
||||
#### 消息 ID 与回复关系说明
|
||||
|
||||
**`platformMessageId`**(消息的平台原始 ID):
|
||||
|
||||
- 存储消息在原始平台上的唯一标识(如 Discord 的 snowflake ID、QQ 的消息 ID)
|
||||
- 用于在查询时关联 `replyToMessageId`,以显示被回复消息的内容
|
||||
- 如果平台不提供消息 ID,可省略此字段
|
||||
|
||||
**`replyToMessageId`**(回复的目标消息 ID):
|
||||
|
||||
- 存储被回复消息的**平台原始 ID**
|
||||
- 通过与其他消息的 `platformMessageId` 关联,可查询被回复消息的内容和发送者
|
||||
- 仅当消息是回复类型时才有意义
|
||||
- 如果平台不支持或数据不包含回复关系,可省略此字段
|
||||
|
||||
---
|
||||
|
||||
## 消息类型对照表
|
||||
|
||||
::: tip 提示若您的聊天记录中有其他特殊类型需要支持,请提交 issue 说明情况,我们会评估是否加入标准消息类型中。:::
|
||||
|
||||
### 基础消息类型 (0-19)
|
||||
|
||||
| 值 | 名称 | 说明 |
|
||||
| --- | -------- | ----------- |
|
||||
| 0 | TEXT | 文本消息 |
|
||||
| 1 | IMAGE | 图片 |
|
||||
| 2 | VOICE | 语音 |
|
||||
| 3 | VIDEO | 视频 |
|
||||
| 4 | FILE | 文件 |
|
||||
| 5 | EMOJI | 表情包/贴纸 |
|
||||
| 7 | LINK | 链接/卡片 |
|
||||
| 8 | LOCATION | 位置 |
|
||||
|
||||
### 交互消息类型 (20-39)
|
||||
|
||||
| 值 | 名称 | 说明 |
|
||||
| --- | ---------- | ---------------------- |
|
||||
| 20 | RED_PACKET | 红包 |
|
||||
| 21 | TRANSFER | 转账 |
|
||||
| 22 | POKE | 拍一拍/戳一戳 |
|
||||
| 23 | CALL | 语音/视频通话 |
|
||||
| 24 | SHARE | 分享(音乐、小程序等) |
|
||||
| 25 | REPLY | 引用回复 |
|
||||
| 26 | FORWARD | 转发消息 |
|
||||
| 27 | CONTACT | 名片消息 |
|
||||
|
||||
### 系统消息类型 (80+)
|
||||
|
||||
| 值 | 名称 | 说明 |
|
||||
| --- | ------ | ------------------------------ |
|
||||
| 80 | SYSTEM | 系统消息(入群/退群/群公告等) |
|
||||
| 81 | RECALL | 撤回消息 |
|
||||
| 99 | OTHER | 其他/未知 |
|
||||
|
||||
## 头像格式说明
|
||||
|
||||
头像字段 `avatar` 和 `groupAvatar` 支持两种格式:
|
||||
|
||||
### 1. Data URL
|
||||
|
||||
嵌入式格式,图片数据直接编码在文件中,离线可用:
|
||||
|
||||
```
|
||||
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...
|
||||
```
|
||||
|
||||
支持的图片 MIME 类型:
|
||||
|
||||
- `image/jpeg` - JPEG 格式(推荐,体积较小)
|
||||
- `image/png` - PNG 格式
|
||||
- `image/gif` - GIF 格式
|
||||
- `image/webp` - WebP 格式
|
||||
|
||||
### 2. 网络 URL
|
||||
|
||||
外链格式,图片存储在网络服务器,体积更小但需网络访问:
|
||||
|
||||
```
|
||||
https://example.com/avatars/user123.jpg
|
||||
```
|
||||
|
||||
::: tip 建议
|
||||
|
||||
- 如果需要离线使用或长期存档,推荐使用 Data URL 格式
|
||||
- 导出 Data URL 时建议将头像压缩为 100×100 像素以内,以减小文件体积
|
||||
- 如果头像来自可靠的长期有效的 CDN,可使用网络 URL 以减小文件体积 :::
|
||||
|
||||
## 完整示例
|
||||
|
||||
### 群聊示例(含可选字段)
|
||||
|
||||
```json
|
||||
{
|
||||
"chatlab": {
|
||||
"version": "0.0.2",
|
||||
"exportedAt": 1703001600,
|
||||
"generator": "My Converter Tool",
|
||||
"description": "2024年技术交流群聊天记录备份"
|
||||
},
|
||||
"meta": {
|
||||
"name": "技术交流群",
|
||||
"platform": "wechat",
|
||||
"type": "group",
|
||||
"groupId": "38988428513",
|
||||
"groupAvatar": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
|
||||
"ownerId": "abc123"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
"platformId": "abc123",
|
||||
"accountName": "张三",
|
||||
"groupNickname": "群主-张三",
|
||||
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
|
||||
"roles": [{ "id": "owner" }]
|
||||
},
|
||||
{
|
||||
"platformId": "def456",
|
||||
"accountName": "李四",
|
||||
"groupNickname": "管理员",
|
||||
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
|
||||
"roles": [{ "id": "admin" }]
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"platformMessageId": "msg_001",
|
||||
"sender": "abc123",
|
||||
"accountName": "张三",
|
||||
"groupNickname": "群主-张三",
|
||||
"timestamp": 1703001600,
|
||||
"type": 0,
|
||||
"content": "大家好!欢迎加入技术交流群~"
|
||||
},
|
||||
{
|
||||
"platformMessageId": "msg_002",
|
||||
"sender": "def456",
|
||||
"accountName": "李四",
|
||||
"groupNickname": "管理员",
|
||||
"timestamp": 1703001610,
|
||||
"type": 25,
|
||||
"content": "收到!",
|
||||
"replyToMessageId": "msg_001"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 私聊示例
|
||||
|
||||
```json
|
||||
{
|
||||
"chatlab": {
|
||||
"version": "0.0.2",
|
||||
"exportedAt": 1703001600
|
||||
},
|
||||
"meta": {
|
||||
"name": "与小明的对话",
|
||||
"platform": "qq",
|
||||
"type": "private"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
"platformId": "123456789",
|
||||
"accountName": "我",
|
||||
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
|
||||
},
|
||||
{
|
||||
"platformId": "987654321",
|
||||
"accountName": "小明",
|
||||
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"sender": "123456789",
|
||||
"accountName": "我",
|
||||
"timestamp": 1703001600,
|
||||
"type": 0,
|
||||
"content": "在吗?"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## JSONL 流式格式
|
||||
|
||||
JSONL(JSON Lines)格式适用于**超大规模聊天记录**(>100 万条),可避免内存溢出问题。
|
||||
|
||||
### 格式特点
|
||||
|
||||
- 每行一个 JSON 对象
|
||||
- 通过 `_type` 字段区分行类型:`header` / `member` / `message`
|
||||
- 内存占用恒定(约 100MB),支持 GB 级文件
|
||||
- 支持流式写入,可边导出边追加
|
||||
|
||||
### 行类型说明
|
||||
|
||||
| `_type` | 说明 | 是否必需 |
|
||||
| --------- | -------------------------------- | --------------- |
|
||||
| `header` | 文件头,包含 `chatlab` 和 `meta` | ✅ 必须在第一行 |
|
||||
| `member` | 成员信息 | - 可选 |
|
||||
| `message` | 消息记录 | ✅ 至少一条 |
|
||||
|
||||
### 完整示例
|
||||
|
||||
```jsonl
|
||||
{"_type":"header","chatlab":{"version":"0.0.2","exportedAt":1703001600},"meta":{"name":"技术交流群","platform":"qq","type":"group"}}
|
||||
{"_type":"member","platformId":"123456","accountName":"张三","groupNickname":"群主","roles":[{"id":"owner"}]}
|
||||
{"_type":"member","platformId":"789012","accountName":"李四"}
|
||||
{"_type":"message","platformMessageId":"msg_001","sender":"123456","accountName":"张三","groupNickname":"群主","timestamp":1703001600,"type":0,"content":"大家好!"}
|
||||
{"_type":"message","sender":"789012","accountName":"李四","timestamp":1703001610,"type":0,"content":"你好!"}
|
||||
{"_type":"message","sender":"123456","accountName":"张三","groupNickname":"群主","timestamp":1703001620,"type":1,"content":"[图片]"}
|
||||
```
|
||||
|
||||
### 解析规则
|
||||
|
||||
1. **第一行必须是 header**:包含 `chatlab` 版本和 `meta` 元信息
|
||||
2. **成员行在消息之前**:可选,如果省略,成员信息会从消息中自动收集
|
||||
3. **消息按时间顺序排列**:建议按 `timestamp` 升序排列
|
||||
4. **每行独立完整**:单行解析错误可跳过继续处理
|
||||
5. **支持注释行**:以 `#` 开头的行会被跳过(可用于添加备注)
|
||||
|
||||
::: warning 注意
|
||||
|
||||
- 每行必须是**有效的 JSON**(不能跨行)
|
||||
- 行之间用换行符 `\n` 分隔
|
||||
|
||||
:::
|
||||
|
||||
## 版本历史
|
||||
|
||||
| 版本 | 日期 | 变更 |
|
||||
| ----- | ---------- | ------------------------------------------------------------------------------ |
|
||||
| 0.0.1 | 2025-12-22 | 初始版本 |
|
||||
| 0.0.2 | 2026-01-09 | 新增 roles、ownerId、platformMessageId、replyToMessageId 字段;新增 JSONL 格式 |
|
||||
@@ -1,6 +1,21 @@
|
||||
# ChatLab API 文档
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
ChatLab 提供本地 RESTful API 服务,允许外部工具、脚本和 MCP 等通过 HTTP 接口查询聊天记录、执行 SQL 查询、导入聊天数据。
|
||||
# ChatLab API
|
||||
|
||||
> v1
|
||||
|
||||
ChatLab 提供本地 RESTful API 服务,允许外部工具、脚本和 MCP 等通过 HTTP 接口查询聊天记录、执行 SQL 查询、导出聊天数据。
|
||||
|
||||
::: tip 数据导入
|
||||
|
||||
如需通过 API 导入聊天数据,请参阅:
|
||||
|
||||
- **[Push 导入协议](./chatlab-import.md)** — 外部系统主动将数据推送到 ChatLab
|
||||
- **[Pull 远程数据源协议](./chatlab-pull.md)** — 第三方暴露标准端点,ChatLab 主动拉取数据
|
||||
|
||||
:::
|
||||
|
||||
## 快速开始
|
||||
|
||||
@@ -93,7 +108,7 @@ Token 可在 设置 → ChatLab API 页面查看和重新生成。
|
||||
| GET | `/api/v1/status` | 服务状态 |
|
||||
| GET | `/api/v1/schema` | ChatLab Format JSON Schema |
|
||||
|
||||
### 数据查询(导出)
|
||||
### 数据查询与导出
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| ---- | ------------------------------------- | ------------------------ |
|
||||
@@ -107,10 +122,9 @@ Token 可在 设置 → ChatLab API 页面查看和重新生成。
|
||||
|
||||
### 数据导入
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| ---- | ----------------------------- | ------------------------ |
|
||||
| POST | `/api/v1/import` | 导入聊天记录(新建会话) |
|
||||
| POST | `/api/v1/sessions/:id/import` | 增量导入到指定会话 |
|
||||
| 方法 | 路径 | 说明 | 文档 |
|
||||
| ---- | ------------------------------------ | -------------------------------------------------------- | -------------------------------- |
|
||||
| POST | `/api/v1/imports/:sessionId` | 导入消息到指定会话(首次自动创建,后续追加) | [Push 导入协议](./chatlab-import.md) |
|
||||
|
||||
---
|
||||
|
||||
@@ -153,7 +167,8 @@ Token 可在 设置 → ChatLab API 页面查看和重新生成。
|
||||
"platform": "qq",
|
||||
"type": "group",
|
||||
"messageCount": 58000,
|
||||
"memberCount": 120
|
||||
"memberCount": 120,
|
||||
"lastTimestamp": 1711468800
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -171,6 +186,36 @@ Token 可在 设置 → ChatLab API 页面查看和重新生成。
|
||||
| ---- | ------ | ------- |
|
||||
| `id` | string | 会话 ID |
|
||||
|
||||
**响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"id": "wechat_xxx@chatroom",
|
||||
"name": "产品讨论群",
|
||||
"platform": "wechat",
|
||||
"type": "group",
|
||||
"messageCount": 58000,
|
||||
"memberCount": 86,
|
||||
"firstTimestamp": 1609459200,
|
||||
"lastTimestamp": 1711468800,
|
||||
"lastPlatformMessageId": "msg_900000",
|
||||
"groupId": "xxx@chatroom",
|
||||
"importedAt": 1711469900
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| ----------------------- | ------------ | ------------------------------------------------------ |
|
||||
| `messageCount` | number | 会话内消息总数 |
|
||||
| `memberCount` | number | 成员总数 |
|
||||
| `firstTimestamp` | number\|null | 最早消息时间戳(秒级 Unix) |
|
||||
| `lastTimestamp` | number\|null | 最新消息时间戳(秒级 Unix) |
|
||||
| `lastPlatformMessageId` | string\|null | 最新一条有 platformMessageId 的消息 ID(用于增量边界) |
|
||||
| `importedAt` | number | 最后一次导入时间 |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/sessions/:id/messages
|
||||
@@ -186,8 +231,7 @@ Token 可在 设置 → ChatLab API 页面查看和重新生成。
|
||||
| `startTime` | number | - | 起始时间戳(秒级 Unix) |
|
||||
| `endTime` | number | - | 结束时间戳(秒级 Unix) |
|
||||
| `keyword` | string | - | 关键词搜索 |
|
||||
| `senderId` | string | - | 按发送者 platformId 筛选 |
|
||||
| `type` | number | - | 按消息类型筛选 |
|
||||
| `senderId` | string | - | 按发送者 ID 筛选 |
|
||||
|
||||
**请求示例:**
|
||||
|
||||
@@ -279,7 +323,7 @@ curl "http://127.0.0.1:5200/api/v1/sessions/abc123/messages?page=1&limit=50&keyw
|
||||
|
||||
```json
|
||||
{
|
||||
"sql": "SELECT sender, COUNT(*) as count FROM messages GROUP BY sender ORDER BY count DESC LIMIT 10"
|
||||
"sql": "SELECT sender_id, COUNT(*) as count FROM message GROUP BY sender_id ORDER BY count DESC LIMIT 10"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -289,16 +333,18 @@ curl "http://127.0.0.1:5200/api/v1/sessions/abc123/messages?page=1&limit=50&keyw
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"columns": ["sender", "count"],
|
||||
"columns": ["sender_id", "count"],
|
||||
"rows": [
|
||||
["123456", 5800],
|
||||
["789012", 3200]
|
||||
[1, 5800],
|
||||
[2, 3200]
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 关于数据库表结构,请参考 ChatLab 内部文档或使用 `SELECT * FROM sqlite_master WHERE type='table'` 查询。
|
||||
::: tip 提示
|
||||
使用 `SELECT * FROM sqlite_master WHERE type='table'` 查询可用的数据库表结构。
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
@@ -332,104 +378,6 @@ curl "http://127.0.0.1:5200/api/v1/sessions/abc123/messages?page=1&limit=50&keyw
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/import
|
||||
|
||||
将聊天记录导入 ChatLab,**创建新会话**。
|
||||
|
||||
#### 支持的 Content-Type
|
||||
|
||||
| Content-Type | 格式 | 适用场景 | Body 限制 |
|
||||
| ---------------------- | ------------------- | ------------------------------ | ---------- |
|
||||
| `application/json` | ChatLab Format JSON | 中小数据(快速测试、脚本集成) | **50MB** |
|
||||
| `application/x-ndjson` | ChatLab JSONL 格式 | 大规模数据(生产级集成) | **无限制** |
|
||||
|
||||
#### JSON 模式示例
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:5200/api/v1/import \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"chatlab": {
|
||||
"version": "0.0.2",
|
||||
"exportedAt": 1711468800
|
||||
},
|
||||
"meta": {
|
||||
"name": "导入测试",
|
||||
"platform": "qq",
|
||||
"type": "group"
|
||||
},
|
||||
"members": [
|
||||
{ "platformId": "123", "accountName": "测试用户" }
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"sender": "123",
|
||||
"accountName": "测试用户",
|
||||
"timestamp": 1711468800,
|
||||
"type": 0,
|
||||
"content": "Hello World"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
#### JSONL 模式示例
|
||||
|
||||
```bash
|
||||
cat data.jsonl | curl -X POST http://127.0.0.1:5200/api/v1/import \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/x-ndjson" \
|
||||
--data-binary @-
|
||||
```
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"mode": "new",
|
||||
"sessionId": "session_xyz789"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 关于 ChatLab Format 的详细规范,请参考 [ChatLab 标准化格式规范](./chatlab-format.md)。
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/sessions/:id/import
|
||||
|
||||
将聊天记录**增量导入**到已存在的会话。支持去重,相同消息不会重复插入。
|
||||
|
||||
**去重规则:**
|
||||
|
||||
消息唯一键为 `timestamp + senderPlatformId + contentLength`。如果一条消息的时间戳、发送者和内容长度与已有消息完全相同,则视为重复并跳过。
|
||||
|
||||
**路径参数:**
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
| ---- | ------ | ----------- |
|
||||
| `id` | string | 目标会话 ID |
|
||||
|
||||
Content-Type 和请求体格式与 `POST /api/v1/import` 相同。
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"mode": "incremental",
|
||||
"sessionId": "session_abc123",
|
||||
"newMessageCount": 150
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 并发与限制
|
||||
|
||||
| 限制项 | 值 | 说明 |
|
||||
@@ -444,18 +392,20 @@ Content-Type 和请求体格式与 `POST /api/v1/import` 相同。
|
||||
|
||||
## 错误码
|
||||
|
||||
| 错误码 | HTTP 状态码 | 说明 |
|
||||
| ------------------------ | ----------- | ------------------------------- |
|
||||
| `UNAUTHORIZED` | 401 | Token 无效或缺失 |
|
||||
| `SESSION_NOT_FOUND` | 404 | 会话不存在 |
|
||||
| `INVALID_FORMAT` | 400 | 请求体不符合 ChatLab Format |
|
||||
| `SQL_READONLY_VIOLATION` | 400 | SQL 不是 SELECT 语句 |
|
||||
| `SQL_EXECUTION_ERROR` | 400 | SQL 执行出错 |
|
||||
| `EXPORT_TOO_LARGE` | 400 | 消息数超过导出上限(10 万条) |
|
||||
| `BODY_TOO_LARGE` | 413 | 请求体超过 50MB(仅 JSON 模式) |
|
||||
| `IMPORT_IN_PROGRESS` | 409 | 有其他导入正在进行 |
|
||||
| `IMPORT_FAILED` | 500 | 导入失败 |
|
||||
| `SERVER_ERROR` | 500 | 服务内部错误 |
|
||||
| 错误码 | HTTP 状态码 | 说明 |
|
||||
| ------------------------ | ----------- | ----------------------------------- |
|
||||
| `UNAUTHORIZED` | 401 | Token 无效或缺失 |
|
||||
| `SESSION_NOT_FOUND` | 404 | 会话不存在 |
|
||||
| `INVALID_FORMAT` | 400 | Content-Type 不支持或请求体格式错误 |
|
||||
| `INVALID_PAYLOAD` | 400 | 必填字段缺失、类型错误或校验失败 |
|
||||
| `SQL_READONLY_VIOLATION` | 400 | SQL 不是 SELECT 语句 |
|
||||
| `SQL_EXECUTION_ERROR` | 400 | SQL 执行出错 |
|
||||
| `EXPORT_TOO_LARGE` | 400 | 消息数超过导出上限(10 万条) |
|
||||
| `BODY_TOO_LARGE` | 413 | 请求体超过 50MB(仅 JSON 模式) |
|
||||
| `IMPORT_IN_PROGRESS` | 409 | 有其他导入正在进行 |
|
||||
| `IDEMPOTENCY_CONFLICT` | 409 | 相同幂等键但请求体不一致 |
|
||||
| `IMPORT_FAILED` | 500 | 导入失败 |
|
||||
| `SERVER_ERROR` | 500 | 服务内部错误 |
|
||||
|
||||
---
|
||||
|
||||
@@ -474,9 +424,9 @@ Content-Type 和请求体格式与 `POST /api/v1/import` 相同。
|
||||
|
||||
将 ChatLab API 接入 Claude Desktop 等 AI 工具,实现 AI 对聊天记录的直接查询和分析。
|
||||
|
||||
### 2. 自动化脚本
|
||||
### 2. 自动化导入
|
||||
|
||||
编写脚本定期从其他平台导出聊天记录,转换为 ChatLab Format 后通过 Push API 自动导入。
|
||||
编写脚本定期从其他平台导出聊天记录,转换为 ChatLab Format 后通过 [Push 导入协议](./chatlab-import.md) 自动导入。
|
||||
|
||||
### 3. 数据分析
|
||||
|
||||
@@ -486,9 +436,9 @@ Content-Type 和请求体格式与 `POST /api/v1/import` 相同。
|
||||
|
||||
通过 `/export` 端点定期导出重要会话数据作为 JSON 备份。
|
||||
|
||||
### 5. 定时拉取
|
||||
### 5. 远程数据源
|
||||
|
||||
在设置页配置外部数据源 URL,ChatLab 会按设定间隔自动拉取并导入新数据。
|
||||
在设置页配置外部数据源 URL,ChatLab 按 [Pull 远程数据源协议](./chatlab-pull.md) 自动拉取并导入新数据。
|
||||
|
||||
---
|
||||
|
||||
@@ -496,4 +446,12 @@ Content-Type 和请求体格式与 `POST /api/v1/import` 相同。
|
||||
|
||||
| 版本 | 说明 |
|
||||
| ---- | ------------------------------------------------------------------------------ |
|
||||
| v1 | 初始版本,支持会话查询、消息搜索、SQL、导出、导入(JSON + JSONL)、Pull 调度器 |
|
||||
| v1 | 支持会话查询、消息搜索、SQL、导出、Push 导入(JSON + JSONL)、Pull 远程数据源 |
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [ChatLab 标准化格式规范](./chatlab-format.md) — 数据交换格式定义
|
||||
- [Push 导入协议](./chatlab-import.md) — 外部系统主动推送数据到 ChatLab
|
||||
- [Pull 远程数据源协议](./chatlab-pull.md) — 第三方暴露标准端点,ChatLab 主动拉取
|
||||
@@ -10,7 +10,9 @@ ChatLab 定义了一套标准的聊天记录数据交换格式,用于支持多
|
||||
|
||||
只要你将聊天记录转为该格式,那么就可以被 ChatLab 解析并使用其分析能力。
|
||||
|
||||
::: warning 注意该格式规范目前仍处于早期制定阶段,部分字段和结构可能会在后续版本中调整。:::
|
||||
::: warning 注意
|
||||
该格式规范目前仍处于早期制定阶段,部分字段和结构可能会在后续版本中调整。
|
||||
:::
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -165,7 +167,9 @@ ChatLab 定义了一套标准的聊天记录数据交换格式,用于支持多
|
||||
|
||||
## 消息类型对照表
|
||||
|
||||
::: tip 提示若您的聊天记录中有其他特殊类型需要支持,请提交 issue 说明情况,我们会评估是否加入标准消息类型中。:::
|
||||
::: tip 提示
|
||||
若您的聊天记录中有其他特殊类型需要支持,请提交 issue 说明情况,我们会评估是否加入标准消息类型中。
|
||||
:::
|
||||
|
||||
### 基础消息类型 (0-19)
|
||||
|
||||
@@ -232,7 +236,8 @@ https://example.com/avatars/user123.jpg
|
||||
|
||||
- 如果需要离线使用或长期存档,推荐使用 Data URL 格式
|
||||
- 导出 Data URL 时建议将头像压缩为 100×100 像素以内,以减小文件体积
|
||||
- 如果头像来自可靠的长期有效的 CDN,可使用网络 URL 以减小文件体积 :::
|
||||
- 如果头像来自可靠的长期有效的 CDN,可使用网络 URL 以减小文件体积
|
||||
:::
|
||||
|
||||
## 完整示例
|
||||
|
||||
|
||||
@@ -0,0 +1,465 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Push 导入协议
|
||||
|
||||
> v1
|
||||
|
||||
本文档定义外部数据源向 ChatLab 推送聊天数据的标准导入协议。覆盖首次全量导入、历史回填、周期性增量同步三类场景。
|
||||
|
||||
::: tip 两种导入方式
|
||||
|
||||
- **Push 模式**(本文档):外部系统主动将数据推送到 ChatLab 的导入接口。适用于脚本集成、一次性文件导入等场景。
|
||||
- **[Pull 模式](./chatlab-pull.md)**:第三方暴露标准 HTTP 端点,ChatLab 主动拉取数据。**推荐的第三方集成方式。**
|
||||
|
||||
两种模式底层共用同一套导入逻辑(去重、meta/members 更新、FTS 索引),数据格式统一为 [ChatLab Format](./chatlab-format.md)。
|
||||
|
||||
:::
|
||||
|
||||
## 设计原则
|
||||
|
||||
1. **统一入口**:首次导入和增量导入使用同一个端点,调用方无需区分。
|
||||
2. **接口最小化**:1 个导入接口 + 2 个查询接口覆盖全部 Push 场景。
|
||||
3. **双层幂等**:请求级幂等(Idempotency-Key)+ 记录级去重(platformMessageId / 内容哈希),承诺 **at-least-once + deterministic dedupe**。
|
||||
4. **同步优先**:小批量导入同步返回 `200 OK` 和写入结果。
|
||||
5. **默认自动更新**:meta 和 members 默认随导入请求自动更新,可通过 `options` 控制。
|
||||
|
||||
---
|
||||
|
||||
## 基础约定
|
||||
|
||||
### 服务地址
|
||||
|
||||
```
|
||||
Base URL:http://<host>:<port> (桌面端默认 127.0.0.1:5200)
|
||||
Prefix: /api/v1
|
||||
```
|
||||
|
||||
### 认证
|
||||
|
||||
所有请求必须携带 Bearer Token:
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
Token 在 ChatLab 设置页面生成,格式为 `clb_` + 64 字符 hex。
|
||||
|
||||
### Content-Type
|
||||
|
||||
```
|
||||
application/json # 标准 JSON body(≤50MB)
|
||||
application/x-ndjson # JSONL 流式(无大小限制)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 接口总表
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| ------ | ---------------------------- | -------------------------------------------- |
|
||||
| `POST` | `/api/v1/imports/:sessionId` | 导入消息到指定会话(首次自动创建,后续追加) |
|
||||
| `GET` | `/api/v1/sessions/:id` | 查询会话状态(主要用于对账校验) |
|
||||
| `GET` | `/api/v1/sessions` | 列出所有会话(发现目标 Session) |
|
||||
|
||||
查询接口的详细说明请参阅 [ChatLab API 文档](./chatlab-api.md)。
|
||||
|
||||
---
|
||||
|
||||
## POST /api/v1/imports/:sessionId
|
||||
|
||||
**唯一导入入口。** 会话不存在时自动创建,已存在时追加数据并自动更新 meta/members。
|
||||
|
||||
### Path 参数
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
| ----------- | ------ | ------------------------------------------------------------------------------------ |
|
||||
| `sessionId` | string | Session ID,由调用方生成并维护。同一聊天来源必须保持固定,跨批一致。生成策略见下方。 |
|
||||
|
||||
**Session ID 生成策略:**
|
||||
|
||||
| 优先级 | 场景 | 推荐格式 | 示例 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1(首选) | 有平台原始 ID | `{platform}_{originalId}` | `wechat_xxx@chatroom`、`qq_123456789` |
|
||||
| 2 | 文件导入(有结构化 ID) | `{platform}_{meta.groupId}` 或 `{platform}_{对方platformId}` | `wechat_xxx@chatroom` |
|
||||
| 3 | 文件导入(无结构化标识) | `file_{SHA256(文件内容)[:16]}` | `file_a1b2c3d4e5f6g7h8` |
|
||||
| 4(兜底) | 一次性导入 | `import_{UUID}` | `import_550e8400-e29b-41d4-a716-446655440000` |
|
||||
|
||||
::: warning 注意
|
||||
- 不建议使用文件路径作为 sessionId 的输入——文件重命名会导致 sessionId 变化
|
||||
- 同一聊天来源的首次导入和增量导入**必须**使用相同的 sessionId
|
||||
:::
|
||||
|
||||
### 请求 Header
|
||||
|
||||
| Header | 必填 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `Authorization` | 是 | `Bearer <token>` |
|
||||
| `Content-Type` | 是 | `application/json` 或 `application/x-ndjson` |
|
||||
| `Idempotency-Key` | 建议 | 当前批次的唯一标识,用于重试安全。建议格式:`{sessionId}-{batchIndex}-{windowStart}` |
|
||||
| `X-Dry-Run` | 否 | 设为 `true` 时仅分析不写入,返回预估结果 |
|
||||
|
||||
### 请求 Body(JSON 模式)
|
||||
|
||||
```json
|
||||
{
|
||||
"chatlab": {
|
||||
"version": "0.0.2",
|
||||
"exportedAt": 1711468800,
|
||||
"generator": "YourSystem/1.0"
|
||||
},
|
||||
"meta": {
|
||||
"name": "产品讨论群",
|
||||
"platform": "wechat",
|
||||
"type": "group",
|
||||
"groupId": "xxx@chatroom",
|
||||
"groupAvatar": "data:image/jpeg;base64,...",
|
||||
"ownerId": "wxid_owner"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
"platformId": "wxid_a",
|
||||
"accountName": "张三",
|
||||
"groupNickname": "产品",
|
||||
"avatar": "data:image/jpeg;base64,...",
|
||||
"roles": [{ "id": "owner" }]
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"platformMessageId": "msg_1001",
|
||||
"sender": "wxid_a",
|
||||
"accountName": "张三",
|
||||
"groupNickname": "产品",
|
||||
"timestamp": 1711468800,
|
||||
"type": 0,
|
||||
"content": "Hello",
|
||||
"replyToMessageId": "msg_1000"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"metaUpdateMode": "patch",
|
||||
"memberUpdateMode": "upsert"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### options 对象(可选)
|
||||
|
||||
| 字段 | 类型 | 默认值 | 可选值 | 说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `metaUpdateMode` | string | `patch` | `patch` / `none` | `patch`:非空字段覆盖更新;`none`:跳过更新 |
|
||||
| `memberUpdateMode` | string | `upsert` | `upsert` / `none` | `upsert`:新增+更新;`none`:跳过更新 |
|
||||
|
||||
::: tip 提示
|
||||
回填历史数据时建议传 `"metaUpdateMode": "none"` 防止旧群名覆盖当前值。
|
||||
:::
|
||||
|
||||
### 请求 Body(JSONL 模式)
|
||||
|
||||
每行一个 JSON 对象,通过 `_type` 字段区分类型。行顺序:`header` → `member`(零或多行) → `message`(一或多行)。
|
||||
|
||||
```jsonl
|
||||
{"_type":"header","chatlab":{"version":"0.0.2","exportedAt":1711468800,"generator":"YourSystem/1.0"},"meta":{"name":"产品讨论群","platform":"wechat","type":"group","groupId":"xxx@chatroom"},"options":{"metaUpdateMode":"patch","memberUpdateMode":"upsert"}}
|
||||
{"_type":"member","platformId":"wxid_a","accountName":"张三","groupNickname":"产品"}
|
||||
{"_type":"message","platformMessageId":"msg_1001","sender":"wxid_a","accountName":"张三","timestamp":1711468800,"type":0,"content":"Hello"}
|
||||
{"_type":"message","platformMessageId":"msg_1002","sender":"wxid_b","accountName":"李四","timestamp":1711468860,"type":0,"content":"Hi"}
|
||||
```
|
||||
|
||||
### 各块携带规则
|
||||
|
||||
| 块 | 会话首次创建 | 后续增量导入 | 语义 |
|
||||
| ---------- | ------------ | ------------ | -------------------------------------------------------------- |
|
||||
| `chatlab` | 必填 | 可选 | 首次用于创建会话;后续用于版本兼容判断 |
|
||||
| `meta` | 必填 | 可选 | 首次作为初始值;后续携带则非空字段自动覆盖更新 |
|
||||
| `members` | 必填 | 可选 | 首次写入全量成员;后续按 `platformId` 做 upsert |
|
||||
| `messages` | 必填 | 必填 | 每批必须包含至少一条消息 |
|
||||
|
||||
**Meta 自动更新规则:**
|
||||
|
||||
- 调用方传了且值不为空的字段 → 覆盖更新
|
||||
- 调用方未传或值为空的字段 → 保持原值不变
|
||||
- `platform` 和 `type` 不允许增量更新(会话创建后不变)
|
||||
|
||||
**Members Upsert 规则:**
|
||||
|
||||
- 按 `platformId` 匹配:新 `platformId` → 插入为新成员;已存在的 → 更新非空字段
|
||||
- 不携带 `members` 时:消息中出现的未知 `sender` 仍会被自动创建为成员(仅含最小信息)
|
||||
|
||||
---
|
||||
|
||||
### 字段定义
|
||||
|
||||
#### chatlab 对象
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| ------------ | ------ | ---- | --------------------------------- |
|
||||
| `version` | string | 是 | 格式版本号,当前为 `"0.0.2"` |
|
||||
| `exportedAt` | number | 是 | 导出/生成时间(秒级 Unix 时间戳) |
|
||||
| `generator` | string | 否 | 生成工具/系统名称 |
|
||||
|
||||
#### meta 对象
|
||||
|
||||
| 字段 | 类型 | 首次必填 | 说明 |
|
||||
| ------------- | ------ | -------- | -------------------------------------------- |
|
||||
| `name` | string | 是 | 群名/会话名 |
|
||||
| `platform` | string | 是 | 平台标识(见下方枚举) |
|
||||
| `type` | string | 是 | 会话类型:`group`(群聊)/ `private`(私聊) |
|
||||
| `groupId` | string | 否 | 群的平台原始 ID |
|
||||
| `groupAvatar` | string | 否 | 群头像,base64 Data URL 或网络 URL |
|
||||
| `ownerId` | string | 否 | 导出者/所有者的 platformId |
|
||||
|
||||
**平台标识枚举:**
|
||||
|
||||
| 值 | 平台 |
|
||||
| ---------- | --------- |
|
||||
| `wechat` | 微信 |
|
||||
| `qq` | QQ |
|
||||
| `telegram` | Telegram |
|
||||
| `discord` | Discord |
|
||||
| `whatsapp` | WhatsApp |
|
||||
| `line` | LINE |
|
||||
| `slack` | Slack |
|
||||
| `unknown` | 未知/其他 |
|
||||
|
||||
::: tip 提示
|
||||
如果你的平台不在上述列表中,可使用小写英文标识(如 `signal`、`matrix`),ChatLab 会按 `unknown` 的分析策略处理。
|
||||
:::
|
||||
|
||||
#### members 数组元素
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --------------- | ------ | ---- | -------------------------------------- |
|
||||
| `platformId` | string | 是 | 成员在平台的唯一标识(QQ号、微信ID等) |
|
||||
| `accountName` | string | 建议 | 账号名称(不随群变化的原始昵称) |
|
||||
| `groupNickname` | string | 否 | 群内专属昵称 |
|
||||
| `avatar` | string | 否 | 头像,base64 Data URL 或网络 URL |
|
||||
| `roles` | array | 否 | 角色列表,见 [角色定义](./chatlab-format.md#角色-roles) |
|
||||
|
||||
#### messages 数组元素
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| ------------------- | ------------ | -------- | ------------------------------------------------------------------- |
|
||||
| `sender` | string | 是 | 发送者的 `platformId` 或保留标识(如 `SYSTEM`) |
|
||||
| `timestamp` | number | 是 | 消息时间戳,秒级 Unix 时间戳 |
|
||||
| `type` | number | 是 | 消息类型枚举(见 [消息类型](./chatlab-format.md#消息类型对照表)) |
|
||||
| `accountName` | string | 建议 | 发送时的账号名称 |
|
||||
| `groupNickname` | string | 否 | 发送时的群昵称 |
|
||||
| `content` | string\|null | 否 | 纯文本内容,非文本消息可为 null |
|
||||
| `platformMessageId` | string | 强烈建议 | 消息的平台原始 ID,去重的首选依据 |
|
||||
| `replyToMessageId` | string | 否 | 回复目标消息的 `platformMessageId` |
|
||||
|
||||
**sender 字段规则:**
|
||||
|
||||
1. 必须是稳定的 `platformId` 或保留标识 `SYSTEM`
|
||||
2. 若 `sender` 对应的成员不在 `members` 中,ChatLab 自动补创建成员(仅含最小信息)
|
||||
3. `SYSTEM` 用于系统消息(入群/退群/公告等),不计入成员统计
|
||||
|
||||
---
|
||||
|
||||
### 成功响应
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"sessionId": "wechat_xxx@chatroom",
|
||||
"created": false,
|
||||
"batch": {
|
||||
"receivedCount": 5000,
|
||||
"writtenCount": 4986,
|
||||
"duplicateCount": 14
|
||||
},
|
||||
"session": {
|
||||
"totalCount": 128640,
|
||||
"memberCount": 86,
|
||||
"firstTimestamp": 1609459200,
|
||||
"lastTimestamp": 1711468800
|
||||
},
|
||||
"updates": {
|
||||
"metaUpdated": true,
|
||||
"membersAdded": 3,
|
||||
"membersUpdated": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 说明 |
|
||||
| ------------------------ | ----------------------------------------------------- |
|
||||
| `created` | `true` 表示本次请求触发了会话创建(首次导入) |
|
||||
| `batch.receivedCount` | 本批收到的消息条数 |
|
||||
| `batch.writtenCount` | 实际写入的条数 |
|
||||
| `batch.duplicateCount` | 因去重跳过的条数 |
|
||||
| `session.totalCount` | 写入后会话的累计消息总数 |
|
||||
| `session.memberCount` | 会话的成员总数 |
|
||||
| `session.firstTimestamp` | 会话内最早消息时间戳 |
|
||||
| `session.lastTimestamp` | 会话内最新消息时间戳 |
|
||||
| `updates.metaUpdated` | 本次请求是否触发了 meta 更新 |
|
||||
| `updates.membersAdded` | 本次新增的成员数 |
|
||||
| `updates.membersUpdated` | 本次更新的成员数 |
|
||||
|
||||
---
|
||||
|
||||
## 去重语义
|
||||
|
||||
去重在单个 Session 内生效,不跨会话。
|
||||
|
||||
**优先级:**
|
||||
|
||||
1. 若消息提供了 `platformMessageId`,以此作为唯一键去重(高精度,推荐)。
|
||||
2. 若未提供 `platformMessageId`,退化为内容哈希去重:`sha256(timestamp + '\0' + sender + '\0' + contentTag + '\0' + normalizedContent)`
|
||||
|
||||
| 层次 | 机制 | 适用范围 | 精度 |
|
||||
| ------------------ | ----------------------------------------------- | ----------------------------- | -------- |
|
||||
| 请求级幂等 | `Idempotency-Key` | 同一 HTTP 请求的重试 | 精确 |
|
||||
| 消息级去重(主键) | `platformMessageId` | 跨批次、跨窗口的同一条消息 | 精确 |
|
||||
| 消息级去重(降级) | 内容哈希 `sha256(timestamp + sender + content)` | 无 platformMessageId 时的兜底 | 最大努力 |
|
||||
|
||||
::: warning 注意
|
||||
- 同一 `platformMessageId` 的消息不会被重复写入,即使 content 不同(以首次写入为准)
|
||||
- 内容哈希去重在"同一人、同一秒、完全相同内容"时判定为重复,存在极小概率误判
|
||||
- **强烈建议**外部数据源提供 `platformMessageId`,这是最可靠的去重依据
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## 分批策略
|
||||
|
||||
### 默认批次大小
|
||||
|
||||
每批建议 **5000 条消息**。
|
||||
|
||||
| 约束 | 值 | 说明 |
|
||||
| ------------------ | ------------ | ------------------------------- |
|
||||
| JSON body 大小上限 | 50MB | 超过返回 `BODY_TOO_LARGE` (413) |
|
||||
| JSONL body 大小 | 无限制 | 通过 stream 写入临时文件后处理 |
|
||||
| 建议每批消息数 | 5000 条 | 兼顾性能和内存占用 |
|
||||
|
||||
### 分批原则
|
||||
|
||||
- 按时间顺序分批,从旧到新推送
|
||||
- 批次间允许时间重叠(建议重叠 5~10 分钟),依靠去重吸收
|
||||
- 每批独立请求,任意一批失败不影响其他批次
|
||||
- 第一批必须携带 `chatlab` + `meta` + `members`(触发会话创建)
|
||||
- 后续批次可仅携带 `messages`
|
||||
|
||||
### 游标维护(由调用方负责)
|
||||
|
||||
ChatLab 不为调用方维护游标。推荐结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"sessionId": "wechat_xxx@chatroom",
|
||||
"lastSyncedTimestamp": 1711468800,
|
||||
"lastSyncedMessageId": "msg_900000"
|
||||
}
|
||||
```
|
||||
|
||||
每批成功后,将响应中的 `session.lastTimestamp` 更新到游标。失败时保持游标不变,用相同的 `Idempotency-Key` 重试。
|
||||
|
||||
### 并发约束
|
||||
|
||||
当前版本:**同一时刻仅允许一个导入任务**。并发请求会收到 `IMPORT_IN_PROGRESS` (409) 错误。
|
||||
|
||||
---
|
||||
|
||||
## 标准调用流程
|
||||
|
||||
### 首次全量导入(Bootstrap)
|
||||
|
||||
```
|
||||
1. 准备全量聊天数据,按时间顺序切分为 N 批(每批 ≤5000 条)
|
||||
|
||||
2. 第一批请求:
|
||||
POST /api/v1/imports/wechat_xxx@chatroom
|
||||
Body: { chatlab, meta, members, messages }
|
||||
→ 响应 created: true,会话创建成功
|
||||
|
||||
3. 第 2~N 批请求:
|
||||
POST /api/v1/imports/wechat_xxx@chatroom
|
||||
Body: { messages }
|
||||
Idempotency-Key: {sessionId}-{batchIndex}-{windowStart}
|
||||
|
||||
4. 每批成功后记录游标;失败用相同 Idempotency-Key 重试
|
||||
|
||||
5. 全部批次完成后对账:
|
||||
GET /api/v1/sessions/wechat_xxx@chatroom
|
||||
→ 校验 totalCount、firstTimestamp、lastTimestamp
|
||||
```
|
||||
|
||||
### 历史回填(Backfill)
|
||||
|
||||
```
|
||||
1. 确定需要补齐的时间区间 [start, end]
|
||||
2. 按时间窗口拆分为多批
|
||||
3. 依次调用 POST /api/v1/imports/:sessionId
|
||||
(建议设置 options.metaUpdateMode: "none" 防止旧群名覆盖)
|
||||
4. 每批成功后更新本地游标
|
||||
5. 可选:GET /api/v1/sessions/:id 对账
|
||||
```
|
||||
|
||||
### 每日定时增量(Scheduled Sync)
|
||||
|
||||
```
|
||||
1. 固定 Session ID + 定时器(如每小时/每天)
|
||||
2. 从上次游标开始,向前重叠 5~10 分钟作为窗口起点
|
||||
3. 拉取该时间窗口内的新消息
|
||||
4. 如有新成员或群名变更,携带 meta/members
|
||||
5. 调用 POST /api/v1/imports/:sessionId
|
||||
6. 依靠去重吸收重叠数据
|
||||
7. 更新本地游标
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 媒体附件(协议预留)
|
||||
|
||||
当前版本重点保证文本消息的导入稳定性。`attachments` 作为协议预留字段:调用方可在消息中携带该字段,ChatLab 当前接收但不承诺完整落库与渲染。
|
||||
|
||||
预留字段结构见 [ChatLab 格式规范](./chatlab-format.md)。
|
||||
|
||||
---
|
||||
|
||||
## 错误码与重试策略
|
||||
|
||||
| 错误码 | HTTP 状态 | 说明 | 可重试 |
|
||||
| --- | --- | --- | --- |
|
||||
| `UNAUTHORIZED` | 401 | Token 无效或缺失 | 否 |
|
||||
| `INVALID_FORMAT` | 400 | Content-Type 不支持或请求体格式错误 | 否 |
|
||||
| `INVALID_PAYLOAD` | 400 | 必填字段缺失、类型错误或校验失败 | 否 |
|
||||
| `BODY_TOO_LARGE` | 413 | JSON body 超过 50MB | 否 |
|
||||
| `IMPORT_IN_PROGRESS` | 409 | 当前有其他导入正在执行 | 是 |
|
||||
| `IDEMPOTENCY_CONFLICT` | 409 | 相同幂等键但请求体不一致 | 否 |
|
||||
| `IMPORT_FAILED` | 500 | 导入过程内部错误 | 是 |
|
||||
| `SERVER_ERROR` | 500 | 服务内部错误 | 是 |
|
||||
|
||||
**重试策略建议:**
|
||||
|
||||
```
|
||||
最大重试次数:3
|
||||
退避策略:指数退避 + 随机抖动
|
||||
第 1 次重试:5s + random(0, 1s)
|
||||
第 2 次重试:15s + random(0, 3s)
|
||||
第 3 次重试:45s + random(0, 5s)
|
||||
重试时必须使用相同的 Idempotency-Key
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 版本与兼容性
|
||||
|
||||
- `chatlab.version`:`0.0.2`
|
||||
- API 路径前缀:`/api/v1`
|
||||
- **向后兼容**:新增字段均为可选,不破坏旧调用方
|
||||
- **字段废弃策略**:废弃字段先标记为 `deprecated`,保留两个版本后移除
|
||||
- **平台标识可扩展**:`platform` 字段不限于预定义枚举,可传入任意小写字母标识
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [ChatLab API 文档](./chatlab-api.md) — 查询、导出和系统端点
|
||||
- [Pull 远程数据源协议](./chatlab-pull.md) — 第三方暴露标准端点,ChatLab 主动拉取
|
||||
- [ChatLab 标准化格式规范](./chatlab-format.md) — 数据交换格式定义
|
||||
@@ -0,0 +1,308 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Pull 远程数据源协议
|
||||
|
||||
> v1
|
||||
|
||||
本文档定义第三方数据源暴露标准 HTTP 端点供 ChatLab 主动拉取数据的协议规范。这是 ChatLab 生态**推荐的第三方集成方式**。
|
||||
|
||||
::: tip 两种导入方式
|
||||
|
||||
- **[Push 模式](./chatlab-import.md)**:外部系统主动将数据推送到 ChatLab 的导入接口。适用于脚本集成、一次性文件导入。
|
||||
- **Pull 模式**(本文档):第三方暴露标准 HTTP 端点,ChatLab 主动拉取数据。**推荐的第三方集成方式。**
|
||||
|
||||
:::
|
||||
|
||||
## 为什么 Pull 是推荐方案
|
||||
|
||||
- 第三方工具是数据生产者,天然适合暴露数据;ChatLab 是数据消费者/分析者,天然适合主动获取
|
||||
- 用户只需在 ChatLab UI 中输入数据源地址,即可浏览、选择、同步——操作完全在 ChatLab 端完成
|
||||
- Push 模式需要第三方实现 HTTP 客户端逻辑(批次管理、重试、游标维护),门槛更高
|
||||
- Pull 协议定义的是**通用数据暴露标准**,不只服务 ChatLab,任何兼容工具都可以接入
|
||||
|
||||
**适用场景:**
|
||||
|
||||
- 外部采集端运行在远程设备上,只需暴露 HTTP 接口
|
||||
- 用户希望在 ChatLab UI 上浏览可用对话、选择导入、点击"立即同步"
|
||||
- 需要定时自动增量同步的长期运行场景
|
||||
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
Pull 模式的工作流程分为三个阶段:
|
||||
|
||||
```
|
||||
1. 发现:ChatLab 获取数据源上的所有可用对话列表
|
||||
2. 拉取:用户选择对话后,ChatLab 拉取历史消息
|
||||
3. 同步:定时增量拉取新消息(可选 SSE 实时通知加速)
|
||||
```
|
||||
|
||||
第三方数据源只需按本协议实现标准 HTTP 端点,ChatLab(以及未来任何兼容工具)即可自动完成发现、全量拉取和增量同步。
|
||||
|
||||
---
|
||||
|
||||
## 阶段一:发现可用对话
|
||||
|
||||
ChatLab 连接到远程数据源后,首先获取所有可拉取的对话列表。
|
||||
|
||||
### GET /sessions
|
||||
|
||||
```
|
||||
GET {baseUrl}/sessions
|
||||
Authorization: Bearer {token} ← 仅配置了 token 时携带
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
**可选参数:**
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
| --------- | ------ | ------------------------ |
|
||||
| `keyword` | string | 按对话名称模糊搜索 |
|
||||
| `limit` | number | 返回条数限制(默认全部) |
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"sessions": [
|
||||
{
|
||||
"id": "xxx@chatroom",
|
||||
"name": "产品讨论群",
|
||||
"platform": "wechat",
|
||||
"type": "group",
|
||||
"messageCount": 58000,
|
||||
"memberCount": 86,
|
||||
"lastMessageAt": 1711468800
|
||||
},
|
||||
{
|
||||
"id": "wxid_friend_a",
|
||||
"name": "张三",
|
||||
"platform": "wechat",
|
||||
"type": "private",
|
||||
"messageCount": 1200,
|
||||
"memberCount": 2,
|
||||
"lastMessageAt": 1711465200
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --------------- | ------ | ---- | ----------------------------------- |
|
||||
| `id` | string | 是 | 对话在数据源中的唯一标识 |
|
||||
| `name` | string | 是 | 对话名称(群名/联系人名) |
|
||||
| `platform` | string | 是 | 平台标识(与 Push 模式相同) |
|
||||
| `type` | string | 是 | `group` / `private` |
|
||||
| `messageCount` | number | 否 | 消息总数(用于 ChatLab 展示预估量) |
|
||||
| `memberCount` | number | 否 | 成员数 |
|
||||
| `lastMessageAt` | number | 否 | 最新消息时间戳 |
|
||||
|
||||
ChatLab 在 UI 中展示该列表,用户选择需要导入的对话。
|
||||
|
||||
---
|
||||
|
||||
## 阶段二:拉取对话数据
|
||||
|
||||
用户选定对话后,ChatLab 拉取指定对话的数据。
|
||||
|
||||
### GET /sessions/:id/messages
|
||||
|
||||
```
|
||||
GET {baseUrl}/sessions/{sessionId}/messages?format=chatlab&since={timestamp}
|
||||
Authorization: Bearer {token}
|
||||
Accept: application/json, application/x-ndjson
|
||||
```
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
| ----------- | ---- | ------------------------------------------------------------------- |
|
||||
| `sessionId` | 是 | 来自阶段一返回的对话 `id` |
|
||||
| `format` | 是 | 固定为 `chatlab`,要求数据源返回 ChatLab 标准格式 |
|
||||
| `since` | 否 | Unix 时间戳(秒级)。省略或为 `0` 时为全量拉取,大于 0 时为增量拉取 |
|
||||
| `end` | 否 | Unix 时间戳(秒级)。指定时间范围上界,用于历史回填等分段拉取 |
|
||||
| `limit` | 否 | 单次返回的最大消息数,用于分页 |
|
||||
| `offset` | 否 | 分页偏移量,配合 `limit` 使用 |
|
||||
|
||||
### 数据携带规则
|
||||
|
||||
- **首次全量**(`since` 为空或 0):**必须**包含 `chatlab` + `meta` + `members` + `messages`
|
||||
- **增量同步**(`since > 0`):**必须**包含 `messages`。`meta` / `members` **仅在发生实际变更时携带**,未变更时不得携带,以避免历史快照覆盖当前状态
|
||||
- 无新数据时返回空 `messages` 数组
|
||||
|
||||
### 响应格式
|
||||
|
||||
响应为标准 [ChatLab Format](./chatlab-format.md)(JSON 或 JSONL),并附带 `sync` 同步元信息。
|
||||
|
||||
```json
|
||||
{
|
||||
"chatlab": { "version": "0.0.2", "exportedAt": 1711468800 },
|
||||
"meta": { "name": "产品讨论群", "platform": "wechat", "type": "group" },
|
||||
"members": [ ... ],
|
||||
"messages": [ ... ],
|
||||
"sync": {
|
||||
"hasMore": true,
|
||||
"nextSince": 1711468800,
|
||||
"nextOffset": 5000,
|
||||
"watermark": 1711470000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### sync 同步元信息
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| ------------ | ------- | ------------------------------------------------------------------------------------------ |
|
||||
| `hasMore` | boolean | 是否还有更多数据。为 `true` 时 ChatLab 自动续拉 |
|
||||
| `nextSince` | number | 下一次请求建议使用的 `since` 值 |
|
||||
| `nextOffset` | number | 下一次请求建议使用的 `offset` 值,用于分页续拉 |
|
||||
| `watermark` | number | 本次拉取的快照上界时间戳,防止分页期间新数据写入导致的窗口漂移 |
|
||||
|
||||
**sync 块的必要性规则:**
|
||||
|
||||
| 数据源返回方式 | sync 块要求 | 说明 |
|
||||
| -------------------------- | ----------- | ---------------------------------------------------------------- |
|
||||
| 单次返回全部数据(不分页) | 可选 | ChatLab 视 `messages` 为完整结果 |
|
||||
| 支持 `limit`/`offset` 分页 | **必须** | 至少包含 `hasMore`;若无法保证快照一致性,还必须包含 `watermark` |
|
||||
|
||||
::: warning 注意
|
||||
若数据源支持分页但未返回 `sync` 块,ChatLab 不保证自动续拉和分页一致性——仅处理首次返回的数据。
|
||||
:::
|
||||
|
||||
### 快照一致性要求
|
||||
|
||||
- 同一次分页拉取(通过 `limit`/`offset` 遍历)**应当**基于同一数据快照视图
|
||||
- 若数据源无法保证快照一致性,**必须**返回 `sync.watermark`,供 ChatLab 固定拉取窗口上界
|
||||
|
||||
### 分批拉取策略
|
||||
|
||||
对于大量历史数据(如数万条消息),推荐两种分批方式:
|
||||
|
||||
1. **时间窗口分批**:通过 `since` + `end` 指定时间段,逐段拉取
|
||||
2. **分页分批**:通过 `limit` + `offset` 做数据库级分页,结合 `sync` 块自动续拉
|
||||
|
||||
ChatLab 会自动处理分批场景,通过去重机制保证不重复写入。
|
||||
|
||||
---
|
||||
|
||||
## 阶段三:定时增量同步
|
||||
|
||||
ChatLab 按用户配置的间隔,定期对已订阅的对话执行增量拉取:
|
||||
|
||||
```
|
||||
GET {baseUrl}/sessions/{sessionId}/messages?format=chatlab&since={lastPullAt}
|
||||
```
|
||||
|
||||
远程数据源返回 `since` 之后的增量消息。ChatLab 通过内部导入管道处理(去重、meta/members 更新、FTS 索引等全部复用 Push 模式逻辑)。
|
||||
|
||||
---
|
||||
|
||||
## 可选:SSE 实时通知
|
||||
|
||||
除定时轮询外,远程数据源可**可选**实现 SSE(Server-Sent Events)端点,用于**通知 ChatLab 有新数据可拉取**。
|
||||
|
||||
::: warning 重要
|
||||
SSE 仅作为通知通道,不是数据同步主通道。ChatLab 不假设 SSE 事件可靠送达(网络断连、进程重启均可能丢失事件)。最终数据一致性始终由定时 Pull 保证。SSE 的作用是将增量同步延迟从"分钟级"降到"秒级"。
|
||||
:::
|
||||
|
||||
### GET /push/messages
|
||||
|
||||
```
|
||||
GET {baseUrl}/push/messages
|
||||
Authorization: Bearer {token}
|
||||
Accept: text/event-stream
|
||||
```
|
||||
|
||||
**事件格式:**
|
||||
|
||||
```
|
||||
event: message.new
|
||||
data: {"eventId":"evt_001","sessionId":"xxx@chatroom","timestamp":1711468800}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| ------------------- | ------ | ---- | ------------------------------------------ |
|
||||
| `eventId` | string | 是 | 事件唯一 ID,用于 ChatLab 去重已处理的通知 |
|
||||
| `sessionId` | string | 是 | 有新消息的对话 ID |
|
||||
| `timestamp` | number | 是 | 新消息的时间戳 |
|
||||
| `platformMessageId` | string | 否 | 新消息的平台 ID(如可获取) |
|
||||
|
||||
ChatLab 接收到 SSE 事件后,**触发一次该 session 的增量拉取**(调用 `GET /sessions/:id/messages?format=chatlab&since={lastPullAt}`),而非直接将事件数据写入存储。
|
||||
|
||||
---
|
||||
|
||||
## 认证
|
||||
|
||||
远程数据源可选择是否要求认证。如果需要,使用 `Authorization: Bearer {token}` 机制。
|
||||
|
||||
::: tip SSE 认证
|
||||
部分数据源额外支持 `?access_token=TOKEN` 查询参数方式传递 Token(SSE 长连接场景推荐此方式,因为 EventSource API 不支持自定义 Header)。ChatLab 在连接 SSE 时也支持查询参数传 Token。
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## 实现指南
|
||||
|
||||
### 最小实现(2 个端点)
|
||||
|
||||
只需实现以下两个端点即可接入 ChatLab:
|
||||
|
||||
| 端点 | 说明 |
|
||||
| --------------------------------------------------- | --------------------- |
|
||||
| `GET /sessions` | 返回对话列表 |
|
||||
| `GET /sessions/:id/messages?format=chatlab&since=X` | 返回 ChatLab 格式数据 |
|
||||
|
||||
最小实现不需要分页、SSE 或复杂的 `sync` 块。ChatLab 会将响应中的 `messages` 视为完整数据。
|
||||
|
||||
### 增强实现
|
||||
|
||||
| 能力 | 说明 |
|
||||
| -------------------------- | ------------------------------------------------------------ |
|
||||
| `GET /push/messages` | SSE 实时通知(仅唤醒拉取,不传输完整数据) |
|
||||
| 支持 `limit`/`offset` 分页 | 大量历史数据的分页拉取 |
|
||||
| 支持 `end` 参数 | 时间窗口分段拉取 |
|
||||
| 响应包含 `sync` 块 | 提供 `hasMore`/`nextSince`/`nextOffset`/`watermark` 续拉信息 |
|
||||
|
||||
### 数据格式
|
||||
|
||||
所有数据响应必须符合 [ChatLab 标准化格式规范](./chatlab-format.md)(JSON 或 JSONL),包括 `chatlab`、`meta`、`members`、`messages` 四个标准块。
|
||||
|
||||
### 媒体文件
|
||||
|
||||
如果数据源的消息中包含媒体引用,`attachments` 中的 `filePath` 或 `dataUri` 可指向数据源的媒体服务端点。ChatLab 当前按"协议预留"处理,未来版本将支持从数据源拉取媒体文件。
|
||||
|
||||
---
|
||||
|
||||
## 示例场景
|
||||
|
||||
某采集端在手机上持续采集微信消息,暴露 `GET /sessions` 和 `GET /sessions/:id/messages` 两个端点。用户在 ChatLab 中操作:
|
||||
|
||||
```
|
||||
1. 在 ChatLab 设置中添加远程数据源(输入采集端 URL + 可选 Token)
|
||||
|
||||
2. ChatLab 调用 GET {baseUrl}/sessions
|
||||
→ 展示 86 个群和 200 个私聊
|
||||
|
||||
3. 用户选择其中 5 个群导入
|
||||
|
||||
4. ChatLab 立即执行全量拉取:
|
||||
GET {baseUrl}/sessions/{id}/messages?format=chatlab&since=0
|
||||
→ 如有 sync.hasMore=true,自动续拉直到全部完成
|
||||
|
||||
5. 之后每小时自动增量同步:
|
||||
GET {baseUrl}/sessions/{id}/messages?format=chatlab&since={lastPullAt}
|
||||
|
||||
6. 如果采集端实现了 SSE:
|
||||
收到 message.new 事件 → 立即触发增量拉取(不等定时器)
|
||||
|
||||
7. 用户可随时在 ChatLab UI 点击"立即同步"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [ChatLab API 文档](./chatlab-api.md) — 查询、导出和系统端点
|
||||
- [Push 导入协议](./chatlab-import.md) — 外部系统主动推送数据到 ChatLab
|
||||
- [ChatLab 标准化格式规范](./chatlab-format.md) — 数据交换格式定义
|
||||
@@ -8,7 +8,9 @@ ChatLab defines a standard chat record data exchange format to support unified i
|
||||
|
||||
As long as you convert your chat records to this format, ChatLab can parse and analyze them.
|
||||
|
||||
::: warning Notice This format specification is still in its early development stage. Some fields and structures may be adjusted in future versions. :::
|
||||
::: warning Notice
|
||||
This format specification is still in its early development stage. Some fields and structures may be adjusted in future versions.
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -111,7 +113,9 @@ Here's a **minimal** ChatLab format example with only required fields:
|
||||
|
||||
## Message Type Reference
|
||||
|
||||
::: warning Tip If you have other special types in your chat records that need support, please submit an issue explaining your situation. We'll evaluate whether to add them to the standard message types. :::
|
||||
::: warning Tip
|
||||
If you have other special types in your chat records that need support, please submit an issue explaining your situation. We'll evaluate whether to add them to the standard message types.
|
||||
:::
|
||||
|
||||
### Basic Message Types (0-19)
|
||||
|
||||
@@ -162,7 +166,9 @@ Supported image formats:
|
||||
- `image/gif` - GIF format
|
||||
- `image/webp` - WebP format
|
||||
|
||||
::: tip Suggestion When exporting, we recommend compressing avatars to 100×100 pixels or less to reduce file size. :::
|
||||
::: tip Suggestion
|
||||
When exporting, we recommend compressing avatars to 100×100 pixels or less to reduce file size.
|
||||
:::
|
||||
|
||||
## Complete Examples
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ ChatLab 定義了一套標準的聊天記錄資料交換格式,用於支援多
|
||||
|
||||
只要你將聊天記錄轉為該格式,那麼就可以被 ChatLab 解析並使用其分析能力。
|
||||
|
||||
::: warning 注意該格式規範目前仍處於早期制定階段,部分欄位和結構可能會在後續版本中調整。:::
|
||||
::: warning 注意
|
||||
該格式規範目前仍處於早期制定階段,部分欄位和結構可能會在後續版本中調整。
|
||||
:::
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -170,7 +172,9 @@ ChatLab 定義了一套標準的聊天記錄資料交換格式,用於支援多
|
||||
|
||||
## 訊息類型對照表
|
||||
|
||||
::: tip 提示若您的聊天記錄中有其他特殊類型需要支援,請提交 issue 說明情況,我們會評估是否加入標準訊息類型中。:::
|
||||
::: tip 提示
|
||||
若您的聊天記錄中有其他特殊類型需要支援,請提交 issue 說明情況,我們會評估是否加入標準訊息類型中。
|
||||
:::
|
||||
|
||||
### 基礎訊息類型 (0-19)
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ ChatLab 定義了一套標準的聊天記錄資料交換格式,用於支援多
|
||||
|
||||
只要你將聊天記錄轉為該格式,那麼就可以被 ChatLab 解析並使用其分析能力。
|
||||
|
||||
::: warning 注意該格式規範目前仍處於早期制定階段,部分欄位和結構可能會在後續版本中調整。:::
|
||||
::: warning 注意
|
||||
該格式規範目前仍處於早期制定階段,部分欄位和結構可能會在後續版本中調整。
|
||||
:::
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -165,7 +167,9 @@ ChatLab 定義了一套標準的聊天記錄資料交換格式,用於支援多
|
||||
|
||||
## 訊息類型對照表
|
||||
|
||||
::: tip 提示若您的聊天記錄中有其他特殊類型需要支援,請提交 issue 說明情況,我們會評估是否加入標準訊息類型中。:::
|
||||
::: tip 提示
|
||||
若您的聊天記錄中有其他特殊類型需要支援,請提交 issue 說明情況,我們會評估是否加入標準訊息類型中。
|
||||
:::
|
||||
|
||||
### 基礎訊息類型 (0-19)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user