base.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. """工具基类"""
  2. from abc import ABC, abstractmethod
  3. from typing import Dict, Any, List
  4. from pydantic import BaseModel
  5. class ToolParameter(BaseModel):
  6. """工具参数定义"""
  7. name: str
  8. type: str
  9. description: str
  10. required: bool = True
  11. default: Any = None
  12. class Tool(ABC):
  13. """工具基类"""
  14. def __init__(self, name: str, description: str):
  15. self.name = name
  16. self.description = description
  17. @abstractmethod
  18. def run(self, parameters: Dict[str, Any]) -> str:
  19. """执行工具"""
  20. pass
  21. @abstractmethod
  22. def get_parameters(self) -> List[ToolParameter]:
  23. """获取工具参数定义"""
  24. pass
  25. def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
  26. """验证参数"""
  27. required_params = [p.name for p in self.get_parameters() if p.required]
  28. return all(param in parameters for param in required_params)
  29. def to_openai_schema(self) -> Dict[str, Any]:
  30. """转换为 OpenAI function calling schema 格式"""
  31. parameters = self.get_parameters()
  32. properties = {}
  33. required = []
  34. for param in parameters:
  35. prop = {"type": param.type, "description": param.description}
  36. if param.default is not None:
  37. prop["description"] = f"{param.description} (默认: {param.default})"
  38. if param.type == "array":
  39. prop["items"] = {"type": "string"}
  40. properties[param.name] = prop
  41. if param.required:
  42. required.append(param.name)
  43. return {
  44. "type": "function",
  45. "function": {
  46. "name": self.name,
  47. "description": self.description,
  48. "parameters": {
  49. "type": "object",
  50. "properties": properties,
  51. "required": required,
  52. },
  53. },
  54. }
  55. def __str__(self) -> str:
  56. return f"Tool(name={self.name})"
  57. def __repr__(self) -> str:
  58. return self.__str__()