-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtools.go
More file actions
157 lines (131 loc) · 4.01 KB
/
tools.go
File metadata and controls
157 lines (131 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package modelsocket
import (
"context"
"encoding/json"
"fmt"
"sync"
)
// Tool defines the interface for a callable tool.
type Tool interface {
Definition() ToolDefinition
Call(ctx context.Context, args string) (string, error)
}
// ToolDefinition describes a tool for the model.
type ToolDefinition struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters ToolParameters `json:"parameters"`
}
// ToolParameters defines the JSON Schema for tool parameters.
type ToolParameters struct {
Type string `json:"type"`
Properties map[string]ToolProperty `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
}
// ToolProperty defines a single parameter property.
type ToolProperty struct {
Type string `json:"type"`
Description string `json:"description,omitempty"`
Enum []string `json:"enum,omitempty"`
}
// Toolbox manages a collection of tools.
type Toolbox struct {
mu sync.RWMutex
tools map[string]Tool
toolInstructions string
toolDefinitionPrompt string
}
// NewToolbox creates an empty toolbox.
func NewToolbox() *Toolbox {
return &Toolbox{
tools: make(map[string]Tool),
}
}
// Add registers a tool.
func (t *Toolbox) Add(tool Tool) {
def := tool.Definition()
t.mu.Lock()
t.tools[def.Name] = tool
t.mu.Unlock()
}
// Get retrieves a tool by name.
func (t *Toolbox) Get(name string) (Tool, bool) {
t.mu.RLock()
defer t.mu.RUnlock()
tool, ok := t.tools[name]
return tool, ok
}
// Call executes a tool by name with the given arguments.
func (t *Toolbox) Call(ctx context.Context, name string, args string) (string, error) {
tool, ok := t.Get(name)
if !ok {
return "", fmt.Errorf("%w: %s", ErrToolNotFound, name)
}
return tool.Call(ctx, args)
}
// CallTools executes multiple tool calls and returns results.
func (t *Toolbox) CallTools(ctx context.Context, calls []ToolCall) ([]ToolResult, error) {
results := make([]ToolResult, 0, len(calls))
for _, call := range calls {
result, err := t.Call(ctx, call.Name, call.Args)
if err != nil {
// Return error as result instead of failing
result = fmt.Sprintf("error: %v", err)
}
results = append(results, ToolResult{
Name: call.Name,
Result: result,
})
}
return results, nil
}
// Definitions returns all tool definitions.
func (t *Toolbox) Definitions() []ToolDefinition {
t.mu.RLock()
defer t.mu.RUnlock()
defs := make([]ToolDefinition, 0, len(t.tools))
for _, tool := range t.tools {
defs = append(defs, tool.Definition())
}
return defs
}
func (t *Toolbox) SetToolInstructions(instructions string) {
t.toolInstructions = instructions
}
// ToolInstructions returns the tool instructions.
func (t *Toolbox) ToolInstructions() string {
return t.toolInstructions
}
func (t *Toolbox) SetToolDefinitionPrompt(prompt string) {
t.toolDefinitionPrompt = prompt
}
// ToolPrompt returns the tool prompt. If a custom prompt was set via SetToolPrompt,
// it returns that; otherwise it returns an auto-generated prompt describing all tools.
func (t *Toolbox) ToolDefinitionPrompt() string {
if t.toolDefinitionPrompt != "" {
return t.toolDefinitionPrompt
}
defs := t.Definitions()
if len(defs) == 0 {
return ""
}
data, _ := json.MarshalIndent(defs, "", " ")
return fmt.Sprintf("You have access to the following tools:\n\n%s\n\nTo use a tool, respond with a tool call in the appropriate format.", string(data))
}
// FuncTool wraps a function as a Tool.
type FuncTool struct {
def ToolDefinition
fn func(ctx context.Context, args string) (string, error)
}
// NewFuncTool creates a tool from a function.
func NewFuncTool(def ToolDefinition, fn func(ctx context.Context, args string) (string, error)) *FuncTool {
return &FuncTool{def: def, fn: fn}
}
// Definition returns the tool definition.
func (f *FuncTool) Definition() ToolDefinition {
return f.def
}
// Call invokes the tool function.
func (f *FuncTool) Call(ctx context.Context, args string) (string, error) {
return f.fn(ctx, args)
}