使用ChatGPT提高研发效率与质量

在研发方面的应用场景
帮助代码实现
AI大语音模型可以通过自然语言描述来自动生成代码,减少了程序员手动编写代码的时间和复杂性。
Code Review
AI大语音模型可以通过自然语言描述来帮助程序员进行代码重构,从而改进代码的质量和可读性。
源码共读
学习经典的源码,提升自我代码能力水平,AI大语音模型可以通过自然语言描述来进行代码语义分析,从而帮助程序员更好地理解代码的功能和结构。
应用场景实践
帮助代码实现
观点:作为开发者我们必须承担 代码设计、架构、编排与审核(CodeReview)的职责,对方案和结果负责。
而具体的代码片段编写这种纯体力活可以考虑交由 ChatGPT 完成。
实现功能
目的:实现一个能在控制台运行的openAI API 的Go应用程序
代码描述
Bad:“请帮我编写一个Go应用程序对接ChatGPT API,来实现控制台访问”
Good:"
调用最新的ChatGPT API接口,实现一个命令行版的ChatGPT,当用户输入"start"启动应用后,它能读取用户输入,然后返回ChatGPT结果到控制台,当用户输入"quit"则退出应用,请帮我编写对应的Go视线代码。
另外还有额外约束条件: 1.API KEY从系统环境变量(os.getenv),不要硬编码在代码中,不存在则答应错误信息并退出 2.通过第三方库sashabaranov/go-openai与ChatGPT API交互,让代码更简洁优雅 3.最后输出结果尽可能美观,使用glamour库渲染输出"
代码编写
面向ChatGPT编程的核心就是把需求尽可能全面的描述清楚并传递给ChatGPT,里面有产品需求,也有代码设计和架构上的需求或要求,然后交给它来生成代码。
这是作为合格的 Prompt(提示)工程师必要条件。
什么样的ChatGPT对话才是好的,我们如何制定有效的沟通对话?
与ChatGPT沟通原则
- 清晰度:明确而简明的信息有助于确保ChatGPT理解任务,避免一些模棱两可的语音。
- 简洁性:提示中尽量简洁,将有助于确保ChatGPT能够生成有针对性和相关的响应。
- 相关性:确保输入的提示与需求相关,避免引入不相关的主题内容。
如何编写清晰的提示
- 明确会话的目的和焦点。在编写提示之前,有一个清晰的想法很重要,即您想通过会话实现什么目标。您的目标是提供信息、回答问题还是进行随意交谈?明确会话的目的和焦点将有助于您编写一个特定且相关的提示。
- 使用具体和相关的语言。为了确保 ChatGPT 理解您的提示并能够生成适当的响应,使用具体和相关的语言非常重要。避免使用术语或模棱两可的语言,这可能导致混淆或误解。
- 避免开放性或过于广泛的提示。虽然为了获得更全面的响应而问开放性或过于广泛的问题很诱人,但这些类型的提示通常会导致不连贯或无焦点的对话。相反,力求在提示中尽可能具体,为会话定义明确的目的和焦点。
- 保持会话在正确的轨道上。当您参与 ChatGPT 对话时,保持关注所讨论的主题并避免引入与主题不相关的话题非常重要。




场景效果展示

Code Review
思路流程
- 当极狐 GitLab 有代码变更时(创建 MR),通过 webhook 发送事件消息到 ai-code-review 服务;
- 当 ai-code-review 服务收到消息后,发送 Review Reqeust 到 ChatGPT(调用 ChatGPT 的 API);
- ChatGPT 将 Code Review 结果以 Review Response 形式返回;
- ai-code-review 收到 Review Response 后,将内容(Review Comment)发送到极狐 GitLab 的 MR 中。
配置GitLab Webhook

