feat(tool system): Tool system reengineering

This commit is contained in:
谢俊男
2025-12-25 17:30:20 +08:00
parent 3bcaead413
commit 04be3088a2
25 changed files with 1887 additions and 3325 deletions

View File

@@ -3,7 +3,8 @@ from abc import ABC, abstractmethod
from typing import Dict, Any, List
from app.models.tool_model import ToolType
from app.core.tools.base import BaseTool, ToolResult, ToolParameter
from app.core.tools.base import BaseTool
from app.schemas.tool_schema import ToolResult, ToolParameter
class BuiltinTool(BaseTool, ABC):

View File

@@ -4,7 +4,7 @@ from datetime import datetime, timezone, timedelta
from typing import List
import pytz
from app.core.tools.base import ToolParameter, ToolResult, ParameterType
from app.schemas.tool_schema import ToolParameter, ToolResult, ParameterType
from .base import BuiltinTool
@@ -54,14 +54,14 @@ class DateTimeTool(BuiltinTool):
type=ParameterType.STRING,
description="源时区UTC, Asia/Shanghai",
required=False,
default="UTC"
default="Asia/Shanghai"
),
ToolParameter(
name="to_timezone",
type=ParameterType.STRING,
description="目标时区UTC, Asia/Shanghai",
required=False,
default="UTC"
default="Asia/Shanghai"
),
ToolParameter(
name="calculation",
@@ -106,10 +106,11 @@ class DateTimeTool(BuiltinTool):
error_code="DATETIME_ERROR",
execution_time=execution_time
)
def _get_current_time(self, kwargs) -> dict:
@staticmethod
def _get_current_time(kwargs) -> dict:
"""获取当前时间"""
timezone_str = kwargs.get("to_timezone", "UTC")
timezone_str = kwargs.get("to_timezone", "Asia/Shanghai")
output_format = kwargs.get("output_format", "%Y-%m-%d %H:%M:%S")
if timezone_str == "UTC":
@@ -118,15 +119,20 @@ class DateTimeTool(BuiltinTool):
tz = pytz.timezone(timezone_str)
now = datetime.now(tz)
utc_now = datetime.now(timezone.utc)
return {
"datetime": now.strftime(output_format),
"timestamp": int(now.timestamp()),
"timezone": timezone_str,
"iso_format": now.isoformat()
"iso_format": now.isoformat(),
"timestamp_ms": int(now.timestamp() * 1000),
"utc_datetime": utc_now.strftime(output_format)
}
def _format_datetime(self, kwargs) -> dict:
@staticmethod
def _format_datetime(kwargs) -> dict:
"""格式化时间"""
input_value = kwargs.get("input_value")
input_format = kwargs.get("input_format", "%Y-%m-%d %H:%M:%S")
@@ -144,8 +150,9 @@ class DateTimeTool(BuiltinTool):
"timestamp": int(dt.timestamp()),
"iso_format": dt.isoformat()
}
def _convert_timezone(self, kwargs) -> dict:
@staticmethod
def _convert_timezone(kwargs) -> dict:
"""时区转换"""
input_value = kwargs.get("input_value")
input_format = kwargs.get("input_format", "%Y-%m-%d %H:%M:%S")
@@ -184,8 +191,9 @@ class DateTimeTool(BuiltinTool):
"converted_timezone": to_timezone,
"timestamp": int(converted_dt.timestamp())
}
def _timestamp_to_datetime(self, kwargs) -> dict:
@staticmethod
def _timestamp_to_datetime(kwargs) -> dict:
"""时间戳转日期时间"""
input_value = kwargs.get("input_value")
output_format = kwargs.get("output_format", "%Y-%m-%d %H:%M:%S")
@@ -196,6 +204,8 @@ class DateTimeTool(BuiltinTool):
# 转换时间戳
timestamp = float(input_value)
if timestamp > 1e12:
timestamp = timestamp / 1000
# 设置时区
if timezone_str == "UTC":
@@ -211,8 +221,9 @@ class DateTimeTool(BuiltinTool):
"timezone": timezone_str,
"iso_format": dt.isoformat()
}
def _datetime_to_timestamp(self, kwargs) -> dict:
@staticmethod
def _datetime_to_timestamp(kwargs) -> dict:
"""日期时间转时间戳"""
input_value = kwargs.get("input_value")
input_format = kwargs.get("input_format", "%Y-%m-%d %H:%M:%S")
@@ -240,7 +251,7 @@ class DateTimeTool(BuiltinTool):
"timestamp": int(dt.timestamp()),
"iso_format": dt.isoformat()
}
def _calculate_datetime(self, kwargs) -> dict:
"""时间计算"""
input_value = kwargs.get("input_value")
@@ -278,8 +289,9 @@ class DateTimeTool(BuiltinTool):
"timezone": timezone_str,
"timestamp": int(calculated_dt.timestamp())
}
def _parse_time_delta(self, calculation: str) -> timedelta:
@staticmethod
def _parse_time_delta(calculation: str) -> timedelta:
"""解析时间计算表达式"""
import re

View File

