feat: 在插件系统中添加 Chatter 组件

- 在 component_types.py 中新增了用于 CHATTER 的 ComponentType。
- 实现了 ChatterInfo 类,用于存储 Chatter 组件的相关信息。
- 增强了 ComponentRegistry,以支持 Chatter 组件的注册与管理。
- 创建了 ChatterManager,用于管理 Chatter 实例并处理聊天流。
- 开发了 BaseChatter 抽象类,用于定义 Chatter 的行为规范。
- 实现了 AffinityChatter,作为具备兴趣评分与关系构建功能的具体 Chatter 组件。
- 添加了一个内置的 Chatter 插件,并附带完整文档与使用示例。
- 更新了 PluginManager,在插件概览中加入 Chatter 组件的统计信息。
This commit is contained in:
Windpicker-owo
2025-09-23 00:17:32 +08:00
parent 087ecfb420
commit dce48d38cf
15 changed files with 807 additions and 62 deletions

View File

@@ -0,0 +1,125 @@
# 亲和力聊天处理器插件
## 概述
这是一个内置的chatter插件实现了基于亲和力流的智能聊天处理器具有兴趣度评分和人物关系构建功能。
## 功能特性
- **智能兴趣度评分**: 自动识别和评估用户兴趣话题
- **人物关系系统**: 根据互动历史建立和维持用户关系
- **多聊天类型支持**: 支持私聊和群聊场景
- **插件化架构**: 完全集成到插件系统中
## 组件架构
### BaseChatter (抽象基类)
- 位置: `src/plugin_system/base/base_chatter.py`
- 功能: 定义所有chatter组件的基础接口
- 必须实现的方法: `execute(context: StreamContext) -> dict`
### ChatterManager (管理器)
- 位置: `src/chat/chatter_manager.py`
- 功能: 管理和调度所有chatter组件
- 特性: 自动从插件系统注册和发现chatter组件
### AffinityChatter (具体实现)
- 位置: `src/plugins/built_in/chatter/affinity_chatter.py`
- 功能: 亲和力流聊天处理器的具体实现
- 支持的聊天类型: PRIVATE, GROUP
## 使用方法
### 1. 基本使用
```python
from src.chat.chatter_manager import ChatterManager
from src.chat.planner_actions.action_manager import ActionManager
# 初始化
action_manager = ActionManager()
chatter_manager = ChatterManager(action_manager)
# 处理消息流
result = await chatter_manager.process_stream_context(stream_id, context)
```
### 2. 创建自定义Chatter
```python
from src.plugin_system.base.base_chatter import BaseChatter
from src.plugin_system.base.component_types import ChatType, ComponentType
from src.plugin_system.base.component_types import ChatterInfo
class CustomChatter(BaseChatter):
chat_types = [ChatType.PRIVATE] # 只支持私聊
async def execute(self, context: StreamContext) -> dict:
# 实现你的聊天逻辑
return {"success": True, "message": "处理完成"}
# 在插件中注册
async def on_load(self):
chatter_info = ChatterInfo(
name="custom_chatter",
component_type=ComponentType.CHATTER,
description="自定义聊天处理器",
enabled=True,
plugin_name=self.name,
chat_type_allow=ChatType.PRIVATE
)
ComponentRegistry.register_component(
component_info=chatter_info,
component_class=CustomChatter
)
```
## 配置
### 插件配置文件
- 位置: `src/plugins/built_in/chatter/_manifest.json`
- 包含插件信息和组件配置
### 聊天类型
- `PRIVATE`: 私聊
- `GROUP`: 群聊
- `ALL`: 所有类型
## 核心概念
### 1. 兴趣值系统
- 自动识别同类话题
- 兴趣值会根据聊天频率增减
- 支持新话题的自动学习
### 2. 人物关系系统
- 根据互动质量建立关系分
- 不同关系分对应不同的回复风格
- 支持情感化的交流
### 3. 执行流程
1. 接收StreamContext
2. 使用ActionPlanner进行规划
3. 执行相应的Action
4. 返回处理结果
## 扩展开发
### 添加新的Chatter类型
1. 继承BaseChatter类
2. 实现execute方法
3. 在插件中注册组件
4. 配置支持的聊天类型
### 集成现有功能
- 使用ActionPlanner进行动作规划
- 通过ActionManager执行动作
- 利用现有的记忆和知识系统
## 注意事项
1. 所有chatter组件必须实现`execute`方法
2. 插件注册时需要指定支持的聊天类型
3. 组件名称不能包含点号(.)
4. 确保在插件卸载时正确清理资源

