2026-01-26 20:29:04 +00:00
|
|
|
package llm
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2026-03-18 18:56:51 +00:00
|
|
|
"errors"
|
2026-01-26 20:29:04 +00:00
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"github.com/maruel/genai"
|
|
|
|
|
"github.com/maruel/genai/adapters"
|
|
|
|
|
"github.com/maruel/genai/providers/openaichat"
|
2026-01-27 18:44:02 +00:00
|
|
|
"github.com/rs/zerolog"
|
2026-01-26 20:29:04 +00:00
|
|
|
)
|
|
|
|
|
|
2026-01-27 18:44:02 +00:00
|
|
|
func CreateOpenAIClient(ctx context.Context, logger *zerolog.Logger) error {
|
|
|
|
|
linkLogger(logger)
|
2026-01-26 20:29:04 +00:00
|
|
|
|
|
|
|
|
opts := genai.ProviderOptions{
|
|
|
|
|
Model: genai.ModelCheap,
|
|
|
|
|
}
|
|
|
|
|
c, err := openaichat.New(ctx, &opts, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to create genai client: %v", err)
|
|
|
|
|
}
|
|
|
|
|
client = &openAIClient{
|
|
|
|
|
client: c,
|
|
|
|
|
conversations: make(map[string][]genai.Message),
|
|
|
|
|
log: logger,
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-27 14:29:55 +00:00
|
|
|
type openAIClient struct {
|
|
|
|
|
client *openaichat.Client
|
|
|
|
|
conversations map[string][]genai.Message
|
|
|
|
|
log *Logger
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-27 18:44:02 +00:00
|
|
|
type ContactSupervisorInput struct {
|
|
|
|
|
Reason string `json:"reason"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ContactDistrictInput struct {
|
|
|
|
|
Reason string `json:"reason"`
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-27 14:29:55 +00:00
|
|
|
type QueryReportStatusInput struct {
|
|
|
|
|
ReportID string `json:"report_id"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var client *openAIClient
|
2026-01-26 20:29:04 +00:00
|
|
|
|
2026-01-27 18:44:02 +00:00
|
|
|
func (c *openAIClient) continueConversation(ctx context.Context, tools genai.OptionsTools, msg genai.Message) (Message, error) {
|
2026-03-18 18:56:51 +00:00
|
|
|
if c.client == nil {
|
|
|
|
|
return Message{}, errors.New("Client not initialized")
|
|
|
|
|
}
|
2026-01-27 18:44:02 +00:00
|
|
|
res, _, err := adapters.GenSyncWithToolCallLoop(ctx, c.client, genai.Messages{msg}, &tools)
|
2026-01-26 20:29:04 +00:00
|
|
|
if err != nil {
|
2026-01-27 14:29:55 +00:00
|
|
|
return Message{}, fmt.Errorf("Failed to continue conversation: %v", err)
|
2026-01-26 20:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, m := range res {
|
|
|
|
|
// Empty responses are tool call related.
|
|
|
|
|
if m.String() == "" {
|
2026-01-27 18:44:02 +00:00
|
|
|
//log.Debug().Msg("Tool called")
|
2026-01-26 20:29:04 +00:00
|
|
|
} else {
|
|
|
|
|
var toSay string = m.String()
|
2026-01-27 14:29:55 +00:00
|
|
|
toSay = strings.Replace(toSay, "report-mosquitoes-online: ", "", 1)
|
|
|
|
|
return Message{
|
|
|
|
|
Content: toSay,
|
|
|
|
|
IsFromCustomer: false,
|
|
|
|
|
}, nil
|
2026-01-26 20:29:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-27 14:29:55 +00:00
|
|
|
return Message{}, nil
|
2026-01-26 20:29:04 +00:00
|
|
|
}
|