31 KiB
4-3 文本标注与语音标注(Label Studio)
学习目标
- 掌握 Label Studio 文本标注的四种类型:分类、NER、意图、关系
- 掌握 Label Studio 语音标注的四种类型:转写、说话人、分类
- 学会 BIO 标注法、CoNLL 数据格式
- 独立完成一个文本分类和一个 ASR 项目
1. 为什么用 Label Studio 做文本和语音
1.1 回顾:Label Studio 的多模态优势
一个工具,全模态覆盖:
┌──────────┐
图像 ──→│ │
文本 ──→│ Label │──→ 统一管理
语音 ──→│ Studio │──→ 统一导出
视频 ──→│ │
└──────────┘
1.2 本节内容地图
4-3 文本与语音标注
├── 文本部分
│ ├── 文本分类
│ ├── NER 命名实体识别
│ ├── 意图识别 + 槽位
│ └── 关系抽取
└── 语音部分
├── 语音转写 ASR
├── 说话人分离
└── 音频分类
2. 文本标注基础概念
2.1 文本数据的特殊性
文本是最难标注的数据,因为:
- 没有"形状",靠"语义"
- 同样含义表达方式千变万化
- 上下文影响判断
- 中文分词、歧义多
"苹果" 这个词可以指:
├── 水果(吃的苹果)
├── 公司(苹果公司)
└── 手机(iPhone)
只有结合上下文才能判断。
2.2 文本标注的四大任务
| 任务 | 输入 | 输出 | 应用 |
|---|---|---|---|
| 文本分类 | 一段文本 | 一个或多个类别 | 情感、新闻分类 |
| NER | 一段文本 | 实体边界+类型 | 信息抽取、知识图谱 |
| 意图识别 | 用户query | 意图+槽位 | 智能客服、对话系统 |
| 关系抽取 | 文本+实体对 | 实体间关系 | 知识图谱构建 |
3. 文本分类标注
3.1 任务说明
场景:对 10 条商品评论做情感分类(正面/负面/中性)
3.2 创建项目
- 启动 Label Studio
+ Create Project,命名为review_sentiment- 进入项目 →
Settings→Labeling Interface→Code
3.3 文本分类配置 XML
<View>
<Text name="text" value="$text"/>
<Choices name="sentiment" toName="text" choice="single-radio" showInline="true">
<Choice value="positive"/>
<Choice value="negative"/>
<Choice value="neutral"/>
</Choices>
</View>
关键参数:
<Text> ← 显示待标注文本
<Choices> ← 单选/多选
choice="single-radio" ← 单选(必选一个)
showInline="true" ← 横排显示
3.4 准备数据
reviews.csv:
text
这家餐厅的菜品非常美味,下次还会再来
等位等了两个小时,体验非常差
今天天气不错,适合出门散步
物流速度很快,第二天就到了
服务员态度恶劣,很不耐烦
这个电影剧情一般,但特效不错
产品质量一般,用了几天就坏了
环境优雅,装修很有格调
价格有点贵,性价比不高
操作简单,上手很快
导入方式:项目页 → Settings → Data Import → 上传 CSV
3.5 标注操作
- 进入
Label All Tasks - 看到一段文本 + 三个选项
- 选择最合适的情感
Submit进入下一条
┌────────────────────────────────────────┐
│ 这家餐厅的菜品非常美味,下次还会再来 │
│ │
│ ( ) positive ( ) negative ( ) neutral│
│ │
│ [ Submit ] │
└────────────────────────────────────────┘
3.6 多标签分类(进阶)
如果一条文本可以同时属于多个类别:
<Choices name="topics" toName="text" choice="multiple">
<Choice value="科技"/>
<Choice value="财经"/>
<Choice value="体育"/>
<Choice value="娱乐"/>
<Choice value="教育"/>
</Choices>
choice="multiple" 表示可多选。
3.7 文本分类标注规范
┌──────────────────────────────────────────────┐
│ 情感分析标注规范 v1.0 │
├──────────────────────────────────────────────┤
│ │
│ 【正面 positive】 │
│ 表达满意、喜欢、赞美、推荐 │
│ 关键词: 好、棒、赞、满意、推荐、完美 │
│ 示例: "东西很好用,下次还来" │
│ │
│ 【负面 negative】 │
│ 表达不满、失望、抱怨、批评 │
│ 关键词: 差、烂、垃圾、失望、后悔、投诉 │
│ 示例: "等了两小时没上菜,差评" │
│ │
│ 【中性 neutral】 │
│ 客观陈述事实,无明显情感倾向 │
│ 示例: "今天吃了火锅" │
│ │
│ ⚠️ 边界情况: │
│ - "还行" / "一般" 归为中性 │
│ - "好贵" 可能是负面(嫌贵) │
│ - 反讽要识别: "真是太好了(等了2小时)" │
│ 实际是负面 │
│ - 不确定时标 neutral │
│ │
└──────────────────────────────────────────────┘
4. NER 命名实体识别标注
4.1 什么是 NER
NER(Named Entity Recognition):在文本中找出实体(人名、地名、机构名等),并标注它们在文本中的起止位置和类型。
输入: 张伟毕业于清华大学
标注: 张伟 [人名] 清华大学 [机构]
4.2 常见实体类型
| 类型 | 缩写 | 说明 | 示例 |
|---|---|---|---|
| 人名 | PER | 真实人物 | 张三、马云、周杰伦 |
| 地名 | LOC | 国家、城市、地区 | 北京、东京、华北 |
| 机构名 | ORG | 公司、学校、政府 | 华为、清华、公安部 |
| 时间 | TIME | 时间点、时期 | 1990年、昨天、三天前 |
| 数字 | NUM | 数字表达式 | 100、3.14、百分之十 |
| 货币 | MONEY | 金额 | 100元、500美元 |
4.3 BIO 标注法
NER 训练数据的标准格式是 BIO:
B-XXX = 实体开始(Begin)
I-XXX = 实体延续(Inside)
O = 非实体(Outside)
示例:
句子: 马化腾 创办 了 腾讯 公司
BIO: B-PER I-PER O B-ORG I-ORG
E-PER E-ORG (BIOES 体系)
按 BIEOS(更精细):
马: B-PER
化: I-PER
腾: E-PER
创: O
办: O
了: O
腾: B-ORG
讯: I-ORG
公: I-ORG
司: E-ORG
> 注意:上面是 BIEOS 体系(多了 E=End 单字实体、S=Single 单词实体),比 BIO 更精细。教材示例这里就以马化腾(3字)为例说明 B/I/E 三个符号。
4.4 Label Studio NER 配置
<View>
<Labels name="label" toName="text">
<Label value="人名" background="#FF0000"/>
<Label value="地名" background="#00FF00"/>
<Label value="机构" background="#0000FF"/>
<Label value="时间" background="#FFFF00"/>
</Labels>
<Text name="text" value="$text"/>
</View>
<Labels> + <Label> 是 NER 标注的核心:先在右侧定义标签及其颜色,标注时用鼠标框选文字就能打上对应标签。
4.5 标注操作
- 进入标注界面
- 看到一段文本
- 用鼠标拖选要标的实体
- 弹出标签列表,选对应类别
- 选中的文字会变彩色背景
原文本:
张伟毕业于清华大学,现在在北京工作。
标注后:
[张伟]毕业于[清华大学],现在在[北京]工作。
人名 机构 地名
4.6 NER 数据准备
ner_data.json:
[
{"text": "张伟毕业于清华大学"},
{"text": "马云创办了阿里巴巴"},
{"text": "北京是中华人民共和国的首都"},
{"text": "周杰伦在上海开了演唱会"},
{"text": "华为公司总部在深圳"}
]
导入即可,每条 text 是一行任务。
4.7 导出 CoNLL 格式
项目页 → Export → 选 CoNLL:
下载得到 project-1-conll.txt:
张 B-PER
伟 E-PER
毕 O
业 O
于 O
清 B-ORG
华 I-ORG
大 I-ORG
学 E-ORG
<空白行> ← 一句话结束
训练 NER 模型时,常用脚本把 CoNLL 格式转成 CRF / BERT 需要的格式。
4.8 NER 标注规范
┌──────────────────────────────────────────────┐
│ NER 标注规范 v1.0 │
├──────────────────────────────────────────────┤
│ │
│ 【人名 PER】 │
│ - 完整姓名: 张三、李四 │
│ - 姓名简称: 需上下文确认("小明") │
│ - 历史人物: 鲁迅、毛泽东 │
│ │
│ 【地名 LOC】 │
│ - 国家: 中国、美国 │
│ - 城市: 北京、上海 │
│ - 区域: 华北、西部 │
│ ⚠️ "清华" 是机构不是地名 │
│ │
│ 【机构 ORG】 │
│ - 公司: 华为、阿里 │
│ - 学校: 清华、北大 │
│ - 政府: 公安部 │
│ │
│ 【歧义处理】 │
│ "苹果" → 看上下文: 水果/公司/手机 │
│ "长江" → 看上下文: 河流/公司 │
│ │
│ 【边界规则】 │
│ - 实体边界要准确,不多不少 │
│ - 含人称前缀: "马云先生" 标 "马云" │
│ - 不拆嵌套: "北京大学" 整体标 ORG │
│ │
└──────────────────────────────────────────────┘
5. 意图识别 + 槽位标注
5.1 任务说明
场景:智能客服。识别用户 query 的意图,并提取槽位(关键参数)。
5.2 概念
用户输入: 帮我查一下明天北京的天气
意图(intent): query_weather ← 用户想干什么
槽位(slot): city=北京, time=明天 ← 关键参数
5.3 Label Studio 配置
<View>
<Text name="text" value="$text"/>
<!-- 意图:单选 -->
<Choices name="intent" toName="text" choice="single-radio">
<Choice value="query_weather"/>
<Choice value="play_music"/>
<Choice value="set_alarm"/>
<Choice value="book_ticket"/>
<Choice value="other"/>
</Choices>
<!-- 槽位:文本中框选 -->
<Labels name="slots" toName="text">
<Label value="city" background="#FF6B6B"/>
<Label value="time" background="#4ECDC4"/>
<Label value="song" background="#FFE66D"/>
<Label value="place" background="#95E1D3"/>
</Labels>
</View>
5.4 数据示例
intents.csv:
text
明天北京天气怎么样
放一首周杰伦的晴天
帮我设个早上7点的闹钟
查一下从上海到北京的高铁
打开客厅的灯
5.5 标注操作
- 先选意图(单选)
- 再框选槽位文字(按类型上色)
- 一次任务两个标签都打
文本: 明天北京天气怎么样
意图: query_weather
槽位: [明天] time, [北京] city
5.6 导出格式
{
"data": {"text": "明天北京天气怎么样"},
"annotations": [{
"result": [
{
"from_name": "intent",
"value": {"choices": ["query_weather"]}
},
{
"from_name": "slots",
"value": {
"start": 0, "end": 2, "text": "明天",
"labels": ["time"]
}
},
{
"from_name": "slots",
"value": {
"start": 2, "end": 4, "text": "北京",
"labels": ["city"]
}
}
]
}]
}
6. 关系抽取标注
6.1 任务说明
任务:从文本中识别两个实体之间的关系。
文本: 马化腾创办了腾讯
实体: 马化腾(人), 腾讯(公司)
关系: 创办
6.2 Label Studio 配置
关系抽取在 Label Studio 里使用 <Relations> 控件,需要先做 NER 标注,再连接实体:
<View>
<Labels name="ner" toName="text">
<Label value="人物" background="#FF6B6B"/>
<Label value="公司" background="#4ECDC4"/>
</Labels>
<Text name="text" value="$text"/>
<Relations name="relation" toName="text">
<Relation value="创办"/>
<Relation value="任职"/>
<Relation value="持股"/>
<Relation value="合作"/>
</Relations>
</View>
6.3 标注操作
- 先用 NER 方式标出两个实体
- 在实体上点击,会弹出关系选项
- 选择对应的关系(也可以从一个实体拖到另一个实体)
文本: 马化腾创办了腾讯
标注步骤:
1. 框选 "马化腾" → 标 "人物"
2. 框选 "腾讯" → 标 "公司"
3. 点击 "马化腾" → 弹出关系 → 选 "创办" → 拖到 "腾讯"
6.4 关系抽取标注规范
┌──────────────────────────────────────────────┐
│ 关系抽取标注规范 v1.0 │
├──────────────────────────────────────────────┤
│ │
│ 关系类型: │
│ │
│ 【创办】 │
│ X 创办了 Y / Y 由 X 创办 │
│ 例: 马化腾创办了腾讯 │
│ │
│ 【任职】 │
│ X 任职于 Y / X 是 Y 的 CEO │
│ 例: 李彦宏是百度的 CEO │
│ │
│ 【持股】 │
│ X 持有 Y 的股份 │
│ 例: 马云持有阿里巴巴的股份 │
│ │
│ 【合作】 │
│ X 与 Y 合作 │
│ 例: 腾讯与京东合作 │
│ │
│ ⚠️ 边界情况: │
│ - 关系不明时标"无关系" │
│ - 一对多: "马云创办了阿里和蚂蚁" │
│ → 两条关系: 马云-阿里-创办, 马云-蚂蚁-创办│
│ │
└──────────────────────────────────────────────┘
7. 语音标注基础
7.1 语音数据的特点
文本:已处理好,直接可用
图像:矩阵,有空间结构
语音:一维波形 + 时序:
┌────────────────────────────────────┐
│ ▂▃▅▇█▇▅▃▂▃▅▇█▇▅▃▂▃▅▇▇▅▃▂▃▅▇█... │ ← 采样点
└────────────────────────────────────┘
每秒 16000 个采样点(16kHz)
- 含时序信息
- 易受噪声影响
- 说话人差异大
7.2 语音标注任务
| 任务 | 标注内容 | 应用 |
|---|---|---|
| 语音转写 ASR | 把语音转成文字 | 字幕、会议记录 |
| 说话人分离 | 标出每段话是谁 | 多人会议、客服 |
| 音频分类 | 给整段音频打类别 | 音乐/语音/噪音分类 |
| 时间戳标注 | 标记每个字的时间 | 字幕对齐 |
8. 语音转写 ASR
8.1 任务说明
任务:把 3 段音频转写成文字,并标记时间戳。
8.2 Label Studio ASR 配置
<View>
<Audio name="audio" value="$audio"/>
<TextArea name="transcription" toName="audio"
placeholder="请输入听到的文字..."
maxSubmissions="1"
editable="true"/>
</View>
参数说明:
<Audio>:加载音频(带播放控件)<TextArea>:文本输入框,标注员在这里听写toName="audio":把文本框和音频控件关联到同一个任务(用toName而不是toName="text",因为这段任务的主控件是 audio)placeholder:提示文字editable="true":允许编辑maxSubmissions="1":每条任务只提交一次
💡 小提示:在 ASR 项目里
toName="audio"是常见的写法;如果同时还有一段文字说明要标注,则用toName="text"关联到<Text>控件。两者本质都是"把标注结果挂到对应数据上"。
8.3 数据准备
audio_tasks.json:
[
{"audio": "audio/sample_001.wav"},
{"audio": "audio/sample_002.wav"},
{"audio": "audio/sample_003.wav"}
]
注意:Label Studio 只能访问特定路径下的音频,有两种方式:
- 本地路径:
/data/audio/sample_001.wav(需在启动时配置) - HTTP URL:
http://example.com/audio/001.wav
8.4 启动配置(本地音频)
如果是本地音频文件,启动 Label Studio 时需要指定根目录:
label-studio \
--label-config-file my_config.xml \
--root-dir /path/to/data
或者在 Settings → Cloud Storage → Add Source → Local files 里配置。
8.5 标注操作
- 进入标注界面
- 点音频播放按钮听
- 在文本框输入听到的文字
- 标完点 Submit
┌────────────────────────────────────────┐
│ ▶ ━━━━●─────────── 0:00 / 0:08 │
│ │
│ 文本框: │
│ ┌────────────────────────────────┐ │
│ │ 今天天气怎么样 │ │
│ └────────────────────────────────┘ │
│ │
│ [ Submit ] │
└────────────────────────────────────────┘
8.6 时间戳分段标注
如果需要精确时间戳(每个词的时间),用更复杂的配置:
<View>
<Audio name="audio" value="$audio"/>
<Labels name="label" toName="audio">
<Label value="语音" background="#7ED321"/>
<Label value="静音" background="#9B9B9B"/>
</Labels>
<TextArea name="transcription" toName="audio"
placeholder="逐句转写,每行一句"/>
</View>
在音频波形上拖动选中一段时间,配合文字行实现"哪段时间是哪句话"。
8.7 语音转写规范
┌──────────────────────────────────────────────┐
│ 语音转写标注规范 v1.0 │
├──────────────────────────────────────────────┤
│ │
│ 【基本规则】 │
│ - 保持原话原意,不修改内容 │
│ - 标点符号自由(保持项目一致) │
│ - 语气词(嗯、啊、这个)一般保留 │
│ │
│ 【特殊处理】 │
│ - 口吃: "我我我" 保留重复 │
│ - 笑声: 标 [笑声] 或 [laughter] │
│ - 沉默>3秒: 标 [沉默] │
│ - 环境音: 标 [噪音] / [music] │
│ - 听不清: 标 [听不清] │
│ │
│ 【时间戳】 │
│ - 格式: 秒(如 0.0、1.5) │
│ - 开始时间 < 结束时间 │
│ - 段落之间不要有重叠 │
│ │
│ 【示例】 │
│ 0.0-2.5: 今天天气怎么样 │
│ 2.5-5.0: 挺好的,适合出门 │
│ 5.0-5.5: [笑声] │
│ │
└──────────────────────────────────────────────┘
9. 说话人分离
9.1 任务说明
任务:在一段多人对话音频中,标出每段话分别是谁说的。
9.2 Label Studio 配置
<View>
<Audio name="audio" value="$audio"/>
<Labels name="speaker" toName="audio">
<Label value="Speaker A" background="#FF6B6B"/>
<Label value="Speaker B" background="#4ECDC4"/>
<Label value="Speaker C" background="#FFE66D"/>
</Labels>
<TextArea name="text" toName="audio"
placeholder="输入这段话的文字..."/>
</View>
9.3 标注操作
- 听音频
- 在波形上拖选一段对应某说话人的区域
- 选择对应的说话人标签
- 在文本框输入该段话的内容
- 一段一段重复
音频波形 + 标注:
┌────────────────────────────────────────────┐
│ ████████░░░░████████░░██████████░░░░░░░░ │
│ │
│ [SpeA] [SpeB] [SpeA] [SpeB] │
│ │
│ 文字: │
│ 明天要开会吗? │
│ 是的,下午三点。 │
│ 好的,我知道了。 │
│ 收到。 │
└────────────────────────────────────────────┘
9.4 导出格式
{
"data": {"audio": "dialogue_001.wav"},
"annotations": [{
"result": [
{
"from_name": "speaker",
"to_name": "audio",
"type": "labels",
"value": {
"start": 0.0, "end": 2.5,
"labels": ["Speaker A"]
}
},
{
"from_name": "text",
"to_name": "audio",
"type": "textarea",
"value": {"text": ["明天要开会吗?"]}
}
]
}]
}
10. 音频分类
10.1 任务说明
任务:对 10 段音频分类(音乐、语音、噪音)
10.2 Label Studio 配置
<View>
<Audio name="audio" value="$audio"/>
<Choices name="category" toName="audio" choice="single-radio">
<Choice value="speech"/>
<Choice value="music"/>
<Choice value="noise"/>
<Choice value="vehicle"/>
<Choice value="alarm"/>
</Choices>
</View>
10.3 数据准备
audio_cls.csv:
audio
audio/clip_001.wav
audio/clip_002.wav
audio/clip_003.wav
10.4 标注操作
- 播放音频
- 选择对应类别
- 提交
┌────────────────────────────────────────┐
│ ▶ ━━━━●─────────── 0:00 / 0:05 │
│ │
│ 这段音频属于哪一类? │
│ │
│ ( ) speech ( ) music │
│ ( ) noise ( ) vehicle │
│ ( ) alarm │
│ │
│ [ Submit ] │
└────────────────────────────────────────┘
10.5 常见音频类别
| 类别 | 说明 | 示例 |
|---|---|---|
| speech | 人声 | 演讲、对话 |
| music | 音乐 | 流行歌曲、背景音乐 |
| noise | 噪声 | 风声、雨声 |
| vehicle | 交通工具 | 引擎声 |
| alarm | 警报 | 警笛、闹钟 |
| animal | 动物 | 猫叫、狗叫 |
11. 文本与语音标注速查
11.1 Label Studio 控件对照
| 标注任务 | 控件 | 关键属性 |
|---|---|---|
| 文本分类 | <Choices> |
choice="single-radio" |
| NER | <Labels> |
toName="text" |
| 意图+槽位 | <Choices> + <Labels> |
双控件 |
| 关系抽取 | <Relations> |
配合 NER |
| ASR 转写 | <Audio> + <TextArea> |
toName="audio" |
| 说话人分离 | <Audio> + <Labels> + <TextArea> |
拖选时间区域 |
| 音频分类 | <Audio> + <Choices> |
单选 |
11.2 快捷键速查
| 快捷键 | 功能 |
|---|---|
Ctrl + Enter |
提交 |
H |
显示/隐藏已标 |
Ctrl + Z |
撤销 |
Delete |
删除选中 |
Esc |
取消选择 |
| 滚轮 | 滚音频/缩放 |
12. Python SDK 简介
12.1 安装
pip install label-studio-sdk
12.2 批量导入文本任务
from label_studio_sdk import Client
ls = Client(url='http://localhost:8080', api_key='YOUR_API_KEY')
# 读取 CSV / JSONL
import json
tasks = []
with open('reviews.csv', 'r', encoding='utf-8') as f:
next(f) # 跳过表头
for line in f:
text = line.strip()
if text:
tasks.append({"data": {"text": text}})
# 找到项目
project = ls.get_project(title='review_sentiment')
# 批量导入
project.import_tasks(tasks)
print(f"已导入 {len(tasks)} 条任务")
12.3 批量导出 NER 结果
project = ls.get_project(title='ner_demo')
# 导出为 CoNLL 格式
project.export_tasks(export_type='CONLL')
# 解析导出的 JSON
import requests
response = requests.get(
'http://localhost:8080/api/projects/1/export?exportType=JSON',
headers={'Authorization': 'Token YOUR_API_KEY'}
)
data = response.json()
print(f"共 {len(data)} 条标注数据")
13. 实战练习
13.1 任务一:情感分类(必做)
任务:在 Label Studio 创建项目 product_reviews
- 准备 10 条商品评论
- 配置三分类 XML(
positive/negative/neutral) - 全部标完
- 导出 JSON
13.2 任务二:NER 标注(必做)
任务:创建项目 news_ner
- 准备 5 条新闻文本
- 配置 4 个实体(人名/地名/机构/时间)
- 全部标完
- 导出 CoNLL 格式
13.3 任务三:语音转写(选做)
任务:创建项目 asr_demo
- 准备 3 段音频
- 配置 Audio + TextArea
- 全部标完
- 导出 JSON
13.4 自检清单
文本分类:
□ 类别选择是否准确
□ 边界情况(反讽、双重否定)是否正确处理
□ 导出 JSON 是否完整
NER:
□ 实体边界是否准确
□ 实体类型是否正确
□ 是否有漏标
□ CoNLL 格式是否标准
语音转写:
□ 文字内容是否完整
□ 时间戳是否准确
□ 特殊处理(沉默、笑声)是否标了
14. 本节知识小结
┌────────────────────────────────────────────────────────┐
│ 4-3 文本标注与语音标注(Label Studio) │
├────────────────────────────────────────────────────────┤
│ │
│ 📌 文本标注四大任务: │
│ 分类 → <Choices> │
│ NER → <Labels> + BIO 标注法 │
│ 意图+槽位 → <Choices> + <Labels> │
│ 关系抽取 → <Relations> 配合 NER │
│ │
│ 📌 语音标注三大任务: │
│ ASR 转写 → <Audio> + <TextArea> │
│ 说话人分离 → <Audio> + <Labels> + <TextArea> │
│ 音频分类 → <Audio> + <Choices> │
│ │
│ 📌 关键格式: │
│ BIO 标注法: B-X / I-X / O │
│ CoNLL: 一行一字的标签,句子间空行 │
│ │
│ 📌 工具特性: │
│ - Python SDK 批量导入导出 │
│ - 多模态统一管理 │
│ - 可视化 XML 配置 │
│ │
└────────────────────────────────────────────────────────┘
课后任务
- 创建
product_reviews项目,完成 10 条情感分类 - 创建
news_ner项目,完成 5 条 NER 标注(导出 CoNLL) - (选做)创建
asr_demo项目,完成 3 段音频转写
下节预告
下一节我们将学习 4-4 标注质量控制与标注管理(Label Studio 协作管理):
- 标注一致性指标(Kappa 系数)
- Label Studio 组织/成员/角色管理
- 审核员工作流:Approve / Reject
- 冲突解决与活动日志