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:
125
src/plugins/built_in/chatter/README.md
Normal file
125
src/plugins/built_in/chatter/README.md
Normal 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. 确保在插件卸载时正确清理资源
|
||||
8
src/plugins/built_in/chatter/__init__.py
Normal file
8
src/plugins/built_in/chatter/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""
|
||||
亲和力聊天处理器插件
|
||||
"""
|
||||
|
||||
from .plugin import AffinityChatterPlugin
|
||||
from .affinity_chatter import AffinityChatter
|
||||
|
||||
__all__ = ["AffinityChatterPlugin", "AffinityChatter"]
|
||||
23
src/plugins/built_in/chatter/_manifest.json
Normal file
23
src/plugins/built_in/chatter/_manifest.json
Normal 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"]
|
||||
}
|
||||
206
src/plugins/built_in/chatter/affinity_chatter.py
Normal file
206
src/plugins/built_in/chatter/affinity_chatter.py
Normal 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)})"
|
||||
)
|
||||
46
src/plugins/built_in/chatter/plugin.py
Normal file
46
src/plugins/built_in/chatter/plugin.py
Normal 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 []
|
||||
Reference in New Issue
Block a user