全球通讯!基于最新 ChatGPT API 实现命令行版 ChatGPT

2023-03-04 23:55:39 | 来源:程序员客栈
引子OpenAI 这两天发布了ChatGPT API,基于gpt-3.5-turbo模型,这是一个 GPT-3.5 的优化版本,用于支持开发者把 ChatGPT 集成到自己的产品中,同时把 API 调用价格降到 $0.002 每千 token,意味着处理 100万字符的文本只需要 2 美元,也就是差不多十几块钱人民币,效果更好、价格更低,这让 ChatGPT API 更具性价比,因此这两天基于 ChatGPT API 的各种套壳应用如雨后春笋般大量冒出。我也来凑个热闹,试一试水,正好在我今天新建的 ChatGPT 互助讨论群里有人问有没有命令行版 ChatGPT,那就拿它来开刀吧:
老规矩,还是面向 ChatGPT 编程来实现这个命令行版 ChatGPT 应用。
在《面向 ChatGPT 编程实现全栈开发的 18 种方法》这篇教程中,我在最后说到在面向 ChatGPT 编程的时候,需要牢记两个原则:第一,知道你在做什么,第二,不要相信 ChatGPT 的代码。
落地到实践的时候,就是在与 ChatGPT 合作形成的结对编程联盟中,作为开发者我们需要承担代码设计、架构、编排与审核(CodeReview)的职责,对方案和结果负责,而具体的代码片段编写这种纯体力活则交由 ChatGPT 完成。
接下来,我们将遵循这个思路实现命令行版 ChatGPT 应用。
代码设计
如我在微信群里所说,这个需求确实很简单 —— 通过编程在控制台应用代码中调用 ChatGPT API 接口,实现一个命令行版的 ChatGPT,几十行代码就能搞定。不过这里仍然需要做一些简单的设计:

调用 API 需要传递 API KEY,我们不希望这个 KEY 硬编码在代码中,而是从系统环境变量读取,从而让代码更安全可维护;

调用封装好的 Go OpenAI 库与 API 接口进行交互,避免通过 HTTP 协议与原生 API 交互编写大量重复代码,让代码更简洁优雅;

做一个给客户使用的产品,美观会带来更好的用户体验,所以我希望即便是命令行应用,也尽可能让交互和输出更美观一些。

对于第 2 点,可以使用 go-gpt3 库,这是一个通过 Go 封装的 OpenAI API 调用库。


(资料图)

对于第3点,可以使用 glamour 库,这是一个 Go 语言实现的、能够在兼容 ANSI 终端基于样式渲染 Markdown 文本的第三方库,它是让命令行更美观的开源项目 Charm 的一部分。

因为项目很简单,又是在客户端本地使用,所以不需要做什么复杂的架构,下面直接进入编码部分。

代码编写

面向 ChatGPT 编程的核心就是把需求尽可能准确全面地转化为 Prompt 传递给 ChatGPT,这里有产品需求(来自业务和产品),也有代码设计和架构上的需求(来自开发者),然后让它生成代码,这是作为一个合格的 Prompt 工程师自我修养的必要组成部分。

在《ChatGPT 提示的艺术 —— 编写清晰有效提示指南(二)》这篇教程中,我已经给大家介绍了编写清晰有效 Prompt 的原则、做法和技巧,感兴趣的可以去看下,这里我先将我的需求转化为 Prompt 让 ChatGPT 替我编写对应的 Go 代码实现:

代码优化看起来不错,基本流程没问题,但是代码审核会发现,它现在把输入的 Prompt 写死了,并不能动态接收用输入,而且运行一次后就退出了,这不是 ChatGPT 的问题,而是我们的需求并没有明确这一点,作为一个完整的需求和程序,需要说明是什么,怎么样,什么时候开始,什么时候退出。不过细心的同学可能还留意到go-gpt3包引入的时候没有设置别名,会导致运行时出错,同时调用的 OpenAI API 接口也不对,最新的 ChatGPT API 接口方法应该是CreateChatCompletion,可能是太新的缘故,ChatGPT 还没有学习到这里,不过这都属于 ChatGPT 要优化的点了。以及使用了另一个同名的包,这个也需要明确告知它。细节上还是需要优化,现在我们基于这些要点先来完善我们的 Prompt:
这一次,我们更加细化了程序的行为,用户输入start启动,输入quit退出,在此期间则不断读取用户输入,返回 ChatGPT 处理结果并渲染到控制台输出,另外,我还在读取系统环境变量时嘱咐通过os.Getenv获取,因为有时候发现 ChatGPT 输出不稳定,会尝试从.env文件读取OPENAI_API_KEY,当然这不是 ChatGPT 的问题,是我们没有给出明确清晰的 Prompt。
现在再来看 ChatGPT 输出的代码,就更完善了:

