Skip to content

Commit faf3f28

Browse files
committed
Refactor AI functions, add commit command
1 parent b4de1ac commit faf3f28

File tree

14 files changed

+175
-38
lines changed

14 files changed

+175
-38
lines changed

cmd/ask.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ Requires a path to a repository or file as a positional argument.`,
105105
os.Exit(1)
106106
}
107107

108-
resp, err := ai.Question(fileName, content, chatPrompt, conf.APIKey, conf.Model)
108+
resp, err := ai.Question(fileName, content, chatPrompt, conf)
109109

110110
if err != nil {
111111
log.Errorf("Error asking question: %s", err)

cmd/cmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ This command is only supported on MacOS and Linux using Bash or Zsh. Windows and
4444

4545
// fmt.Println("History:", history)
4646

47-
resp, err := ai.CmdQuestion(history, chatPrompt, conf.APIKey, conf.Model)
47+
resp, err := ai.CmdQuestion(history, chatPrompt, conf)
4848

4949
if err != nil {
5050
log.Error(err)

cmd/commit.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright © 2023 Chandler <chandler@chand1012.dev>
3+
*/
4+
package cmd
5+
6+
import (
7+
"fmt"
8+
"os"
9+
"os/exec"
10+
11+
"github.com/chand1012/ottodocs/pkg/ai"
12+
"github.com/chand1012/ottodocs/pkg/config"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
// commitCmd represents the commit command
17+
var commitCmd = &cobra.Command{
18+
Use: "commit",
19+
Short: "Generates a commit message from the git diff",
20+
Long: `Uses the git diff to generate a commit message. Requires Git to be installed on the system.`,
21+
Run: func(cmd *cobra.Command, args []string) {
22+
conf, err := config.Load()
23+
if err != nil || conf.APIKey == "" {
24+
// if the API key is not set, prompt the user to login
25+
log.Error("Please login first.")
26+
log.Error("Run `ottodocs login` to login.")
27+
os.Exit(1)
28+
}
29+
30+
c := exec.Command("git", "diff")
31+
diffBytes, err := c.Output()
32+
if err != nil {
33+
log.Error(err)
34+
os.Exit(1)
35+
}
36+
37+
diff := string(diffBytes)
38+
39+
msg, err := ai.CommitMessage(diff, conventional, conf)
40+
if err != nil {
41+
log.Error(err)
42+
os.Exit(1)
43+
}
44+
45+
fmt.Println("Commit message:", msg)
46+
},
47+
}
48+
49+
func init() {
50+
RootCmd.AddCommand(commitCmd)
51+
52+
// Here you will define your flags and configuration settings.
53+
54+
// Cobra supports Persistent Flags which will work for this command
55+
// and all subcommands, e.g.:
56+
// commitCmd.PersistentFlags().String("foo", "", "A help for foo")
57+
58+
// Cobra supports local flags which will only run when this command
59+
// is called directly, e.g.:
60+
commitCmd.Flags().BoolVarP(&conventional, "conventional", "c", false, "use conventional commits")
61+
}

cmd/docs.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ search for files in the directory and document them. If a single file is specifi
8989
}
9090

9191
if inlineMode || !markdownMode {
92-
contents, err = ai.SingleFile(path, fileContents, chatPrompt, conf.APIKey, conf.Model)
92+
contents, err = ai.SingleFile(path, fileContents, chatPrompt, conf)
9393
} else {
94-
contents, err = ai.Markdown(path, fileContents, chatPrompt, conf.APIKey, conf.Model)
94+
contents, err = ai.Markdown(path, fileContents, chatPrompt, conf)
9595
}
9696

9797
if err != nil {
@@ -152,9 +152,9 @@ search for files in the directory and document them. If a single file is specifi
152152
}
153153

154154
if inlineMode || !markdownMode {
155-
contents, err = ai.SingleFile(filePath, fileContents, chatPrompt, conf.APIKey, conf.Model)
155+
contents, err = ai.SingleFile(filePath, fileContents, chatPrompt, conf)
156156
} else {
157-
contents, err = ai.Markdown(filePath, fileContents, chatPrompt, conf.APIKey, conf.Model)
157+
contents, err = ai.Markdown(filePath, fileContents, chatPrompt, conf)
158158
}
159159

160160
if err != nil {

cmd/vars.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ var inlineMode bool
2020
var markdownMode bool
2121
var overwriteOriginal bool
2222

23+
var conventional bool // use conventional commits
24+
2325
var log = l.NewWithOptions(os.Stderr, l.Options{
2426
Level: l.InfoLevel,
2527
ReportTimestamp: false,

pkg/ai/cmd_question.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import (
66
gopenai "github.com/CasualCodersProjects/gopenai"
77
ai_types "github.com/CasualCodersProjects/gopenai/types"
88
"github.com/chand1012/ottodocs/pkg/calc"
9+
"github.com/chand1012/ottodocs/pkg/config"
910
"github.com/chand1012/ottodocs/pkg/constants"
1011
)
1112

12-
func CmdQuestion(history []string, chatPrompt, APIKey, model string) (string, error) {
13+
func CmdQuestion(history []string, chatPrompt string, conf *config.Config) (string, error) {
1314
openai := gopenai.NewOpenAI(&gopenai.OpenAIOpts{
14-
APIKey: APIKey,
15+
APIKey: conf.APIKey,
1516
})
1617

1718
questionNoHistory := "\nQuestion: " + chatPrompt + "\n\nAnswer:"
@@ -24,7 +25,7 @@ func CmdQuestion(history []string, chatPrompt, APIKey, model string) (string, er
2425
for i := len(history) - 1; i >= 0; i-- {
2526
newHistory := history[i] + "\n"
2627
tokens := calc.EstimateTokens(newHistory) + qTokens + calc.EstimateTokens(historyQuestion) + commandPromptTokens
27-
if tokens < constants.OPENAI_MAX_TOKENS {
28+
if tokens < calc.GetMaxTokens(conf.Model) {
2829
historyQuestion += newHistory
2930
} else {
3031
break
@@ -48,16 +49,16 @@ func CmdQuestion(history []string, chatPrompt, APIKey, model string) (string, er
4849

4950
tokens := calc.EstimateTokens(messages[0].Content, messages[1].Content)
5051

51-
maxTokens := constants.OPENAI_MAX_TOKENS - tokens
52+
maxTokens := calc.GetMaxTokens(conf.Model) - tokens
5253

5354
if maxTokens < 0 {
54-
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", constants.OPENAI_MAX_TOKENS, tokens)
55+
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", calc.GetMaxTokens(conf.Model), tokens)
5556
}
5657

5758
req := ai_types.NewDefaultChatRequest("")
5859
req.Messages = messages
5960
req.MaxTokens = maxTokens
60-
req.Model = model
61+
req.Model = conf.Model
6162
// lower the temperature to make the model more deterministic
6263
// req.Temperature = 0.3
6364

pkg/ai/commit.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package ai
2+
3+
import (
4+
"fmt"
5+
6+
gopenai "github.com/CasualCodersProjects/gopenai"
7+
ai_types "github.com/CasualCodersProjects/gopenai/types"
8+
"github.com/chand1012/ottodocs/pkg/calc"
9+
"github.com/chand1012/ottodocs/pkg/config"
10+
"github.com/chand1012/ottodocs/pkg/constants"
11+
)
12+
13+
func CommitMessage(diff string, conventional bool, conf *config.Config) (string, error) {
14+
openai := gopenai.NewOpenAI(&gopenai.OpenAIOpts{
15+
APIKey: conf.APIKey,
16+
})
17+
18+
sysMessage := constants.GIT_DIFF_PROMPT_STD
19+
if conventional {
20+
sysMessage = constants.GIT_DIFF_PROMPT_CONVENTIONAL
21+
}
22+
23+
messages := []ai_types.ChatMessage{
24+
{
25+
Content: sysMessage,
26+
Role: "system",
27+
},
28+
{
29+
Content: diff,
30+
Role: "user",
31+
},
32+
}
33+
34+
tokens, err := calc.PreciseTokens(messages[0].Content, messages[1].Content)
35+
if err != nil {
36+
return "", fmt.Errorf("could not calculate tokens: %s", err)
37+
}
38+
39+
maxTokens := calc.GetMaxTokens(conf.Model) - tokens
40+
41+
if maxTokens < 0 {
42+
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", calc.GetMaxTokens(conf.Model), tokens)
43+
}
44+
45+
req := ai_types.NewDefaultChatRequest("")
46+
req.Messages = messages
47+
req.MaxTokens = maxTokens
48+
req.Model = conf.Model
49+
50+
resp, err := openai.CreateChat(req)
51+
if err != nil {
52+
return "", err
53+
}
54+
55+
message := resp.Choices[0].Message.Content
56+
57+
return message, nil
58+
}

pkg/ai/markdown.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import (
77
gopenai "github.com/CasualCodersProjects/gopenai"
88
ai_types "github.com/CasualCodersProjects/gopenai/types"
99
"github.com/chand1012/ottodocs/pkg/calc"
10+
"github.com/chand1012/ottodocs/pkg/config"
1011
"github.com/chand1012/ottodocs/pkg/constants"
1112
)
1213

13-
func Markdown(filePath, contents, chatPrompt, APIKey, model string) (string, error) {
14+
func Markdown(filePath, contents, chatPrompt string, conf *config.Config) (string, error) {
1415
openai := gopenai.NewOpenAI(&gopenai.OpenAIOpts{
15-
APIKey: APIKey,
16+
APIKey: conf.APIKey,
1617
})
1718

1819
question := chatPrompt + "\n\n" + strings.TrimRight(contents, " \n")
@@ -33,16 +34,16 @@ func Markdown(filePath, contents, chatPrompt, APIKey, model string) (string, err
3334
return "", fmt.Errorf("could not calculate tokens: %s", err)
3435
}
3536

36-
maxTokens := constants.OPENAI_MAX_TOKENS - tokens
37+
maxTokens := calc.GetMaxTokens(conf.Model) - tokens
3738

3839
if maxTokens < 0 {
39-
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", constants.OPENAI_MAX_TOKENS, tokens)
40+
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", calc.GetMaxTokens(conf.Model), tokens)
4041
}
4142

4243
req := ai_types.NewDefaultChatRequest("")
4344
req.Messages = messages
4445
req.MaxTokens = maxTokens
45-
req.Model = model
46+
req.Model = conf.Model
4647
// lower the temperature to make the model more deterministic
4748
// req.Temperature = 0.3
4849

pkg/ai/question.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import (
77
gopenai "github.com/CasualCodersProjects/gopenai"
88
ai_types "github.com/CasualCodersProjects/gopenai/types"
99
"github.com/chand1012/ottodocs/pkg/calc"
10+
"github.com/chand1012/ottodocs/pkg/config"
1011
"github.com/chand1012/ottodocs/pkg/constants"
1112
)
1213

13-
func Question(filePath, fileContent, chatPrompt, APIKey, model string) (string, error) {
14+
func Question(filePath, fileContent, chatPrompt string, conf *config.Config) (string, error) {
1415
openai := gopenai.NewOpenAI(&gopenai.OpenAIOpts{
15-
APIKey: APIKey,
16+
APIKey: conf.APIKey,
1617
})
1718

1819
question := "File Name: " + filePath + "\nQuestion: " + chatPrompt + "\n\n" + strings.TrimRight(string(fileContent), " \n") + "\nAnswer:"
@@ -33,16 +34,16 @@ func Question(filePath, fileContent, chatPrompt, APIKey, model string) (string,
3334
return "", fmt.Errorf("could not calculate tokens: %s", err)
3435
}
3536

36-
maxTokens := constants.OPENAI_MAX_TOKENS - tokens
37+
maxTokens := calc.GetMaxTokens(conf.Model) - tokens
3738

3839
if maxTokens < 0 {
39-
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", constants.OPENAI_MAX_TOKENS, tokens)
40+
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", calc.GetMaxTokens(conf.Model), tokens)
4041
}
4142

4243
req := ai_types.NewDefaultChatRequest("")
4344
req.Messages = messages
4445
req.MaxTokens = maxTokens
45-
req.Model = model
46+
req.Model = conf.Model
4647
// lower the temperature to make the model more deterministic
4748
// req.Temperature = 0.3
4849

pkg/ai/single_file.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
ai_types "github.com/CasualCodersProjects/gopenai/types"
1111

1212
"github.com/chand1012/ottodocs/pkg/calc"
13+
"github.com/chand1012/ottodocs/pkg/config"
1314
"github.com/chand1012/ottodocs/pkg/constants"
1415
"github.com/chand1012/ottodocs/pkg/textfile"
1516
)
@@ -35,10 +36,10 @@ func extractLineNumber(line string) (int, error) {
3536
}
3637

3738
// Document a file using the OpenAI ChatGPT API. Takes a file path, a prompt, and an API key as arguments.
38-
func SingleFile(filePath, contents, chatPrompt, APIKey, model string) (string, error) {
39+
func SingleFile(filePath, contents, chatPrompt string, conf *config.Config) (string, error) {
3940

4041
openai := gopenai.NewOpenAI(&gopenai.OpenAIOpts{
41-
APIKey: APIKey,
42+
APIKey: conf.APIKey,
4243
})
4344

4445
fileEnding := filepath.Ext(filePath)
@@ -66,16 +67,16 @@ func SingleFile(filePath, contents, chatPrompt, APIKey, model string) (string, e
6667
return "", fmt.Errorf("could not calculate tokens: %s", err)
6768
}
6869

69-
maxTokens := constants.OPENAI_MAX_TOKENS - tokens
70+
maxTokens := calc.GetMaxTokens(conf.Model) - tokens
7071

7172
if maxTokens < 0 {
72-
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", constants.OPENAI_MAX_TOKENS, tokens)
73+
return "", fmt.Errorf("the prompt is too long. max length is %d. Got %d", calc.GetMaxTokens(conf.Model), tokens)
7374
}
7475

7576
req := ai_types.NewDefaultChatRequest("")
7677
req.Messages = messages
7778
req.MaxTokens = maxTokens
78-
req.Model = model
79+
req.Model = conf.Model
7980
// lower the temperature to make the model more deterministic
8081
req.Temperature = 0.3
8182

0 commit comments

Comments
 (0)