Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions cmd/knowledgebot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package main

import (
"context"
"log"
"log/slog"
"os"
"os/signal"
"syscall"
)
Expand All @@ -13,6 +14,7 @@ func main() {

err := rootCmd.ExecuteContext(ctx)
if err != nil {
log.Fatal("FATAL: ", err)
slog.Error(err.Error())
os.Exit(1)
}
}
37 changes: 35 additions & 2 deletions cmd/knowledgebot/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"log/slog"
"os"
"strings"

Expand All @@ -21,6 +22,7 @@ var (
)

func init() {
rootCmd.PersistentFlags().Var(logLevelFlag("INFO"), "log-level", "set the log level")
rootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
_ = cmd.Help()
return err
Expand All @@ -32,10 +34,10 @@ func Execute() error {
}

func preRunEnvVars(cmd *cobra.Command, args []string) error {
return parseFlagsWithEnvVars(cmd.Flags(), "KLB_")
return applyEnvVarsToFlags(cmd.Flags(), "KLB_")
}

func parseFlagsWithEnvVars(fs *pflag.FlagSet, envVarPrefix string) error {
func applyEnvVarsToFlags(fs *pflag.FlagSet, envVarPrefix string) error {
var err error

fs.VisitAll(func(f *pflag.Flag) {
Expand All @@ -50,3 +52,34 @@ func parseFlagsWithEnvVars(fs *pflag.FlagSet, envVarPrefix string) error {

return err
}

type logLevelFlag string

func (logLevelFlag) Set(s string) error {
var level slog.Level

switch s {
case "DEBUG":
level = slog.LevelDebug
case "INFO":
level = slog.LevelInfo
case "WARN":
level = slog.LevelWarn
case "ERROR":
level = slog.LevelError
default:
return fmt.Errorf("unsupported log level %q provided. supported log levels are DEBUG, INFO, WARN, ERROR", s)
}

slog.SetLogLoggerLevel(level)

return nil
}

func (f logLevelFlag) String() string {
return string(f)
}

func (f logLevelFlag) Type() string {
return "LEVEL"
}
6 changes: 3 additions & 3 deletions cmd/knowledgebot/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"context"
"log"
"log/slog"
"net"
"net/http"

Expand Down Expand Up @@ -101,11 +101,11 @@ func runServer(cmd *cobra.Command, args []string) error {
<-ctx.Done()
err := srv.Shutdown(ctx)
if err != nil {
log.Println("ERROR: failed to shutdown server:", err)
slog.Error("failed to shutdown server: " + err.Error())
}
}()

log.Println("listening on", srv.Addr)
slog.Info("listening on " + srv.Addr)

err := srv.ListenAndServe()
if err == http.ErrServerClosed {
Expand Down
16 changes: 8 additions & 8 deletions internal/importer/crawler/crawler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"crypto/sha256"
"encoding/hex"
"fmt"
"log"
"log/slog"
"net/url"
"regexp"
"strings"
Expand All @@ -32,7 +32,7 @@ type Crawler struct {
}

func (s *Crawler) Crawl(ctx context.Context, seedURL string) error {
log.Printf("crawling %s with maxDepth=%d, maxPages=%d and urlRegex=%s", seedURL, s.MaxDepth, s.MaxPages, s.URLRegex)
slog.Info("crawling "+seedURL, "maxDepth", s.MaxDepth, "maxPages", s.MaxPages, "urlRegex", s.URLRegex)

startTime := time.Now()

Expand Down Expand Up @@ -84,26 +84,26 @@ func (s *Crawler) crawl(ctx context.Context, seedURL *url.URL, ch chan<- []schem
}
}

log.Println("visiting", req.URL)
slog.Info("visiting " + req.URL.String())
})

c.OnResponse(func(f *colly.Response) {
err := s.processHTML(ctx, f.Request.URL, string(f.Body), ch)
if err != nil {
log.Println("WARNING:", err)
slog.Warn(err.Error())
}
})

c.OnHTML("a[href]", func(e *colly.HTMLElement) {
err := e.Request.Visit(e.Attr("href"))
if err != nil {
log.Println("ERROR: failed to visit page:", err)
slog.Debug("failed to visit page: " + err.Error())
}
})

err := c.Visit(seedURL.String())
if err != nil {
log.Println("ERROR: failed to crawl page:", err)
slog.Warn("failed to crawl page: " + err.Error())
}

c.Wait()
Expand All @@ -127,7 +127,7 @@ func (s *Crawler) processHTML(ctx context.Context, url *url.URL, html string, ch
return fmt.Errorf("split text: %w", err)
}

log.Printf("scraped %d chunks from %s", len(chunks), url)
slog.Info(fmt.Sprintf("scraped %d chunks from %s", len(chunks), url))

docs := make([]schema.Document, 0, len(chunks))

Expand Down Expand Up @@ -221,7 +221,7 @@ func (s *Crawler) indexDocumentChunks(ctx context.Context, cancel context.Cancel

elapsed := time.Since(startTime)

log.Printf("indexed %d chunks of %d document(s) in %s", chunkCount, docCount, elapsed)
slog.Info(fmt.Sprintf("indexed %d chunks of %d document(s) in %s", chunkCount, docCount, elapsed))

return ctx.Err()
}
4 changes: 2 additions & 2 deletions internal/qdrantutils/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"log"
"log/slog"
"net/http"
"net/url"
"time"
Expand Down Expand Up @@ -37,7 +37,7 @@ func CreateQdrantCollectionIfNotExist(ctx context.Context, qdrantURL, collection
}

if resp.StatusCode == http.StatusOK {
log.Printf("created qdrant collection %q", collection)
slog.Info("created qdrant collection " + collection)
return nil
}

Expand Down
8 changes: 4 additions & 4 deletions internal/qna/qnaworkflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"errors"
"fmt"
"log"
"log/slog"
"strings"

"github.com/tmc/langchaingo/llms"
Expand Down Expand Up @@ -82,7 +82,7 @@ func (w *QuestionAnswerWorkflow) Answer(ctx context.Context, question string) (<
return nil, err
}

log.Println("Requesting LLM answer for prompt:\n ", strings.ReplaceAll(prompt, "\n", "\n "))
slog.Info("Requesting LLM answer for prompt:" + strings.ReplaceAll("\n"+prompt, "\n", "\n "))

go func() {
defer close(ch)
Expand Down Expand Up @@ -124,13 +124,13 @@ func searchResultsToSourceRefs(docs []schema.Document) []SourceReference {
for _, doc := range docs {
urlKey, ok := doc.Metadata["url"].(string)
if !ok {
log.Println("WARNING: vectordb search result doc does not specify 'url' metadata key")
slog.Warn("vectordb search result doc does not specify 'url' metadata key")
continue
}

title, ok := doc.Metadata["title"].(string)
if !ok {
log.Println("WARNING: vectordb search result doc does not specify 'title' metadata key")
slog.Warn("vectordb search result doc does not specify 'title' metadata key")
continue
}

Expand Down
6 changes: 3 additions & 3 deletions internal/server/qnahandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package server
import (
"encoding/json"
"fmt"
"log"
"log/slog"
"net/http"

"github.com/mgoltzsche/knowledgebot/internal/qna"
Expand All @@ -15,7 +15,7 @@ func newQuestionAnswerHandler(ai *qna.QuestionAnswerWorkflow) http.Handler {
if question == "" {
err := req.ParseForm()
if err != nil {
log.Println("WARNING: parse form data:", err)
slog.Warn("parse form data: " + err.Error())
}

question = req.Form.Get("q")
Expand All @@ -40,7 +40,7 @@ func newQuestionAnswerHandler(ai *qna.QuestionAnswerWorkflow) http.Handler {

data, err := json.Marshal(chunk)
if err != nil {
log.Println("ERROR: failed to marshal chunk:", err)
slog.Error("failed to marshal chunk: " + err.Error())
continue
}

Expand Down