fix:添加新插件API
This commit is contained in:
@@ -1,16 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
## [0.7.1] -2025-6-2
|
||||
- 修复关键词功能,并且在focus中可用
|
||||
- 更新planner架构,大大加快速度和表现效果,建议使用simple规划器
|
||||
- 为normal加入使用action的能力
|
||||
- 修复emoji配置项无效问题
|
||||
## [0.7.1] -2025-6-3
|
||||
重点优化
|
||||
|
||||
加入了人物侧写!麦麦认得群友
|
||||
更新planner架构,大大加快速度和表现效果!
|
||||
为normal_chat加入动作执行!
|
||||
新增关系处理器
|
||||
修复关键词功能,并且在focus中可用!
|
||||
|
||||
|
||||
- 修复log出错问题
|
||||
- 修复focus吞第一条消息问题
|
||||
- 可关闭聊天规划处理器(建议关闭)
|
||||
- 优化记忆同步速度,修复记忆构建缺少chat_id的问题
|
||||
|
||||
修复了:
|
||||
群名称导致log保存失败
|
||||
focus吞掉首条消息
|
||||
表达方式的多样性
|
||||
可关闭思考处理器(建议默认关闭)
|
||||
focus没有时间信息的问题
|
||||
修复了表情包action
|
||||
优化聊天记录构建方式
|
||||
优化记忆同步速度和记忆构建缺少chat_id的问题
|
||||
优化工作记忆处理器
|
||||
优化人格表达
|
||||
删除无效字段防止数据库报错
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ from src.chat.focus_chat.planners.actions.base_action import BaseAction, registe
|
||||
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||
from src.chat.focus_chat.hfc_utils import create_empty_anchor_message
|
||||
from src.common.logger_manager import get_logger
|
||||
from src.llm_models.utils_model import LLMRequest
|
||||
from src.person_info.person_info import person_info_manager
|
||||
from abc import abstractmethod
|
||||
from src.config.config import global_config
|
||||
import os
|
||||
import inspect
|
||||
import toml # 导入 toml 库
|
||||
@@ -35,7 +37,6 @@ class PluginAction(BaseAction):
|
||||
|
||||
# 存储内部服务和对象引用
|
||||
self._services = {}
|
||||
self._global_config = global_config # 存储全局配置的只读引用
|
||||
self.config: Dict[str, Any] = {} # 用于存储插件自身的配置
|
||||
|
||||
# 从kwargs提取必要的内部服务
|
||||
@@ -100,10 +101,8 @@ class PluginAction(BaseAction):
|
||||
安全地从全局配置中获取一个值。
|
||||
插件应使用此方法读取全局配置,以保证只读和隔离性。
|
||||
"""
|
||||
if self._global_config:
|
||||
return self._global_config.get(key, default)
|
||||
logger.debug(f"{self.log_prefix} 尝试访问全局配置项 '{key}',但全局配置未提供。")
|
||||
return default
|
||||
|
||||
return global_config.get(key, default)
|
||||
|
||||
async def get_user_id_by_person_name(self, person_name: str) -> Tuple[str, str]:
|
||||
"""根据用户名获取用户ID"""
|
||||
@@ -228,6 +227,62 @@ class PluginAction(BaseAction):
|
||||
|
||||
return success
|
||||
|
||||
async def send_message_by_replyer(self, target: Optional[str] = None, extra_info_block: Optional[str] = None) -> bool:
|
||||
"""通过 replyer 发送消息的简化方法
|
||||
|
||||
Args:
|
||||
text: 要发送的消息文本
|
||||
target: 目标消息(可选)
|
||||
|
||||
Returns:
|
||||
bool: 是否发送成功
|
||||
"""
|
||||
replyer = self._services.get("replyer")
|
||||
chat_stream = self._services.get("chat_stream")
|
||||
|
||||
if not replyer or not chat_stream:
|
||||
logger.error(f"{self.log_prefix} 无法发送消息:缺少必要的内部服务")
|
||||
return False
|
||||
|
||||
# 构造简化的动作数据
|
||||
reply_data = {"target": target or "", "extra_info_block": extra_info_block}
|
||||
|
||||
# 获取锚定消息(如果有)
|
||||
observations = self._services.get("observations", [])
|
||||
|
||||
# 查找 ChattingObservation 实例
|
||||
chatting_observation = None
|
||||
for obs in observations:
|
||||
if isinstance(obs, ChattingObservation):
|
||||
chatting_observation = obs
|
||||
break
|
||||
|
||||
if not chatting_observation:
|
||||
logger.warning(f"{self.log_prefix} 未找到 ChattingObservation 实例,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message = chatting_observation.search_message_by_text(reply_data["target"])
|
||||
if not anchor_message:
|
||||
logger.info(f"{self.log_prefix} 未找到锚点消息,创建占位符")
|
||||
anchor_message = await create_empty_anchor_message(
|
||||
chat_stream.platform, chat_stream.group_info, chat_stream
|
||||
)
|
||||
else:
|
||||
anchor_message.update_chat_stream(chat_stream)
|
||||
|
||||
# 调用内部方法发送消息
|
||||
success, _ = await replyer.deal_reply(
|
||||
cycle_timers=self.cycle_timers,
|
||||
action_data=reply_data,
|
||||
anchor_message=anchor_message,
|
||||
reasoning=self.reasoning,
|
||||
thinking_id=self.thinking_id,
|
||||
)
|
||||
|
||||
return success
|
||||
|
||||
def get_chat_type(self) -> str:
|
||||
"""获取当前聊天类型
|
||||
|
||||
@@ -266,6 +321,60 @@ class PluginAction(BaseAction):
|
||||
|
||||
return messages
|
||||
|
||||
def get_available_models(self) -> Dict[str, Any]:
|
||||
"""获取所有可用的模型配置
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 模型配置字典,key为模型名称,value为模型配置
|
||||
"""
|
||||
if not hasattr(global_config, "model"):
|
||||
logger.error(f"{self.log_prefix} 无法获取模型列表:全局配置中未找到 model 配置")
|
||||
return {}
|
||||
|
||||
models = global_config.model
|
||||
|
||||
return models
|
||||
|
||||
async def generate_with_model(
|
||||
self,
|
||||
prompt: str,
|
||||
model_config: Dict[str, Any],
|
||||
max_tokens: int = 2000,
|
||||
request_type: str = "plugin.generate",
|
||||
**kwargs
|
||||
) -> Tuple[bool, str]:
|
||||
"""使用指定模型生成内容
|
||||
|
||||
Args:
|
||||
prompt: 提示词
|
||||
model_config: 模型配置(从 get_available_models 获取的模型配置)
|
||||
temperature: 温度参数,控制随机性 (0-1)
|
||||
max_tokens: 最大生成token数
|
||||
request_type: 请求类型标识
|
||||
**kwargs: 其他模型特定参数
|
||||
|
||||
Returns:
|
||||
Tuple[bool, str]: (是否成功, 生成的内容或错误信息)
|
||||
"""
|
||||
try:
|
||||
|
||||
|
||||
logger.info(f"prompt: {prompt}")
|
||||
|
||||
llm_request = LLMRequest(
|
||||
model=model_config,
|
||||
max_tokens=max_tokens,
|
||||
request_type=request_type,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
response,(resoning , model_name) = await llm_request.generate_response_async(prompt)
|
||||
return True, response, resoning, model_name
|
||||
except Exception as e:
|
||||
error_msg = f"生成内容时出错: {str(e)}"
|
||||
logger.error(f"{self.log_prefix} {error_msg}")
|
||||
return False, error_msg
|
||||
|
||||
@abstractmethod
|
||||
async def process(self) -> Tuple[bool, str]:
|
||||
"""插件处理逻辑,子类必须实现此方法
|
||||
|
||||
@@ -190,11 +190,10 @@ class ActionPlanner(BasePlanner):
|
||||
prompt = f"{prompt}"
|
||||
llm_content, (reasoning_content, _) = await self.planner_llm.generate_response_async(prompt=prompt)
|
||||
|
||||
logger.debug(
|
||||
f"{self.log_prefix}规划器Prompt:\n{prompt}\n\n决策动作:{action},\n动作信息: '{action_data}'\n理由: {reasoning}"
|
||||
logger.info(
|
||||
f"{self.log_prefix}规划器Prompt:\n{prompt}\n\nLLM 原始响应: {llm_content}'"
|
||||
)
|
||||
|
||||
logger.debug(f"{self.log_prefix}LLM 原始响应: {llm_content}")
|
||||
logger.debug(f"{self.log_prefix}LLM 原始理由响应: {reasoning_content}")
|
||||
except Exception as req_e:
|
||||
logger.error(f"{self.log_prefix}LLM 请求执行失败: {req_e}")
|
||||
|
||||
@@ -24,7 +24,7 @@ import random
|
||||
from datetime import datetime
|
||||
import re
|
||||
|
||||
logger = get_logger("expressor")
|
||||
logger = get_logger("replyer")
|
||||
|
||||
|
||||
def init_prompt():
|
||||
@@ -295,7 +295,7 @@ class DefaultReplyer:
|
||||
# logger.info(f"{self.log_prefix}[Replier-{thinking_id}]\nPrompt:\n{prompt}\n")
|
||||
content, (reasoning_content, model_name) = await self.express_model.generate_response_async(prompt)
|
||||
|
||||
logger.debug(f"prompt: {prompt}")
|
||||
logger.info(f"prompt: {prompt}")
|
||||
logger.info(f"最终回复: {content}")
|
||||
|
||||
info_catcher.catch_after_llm_generated(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[inner]
|
||||
version = "2.12.0"
|
||||
version = "2.12.1"
|
||||
|
||||
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
|
||||
#如果你想要修改配置文件,请在修改后将version的值进行变更
|
||||
|
||||
Reference in New Issue
Block a user