update against go-llm changes

This commit is contained in:
2025-03-16 22:39:47 -04:00
parent 1d47cf5758
commit 4c106d32cb
2 changed files with 73 additions and 72 deletions

View File

@@ -4,6 +4,9 @@ import (
"context"
"errors"
"fmt"
"go.starlark.net/lib/math"
"go.starlark.net/starlark"
"go.starlark.net/syntax"
"log/slog"
"net/url"
"strings"
@@ -74,39 +77,6 @@ type Result struct {
Error error
}
func fanExecuteToolCalls(ctx context.Context, toolBox *gollm.ToolBox, calls []gollm.ToolCall) []Result {
var results []Result
var resultsOutput = make(chan Result, len(calls))
fnCall := func(call gollm.ToolCall) Result {
str, err := toolBox.Execute(ctx, call)
if err != nil {
return Result{
Error: err,
}
}
return Result{
Result: str,
}
}
for _, call := range calls {
go func(call gollm.ToolCall) {
resultsOutput <- fnCall(call)
}(call)
}
for i := 0; i < len(calls); i++ {
result := <-resultsOutput
results = append(results, result)
}
close(resultsOutput)
return results
}
type article struct {
URL string
Title string
@@ -156,11 +126,11 @@ func extractArticle(ctx context.Context, c cache.Cache, u *url.URL) (res article
}, nil
}
func doesTextAnswerQuestion(ctx context.Context, q Question, text string) (string, error) {
func doesTextAnswerQuestion(ctx *gollm.Context, q Question, text string) (string, error) {
fnAnswer := gollm.NewFunction(
"answer",
"The answer from the given text that answers the question.",
func(ctx context.Context, args struct {
func(ctx *gollm.Context, args struct {
Answer string `description:"the answer to the question, the answer should come from the text"`
}) (string, error) {
return args.Answer, nil
@@ -169,7 +139,7 @@ func doesTextAnswerQuestion(ctx context.Context, q Question, text string) (strin
fnNoAnswer := gollm.NewFunction(
"no_answer",
"Indicate that the text does not answer the question.",
func(ctx context.Context, args struct {
func(ctx *gollm.Context, args struct {
Ignored string `description:"ignored, just here to make sure the function is called. Fill with anything."`
}) (string, error) {
return "", nil
@@ -210,8 +180,7 @@ func doesTextAnswerQuestion(ctx context.Context, q Question, text string) (strin
return req.Toolbox.Execute(ctx, res.Choices[0].Calls[0])
}
func functionSearch(ctx context.Context, q Question, searchTerm string) (string, error) {
func functionSearch(ctx *gollm.Context, q Question, searchTerm string) (string, error) {
slog.Info("searching", "search", searchTerm, "question", q)
res, err := q.Search.Search(ctx, searchTerm)
if err != nil {
@@ -260,11 +229,11 @@ func functionSearch(ctx context.Context, q Question, searchTerm string) (string,
return "", nil
}
func functionThink(ctx context.Context, q Question) (string, error) {
func functionThink(ctx *gollm.Context, q Question) (string, error) {
fnAnswer := gollm.NewFunction(
"answer",
"Answer the question.",
func(ctx context.Context, args struct {
func(ctx *gollm.Context, args struct {
Answer string `description:"the answer to the question"`
}) (string, error) {
return args.Answer, nil
@@ -307,7 +276,7 @@ func (o Options) Answer(ctx context.Context, q Question) (Answers, error) {
fnSearch := gollm.NewFunction(
"search",
"Search the web for an answer to a question. You can call this function up to "+fmt.Sprint(o.MaxSearches)+" times.",
func(ctx context.Context, args struct {
func(ctx *gollm.Context, args struct {
SearchQuery string `description:"what to search the web for for this question"`
Question string `description:"what question(s) you are trying to answer with this search"`
}) (string, error) {
@@ -320,7 +289,7 @@ func (o Options) Answer(ctx context.Context, q Question) (Answers, error) {
fnThink := gollm.NewFunction(
"think",
"Think about a question. This is useful for breaking down complex questions into smaller parts that are easier to answer.",
func(ctx context.Context, args struct {
func(ctx *gollm.Context, args struct {
Question string `json:"question" description:"the question to think about"`
}) (string, error) {
q2 := q
@@ -332,13 +301,37 @@ func (o Options) Answer(ctx context.Context, q Question) (Answers, error) {
fnAnswer := gollm.NewFunction(
"answer",
"You definitively answer a question, if you call this it means you know the answer and do not need to search for it or use any other function to find it",
func(ctx context.Context, args struct {
func(ctx *gollm.Context, args struct {
Answer string `json:"answer" description:"the answer to the question"`
}) (string, error) {
return args.Answer, nil
})
var funcs = []*gollm.Function{fnAnswer}
fnWolfram := gollm.NewFunction(
"wolfram",
"Search Wolfram Alpha for an answer to a question.",
func(ctx *gollm.Context, args struct {
Question string `description:"the question to search for"`
}) (string, error) {
return "", nil
})
fnCalculate := gollm.NewFunction(
"calculate",
"Calculate a mathematical expression using starlark.",
func(ctx *gollm.Context, args struct {
Expression string `description:"the mathematical expression to calculate, in starlark format"`
}) (string, error) {
fileOpts := syntax.FileOptions{}
v, err := starlark.EvalOptions(&fileOpts, &starlark.Thread{Name: "main"}, "input", args.Expression, math.Module.Members)
if err != nil {
return "", err
}
return v.String(), nil
})
var funcs = []*gollm.Function{fnAnswer, fnWolfram, fnCalculate}
if o.MaxSearches > 0 {
funcs = append(funcs, fnSearch)
@@ -371,6 +364,13 @@ func (o Options) Answer(ctx context.Context, q Question) (Answers, error) {
})
}
if q.Question != "" {
messages = append(messages, gollm.Message{
Role: gollm.RoleUser,
Text: q.Question,
})
}
req := gollm.Request{
Messages: messages,
Toolbox: gollm.NewToolBox(funcs...),
@@ -397,7 +397,7 @@ func (o Options) Answer(ctx context.Context, q Question) (Answers, error) {
var calls []Result
var callsOutput = make(chan Result, len(choice.Calls))
fnCall := func(call gollm.ToolCall) Result {
str, err := req.Toolbox.Execute(ctx, call)
str, err := req.Toolbox.Execute(gollm.NewContext(ctx, req, &choice, &call), call)
if err != nil {
return Result{