From 4f47502ca832c7b88223f662ccae97823d390de7 Mon Sep 17 00:00:00 2001 From: ahaostudy <1993584108@qq.com> Date: Tue, 26 Dec 2023 20:34:50 +0800 Subject: [PATCH] feat: support custom breakpoints --- bigmodel/bigmodel.go | 2 +- bigmodel/chatgpt.go | 6 ++--- diagnostic/diagnostic.go | 52 +++++++++++++++++++++------------------- example/main.go | 24 ++++++++++++------- example/math/math.go | 9 +++++++ 5 files changed, 56 insertions(+), 37 deletions(-) diff --git a/bigmodel/bigmodel.go b/bigmodel/bigmodel.go index aec0f13..3613b83 100644 --- a/bigmodel/bigmodel.go +++ b/bigmodel/bigmodel.go @@ -22,7 +22,7 @@ package bigmodel // BigModel interface type BigModel interface { // Chat Receive a query for large model calls and write the output results to the Result channel in real time - Chat(query string) chan Result + Chat(string) chan Result } type Result struct { diff --git a/bigmodel/chatgpt.go b/bigmodel/chatgpt.go index 0df0f27..3e95eee 100644 --- a/bigmodel/chatgpt.go +++ b/bigmodel/chatgpt.go @@ -75,7 +75,7 @@ type chunk struct { } `json:"choices"` } -func (gpt *ChatGPT) Chat(query string) chan Result { +func (gpt *ChatGPT) Chat(prompt string) chan Result { out := make(chan Result) go func() { @@ -86,7 +86,7 @@ func (gpt *ChatGPT) Chat(query string) chan Result { "messages": []map[string]string{ { "role": "user", - "content": query, + "content": prompt, }, }, }) @@ -104,7 +104,7 @@ func (gpt *ChatGPT) Chat(query string) chan Result { // TODO: response status exception // read response stream data - buf := make([]byte, 1024) + buf := make([]byte, 4096) var chunks, tmp string for { n, err := resp.Body.Read(buf) diff --git a/diagnostic/diagnostic.go b/diagnostic/diagnostic.go index f0c34f6..771c288 100644 --- a/diagnostic/diagnostic.go +++ b/diagnostic/diagnostic.go @@ -21,13 +21,12 @@ package diagnostic import ( "fmt" + "github.com/ahaostudy/code-diagnostic/bigmodel" "log" "os" "runtime" "runtime/debug" "strings" - - "github.com/ahaostudy/code-diagnostic/bigmodel" ) const ( @@ -69,38 +68,36 @@ func (diag *Diag) Diagnostic() { pnc, strings.ReplaceAll(stack, "\n", "\n\t"), ) - frames := getCallersFrames(defaultMaxStack) - funcList := GetFuncList(frames) - diag.Analyze(pnc, stack, funcList) + funs := GetFuncList(frames) + diag.analyze(pnc, stack, funs) } } -func getCallersFrames(max int) *runtime.Frames { - pc := make([]uintptr, max) - // remove the call stack of diagnostic package - n := runtime.Callers(4, pc) - pc = pc[:n] - return runtime.CallersFrames(pc) +func (diag *Diag) BreakPoint(pnc string) { + stack := string(debug.Stack()) + log.Printf("diagnostic detected:\n\n\t%v\n\n\t%v", + pnc, + strings.ReplaceAll(stack, "\n", "\n\t"), + ) + frames := getCallersFrames(defaultMaxStack) + funs := GetFuncList(frames) + diag.analyze(pnc, stack, funs) } -func (diag *Diag) Analyze(pnc, stack string, funs []*Function) { - funcListDescription := buildFuncListDescription(funs) - - var query string - query += "The following error occurred in the current program: \n```\n" + pnc + "\n```\n\n" - query += "Here is its call stack: \n```\n" + stack + "```\n\n" - query += "The source code list is as follows:\n" + funcListDescription + "\n" +func (diag *Diag) analyze(pnc, stack string, funs []*Function) { + var prompt string + prompt += "The following error occurred in the current program: \n```\n" + pnc + "\n```\n\n" + prompt += "Here is its call stack: \n```\n" + stack + "```\n\n" + prompt += "The source code list is as follows:\n" + buildFuncListDescription(funs) + "\n" if diag.useChinese { - query += "Please reply in Chinese to help analyze the cause of the error and solve it!" + prompt += "Please reply in Chinese to help analyze the cause of the error and solve it!" } else { - query += "Please help analyze the cause of the error and solve it!" + prompt += "Please help analyze the cause of the error and solve it!" } - answer := diag.BigModel.Chat(query) - finish := false - - for !finish { + answer := diag.BigModel.Chat(prompt) + for finish := false; !finish; { ans := <-answer switch ans.Type { case bigmodel.TypeData: @@ -117,6 +114,13 @@ func (diag *Diag) Analyze(pnc, stack string, funs []*Function) { println() } +func getCallersFrames(max int) *runtime.Frames { + pc := make([]uintptr, max) + n := runtime.Callers(1, pc) + pc = pc[:n] + return runtime.CallersFrames(pc) +} + func buildFuncListDescription(funs []*Function) string { fset := MakeFileFuncSet(funs) diff --git a/example/main.go b/example/main.go index dc619ed..ab9b01e 100644 --- a/example/main.go +++ b/example/main.go @@ -20,12 +20,10 @@ package main import ( - "fmt" - "os" - "github.com/ahaostudy/code-diagnostic/bigmodel" "github.com/ahaostudy/code-diagnostic/diagnostic" "github.com/ahaostudy/code-diagnostic/example/math" + "os" "github.com/joho/godotenv" ) @@ -44,15 +42,23 @@ func init() { } func main() { - // initialize a diagnostic tool to automatically capture and analyze program exceptions - defer diagnostic.NewDiag( + // initialize a diagnostic tool + diag := diagnostic.NewDiag( // use the ChatGPT model bigmodel.NewChatGPT(apiKey, bigmodel.WithSpecifyBaseURL(baseURL)), // use chinese diagnostic.WithUseChinese(), - ).Diagnostic() + ) + + // automatically capture and analyze program exceptions + defer diag.Diagnostic() + + a, b := 10, 0 + //math.Div(a, b) - var a, b int - a = 20 - fmt.Println(math.Div(a, b)) + _, err := math.DivError(a, b) + if err != nil { + // custom breakpoint analysis + diag.BreakPoint(err.Error()) + } } diff --git a/example/math/math.go b/example/math/math.go index 40fdae0..580a31e 100644 --- a/example/math/math.go +++ b/example/math/math.go @@ -19,6 +19,8 @@ package math +import "fmt" + func Add(a, b int) int { return a + b } @@ -36,3 +38,10 @@ func Div(a, b int) int { return a / b }(a, b) } + +func DivError(a, b int) (int, error) { + if b == 0 { + return 0, fmt.Errorf("the divisor can not be zero") + } + return a / b, nil +}