Skip to content

Commit 116185a

Browse files
committed
Updated llm
1 parent 5096045 commit 116185a

File tree

9 files changed

+110
-35
lines changed

9 files changed

+110
-35
lines changed

cmd/agent/chat.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ func (cmd *ChatCmd) Run(globals *Globals) error {
7979
calls := session.ToolCalls()
8080
if results, err := globals.toolkit.Run(ctx, calls...); err != nil {
8181
return err
82+
} else if err := session.FromTool(ctx, results...); err != nil {
83+
return err
8284
} else {
83-
fmt.Println(results)
85+
fmt.Println(session.Text())
8486
}
8587
}
8688
})

context.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ type Context interface {
2222
ContextContent
2323

2424
// Generate a response from a user prompt (with attachments and
25-
// other empheral options
25+
// other options)
2626
FromUser(context.Context, string, ...Opt) error
2727

28-
// Generate a response from a tool, passing the call identifier or
29-
// function name, and the result
30-
FromTool(context.Context, string, any, ...Opt) error
28+
// Generate a response from a tool, passing the results
29+
// from the tool call
30+
FromTool(context.Context, ...ToolResult) error
3131
}

pkg/anthropic/message.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ type ContentAttachment struct {
4646
}
4747

4848
type ContentToolResult struct {
49-
Id string `json:"tool_use_id,omitempty"` // tool id
50-
Content []*Content `json:"content,omitempty"`
49+
Id string `json:"tool_use_id,omitempty"` // tool id
50+
Content any `json:"content,omitempty"`
5151
}
5252

