Skip to content

Commit

Permalink
Feat add tools (#201)
Browse files Browse the repository at this point in the history
  • Loading branch information
henomis authored May 29, 2024
1 parent 3930e2b commit 0a2de60
Show file tree
Hide file tree
Showing 20 changed files with 1,093 additions and 12 deletions.
24 changes: 12 additions & 12 deletions examples/llm/openai/thread/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package main

import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/henomis/lingoose/llm/openai"
"github.com/henomis/lingoose/thread"
"github.com/henomis/lingoose/tools/dalle"
"github.com/henomis/lingoose/transformer"
)

Expand All @@ -32,31 +33,30 @@ func newStr(str string) *string {

func main() {
openaillm := openai.New().WithModel(openai.GPT4o)
openaillm.WithToolChoice(newStr("auto"))
err := openaillm.BindFunction(
crateImage,
"createImage",
"use this function to create an image from a description",
)
if err != nil {
panic(err)
}
openaillm.WithToolChoice(newStr("auto")).WithTools(dalle.New())

t := thread.New().AddMessage(
thread.NewUserMessage().AddContent(
thread.NewTextContent("Please, create an image that inspires you"),
),
)

err = openaillm.Generate(context.Background(), t)
err := openaillm.Generate(context.Background(), t)
if err != nil {
panic(err)
}

if t.LastMessage().Role == thread.RoleTool {
var output dalle.Output

err = json.Unmarshal([]byte(t.LastMessage().Contents[0].AsToolResponseData().Result), &output)
if err != nil {
panic(err)
}

t.AddMessage(thread.NewUserMessage().AddContent(
thread.NewImageContentFromURL(
strings.ReplaceAll(t.LastMessage().Contents[0].AsToolResponseData().Result, `"`, ""),
output.ImageURL,
),
).AddContent(
thread.NewTextContent("can you describe the image?"),
Expand Down
32 changes: 32 additions & 0 deletions examples/llm/openai/tools/python/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"context"
"fmt"

"github.com/henomis/lingoose/llm/openai"
"github.com/henomis/lingoose/thread"
"github.com/henomis/lingoose/tools/python"
)

func main() {
newStr := func(str string) *string {
return &str
}
llm := openai.New().WithModel(openai.GPT3Dot5Turbo0613).WithToolChoice(newStr("auto")).WithTools(
python.New(),
)

t := thread.New().AddMessage(
thread.NewUserMessage().AddContent(
thread.NewTextContent("calculate reverse string of 'ailatiditalia', don't try to guess, let's use appropriate tool"),
),
)

llm.Generate(context.Background(), t)
if t.LastMessage().Role == thread.RoleTool {
llm.Generate(context.Background(), t)
}

fmt.Println(t)
}
66 changes: 66 additions & 0 deletions examples/llm/openai/tools/rag/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package main

import (
"context"
"fmt"
"os"

openaiembedder "github.com/henomis/lingoose/embedder/openai"
"github.com/henomis/lingoose/index"
"github.com/henomis/lingoose/index/vectordb/jsondb"
"github.com/henomis/lingoose/llm/openai"
"github.com/henomis/lingoose/rag"
"github.com/henomis/lingoose/thread"
ragtool "github.com/henomis/lingoose/tools/rag"
"github.com/henomis/lingoose/tools/serpapi"
"github.com/henomis/lingoose/tools/shell"
)

func main() {

rag := rag.New(
index.New(
jsondb.New().WithPersist("index.json"),
openaiembedder.New(openaiembedder.AdaEmbeddingV2),
),
).WithChunkSize(1000).WithChunkOverlap(0)

_, err := os.Stat("index.json")
if os.IsNotExist(err) {
err = rag.AddSources(context.Background(), "state_of_the_union.txt")
if err != nil {
panic(err)
}
}

newStr := func(str string) *string {
return &str
}
llm := openai.New().WithModel(openai.GPT4o).WithToolChoice(newStr("auto")).WithTools(
ragtool.New(rag, "US covid vaccines"),
serpapi.New(),
shell.New(),
)

topics := []string{
"how many covid vaccine doses US has donated to other countries.",
"who's the author of LinGoose github project.",
"which process is consuming the most memory.",
}

for _, topic := range topics {
t := thread.New().AddMessage(
thread.NewUserMessage().AddContent(
thread.NewTextContent("Please tell me " + topic),
),
)

llm.Generate(context.Background(), t)
if t.LastMessage().Role == thread.RoleTool {
llm.Generate(context.Background(), t)
}

fmt.Println(t)
}

}
15 changes: 15 additions & 0 deletions examples/tools/duckduckgo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"fmt"

"github.com/henomis/lingoose/tools/duckduckgo"
)

func main() {

t := duckduckgo.New().WithMaxResults(5)
f := t.Fn().(duckduckgo.FnPrototype)

fmt.Println(f(duckduckgo.Input{Query: "Simone Vellei"}))
}
16 changes: 16 additions & 0 deletions examples/tools/python/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import (
"fmt"

"github.com/henomis/lingoose/tools/python"
)

func main() {
t := python.New().WithPythonPath("python3")

pythonScript := `print("Hello from Python!")`
f := t.Fn().(python.FnPrototype)

fmt.Println(f(python.Input{PythonCode: pythonScript}))
}
15 changes: 15 additions & 0 deletions examples/tools/serpapi/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"fmt"

"github.com/henomis/lingoose/tools/serpapi"
)

func main() {

t := serpapi.New()
f := t.Fn().(serpapi.FnPrototype)

fmt.Println(f(serpapi.Input{Query: "Simone Vellei"}))
}
16 changes: 16 additions & 0 deletions examples/tools/shell/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import (
"fmt"

"github.com/henomis/lingoose/tools/shell"
)

func main() {
t := shell.New()

bashScript := `echo "Hello from $SHELL!"`
f := t.Fn().(shell.FnPrototype)

fmt.Println(f(shell.Input{BashScript: bashScript}))
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/henomis/restclientgo v1.2.0
github.com/invopop/jsonschema v0.7.0
github.com/sashabaranov/go-openai v1.24.0
golang.org/x/net v0.25.0
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
19 changes: 19 additions & 0 deletions llm/openai/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,25 @@ func (o *OpenAI) BindFunction(
return nil
}

type Tool interface {
Description() string
Name() string
Fn() any
}

func (o OpenAI) WithTools(tools ...Tool) OpenAI {
for _, tool := range tools {
function, err := bindFunction(tool.Fn(), tool.Name(), tool.Description())
if err != nil {
fmt.Println(err)
}

o.functions[tool.Name()] = *function
}

return o
}

func (o *Legacy) getFunctions() []openai.FunctionDefinition {
var functions []openai.FunctionDefinition

Expand Down
56 changes: 56 additions & 0 deletions tools/dalle/dalle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dalle

import (
"context"
"fmt"
"time"

"github.com/henomis/lingoose/transformer"
)

const (
defaultTimeoutInSeconds = 60
)

type Tool struct {
}

type Input struct {
Description string `json:"description" jsonschema:"description=the description of the image that should be created"`
}

type Output struct {
Error string `json:"error,omitempty"`
ImageURL string `json:"imageURL,omitempty"`
}

type FnPrototype func(Input) Output

func New() *Tool {
return &Tool{}
}

func (t *Tool) Name() string {
return "dalle"
}

func (t *Tool) Description() string {
return "A tool that creates an image from a description."
}

func (t *Tool) Fn() any {
return t.fn
}

func (t *Tool) fn(i Input) Output {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeoutInSeconds*time.Second)
defer cancel()

d := transformer.NewDallE().WithImageSize(transformer.DallEImageSize512x512)
imageURL, err := d.Transform(ctx, i.Description)
if err != nil {
return Output{Error: fmt.Sprintf("error creating image: %v", err)}
}

return Output{ImageURL: imageURL.(string)}
}
Loading

0 comments on commit 0a2de60

Please sign in to comment.