@@ -121,8 +121,9 @@ class JsonTool(BuiltinTool):
error_code="JSON_ERROR",
execution_time=execution_time
)
def _format_json(self, input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
@staticmethod
def _format_json(input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
"""格式化JSON"""
indent = kwargs.get("indent", 2)
ensure_ascii = kwargs.get("ensure_ascii", False)
@@ -151,12 +152,13 @@ class JsonTool(BuiltinTool):
"sort_keys": sort_keys
}
}
def _minify_json(self, input_data: str) -> Dict[str, Any]:
@staticmethod
def _minify_json(input_data: str) -> Dict[str, Any]:
"""压缩JSON"""
# 解析并压缩
data = json.loads(input_data)
minified = json.dumps(data, separators=(',', ':'))
minified = json.dumps(data, ensure_ascii=False, separators=(',', ':'))
return {
"original_size": len(input_data),
@@ -165,7 +167,7 @@ class JsonTool(BuiltinTool):
"minified_json": minified,
"is_valid": True
}
def _validate_json(self, input_data: str) -> Dict[str, Any]:
"""验证JSON"""
try:
@@ -190,17 +192,19 @@ class JsonTool(BuiltinTool):
"size": len(input_data)
}
def _convert_json(self, input_data: str) -> Dict[str, Any]:
@staticmethod
def _convert_json(input_data: str) -> Dict[str, Any]:
"""JSON转义"""
data = json.loads(input_data)
converted = json.dumps(data, ensure_ascii=False)
converted = json.dumps(data, ensure_ascii=True, separators=(',', ':'))
return {
"converted_json": converted,
"is_valid": True
}
def _json_to_yaml(self, input_data: str) -> Dict[str, Any]:
@staticmethod
def _json_to_yaml(input_data: str) -> Dict[str, Any]:
"""JSON转YAML"""
data = json.loads(input_data)
yaml_output = yaml.dump(data, default_flow_style=False, allow_unicode=True, indent=2)
@@ -212,8 +216,9 @@ class JsonTool(BuiltinTool):
"converted_size": len(yaml_output),
"converted_data": yaml_output
}
def _yaml_to_json(self, input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
@staticmethod
def _yaml_to_json(input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
"""YAML转JSON"""
indent = kwargs.get("indent", 2)
ensure_ascii = kwargs.get("ensure_ascii", False)
@@ -228,10 +233,11 @@ class JsonTool(BuiltinTool):
"converted_size": len(json_output),
"converted_data": json_output
}
def _json_to_xml(self, input_data: str) -> Dict[str, Any]:
@staticmethod
def _json_to_xml(input_data: str) -> Dict[str, Any]:
"""JSON转XML"""
data = json.loads(input_data)
json_data = json.loads(input_data)
def dict_to_xml(data, root_name="root"):
"""递归转换字典为XML"""
@@ -267,7 +273,7 @@ class JsonTool(BuiltinTool):
root.text = str(data)
return root
xml_element = dict_to_xml(data)
xml_element = dict_to_xml(json_data)
xml_string = ET.tostring(xml_element, encoding='unicode')
# 格式化XML
@@ -284,8 +290,9 @@ class JsonTool(BuiltinTool):
"converted_size": len(formatted_xml),
"converted_data": formatted_xml
}
def _xml_to_json(self, input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
@staticmethod
def _xml_to_json(input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
"""XML转JSON"""
indent = kwargs.get("indent", 2)
@@ -328,8 +335,9 @@ class JsonTool(BuiltinTool):
"converted_size": len(json_output),
"converted_data": json_output
}
def _merge_json(self, input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
@staticmethod
def _merge_json(input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
"""合并JSON"""
merge_data = kwargs.get("merge_data")
if not merge_data:
@@ -364,8 +372,9 @@ class JsonTool(BuiltinTool):
"result_size": len(merged_json),
"merged_data": merged_json
}
def _extract_json_path(self, input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
@staticmethod
def _extract_json_path( input_data: str, kwargs: Dict[str, Any]) -> Dict[str, Any]:
"""提取JSON路径"""
json_path = kwargs.get("json_path")
if not json_path:

View File

@@ -275,8 +275,9 @@ class TextInTool(BuiltinTool):
"total_confidence": result.get("confidence", 0),
"processing_time": result.get("processing_time", 0)
}
def _format_formula_result(self, result: Dict[str, Any], output_format: str) -> Dict[str, Any]:
@staticmethod
def _format_formula_result( result: Dict[str, Any], output_format: str) -> Dict[str, Any]:
"""格式化公式识别结果"""
formulas = result.get("formulas", [])
@@ -288,8 +289,9 @@ class TextInTool(BuiltinTool):
"total_confidence": result.get("confidence", 0),
"processing_time": result.get("processing_time", 0)
}
def _format_table_result(self, result: Dict[str, Any], output_format: str) -> Dict[str, Any]:
@staticmethod
def _format_table_result(result: Dict[str, Any], output_format: str) -> Dict[str, Any]:
"""格式化表格识别结果"""
tables = result.get("tables", [])
@@ -301,8 +303,9 @@ class TextInTool(BuiltinTool):
"total_confidence": result.get("confidence", 0),
"processing_time": result.get("processing_time", 0)
}
def _format_document_result(self, result: Dict[str, Any], output_format: str) -> Dict[str, Any]:
@staticmethod
def _format_document_result(result: Dict[str, Any], output_format: str) -> Dict[str, Any]:
"""格式化文档识别结果"""
return {
"recognition_mode": "document",
@@ -314,8 +317,9 @@ class TextInTool(BuiltinTool):
"total_confidence": result.get("confidence", 0),
"processing_time": result.get("processing_time", 0)
}
def _group_lines_to_paragraphs(self, lines: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
@staticmethod
def _group_lines_to_paragraphs(lines: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""将行分组为段落"""
paragraphs = []
current_paragraph = []