Skip to content

hooks - 钩子事件驱动系统

字数
2385 字
阅读时间
11 分钟

概述

hooks 是 NekoBot 3.0 的核心模块之一,提供对话生命周期的事件驱动自动化能力。通过在 AI Pipeline 的 27 个关键检查点插入事件,用户可以定义 Hook(钩子)在特定条件下自动执行动作——注入提示词、修改状态、写入记忆、触发工作流等。

核心设计原则:

  • 事件驱动:Pipeline 在关键节点发出 RuntimeEvent,Hook 通过模式匹配订阅事件
  • 条件过滤:支持身份、频道、情绪、关系阈值、时间段等多维条件(AND 逻辑)
  • 安全限制:每轮最多触发 20 个 Hook,事件链最大深度 5 层,防止失控
  • 可扩展:内置 8 种动作类型,支持通过 register() 注册自定义动作

文档导航

文档说明
事件参考27 种事件类型详解、通配符匹配、事件别名映射
条件参考身份匹配、心情条件、关系阈值、时间范围等条件详解
动作参考8 种内置动作类型参数详解、扩展自定义动作
Web API 参考RESTful API 端点、请求/响应格式
Web 管理界面可视化管理界面使用指南
使用示例常见场景的 Hook 配置示例

架构总览

AIPipeline

  ├── conversation.before_receive
  ├── pipeline.before_attachments / after
  ├── pipeline.before_knowledge / after

  ├── CharacterRuntime.before_turn
  │   ├── character.before_turn.started
  │   ├── character.after_profile_load
  │   ├── character.after_memory_retrieve
  │   ├── character.after_world_book_match
  │   ├── character.after_reaction_plan
  │   └── character.before_turn.finished

  ├── pipeline.before_prompt_render / after
  ├── pipeline.before_model_call / after / stream_chunk
  ├── pipeline.before_reply_send / after

  ├── CharacterRuntime.after_turn
  │   ├── character.after_turn.started
  │   ├── character.after_turn.after_state_update
  │   └── character.after_turn.finished

  ├── memory.after_extract
  ├── state.changed / relationship.changed
  └── tool.before_call / after_call

         │  每个检查点发出 RuntimeEvent

┌─────────────────────────────────────────────┐
│              HookManager                     │
│  emit_event(event)                           │
│    ├── match: 事件模式 + 作用域过滤          │
│    ├── evaluate: ConditionEvaluator          │
│    ├── execute: ActionExecutor               │
│    └── log: HookExecutionLog                 │
└─────────────────────────────────────────────┘

核心类

RuntimeEvent

事件数据对象,表示 Pipeline 中的一个检查点事件。

python
from nbot.hooks import RuntimeEvent

event = RuntimeEvent(
    type="character.before_turn.finished",
    source="character_runtime",
    conversation_id="conv_abc123",
    character_id="char_xyz",
    user_id="user_001",
    payload={"mood": "happy", "energy": 85},
)
字段类型说明
typestr事件类型,支持通配符匹配
sourcestr事件来源标识
conversation_idstr会话 ID
character_idstr角色 ID(可选)
user_idstr用户 ID(可选)
group_idstr群聊 ID(可选)
payloaddict事件负载数据
metadatadict附加元数据

详细字段说明见 事件参考

ConversationHook

钩子定义,监听特定事件并执行一组动作。

python
from nbot.hooks import ConversationHook

