112 lines
3.1 KiB
Python
112 lines
3.1 KiB
Python
|
|
"""
|
||
|
|
Tool definition converter for Function Calling.
|
||
|
|
Converts ToolRegistry definitions to LLM ToolDefinition format.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import logging
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from app.services.llm.base import ToolDefinition
|
||
|
|
from app.services.mid.tool_registry import ToolDefinition as RegistryToolDefinition
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
def convert_tool_to_llm_format(tool: RegistryToolDefinition) -> ToolDefinition:
|
||
|
|
"""
|
||
|
|
Convert ToolRegistry tool definition to LLM ToolDefinition format.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
tool: Tool definition from ToolRegistry
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
ToolDefinition for Function Calling
|
||
|
|
"""
|
||
|
|
meta = tool.metadata or {}
|
||
|
|
parameters = meta.get("parameters", {
|
||
|
|
"type": "object",
|
||
|
|
"properties": {},
|
||
|
|
"required": [],
|
||
|
|
})
|
||
|
|
|
||
|
|
if not isinstance(parameters, dict):
|
||
|
|
parameters = {
|
||
|
|
"type": "object",
|
||
|
|
"properties": {},
|
||
|
|
"required": [],
|
||
|
|
}
|
||
|
|
|
||
|
|
if "type" not in parameters:
|
||
|
|
parameters["type"] = "object"
|
||
|
|
if "properties" not in parameters:
|
||
|
|
parameters["properties"] = {}
|
||
|
|
if "required" not in parameters:
|
||
|
|
parameters["required"] = []
|
||
|
|
|
||
|
|
properties = parameters.get("properties", {})
|
||
|
|
if "tenant_id" in properties:
|
||
|
|
properties = {k: v for k, v in properties.items() if k != "tenant_id"}
|
||
|
|
if "user_id" in properties:
|
||
|
|
properties = {k: v for k, v in properties.items() if k != "user_id"}
|
||
|
|
if "session_id" in properties:
|
||
|
|
properties = {k: v for k, v in properties.items() if k != "session_id"}
|
||
|
|
|
||
|
|
parameters["properties"] = properties
|
||
|
|
|
||
|
|
required = parameters.get("required", [])
|
||
|
|
required = [r for r in required if r not in ("tenant_id", "user_id", "session_id")]
|
||
|
|
parameters["required"] = required
|
||
|
|
|
||
|
|
return ToolDefinition(
|
||
|
|
name=tool.name,
|
||
|
|
description=tool.description,
|
||
|
|
parameters=parameters,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def convert_tools_to_llm_format(tools: list[RegistryToolDefinition]) -> list[ToolDefinition]:
|
||
|
|
"""
|
||
|
|
Convert multiple tool definitions to LLM format.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
tools: List of tool definitions from ToolRegistry
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
List of ToolDefinition for Function Calling
|
||
|
|
"""
|
||
|
|
return [convert_tool_to_llm_format(tool) for tool in tools]
|
||
|
|
|
||
|
|
|
||
|
|
def build_tool_result_message(
|
||
|
|
tool_call_id: str,
|
||
|
|
tool_name: str,
|
||
|
|
result: dict[str, Any],
|
||
|
|
tool_guide: str | None = None,
|
||
|
|
) -> dict[str, str]:
|
||
|
|
"""
|
||
|
|
Build a tool result message for the conversation.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
tool_call_id: ID of the tool call
|
||
|
|
tool_name: Name of the tool
|
||
|
|
result: Tool execution result
|
||
|
|
tool_guide: Optional tool usage guide to append
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Message dict with role='tool'
|
||
|
|
"""
|
||
|
|
if isinstance(result, dict):
|
||
|
|
result_copy = {k: v for k, v in result.items() if k != "_tool_guide"}
|
||
|
|
content = str(result_copy)
|
||
|
|
else:
|
||
|
|
content = str(result)
|
||
|
|
|
||
|
|
if tool_guide:
|
||
|
|
content = f"{content}\n\n---\n{tool_guide}"
|
||
|
|
|
||
|
|
return {
|
||
|
|
"role": "tool",
|
||
|
|
"tool_call_id": tool_call_id,
|
||
|
|
"content": content,
|
||
|
|
}
|