use yaml and make debug files easier

This commit is contained in:
Moby von Briesen 2023-09-03 20:10:10 -04:00
parent c76d1a3583
commit 322fc8d1da
9 changed files with 98 additions and 64 deletions

2
go.mod
View File

@ -11,6 +11,7 @@ require (
github.com/stretchr/testify v1.8.1
go.uber.org/zap v1.24.0
golang.org/x/oauth2 v0.7.0
gopkg.in/yaml.v3 v3.0.1
)
require (
@ -53,5 +54,4 @@ require (
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@ -2,8 +2,8 @@ package llm
// File represents a file in a git repository.
type File struct {
Path string `json:"path"`
Contents string `json:"contents"`
Path string `yaml:"path"`
Contents string `yaml:"contents"`
}
type ResponseType int
@ -24,8 +24,8 @@ type CodeChangeRequest struct {
// CodeChangeResponse contains data derived from an LLM response to a prompt generated via a CodeChangeRequest.
type CodeChangeResponse struct {
Files []File `json:"files"`
Notes string `json:"notes"`
Files []File `yaml:"files"`
Notes string `yaml:"notes"`
}
// TODO support threads
@ -37,7 +37,7 @@ type DiffCommentRequest struct {
}
type DiffCommentResponse struct {
Type ResponseType `json:"responseType"`
Response string `json:"response"`
File File `json:"file"`
Type ResponseType `yaml:"responseType"`
Response string `yaml:"response"`
File File `yaml:"file"`
}

View File

@ -2,8 +2,9 @@ package llm
import (
"bytes"
"encoding/json"
"text/template"
"gopkg.in/yaml.v3"
)
func (req DiffCommentRequest) String() string {
@ -57,6 +58,6 @@ func (res DiffCommentResponse) String() string {
func ParseDiffCommentResponse(llmResponse string) (DiffCommentResponse, error) {
var response DiffCommentResponse
err := json.Unmarshal([]byte(llmResponse), &response)
err := yaml.Unmarshal([]byte(llmResponse), &response)
return response, err
}

View File

@ -2,8 +2,9 @@ package llm
import (
"bytes"
"encoding/json"
"text/template"
"gopkg.in/yaml.v3"
)
// String is the string representation of a CodeChangeRequest. Functionally, it contains the LLM prompt.
@ -52,6 +53,6 @@ func (res CodeChangeResponse) String() string {
// ParseCodeChangeResponse parses the LLM's response to CodeChangeRequest (string) into a CodeChangeResponse.
func ParseCodeChangeResponse(llmResponse string) (CodeChangeResponse, error) {
var response CodeChangeResponse
err := json.Unmarshal([]byte(llmResponse), &response)
err := yaml.Unmarshal([]byte(llmResponse), &response)
return response, err
}

View File

@ -52,21 +52,10 @@ func (oc *OpenAIClient) EvaluateCCR(ctx context.Context, model string, req CodeC
choice := resp.Choices[0].Message.Content
oc.log.Info("got response from llm")
if oc.debugDir != "" {
subdir := path.Join(oc.debugDir, "codechangeresponse")
err = os.MkdirAll(subdir, os.ModePerm)
if err != nil {
oc.log.Error("failed to ensure debug directory existed", zap.String("filepath", subdir), zap.Error(err))
} else {
fullPath := path.Join(subdir, fmt.Sprintf("%d-%d.json", req.IssueNumber, time.Now().Unix()))
err = ioutil.WriteFile(fullPath, []byte(choice), 0644)
if err != nil {
oc.log.Error("failed to write response to debug file", zap.String("filepath", fullPath), zap.Error(err))
} else {
oc.log.Info("response written to debug file", zap.String("filepath", fullPath))
}
}
}
debugFilePrefix := fmt.Sprintf("%d-%d", req.IssueNumber, time.Now().Unix())
oc.writeDebug("codechangeresponse", debugFilePrefix+"-req.txt", req.String())
oc.writeDebug("codechangeresponse", debugFilePrefix+"-res.yaml", choice)
return ParseCodeChangeResponse(choice)
}
@ -95,22 +84,32 @@ func (oc *OpenAIClient) EvaluateDiffComment(ctx context.Context, model string, r
choice := resp.Choices[0].Message.Content
oc.log.Info("got response from llm", zap.String("output", choice))
// TODO
if oc.debugDir != "" {
subdir := path.Join(oc.debugDir, "diffcommentresponse")
err = os.MkdirAll(subdir, os.ModePerm)
if err != nil {
oc.log.Error("failed to ensure debug directory existed", zap.String("filepath", subdir), zap.Error(err))
} else {
fullPath := path.Join(subdir, fmt.Sprintf("%d-%d.json", req.PRNumber, time.Now().Unix()))
err = ioutil.WriteFile(fullPath, []byte(choice), 0644)
if err != nil {
oc.log.Error("failed to write response to debug file", zap.String("filepath", fullPath), zap.Error(err))
} else {
oc.log.Info("response written to debug file", zap.String("filepath", fullPath))
}
}
}
debugFilePrefix := fmt.Sprintf("%d-%d", req.PRNumber, time.Now().Unix())
oc.writeDebug("diffcommentresponse", debugFilePrefix+"-req.txt", req.String())
oc.writeDebug("diffcommentresponse", debugFilePrefix+"-res.yaml", choice)
return ParseDiffCommentResponse(choice)
}
func (oc *OpenAIClient) writeDebug(subdir, filename, contents string) {
if oc.debugDir == "" {
return
}
fullFolderPath := path.Join(oc.debugDir, subdir)
err := os.MkdirAll(fullFolderPath, os.ModePerm)
if err != nil {
oc.log.Error("failed to ensure debug directory existed", zap.String("folderpath", fullFolderPath), zap.Error(err))
return
}
fullPath := path.Join(fullFolderPath, filename)
err = ioutil.WriteFile(fullPath, []byte(contents), 0644)
if err != nil {
oc.log.Error("failed to write response to debug file", zap.String("filepath", fullPath), zap.Error(err))
return
}
oc.log.Info("response written to debug file", zap.String("filepath", fullPath))
}

View File

@ -12,14 +12,13 @@ Subject: {{ .Subject }}
Body:
{{ .Body }}
Respond in a parseable JSON format based on the following template:
```
{
"files": [
Respond in a parseable YAML format based on the following template. Respond only with YAML, and nothing else:
files:
{{ range $index, $file := .Files }}
{"path": "{{ $file.Path }}", "contents": "[new {{ $file.Path }} contents]"},
-
path: {{ $file.Path }}
contents: |
[new {{ $file.Path }} contents]
{{ end }}
],
"notes": "[additional context about your changes]"
}
```
notes: |
[additional context about your changes]

View File

@ -82,7 +82,7 @@ func NewPullPal(ctx context.Context, log *zap.Logger, cfg Config) (*PullPal, err
if err != nil {
return nil, err
}
localGitClient, err := vc.NewLocalGitClient(log.Named("gitclient-"+r), cfg.Self, newRepo)
localGitClient, err := vc.NewLocalGitClient(log.Named("gitclient-"+r), cfg.Self, newRepo, cfg.DebugDir)
if err != nil {
return nil, err
}
@ -188,11 +188,13 @@ func (p pullPalRepo) checkIssuesAndComments() error {
}
func (p *pullPalRepo) handleIssue(issue vc.Issue) error {
err := p.ghClient.CommentOnIssue(issue.Number, "working on it")
if err != nil {
p.log.Error("error commenting on issue", zap.Error(err))
return err
}
/*
err := p.ghClient.CommentOnIssue(issue.Number, "working on it")
if err != nil {
p.log.Error("error commenting on issue", zap.Error(err))
return err
}
*/
for _, label := range p.listIssueOptions.Labels {
err = p.ghClient.RemoveLabelFromIssue(issue.Number, label)
if err != nil {

View File

@ -93,6 +93,7 @@ func ParseIssueBody(body string) IssueBody {
issueBody := IssueBody{
BaseBranch: "main",
}
// TODO get rid of parsing like this - "---" may occur in the normal issue body
divider := "---"
parts := strings.Split(body, divider)

View File

@ -6,6 +6,7 @@ import (
"go/format"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"time"
@ -27,10 +28,11 @@ type LocalGitClient struct {
repo Repository
worktree *git.Worktree
debugDir string
}
// NewLocalGitClient initializes a local git client by checking out a repository locally.
func NewLocalGitClient(log *zap.Logger, self Author, repo Repository) (*LocalGitClient, error) {
func NewLocalGitClient(log *zap.Logger, self Author, repo Repository, debugDir string) (*LocalGitClient, error) {
log.Info("checking out local github repo", zap.String("repo name", repo.Name), zap.String("local path", repo.LocalPath))
// clone provided repository to local path
if repo.LocalPath == "" {
@ -57,9 +59,10 @@ func NewLocalGitClient(log *zap.Logger, self Author, repo Repository) (*LocalGit
repo.localRepo = localRepo
return &LocalGitClient{
log: log,
self: self,
repo: repo,
log: log,
self: self,
repo: repo,
debugDir: debugDir,
}, nil
}
@ -239,6 +242,7 @@ func (gc *LocalGitClient) ParseIssueAndStartCommit(issue Issue) (llm.CodeChangeR
}
issueBody := ParseIssueBody(issue.Body)
gc.log.Info("issue body info", zap.Any("files", issueBody.FilePaths))
// start a worktree
err := gc.StartCommit()
@ -264,11 +268,38 @@ func (gc *LocalGitClient) ParseIssueAndStartCommit(issue Issue) (llm.CodeChangeR
files = append(files, nextFile)
}
return llm.CodeChangeRequest{
req := llm.CodeChangeRequest{
Subject: issue.Subject,
Body: issueBody.PromptBody,
IssueNumber: issue.Number,
Files: files,
BaseBranch: issueBody.BaseBranch,
}, nil
}
debugFileNamePrefix := fmt.Sprintf("issue-%d-%d", issue.Number, time.Now().Unix())
gc.writeDebug("issues", debugFileNamePrefix+"-originalbody.txt", issue.Body)
gc.writeDebug("issues", debugFileNamePrefix+"-parsed-req.txt", req.String())
return req, nil
}
func (gc *LocalGitClient) writeDebug(subdir, filename, contents string) {
if gc.debugDir == "" {
return
}
fullFolderPath := path.Join(gc.debugDir, subdir)
err := os.MkdirAll(fullFolderPath, os.ModePerm)
if err != nil {
gc.log.Error("failed to ensure debug directory existed", zap.String("folderpath", fullFolderPath), zap.Error(err))
return
}
fullPath := path.Join(fullFolderPath, filename)
err = ioutil.WriteFile(fullPath, []byte(contents), 0644)
if err != nil {
gc.log.Error("failed to write response to debug file", zap.String("filepath", fullPath), zap.Error(err))
return
}
gc.log.Info("response written to debug file", zap.String("filepath", fullPath))
}