删了点东西

This commit is contained in:
zihanjian
2025-09-25 11:32:32 +08:00
parent 33731cb83b
commit 4419f16843
22 changed files with 278 additions and 2399 deletions

View File

@@ -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])

View File

@@ -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):

View File

@@ -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:

View File

@@ -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",
]

View File

@@ -10,14 +10,6 @@ HELP_LINES = [
"- 新闻",
"- ask [问题]",
"",
"【决斗 & 偷袭】",
"- 决斗@XX",
"- 偷袭@XX",
"- 决斗排行/排行榜",
"- 我的战绩/决斗战绩",
"- 我的装备/查看装备",
"- 改名 [旧名] [新名]",
"",
"【提醒】",
"- 提醒xxxxx一次性、每日、每周",
"- 查看提醒/我的提醒/提醒列表",