View File

@@ -0,0 +1,8 @@
"""
亲和力聊天处理器插件
"""
from .plugin import AffinityChatterPlugin
from .affinity_chatter import AffinityChatter
__all__ = ["AffinityChatterPlugin", "AffinityChatter"]

View File

@@ -0,0 +1,23 @@
{
"manifest_version": 1,
"name": "affinity_chatter",
"display_name": "Affinity Flow Chatter",
"description": "Built-in chatter plugin for affinity flow with interest scoring and relationship building",
"version": "1.0.0",
"author": "MoFox",
"plugin_class": "AffinityChatterPlugin",
"enabled": true,
"is_built_in": true,
"components": [
{
"name": "affinity_chatter",
"type": "chatter",
"description": "Affinity flow chatter with intelligent interest scoring and relationship building",
"enabled": true,
"chat_type_allow": ["all"]
}
],
"host_application": { "min_version": "0.8.0" },
"keywords": ["chatter", "affinity", "conversation"],
"categories": ["Chat", "AI"]
}

View File

@@ -0,0 +1,206 @@
"""
亲和力聊天处理器
基于现有的AffinityFlowChatter重构为插件化组件
"""
import time
import traceback
from datetime import datetime
from typing import Dict, Any
from src.plugin_system.base.base_chatter import BaseChatter
from src.plugin_system.base.component_types import ChatType, ChatMode
from src.common.data_models.message_manager_data_model import StreamContext
from src.chat.planner_actions.planner import ActionPlanner
from src.chat.planner_actions.action_manager import ActionManager
from src.common.logger import get_logger
logger = get_logger("affinity_chatter")
class AffinityChatter(BaseChatter):
"""亲和力聊天处理器"""
chatter_name: str = "AffinityChatter"
chatter_description: str = "基于亲和力模型的智能聊天处理器,支持多种聊天类型"
chat_types: list[ChatType] = [ChatType.ALL] # 支持所有聊天类型
def __init__(self, stream_id: str, planner: ActionPlanner, action_manager: ActionManager):
"""
初始化亲和力聊天处理器
Args:
stream_id: 聊天流ID
planner: 动作规划器
action_manager: 动作管理器
"""
super().__init__(stream_id, planner, action_manager)
# 处理器统计
self.stats = {
"messages_processed": 0,
"plans_created": 0,
"actions_executed": 0,
"successful_executions": 0,
"failed_executions": 0,
}
self.last_activity_time = time.time()
async def execute(self, context: StreamContext) -> dict:
"""
处理StreamContext对象
Args:
context: StreamContext对象包含聊天流的所有消息信息
Returns:
处理结果字典
"""
try:
unread_messages = context.get_unread_messages()
# 使用增强版规划器处理消息
actions, target_message = await self.planner.plan(mode=ChatMode.FOCUS, context=context)
self.stats["plans_created"] += 1
# 执行动作(如果规划器返回了动作)
execution_result = {"executed_count": len(actions) if actions else 0}
if actions:
logger.debug(f"聊天流 {self.stream_id} 生成了 {len(actions)} 个动作")
# 更新统计
self.stats["messages_processed"] += 1
self.stats["actions_executed"] += execution_result.get("executed_count", 0)
self.stats["successful_executions"] += 1
self.last_activity_time = time.time()
result = {
"success": True,
"stream_id": self.stream_id,
"plan_created": True,
"actions_count": len(actions) if actions else 0,
"has_target_message": target_message is not None,
"unread_messages_processed": len(unread_messages),
**execution_result,
}
logger.info(
f"聊天流 {self.stream_id} StreamContext处理成功: 动作数={result['actions_count']}, 未读消息={result['unread_messages_processed']}"
)
return result
except Exception as e:
logger.error(f"亲和力聊天处理器 {self.stream_id} 处理StreamContext时出错: {e}\n{traceback.format_exc()}")
self.stats["failed_executions"] += 1
self.last_activity_time = time.time()
return {
"success": False,
"stream_id": self.stream_id,
"error_message": str(e),
"executed_count": 0,
}
def get_stats(self) -> Dict[str, Any]:
"""
获取处理器统计信息
Returns:
统计信息字典
"""
return self.stats.copy()
def get_planner_stats(self) -> Dict[str, Any]:
"""
获取规划器统计信息
Returns:
规划器统计信息字典
"""
return self.planner.get_planner_stats()
def get_interest_scoring_stats(self) -> Dict[str, Any]:
"""
获取兴趣度评分统计信息
Returns:
兴趣度评分统计信息字典
"""
return self.planner.get_interest_scoring_stats()
def get_relationship_stats(self) -> Dict[str, Any]:
"""
获取用户关系统计信息
Returns:
用户关系统计信息字典
"""
return self.planner.get_relationship_stats()
def get_user_relationship(self, user_id: str) -> float:
"""
获取用户关系分
Args:
user_id: 用户ID
Returns:
用户关系分 (0.0-1.0)
"""
return self.planner.get_user_relationship(user_id)
def update_interest_keywords(self, new_keywords: dict):
"""
更新兴趣关键词
Args:
new_keywords: 新的兴趣关键词字典
"""
self.planner.update_interest_keywords(new_keywords)
logger.info(f"聊天流 {self.stream_id} 已更新兴趣关键词: {list(new_keywords.keys())}")
def reset_stats(self):
"""重置统计信息"""
self.stats = {
"messages_processed": 0,
"plans_created": 0,
"actions_executed": 0,
"successful_executions": 0,
"failed_executions": 0,
}
def is_active(self, max_inactive_minutes: int = 60) -> bool:
"""
检查处理器是否活跃
Args:
max_inactive_minutes: 最大不活跃分钟数
Returns:
是否活跃
"""
current_time = time.time()
max_inactive_seconds = max_inactive_minutes * 60
return (current_time - self.last_activity_time) < max_inactive_seconds
def get_activity_time(self) -> float:
"""
获取最后活动时间
Returns:
最后活动时间戳
"""
return self.last_activity_time
def __str__(self) -> str:
"""字符串表示"""
return f"AffinityChatter(stream_id={self.stream_id}, messages={self.stats['messages_processed']})"
def __repr__(self) -> str:
"""详细字符串表示"""
return (
f"AffinityChatter(stream_id={self.stream_id}, "
f"messages_processed={self.stats['messages_processed']}, "
f"plans_created={self.stats['plans_created']}, "
f"last_activity={datetime.fromtimestamp(self.last_activity_time)})"
)

