MeuAgente / src /tools /calculator.py
gaiotto's picture
deploy: agente aula07 no HF Space
df1da34
Raw
History Blame Contribute Delete
2.71 kB
"""Tool: calculadora aritmética segura.
Avalia expressões matemáticas básicas (+, -, *, /, **, parênteses).
Usada principalmente pelo EducIAção em exemplos de matemática.
"""
import ast
import operator
# Operadores permitidos
_OPS: dict = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow,
ast.Mod: operator.mod,
ast.FloorDiv: operator.floordiv,
ast.USub: operator.neg,
ast.UAdd: operator.pos,
}
def _safe_eval(node: ast.AST) -> float:
"""Avalia AST de forma segura, sem chamar eval() bruto."""
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
return node.value
if isinstance(node, ast.BinOp):
op_type = type(node.op)
if op_type not in _OPS:
raise ValueError(f"Operador {op_type.__name__} não permitido")
return _OPS[op_type](_safe_eval(node.left), _safe_eval(node.right))
if isinstance(node, ast.UnaryOp):
op_type = type(node.op)
if op_type not in _OPS:
raise ValueError(f"Operador unário {op_type.__name__} não permitido")
return _OPS[op_type](_safe_eval(node.operand))
raise ValueError(f"Nó AST não permitido: {type(node).__name__}")
def run_calculator(expression: str) -> str:
"""Avalia uma expressão matemática e retorna string formatada."""
try:
tree = ast.parse(expression, mode="eval")
result = _safe_eval(tree.body)
# Formato: inteiro se possível, senão float com 6 casas
if isinstance(result, float) and result.is_integer():
result = int(result)
elif isinstance(result, float):
result = round(result, 6)
return f"{expression} = {result}"
except (SyntaxError, ValueError, ZeroDivisionError) as exc:
return f"ERRO ao calcular '{expression}': {exc}"
calculator_tool: dict = {
"type": "function",
"function": {
"name": "calculator",
"description": (
"Avalia uma expressão matemática (números, +, -, *, /, **, parênteses). "
"Use SEMPRE que precisar fazer conta exata. Não invente resultados."
),
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": (
"Expressão matemática em formato Python. "
"Exemplos: '3/4 * 5/2', '2 ** 10', '(15 + 7) * 3'"
),
}
},
"required": ["expression"],
"additionalProperties": False,
},
},
}