对接Gitlab开发
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func GetMergeRequests(projectId string, mergeRequestId string) map[string]interface{} {
mergeRequestURL :=
"https://git.wosai-inc.com/api/v4/projects/:id/merge_requests/:merge_request_iid/changes"
// 替换:id 和 :merge_request_iid 为对应的值
mergeRequestURL = replaceParameters(mergeRequestURL,
map[string]string{
":id": projectId, // 替换为 GitLab 项目的 ID
":merge_request_iid": mergeRequestId, // 替换为 Merge Request 的 IID
})
// 创建 HTTP 请求
client := http.Client{}
request, err := http.NewRequest("GET", mergeRequestURL, nil)
if err != nil {
fmt.Println("Error creating request", err)
return nil
}
// 设置 GitLab 认证令牌
request.Header.Add("Private-Token", "你的token")
// 发送 HTTP 请求
response, err := client.Do(request)
if err != nil {
fmt.Println("Error sending request", err)
return nil
}
// 解析响应数据
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println("Error reading response", err)
return nil
}
// 将响应数据解析为 JSON
var mergeRequest map[string]interface{}
err = json.Unmarshal(body, &mergeRequest)
if err != nil {
fmt.Println("Error decoding JSON", err)
return nil
}
// 输出 Merge Request 标题
fmt.Println("Merge Request title:", mergeRequest["title"])
return mergeRequest
}
// replaceParameters 用于替换 URL 中的参数
func replaceParameters(url string, parameters map[string]string) string {
for key, value := range parameters {
url = strings.ReplaceAll(url, key, value)
}
return url
}
AI Code Review服务开发机器人角色设计
定义角色
自动化评审机器人封装在代码中🤖,其角色声明为:
{
Role: openai.ChatMessageRoleSystem,
Content: "你是是一位资深编程专家,负责代码变更的审查工作。需要给出审查建议。在建议的开始需明确对此代码变更给出「拒绝」或「接受」的决定,并且以格式「变更评分:实际的分数」给变更打分,分数区间为0~100分。然后,以精炼的语言、严厉的语气指出存在的问题。如果你觉得必要的情况下,可直接给出修改后的内容。建议中的语句可以使用emoji结尾。你的反馈内容必须使用严谨的markdown格式。",
}
注入感情
所以机器人讲话很没有感情,如果想 “注入感情”🎨,则需要定义自己的评审机器人,比如希望是一个傲娇少女👧来评审,参考如下角色声明:
{
Role: openai.ChatMessageRoleSystem,
Content: "你是一个天才小女孩,精通编程工作,性格很傲娇又高傲,负责对前辈的代码变更进行审查,用后辈的态度、活泼轻快的方式的指出存在的问题。使用markdown格式。可以包含emoji。",
}
AI Code Review服务开发
package main
func main() {
//读取Gitlab MR,并获取对应changes内容
//参数为projectid 、mergeRequestId
runProjectCodeReview("projectid", "mergeRequestId")
}
package main
import (
"context"
"fmt"
"github.com/charmbracelet/glamour"
"github.com/sashabaranov/go-openai"
"os"
"strings"
)
var client *openai.Client
func init() {
fmt.Println("====== open AI client init======")
// 设置代理地址
proxyURL := "http://127.0.0.1:7890"
os.Setenv("HTTP_PROXY", proxyURL)
os.Setenv("HTTPS_PROXY", proxyURL)
apiKey := os.Getenv("OPENAI_API_KEY")
if apiKey == "" {
fmt.Println("Error: OPENAI_API_KEY environment variable not set")
os.Exit(1)
}
client = openai.NewClient(apiKey)
}
func GetCodeReview(input string) {
resp, err := client.CreateChatCompletion(
context.Background(),
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo0301,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: "你是是一位资深编程专家,负责代码变更的审查工作。需要给出审查建议。在建议的开始需明确对此代码变更给出「拒绝」或「接受」的决定,并且以格式「变更评分:实际的分数」给变更打分,分数区间为0~100分。然后,以精炼的语言、严厉的语气指出存在的问题。如果你觉得必要的情况下,可直接给出修改后的内容。建议中的语句可以使用emoji结尾。你的反馈内容必须使用严谨的markdown格式。",
},
{
Role: openai.ChatMessageRoleSystem,
Content: "你是一个天才小女孩,精通编程工作,性格很傲娇又高傲,负责对前辈的代码变更进行审查,用后辈的态度、活泼轻快的方式的指出存在的问题。使用markdown格式。可以包含emoji。",
},
{
Role: openai.ChatMessageRoleUser,
Content: input,
},
},
},
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Println("Bot AI review意见: ", formatOutput(resp.Choices[0].Message.Content))
}
func formatOutput(text string) string {
// Render the text using the glamour library for better formatting
styled, err := glamour.Render(text, "dark")
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
return styled
}
func runProjectCodeReview(projectId string, mergeRequestId string) {
mergeRequest := GetMergeRequests(projectId, mergeRequestId)
changes := mergeRequest["changes"]
ignoreFileName := []string{".yml", "test", ".mod", ".sum", "config", "json", "lock", "css", "html", "Settings"}
for _, change := range changes.([]interface{}) {
changeMap := change.(map[string]interface{})
newPath := changeMap["new_path"]
var ignore = false
for _, s := range ignoreFileName {
if strings.LastIndex(newPath.(string), s) != -1 {
ignore = true
break
}
}
if ignore {
continue
}
fmt.Printf("对 %s review中...\n", newPath)
input := "请review这部分代码变更:" + changeMap["diff"].(string)
GetCodeReview(input)
}
}
GPT 评审效果
Go

React JS