View File

@@ -0,0 +1,46 @@
"""
亲和力聊天处理器插件
"""
from typing import List, Tuple, Type
from src.plugin_system.apis.plugin_register_api import register_plugin
from src.plugin_system.base.base_plugin import BasePlugin
from src.plugin_system.base.component_types import ComponentInfo, ChatterInfo, ComponentType, ChatType
from src.common.logger import get_logger
logger = get_logger("affinity_chatter_plugin")
@register_plugin
class AffinityChatterPlugin(BasePlugin):
"""亲和力聊天处理器插件
- 延迟导入 `AffinityChatter` 并通过组件注册器注册为聊天处理器
- 提供 `get_plugin_components` 以兼容插件注册机制
"""
plugin_name: str = "affinity_chatter"
enable_plugin: bool = True
dependencies: list[str] = []
python_dependencies: list[str] = []
config_file_name: str = ""
# 简单的 config_schema 占位(如果将来需要配置可扩展)
config_schema = {}
def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]:
"""返回插件包含的组件列表ChatterInfo, AffinityChatter
这里采用延迟导入 AffinityChatter 来避免循环依赖和启动顺序问题。
如果导入失败则返回空列表以让注册过程继续而不崩溃。
"""
try:
# 延迟导入以避免循环导入
from .affinity_chatter import AffinityChatter
return [(AffinityChatter.get_chatter_info(), AffinityChatter)]
except Exception as e:
logger.error(f"加载 AffinityChatter 时出错: {e}")
return []