Files
ai-bot/internal/tools/builtin/calculator_tool.go
T

86 lines
1.9 KiB
Go

package builtin
import (
"encoding/json"
"fmt"
"math"
"strconv"
"github.com/expr-lang/expr"
)
type calculatorTool struct {
enabled bool
prompt string
}
func NewCalculatorTool() *calculatorTool {
return &calculatorTool{
enabled: true,
prompt: "计算数学表达式,如 \"(12 + 3) * 4\"、\"2^10\"、\"sqrt(9)\"",
}
}
func (t *calculatorTool) Name() string { return "calculate" }
func (t *calculatorTool) Description() string { return t.prompt }
func (t *calculatorTool) Enabled() bool { return t.enabled }
func (t *calculatorTool) DefaultConfig() map[string]any {
return map[string]any{"enabled": true, "prompt": t.prompt}
}
func (t *calculatorTool) Configure(cfg map[string]any) error {
var err error
if t.enabled, err = parseEnabled(cfg); err != nil {
return err
}
if p, ok := cfg["prompt"].(string); ok && p != "" {
t.prompt = p
}
return nil
}
func (t *calculatorTool) Parameters() map[string]any {
return map[string]any{
"type": "object",
"properties": map[string]any{
"expression": map[string]any{"type": "string", "description": "要计算的数学表达式"},
},
"required": []string{"expression"},
}
}
func (t *calculatorTool) Execute(args json.RawMessage) (string, error) {
var p struct {
Expression string `json:"expression"`
}
if err := json.Unmarshal(args, &p); err != nil {
return "", err
}
if p.Expression == "" {
return "", fmt.Errorf("expression 不能为空")
}
out, err := expr.Eval(p.Expression, nil)
if err != nil {
return "", err
}
switch v := out.(type) {
case float64:
return strconv.FormatFloat(round(v), 'f', -1, 64), nil
case int:
return strconv.Itoa(v), nil
case bool:
return strconv.FormatBool(v), nil
case string:
return v, nil
default:
return fmt.Sprintf("%v", v), nil
}
}
func round(v float64) float64 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return v
}
return math.Round(v*1e8) / 1e8
}