package mainimport ("context""fmt""os""strings""github.com/charmbracelet/glamour""github.com/common-nighthawk/go-figure"gpt3 "github.com/sashabaranov/go-gpt3")func main() {// 获取 OpenAI API KeyapiKey := os.Getenv("OPENAI_API_KEY")if apiKey == "" {fmt.Println("请设置 OPENAI_API_KEY 环境变量")return}// 初始化 Glamour 渲染器renderStyle := glamour.WithEnvironmentConfig()mdRenderer, err := glamour.NewTermRenderer(renderStyle,)if err != nil {fmt.Println("初始化 Markdown 渲染器失败")return}// 输出欢迎语(命令行应用启动界面)myFigure := figure.NewFigure("ChatGPT", "", true)myFigure.Print()fmt.Println("输入 start 启动应用,输入 quit 退出应用")// 创建 ChatGPT 客户端client := gpt3.NewClient(apiKey)if err != nil {fmt.Printf("创建客户端失败: %s\n", err.Error())return}messages := []gpt3.ChatCompletionMessage{{Role:    "system",Content: "你是ChatGPT, OpenAI训练的大型语言模型, 请尽可能简洁地回答我的问题",},}// 读取用户输入并交互var userInput stringfor {fmt.Scanln(&userInput)if strings.ToLower(userInput) == "start" {fmt.Println("ChatGPT 启动成功,请输入您的问题:")} else if strings.ToLower(userInput) == "quit" {fmt.Println("ChatGPT 已退出")return} else if userInput != "" {messages = append(messages, gpt3.ChatCompletionMessage{Role:    "user",Content: userInput,},)// 调用 ChatGPT API 接口生成回答resp, err := client.CreateChatCompletion(context.Background(),gpt3.ChatCompletionRequest{Model:       gpt3.GPT3Dot5Turbo,Messages:    messages,MaxTokens:   1024,Temperature: 0,N:           1,},)if err != nil {fmt.Printf("ChatGPT 接口调用失败: %s\n", err.Error())continue}// 格式化输出结果output := resp.Choices[0].Message.ContentmdOutput, err := mdRenderer.Render(output)if err != nil {fmt.Printf("Markdown 渲染失败: %s\n", err.Error())continue}fmt.Println(mdOutput)messages = append(messages, gpt3.ChatCompletionMessage{Role:    "assistant",Content: output,},)}}}

gpt3 别名和 CreateChatCompletion 方法调用相关的代码还是需要手动调整,不过这也是我前面说的面向 ChatGPT 编程的原则之一,最后一定要审核 ChatGPT 的代码,它目前对于最新的知识还是有一定的迟滞性。

代码细节我就不展开解释了,有不明白的地方可以参考我在《面向 ChatGPT 编程实现全栈开发的 18 种方法》这篇教程中代码解释部分提供的方法自行去基于 ChatGPT 查看。

效果展示最后我们在终端体验一下这个命令行版 ChatGPT,我这里使用的是 Windows WSL 终端,Windows 终端本身体验其实不太好,尤其是中文输入的时候,删除字符特别费劲,且很容易造成消息变形,如果是 Mac 或者 Ubuntu 终端可能效果会更好一些。首先我们启动这个应用,如果没有设置OPENAI_API_KEY这个系统环境变量(运行export OPENAI_API_KEY={你的 OpenAI SECRET KEY}命令设置即可),会提示你设置:
如果已经设置,会进入下面这样的启动欢迎界面:
输入start即可启动应用,然后我们在命令行输入问题,回车,就会将问题提交给 ChatGPT,ChatGPT 处理的结果会返回并输出到控制台,这里的格式经过了 Glamour 库的美化:
因为是 for 循环,所以你可以持续提问、得到答案,直到输入quit退出应用。

终端需要能够访问 OpenAI API 才能调用成功,这意味着命令行也要支持科学上网。

好了,这就是我们基于最新 ChatGPT API 实现的命令行版 ChatGPT 应用,因为 ChatGPT API 是前两天才发布的,所以看起来 ChatGPT 并没有学习到这个最新的 API 如何调用,存在迟滞性,进而导致编写的代码并不能直接满足需求,需要人为介入去修改,希望未来 ChatGPT 能够在这一块上有所进化。

欢迎点赞、关注、分享,更多关于 ChatGPT 的学习实践探讨,请关注这个订阅号或者点击阅读原文了解极客书房最新动态。

上一篇 下一篇

相关新闻

全球通讯!基于最新 ChatGPT API 实现命令行版 ChatGPT

头条焦点:李雪琴的个人资料身高_李雪琴的个人资料

焦点快报!3月2日贵州电视台《百姓财经》报道省供销社系统农业社会化服务工作

誓师演讲的激昂,源自现实的苍凉

又输张本智和!国乒男单遭重创,3人出局,才16强就这么惨了

pc是什么职位_pc是什么_时讯

中铝国际升6% 机构指公司海外业务盈利修复弹性将超预期

德展健康:融资净偿还428.77万元,融资余额2.25亿元(03-01)

2008中国当代国画精品集

环球关注:越南这里,到处都是明朝移民

受理的读法|全球百事通

环球热讯:21世纪学校德育初探

准入悬了?媒体人:昆山队、深圳队、河北队的情况仍需等待 全球新要闻

万润新能股东户数减少160户,户均持股19.34万元

最新消息:360安全卫士打不开怎么办苹果_360安全卫士打不开怎么办

最新新闻

全球通讯!基于最新 ChatGPT API 实现命令行版 ChatGPT

头条焦点:李雪琴的个人资料身高_李雪琴的个人资料

焦点快报!3月2日贵州电视台《百姓财经》报道省供销社系统农业社会化服务工作

誓师演讲的激昂,源自现实的苍凉

又输张本智和!国乒男单遭重创,3人出局,才16强就这么惨了

pc是什么职位_pc是什么_时讯

中铝国际升6% 机构指公司海外业务盈利修复弹性将超预期

德展健康:融资净偿还428.77万元,融资余额2.25亿元(03-01)

2008中国当代国画精品集

环球关注:越南这里,到处都是明朝移民

受理的读法|全球百事通

环球热讯:21世纪学校德育初探

准入悬了?媒体人:昆山队、深圳队、河北队的情况仍需等待 全球新要闻

万润新能股东户数减少160户,户均持股19.34万元

最新消息:360安全卫士打不开怎么办苹果_360安全卫士打不开怎么办

【时快讯】英媒指查理斯收回浮若阁摩尔,哈里夫妇失英国仅余居所

测绘股份:多年的经营和发展形成的区域品牌优势及全国性的行业影响力

国一国二

university前面用a还是an类似

每日快播:韩网热帖!悦诗风吟张元英 珉奎的广告片是什么情况

Forge one's understandings deep behind 环球报道

观速讯丨GT-FH827型钢铁无铬钝化剂

全球观焦点:现在烧制的瓷器肯定比那些所谓古董好,更精致,怎么就不值钱呢?

今日热闻!理想去年亏损超20亿!今年想卖30万辆?

胫骨平台骨折康复训练贴吧_胫骨平台骨折康复训练方法 当前快播

2万左右的双排小货车_2万左右的微型柴油货车

上海今年将建20家社区康复中心、30家中医示范站点 世界最资讯

黄金短期有望止跌回升_当前快报

Photoshop超完美创意设计

PNAS:早上锻炼更燃脂!科学家发现运动时间影响脂肪组织代谢,早晨运动,脂肪细胞分解效率更高丨科学大发现