---
title: Phrases 系统设计
weight: 7
description: 为什么 HotPlex 用加权随机话术池而非硬编码文本，以及 cascade-append 合并策略的设计决策
---

# Phrases 系统设计

> 为什么 Bot 的 UI 话术需要一套独立的配置系统，而不是写在 Agent 人格配置（SOUL.md）里。

## 核心问题

HotPlex 的 Bot 在飞书和 Slack 上有多种 UI 触点：占位卡片、欢迎卡片、状态文本、完成提示。这些话术最初硬编码在 Go 源码中，带来三个问题：

1. **不可定制**：Bot 运维者无法为不同 Bot 设置不同风格的话术
2. **多 Bot 冲突**：同一 gateway 运行的多个 Bot（如公司技术助手和 HR 助手）必须显示相同文本
3. **改代码成本高**：修改一句问候语需要重新编译、部署、重启

Agent 配置系统（SOUL.md / AGENTS.md）控制的是 **Agent 的推理行为**，而 Phrases 控制的是 **平台 UI 展示**。两者关注点不同——一个 Bot 可以有相同的技术能力，但呈现完全不同的交互风格。

## 设计决策

### Cascade-Append 而非替换

三级配置（全局 → 平台 → Bot）的条目**累加**到同一个池中，而非后者替换前者。

**为什么**：如果用替换策略，Bot 级配置必须完整复制所有条目才能避免丢失。累加策略允许只添加差异——在全局定义 8 条默认问候语后，Bot 级只需新增 1 条专属问候，9 条共同参与随机选择。

**权重作为软优先级**：Bot 级条目权重 4，全局权重 2，平台权重 1。这确保 Bot 专属话术有更高选中概率（~67%），但不完全排除全局话术——保留多样性。

### 加权随机而非固定选择

每次请求从池中加权随机选取一条。

**为什么**：固定选择（如轮询、随机序）会让对话显得机械。加权随机在大量对话中自然产生分布，同时 Bot 运维者可以通过添加更多高权重条目来微调概率分布。

### 重启生效而非热更新

Phrases 在 gateway 启动时一次性加载，运行中修改文件不自动生效。

**为什么**：
- Phrases 是不可变值对象（`Phrases` struct 无 mutex），所有读取路径零锁
- 热更新需要引入同步机制，增加所有读取路径的复杂度
- 话术变更频率极低（可能几个月改一次），不值得为此牺牲读取性能

如果需要热更新，可以通过 `hotplex gateway restart` 原子重启（<2s 中断）。

### Markdown 格式而非 YAML/JSON

PHRASES.md 使用 `## 标题` + `- 列表` 格式。

**为什么**：
- Bot 自身可以直接编辑（LLM 天然理解 Markdown）
- 人类运维者用任何文本编辑器都能直观阅读和修改
- 避免引号转义问题（YAML/JSON 中含 emoji 和中文引号容易出错）

## 与 Agent Config 的关系

| 维度 | Agent Config (B/C 通道) | Phrases |
|------|------------------------|---------|
| 控制 | Agent 的推理行为 | 平台 UI 展示文本 |
| 位置 | `~/.hotplex/agent-configs/` | `~/.hotplex/phrases/` |
| 加载时机 | Session 初始化或 `/reset` | Gateway 启动 |
| 更新方式 | `/reset` 即时生效 | 重启 gateway |
| 消费者 | LLM (Claude Code / OCS) | 消息适配器 (飞书 / Slack) |

两者独立运作，不互相依赖。同一个 Bot 可以通过 Agent Config 定义"用 Go 写代码"，同时通过 Phrases 定义"用活泼的语气打招呼"。
