From f4880fd90db713c67151f1cbfd58f292982a5a0c Mon Sep 17 00:00:00 2001 From: Raven95676 Date: Mon, 21 Apr 2025 00:11:31 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dget=5Ffunc=5Fdesc?= =?UTF-8?q?=5Fgoogle=5Fgenai=5Fstyle=E6=9C=AA=E6=AD=A3=E7=A1=AE=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E5=87=BD=E6=95=B0=E8=B0=83=E7=94=A8=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/provider/func_tool_manager.py | 78 ++++++++++++++++------ 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/astrbot/core/provider/func_tool_manager.py b/astrbot/core/provider/func_tool_manager.py index 918542f17..a54782c3c 100644 --- a/astrbot/core/provider/func_tool_manager.py +++ b/astrbot/core/provider/func_tool_manager.py @@ -435,28 +435,64 @@ class FuncCall: tools.append(tool) return tools - def get_func_desc_google_genai_style(self) -> Dict: + def get_func_desc_google_genai_style(self) -> dict: + """ + 获得 Google GenAI API 风格的**已经激活**的工具描述 + """ + + # Gemini API 支持的数据类型和格式 + supported_types = {"string", "number", "integer", "boolean", "array", "object", "null"} + supported_formats = { + "string": {"enum", "date-time"}, + "integer": {"int32", "int64"}, + "number": {"float", "double"} + } + + def convert_schema(schema: dict) -> dict: + """转换 schema 为 Gemini API 格式""" + result = {} + + if "type" in schema and schema["type"] in supported_types: + result["type"] = schema["type"] + if ("format" in schema and + schema["format"] in supported_formats.get(result["type"], set())): + result["format"] = schema["format"] + else: + # 暂时指定默认为null + result["type"] = "null" + + support_fields = {"title", "description", "enum", "minimum", "maximum", + "maxItems", "minItems", "nullable", "required"} + result.update({k: schema[k] for k in support_fields if k in schema}) + + if "properties" in schema: + properties = {} + for key, value in schema["properties"].items(): + prop_value = convert_schema(value) + if "default" in prop_value: + del prop_value["default"] + properties[key] = prop_value + + if properties: # 只在有非空属性时添加 + result["properties"] = properties + + if "items" in schema: + result["items"] = convert_schema(schema["items"]) + if "anyOf" in schema: + result["anyOf"] = [convert_schema(s) for s in schema["anyOf"]] + + return result + + tools = [ + { + "name": f.name, + "description": f.description, + **({"parameters": convert_schema(f.parameters)} if convert_schema(f.parameters) else {}) + } + for f in self.func_list if f.active + ] + declarations = {} - tools = [] - for f in self.func_list: - if not f.active: - continue - - func_declaration = {"name": f.name, "description": f.description} - - # 检查并添加非空的properties参数 - params = f.parameters if isinstance(f.parameters, dict) else {} - params = copy.deepcopy(params) - if params.get("properties", {}): - properties = params["properties"] - for key, value in properties.items(): - if "default" in value: - del value["default"] - params["properties"] = properties - func_declaration["parameters"] = params - - tools.append(func_declaration) - if tools: declarations["function_declarations"] = tools return declarations From f5024984f75d31e535c60f5035f964c7ad68d480 Mon Sep 17 00:00:00 2001 From: Raven95676 Date: Mon, 21 Apr 2025 00:55:20 +0800 Subject: [PATCH 2/2] =?UTF-8?q?perf:=20=E7=A7=BB=E9=99=A4=E5=86=97?= =?UTF-8?q?=E4=BD=99=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/provider/func_tool_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astrbot/core/provider/func_tool_manager.py b/astrbot/core/provider/func_tool_manager.py index a54782c3c..d7b0ca4b1 100644 --- a/astrbot/core/provider/func_tool_manager.py +++ b/astrbot/core/provider/func_tool_manager.py @@ -487,7 +487,7 @@ class FuncCall: { "name": f.name, "description": f.description, - **({"parameters": convert_schema(f.parameters)} if convert_schema(f.parameters) else {}) + **({"parameters": convert_schema(f.parameters)}) } for f in self.func_list if f.active ]