5353
type contentsource struct {
@@ -75,6 +75,24 @@ func NewTextContent(v string) *Content {
7575
return content
7676
}
7777

78+
// Return a Content object with tool result
79+
func NewToolResultContent(v llm.ToolResult) *Content {
80+
content := new(Content)
81+
content.Type = "tool_result"
82+
content.ContentToolResult.Id = v.Call().Id()
83+
// content.ContentToolResult.Name = v.Call().Name()
84+
85+
// We only support JSON encoding for the moment
86+
data, err := json.Marshal(v.Value())
87+
if err != nil {
88+
content.ContentToolResult.Content = err.Error()
89+
} else {
90+
content.ContentToolResult.Content = string(data)
91+
}
92+
93+
return content
94+
}
95+
7896
///////////////////////////////////////////////////////////////////////////////
7997
// STRINGIFY
8098

pkg/anthropic/session.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,25 @@ func (session *session) FromUser(ctx context.Context, prompt string, opts ...llm
141141

142142
// Generate a response from a tool, passing the call identifier or
143143
// function name, and the result
144-
func (session *session) FromTool(context.Context, string, any, ...llm.Opt) error {
145-
return llm.ErrNotImplemented
144+
func (session *session) FromTool(ctx context.Context, results ...llm.ToolResult) error {
145+
meta, err := toolResults(results...)
146+
if err != nil {
147+
return err
148+
} else {
149+
session.seq = append(session.seq, meta)
150+
}
151+
152+
// Call the 'chat' method
153+
client := session.model.client
154+
r, err := client.Messages(ctx, session, session.opts...)
155+
if err != nil {
156+
return err
157+
} else {
158+
session.seq = append(session.seq, &r.MessageMeta)
159+
}
160+
161+
// Return success
162+
return nil
146163
}
147164

148165
///////////////////////////////////////////////////////////////////////////////
@@ -179,3 +196,22 @@ func userPrompt(prompt string, opts ...llm.Opt) (*MessageMeta, error) {
179196
// Return success
180197
return &meta, nil
181198
}
199+
200+
func toolResults(results ...llm.ToolResult) (*MessageMeta, error) {
201+
// Check for no results
202+
if len(results) == 0 {
203+
return nil, llm.ErrBadParameter.Withf("No tool results")
204+
}
205+
206+
// Create user message
207+
meta := MessageMeta{
208+
Role: "user",
209+
Content: make([]*Content, 0, len(results)),
210+
}
211+
for _, result := range results {
212+
meta.Content = append(meta.Content, NewToolResultContent(result))
213+
}
214+
215+
// Return success
216+
return &meta, nil
217+
}

pkg/ollama/session.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,21 +91,20 @@ func (s *session) FromUser(ctx context.Context, prompt string, opts ...llm.Opt)
9191
}
9292

9393
// Generate a response from a tool calling result
94-
func (s *session) FromTool(ctx context.Context, call string, result any, opts ...llm.Opt) error {
95-
// Append the tool result
96-
if message, err := toolResult(call, result); err != nil {
97-
return err
98-
} else {
99-
s.seq[len(s.seq)-1] = message
94+
func (s *session) FromTool(ctx context.Context, results ...llm.ToolResult) error {
95+
if len(results) == 0 {
96+
return llm.ErrConflict.Withf("No tool results")
10097
}
10198

102-
// The options come from the session options and the user options
103-
chatopts := make([]llm.Opt, 0, len(s.opts)+len(opts))
104-
chatopts = append(chatopts, s.opts...)
105-
chatopts = append(chatopts, opts...)
99+
// Append the tool results
100+
for _, result := range results {
101+
if message, err := toolResult(result); err != nil {
102+
s.seq = append(s.seq, message)
103+
}
104+
}
106105

107106
// Call the 'chat' method
108-
r, err := s.model.client.Chat(ctx, s, chatopts...)
107+
r, err := s.model.client.Chat(ctx, s, s.opts...)
109108
if err != nil {
110109
return err
111110
} else {
@@ -177,17 +176,17 @@ func userPrompt(prompt string, opts ...llm.Opt) (*MessageMeta, error) {
177176
return &meta, nil
178177
}
179178

180-
func toolResult(name string, result any) (*MessageMeta, error) {
179+
func toolResult(result llm.ToolResult) (*MessageMeta, error) {
181180
// Turn result into JSON
182-
data, err := json.Marshal(result)
181+
data, err := json.Marshal(result.Value())
183182
if err != nil {
184183
return nil, err
185184
}
186185

187186
// Create a new message
188187
var meta MessageMeta
189188
meta.Role = "tool"
190-
meta.FunctionName = name
189+
meta.FunctionName = result.Call().Name()
191190
meta.Content = string(data)
192191

193192
// Return success

pkg/tool/call.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ func NewCall(id, name string, input map[string]any) *call {
3535
///////////////////////////////////////////////////////////////////////////////
3636
// STRINGIFY
3737

38+
func (t call) MarshalJSON() ([]byte, error) {
39+
return json.Marshal(t.meta)
40+
}
41+
3842
func (t call) String() string {
3943
data, err := json.MarshalIndent(t.meta, "", " ")
4044
if err != nil {

pkg/tool/result.go

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,38 @@ import (
1010
///////////////////////////////////////////////////////////////////////////////
1111
// TYPES
1212

13+
type ResultMeta struct {
14+
Call llm.ToolCall `json:"call"`
15+
Value any `json:"result"`
16+
}
17+
1318
type result struct {
14-
call llm.ToolCall
15-
value any
19+
meta ResultMeta
1620
}
1721

1822
var _ llm.ToolResult = (*result)(nil)
1923

24+
///////////////////////////////////////////////////////////////////////////////
25+
// LIFECYCLE
26+
27+
func NewResult(call llm.ToolCall, value any) llm.ToolResult {
28+
return &result{
29+
meta: ResultMeta{
30+
Call: call,
31+
Value: value,
32+
},
33+
}
34+
}
35+
2036
///////////////////////////////////////////////////////////////////////////////
2137
// STRINGIFY
2238

39+
func (r result) MarshalJSON() ([]byte, error) {
40+
return json.Marshal(r.meta)
41+
}
42+
2343
func (r result) String() string {
24-
type j struct {
25-
Call llm.ToolCall `json:"call"`
26-
Result any `json:"result"`
27-
}
28-
data, err := json.MarshalIndent(j{r.call, r.value}, "", " ")
44+
data, err := json.MarshalIndent(r.meta, "", " ")
2945
if err != nil {
3046
return err.Error()
3147
}
@@ -37,10 +53,10 @@ func (r result) String() string {
3753

3854
// The call associated with the result
3955
func (r result) Call() llm.ToolCall {
40-
return r.call
56+
return r.meta.Call
4157
}
4258

4359
// The result, which can be encoded into json
44-
func (r result) Result() any {
45-
return r.value
60+
func (r result) Value() any {
61+
return r.meta.Value
4662
}

pkg/tool/toolkit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func (kit *ToolKit) Run(ctx context.Context, calls ...llm.ToolCall) ([]llm.ToolR
125125
} else if out, err := kit.functions[name].Tool.Run(ctx); err != nil {
126126
errs = errors.Join(errs, err)
127127
} else {
128-
toolresult = append(toolresult, &result{call, out})
128+
toolresult = append(toolresult, NewResult(call, out))
129129
}
130130
}(call)
131131
}

toolkit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@ type ToolResult interface {
5050
Call() ToolCall
5151

5252
// The result, which can be encoded into json
53-
Result() any
53+
Value() any
5454
}

0 commit comments

Comments
 (0)