Skip to content

Commit 89bdf64

Browse files
committed
feat: simple search tool for internal testing #52
1 parent 15bb593 commit 89bdf64

2 files changed

Lines changed: 136 additions & 0 deletions

File tree

examples/agents/search/main.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"time"
8+
9+
"github.com/bit8bytes/beago/agents"
10+
"github.com/bit8bytes/beago/llms/ollama"
11+
"github.com/bit8bytes/beago/runner"
12+
"github.com/bit8bytes/beago/stores/memory"
13+
"github.com/bit8bytes/beago/tools"
14+
)
15+
16+
func main() {
17+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*120)
18+
defer cancel()
19+
20+
storage := memory.New()
21+
defer storage.Close()
22+
23+
model := ollama.New(ollama.Model{
24+
Model: "gemma3:12b",
25+
Options: ollama.Options{NumCtx: 4096},
26+
Stream: false,
27+
Format: ollama.JSON,
28+
})
29+
30+
tools := []tools.Tool{&tools.Search{}}
31+
32+
agent, err := agents.NewReAct(ctx, model, tools, storage)
33+
if err != nil {
34+
panic(err)
35+
}
36+
37+
// The llm will use the search tool to fetch the content of the page and extract the arguments if any.
38+
// The search tool is currently just for testing and needs to be remodeled to be production ready.
39+
task := "Fetch https://httpbin.org/get?q=lorem+ipsum and tell me what arguments the response contains."
40+
if err := agent.Task(ctx, task); err != nil {
41+
panic(err)
42+
}
43+
44+
r := runner.New(agent)
45+
46+
res, err := r.Run(ctx)
47+
if err != nil {
48+
switch {
49+
case errors.Is(err, runner.ErrNoFinalAnswer):
50+
fmt.Println("No final answer found")
51+
default:
52+
panic(err)
53+
}
54+
return
55+
}
56+
57+
fmt.Println(res)
58+
}

tools/search.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package tools
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"html"
8+
"io"
9+
"net/http"
10+
"regexp"
11+
"strings"
12+
)
13+
14+
var (
15+
scriptRx = regexp.MustCompile(`(?is)<script[^>]*>.*?</script>`)
16+
styleRx = regexp.MustCompile(`(?is)<style[^>]*>.*?</style>`)
17+
tagsRx = regexp.MustCompile(`<[^>]+>`)
18+
spaceRx = regexp.MustCompile(`\s+`)
19+
)
20+
21+
// Search is a tool for performing simple web searches.
22+
// Its currently not production ready and is only used for testing.
23+
type Search struct{}
24+
25+
func (s *Search) Name() string {
26+
return "search"
27+
}
28+
29+
func (s *Search) Description() string {
30+
return "A tool for performing web searches. Use this tool to crawl and extract information from web pages."
31+
}
32+
33+
func (s *Search) Parameters() []Parameter {
34+
return []Parameter{
35+
{
36+
Name: "url",
37+
Description: "URL to search. This should be a valid URL string.",
38+
Required: true,
39+
},
40+
}
41+
}
42+
43+
func (s *Search) Execute(ctx context.Context, params json.RawMessage) (string, error) {
44+
var input struct {
45+
URL string `json:"url"`
46+
}
47+
if err := json.Unmarshal(params, &input); err != nil {
48+
return "", fmt.Errorf("search invalid params: %w", err)
49+
}
50+
51+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, input.URL, nil)
52+
if err != nil {
53+
return "", fmt.Errorf("failed to create request: %w", err)
54+
}
55+
56+
resp, err := http.DefaultClient.Do(req)
57+
if err != nil {
58+
return "", fmt.Errorf("failed with error: %w", err)
59+
}
60+
defer resp.Body.Close()
61+
62+
b, err := io.ReadAll(resp.Body)
63+
if err != nil {
64+
return "", fmt.Errorf("failed to read response body: %w", err)
65+
}
66+
67+
// Pragmatically extract text from HTML responses.
68+
// This is not a robust solution and requires more work to be production ready.
69+
text := string(b)
70+
text = scriptRx.ReplaceAllString(text, " ")
71+
text = styleRx.ReplaceAllString(text, " ")
72+
text = tagsRx.ReplaceAllString(text, " ")
73+
text = html.UnescapeString(text)
74+
text = spaceRx.ReplaceAllString(text, " ")
75+
text = strings.TrimSpace(text)
76+
77+
return text, nil
78+
}

0 commit comments

Comments
 (0)