mirror of
https://github.com/Zippland/Bubbles.git
synced 2026-03-04 07:47:48 +08:00
删了点东西
This commit is contained in:
@@ -1,64 +1,25 @@
|
||||
"""Function Call handlers built on top of structured services."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from commands.context import MessageContext
|
||||
|
||||
from .models import (
|
||||
WeatherArgs,
|
||||
NewsArgs,
|
||||
ReminderArgs,
|
||||
ReminderListArgs,
|
||||
ReminderDeleteArgs,
|
||||
PerplexityArgs,
|
||||
HelpArgs,
|
||||
SummaryArgs,
|
||||
ClearMessagesArgs,
|
||||
InsultArgs,
|
||||
)
|
||||
from .registry import tool_function
|
||||
from .spec import FunctionResult
|
||||
from .services import (
|
||||
build_help_text,
|
||||
build_insult,
|
||||
clear_group_messages,
|
||||
create_reminder,
|
||||
delete_reminder,
|
||||
get_news_digest,
|
||||
get_weather_report,
|
||||
list_reminders,
|
||||
run_perplexity,
|
||||
summarize_messages,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@tool_function(
|
||||
name="weather_query",
|
||||
description="查询城市天气预报",
|
||||
examples=["北京天气怎么样", "上海天气", "深圳明天会下雨吗"],
|
||||
scope="both",
|
||||
require_at=True,
|
||||
)
|
||||
def handle_weather(ctx: MessageContext, args: WeatherArgs) -> FunctionResult:
|
||||
result = get_weather_report(args.city)
|
||||
at = ctx.msg.sender if ctx.is_group else ""
|
||||
return FunctionResult(handled=True, messages=[result.message], at=at if at else "")
|
||||
|
||||
|
||||
@tool_function(
|
||||
name="news_query",
|
||||
description="获取今日新闻",
|
||||
examples=["看看今天的新闻", "今日要闻", "新闻"],
|
||||
scope="both",
|
||||
require_at=True,
|
||||
)
|
||||
def handle_news(ctx: MessageContext, args: NewsArgs) -> FunctionResult:
|
||||
result = get_news_digest()
|
||||
at = ctx.msg.sender if ctx.is_group else ""
|
||||
return FunctionResult(handled=True, messages=[result.message], at=at if at else "")
|
||||
|
||||
|
||||
@tool_function(
|
||||
name="reminder_set",
|
||||
@@ -68,7 +29,7 @@ def handle_news(ctx: MessageContext, args: NewsArgs) -> FunctionResult:
|
||||
require_at=True,
|
||||
)
|
||||
def handle_reminder_set(ctx: MessageContext, args: ReminderArgs) -> FunctionResult:
|
||||
manager = getattr(ctx.robot, 'reminder_manager', None)
|
||||
manager = getattr(ctx.robot, "reminder_manager", None)
|
||||
at = ctx.msg.sender if ctx.is_group else ""
|
||||
if not manager:
|
||||
return FunctionResult(handled=True, messages=["❌ 内部错误:提醒管理器未初始化。"], at=at)
|
||||
@@ -90,7 +51,7 @@ def handle_reminder_set(ctx: MessageContext, args: ReminderArgs) -> FunctionResu
|
||||
require_at=True,
|
||||
)
|
||||
def handle_reminder_list(ctx: MessageContext, args: ReminderListArgs) -> FunctionResult:
|
||||
manager = getattr(ctx.robot, 'reminder_manager', None)
|
||||
manager = getattr(ctx.robot, "reminder_manager", None)
|
||||
at = ctx.msg.sender if ctx.is_group else ""
|
||||
if not manager:
|
||||
return FunctionResult(handled=True, messages=["❌ 内部错误:提醒管理器未初始化。"], at=at)
|
||||
@@ -107,7 +68,7 @@ def handle_reminder_list(ctx: MessageContext, args: ReminderListArgs) -> Functio
|
||||
require_at=True,
|
||||
)
|
||||
def handle_reminder_delete(ctx: MessageContext, args: ReminderDeleteArgs) -> FunctionResult:
|
||||
manager = getattr(ctx.robot, 'reminder_manager', None)
|
||||
manager = getattr(ctx.robot, "reminder_manager", None)
|
||||
at = ctx.msg.sender if ctx.is_group else ""
|
||||
if not manager:
|
||||
return FunctionResult(handled=True, messages=["❌ 内部错误:提醒管理器未初始化。"], at=at)
|
||||
@@ -132,18 +93,6 @@ def handle_perplexity_search(ctx: MessageContext, args: PerplexityArgs) -> Funct
|
||||
return FunctionResult(handled=True, messages=service_result.messages, at=at if at else "")
|
||||
|
||||
|
||||
@tool_function(
|
||||
name="help",
|
||||
description="显示机器人帮助信息",
|
||||
examples=["help", "帮助", "指令"],
|
||||
scope="both",
|
||||
require_at=False,
|
||||
)
|
||||
def handle_help(ctx: MessageContext, args: HelpArgs) -> FunctionResult:
|
||||
help_text = build_help_text()
|
||||
return FunctionResult(handled=True, messages=[help_text])
|
||||
|
||||
|
||||
@tool_function(
|
||||
name="summary",
|
||||
description="总结群聊最近的消息",
|
||||
@@ -154,27 +103,3 @@ def handle_help(ctx: MessageContext, args: HelpArgs) -> FunctionResult:
|
||||
def handle_summary(ctx: MessageContext, args: SummaryArgs) -> FunctionResult:
|
||||
result = summarize_messages(ctx)
|
||||
return FunctionResult(handled=True, messages=[result.message])
|
||||
|
||||
|
||||
@tool_function(
|
||||
name="clear_messages",
|
||||
description="清除群聊历史消息记录",
|
||||
examples=["clearmessages", "清除历史"],
|
||||
scope="group",
|
||||
require_at=True,
|
||||
)
|
||||
def handle_clear_messages(ctx: MessageContext, args: ClearMessagesArgs) -> FunctionResult:
|
||||
result = clear_group_messages(ctx)
|
||||
return FunctionResult(handled=True, messages=[result.message])
|
||||
|
||||
|
||||
@tool_function(
|
||||
name="insult",
|
||||
description="骂指定用户(仅限群聊)",
|
||||
examples=["骂一下@某人"],
|
||||
scope="group",
|
||||
require_at=True,
|
||||
)
|
||||
def handle_insult(ctx: MessageContext, args: InsultArgs) -> FunctionResult:
|
||||
result = build_insult(ctx, args.target_user)
|
||||
return FunctionResult(handled=True, messages=[result.message])
|
||||
|
||||
@@ -3,7 +3,7 @@ Function Call 参数模型定义
|
||||
"""
|
||||
from typing import Literal, Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class WeatherArgs(BaseModel):
|
||||
@@ -19,10 +19,17 @@ class NewsArgs(BaseModel):
|
||||
class ReminderArgs(BaseModel):
|
||||
"""设置提醒参数"""
|
||||
|
||||
type: Literal["once", "daily", "weekly"]
|
||||
time: str
|
||||
content: str
|
||||
weekday: Optional[int] = None
|
||||
type: Literal["once", "daily", "weekly"] = Field(
|
||||
..., description="提醒类型:once=一次性提醒,daily=每天,weekly=每周"
|
||||
)
|
||||
time: str = Field(
|
||||
..., description="提醒时间。once 使用 'YYYY-MM-DD HH:MM',daily/weekly 使用 'HH:MM'"
|
||||
)
|
||||
content: str = Field(..., description="提醒内容,将直接发送给用户")
|
||||
weekday: Optional[int] = Field(
|
||||
default=None,
|
||||
description="当 type=weekly 时的星期索引,0=周一 … 6=周日",
|
||||
)
|
||||
|
||||
|
||||
class ReminderListArgs(BaseModel):
|
||||
@@ -33,12 +40,13 @@ class ReminderListArgs(BaseModel):
|
||||
class ReminderDeleteArgs(BaseModel):
|
||||
"""删除提醒参数"""
|
||||
|
||||
reminder_id: str
|
||||
reminder_id: str = Field(..., description="提醒列表中的 ID(前端可展示前几位)")
|
||||
|
||||
|
||||
class PerplexityArgs(BaseModel):
|
||||
"""Perplexity搜索参数"""
|
||||
query: str
|
||||
|
||||
query: str = Field(..., description="要搜索的问题或主题")
|
||||
|
||||
|
||||
class HelpArgs(BaseModel):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Function Call 路由器"""
|
||||
|
||||
import logging
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Dict
|
||||
|
||||
from commands.context import MessageContext
|
||||
|
||||
@@ -39,45 +39,6 @@ class FunctionCallRouter:
|
||||
|
||||
return True
|
||||
|
||||
def _try_direct_command_match(self, ctx: MessageContext) -> Optional[str]:
|
||||
"""
|
||||
尝试直接命令匹配,避免不必要的LLM调用
|
||||
|
||||
返回匹配的函数名,如果没有匹配则返回None
|
||||
"""
|
||||
text = ctx.text.strip().lower()
|
||||
|
||||
# 定义一些明确的命令关键字映射
|
||||
direct_commands = {
|
||||
"help": "help",
|
||||
"帮助": "help",
|
||||
"指令": "help",
|
||||
"新闻": "news_query",
|
||||
"summary": "summary",
|
||||
"总结": "summary",
|
||||
"clearmessages": "clear_messages",
|
||||
"清除历史": "clear_messages"
|
||||
}
|
||||
|
||||
# 检查完全匹配
|
||||
if text in direct_commands:
|
||||
return direct_commands[text]
|
||||
|
||||
# 检查以特定前缀开头的命令
|
||||
if text.startswith("ask ") and len(text) > 4:
|
||||
return "perplexity_search"
|
||||
|
||||
if text.startswith("天气") or text.startswith("天气预报"):
|
||||
return "weather_query"
|
||||
|
||||
if text in ["查看提醒", "我的提醒", "提醒列表"]:
|
||||
return "reminder_list"
|
||||
|
||||
if text.startswith("骂一下"):
|
||||
return "insult"
|
||||
|
||||
return None
|
||||
|
||||
def dispatch(self, ctx: MessageContext) -> bool:
|
||||
"""
|
||||
分发消息到函数处理器
|
||||
@@ -100,26 +61,7 @@ class FunctionCallRouter:
|
||||
self.logger.warning("没有注册任何函数")
|
||||
return False
|
||||
|
||||
# 第一步:尝试直接命令匹配
|
||||
direct_function = self._try_direct_command_match(ctx)
|
||||
if direct_function and direct_function in functions:
|
||||
spec = functions[direct_function]
|
||||
|
||||
if not self._check_scope_and_permissions(ctx, spec):
|
||||
return False
|
||||
|
||||
arguments = self._extract_arguments_for_direct_command(ctx, direct_function)
|
||||
if not self.llm.validate_arguments(arguments, spec.parameters_schema):
|
||||
self.logger.warning(f"直接命令 {direct_function} 参数验证失败")
|
||||
return False
|
||||
|
||||
result = self._invoke_function(ctx, spec, arguments)
|
||||
if result.handled:
|
||||
result.dispatch(ctx)
|
||||
return True
|
||||
# 如果没有处理成功,继续尝试LLM流程
|
||||
|
||||
# 第二步:使用LLM执行多轮函数调用
|
||||
# 使用 LLM 执行函数调用流程
|
||||
llm_result = self.llm.run(
|
||||
ctx,
|
||||
functions,
|
||||
@@ -141,38 +83,6 @@ class FunctionCallRouter:
|
||||
self.logger.error(f"FunctionCallRouter dispatch 异常: {e}")
|
||||
return False
|
||||
|
||||
def _extract_arguments_for_direct_command(self, ctx: MessageContext, function_name: str) -> Dict[str, Any]:
|
||||
"""为直接命令提取参数"""
|
||||
text = ctx.text.strip()
|
||||
|
||||
if function_name == "weather_query":
|
||||
# 提取城市名
|
||||
if text.startswith("天气预报 "):
|
||||
city = text[4:].strip()
|
||||
elif text.startswith("天气 "):
|
||||
city = text[3:].strip()
|
||||
else:
|
||||
city = ""
|
||||
return {"city": city}
|
||||
|
||||
elif function_name == "perplexity_search":
|
||||
# 提取搜索查询
|
||||
if text.startswith("ask "):
|
||||
query = text[4:].strip()
|
||||
else:
|
||||
query = text
|
||||
return {"query": query}
|
||||
|
||||
elif function_name == "insult":
|
||||
# 提取要骂的用户
|
||||
import re
|
||||
match = re.search(r"骂一下\s*@([^\s@]+)", text)
|
||||
target_user = match.group(1) if match else ""
|
||||
return {"target_user": target_user}
|
||||
|
||||
# 对于不需要参数的函数,返回空字典
|
||||
return {}
|
||||
|
||||
def _invoke_function(self, ctx: MessageContext, spec: FunctionSpec, arguments: Dict[str, Any]) -> FunctionResult:
|
||||
"""调用函数处理器,返回结构化结果"""
|
||||
try:
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
"""Service helpers for Function Call handlers."""
|
||||
|
||||
from .weather import get_weather_report
|
||||
from .news import get_news_digest
|
||||
from .reminder import create_reminder, list_reminders, delete_reminder
|
||||
from .help import build_help_text
|
||||
from .group_tools import summarize_messages, clear_group_messages
|
||||
from .group_tools import summarize_messages
|
||||
from .perplexity import run_perplexity
|
||||
from .insult import build_insult
|
||||
|
||||
__all__ = [
|
||||
"get_weather_report",
|
||||
"get_news_digest",
|
||||
"create_reminder",
|
||||
"list_reminders",
|
||||
"delete_reminder",
|
||||
"build_help_text",
|
||||
"summarize_messages",
|
||||
"clear_group_messages",
|
||||
"run_perplexity",
|
||||
"build_insult",
|
||||
]
|
||||
|
||||
@@ -10,14 +10,6 @@ HELP_LINES = [
|
||||
"- 新闻",
|
||||
"- ask [问题]",
|
||||
"",
|
||||
"【决斗 & 偷袭】",
|
||||
"- 决斗@XX",
|
||||
"- 偷袭@XX",
|
||||
"- 决斗排行/排行榜",
|
||||
"- 我的战绩/决斗战绩",
|
||||
"- 我的装备/查看装备",
|
||||
"- 改名 [旧名] [新名]",
|
||||
"",
|
||||
"【提醒】",
|
||||
"- 提醒xxxxx:一次性、每日、每周",
|
||||
"- 查看提醒/我的提醒/提醒列表",
|
||||
|
||||
Reference in New Issue
Block a user