diff --git a/cmd/deepgram/deepgram.go b/cmd/deepgram/deepgram.go index 4017039..2bc260b 100644 --- a/cmd/deepgram/deepgram.go +++ b/cmd/deepgram/deepgram.go @@ -42,7 +42,7 @@ var Command = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { apiKey := viper.GetString("deepgram_api_key") if apiKey == "" { - return errors.New("Deepgram API key not found. Please run 'podscript configure' or set the PODSCRIPT_DEEPGRAM_API_KEY environment variable.") + return errors.New("Deepgram API key not found. Please run 'podscript configure' or set the DEEPGRAM_API_KEY environment variable.") } folder, _ := cmd.Flags().GetString("path") diff --git a/cmd/groq/groq.go b/cmd/groq/groq.go index 60ed78d..3da2ce8 100644 --- a/cmd/groq/groq.go +++ b/cmd/groq/groq.go @@ -112,7 +112,7 @@ var Command = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { apiKey := viper.GetString("groq_api_key") if apiKey == "" { - return errors.New("Groq API key not found. Please run 'podscript configure' or set the PODSCRIPT_GROQ_API_KEY environment variable") + return errors.New("Groq API key not found. Please run 'podscript configure' or set the GROQ_API_KEY environment variable") } folder, _ := cmd.Flags().GetString("path") diff --git a/cmd/root.go b/cmd/root.go index 33454d0..ff86de7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -21,6 +21,12 @@ var rootCmd = &cobra.Command{ Speech-To-Text (STT) APIs.`, } +var supportedLLMKeys = []string{ + "openai_api_key", + "anthropic_api_key", + "groq_api_key", +} + func init() { cobra.OnInitialize(initConfig) @@ -39,8 +45,10 @@ func initConfig() { viper.SetConfigType("toml") viper.SetConfigFile(path.Join(homeDir, ".podscript.toml")) - viper.SetEnvPrefix("PODSCRIPT") - viper.AutomaticEnv() + // Bind env values to keys + for _, k := range supportedLLMKeys { + viper.BindEnv(k) + } // Read in config file and ENV variables if set if err := viper.ReadInConfig(); err != nil { diff --git a/cmd/ytt/llms.go b/cmd/ytt/llms.go index 8eae3d0..43e8bda 100644 --- a/cmd/ytt/llms.go +++ b/cmd/ytt/llms.go @@ -1,23 +1,23 @@ package ytt import ( - "context" "errors" "fmt" - "net/http" - "time" + "unicode" - "github.com/cenkalti/backoff/v4" - "github.com/liushuangls/go-anthropic/v2" - "github.com/sashabaranov/go-openai" + "github.com/spf13/viper" + "github.com/tmc/langchaingo/llms" + "github.com/tmc/langchaingo/llms/anthropic" + "github.com/tmc/langchaingo/llms/openai" + "github.com/tmc/langchaingo/textsplitter" ) type Model string const ( - ChatGPT4o Model = openai.GPT4o - ChatGpt4oMini Model = openai.GPT4oMini - Claude3Dot5Sonnet20240620 Model = anthropic.ModelClaude3Dot5Sonnet20240620 + ChatGPT4o Model = "gpt-4o" + ChatGpt4oMini Model = "gpt-4o-mini" + Claude3Dot5Sonnet20240620 Model = "claude-3-5-sonnet-20240620" ) var ( @@ -27,118 +27,52 @@ var ( Claude3Dot5Sonnet20240620: 8192} ) -type TranscriptCleaner interface { - CleanupTranscript(string) (string, error) -} - -type OpenAITranscriptCleaner struct { - client *openai.Client - model Model -} - -type AnthropicTranscriptCleaner struct { - client *anthropic.Client -} - -func NewOpenAITranscriptCleaner(apiKey string, model Model) TranscriptCleaner { - return &OpenAITranscriptCleaner{ - client: openai.NewClient(apiKey), - model: model, +func getModel(model Model) (llms.Model, error) { + switch model { + case ChatGPT4o, ChatGpt4oMini: + openaiApiKey := viper.GetString("openai_api_key") + if openaiApiKey == "" { + return nil, errors.New("OpenAI API key not found. Please run 'podscript configure' or set the OPENAI_API_KEY environment variable") + } + return openai.New(openai.WithToken(openaiApiKey), openai.WithModel(string(model))) + case Claude3Dot5Sonnet20240620: + anthropicApiKey := viper.GetString("anthropic_api_key") + if anthropicApiKey == "" { + return nil, errors.New("Anthropic API key not found. Please run 'podscript configure' or set the ANTHROPIC_API_KEY environment variable") + } + return anthropic.New(anthropic.WithToken(anthropicApiKey), anthropic.WithModel(string(model)), anthropic.WithAnthropicBetaHeader(anthropic.MaxTokensAnthropicSonnet35)) + default: + panic(fmt.Sprintf("Invalid model %s. Should not get here!", model)) } } -func NewAnthropicTranscriptCleaner(apiKey string) TranscriptCleaner { - return &AnthropicTranscriptCleaner{ - client: anthropic.NewClient(apiKey, anthropic.WithBetaVersion(anthropic.BetaMaxTokens35Sonnet20240715)), - } +func calcWordsFromTokens(tokens int) int { + // round down to nearest 1000 + return int((float64(tokens)*0.75)/1000) * 1000 } -func (tc *OpenAITranscriptCleaner) CleanupTranscript(text string) (string, error) { - req := openai.ChatCompletionRequest{ - Model: string(tc.model), - Messages: []openai.ChatCompletionMessage{ - { - Role: openai.ChatMessageRoleUser, - Content: fmt.Sprintf(userPrompt, text), - }, - }, - MaxTokens: maxTokens[tc.model], - } - - backOff := backoff.NewExponentialBackOff() - backOff.MaxElapsedTime = 10 * time.Minute - - var resp openai.ChatCompletionResponse +func countWords(s string) int { + count := 0 + inWord := false - err := backoff.Retry(func() (err error) { - resp, err = tc.client.CreateChatCompletion(context.Background(), req) - if err != nil { - // Check if the error is a 429 (Too Many Requests) error - var openAIError *openai.APIError - if errors.As(err, &openAIError) { - if openAIError.HTTPStatusCode == http.StatusTooManyRequests { - // This is a 429 error, so we'll retry - fmt.Printf("%v\n", err) - fmt.Println("Retrying…") - return err - } - } - // For any other error, we'll stop retrying - return backoff.Permanent(err) + for _, char := range s { + if unicode.IsSpace(char) { + inWord = false + } else if !inWord { + inWord = true + count++ } - return nil - }, backOff) - - if err != nil { - return "", err - } - if len(resp.Choices) == 0 { - return "", fmt.Errorf("no choices returned from API") } - // TODO: Log this as debug output - // fmt.Printf("Usage: %+v\n", resp.Usage) - return resp.Choices[0].Message.Content, nil + return count } -func (tc *AnthropicTranscriptCleaner) CleanupTranscript(text string) (string, error) { - - req := &anthropic.MessagesRequest{ - Model: string(Claude3Dot5Sonnet20240620), - Messages: []anthropic.Message{ - anthropic.NewUserTextMessage(fmt.Sprintf(userPrompt, text)), - }, - MaxTokens: 8192, - } - - backOff := backoff.NewExponentialBackOff() - backOff.MaxElapsedTime = 10 * time.Minute - - var resp anthropic.MessagesResponse - - err := backoff.Retry(func() (err error) { - resp, err = tc.client.CreateMessages(context.Background(), *req) - if err != nil { - var anthropicAPIError *anthropic.APIError - if errors.As(err, &anthropicAPIError) { - if anthropicAPIError.IsRateLimitErr() || anthropicAPIError.IsOverloadedErr() { - fmt.Printf("%v\n", err) - fmt.Println("Retrying…") - return err - } - } - // For any other error, we'll stop retrying - return backoff.Permanent(err) - } - return nil - }, backOff) - - if err != nil { - return "", err - } - - // TODO: Log this as debug output - // fmt.Printf("Usage: %+v\n", resp.Usage) - return resp.GetFirstContentText(), nil - +func splitText(text string, model Model) ([]string, error) { + maxChunkSize := calcWordsFromTokens(maxTokens[model]) + splitter := textsplitter.NewRecursiveCharacter( + textsplitter.WithChunkSize(maxChunkSize), + textsplitter.WithChunkOverlap(0), + textsplitter.WithLenFunc(countWords), + ) + return splitter.SplitText(text) } diff --git a/cmd/ytt/ytt.go b/cmd/ytt/ytt.go index 11c4193..ab78e23 100644 --- a/cmd/ytt/ytt.go +++ b/cmd/ytt/ytt.go @@ -1,8 +1,7 @@ package ytt import ( - "bufio" - "errors" + "context" "fmt" "os" "path" @@ -12,7 +11,7 @@ import ( "github.com/kkdai/youtube/v2" "github.com/spf13/cobra" - "github.com/spf13/viper" + "github.com/tmc/langchaingo/llms" ) const ( @@ -51,35 +50,41 @@ func extractTranscript(input string) string { return "" } -func calcWordsFromTokens(tokens int) int { - // round down to nearest 1000 - return int((float64(tokens)*0.75)/1000) * 1000 +type transcriptCleaner struct { + modelOpt Model + model llms.Model } -func chunkTranscript(transcript string, maxWordsPerChunk int) []string { - // Split the transcript into chunks - var chunks []string - scanner := bufio.NewScanner(strings.NewReader(transcript)) - scanner.Split(bufio.ScanWords) - - var chunkBuilder strings.Builder - wordCount := 0 - - for scanner.Scan() { - word := scanner.Text() - chunkBuilder.WriteString(word + " ") - wordCount++ - if wordCount >= maxWordsPerChunk { - chunks = append(chunks, chunkBuilder.String()) - chunkBuilder.Reset() - wordCount = 0 - } +func newTranscriptCleaner(model Model) (*transcriptCleaner, error) { + llm, err := getModel(model) + if err != nil { + return nil, err } - if chunkBuilder.Len() > 0 { - chunks = append(chunks, chunkBuilder.String()) + return &transcriptCleaner{modelOpt: model, model: llm}, nil +} + +func (tc transcriptCleaner) cleanupTranscript(transcript string) (string, error) { + chunks, err := splitText(transcript, tc.modelOpt) + + if err != nil { + return "", fmt.Errorf("error splitting text: %w", err) } - return chunks + var cleanedTranscript strings.Builder + for i, chunk := range chunks { + cleanedChunk, err := llms.GenerateFromSinglePrompt( + context.Background(), + tc.model, userPrompt+"\n\n"+chunk, + llms.WithMaxTokens(maxTokens[tc.modelOpt]), + ) + if err != nil { + return "", fmt.Errorf("failed to process chunk: %w", err) + } + cleanedChunk = extractTranscript(cleanedChunk) + cleanedTranscript.WriteString(cleanedChunk) + fmt.Printf("transcribed part %d/%d…\n", i+1, len(chunks)) + } + return cleanedTranscript.String(), nil } var Command = &cobra.Command{ @@ -149,47 +154,20 @@ var Command = &cobra.Command{ } // Initialize API client - var ( - model Model - tc TranscriptCleaner - ) m, _ := cmd.Flags().GetString("model") - model = Model(m) - switch model { - case ChatGPT4o, ChatGpt4oMini: - openaiApiKey := viper.GetString("openai_api_key") - if openaiApiKey == "" { - return errors.New("OpenAI API key not found. Please run 'podscript configure' or set the PODSCRIPT_OPENAI_API_KEY environment variable") - } - tc = NewOpenAITranscriptCleaner(openaiApiKey, model) - - case Claude3Dot5Sonnet20240620: - anthropicApiKey := viper.GetString("anthropic_api_key") - if anthropicApiKey == "" { - return errors.New("Anthropic API key not found. Please run 'podscript configure' or set the PODSCRIPT_ANTHROPIC_API_KEY environment variable") - } - tc = NewAnthropicTranscriptCleaner(anthropicApiKey) - default: - // Should never get here - panic(fmt.Sprintf("Cannot initialise API client from model %s", model)) + model := Model(m) + tc, err := newTranscriptCleaner(model) + if err != nil { + return fmt.Errorf("failed to initialize model %s: %v", model, err) } - // Chunk and Send to LLM API - chunks := chunkTranscript(transcriptTxt, calcWordsFromTokens(maxTokens[model])) - - var cleanedTranscript strings.Builder - for i, chunk := range chunks { - cleanedChunk, err := tc.CleanupTranscript(chunk) - if err != nil { - return fmt.Errorf("failed to process chunk: %w", err) - } - cleanedChunk = extractTranscript(cleanedChunk) - cleanedTranscript.WriteString(cleanedChunk) - fmt.Printf("transcribed part %d/%d…\n", i+1, len(chunks)) + cleanedTranscriptTxt, err := tc.cleanupTranscript(transcriptTxt) + if err != nil { + return fmt.Errorf("failed to transcribe: %w", err) } cleanedTranscriptFilename := path.Join(folder, fmt.Sprintf("cleaned_transcript_%s.txt", filenameSuffix)) - if err = os.WriteFile(cleanedTranscriptFilename, []byte(cleanedTranscript.String()), 0644); err != nil { + if err = os.WriteFile(cleanedTranscriptFilename, []byte(cleanedTranscriptTxt), 0644); err != nil { return fmt.Errorf("failed to write cleaned transcript: %w", err) } fmt.Printf("wrote cleaned up transcripts to %s\n", cleanedTranscriptFilename) diff --git a/go.mod b/go.mod index 9694910..e8059d4 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,9 @@ go 1.22.4 require ( github.com/charmbracelet/huh v0.4.2 github.com/deepgram/deepgram-go-sdk v1.3.6 - github.com/liushuangls/go-anthropic/v2 v2.4.0 - github.com/sashabaranov/go-openai v1.27.0 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 + github.com/tmc/langchaingo v0.1.13-0.20240725041451-1975058648b5 ) require ( @@ -24,14 +23,20 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/schema v1.3.0 // indirect + github.com/pkoukk/tiktoken-go v0.1.6 // indirect + gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 // indirect + gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82 // indirect + gitlab.com/golang-commonmark/markdown v0.0.0-20211110145824-bf3e522c626a // indirect + gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84 // indirect + gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f // indirect k8s.io/klog/v2 v2.110.1 // indirect ) require ( github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 github.com/charmbracelet/x/ansi v0.1.2 // indirect github.com/charmbracelet/x/input v0.1.1 // indirect github.com/charmbracelet/x/term v0.1.1 // indirect diff --git a/go.sum b/go.sum index 9c112ff..2f34406 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,6 @@ github.com/bitly/go-simplejson v0.5.1 h1:xgwPbetQScXt1gh9BmoJ6j9JMr3TElvuIyjR8pg github.com/bitly/go-simplejson v0.5.1/go.mod h1:YOPVLzCfwK14b4Sff3oP1AmGhI9T9Vsg84etUnlyp+Q= github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA= github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= @@ -61,11 +59,13 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/schema v1.3.0 h1:rbciOzXAx3IB8stEFnfTwO3sYa6EWlQk79XdyustPDA= github.com/gorilla/schema v1.3.0/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -84,8 +84,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/liushuangls/go-anthropic/v2 v2.4.0 h1:OIqja8JAB5oQRLVst3fiila+6B6tsh1EJ7L1IfzrXLQ= -github.com/liushuangls/go-anthropic/v2 v2.4.0/go.mod h1:8BKv/fkeTaL5R9R9bGkaknYBueyw2WxY20o7bImbOek= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -106,6 +104,8 @@ github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkoukk/tiktoken-go v0.1.6 h1:JF0TlJzhTbrI30wCvFuiw6FzP2+/bR+FIxUdgEAcUsw= +github.com/pkoukk/tiktoken-go v0.1.6/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -115,13 +115,12 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/sashabaranov/go-openai v1.27.0 h1:L3hO6650YUbKrbGUC6yCjsUluhKZ9h1/jcgbTItI8Mo= -github.com/sashabaranov/go-openai v1.27.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -145,9 +144,23 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tmc/langchaingo v0.1.13-0.20240725041451-1975058648b5 h1:sm/byUjE0HYMSB9ihZqOJng/3tepwGkiNo52kmclMoA= +github.com/tmc/langchaingo v0.1.13-0.20240725041451-1975058648b5/go.mod h1:vjzUeUsmulZ7Hwq0Ju3Ez+ZmM5aw0dA7K7K2u7wooIw= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 h1:K+bMSIx9A7mLES1rtG+qKduLIXq40DAzYHtb0XuCukA= +gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181/go.mod h1:dzYhVIwWCtzPAa4QP98wfB9+mzt33MSmM8wsKiMi2ow= +gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82 h1:oYrL81N608MLZhma3ruL8qTM4xcpYECGut8KSxRY59g= +gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8= +gitlab.com/golang-commonmark/markdown v0.0.0-20211110145824-bf3e522c626a h1:O85GKETcmnCNAfv4Aym9tepU8OE0NmcZNqPlXcsBKBs= +gitlab.com/golang-commonmark/markdown v0.0.0-20211110145824-bf3e522c626a/go.mod h1:LaSIs30YPGs1H5jwGgPhLzc8vkNc/k0rDX/fEZqiU/M= +gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84 h1:qqjvoVXdWIcZCLPMlzgA7P9FZWdPGPvP/l3ef8GzV6o= +gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84/go.mod h1:IJZ+fdMvbW2qW6htJx7sLJ04FEs4Ldl/MDsJtMKywfw= +gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI= +gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs= +gitlab.com/opennota/wd v0.0.0-20180912061657-c5d65f63c638 h1:uPZaMiz6Sz0PZs3IZJWpU5qHKGNy///1pacZC9txiUI= +gitlab.com/opennota/wd v0.0.0-20180912061657-c5d65f63c638/go.mod h1:EGRJaqe2eO9XGmFtQCvV3Lm9NLico3UhFwUpCG/+mVU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -158,8 +171,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= @@ -177,6 +190,7 @@ golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -201,3 +215,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=