hook = ConversationHook(
    name="开心时注入撒娇提示词",
    event="character.before_turn.finished",
    scope="character",
    character_id="char_xyz",
    conditions={"mood_is": "happy", "affection_gte": 70},
    actions=[
        {"type": "prompt_inject", "key": "mood_hint", "content": "角色心情很好,倾向于撒娇", "priority": 50},
        {"type": "state_delta", "field": "energy", "delta": 5},
    ],
    enabled=True,
    priority=10,
)
字段类型默认值说明
namestr-钩子名称
eventstr-监听的事件类型,支持通配符(如 character.*
scopestr"global"作用域:global / character / conversation / user
conditionsdict{}触发条件(AND 逻辑)
actionslist[dict]-要执行的动作列表
enabledboolTrue是否启用
priorityint100优先级(数值越小越先执行)
timeout_msint3000单次执行超时(毫秒)
max_retriesint0失败重试次数(失败、超时、部分失败均会重试)
trigger_modestr"always"触发模式:always / once_per_conversation
permissionsdict{}权限限制(见下表)

trigger_mode 字段说明:

说明
always每次条件满足都会触发
once_per_conversation每个会话最多触发一次,状态持久化到磁盘,重启后仍有效

permissions 字段说明:

类型说明示例
channelslist[str]白名单:只允许这些频道触发["web", "qq"]
deny_channelslist[str]黑名单:禁止这些频道触发["telegram"]

详细字段说明见 Web 管理界面 - ConversationHook 模型

HookExecutionLog

执行日志,记录每次 Hook 触发的结果。

字段类型说明
hook_idstr触发的 Hook ID
event_idstr触发事件 ID
statusstrsuccess / partial / failed / skipped / timeout / denied
actions_executedint已执行的动作数
errorstr错误信息(可选)
duration_msint执行耗时(毫秒)
conversation_idstr会话 ID
event_typestr事件类型

HookManager

中央协调器,负责 Hook 的 CRUD、事件匹配、条件评估和动作执行。通过 get_hook_manager() 获取全局单例。

python
from nbot.hooks.manager import get_hook_manager

manager = get_hook_manager(data_dir="data")

# 添加 Hook
manager.add_hook(hook)

# 发出事件(通常由 Pipeline 自动调用)
logs = await manager.emit_event(event, context={})

# 查询执行日志
logs = manager.get_execution_logs(hook_id="hk_...", limit=20)

# 统计信息
stats = manager.get_stats()

安全常量:

常量说明
_MAX_HOOKS_PER_TURN20每轮最多触发的 Hook 数
_MAX_EVENT_CHAIN_DEPTH5事件链最大嵌套深度

条件系统

ConditionEvaluator 评估 Hook 的触发条件,所有条件之间为 AND 逻辑(全部满足才触发)。

支持的条件类型

条件键类型说明
character_idstr匹配角色 ID
user_idstr匹配用户 ID
channelstr匹配频道(qq / web / telegram
event_sourcestr匹配事件来源
mood_isstr角色心情等于指定值
mood_is_notstr角色心情不等于指定值
affection_gte / affection_ltefloat好感度阈值
trust_gte / trust_ltefloat信任度阈值
familiarity_gte / familiarity_ltefloat熟悉度阈值
dependency_gte / dependency_ltefloat依赖度阈值
security_gte / security_ltefloat安全感阈值
jealousy_gte / jealousy_ltefloat嫉妒度阈值
energy_gte / energy_ltefloat精力阈值
time_range[str, str]时间段限制,格式 ["HH:MM", "HH:MM"],支持跨午夜

详细说明见 条件参考

条件示例

json
{
  "mood_is": "happy",
  "affection_gte": 60,
  "channel": "qq",
  "time_range": ["08:00", "22:00"]
}

动作系统

ActionExecutor 执行 Hook 定义的动作。内置 8 种动作类型,可通过 register() 扩展。

内置动作类型

动作类型说明关键参数
prompt_inject注入提示词到 PromptStackkey, content, priority, scope
state_delta修改角色状态字段field, delta(mood_intensity 限 0-1,energy 限 0-100)
relationship_delta修改关系字段field, delta(限 0-100)
memory_write写入角色记忆content, memory_type
log写入日志message, level
message追加消息到上下文content
workflow触发工作流执行workflow_id
world_book_add添加世界书条目book_id, content, keywords

参数兼容state_deltarelationship_delta 同时支持 payload 格式(如 {"payload": {"energy": -5}})。 memory_write 同时支持 mem_type 字段名。workflow 同时支持 workflow 字段名。

详细参数说明见 动作参考

动作示例

json
[
  {"type": "prompt_inject", "key": "mood_hint", "content": "角色很开心", "priority": 50},
  {"type": "state_delta", "field": "energy", "delta": -10},
  {"type": "relationship_delta", "field": "affection", "delta": 5},
  {"type": "memory_write", "content": "用户说了一句很暖心的话", "memory_type": "relationship"},
  {"type": "log", "message": "好感度变化触发", "level": "info"}
]

扩展自定义动作

python
from nbot.hooks.actions import ActionExecutor

async def my_custom_action(params, context):
    # 自定义逻辑
    return {"success": True, "detail": "done"}

ActionExecutor.register("my_action", my_custom_action)

事件总线

ConversationEventBus 是会话级事件总线,独立于 Gateway 的 EventBus,用于模块间的事件通信。

python
from nbot.hooks.event_bus import ConversationEventBus, HookEventType

bus = ConversationEventBus()

# 订阅事件(支持通配符)
bus.subscribe("character.*", callback=my_handler, name="character_watcher")

# 发出事件
delivered = bus.emit(event)

# 查询历史
history = bus.get_history(event_type="character.before_turn.finished", limit=50)

事件类型一览

别名兼容:文档中的 pipeline.before_model_call 等名称可直接用于 Hook 的 event 字段, 系统会自动映射到代码实际 emit 的事件名(如 model.before_call)。两种写法均可生效。

分类代码事件名文档别名(也可用)
会话入口conversation.before_receive
附件处理pipeline.before_attachments, pipeline.after_attachments
知识检索pipeline.before_knowledge, pipeline.after_knowledge
角色 before_turncharacter.before_turn.started, character.after_profile_load, character.after_memory_retrieve, character.after_world_book_match, character.after_reaction_plan, character.before_turn.finishedcharacter.before_turn.after_memory_retrieve
模型调用model.before_call, model.after_call, model.on_stream_chunk(仅首块)pipeline.before_model_call, pipeline.after_model_call, pipeline.stream_chunk
回复发送reply.before_send, reply.after_sendpipeline.before_reply_send, pipeline.after_reply_send
提示词渲染prompt.before_render, prompt.after_renderpipeline.before_prompt_render, pipeline.after_prompt_render
角色 after_turncharacter.after_turn.started, character.after_state_update, character.after_turn.finishedcharacter.after_turn.after_state_update
记忆抽取memory.after_extract
状态变化state.changed, relationship.changed
工具调用tool.before_call, tool.after_call

详细的事件说明、payload 结构和发射位置见 事件参考

Web API

Hook 系统通过 Web 后台提供完整的管理接口:

方法路由说明
GET/api/hooks列出所有 Hook(支持 scopeeventenabled 过滤)
POST/api/hooks创建 Hook(需 name + event
GET/api/hooks/<hook_id>获取单个 Hook
PUT/api/hooks/<hook_id>更新 Hook
DELETE/api/hooks/<hook_id>删除 Hook
POST/api/hooks/<hook_id>/toggle启用/禁用 Hook
POST/api/hooks/test发送模拟事件测试 Hook 触发
GET/api/hooks/logs查询执行日志
GET/api/hooks/events查询事件总线历史
GET/api/hooks/stats查询统计信息

详细的请求/响应格式见 Web API 参考

前端通知

Hook 成功触发时,Web 管理界面会弹出实时 Toast 通知,通过 Socket.IO 的 hook_notification 事件推送。通知内容包含 Hook 名称、事件类型和 display_message(从第一个 logmessage 动作中提取)。

目录结构

nbot/hooks/
├── __init__.py        # 模块入口,导出 ConversationHook / HookExecutionLog / RuntimeEvent
├── models.py          # 数据模型定义
├── manager.py         # HookManager 中央协调器
├── event_bus.py       # ConversationEventBus 会话级事件总线
├── conditions.py      # ConditionEvaluator 条件评估器
└── actions.py         # ActionExecutor 动作执行器

数据存储

data/web/
├── hooks.json                # Hook 定义(持久化)
├── hooks_logs.json           # 执行日志(持久化,最多 500 条,裁剪到 250 条)
└── hooks_trigger_state.json  # once_per_conversation 触发状态(持久化)

使用示例

自动情绪联动

json
{
  "name": "伤心时注入安慰提示",
  "event": "character.before_turn.finished",
  "conditions": {"mood_is": "sad"},
  "actions": [
    {"type": "prompt_inject", "key": "comfort", "content": "角色正在伤心,回复应温柔安慰", "priority": 30},
    {"type": "state_delta", "field": "energy", "delta": -5}
  ]
}

更多示例见 使用示例

页面历史