OpenAI-API-人工智能应用构建指南-全-

OpenAI API 人工智能应用构建指南(全)

原文:zh.annas-archive.org/md5/f7ddf3ef1e7a30167428b93eec187cf2

译者:飞龙

协议:CC BY-NC-SA 4.0

第一章:前言

你好! ChatGPT API 是 OpenAI 提供的一个强大工具,它允许开发者将最先进的 ChatGPT 语言模型集成到自己的应用中,通过 API 调用实现交互式和动态的对话体验。 随着人工智能AI)领域的快速发展,对能够理解和响应人类语言并生成创造性视觉内容的智能和交互式系统的需求也在增加。

有三个主要的 OpenAI API 可以使得开发者能够利用 AI 的力量:

  • ChatGPT API:使用它来释放类似人类的文本生成能力

  • Whisper API:使用它来增强语音识别和文本到语音的能力

  • DALL-E API:使用它来探索 AI 生成艺术的世界

本书的目的是赋予你利用这些强大 API 所需的知识和技能。 通过一系列九个创新的 AI 项目,我们将带你逐步成为一位熟练的开发者,能够创建、部署和盈利自己的智能应用。

在本书中,你将获得将 ChatGPT 与 Flask、Django、Microsoft Office API 和 PyQt 等流行框架和工具集成的实践经验。 我们将涵盖广泛的 NLP 任务,你将学习如何构建自己的 ChatGPT 克隆,并创建一个 AI 驱动的代码错误修复 SaaS 应用。 此外,我们还将探索语音识别、文本到语音功能、语言翻译、嵌入以及生成电子邮件回复和PowerPoint 演示文稿

此外,我还会教你如何微调你自己的 ChatGPT 模型。 ChatGPT API 微调为创建高度定制和专业的 AI 应用打开了可能性。 通过微调 ChatGPT 模型,我们可以在特定数据集上对其进行训练,使 AI 能够学习和适应特定领域、行业或用户需求。 这一微调过程使得创建的 AI 应用具有更高的准确性、改进的相关性和对特定语境的更深入理解。

在这个 AI 革命的时代,对于那些有技能开发 AI 应用的人来说,机会无限。

本书面向对象

这本书的目标读者是各种专业人士,包括程序员、企业家、学生和软件爱好者,旨在提供使用 ChatGPT API 构建应用的最佳实践、技巧和窍门。 它对初学者程序员、希望整合 AI 技术的软件开发人员和希望使用 ChatGPT 创建 AI 驱动的 Web 应用的开发人员特别有益。 ChatGPT。

这本书的目标受众是三个主要角色: 受众画像:

AI 爱好者:这些人热衷于 AI,并渴望探索其实际应用。 他们可能是爱好者、学生或来自不同背景的专业人士,他们希望深入了解 AI 技术并利用它们来构建创新的应用。 这本书将为他们提供必要的知识和实践经验,以便他们能够使用 ChatGPT API 开始他们的 AI 之旅。 ChatGPT API。

软件开发人员:对将 AI 功能集成到他们的应用程序感兴趣的软件开发人员,无论是初学者还是经验丰富的专业人士,都会发现这本书很有价值。 他们可能希望用 AI 驱动的功能(如聊天机器人、情感分析或自然语言理解)来增强他们现有的项目。 通过掌握 ChatGPT API,他们可以提高他们的软件开发技能,并为用户提供智能和对话式的体验。 他们的用户。

AI 企业家:希望利用 AI 潜力并为商业目的构建 AI 应用的企业家将受益于这本书。 无论他们是否想创建基于聊天的客户支持系统、虚拟助手或其他 AI 驱动的解决方案,这本书都将指导他们通过构建自维持应用的过程。 他们将学习如何货币化他们的 AI 应用、整合支付平台并部署可扩展的 SaaS 解决方案,使他们能够利用 ChatGPT API 带来的机会。 ChatGPT API。

无论他们的背景或专业知识如何,这三个目标受众都将在这本书中找到实用的指导、现实世界的例子和全面的说明,以掌握 ChatGPT API 并成功开发他们自己的 AI 应用。

本书涵盖内容

第一章, 使用 ChatGPT API 开始 NLP 任务,介绍了 ChatGPT 和 ChatGPT API,指导你设置 Python 环境以及必要的下载,并探讨了 OpenAI 账户注册、API 令牌使用以及利用 OpenAI API 的定价模式。

第二章, 构建 ChatGPT 克隆,提供了设计 ChatGPT 克隆的逐步指南,涵盖了使用 ChatGPT API 进行后端开发、本地部署项目、保留对话历史以及使用 HTML、CSS 和基本 JavaScript 设计前端,提供了一个实践项目,为你准备后续章节中涵盖的更高级 SaaS 应用程序开发。

第三章, 使用 Flask 创建和部署代码修复应用程序,指导你构建和部署一个使用 ChatGPT API 的强大 SaaS 应用程序。 它展示了如何构建完整的发展周期,从部署到网络托管,实现全球使用。 该应用程序利用 ChatGPT 提供代码调试和错误描述,介绍了一个独特且 有价值的项目。

第四章, 将代码修复应用程序与支付服务集成,提供了将支付服务集成到 ChatGPT 应用程序中的见解,利用访问跟踪实现基于 Stripe API 的支付机制。 你还将了解如何将基本数据库集成到 你的项目中。

第五章, 使用 ChatGPT 和 Django 创建测验生成应用程序,提供了将 ChatGPT API 集成到 Django 中的全面指南,教你如何创建具有 AI 功能的 Django 页面和视图。 你将学习如何构建一个 Django 项目,从学习材料生成考试问题,并在本地作为 SaaS 应用程序运行。

第六章, 使用 ChatGPT API 和 Microsoft Word 的桌面端语言翻译应用,指导您如何利用 ChatGPT API 进行 Microsoft Word 文本翻译,同时教授您如何使用 TKinter 将 Python 脚本打包成一个功能性的桌面应用程序。 它介绍了 ChatGPT API 与 Microsoft Office 自动化工具的集成,让您能够创建一个定制的文本 翻译应用程序。

第七章, 构建 Outlook 电子邮件回复生成器,提供了一个实用的指南,介绍如何构建一个利用 Outlook 电子邮件数据生成个性化回复和 提示设计的应用程序。

第八章, 使用 PyQt 和 ChatGPT API 的论文生成工具,为您提供了一步一步的指南,说明如何将 ChatGPT API 与 PyQT 集成以进行桌面应用程序开发,以及如何从 应用程序前端控制 API 令牌。

第九章, 集成 ChatGPT 和 DALL-E API:构建端到端 PowerPoint 演示文稿生成器,提供了一种实际的方法来集成两个 AI API,ChatGPT 和 DALL-E,并创建一个 AI 生成的 PowerPoint 演示文稿。

第十章, 使用 Whisper API 进行语音识别和文本转语音,为您提供了 Whisper API 的概述,并指导您通过一个实际项目使用音频文件构建字幕和翻译。

第十一章, 选择合适的 ChatGPT API 模型,概述了 ChatGPT API 模型和参数,帮助您选择最适合您项目的模型,了解模型的限制,并学习 关于嵌入的内容。

第十二章, 微调 ChatGPT 以创建独特的 API 模型,概述了微调 ChatGPT API 模型,并附带一个案例研究,说明如何在现实世界的应用中利用此过程以降低构建 AI 应用程序的成本。

为了充分利用这本书

在开始阅读本书之前,您对 Python 编程和 API 概念有一个基本的理解是非常重要的。此外,了解应用开发中使用的客户端和服务器端技术的基础知识也非常推荐。 这些先决知识将增强您的理解,并使您能够全面掌握书中呈现的概念和示例。 全书。

| 本书涵盖的软件/硬件操作系统要求操作系统 要求 |
| --- | --- |
| Python | Windows, macOS, 或 Linux |
| Django | Windows, macOS, 或 Linux |
| Flask | Windows, macOS, 或 Linux |
| PyQt | Windows, macOS, 或 Linux |
| OpenAI 库 | Windows, macOS, 或 Linux |
| Stripe | Windows, macOS, 或 Linux |

请放心,本书全面涵盖了所有必要的安装,包括 Python 和 VS Code IDE。 您将在书中找到逐步说明和详细解释,以指导您完成安装过程。 按照提供的说明操作,您将能够轻松设置 Python 环境和 VS Code IDE,确保顺利通过 本书的内容。

如果您使用的是本书的数字版,我们建议您亲自输入代码或从本书的 GitHub 仓库(下一节中提供链接)获取代码。 这样做将帮助您避免与代码复制和粘贴相关的任何潜在错误。 代码。**

我强烈建议您通过尝试变量更改并观察对应用程序的影响来积极参与本书中构建的应用程序。 这种动手方法将更深入地了解不同变量如何影响应用程序的行为。 此外,我敦促您利用从本书中获得的知识开始自己的应用程序构建之旅。 通过将本书中的应用程序作为基础,您可以将新获得的技术和创造力应用于开发您自己的独特应用程序,从而加深对 涉及概念的理解。

下载示例代码文件

您可以从 GitHub 下载本书的示例代码文件,网址为 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-APIs。如果代码有更新,它将在 GitHub 仓库中更新。

我们还有其他来自我们丰富的图书和视频目录的代码包可供使用,网址为 https://github.com/PacktPublishing/。查看它们吧!

使用的约定

本书中使用了多种文本约定。

<st c="10539">文本中的代码</st>:表示文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名和用户输入。 以下是一个示例:“要开始,您需要将 <st c="10739">openai</st> 库导入到您的 <st c="10764">app.py</st> 文件中。”

代码块被 设置为以下格式:

 from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")

当我们希望您注意代码块中的特定部分时,相关的行或项目将被 加粗:

<st c="10997">question = input("What would you like to ask ChatGPT?</st> <st c="11052">")</st>

任何命令行输入或输出都按照以下方式编写:

 $ python app.py

<st c="11330">templates</st> 文件夹并选择 新建 | HTML 文件。”

提示或重要注意事项

看起来像这样。

联系我们

我们始终欢迎读者的反馈。

一般反馈:如果您对本书的任何方面有任何疑问,请通过电子邮件发送至 customercare@packtpub.com 并在邮件主题中提及书名。

勘误:尽管我们已经尽最大努力确保内容的准确性,但错误仍然可能发生。 如果您在这本书中发现了错误,如果您能向我们报告,我们将不胜感激。 请访问 www.packtpub.com/support/errata 并填写 表格。

盗版:如果您在互联网上以任何形式发现我们作品的非法副本,如果您能提供位置地址或网站名称,我们将不胜感激。 请通过电子邮件发送至 copyright@packt.com 并提供 材料的链接。

如果您有兴趣成为作者:如果您在某个领域有专业知识,并且您有兴趣撰写或为书籍做出贡献,请 访问 authors.packtpub.com

分享您的想法

一旦您阅读了《使用 OpenAI API 构建人工智能应用,我们很乐意听听您的想法! 请点击此处直接进入此书的亚马逊评论页面并分享 您的反馈

您的评论对我们和科技社区都很重要,并将帮助我们确保我们提供优秀的 内容质量。

下载此书的免费 PDF 复印本

感谢您购买 此书!

您喜欢在路上阅读,但无法携带您的印刷 书籍到处走吗?

您的电子书购买是否与您选择的设备不兼容?

不用担心,现在,每购买一本 Packt 书,您都可以免费获得该书的 DRM-free PDF 版本。

在任何地方、任何设备上阅读。 从您最喜欢的技术书籍中直接搜索、复制和粘贴代码到您的应用程序中。

优惠远不止于此,您还可以获得独家折扣、时事通讯和每日收件箱中的精彩免费内容。

按照以下简单步骤获取 这些好处:

  1. 扫描二维码或访问以下 链接

https://packt.link/free-ebook/9781835884003

  1. 提交您的购买 证明

  2. 这就完了! 我们将直接将您的免费 PDF 和其他优惠发送到您的 电子邮件

第一部分:开始使用 OpenAI API

在第一部分中,包含两章,重点是提供对 ChatGPT 和其在自然语言处理(NLP)中重要性的全面概述。 我们将讨论 ChatGPT 的基础知识,探讨其在网络应用中的影响和用途,并介绍 ChatGPT API。 本部分展示了构建 ChatGPT 克隆的过程,这是一个利用 OpenAI 的语言模型生成类似人类响应并保留对话历史的聊天机器人。 该应用程序将使用 Flask 构建,这是一个用于 Python 的轻量级 Web 框架。

本部分包含以下章节:

  • 第一章,使用 ChatGPT API 进行 NLP 任务入门

  • 第二章,构建 ChatGPT 克隆版

第二章:1

开始使用 ChatGPT API 进行 NLP 任务

自然语言处理 (NLP)是人工智能AI领域的一个分支,专注于通过自然语言进行人机交互。多年来,自然语言处理在语言理解领域取得了显著的进步;ChatGPT是近年来在 NLP 领域获得显著流行的一种革命性 NLP 工具。

ChatGPT 是由OpenAI开发的高级 AI 语言模型,并在包括书籍、文章和网页在内的各种文本的庞大数据集上进行了训练。凭借其理解和生成类似人类文本的能力,ChatGPT 已成为许多 NLP 应用(包括聊天机器人、语言翻译和内容生成)的首选工具。

本章中,我们将探讨 ChatGPT 的基础知识以及如何使用它来执行 NLP 任务。我们将从介绍 ChatGPT 及其对 NLP 领域的影响开始。 然后我们将探讨如何从网络使用 ChatGPT 及其优势。 接着,我们将学习如何开始使用 ChatGPT API,包括创建账户和生成 API 密钥。 之后,我们将了解如何设置开发环境以与 ChatGPT API 一起工作。 最后,我们将通过一个简单的 ChatGPT API 响应示例来了解该工具的基本功能。

本章中,我们将涵盖以下主题: 以下内容:

  • ChatGPT 革命

  • 从网络使用 ChatGPT

  • 开始使用 ChatGPT API

  • 设置您的 Python开发环境

  • 简单的 ChatGPT API 响应

到本章结束时,您将对该章内容有扎实的理解,了解 ChatGPT 及其如何高效地执行 NLP任务。

技术要求

为了充分利用本章内容,您需要一些基本工具来处理 Python 代码和 ChatGPT API。本章将指导您完成所有软件安装和注册。

您需要以下内容: 以下:

  • 在您的计算机上安装了Python 3.7 或更高版本

  • 一个 OpenAI API 密钥,可以通过注册一个 OpenAI 账户来获取

  • 一个代码编辑器,例如 VSCode (推荐),用于编写和运行 Python 代码

  • 基本的 Python 编程经验 使用 Python

本章的代码示例可以在 GitHub 上找到 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

ChatGPT 革命

ChatGPT 是由 OpenAI 开发的高级 AI 语言模型,并在 NLP 领域产生了重大影响。 该模型基于 transformer 架构,并在包括书籍、文章和 网页在内的各种文本的大量数据集上进行了训练。

ChatGPT 的一个关键特性是它能够生成连贯且上下文适当的文本。 与之前的 NLP 模型不同,ChatGPT 对语言有更广泛的理解,并且可以生成与人类生成文本在风格和结构上相似的文本。 这一特性使 ChatGPT 成为各种应用的宝贵工具,包括对话 AI 和 内容创作

ChatGPT 在对话 AI 领域也取得了显著进展,其中它被用于开发能够与人类自然互动的聊天机器人。 凭借其理解上下文并生成与人类生成文本风格相似文本的能力,ChatGPT 已成为开发 对话 AI的必备工具。

大型语言模型 (LLMs)如 GPT-3 的出现,彻底改变了聊天机器人的格局。 在 LLMs 之前,聊天机器人的功能有限,依赖于基于规则的系统,并具有预定义的响应。 这些聊天机器人缺乏上下文理解,难以进行有意义的对话。 然而,基于 LLMs 的聊天机器人经历了显著的变化。 这些模型能够理解复杂的查询,生成连贯且细微的响应,并拥有更广泛的知识库。 它们表现出改进的上下文理解能力,从用户交互中学习,并不断改进其性能。 基于 LLMs 的聊天机器人通过提供更自然和个性化的交互,提升了用户体验,展示了聊天机器人技术的显著进步。

ChatGPT 在 NLP 领域有着悠久而成功的历史。 该模型在多年中经历了多次改进,包括以下内容:

  • GPT-1 (2018):拥有 1.17 亿个参数,并在多样化的网页集上进行训练。 它在各种 NLP 任务中表现出色,包括问答、情感分析和 语言翻译。

  • GPT-2 (2019):拥有 15 亿个参数,并在超过 800 万个网页上进行训练。 它在语言理解和生成方面取得了显著的进步,并成为各种 NLP 应用中的广泛使用工具。

  • GPT-3 (2020):拥有创纪录的 1750 亿个参数,为语言理解和生成设定了新的基准。 它被用于各种应用,包括聊天机器人、语言翻译和 内容创作。

  • GPT-3.5:在 OpenAI 的持续优化和改进后发布。 在成本和性能比较中是目前最佳价值模型。

  • GPT-4:能够以更高的精度解决难题,这得益于其更广泛的一般知识和 问题解决能力。

开发者可以利用 生成式预训练变换器 (GPT) 模型的力量,而无需从头开始训练自己的 模型。 这可以节省大量时间和资源,尤其是对于小型团队或 个人开发者。

在下一节中,你将学习如何从网页上使用 ChatGPT。你将学习如何创建一个 OpenAI 账户并探索 ChatGPT 的 网页界面。

从网页上使用 ChatGPT

通过 OpenAI 网站与 ChatGPT 交互 非常简单。 OpenAI 提供 一个基于网页的界面,可以在 https://chat.openai.com找到,使用户能够无需 任何先前的编码知识或设置即可与模型互动。 一旦访问网站,您就可以开始输入您的问题或提示,模型将产生其最佳可能的答案或生成的文本。 值得注意的是,网页上的 ChatGPT 还向用户提供各种设置和选项,使他们能够跟踪对话的上下文并保存与 AI 的所有互动历史。 这种功能丰富的基于网页的 AI 交互方法使用户能够轻松地尝试模型的功能,并深入了解其广泛的应用潜力。 要开始使用基于网页的界面,您需要通过 OpenAI 注册一个账户,我们将在下一节中详细介绍。 一旦创建了账户,您就可以访问网页界面,开始探索模型的功能,包括各种设置和选项来增强您的 AI 交互。

创建 OpenAI 账户

在使用 ChatGPT 或 ChatGPT API 之前,您必须在 OpenAI 网站上创建一个账户,这将使您能够访问公司开发的所有工具。 为此,您可以访问 https://chat.openai.com,在那里您将被要求登录或注册一个新账户,如图 图 1**.1所示:

图 1.1 – OpenAI 欢迎窗口

图 1.1 – OpenAI 欢迎窗口

只需点击 注册 按钮,按照提示进入注册窗口(见 图 1**.2)。 从那里,您可以选择输入您的电子邮件地址并点击 继续,或者您可以选择使用 Google 或 Microsoft 账户注册。 完成此步骤后,您可以选择一个密码并验证您的电子邮件,就像在其他任何网站的注册过程中一样 注册过程。

完成注册 流程后,您就可以开始探索 ChatGPT 的全部功能。 只需点击 登录 按钮,如图 图 1**.1* 所示,并在登录窗口中输入您的凭证。 登录成功后,您将获得对 ChatGPT 以及所有其他 OpenAI 产品的完全访问权限。 通过这种简单易用的访问方式,您可以无缝探索 ChatGPT 的全部功能,并亲眼见证它为何成为 NLP 任务如此强大的工具

图 1.2 – OpenAI 注册窗口

图 1.2 – OpenAI 注册窗口

现在我们可以更详细地探索 ChatGPT 网页界面的功能和特性。 我们将向您展示如何导航界面,并充分利用其多样化的选项,以从 AI 模型中获得最佳结果

ChatGPT 网页界面

ChatGPT 网页界面 允许用户与 AI 模型交互。 一旦用户注册服务并登录,他们可以将文本提示或问题输入到聊天窗口中,并从模型那里获得回应。 您可以使用 发送消息 文本字段向 ChatGPT 提问。 聊天窗口还会显示之前的消息和提示,使用户能够跟踪对话的上下文,如图 F图 1**.3* 所示:

图 1.3 – ChatGPT 跟随对话上下文

图 1.3 – ChatGPT 跟随对话上下文

除了这些,ChatGPT 允许用户轻松记录与模型交互的历史。用户的聊天记录会自动保存,稍后可以从左侧侧边栏访问以供参考或分析。 此功能对于研究人员或希望跟踪与模型对话并评估其性能随时间变化的人来说特别有用。 聊天记录还可以用于训练其他模型或比较不同模型的性能。 你现在能够区分并使用不同 ChatGPT 模型的进步。 您还可以通过网页使用 ChatGPT,包括创建账户和生成 API 密钥。 ChatGPT API 灵活且可定制,可以节省开发者的时间和资源,使其成为聊天机器人、虚拟助手和自动内容生成的理想选择。 在下一节中,您将学习如何使用 Python 轻松访问 ChatGPT API。

开始使用 ChatGPT API

ChatGPT API 是由 OpenAI 开发的,允许开发者与 GPT 模型进行 NLP 任务交互。 此 API 提供了一个易于使用的界面,用于生成文本、完成提示、回答问题和执行其他 NLP 任务,使用的是最先进的机器学习模型。

ChatGPT API 用于聊天机器人、虚拟助手和自动内容生成。 它还可以用于语言翻译、情感分析和内容分类。 API 灵活且可定制,允许开发者针对特定用例微调模型性能。 现在让我们了解获取 API 密钥的过程。 这是从您自己的应用程序访问 ChatGPT API 的第一步。

获取 API 密钥

要使用 ChatGPT API,您需要获取 一个 API 密钥。 这可以从 OpenAI 获取。 此密钥将允许您验证对 API 的请求,并确保只有授权用户才能访问 您的账户。

要获取 API 密钥,您必须 使用 ChatGPT 凭据访问 https://platform.openai.com 的 OpenAI 平台。 OpenAI 平台页面提供了一个管理您的 OpenAI 资源的中心枢纽。 一旦 您注册成功,您就可以导航到 API 访问页面: https://platform.openai.com/account/api-keys。在 API 访问页面上,您可以管理 ChatGPT API 和其他 OpenAI 服务的 API 密钥。 您可以生成新的 API 密钥,查看和编辑每个密钥的权限,并监控 API 的使用情况。 该页面提供了您 API 密钥的清晰概述,包括它们的名称、类型和创建日期,并允许您根据需要轻松撤销或重新生成密钥

点击 + 创建新的密钥 按钮,您的 API 密钥将被创建:

图 1.4 – 创建 API 密钥

图 1.4 – 创建 API 密钥

创建您的 API 密钥后,您将只有一次机会复制它(见 图 1**.5)。 保护您的 API 密钥的安全和机密性非常重要,因为任何能够访问您的密钥的人都有可能访问您的账户并使用您的资源。 您还应该小心不要将密钥与未经授权的用户共享,并避免将密钥提交到公共存储库或通过不安全的渠道以明文形式共享。

图 1.5 – 保存 API 密钥

图 1.5 – 保存 API 密钥

在我们的应用程序和脚本中复制和粘贴 API 密钥 使我们能够使用 ChatGPT API。 现在,让我们来探讨 ChatGPT 的 token 及其在 OpenAI 定价模型中的作用。

API token 和定价

在使用 ChatGPT API 时,理解 token 的概念非常重要 至关重要 Token 是模型用于处理和理解的文本的基本单元。

标记可以是单词或字符块,通过将文本分解成更小的部分来创建。 例如,单词 汉堡 可以被分解为 ham, bur, 和 ger,而像 这样的较短的单词是一个单独的标记。 标记也可以以空白字符开头,例如 hello bye

在 API 请求中使用的标记数量取决于输入和输出文本的长度。 一般来说,一个标记大约对应于 4 个字符或 0.75 个英文单词。 需要注意的是,文本提示和生成的响应的总长度不能超过模型的最大上下文长度。 表 1.1 显示了某些流行 ChatGPT 模型的标记限制。

模型 最大标记数
gpt-4 8,192 标记
gpt-4-32k 32,768 标记
gpt-3.5-turbo 4,096 标记
gpt-3.5-turbo-0125 16,385 标记

表 1.1 – API 模型标记限制

要了解更多关于文本如何转换为标记的信息 ,您可以查看 OpenAI 的标记化工具 标记化工具是 OpenAI 提供的一个有用的资源,用于了解文本如何转换为标记。 该工具将文本分解成单个标记,并显示它们对应的字节偏移量,这对于分析和理解 您的文本结构非常有用。

您可以在 https://platform.openai.com/tokenizer] 找到标记化工具。要使用标记化工具,只需 输入您想要分析的文本并选择合适的模型和设置。 然后,该工具将生成一个标记列表,以及它们对应的字节偏移量(见 图 1**.6)。

图 1.6 – 标记化工具

图 1.6 – 标记化工具

ChatGPT API 的定价 是按照每处理 1,000 个令牌计费 ,并且每个 API 请求有最低费用。 这意味着你的输入和输出文本越长,处理的令牌就越多,费用也就越高。 表 1.2 显示了截至 2024 年 5 月,处理 1,000 个令牌的当前成本,适用于几个常用的 ChatGPT 模型。

模型 提示 完成
gpt-4 $0.03 / 1K 令牌 $0.06 / 1K 令牌
gpt-4-32k $0.06 / 1K 令牌 $0.12 / 1K 令牌
gpt-3.5-turbo $0.0005 / 1K 令牌 $0.0015 / 1K 令牌
gpt-3.5-turbo-0125 $0.0005 / 1K 令牌 $0.0015 / 1K 令牌

表 1.2 – ChatGPT API 模型定价

重要提示

注意你的令牌使用情况,以避免意外收费。 你可以通过 使用情况 仪表板 https://platform.openai.com/account/usage上跟踪你的使用情况和监控 账单信息。

正如你所见,ChatGPT 是一个易于使用的界面,允许开发者与 GPT 模型进行 NLP 任务交互。 令牌是模型用于处理和理解输入和输出文本的基本文本单元。 ChatGPT API 的定价结构基于处理的令牌数量,每个 API 请求有最低费用。

在下一节中,我们将介绍 如何设置 Python 开发环境 以使用 ChatGPT API。 这包括安装 Python 和 VSCode 的 <st c="17223">venv</st> 模块以及如何在 VSCode 中访问 终端 选项卡。

设置你的 Python 开发环境

在我们开始编写 我们的第一个代码之前,创建一个工作环境并安装任何必要的依赖项是很重要的。 幸运的是,Python 有一个出色的工具系统来管理虚拟环境。 Python 中的虚拟环境是一个复杂的话题,但就本书的目的而言,只需知道它们是独立的 Python 环境,与您的全局 Python 安装分开即可。 这种隔离允许开发者使用不同的 Python 版本,在环境中安装包,并管理项目依赖项,而不会干扰 Python 的 全局安装。

为了在您的 NLP 项目中使用 ChatGPT API,您需要设置您的 Python 开发环境。 本节将指导您完成启动所需的步骤,包括以下内容:

  • 安装 Python

  • 安装 VSCode IDE

  • 安装 <st c="18228">pip</st>

  • 设置 虚拟环境

  • 安装所需的 Python 包

一个正确配置的开发环境 将允许您向 ChatGPT 发送 API 请求,并在您的 Python 代码中处理生成的响应。

安装 Python 和 VSCode IDE

Python 是一种流行的 编程语言 ,被广泛用于各种目的,包括机器学习和数据分析。 您可以从官方网站下载并安装 Python 的最新 版本, https://www.python.org/downloads/ (见 图 1.7**.7). 为了验证 Python 是否已安装,您可以在设备上的终端中输入以下内容:

 $ python --version

一旦您下载了 Python 安装程序,只需按照说明在您的计算机上安装 Python 即可。 下一步是选择一个 IDE 来 与之配合。

Figure 1.7 – Python installation

Figure 1.7 – Python installation

Python 开发者中一个流行的选择是 VSCode,这是一个强大且用户友好的 IDE。 VSCode 提供了一系列功能,使开发 Python 应用程序变得容易,包括代码补全、调试工具和项目 管理功能。

要安装 VSCode,您可以从 VSCode 网站免费 下载它https://code.visualstudio.com/download。下载安装程序后,只需 按照说明在您的计算机上安装 VSCode。

设置 Python 虚拟环境

设置 Python 虚拟环境 是创建项目独立开发环境的关键步骤。 通过创建虚拟环境,您可以在不干扰系统上其他项目的情况下安装特定版本的 Python 包和依赖项。 您的系统。

为您的 ChatGPT 应用程序项目创建特定的 Python 虚拟环境是一种推荐的最佳实践。 这样做可以确保所有包和依赖项都保存在您的项目文件夹中,而不是弄乱您计算机的全局 Python 安装。 这种方法为项目开发和执行提供了一个更组织化和隔离的环境。

VSCode IDE 允许您使用其内置终端设置 Python 虚拟环境。 您可以通过以下步骤设置您的 VSCode 项目:

  1. 在您的计算机上启动 VSCode。

  2. 使用文件资源管理器或 <st c="21665">ChatGPTResponse</st>

  3. 创建文件夹后,通过选择文件 | 打开文件夹 并导航到您刚刚创建的文件夹来在 VSCode 中打开它。

  4. 在打开的文件夹内,创建一个新的 Python 文件,您将在其中编写代码。 您可以通过在 <st c="21997">.py</st> 扩展名上右键单击,例如 <st c="22017">app.py</st>

  5. 通过选择视图 | 终端 从菜单中打开 VSCode 的集成终端。

  6. 进入您的项目文件夹后,运行以下命令创建虚拟环境。 第二个 <st c="22218">venv</st> 参数指的是您的虚拟环境文件夹名称:

    <st c="22349">venv</st> that contains the virtual environment (see *<st c="22397">Figure 1</st>**<st c="22405">.8</st>*). You can replace <st c="22427">venv</st> with any name you want.
    
  7. 要激活虚拟环境,请运行以下 终端命令:

    • 在 Windows 上,运行以下终端命令以激活 虚拟环境:

      <st c="22612">$ venv\Scripts\activate.bat</st>
      
    • 在 macOS 或 Linux 上,运行以下终端命令来激活虚拟环境:

      <st c="22731">$ source venv/b</st><st c="22747">in/activate</st>
      

图 1.8 – VSCode 项目层次结构

图 1.8 – VSCode 项目层次结构

一旦激活,您应该在命令提示符或终端中看到虚拟环境的名称,如图所示。 从这里,您可以安装您项目所需的任何包或依赖项,而不会干扰系统上的其他 Python 安装:

 ChatGPTResponse % source venv/bin/activate <st c="23141">(venv)</st> ChatGPTResponse % <st c="23166">(venv)</st> ChatGPTResponse %

重要提示

为了保持一致性,您需要为每个新创建的 Python 项目激活虚拟环境。

安装任何 Python 包的关键组件是 pip 。让我们看看如何检查 pip 是否已安装在您的系统上,以及如果需要的话如何安装它

pip 包安装器

pip 是 Python 的包安装器。 它允许您轻松安装和管理第三方 Python 库和包,例如 <st c="23640">openai</st> <st c="23646">。如果您使用的是 Python 的较新版本,</st> pip 应该已经安装。 您可以通过打开命令提示符或终端并键入 <st c="23831">pip</st> <st c="23834">然后按下</st> *<st c="23860">Enter</st> <st c="23865">键来检查您的系统上是否已安装 pip。</st> <st c="23871">如果</st> pip 已安装,您应该会看到一些描述其用法和命令的输出。

如果您的系统上没有安装 pip,您可以通过以下步骤安装它:

  1. 首先,从 get-pip.py 脚本从官方 Python 网站下载: https://bootstrap.pypa.io/get-pip.py

  2. 将文件保存到您容易访问的位置,例如桌面或 下载文件夹。

  3. 打开命令提示符或终端,导航到您保存 get-pip.py 文件的目录。

  4. 运行以下命令来安装 pip: python get-pip.py

  5. 安装完成后,您可以通过在命令提示符或终端中键入 pip 并按下 *Enter 键来验证 pip 是否已安装。

你现在应该已经在你的系统上安装了 pip,并且可以使用它来安装 Python 的包和库

这是一份关于如何在 NLP 项目中使用 ChatGPT API 设置 Python 开发环境的完整指南。 设置虚拟环境是在创建一个独立开发环境的过程中一个关键步骤 为你的项目。 你现在可以准备使用 Python 与 ChatGPT API 进行交互,完成你的第一个实践练习,以与 OpenAI 库进行交互。

一个简单的 ChatGPT API 响应

使用 Python 与 ChatGPT API 结合是一个相对简单的过程。首先,你需要确保你已经创建了上一节中描述的名为 <st c="25220">CHATGPTRESPONSE</st> 的目录(参见 图 1**.8)。 一旦设置好,你就可以使用 OpenAI Python 库与 ChatGPT API 进行交互。 在 VSCode 中打开一个新的终端,确保你处于你的项目文件夹和虚拟环境中,并安装 <st c="25506">openai</st> 包:

 $ pip install openai

要开始,你需要将 <st c="25585">openai</st> 库导入到你的 <st c="25610">app.py</st> 文件中。 此外,你还需要提供 <st c="25651">你的 OpenAI API 密钥。</st> 你可以通过遵循本书前几节中概述的步骤从 OpenAI 网站获得 API 密钥。 然后,你需要在 Python 代码中将它设置为参数。 一旦你的 API 密钥设置好,你就可以开始与 <st c="25921">ChatGPT API</st>进行交互:

 from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")

<st c="26008">YOUR_API_KEY</st> 替换为你从 OpenAI 平台页面获得的 API 密钥。 通常,将 API 密钥保存在与你的主要代码相同的文件中并不是一个好的做法。 在下一章中,我们将讨论如何安全地保存这些密钥。 现在,你可以使用 <st c="26285">input()</st> 函数向用户提问:

<st c="26364">input()</st> function is used to prompt the user to input a question they would like to ask the ChatGPT API. The function takes a string as an argument, which is displayed to the user when the program is run. In this case, the question string is <st c="26605">"What would you like to ask ChatGPT?"</st>. When the user types their question and presses *<st c="26691">Enter</st>*, the <st c="26702">input()</st> function will return the string that the user typed. This string is then assigned to the question variable.
			<st c="26817">To pass the user question from your Python script to ChatGPT, you will need to use the ChatGPT API</st> `<st c="26917">create</st>` <st c="26923">function:</st>

response = client.chat.completions.create(

model="gpt-3.5-turbo",

messages=[

    {"role": "user", "content": f"{question}"},

]

max_tokens=512,

n=1,

stop=None,

temperature=0.8,

)


			<st c="27108">The</st> `<st c="27113">client.chat.completions.create()</st>` <st c="27145">function in the code is used to send a request to the ChatGPT API to generate the completion of the user’s input prompt.</st> <st c="27267">The</st> `<st c="27271">model</st>` <st c="27276">parameter allows us to specify the specific variant or version of the GPT model we want to utilize for the request, and in this case, it is set to</st> `<st c="27424">"gpt-3.5-turbo"</st>`<st c="27439">.</st> `<st c="27441">messages</st>` <st c="27449">is a list of dictionaries that specifies the text prompts for the API to complete, which is the user’s input question in</st> <st c="27571">this case.</st>
			<st c="27581">The</st> `<st c="27586">max_tokens</st>` <st c="27596">parameter specifies the maximum number of tokens the request and the response should contain together.</st> <st c="27700">The</st> `<st c="27704">n</st>` <st c="27705">parameter specifies the number of completions to generate for the prompt.</st> <st c="27780">The</st> `<st c="27784">stop</st>` <st c="27788">parameter specifies the sequence where the API should stop generating</st> <st c="27859">the response.</st>
			<st c="27872">The</st> `<st c="27877">temperature</st>` <st c="27888">parameter controls</st> <st c="27907">the creativity of the generated response.</st> <st c="27950">It ranges from</st> `<st c="27965">0</st>` <st c="27966">to</st> `<st c="27970">1</st>`<st c="27971">. Higher values will result in more creative but potentially less coherent responses, while lower values will result in more predictable but potentially less interesting responses.</st> <st c="28152">Later in the book, we will delve into how these parameters impact the responses received</st> <st c="28241">from ChatGPT.</st>
			<st c="28254">The function returns a</st> `<st c="28278">ChatCompletion</st>` <st c="28292">object containing the generated response from the ChatGPT API, which</st> <st c="28361">then can be accessed and printed to the console in the next line</st> <st c="28427">of code:</st>

打印(response)


			<st c="28451">From the terminal, you can run the project through the</st> `<st c="28507">app.py</st>` <st c="28513">file using the</st> <st c="28529">following command:</st>

$ python app.py


			<st c="28563">You should receive a message in the</st> **<st c="28600">TERMINAL</st>** <st c="28608">window that asks you to write a question for ChatGPT (see</st> *<st c="28667">Figure 1</st>**<st c="28675">.9</st>*<st c="28677">).</st>
			![Figure 1.9 – Asking ChatGPT a question](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_01_9.jpg)

			<st c="28843">Figure 1.9 – Asking ChatGPT a question</st>
			<st c="28881">Once you have entered your question, press the</st> *<st c="28929">Enter</st>* <st c="28934">key to submit your request to the ChatGPT API.</st> <st c="28982">The response</st> <st c="28994">generated by the ChatGPT API model will be displayed in the TERMINAL window as a complete</st> `<st c="29085">ChatCompletion</st>` <st c="29099">object:</st>

ChatCompletion(

id='chatcmpl-8xoDCiDPy0ZUzjLtJMTTHZ0keGeEh',

choices=[

    Choice(

        finish_reason='length',

        index=0,

        logprobs=None,

        message=ChatCompletionMessage(

            content='游泳是一种极佳的锻炼方式,也是一项宝贵的生存技能。以下是一些基本步骤来…',

            role='assistant',

            function_call=None,

            tool_calls=None

        )

    )

],

created=1709265058,

model='gpt-3.5-turbo-0125',

object='chat.completion',

system_fingerprint='fp_86156a94a0',

usage=CompletionUsage(

    completion_tokens=20,

    prompt_tokens=11,

    total_tokens=31

)

)


			<st c="29624">This response produced by the OpenAI API contains information about the response generated by the GPT-3.5 model.</st> <st c="29738">This response consists of the</st> <st c="29768">following fields:</st>

				*   <st c="29785">The</st> `<st c="29790">id</st>` <st c="29792">field is a unique identifier for the API request that generated</st> <st c="29857">this response.</st>
				*   <st c="29871">The</st> `<st c="29876">choices</st>` <st c="29883">field contains an array of objects with the generated responses, which in this case only contains one response object as the</st> <st c="30009">parameter</st> `<st c="30019">n=1</st>`<st c="30022">.</st>
				*   <st c="30023">The</st> `<st c="30028">finish_reason</st>` <st c="30041">field indicates the reason why the response was generated; in this case, it was because the model reached the</st> `<st c="30152">stop</st>` <st c="30156">condition provided in the request.</st> <st c="30192">Since in our case</st> `<st c="30210">stop=None</st>`<st c="30219">, the full response from the ChatGPT API</st> <st c="30260">was returned.</st>
				*   <st c="30273">The</st> `<st c="30278">index</st>` <st c="30283">variable of this particular choice in the array of choices, we can see only</st> `<st c="30360">index=0</st>` <st c="30367">as</st> `<st c="30371">n=0</st>`<st c="30374">.</st>
				*   <st c="30375">The</st> `<st c="30380">created</st>` <st c="30387">field specifies the Unix timestamp of when the response</st> <st c="30444">was created.</st>
				*   <st c="30456">The</st> `<st c="30461">model</st>` <st c="30466">field specifies the GPT-3.5 model that was used to generate</st> <st c="30527">the response.</st>
				*   <st c="30540">The</st> `<st c="30545">object</st>` <st c="30551">field specifies the type of object that was returned, which in this case</st> <st c="30625">is</st> `<st c="30628">chat.completion</st>`<st c="30643">.</st>
				*   `<st c="30644">system_fingerprint</st>` <st c="30663">is an identifier for the current combination of model weights</st> <st c="30726">and infrastructure.</st>

			<st c="30745">The</st> `<st c="30750">ChatCompletionMessage</st>` <st c="30771">object includes the information related to the specific ChatGPT response.</st> <st c="30846">It includes</st> <st c="30858">the following:</st>

				*   `<st c="30872">content</st>`<st c="30880">: The completed answer generated by</st> <st c="30917">the model</st>
				*   `<st c="30926">role</st>`<st c="30931">: Indicates the role of the message; in this case, it’s from</st> <st c="30993">the assistant</st>
				*   `<st c="31006">function_call</st>`<st c="31020">: Any function calls associated with</st> <st c="31058">the completion</st>
				*   `<st c="31072">tool_calls</st>`<st c="31083">: Any tool calls associated with</st> <st c="31117">the completion</st>

			<st c="31131">Finally, the</st> `<st c="31145">usage</st>` <st c="31150">field provides information about the resource usage of the API request.</st> <st c="31223">It contains information about the number of tokens used for the completion, the number of tokens in the prompt, and the total number of</st> <st c="31359">tokens used.</st>
			<st c="31371">The most important parameter</st> <st c="31400">from the response is the</st> `<st c="31426">message</st>` <st c="31433">field, which contains the answer to the question asked to the ChatGPT API.</st> <st c="31509">This is why most API users would like to access only that parameter from the</st> `<st c="31586">ChatCompletion</st>` <st c="31600">object.</st> <st c="31609">You can easily separate the text from the main body</st> <st c="31661">as follows:</st>

answer = response.choices[0].message.content

print("OpenAI:" + answer)


			<st c="31743">By following this approach, you can guarantee that the</st> `<st c="31799">answer</st>` <st c="31805">variable will hold the complete ChatGPT API text</st> <st c="31854">response, which you can then print to verify.</st> <st c="31901">Keep in mind that ChatGPT responses can significantly differ depending on the input, making each</st> <st c="31998">response unique:</st>

OpenAI:

游泳是一种极佳的锻炼方式,也是一项宝贵的生存技能。以下是一些基本步骤:

1. 首先进入水中。如果你在游泳池游泳,你可以从侧面、梯子或跳板进入水中。如果你在海边或湖中游泳,你可以从岸边或码头进入水中。2. 深吸一口气,然后慢慢呼出。这有助于你放松并准备游泳。


			<st c="32443">ChatGPT can be employed for a multitude of NLP tasks across a wide array of topics accessible in the vast expanse of information.</st> <st c="32574">We can utilize our script to inquire about diverse areas of expertise and receive advanced responses from the ChatGPT API, as</st> <st c="32700">demonstrated here:</st>

				*   <st c="32718">Solving</st> <st c="32727">mathematical problems:</st>
    *   **<st c="32749">User</st>**<st c="32754">: What is the square root</st> <st c="32781">of 256?</st>
    *   **<st c="32788">ChatGPT</st>**<st c="32796">: The square root of 256</st> <st c="32822">is 16.</st>
				*   <st c="32828">Performing</st> <st c="32840">sentiment analysis:</st>
    *   **<st c="32859">User</st>**<st c="32864">: Analyze the sentiment of the sentence “I had a great</st> <st c="32920">day today!”</st>
    *   **<st c="32931">ChatGPT</st>**<st c="32939">: The sentiment of the sentence “I had a great day today!”</st> <st c="32999">is positive.</st>
				*   <st c="33011">Helping with</st> <st c="33025">programming tasks:</st>
    *   `<st c="33169">variable_name =</st>` `<st c="33185">value</st>`<st c="33190">.</st>
				*   <st c="33191">Improving</st> <st c="33202">scientific knowledge:</st>
    *   **<st c="33223">User</st>**<st c="33228">: What is the process of photosynthesis</st> <st c="33269">in plants?</st>
    *   **<st c="33279">ChatGPT</st>**<st c="33287">: The process of photosynthesis in plants is the fundamental mechanism by which they convert light energy into</st> <st c="33399">chemical energy.</st>
				*   <st c="33415">Answering questions related</st> <st c="33444">to literature:</st>
    *   **<st c="33458">User</st>**<st c="33463">: What are the major themes in Shakespeare’s</st> <st c="33509">play “Hamlet”?</st>
    *   **<st c="33523">ChatGPT</st>**<st c="33531">: “Hamlet,” one of Shakespeare’s most renowned tragedies, explores several major themes that continue to captivate audiences and</st> <st c="33661">provoke thought.</st>

			<st c="33677">In this section, you learned how to use the OpenAI Python</st> <st c="33735">library to interact with the ChatGPT API by sending a request to generate the completion of a user’s input prompt/question.</st> <st c="33860">You also learned how to set up your API key and how to prompt the user to input a question, and finally, how to access the generated response from ChatGPT in the form of an object containing information about the response.</st> <st c="34083">You are now ready to build more complex projects and integrate the ChatGPT API with</st> <st c="34167">other frameworks.</st>
			<st c="34184">Summary</st>
			<st c="34192">In this chapter, you learned the basics of getting started with the ChatGPT API.</st> <st c="34274">We covered the concept of NLP and how ChatGPT has revolutionized the field.</st> <st c="34350">You also learned how to access the ChatGPT API through the web interface and how to create an</st> <st c="34444">OpenAI account.</st>
			<st c="34459">We dived into the technical details of using the ChatGPT API, including obtaining an API key, API tokens, and pricing.</st> <st c="34579">We covered how to set up a Python development environment, specifically using the VSCode IDE, and creating a virtual environment.</st> <st c="34709">To help you get started with using the ChatGPT API, we walked through a simple example of obtaining a ChatGPT</st> <st c="34819">API response.</st>
			*<st c="34832">Chapter 2</st>*<st c="34842">,</st> *<st c="34844">Building a ChatGPT Clone</st>*<st c="34868">, builds upon the foundational knowledge gained in this chapter by guiding you through the process of creating your own ChatGPT clone using the Flask framework.</st> <st c="35029">This chapter will provide you with a comprehensive overview of how to seamlessly integrate the ChatGPT API with Flask to develop your first end-to-end</st> <st c="35180">AI application.</st>

第三章:构建一个 ChatGPT 克隆

本章和本书的第一个应用将是一个ChatGPT 克隆,它利用 OpenAI 强大的语言模型对用户输入生成类似人类的响应。该应用将使用Flask构建,这是一个用于 Python 的轻量级 Web 框架,并具有简单优雅的前端界面,供用户与之交互。 只需几行代码,用户就可以输入文本并接收由 OpenAI 语言模型生成的响应。 具体来说,该应用将能够渲染一个简单的浏览器聊天界面,与聊天机器人进行交互。 聊天机器人将接受用户输入并将其发送到 ChatGPT API,向用户显示 ChatGPT API 的响应,并显示聊天历史。

克隆应用将能够接收用户的输入,将其发送到 OpenAI 的 API,并实时接收响应,这些响应将显示给用户。该应用将可定制,以便使用不同的 OpenAI 模型以及其他选项,例如生成的文本的长度。

初始时,我们的聊天机器人将缺乏维持上下文对话的能力。虽然它将根据单个查询生成响应,但它将不具备保留先前交互信息的记忆。 然后,我们将介绍一种简单而有效的技术,帮助我们的聊天机器人保持对话上下文,使用 GPT-3.5 模型的字典结构和角色。 我们将探讨使我们的聊天机器人在进行中的对话上下文中理解和连贯响应的技术和工具。

在本章中,我们将涵盖以下主题:

  • 使用 Flask 创建一个 ChatGPT 克隆

  • 生成 ChatGPT 克隆的HTML

  • 截获 ChatGPT 的 API 端点

  • OpenAI 的 ChatGPT API 用于 文本生成

  • 通过使用AJAX将用户输入从前端传递到后端

  • 在前端显示生成的文本

  • 保留和更新聊天上下文

当使用 Flask 构建一个 ChatGPT 克隆时,有一些事项需要牢记。设置一个 Python 虚拟环境来将您的依赖项与其他机器上的项目分离是很重要的。 这确保了您的项目拥有所有必要的依赖项,并且不会与其他项目发生冲突。 此外,请确保安全地存储您的 ChatGPT API 密钥,以避免未经授权的访问。 管理您的 API 请求也很重要,因为价格是基于处理令牌的数量。 最后,Flask 在如何构建您的应用程序方面提供了灵活性,但随着项目的增长,保持代码的整洁和可维护性同样重要。 项目。

技术要求

为了充分利用本章内容,您将需要一些基本工具。将提供前一章未涵盖的所有安装的深入解释。

您将需要以下内容:

  • Python 3.7 或更高版本已安装在您的计算机上

  • OpenAI API 密钥,从您的 OpenAI 账户 获取

  • 一个代码编辑器,例如 VSCode(推荐)

  • 在您的 Python 虚拟环境 中安装的 Flask 框架

本章的代码示例可以在 GitHub 上找到 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

在下一节中,我们将开始使用 Flask 构建 ChatGPT 克隆,通过设置一个与 ChatGPT API 通信以生成对用户输入的响应的后端来构建 ChatGPT 克隆。您将创建一个简单的 Flask 应用程序,并通过集成 ChatGPT API 来逐步增强它。 我们还将对代码进行结构化,并将 ChatGPT API 密钥作为环境变量存储,以提高其安全性。

使用 Flask 创建 ChatGPT 克隆

要使用 Flask 创建一个 ChatGPT 克隆,您需要设置一个后端,该后端与 ChatGPT API 通信以生成对用户输入的响应。Flask 是一个流行的 Python 网络框架,可用于创建包括 ChatGPT 克隆在内的网络应用程序。 我们将从创建一个简单的 Flask 应用程序开始我们的项目,并通过集成 ChatGPT API、额外的网页和前端来逐步增强它。 我们将开始我们的项目,创建一个简单的 Flask 应用程序,并通过集成 ChatGPT API 来逐步增强它。 我们还将对代码进行结构化,并将 ChatGPT API 密钥作为环境变量存储,以提高其安全性。

  1. 要开始,创建一个新的文件夹并将其命名为 <st c="4133">ChatGPT_Clone</st>。按照 第一章 中概述的步骤创建并激活你的 Python 虚拟环境。 创建一个名为 <st c="4267">app.py</st> 的新文件,作为应用程序的后端,你将在其中定义 Flask 应用程序并与 ChatGPT API 交互。 创建项目后,你需要使用 <st c="4481">pip</st> 安装 Flask 包。 你可以在项目的终端中运行以下命令来完成此操作:

    <st c="4778">Flask</st> class and pass your application’s name as an argument. Here’s how you can create a new Flask app in your <st c="4889">app.py</st> file:
    
    

    from flask import Flask

    app = Flask(name)

    
    
  2. 在 Flask 中,路由是用户可以访问的你的应用程序中的 URL 路径。 你可以使用 <st c="5055">@app.route</st> 装饰器和 Python 函数来定义路由。 让我们创建一个显示 <st c="5134">Hello, World!</st> 的路由,如下所示:

     @app.route("/")
    def index():
        return "Hello, World!"
    
  3. 最后,你可以使用 <st c="5258">app.run()</st> 方法运行你的 Flask 应用程序。 这将允许你启动一个开发服务器,你可以在你的 网络浏览器 中访问它:

     if __name__ == "__main__":
        app.run()
    
  4. 一旦你 创建了运行配置,你可以通过点击 <st c="5557">app.py</st> 并选择 运行 选项来运行你的 Flask 应用程序。 然后你将在 运行 窗口中看到你的 Flask 应用的 URL,如图 图 2** 所示。1*:

图 2.1 – Flask 应用程序 URL

图 2.1 – Flask 应用程序 URL

按照这些步骤,你可以构建一个基本的 Flask 应用程序,当用户访问应用程序的根 URL 时,它会显示 <st c="6020">Hello, World!</st> 从这里,你可以向 Flask 应用程序添加更多路由、模板和功能,使用 ChatGPT API 构建更复杂的 Web 应用程序(见图 图 2**.2*)。

图 2.2 – Flask 应用程序页面

图 2.2 – Flask 应用程序页面

每个 ChatGPT 应用程序都从设置你的 API 密钥开始。 当在 Python 文件中使用 ChatGPT API 密钥时,你通常会直接将密钥硬编码到文件中,就像你在构建简单的 ChatGPT API 响应时做的那样,这意味着密钥在代码本身中是可见的。 如果有人获取了代码或你意外地将代码推送到公共仓库,这可能会带来安全风险。

另一方面,将 ChatGPT API 密钥作为环境变量添加意味着密钥存储在代码库之外,并且可以在运行时由代码访问。 这使得它更安全,因为密钥不在代码本身中可见,并且可以轻松更改而无需修改 代码。

另一种安全存储 API 密钥的方法是将它添加到一个单独的文件中,该文件保存在你的 Git 仓库之外。 要遵循这种方法,让我们创建 <st c="7173">config.py</st> ,然后使用 <st c="7200">config</st> 包从 <st c="7233">app.py</st>中访问它。以下代码是相应地构建这两个文件的示例: 文件:

config.py

 API_KEY = "YOUR_API_KEY"

app.py

 from flask import Flask <st c="7384">import config</st>
<st c="7397">client = OpenAI(</st>
 <st c="7414">api_key=config.API_KEY,</st>
<st c="7438">)</st> app = Flask(__name__)
@app.route("/")
def index():
    return "Hello, World!" if __name__ == "__main__":
    app.run()

重要提示

如果你想要将你的 项目推送到 Git 仓库,重要的是要将 <st c="7648">config.py</st> 文件添加到你的项目的 <st c="7681">.gitignore</st> 文件中,以防止意外将你的 API 密钥提交到 版本控制。

让我们修改 你的 <st c="7804">index()</st> 函数的功能,通过 配置它从前端返回一个 HTML 模板:

 @app.route("/")
def index(): <st c="8020">("/")</st>. When a user navigates to the root URL, Flask will call the function decorated with <st c="8110">@app.route("/")</st>.
			<st c="8126">The function returns the result of</st> `<st c="8162">render_template("index.html")</st>`<st c="8191">. The</st> `<st c="8197">render_template</st>` <st c="8212">function is a Flask method that renders an HTML template.</st> <st c="8271">In this case, it renders the</st> `<st c="8300">index.html</st>` <st c="8310">template that will be created in the text section.</st> <st c="8362">You can also modify your imports to incorporate the</st> `<st c="8414">render</st>` <st c="8420">function:</st>

flask库导入Flask<st c="8576">index.html</st>文件通常是用户加载 Web 应用程序时看到的第一个页面。这是用户输入初始输入以开始与 ChatGPT API 聊天的地方。

        <st c="8768">下一步是构建一个函数,该函数将获取 ChatGPT API 的响应,这样你就可以在你的聊天克隆中使用该响应。</st> <st c="8904">你可以通过在`<st c="8986">index()</st>` <st c="8993">函数下方构建`<st c="8943">get_bot_response()</st>` <st c="8961">函数来轻松完成此操作:</st>
 @app.route("/get")
def get_bot_response():
    userText = request.args.get('msg')
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
        {"role": "user", "content": f"{userText}"},
    ],
        max_tokens=1024,
        n=1,
        stop=None,
        temperature=1,
    )
    answer = response.choices[0].message.content
    return str(answer)
        <st c="9319">此代码</st> <st c="9330">为 Flask 应用程序设置了一个</st> `<st c="9340">/get</st>` <st c="9344">路由。</st> <st c="9370">当用户请求此路由时,</st> `<st c="9403">get_bot_response()</st>` <st c="9421">被调用。</st>

        <st c="9432">使用</st> `<st c="9437">request.args.get()</st>` <st c="9455">方法从 URL 查询字符串中检索`<st c="9500">msg</st>` <st c="9503">参数的值。</st> <st c="9541">此参数用作 ChatGPT API 的输入。</st> <st c="9598">稍后,我们将在前端创建一个按钮,当选择时将激活</st> `<st c="9668">/get</st>` <st c="9672">路由。</st>

        `<st c="9688">The</st>` `<st c="9693">client.chat.completions.create()</st>` 方法用于从 ChatGPT API 生成响应。它接受多个参数,例如要使用的模型、提供给 API 的消息以及响应中要生成的标记数量。

        `<st c="9933">在生成响应后,该函数使用字典键从 API 的响应中提取响应文本。</st>` `<st c="10052">最后,响应作为</st>` `<st c="10089">字符串返回。</st>`

        `<st c="10098">当用户键入消息并点击发送时,JavaScript 代码将向此路由发出 HTTP 请求以获取 AI 响应,然后将其显示在</st>` `<st c="10252">网页上。</st>`

        `<st c="10261">为了最终确定您的聊天机器人应用程序的后端,更新您的导入并添加任何必要的包</st>` `<st c="10384">以供</st>` `<st c="10388">get_bot_response()</st>` `<st c="10406">使用:</st>`
 from flask import Flask, <st c="10434">request</st>, render_template <st c="10459">from openai import OpenAI</st> import config
        `<st c="10498">这就是您如何通过安装 Flask、定义路由、设置 API 密钥、创建 HTML 模板以及构建从 ChatGPT API 获取响应的功能来高效地创建 Flask 应用程序的方法。</st>` `<st c="10691">您还学习了如何构建配置文件的结构,并强调了保护</st>` `<st c="10820">API 密钥的重要性。</st>`

        `<st c="10828">在下一节中,您将学习如何将后端端点连接到聊天应用程序的前端。</st>` `<st c="10943">我们还将使用</st>` **`<st c="10960">jQuery</st>`** `<st c="10966">来处理前端和后端之间的通信,允许在聊天应用程序中进行实时消息传递。</st>`

        `<st c="11086">前端 HTML 生成</st>`

        `<st c="11111">让我们开始创建生成我们聊天应用前端的必要 HTML 和 CSS。</st>` `<st c="11175">我们将使用 HTML、CSS 和 Bootstrap 来创建</st>` `<st c="11262">用户</st>` `<st c="11271">界面,并使用 jQuery 来处理前端和后端之间的通信。</st>` `<st c="11358">HTML 和 CSS 将负责创建用户界面的结构和样式。</st>`

        `<st c="11454">在创建 Flask 网络应用程序时,建议将您的 HTML 文件保存在一个名为</st>` `<st c="11564">templates</st>` `<st c="11573">的单独文件夹中。这是因为</st>` `<st c="11591">Flask 使用</st>` `<st c="11606">Jinja2</st>` `<st c="11612">模板引擎,它允许您通过将其分成更小、可重用的部分来以更模块化的方式编写可重用的 HTML 代码,这些部分被称为模板。</st>`

        要创建`<div>templates</div>`文件夹,只需在项目目录中创建一个新的目录并命名为`<div>templates</div>`<div>。在`<div>templates</div>`文件夹内,您可以创建您的 HTML 文件,在这个例子中称为`<div>index.html</div>`。</div>要这样做,右键单击`<div>templates</div>`文件夹并选择**<div>New</div>** **<div>HTML file</div>**<div>。以下是项目目录应该看起来像什么:</div>
 ChatGPTChatBot/
├── config.py
├── app.py
├── templates/
│   └── index.html
        创建一个`<div>templates</div>`文件夹很重要,因为它允许您将 HTML 文件与 Python 代码分开组织,这使得管理和管理您的 Web 应用更容易。</div>此外,Flask 框架专门设计为查找模板文件夹以渲染 HTML 模板,因此创建此文件夹对于您的`<div>Flask 应用</div>`的正常运行是必要的。

        我们现在可以使用 HTML 和 Bootstrap 创建我们的聊天应用的前端。</div>最初,我们的前端代码将包含一个基本的布局,包括聊天窗口、输入字段和提交按钮。</div>您可以将以下代码包含在您的`<div>index.html</div>`文件中:
 <!DOCTYPE html>
<html>
<head>
    <title>OpenAI GPT Chat</title>
</head>
<body>
    <div class="container">
        <h2>OpenAI GPT Chat</h2>
        <hr>
        <div class="panel panel-default">
            <div class="panel-heading">Chat Messages</div>
            <div class="panel-body" id="chat">
                <ul class="list-group">
                </ul>
            </div>
        </div>
        <div class="input-group">
            <input type="text" id="userInput" class="form-control">
            <span class="input-group-btn">
                <button class="btn btn-default" id="submit">Submit</button>
            </span>
        </div>
    </div>
</body>
</html>
        `<div>!</div>`在代码开头的声明表示文档类型和版本。</div> `<div>!</div>`标签表示 HTML 文档的开始,而`<div>!</div>`标签包含有关文档的信息,例如文档的标题,该标题在`<div>!</div>`标签中指定。</div> `<div>!</div>`标签包含在浏览器中显示的文档的可视内容,包括聊天历史和用户消息。

        在 HTML 中,`<div>`元素是一个容器,用于将其他 HTML 元素分组并作为一个组应用样式。</div>它没有固有的语义意义,但其灵活性允许网页开发者以结构化的方式创建布局和组织内容。

        <st c="14040">第一个</st> `<st c="14051"><div></st>` <st c="14056">元素是一个容器的类属性。</st> <st c="14102">整个聊天应用程序都将包含在这个容器中。</st> <st c="14171">我们还有一个</st> `<st c="14187"><h2></st>` <st c="14191">元素,其文本为</st> `<st c="14214">"OpenAI GPT Chat"</st>`<st c="14231">。这是聊天应用程序的标题。</st>

        <st c="14275">接下来,我们有一个</st> `<st c="14293"><hr></st>` <st c="14297">元素,它用于创建一条水平线,以将标题与聊天界面的其余部分分开。</st> <st c="14408">之后,我们还有一个</st> `<st c="14440"><div></st>` <st c="14445">元素,其类属性为</st> `<st c="14480">panel panel-default</st>`<st c="14499">。这个</st> `<st c="14505">panel</st>` <st c="14510">将构建一个带有边框的容器,包含其中的内容,并通过填充提供额外的空间。</st> <st c="14640">此类用于创建一个包含聊天消息历史的面板。</st> <st c="14721">在聊天历史窗口中,还有两个</st> <st c="14763">更多元素。</st>

        <st c="14777">第一个</st> `<st c="14788"><div></st>` <st c="14793">元素具有类属性</st> `<st c="14827">panel-heading</st>` <st c="14840">并包含</st> `<st c="14858">"Chat Messages"</st>` <st c="14873">文本。</st> <st c="14880">这是包含聊天消息的面板的标题。</st>

        <st c="14950">第二个</st> `<st c="14962"><div></st>` <st c="14967">元素具有类属性</st> `<st c="15001">panel-body</st>` <st c="15011">和一个</st> `<st c="15019">id</st>` <st c="15021">属性为</st> `<st c="15035">chat</st>`<st c="15039">。此元素将用于显示聊天消息。</st> <st c="15097">在这个</st> `<st c="15109"><div></st>` <st c="15114">元素内部,我们有一个带有类属性</st> `<st c="15189">list-group</st>`<st c="15199">的无序列表元素,它将包含单个</st> <st c="15235">聊天消息。</st>

        <st c="15249">接下来,我们将</st> <st c="15264">构建一个输入框,用户可以在此输入他们的消息,以及一个提交按钮,将消息发送到服务器进行处理。</st> <st c="15391">输入框是通过使用</st> `<st c="15426"><input></st>` <st c="15433">标签并设置</st> `<st c="15443">type="text"</st>`<st c="15454">创建的。输入框有一个类为</st> `<st c="15485">"form-control"</st>`<st c="15499">,这是一个 Bootstrap 类,用于样式化表单</st> <st c="15549">控件元素。</st>

        <st c="15566">具有</st> `<st c="15606"><button></st>` <st c="15614">ID 为</st> `<st c="15633">submit</st>`<st c="15639">的</st> `<st c="15645">tag</st>` <st c="15656">类是 Bootstrap 类,用于将输入框和“提交”</st> <st c="15729">按钮组合在一起。</st>

        <st c="15745">一旦创建了基本的 HTML 文件,你可以通过运行</st> `<st c="15832">app.py</st>` <st c="15838">文件来激活你的应用程序(见</st> *<st c="15849">图 2</st>**<st c="15857">.3</st>*<st c="15859">)。</st>

        ![图 2.3 – 初始 ChatGPT 克隆前端](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_02_3.jpg)

        <st c="15918">图 2.3 – 初始 ChatGPT 克隆前端</st>

        <st c="15961">界面将包含一个标题,显示为</st> **<st c="16006">OpenAI GPT 聊天</st>**<st c="16021">,一个显示消息的聊天面板,以及底部的一个输入框,用户可以在其中输入他们的消息。</st> <st c="16140">此外,输入框旁边还将有一个</st> **<st c="16161">提交</st>** <st c="16167">按钮。</st> <st c="16198">然而,由于后端端点</st> <st c="16279">尚未连接到应用程序的前端</st> <st c="16316">,聊天功能目前还不能使用。</st>

        <st c="16332">在本节中,我们讨论了如何使用 HTML 创建聊天应用程序的前端。</st> <st c="16424">我们在 Flask 中创建了</st> `<st c="16439">模板</st>` <st c="16448">文件夹,用于基本聊天界面的可重用 HTML 模板,包括聊天窗口、输入字段和提交按钮。</st> <st c="16574">现在我们可以探索不同的方法来自定义应用程序的外观,例如更改字体和添加图标,使其更具</st> <st c="16713">视觉吸引力。</st>

        <st c="16732">增强 ChatGPT 克隆设计</st>

        <st c="16767">为了增强 ChatGPT 克隆的设计和美学,我们将应用一些 CSS 代码。</st> <st c="16862">通过应用 CSS 修改,我们可以提高聊天应用程序的整体视觉吸引力,并创建一个更</st> <st c="16976">用户友好的界面。</st>

        <st c="17000">让我们首先添加由 Bootstrap 框架提供的样式表。</st> <st c="17078">为此,在页面标题下,你可以添加以下内容:</st> <st c="17124">以下内容:</st>
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
        <st c="17239">将其添加到 HTML 代码中后,它允许使用 Bootstrap 提供的各种类来样式化网页。</st> <st c="17355">此链接指向 Bootstrap 框架的</st> `<st c="17383">3.3.7</st>` <st c="17388">版本,并包括用于样式化常见 HTML 元素(如标题、段落、表单和按钮等)的 CSS 规则。</st> <st c="17548">使用 Bootstrap 可以帮助确保网页设计的统一性,同时简化样式化任务,并使页面能够适应不同的</st> <st c="17712">屏幕尺寸。</st>

        <st c="17725">接下来,在 Bootstrap 链接下,我们可以包含 CSS 代码,用于自定义 body 元素的背景颜色和文本颜色,设置</st> `<st c="17881">margin-top</st>` <st c="17891">属性</st>的`<st c="17908">container</st>` <st c="17917">类,调整聊天消息区域的`<st c="17917">高度</st>`和`<st c="17917">溢出</st>`属性,以及样式化“提交”按钮和</st> `<st c="18033">输入字段</st>`:
 <style>
        body {
            background-color: #35372D;
            color: #ededf2;
        }
        .container {
            margin-top: 20px;
        }
        #chat {
            height: 400px;
            overflow-y: scroll;
            background-color: #444654;
        }
        .list-group-item {
            border-radius: 5px;
            background-color: #444654;
        }
        .submit {
            background-color:#21232e;
            color: white;
            border-radius: 5px;
        }
        .input-group input {
            background-color: #444654;
            color: #ededf2;
            border: none;
        }
    </style>
        <st c="18439">The</st> `<st c="18444">body</st>` <st c="18448">规则将页面的背景颜色设置为深绿色灰色,并将文本颜色设置为浅灰色。</st> <st c="18564">The</st> `<st c="18568">.container</st>` <st c="18578">规则在容器元素顶部应用 20 像素的边距,这将使聊天界面从页面顶部向下移动一点。</st> <st c="18715">The</st> `<st c="18719">#chat</st>` <st c="18724">规则将聊天消息显示区域的高度设置为 400 像素,并在内容超过</st> <st c="18867">高度限制时应用垂直滚动条。</st>

        <st c="18880">The</st> `<st c="18885">.list-group-item</st>` <st c="18901">块设置了在聊天面板中显示的列表项的边框半径和背景颜色。</st> <st c="18999">The</st> `<st c="19003">.submit</st>` <st c="19010">块设置了`.input-group` <st c="19100">输入块</st>的背景颜色、文本颜色和边框半径,输入块样式化输入组内的输入字段,设置背景颜色和文本颜色并移除边框。</st> <st c="19241">您可以通过停止并重新运行</st> <st c="19330">您的项目</st>来验证所有 CSS 更改是否正确实施。

        <st c="19343">这些样式</st> <st c="19357">有助于实现一个统一且视觉上吸引人的设计。</st> <st c="19413">现在您可以重新运行应用程序,以查看 ChatGPT 克隆应用程序的最终样式。</st> <st c="19489">clone application。</st>

        <st c="19507">在本节中,我们使用 CSS 代码改进了 ChatGPT 克隆的设计,包括从 Bootstrap 中引入的外部样式表和自定义 CSS 修改。</st> <st c="19664">在下一节中,您将学习如何使用 Flask 拦截 ChatGPT API 端点。</st> <st c="19752">这将允许您创建自定义路由,在 ChatGPT 克隆应用程序的前端和后端服务器之间发送和接收 HTTP 请求。</st>

        <st c="19907">拦截 ChatGPT API 端点</st>

        <st c="19942">我们的 ChatGPT 克隆需要使用 JavaScript 来实时处理与聊天应用程序的用户交互</st> <st c="20039">。</st> <st c="20053">为此,我们可以使用一个 jQuery 脚本,该脚本监听对服务器的</st> `<st c="20189">GET</st>` <st c="20192">请求,其中用户输入作为查询参数,然后从 ChatGPT 接收响应。</st> <st c="20300">以这种方式使用 JavaScript 将使聊天应用程序能够在不刷新页面的情况下更新和显示新的聊天消息,从而提供更流畅和</st> <st c="20475">用户友好的体验。</st>

        <st c="20500">我们可以在</st> `<st c="20549">input-group</st>` <st c="20560">类下面编写 JavaScript 代码,如下所示:</st>
 <div class="input-group">
            <input type="text" id="userInput" class="form-control">
            <span class="input-group-btn">
                <button class="btn btn-default" id="submit">Submit</button>
            </span>
        </div>
    </div> <st c="20778"><script src="img/jquery.min.js"></script></st>
 <st c="20866"><script></st>
 <st c="20875">$("#submit").click(function(){</st>
 <st c="20906">var userInput = $("#userInput").val();</st>
 <st c="20945">$.get("/get?msg=" + userInput, function(data){</st>
 <st c="20992">$("#chat").append("<li class='list-group-item'><b>You:</b> " + userInput + "</li>");</st>
 <st c="21077">$("#chat").append("<li class='list-group-item'><b>OpenAI:</b> " + data + "</li>");</st>
 <st c="21160">});</st>
 <st c="21164">});</st>
 <st c="21168"></script></st> </body>
</html>
        <st c="21194">JavaScript 将使我们的应用程序更加动态和响应。</st> <st c="21261">以下是如何实现前面的代码片段:</st>

            1.  首先,我们包含了来自谷歌的 jQuery 库<st c="21315">,使用</st> <st c="21337">Google</st> `<st c="21485">$("#submit")</st>` <st c="21497">选择器用于选择具有 ID 为</st> `<st c="21557">submit</st>`<st c="21563">的 HTML 元素,它就是</st> `<st c="21621">.click()</st>` <st c="21629">方法被用来附加一个点击事件监听器到这个元素。</st> <st c="21700">每次用户点击</st> **<st c="21731">提交</st>** <st c="21737">按钮时,JavaScript 函数中的其余代码将</st> <st c="21799">执行操作。</st>

            1.  <st c="21811">下面的</st> `<st c="21816">function()</st>` <st c="21826">代码块是当使用</st> `<st c="21959">var userInput</st>` <st c="21972">变量来检索用户在聊天输入字段中输入的值时执行的事件处理函数。</st> <st c="22057">这个值是通过使用</st> `<st c="22090">$("#userInput")</st>` <st c="22105">jQuery 选择器来选择具有 ID 为</st> `<st c="22164">userInput</st>`<st c="22173">的 HTML 元素获得的,它就是聊天输入字段。</st> <st c="22206">然后,使用</st> `<st c="22210">.val()</st>` <st c="22216">方法获取用户在此字段中输入的值并将其存储在</st> `<st c="22308">userInput</st>` <st c="22317">变量中。</st>

            1.  <st c="22327">然后,使用 jQuery 库的</st> `<st c="22440">$.get()</st>` <st c="22447">方法将用户输入消息作为参数发送到服务器上的</st> `<st c="22336">GET</st>` <st c="22339">请求。</st> <st c="22456">服务器响应作为匿名函数中的数据参数接收。</st>

            1.  <st c="22545">一旦收到响应,代码将使用 jQuery 库的</st> `<st c="22688">append()</st>` <st c="22696">方法在 HTML 文档的聊天区域</st> `<st c="22631">(#chat)</st>`<st c="22638">中添加两个新的列表项。</st> <st c="22705">第一个列表项以粗体显示用户输入的消息</st> `<st c="22759">"您: <message>"</st>` <st c="22775">。</st> <st c="22785">此项目将记录并显示聊天历史中的用户输入。</st> <st c="22800">第二个列表项显示 ChatGPT API 的响应</st> `<st c="22916">"OpenAI: <response>"</st>` <st c="22936">在聊天历史中。</st>

        <st c="22957">完成此步骤后,您就准备好使用 ChatGPT 克隆应用程序,并通过用户友好的界面轻松与 ChatGPT API 交换响应了。</st> <st c="23127">要开始,只需运行</st> `<st c="23158">app.py</st>` <st c="23164">文件并开始聊天。</st> <st c="23190">请随时提问,答案将被保存在聊天历史窗口中。</st> <st c="23278">以下是一些示例(见</st> *<st c="23307">图 2</st>**<st c="23315">.4</st>*<st c="23317">):</st>

            +   `<st c="23320">谁发明了</st>` `<st c="23338">灯泡?</st>`

            +   `<st c="23349">熊猫是一种熊吗?</st>` `<st c="23370"></st>`

            +   `<st c="23378">能否将一个数除以零?</st>` `<st c="23413"></st>`

            +   `<st c="23421">如果我有两个苹果,我吃掉半个苹果,我还会剩下多少个苹果?</st>` `<st c="23490"></st>`

        ![图 2.4 – ChatGPT 克隆响应](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_02_4.jpg)

        <st c="24191">图 2.4 – ChatGPT 克隆响应</st>

        <st c="24227">重要提示</st>

        <st c="24242">此处显示的截图是为了清晰和可见性目的,显示了应用的光色模式。</st> <st c="24356">请注意,实际应用将按照其</st> <st c="24429">默认设置以暗色模式显示。</st>

        <st c="24446">回到</st> <st c="24458">VSCode</st> `<st c="24508">GET</st>` <st c="24511">请求已正确发送到 ChatGPT。</st> <st c="24552">如您所见,我们已收到一个带有</st> `<st c="24601">代码 200</st>`<st c="24609">的响应,这意味着 HTTP 请求成功,服务器已返回所需的数据。</st> <st c="24709">当服务器能够处理客户端的请求并返回所需数据时,它会将此代码作为 HTTP 响应的一部分发送:</st>
 127.0.0.1 - - [11/Apr/2023 14:37:04] "GET / HTTP/1.1" 200 –
127.0.0.1 - - [11/Apr/2023 14:37:26] "GET /get?msg=Who%20invented%20the%20lightbulb? HTTP/1.1" 200 –
127.0.0.1 - - [11/Apr/2023 14:37:53] "GET /get?msg=Is%20the%20Panda%20a%20type%20of%20bear? HTTP/1.1" 200 –
127.0.0.1 - - [11/Apr/2023 14:38:24] "GET /get?msg=Is%20it%20possible%20to%20divide%20a%20number%20by%20zero? HTTP/1.1" 200 –
127.0.0.1 - - [11/Apr/2023 14:44:39] "GET /get?msg=If%20I%20have%20two%20apples%20and%20I%20eat%20a%20half%20apple,%20how%20many%20apples%20will%20I%20have%20lest? HTTP/1.1" 200 –
        <st c="25414">这些是</st> <st c="25429">如何使用 JavaScript 处理与聊天应用的用户交互的说明。</st> <st c="25520">我们使用 jQuery 脚本来监听用户输入,并将用户输入作为查询参数发送到服务器上的 GET 请求,然后从 ChatGPT API 接收响应。</st> <st c="25689">我们还完成了一些如何使用 ChatGPT 克隆的示例,并验证所有 GET 请求都已正确发送到 ChatGPT,响应代码为</st> `<st c="25842">200</st>`<st c="25845">。你现在可以构建更多功能性的</st> <st c="25890">AI 应用程序。</st>

        <st c="25906">在下一节中,我们将通过实现一个无缝保留对话历史的特性来提升我们的 ChatGPT 克隆的功能。</st> <st c="26051">这一增强不仅允许用户访问之前的对话并回顾过去的交互,而且还将使我们的克隆能够在新问题提出时动态地记住对话历史。</st> <st c="26269">这意味着每次后续交互都将建立在之前交互的上下文之上,为用户提供更加个性化和吸引人的体验。</st>

        <st c="26430">ChatGPT 克隆对话保留</st>

        <st c="26467">我们成功</st> <st c="26483">使用 OpenAI 的 GPT-3.5 引擎和 Flask 创建了一个简单的 ChatGPT 克隆。</st> <st c="26556">现在,让我们通过实现一个保留对话历史并将其纳入对话上下文的功能,将我们的克隆提升到一个新的层次。</st>

        <st c="26714">保留对话历史允许我们的 ChatGPT 克隆在交互中保持上下文。</st> <st c="26812">用户和 AI 之间的每次交流都存储在一个名为</st> `<st c="26881">conversation_history</st>`<st c="26901">的列表中。</st> <st c="26970">以下列表跟踪了用户的消息和</st> <st c="26975">AI 的</st> <st c="26975">响应:</st>

            1.  <st c="26985">我们首先在 Flask 应用程序外部初始化一个名为</st> `<st c="27032">conversation_history</st>` <st c="27052">的空列表。</st> <st c="27087">此列表将存储用户和</st> <st c="27156">AI</st> <st c="27156">之间交换的所有消息:</st>

```py
<st c="27163">conversation_history = []</st> @app.route("/")
def index():
    return render_template("index.html")
```

                1.  <st c="27255">在收到用户的消息后,我们最初将其附加到</st> `<st c="27327">conversation_history</st>` <st c="27347">列表中,并附带</st> `<st c="27368">"user"</st>` <st c="27374">角色标识符,以表明它来自</st> <st c="27427">用户:</st>

```py
 userText = request.args.get('msg')      model_engine = "gpt-3.5-turbo" <st c="27753">conversation_history</st> list with the <st c="27788">"assistant"</st> role identifier to denote that it’s generated by the AI:

```

ai_response = response.choices[0].message.content <st c="27907">conversation_history.append({"role": "assistant", "content": ai_response})</st> return ai_response

```py

```

        <st c="28000">在 ChatGPT API 的上下文中,`<st c="28036">"assistant"</st>` <st c="28047">指的是 AI 模型扮演的角色,负责生成响应,而</st> `<st c="28137">"user"</st>` <st c="28143">表示与 AI 交互的人类,提供输入</st> <st c="28205">或查询。</st>

        <st c="28216">现在我们已经在我们 ChatGPT 克隆中实现了对话历史保留功能,测试和验证其功能是至关重要的。</st> <st c="28352">我们将与我们的应用程序进行一系列交互,以确认对话历史确实被保留并在</st> <st c="28494">后续响应中被利用。</st>

        <st c="28515">以下是 ChatGPT 克隆应用的测试</st> <st c="28536">程序:</st>

            1.  **<st c="28571">初始交互</st>**<st c="28591">:首先与 ChatGPT 克隆开始对话。</st> <st c="28653">发送消息或提问以触发</st> <st c="28701">AI 的响应。</st>

            1.  **<st c="28715">观察对话历史</st>**<st c="28746">:在收到 AI 的响应后,观察对话历史的内</st> <st c="28834">容。确保用户的消息和 AI 的响应都被</st> <st c="28898">正确存储。</st>

            1.  **<st c="28915">后续交互</st>**<st c="28939">:通过提问后续问题或发表相关陈述来继续对话。</st> <st c="29028">注意 AI 的响应如何根据之前交互中建立的上下文而演变。</st>

            1.  **<st c="29133">验证</st>**<st c="29144">:验证 AI 的响应是否连贯且相关,这表明它正在利用对话历史来</st> <st c="29266">维持上下文。</st>

        <st c="29283">在图 2*<st c="29317">.5</st>**<st c="29325">中提供的测试场景中,我们与我们的 ChatGPT 克隆进行了一系列交互,以评估其有效保留和利用对话历史的能力。</st> <st c="29464">最初,我们向 AI 介绍自己为“Martin”,并说明我们最喜欢的编程语言为“Python”,提示它在后续交互中承认我们的名字。</st> <st c="29637">AI 成功记住了我们的名字和最喜欢的编程语言,并将其纳入其响应中,展示了其保留用户提供信息的能力。</st> <st c="29821">此外,当我们询问我们的名字和最喜欢的编程语言时,AI 能够从对话历史中准确回忆起它,展示了其检索和利用</st> <st c="30009">上下文信息的能力。</st>

        ![图 2.5 – ChatGPT 克隆对话保留](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_02_5.jpg)

        <st c="30558">图 2.5 – ChatGPT 克隆对话保留</st>

        <st c="30607">这个场景</st> <st c="30622">强调了我们的 ChatGPT 克隆在保留和利用对话历史以维持情境并传递相关响应方面的有效性。</st> <st c="30773">通过成功回忆用户提供的信息并相应地定制响应,AI 增强了对话体验,培养了一种连续性和参与感。</st> <st c="30957">此外,AI 根据用户偏好和兴趣调整其响应的能力展示了其在生成连贯和</st> <st c="31104">个性化交互方面的多功能性。</st>

        <st c="31130">总结</st>

        <st c="31138">在本章中,您了解了构建 ChatGPT 克隆的过程,这是一个利用 OpenAI 的语言模型生成类似人类响应的用户输入的聊天机器人。</st> <st c="31337">该应用程序使用 Flask 构建,这是一个用于 Python 的轻量级 Web 框架,并且可定制,允许使用不同的 OpenAI 模型以及其他选项,如生成的文本长度。</st> <st c="31529">。

        <st c="31544">我们还涵盖了创建 ChatGPT 克隆的前端 HTML、拦截 ChatGPT API 端点、使用 AJAX 将用户输入从前端传递到后端以及在前端显示生成的文本等主题。</st> <st c="31778">。

        <st c="31791">我们学习了如何保留对话历史,使我们的 ChatGPT 克隆更加情境感知,根据之前的交互提供更连贯和相关的响应。</st> <st c="31957">。

        <st c="31979">在第</st> *<st c="31983">3 章</st>*<st c="31992">中,您将学习如何使用 Flask 和 ChatGPT 语言模型创建和部署一个 AI 驱动的代码错误修复 SaaS 应用程序。</st> <st c="32125">您将熟练使用 ChatGPT API。</st> <st c="32178">您将学习如何创建一个接受用户输入的 Web 表单,将应用程序部署到 Azure 云平台,并将其与 WordPress 网站集成。</st> <st c="32339">完成本章后,您将具备使 ChatGPT 应用程序对</st> <st c="32448">全球个人可访问的必要技能。</st>

第二部分:使用 ChatGPT API 构建 Web 应用程序

在这里,您将通过将 ChatGPT 与知名的 Python Web 框架如 Django 和 Stripe 无缝集成,掌握 Web 应用程序开发。 您将从零开始创建两个前沿的应用程序:一个动态的代码修复工具和一个创新的测验生成应用程序,利用 ChatGPT API 的巨大潜力。 此外,您还将获得有关将您的 Web 应用程序部署到 Azure 云、上传到您的网站以及使用 Stripe API 实现用户支付功能的宝贵见解。

本部分包含以下章节:

  • 第三章, 使用 Flask 创建和部署代码错误修复应用程序

  • 第四章, 将代码错误修复应用程序与支付服务集成

  • 第五章**,使用 ChatGPT 和 Django 的测验生成应用程序

第四章:3

使用 Flask 创建和部署代码错误修复应用程序

在本章中,我们将深入探讨使用 Flask 创建和部署一个由人工智能驱动的代码错误修复 SaaS 应用程序。此 应用程序将利用 OpenAI 的 GPT-3.5 语言模型为用户提供代码错误解释和修复。随着软件开发速度的快速增长,对有效且高效的错误调试解决方案的需求比以往任何时候都更加重要。 通过构建此 SaaS 应用程序,我们的目标是向开发者提供一款强大的工具,以加快他们的调试过程并提高其代码的质量。

为了开发此 SaaS 应用程序,我们将利用一个你可能已经非常熟悉的工具,即用于在 Python 中构建网络应用的 Flask 框架。我们的目标是熟练掌握这个框架,以构建一个有效且可扩展的 Web 应用程序,能够为用户提供高效的代码错误解决方案。 我们的目标是熟练掌握这个框架,以构建一个有效且可扩展的 Web 应用程序,能够为用户提供高效的代码错误解决方案。 此外,我们还将利用 OpenAI 的 GPT-3.5 语言模型提供自然语言解释和代码修复。

在本章中,我们将学习如何进行以下操作:

  • 执行多个 ChatGPT API 请求

  • 设置代码错误 修复器项目

  • 实现代码错误 修复器后端

  • 使用文本区域 和容器

  • 测试代码错误 修复器应用

  • 将 ChatGPT 应用部署到 Azure 云

完成本章后,你将具备使你的 ChatGPT 应用程序对全球个人用户可访问所需的技能。

技术要求

本项目的技术要求如下

  • 你的机器上安装了 Python 3.7 或更高版本

  • 一个代码编辑器,例如 VSCode(推荐)

  • 一个 Python 虚拟环境

  • 虚拟环境 中安装的 Flask 网络框架

  • 一个 OpenAI API 密钥

  • 访问云托管服务,例如 Microsoft Azure

本章中的代码示例可以在 GitHub 上找到 ,位于 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

执行多个 ChatGPT API 请求

让我们首先 深入了解 ChatGPT API 请求,并学习如何构建项目和 <st c="2128">app.py</st> 文件。 在这个项目中,我们将探讨如何进行多个 ChatGPT API 请求,以获取我们输入查询的解释和修复后的代码。 我们将逐步讲解整个过程,并提供清晰的示例,以便您可以轻松跟随。

为了修复用户的代码,ChatGPT 需要两个关键组件:一些有错误的代码和系统提供的错误信息。 代码错误修复器应用程序背后的理念是,你同时向 ChatGPT 提供两个单独的请求(参见 图 3**.1):

  • 请求 1:ChatGPT 使用有错误的代码和错误信息来修复 代码

  • 请求 2:ChatGPT 使用有错误的代码和错误信息,用普通英语向用户解释错误

图 3.1 – 代码错误修复器请求/响应映射

图 3.1 – 代码错误修复器请求/响应映射

如图 所示 图 3**.2,代码错误修复器应用程序的设计是一个界面简洁、现代的 Web 应用程序。 它包含一个表单,允许用户输入代码和相关错误。 提交表单后,应用程序将代码和错误发送到服务器,并在两个单独的 文本区域中显示生成的解释和修复后的代码。

用户界面的设计简单直观,有两个文本区域用于代码和错误输入,以及两个只读文本区域用于显示生成的解释和修复后的代码。 应用程序的布局整洁,采用蓝色和白色的配色方案,并有一个居中的标题显示应用程序的名称。 应用程序旨在为识别和修复 代码错误提供无缝的用户体验。

图 3.2 – 代码错误修复器应用程序用户界面

图 3.2 – 代码错误修复器应用程序用户界面

我们的应用程序将接受有错误的代码和一个错误,并同时提供两个请求:一个 用于修复代码,另一个向用户解释错误。 应用程序将具有高效的用户界面和简单的布局,从而提供无缝的用户体验。 现在,我们可以回顾一下在 VSCode 中创建必要的文件和文件夹的过程,包括 <st c="4086">CodeBugFixer</st> 项目,包括 <st c="4132">templates</st> 文件夹,该文件夹将包含 Flask 应用程序的 HTML 模板,以及 <st c="4212">config.py</st> <st c="4226">app.py</st> 文件,以在 Code Bug Fixer 应用程序中利用 ChatGPT API 奠定基础。

设置 Code Bug Fixer 项目

任何 Python 开发过程中的第一步是创建一个名为 <st c="4456">CodeBugFixer</st>的 VSCode 项目。 你可以通过前往(venv) 指示器来在 VSCode 中打开终端,以确认你正在虚拟环境中工作。 这是防止项目间包安装冲突并确保你使用正确集合的依赖项的必要步骤。 的依赖项。

现在我们可以按照以下步骤创建必要的文件和文件夹,用于 <st c="4927">CodeBugFixer</st> 项目:

  1. 首先,在项目的根目录中创建两个新的 Python 文件,分别命名为 <st c="5022">app.py</st> <st c="5033">config.py</st> <st c="5086">app.py</st> 文件是编写<st c="5129">CodeBugFixer</st> 应用程序主要代码的地方,而<st c="5171">config.py</st> 文件将包含任何敏感信息,如 API 密钥 和密码。

  2. 接下来,在项目的根目录中创建一个名为 <st c="5290">templates</st> 的新文件夹。 此文件夹将包含 Flask 应用程序将渲染的 HTML 模板。 <st c="5425">templates</st> 文件夹内,创建一个名为 <st c="5468">index.html</st>的新文件。 此文件将包含<st c="5542">CodeBugFixer</st> 应用程序主页的 HTML 代码。

    项目结构应如下所示

    <st c="5613">CodeBugFixer/</st>
    <st c="5627">├── config.py</st>
    <st c="5641">├── app.py</st>
    <st c="5652">├── templates/</st>
    <st c="5769">CodeBugFixer</st> project in your VSCode project. You can now start writing the code for your Flask app in the <st c="5875">app.py</st> file and the HTML code in the <st c="5912">index.html</st> file.
    
  3. 在终端窗口中,你可以按照以下方式安装任何必要的库:

     (venv)$ pip install flask
    (venv)$ pip install openai
    
  4. 最后,为了在您的 <st c="6142">CodeBugFixer</st> 应用程序中建立使用 ChatGPT API 的基础,您需要将以下代码添加到 <st c="6201">config.py</st> <st c="6215">app.py</st> :

config.py

 API_KEY = <Your API Key>

app.py

 from flask import Flask, request, render_template
from openai import OpenAI
import config
app = Flask(__name__)
# API Token
client = OpenAI(
  api_key=config.API_KEY,
)
@app.route("/")
def index():
    return render_template("index.html")
if __name__ == "__main__":
    app.run()

<st c="6539">config.py</st> 文件将安全地存储您的 OpenAI API 密钥。 请确保将 <st c="6615"><Your API Key></st> 替换为您从 OpenAI 获得的实际 API 密钥。

The <st c="6689">app.py</st> 文件是一个 Python 脚本,它定义了一个 Flask 应用程序。 它导入了 <st c="6769">Flask</st> 模块以及 CodeBugFixer 项目所需的库。 它从 <st c="6877">config.py</st> 文件中获取 API 密钥。 该脚本定义了主页的路线,并使用 Flask 的 <st c="6988">render_template</st> 函数渲染 <st c="6954">index.html</st> 模板。

为了设置 <st c="7028">CodeBugFixer</st> 项目,您需要创建一个新的项目,配置项目设置,创建项目所需文件和文件夹,安装 Flask 和 OpenAI 库,并将代码添加到 <st c="7219">config.py</st> <st c="7233">app.py</st> 文件中。 <st c="7251">config.py</st> 文件安全地存储 OpenAI API 密钥,而<st c="7311">app.py</st> 文件定义了一个 Flask 应用程序并渲染了<st c="7367">index.html</st> 模板。 此时,如果您运行<st c="7418">app.py</st> 文件,您将在浏览器上看到一个空白的(白色)页面。

在下一节中,我们将修改 Code Bug Fixer 应用程序后端的 <st c="7534">index()</st> 函数,以确保它可以区分 <st c="7642">GET</st> <st c="7650">POST</st> 请求。 我们还将使用 OpenAI GPT-3.5 API 为用户的输入生成解释和修复后的代码,然后我们将使用 <st c="7828">render_template</st> 函数将这些内容传递给 <st c="7798">index.html</st> 模板。

实现 Code Bug Fixer 后端

代码错误修复应用程序的后端 <st c="7940">应确保我们正确地将有错误的代码发送到 ChatGPT,并在另一端接收正确的响应。</st> 因此,您需要确保 <st c="8104">index()</st> <st c="8111">函数能够清楚地区分</st> GET POST 请求。 <st c="8183">您可以在</st> index() 函数中添加以下修改来实现这一点:

 @app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        code = request.form["code"]
        error = request.form["error"]
        prompt = (f"Explain the error in this code without fixing it:"
                  f"\n\n{code}\n\nError:\n\n{error}")
        model_engine = "gpt-3.5-turbo"

此函数 <st c="8548">检查 HTTP 请求方法——是</st> GET 还是 POST 请求。 <st c="8618">如果请求方法是</st> POST ,这意味着用户已从 <st c="8702">index.html</st> <st c="8712">模板中提交了表单。</st> 这样,你可以确保只有在用户提交表单并点击了 代码修复 `按钮后,ChatGPT API 才会被调用,我们将在下一节中构建该按钮。

函数随后从 <st c="9037">代码</st> <st c="9041">和</st> <st c="9046">错误</st> <st c="9051">变量中分别检索用户的输入。</st> 这些变量将保存用户想要修复的代码和接收到的错误代码。 <st c="9168">然后使用提取的</st> 代码 错误 变量来创建一个传递给 OpenAI ChatGPT API 的提示。 <st c="9282">这些变量使用 Python 中的</st> **<st c="9318">f-strings</st>** 进行格式化。

例如,假设 <st c="9367">代码</st> <st c="9371">和</st> <st c="9376">错误</st> `变量具有以下值:

 code = print(1
error = SyntaxError: '(' was never closed

在这种情况下,我们的提示将显示如下:

 Explain the error in this code without fixing it:
print(1
Error:
SyntaxError: '(' was never closed
The API is instructed to generate an explanation for the error in the code.

<st c="9710">提示</st> <st c="9716">变量为 ChatGPT 模型提供了一个明确和具体的任务,并确保模型生成的输出与</st> 用户输入 相关。

您可以将 <st c="9898">gpt-3.5-turbo</st> <st c="9911">字符串值设置为</st> model_engine 变量。 <st c="9955">此变量随后用于指定用于文本补全的 OpenAI 语言模型。</st> 在这种情况下, <st c="10072">gpt-3.5-turbo</st> `是 OpenAI 提供的功能最强大和最通用的模型之一。

<st c="10153">在</st> <st c="10165">if</st> <st c="10167">语句中,你现在可以调用 ChatGPT API 来为用户构建</st> <st c="10231">explanation_completion</st> <st c="10253">和</st> <st c="10258">fixed_code_completion</st> <st c="10279">:</st>

 explanation_completions = client.chat.completions.create(
            model=model_engine,
            messages=[{"role": "user", "content": f"{prompt}"}],
            max_tokens=1024,
            n=1,
            stop=None,
            temperature=0.2,
        )
        explanation = explanation_completions.choices[0].message.content
        fixed_code_prompt = (f"Fix this code: \n\n{code}\n\nError:\n\n{error}." f" \n Respond only with the fixed code.")
        fixed_code_completions = client.chat.completions.create(
            model=model_engine,
            messages=[
                {"role": "user", "content": f"{fixed_code_prompt}"},
            ],
            max_tokens=1024,
            n=1,
            stop=None,
            temperature=0.2,
        )
        fixed_code = fixed_code_completions.choices[0].message.content

<st c="10914">前面的代码利用 ChatGPT API</st> <st c="10965">根据给定的提示生成补全内容。</st> <st c="11012">在这段代码中,</st> <st c="11016">client.chat.completions.create()</st> <st c="11048">函数被调用两次,以生成两个不同的补全内容:</st> <st c="11134">explanation_completions</st> <st c="11157">和</st> <st c="11162">fixed_code_completions</st> <st c="11184">。</st>

<st c="11185">在调用</st> <st c="11196">client.chat.completions.create()</st> <st c="11228">函数两次后,</st> <st c="11259">解释</st> <st c="11270">和</st> <st c="11275">fixed_code</st> <st c="11285">变量分别被分配给两个对象的 choices 属性中生成的文本。</st> <st c="11389">这些生成的文本将在代码的下一步中使用,以向用户显示解释和修复代码。</st>

最后,你可以使用<st c="11509">render_template</st> <st c="11535">函数来更新一个 HTML 模板,并使用</st> ChatGPT 响应`:

<st c="11613">return render_template("index.html",</st><st c="11650">explanation=explanation,</st><st c="11675">fixed_code=fixed_code)</st> return render_template("index.html")
if __name__ == "__main__":
    app.run()

<st c="11772">该函数接受两个参数:第一个是要渲染的模板名称,第二个是将在模板中使用的变量字典。</st> 传递给模板的变量是 解释 fixed_code 解释 是 ChatGPT API 生成的文本,用于解释用户代码中的错误。 fixed_code 是 ChatGPT API 生成的文本,表示用户代码的修复版本。`

<st c="12207">这些变量被传递到</st> <st c="12226">index.html</st> <st c="12240">模板中,以便它们可以显示给用户。</st> <st c="12303">模板将使用这些变量来动态更新页面内容,显示由 API 生成的解释和修复代码。</st>

<st c="12437">执行你的 Flask 应用程序后,不应显示任何错误。</st> <st c="12508">然而,你的浏览器会显示一个完全空白的屏幕,因为我们的</st> <st c="12582">index.html</st> <st c="12592">文件是空的。</st> <st c="12608">我们的下一个任务是创建该文件,这将在下一节中讨论。</st>

这就是如何修改 <st c="12730">index()</st> 函数以确保在用户提交表单并点击 <st c="13037">render_template</st> 函数之后才调用 ChatGPT API。

在下一节中,您将学习如何创建一个 <st c="13116">index.html</st> 文件并构建一个 代码修复 按钮,允许用户提交他们的代码进行调试。 您还将学习如何使用 JavaScript 和 AJAX 处理表单提交并在不重新加载 页面的情况下显示 Flask 应用程序的响应。

使用文本区域和容器

在本节中,您将学习如何使用 HTML 和 CSS 为您的 <st c="13492">CodeBugFixer</st> 应用程序创建一个简单的用户 界面。 我们将逐步讲解为用户设计一个简单表单的过程,以便他们输入代码和错误信息,并显示 ChatGPT API 调用的结果。 在本节结束时,您将拥有一个功能齐全的 Web 应用程序,可以帮助用户修复他们代码中的错误。

要修改 <st c="13831">index.html</st> 文件,首先,您需要打开位于您项目 <st c="13896">templates</st> 文件夹中的文件。 您可以在任何文本编辑器中打开此文件,或者您可以使用 VSCode 内置的 HTML 编辑器。 一旦文件打开,添加以下基本的 HTML 结构:

 <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Code Bug Fixer</title>
</head>
<body>
<div class="header">
    <h1>Code Bug Fixer</h1>
</div>
</body>
</html>

The <st c="14263"><title></st> 标签将 HTML 页面的标题设置为 <st c="14310">代码错误修复器</st>。这是当页面加载时将在浏览器标签上显示的文本。 它还被搜索引擎用于在 搜索结果中显示页面的标题。

然后,您可以使用 <st c="14512"><h1></st> 标签在网页上创建一个包含文本 代码错误修复器 的标题,并使用大字体。

接下来,我们将向我们的 <st c="14639">index.html</st> 文件中添加一个输入表单。 此表单将允许用户输入他们的代码和相应的错误信息,然后点击 <st c="14894"><</st>``<st c="14895">div></st> 标签:

 <div class="header">
    <h1>Code Bug Fixer</h1>
</div>
<form action="/" method="post">
    <button class="submit-button" type="submit">Code Fix</button>
    <div class="container">
        <div class="left-column">
            <textarea name="code" placeholder="Enter Code"></textarea>
            <textarea name="error" placeholder="Enter Error"></textarea>
        </div>
        <div class="right-column">
            <textarea class="fixed-code" name="fixed-code" placeholder="Fixed Code" readonly>{{ fixed_code }}</textarea>
            <textarea class="explanation" name="explanation" placeholder="Explanation" readonly>{{ explanation }}</textarea>
        </div>
    </div>
</form>

表单被 HTML <st c="15528"><form></st> 标签包围,其中 <st c="15550">action</st> 属性设置为 <st c="15574">"/"</st> ,而 <st c="15586">method</st> 属性设置为 <st c="15610">post</st>。这意味着当用户提交表单时,数据将通过 HTTP <st c="15737">POST</st> 方法发送到根 URL <st c="15716">("/")</st> 这指的是我们 <st c="15769">index()</st> 函数在 <st c="15793">app.py</st> 文件中的实现。

在表单内部,我们有两个文本区域,其 <st c="15855">name</st> 属性分别设置为 <st c="15878">code</st> <st c="15887">error</st> 这将允许用户输入他们的代码和 错误信息。

表单还包含一个 <st c="15998">submit</st> 按钮,带有 <st c="16021">submit-button</st> 类。 当用户点击此按钮时,表单将被提交,数据将被发送到 后端服务器。

表单 分为两列,使用 <st c="16197"><div></st> 标签,并带有 <st c="16216">container</st> 类。 左侧列包含代码和错误信息文本区域,而右侧列包含固定的代码和解释 文本区域。

固定的代码和解释文本区域将 <st c="16423">name</st> 属性设置为 <st c="16446">fixed-code</st> <st c="16461">explanation</st>,分别。 它们也被设置为 <st c="16509">readonly</st>,因此用户无法修改其内容。 这些文本区域将在用户提交 表单后,由 ChatGPT API 生成的固定代码和解释进行更新。

现在你已经添加了index 页面的必要 HTML 代码,让我们运行 Flask 应用程序并查看它在浏览器中的外观。 当你运行 Flask 应用程序时,你应该会看到一个带有标题的页面,标题为Code Bug Fixer ,以及一个包含两个文本区域以输入你的代码和错误信息的表单。 还有一个标记为Code Fix的提交按钮。 在表单的右侧,你将看到另外两个文本区域,它们将显示修复后的代码和说明。 然而,这些文本区域最初将是空的,直到用户输入代码和错误信息并点击Code Fix 按钮(见图 3.3)。

目前,由于我们没有将任何样式添加到 HTML 中,应用程序的外观可能不够吸引人。

图 3.3 – 基于 HTML 的 Code Bug Fixer 应用前端

图 3.3 – 基于 HTML 的 Code Bug Fixer 应用前端

最后,我们将向我们的应用程序添加一些 CSS 来样式化 HTML 元素。CSS 代码将定义页面中元素的字体、颜色、大小和位置。 我们将向我们的index.html 文件中添加 CSS 代码,以增强应用程序的外观和感觉。 通过这些样式改进,我们的应用程序将更具视觉吸引力,并且更容易为我们的用户使用。

你可以在<st c="17958">title</st> 标签内 <st c="17979">head</st> <st c="17991">index.html</st> 文件中添加你的 CSS 代码:

 <title>Code Bug Fixer</title>
    <style type="text/css">
        body {
            font-family: Arial sans-serif;
            background-color: #f6f7f9;
        }

首先,让我们打开 CSS 样式块。 它表示以下代码是 CSS,并将应用于网页中的 HTML 元素。

CSS 代码针对 HTML 中的 元素。 在 CSS 中,你可以使用它们的标签名、类名或 ID 来定位元素。 在这里,我们正在定位整个网页的 body。

在这里,我们还可以将font-family 设置为Arial sans-serif ,这意味着任何在body 元素内的文本都将使用 Arial 字体显示,或者如果 Arial 不可用,则使用类似的 sans-serif 字体。 我们还可以将 body 的背景色设置为浅灰色:

 .header {
            background-color: #3b5998;
            color: #ffffff;
            padding: 15px;
            text-align: center;
        }
        .header h1 {
            margin: 0;
            font-size: 28px;
            font-weight: bold;
        }
        .container {
            display: flex;
            justify-content: space-between;
            padding: 15px;
        }

.header 指定了标题的背景颜色、文字颜色、填充和对齐方式。 在这里,文本是通过使用 <st c="19099">text-align</st> 属性来居中的。

.header h1 字体大小 属性设置为 28 像素, <st c="19181">字体粗细</st> 设置为 <st c="19203">粗体</st>,并且 <st c="19213">边距</st> 设置为 <st c="19230">0</st>,因此页面顶部和 标题之间没有空间。

.container <st c="19319">display</st> 属性设置为 <st c="19346">flex</st> ,以便我们可以使用 Flexbox 进行布局,并且 <st c="19394">justify-content</st> 设置为 <st c="19420">space-between</st> ,以便在水平轴上均匀分布容器的内容:

 .left-column, .right-column {
            width: 49%;
            padding: 15px;
        }
        textarea {
            width: 100%;
            height: 200px;
            font-size: 16px;
            padding: 10px;
            margin-bottom: 15px;
            border: 1px solid #cccccc;
            border-radius: 5px;
            resize: none;
        }
        .fixed-code, .explanation {
            background-color: #e9ebee;
            color: #3b5998;
            font-weight: bold;
        }

接下来,让我们设计一个 两列布局,其中左侧列包含用户输入代码和错误的输入字段,而右侧列显示 程序的输出。

.left-column .right-column 类被赋予了 <st c="20075">49%</st> 的宽度,以便它们在页面上占据几乎相等的空间。 <st c="20145">textarea 元素被设计为具有固定的宽度为 <st c="20204">100%</st> 和高度为 <st c="20225">200px</st> ,以创建一个清晰的输入字段。 <st c="20262">resize: none</st> 属性确保用户不能调整 输入字段的大小。

.fixed-code .explanation 类被赋予了<st c="20394">bold</st> <st c="20403">font-weight</st> 属性,使它们从输入字段中脱颖而出。 `这有助于用户快速识别 输出字段:

 .submit-button {
            background-color: #3b5998;
            color: #ffffff;
            font-size: 18px;
            font-weight: bold;
            padding: 10px 20px;
            border: none;
            border-radius: 5px;
            margin-top: 15px;
            cursor: pointer;
        }
        .submit-button:hover {
            background-color:  #4b76be;
        }
    </style>

我们的最终目标是 使 <st c="20797">提交</st> 按钮看起来更吸引人,并在用户悬停时向用户提供反馈。 我们将背景颜色设置为深蓝色(<st c="20938">#3b5998</st>)并将字体颜色设置为白色(<st c="20978">#ffffff</st>)以创建对比。 我们还添加了填充和边框半径,使按钮更引人注目 和吸引人。

<st c="21106">margin-top</st> 属性在按钮和文本区域之间添加了一些空间。 最后,我们添加了 <st c="21203">:hover</st> 伪类,当用户悬停时改变按钮的背景颜色,这为用户提供视觉反馈,表明按钮 是交互式的。

您现在已经完成了 <st c="21400">index.html</st> 文件,这是 <st c="21424">CodeBugFixer</st> 应用程序的。 现在您可以运行 <st c="21470">app.py</st> 文件并测试应用程序,以确保一切运行正常。 在下一节中,我们将提供一些如何使用应用程序修复代码错误的示例。 或者,您也可以尝试自己的代码示例来查看应用程序的表现。

这就是我们如何使用 HTML 和 CSS 为 <st c="21786">CodeBugFixer</st> 应用程序创建用户界面。 我们介绍了为用户设计表单的过程,以便他们可以输入代码和错误信息,并显示 ChatGPT API 调用的结果。

在下一节中,您将通过编写测试用例并验证它是否正确处理不同的场景来学习如何测试 <st c="22015">CodeBugFixer</st> 应用程序。 您还将看到 Code Bug Fixer 应用程序如何修复用 Java 和 Python 两种不同的编程语言编写的代码的示例,并学习如何测试修复后的代码以确认 其准确性。

测试代码错误修复应用程序

现在,我们将学习如何测试我们的代码错误修复应用程序。 我们 将编写一些测试用例以确保应用程序能够正确运行并适当地处理不同的场景。 测试是软件开发的一个关键部分,因为它确保应用程序按预期工作并满足 用户的需求。

代码错误修复器应用程序可以修复任何编程语言,使其成为一个多功能的工具。因此,我们将通过使用两种不同编程语言编写的示例来展示其有效性:Java 和 Python。

**我们的 Python 示例有两个属性。 **首先,我们有以下 有错误的代码:

 def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)
print("The factorial of 5 is: " + factorial(5))

然后,您可以输入以下错误:<st c="23147">类型错误:</st>

**此代码返回错误,因为它试图在<st c="23262">print</st> 语句中将字符串和整数连接起来。 <st c="23283">factorial</st> 函数返回一个整数,但它被连接到字符串<st c="23365">"The factorial of 5</st> is: "`.

**为了在代码错误修复器应用程序中修复此代码,请按照以下步骤操作: 这些步骤:

  1. 将代码粘贴到输入 代码 字段中。

  2. 将错误粘贴到输入 错误 字段中。

  3. 左键单击代码 修复 按钮。

完成列出的步骤后,固定代码和 ChatGPT API 生成的解释将显示在相应的字段中。如图图 3.4*所示,ChatGPT 的响应以粗体显示且不可编辑。 您还可以看到解释是准确的。

**图 3.4 – 代码错误修复器处理一些 Python 代码**

图 3.4 – 代码错误修复器处理一些 Python 代码

为了确保固定代码正确运行,您可以通过在 Python IDE(如 VSCode 或任何其他在线 Python 编译器)中运行它来测试它。通过检查与固定代码一起提供的说明,您可以确认它提供了对错误的准确和详细的解释。 错误。

**最后,为了验证代码错误修复器应用程序可以与任何编程语言一起工作,让我们尝试修复以下 Java 代码:

 public class ComplexError {
    public static void main(String[] args) {
        String str = "Hello, World!";
        int length = str.length();
        for (int i = 0; i <= length; i++) {
            System.out.println(str.charAt(i));
        }
    }
}

以下是 Java 编译器产生的错误代码:

<st c="24987">for</st> loop is iterating from <st c="25014">0</st> to <st c="25019">length</st>, which is the length of the string. However, the index of the last character in the string is length <st c="25127">-1</st>, so when <st c="25139">i</st> equals <st c="25148">length</st>, the program will try to access an index that is out of bounds and throw an <st c="25231">IndexOutOfBoundsException</st> message.
			<st c="25265">Once you run</st> <st c="25279">the code through the Code Bug Fixer app, you will get a response similar to the one depicted in</st> *<st c="25375">Figure 3</st>**<st c="25383">.5</st>*<st c="25385">. You can verify that the fixed code and the description are correct.</st> <st c="25455">ChatGPT fixed the error because it changed the condition in the</st> `<st c="25519">for</st>` <st c="25522">loop from</st> `<st c="25533">i <= length</st>` <st c="25544">to</st> `<st c="25548">i < length</st>`<st c="25558">. By changing the condition to</st> `<st c="25589">i < length</st>`<st c="25599">, the loop only iterates up to the last index of the string and avoids accessing an index that does</st> <st c="25699">not exist.</st>
			<st c="25709">This confirms that your Code Bug Fixer has the ability to differentiate between two distinct programming languages and was able to repair the code within a matter</st> <st c="25873">of seconds.</st>
			![Figure 3.5 – Code Bug Fixer processing some Java code](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_03_5.jpg)

			<st c="26503">Figure 3.5 – Code Bug Fixer processing some Java code</st>
			<st c="26556">This section</st> <st c="26570">explained how to test the Code Bug Fixer application by providing examples in the Python and Java programming languages.</st> <st c="26691">The application can fix any programming language, and the fixed code can be verified by running it in a Python or Java IDE.</st> <st c="26815">We saw how the application can differentiate between two programming languages and fix the code</st> <st c="26911">within seconds.</st>
			<st c="26926">In the next section, you will learn how to set up an Azure account, install the Azure CLI, and deploy its application to the cloud using the CLI.</st> <st c="27073">You will also learn how to create a</st> `<st c="27109">requirements.txt</st>` <st c="27125">file in the root directory of your project, listing all the Python packages and their specific versions that your app needs</st> <st c="27250">to run.</st>
			<st c="27257">Deploying the ChatGPT app to the Azure cloud</st>
			<st c="27302">Now let’s upload our</st> <st c="27324">Code Bug Fixer application to the</st> **<st c="27358">Azure</st>** <st c="27363">cloud</st> <st c="27370">platform.</st> <st c="27380">Azure is a cloud computing service provided by Microsoft that allows developers to host, manage, and scale their applications in the cloud.</st> <st c="27520">By hosting our application on Azure, we can make our application accessible to a wider audience.</st> <st c="27617">We will go through the steps required to create an Azure account, set up our application for deployment, and deploy it to Azure using the</st> <st c="27755">Azure CLI.</st>
			<st c="27765">You can create your Azure account by following</st> <st c="27813">these steps:</st>

				1.  <st c="27825">Go to the Azure website at</st> [<st c="27853">https://azure.microsoft.com/free/</st>](https://azure.microsoft.com/free/) <st c="27886">and click on</st> **<st c="27900">Start free</st>**<st c="27910">.</st>
				2.  <st c="27911">Sign in with your Microsoft account or create one if you don’t</st> <st c="27975">have one.</st>
				3.  <st c="27984">Enter your personal information and payment details.</st> <st c="28038">You won’t be charged unless you upgrade to a</st> <st c="28083">paid plan.</st>
				4.  <st c="28093">Choose your subscription type and agree to the terms</st> <st c="28147">and conditions.</st>
				5.  <st c="28162">Verify your account by entering a phone number and entering the code</st> <st c="28232">you receive.</st>
				6.  <st c="28244">You can log in to your account</st> <st c="28276">at</st> [<st c="28279">https://signup.azure.com/</st>](https://signup.azure.com/)<st c="28304">.</st>
				7.  <st c="28305">Once you log in, on the</st> `<st c="28444">portal.azure.com/#home</st>`<st c="28466">, where you can start using Azure services (see</st> *<st c="28514">Figure 3</st>**<st c="28522">.6</st>*<st c="28524">).</st>

			![Figure 3.6 – Azure home page](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_03_6.jpg)

			<st c="28789">Figure 3.6 – Azure home page</st>
			<st c="28817">Important note</st>
			<st c="28832">When deploying the Code Bug Fixer app to the Azure cloud, it is important to name the file containing the Flask app</st> `<st c="28949">app.py</st>`<st c="28955">. This is because Azure expects the main file to be named</st> `<st c="29013">app.py</st>` <st c="29019">for deployment to</st> <st c="29038">work properly.</st>
			<st c="29052">To deploy</st> <st c="29063">our application on Azure, we need to install</st> <st c="29108">the Azure</st> **<st c="29118">Command-Line Interface</st>** <st c="29140">(</st>**<st c="29142">CLI</st>**<st c="29145">).</st> <st c="29149">The CLI</st> <st c="29156">provides us with an efficient way to automate and manage our Azure resources.</st> <st c="29235">Next, you can find the steps to install the</st> <st c="29279">Azure CLI.</st>
			<st c="29289">These are the steps for macOS</st> <st c="29320">users (</st>[<st c="29327">https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-macos</st>](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-macos)<st c="29395">):</st>

				1.  <st c="29398">Open your</st> <st c="29409">macOS Terminal.</st>
				2.  <st c="29424">Install</st> `<st c="29433">brew</st>`<st c="29437">. Homebrew is a popular package manager</st> <st c="29477">for macOS:</st>

    ```

    **$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"**

    ```py

    				3.  <st c="29585">Once Homebrew</st> <st c="29599">is installed, run the following command to install</st> <st c="29651">Azure CLI:</st>

    ```

    **$ brew update && brew install azure-cli**

    ```py

    				4.  <st c="29701">Verify that the installation was successful by running the</st> <st c="29761">following command:</st>

    ```

    **$ az --version**

    ```py

    				5.  <st c="29794">This should display</st> <st c="29814">the version number of the Azure CLI that you</st> <st c="29860">just installed:</st>

    ```

    **azure-cli** 2.47.0

    **core** 2.47.0

    **telemetry** 1.0.8

    <st c="29920">依赖项:</st>

    <st c="29934">msal                              1.20.0</st>

    <st c="29946">azure-mgmt-resource               22.0.0</st>

    <st c="29973">Python 位置 '/opt/homebrew/Cellar/azure-cli/2.47.0/libexec/bin/python'</st>

    <st c="30048">扩展目录 '/Users/martinyanev/.azure/cliextensions'</st>

    <st c="30111">Python (Darwin) 3.10.11 (main, Apr  7 2023, 07:24:47) [Clang 14.0.0 (clang-1400.0.29.202)]</st>

    <st c="30201">法律文件和信息:aka.ms/AzureCliLegal</st>

    <st c="30250">您的 CLI 已更新。</st>

    ```py

			<st c="30274">These are the steps for Windows</st> <st c="30307">users (</st>[<st c="30314">https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-cli</st>](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-cli)<st c="30399">):</st>

				1.  <st c="30402">Open a web browser and navigate</st> <st c="30435">to</st> [<st c="30438">https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows</st>](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows)<st c="30506">.</st>
				2.  <st c="30507">Scroll down to the section titled</st> **<st c="30542">Install or update</st>** <st c="30559">and click on the</st> **<st c="30577">Microsoft Installer</st>** <st c="30596">(</st>**<st c="30598">MSI</st>**<st c="30601">) tab.</st>
				3.  <st c="30608">Click on the</st> **<st c="30622">Latest release of the Azure CLI</st>** <st c="30653">button to start the MSI</st> <st c="30678">package download.</st>
				4.  <st c="30695">Once the</st> <st c="30705">MSI package has downloaded, double-click on the file to begin the</st> <st c="30771">installation process.</st>
				5.  <st c="30792">Follow the prompts in the installation wizard to complete the</st> <st c="30855">installation process.</st>
				6.  <st c="30876">Once the installation is complete, open a Command Prompt or PowerShell window and type</st> <st c="30964">the following:</st>

    ```

    <st c="30978">$ az –version</st>

    ```py

    <st c="30992">For Linux users (</st>[<st c="31010">https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=script</st>](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=script)<st c="31092">), you can type the following in</st> <st c="31126">the Terminal:</st>

    ```

    curl -L https://aka.ms/InstallAzureCli | bash

    ```py

			<st c="31185">This line will automatically download the installation script and you can follow all steps for setting up your</st> <st c="31297">Azure CLI.</st>
			<st c="31307">Important note</st>
			<st c="31322">After installing the Azure CLI, you may need to close and re-open your Terminal window to ensure that the CLI is fully recognized</st> <st c="31453">and operational.</st>
			<st c="31469">You should now be able to use the Azure CLI on your</st> <st c="31522">Linux machine.</st>
			<st c="31536">Before deploying your app to Azure using the CLI, you’ll need to log in to your Azure account from the CLI.</st> <st c="31645">This will enable you to manage your resources and perform other tasks related to</st> <st c="31726">your account.</st>
			<st c="31739">To log in to your Azure account using the Azure CLI, you can type in the</st> <st c="31813">Terminal window:</st>

$ az login


			<st c="31840">A pop-up window will</st> <st c="31862">appear asking you to enter your Azure</st> <st c="31899">account credentials.</st> <st c="31921">Enter your account email and password and click on the</st> **<st c="31976">Sign in</st>** <st c="31983">button.</st> <st c="31992">Once you are successfully logged in, you will see a message in the Command Prompt indicating that you</st> <st c="32094">are authenticated.</st>
			<st c="32112">To prepare our app for deployment, we need to create a file called</st> `<st c="32180">requirements.txt</st>` <st c="32196">in the root directory of our</st> `<st c="32226">CodeBugFixer</st>` <st c="32238">project.</st> <st c="32248">This file will list all the Python packages and their specific versions that our app needs to run.</st> <st c="32347">The</st> `<st c="32351">requirements.txt</st>` <st c="32367">file is a common practice in Python projects to document and manage the project’s dependencies.</st> <st c="32464">It lists all the external packages and their versions that are necessary for the application to function properly.</st> <st c="32579">Each line in the</st> `<st c="32596">requirements.txt</st>` <st c="32612">file typically represents a separate package and may include a specific version number or a version range.</st> <st c="32720">Azure will use this file to install the dependencies in the server where our app will</st> <st c="32806">be hosted.</st>
			<st c="32816">The project structure should look like</st> <st c="32856">the following:</st>

CodeBugFixer/

├── config.py

├── app.py

├── requirements.txt

├── templates/

│ └── index.html


			<st c="32962">To create a</st> `<st c="32975">requirements.txt</st>` <st c="32991">file in your project, follow</st> <st c="33021">these steps:</st>

				1.  <st c="33033">Right-click on your</st> `<st c="33054">CodeBugFixer</st>` <st c="33066">project folder in the</st> **<st c="33089">Explorer panel</st>** <st c="33103">on the left-hand side</st> <st c="33126">of VSCode.</st>
				2.  <st c="33136">Select</st> `<st c="33175">requirements.txt</st>` <st c="33191">as</st> <st c="33195">the filename.</st>
				3.  <st c="33208">Once the</st> <st c="33217">file is created, you can add the</st> <st c="33250">necessary libraries to it.</st> <st c="33278">To include Flask and OpenAI libraries, add the following lines to your</st> `<st c="33349">requirements.txt</st>` <st c="33365">file:</st>

    ```

    Flask==3.0.2

    openai==1.13.3

    ```py

			<st c="33399">Now that we have everything set up, it’s time to deploy the app to Azure.</st> <st c="33474">We’ll be using the Azure CLI to accomplish this:</st> 

				1.  <st c="33523">First, navigate to the root directory of your project, where the</st> `<st c="33588">app.py</st>` <st c="33594">and</st> `<st c="33599">requirements.txt</st>` <st c="33615">files</st> <st c="33622">are located.</st>
				2.  <st c="33634">Next, run the following command in</st> <st c="33670">the CLI:</st>

    ```

    $ az webapp up --name <app_name>

    ```py

    <st c="33711">In this command,</st> `<st c="33729">webapp up</st>` <st c="33738">deploys the web app to Azure.</st> <st c="33769">Replace</st> `<st c="33777"><app-name></st>` <st c="33787">with a unique name of</st> <st c="33810">your choice.</st>

    				3.  <st c="33822">After deploying the app, if everything is set up correctly, you should see a JSON output in the Azure CLI terminal.</st> <st c="33939">This output will contain information about the deployed app, such as the app name, URL, location, resource group, and other details.</st> <st c="34072">It will also include the status of the deployment, such as whether it was successful or whether there were</st> <st c="34179">any errors:</st>

    ```

    {

    "URL": "http://<app_name>.azurewebsites.net",

    "appserviceplan": "martinyanev94_asp_7277",

    "location": "location",

    "name": "您的应用名称",

    "os": "Linux",

    "resourcegroup": "resourcegroup",

    "runtime_version": "python|3.10",

    "runtime_version_detected": "-",

    "sku": "PREMIUMV2",

    "src_path": "//Local/app/path"

    }

    ```py

			<st c="34500">After successfully</st> <st c="34519">deploying your app on Azure, you can access it</st> <st c="34566">from anywhere around the world using the URL provided in the JSON output.</st> <st c="34641">Simply copy the URL and paste it into your web browser’s address bar to open the app.</st> <st c="34727">You can also share this URL with others to let them use your Code Bug</st> <st c="34797">Fixer app.</st>
			<st c="34807">If you want to upload the Code Bug Fixer app to your</st> *<st c="34861">WordPress</st>* <st c="34870">website, you can easily do so by using an</st> `<st c="34913">iframe</st>`<st c="34919">. Simply copy and paste the following code into the text editor, replacing</st> `<st c="34994"><your_app_url></st>` <st c="35008">with the URL of your</st> <st c="35030">deployed app:</st>


			<st c="35110">This will embed the app into your website and allow your visitors to access it directly from</st> <st c="35204">your page.</st>
			<st c="35214">Finally, you can access your deployed application from the Azure web portal.</st> <st c="35292">To access your app from your Azure web account, follow</st> <st c="35347">these steps:</st>

				1.  <st c="35359">Sign in to the Azure portal</st> <st c="35388">at</st> [<st c="35391">https://portal.azure.com/#home</st>](https://portal.azure.com/#home)<st c="35421">.</st>
				2.  <st c="35422">In the left-hand menu, click on</st> **<st c="35455">App Services</st>**<st c="35467">.</st>
				3.  <st c="35468">From there, you will be able to manage the app that</st> <st c="35521">you deployed.</st>

			<st c="35534">Here, you can modify or delete the deployment from your Azure web account (see</st> *<st c="35614">Figure 3</st>**<st c="35622">.7</st>*<st c="35624">):</st>

				*   <st c="35627">To modify the deployment, you can upload a new version of your code using the Azure CLI or</st> <st c="35719">Azure portal</st>
				*   <st c="35731">To delete</st> <st c="35742">the deployment, simply click on the</st> **<st c="35778">Delete</st>** <st c="35784">button</st> <st c="35791">on the</st> **<st c="35799">Overview</st>** <st c="35807">page of your app in the</st> <st c="35832">Azure portal</st>

			![Figure 3.7 – Azure cloud app management](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_03_7.jpg)

			<st c="36128">Figure 3.7 – Azure cloud app management</st>
			<st c="36167">This is how you can deploy your app on the Azure cloud using the Azure CLI.</st> <st c="36244">We listed all the steps involved in creating an Azure account, installing the Azure CLI, and preparing the app for deployment.</st> <st c="36371">The section also emphasized that the main file of the app should be named</st> `<st c="36445">app.py</st>` <st c="36451">for proper deployment, and a</st> `<st c="36481">requirements.txt</st>` <st c="36497">file is needed to list all the Python packages required by the app to run.</st> <st c="36573">The steps to install the Azure CLI for macOS and Windows users were</st> <st c="36641">also listed.</st>
			<st c="36653">Summary</st>
			<st c="36661">This chapter described the creation and deployment of an AI-powered SaaS application, Code Bug Fixer, which uses OpenAI’s GPT-3.5 language model to provide code error explanations and fixes to users.</st> <st c="36862">It covered building the application using Flask, creating a web form that accepts user input for code and error messages, and designing a web interface to display the generated explanations and solutions.</st> <st c="37067">The chapter also provided instructions on how to test and deploy the application to the Azure cloud platform, offering security and scalability features to</st> <st c="37223">the application.</st>
			<st c="37239">Furthermore, you learned how to create a user interface for Code Bug Fixer using HTML and CSS, adding a basic HTML structure, a header, an input form, and two columns containing text areas for the user to enter their code and error message.</st> <st c="37481">The testing process involved running test cases for the application in two different programming languages, Python and Java.</st> <st c="37606">By following the given steps, users can check whether the application is repairing the codes accurately or not.</st> <st c="37718">This chapter provided a comprehensive guide to building, testing, and deploying an AI-powered SaaS application that can help users fix errors in</st> <st c="37863">their code.</st>
			<st c="37874">In</st> *<st c="37878">Chapter 4</st>*<st c="37887">,</st> *<st c="37889">Integrating the Code Bug-Fixing Application with a Payment Service</st>*<st c="37955">, you will learn how to integrate the popular Stripe payment service into your web application using the Stripe API.</st> <st c="38072">The chapter will cover the step-by-step process of setting up a Stripe account, configuring the API keys, creating a form to collect user payment information, and processing payments securely through Stripe.</st> <st c="38280">Additionally, the chapter will explain how to track and store user data securely for future transactions</st> <st c="38385">and analysis.</st>

第五章:4

将代码错误修复应用程序与支付服务集成

在本章中,我们将探讨如何使用 Stripe API 将支付服务集成到您的 ChatGPT 代码错误修复应用程序中,以便您能够跟踪用户在您的 ChatGPT 应用程序上的访问次数,并实现高级功能或内容的支付机制。 您还将学习如何在您的 ChatGPT 项目中使用基本数据库,这对于跟踪用户数据和交易至关重要。

首先,我们将介绍 Stripe 并向您展示如何设置账户和 API 密钥。 然后,我们将介绍创建用于存储用户数据和交易历史的 SQL 用户数据库的步骤。 最后,我们将指导您使用 Stripe API 将支付功能添加到您的 ChatGPT 应用程序中,包括创建结账流程、处理支付 webhook 以及更新 数据库。

在本章中,我们将学习如何做 以下内容:

  • 设置 SQL 用户数据库

  • 向 ChatGPT 应用程序添加支付 功能

在本章结束时,您将具备添加支付服务到您的 ChatGPT 应用程序并构建成功的 在线业务所需的必要知识和工具。

技术要求

本项目的技术要求如下: 如下:

  • 在您的 机器上安装了 Python 3.7 或更高版本

  • 代码编辑器,例如 VSCode(推荐)

  • Python 虚拟环境

  • 一个 OpenAI API 密钥

  • 一个 Stripe 账户和 API 密钥

在下一节中,您将学习如何集成 Stripe 支付。 您将了解如何创建 Stripe 账户,获取必要的 API 密钥,并在 您的应用程序中设置 Stripe API。

本章中的代码示例可以在 GitHub 上找到 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-APIs

介绍和集成 Stripe 支付

Stripe 是一个 流行的支付网关,提供了一种简单的方式来在线接受支付。 它允许企业和个人在网上接受支付、管理订阅和跟踪收入,一切都在一个地方完成。 Stripe 提供了一个易于使用的 API,允许 开发人员将支付功能集成到他们的网站和应用程序中。 我们将从创建一个 Stripe 账户 并配置我们将用于验证对 Stripe API 请求的 Stripe API 密钥开始。 在这里,您将使用 Stripe API 创建一个支付表单,并在您的 Python 代码中安全地处理支付。 与 Stripe 类似的服务还包括 PayPal、Square 和 Braintree。

接受支付的第一步是在您的 《代码错误修复器》 应用程序中创建一个 Stripe 账户。 Stripe 是一个流行的支付处理平台,它使企业能够在线接受支付。 通过设置 Stripe 账户,您可以将其与 ChatGPT 应用程序集成,并开始接受用户的支付。 设置 Stripe 账户既简单又直接,我们将引导您完成所有步骤。

要开始使用 Stripe,您需要创建一个账户。 按照以下步骤创建一个新的 Stripe 账户:

  1. 访问 Stripe 网站: https://stripe.com/

  2. 点击页面右上角的 登录 按钮。

  3. 点击 创建 账户 按钮。

  4. 填写注册表单,提供您的个人或业务信息。 您需要提供您的姓名、电子邮件地址和密码(见 图 4**.1)。

  5. 通过点击 Stripe 发送给您的验证电子邮件中的链接来确认您的电子邮件地址。

  6. 提供您的 业务详细信息,例如您的 公司名称、地址和税务识别号 (可选)。

  7. 设置您的支付设置。 您可以选择接受所有主要信用卡和借记卡的支付,以及像 Apple Pay 和 Google Pay 这样的数字钱包支付(可选)。

图 4.1 – Stripe 注册表单

图 4.1 – Stripe 注册表单

一旦你创建了 Stripe 账户,你就可以开始接受客户的支付。 你还可以使用 Stripe 的仪表板,如图 *图 4.2所示,来管理你的交易,处理退款,并查看你的支付活动报告。 Stripe 对其平台处理的每笔交易都会收取费用,但费用具有竞争力 且透明。

图 4.2 – Stripe 仪表板

图 4.2 – Stripe 仪表板

接下来,你需要 获取访问你的 Stripe API 密钥,这些密钥将在你的应用程序中用于后续的支付处理。 仪表板中,点击屏幕左侧的 开发者 标签页,然后点击 API 密钥。在这个页面上,你可以看到你的实时和测试 API 密钥,以及显示每个密钥秘密的选项。 请确保复制并安全存储你的密钥,因为你将需要它们从你的 ChatGPT 应用程序向 Stripe 发送 API 请求。

重要提示

你的实时 API 密钥应保持私密,不要公开分享,因为它们提供了访问你的 Stripe 账户敏感数据的权限,并允许用户进行更改。 相反,你可以使用你的 测试 API 密钥 进行开发和 测试目的。

Stripe 提供了三种类型的 API 密钥 – 发布密钥秘密密钥,和测试密钥

  • 发布密钥 用于客户端,以安全地向 Stripe 发送请求。 它没有任何访问你账户的权限,可以公开分享。 这个密钥通常放置在 应用程序前端。

  • 秘密密钥 用于服务器端,以向 Stripe 发送请求,并且 具有完全访问你账户的权限,包括进行收费的能力。 它应该保密,并且永远不应该公开分享。 这个密钥通常放置在 应用程序后端。

  • 测试密钥 用于测试环境,以执行测试交易而不收取任何费用。 它像秘密密钥一样工作,但只影响测试数据,并且不应该在生产中使用。

API keys 页面,您将看到publishable test API keys。 我们将使用publishable key 来识别您的应用程序前端中的 Stripe 账户,而test key 用于与 Stripe 的后端通信。 您需要将publishable key 添加到您的 ChatGPT 应用程序的前端代码中,并将test key 添加到后端代码中。

您可以使用Stripe将支付集成到网站或应用程序中,Stripe 是一个流行的支付网关,它提供了一种轻松接受在线支付的方式。This is how you can integrate payments into a website or application using Stripe, a popular payment gateway that provides an effortless way to accept payments online. 在本节中,为了使用 Stripe,您创建了一个 Stripe 账户并获得了 API 密钥,包括可发布密钥和秘密密钥,它们具有不同的访问级别,应该**have different access levels and should be kept secure.

在下一节中,您将学习如何为 Code Bug Fixer 应用程序设置 SQL 用户数据库。In the next section, you will learn about setting up a SQL user database for the Code Bug Fixer application. We will explore the different payment models and understand how to design a subscription-based payment plan.

设置 SQL 用户数据库

在将支付基础设施集成到您的应用程序之前,确定您的业务策略至关重要,这关系到您将如何向您的 Web 应用程序用户收费。Prior to implementing the payment infrastructure into your application, it’s essential to determine your business strategy, which pertains to how you’ll charge users of your web application. There are several ways to accomplish this:

  • 订阅计划:这是一种定期付款模式,允许用户定期支付服务或产品费用,例如按月或按年支付。This is a recurring payment model that allows users to pay for a service or product on a regular basis, such as monthly or yearly. 它是软件即服务 (SaaS)产品以及在线出版物中常见的支付选项,用户支付费用以获取服务或内容的访问权限。It is a common payment option for Software-as-a-Service (SaaS) products and online publications, where users pay for access to the service or content.

  • 一次性付款计划:客户为产品或服务支付一次费用。make a single payment for a product or service.

  • 基于使用量的计划:客户根据他们对产品或服务的使用情况付费,例如按次付费或按点击付费。are charged based on their usage of a product or service, such as pay-per-view or pay-per-click.

对于我们的代码错误修复应用程序,我们将设计一个订阅模式,为用户提供三个不同的计划进行选择。 此外,为了使用户入门过程更加顺畅,我们将包括一个 免费试用期 ,允许用户在承诺支付计划之前尝试应用程序一定次数。

免费试用期 将为用户提供探索应用程序功能并确定其是否符合需求的机会。 在试用期间,用户可以在不收费的情况下使用应用程序特定次数。 试用期结束后,用户将被提示选择一个支付计划以继续使用应用程序。 这种基于订阅的方法对用户和作为应用程序所有者的您都有益。 用户可以选择最适合其预算和使用的订阅计划,而您可以从 订阅费中产生稳定的收入流。

为了实现我们应用程序的支付机制,我们需要建立一个数据库来跟踪用户访问和使用情况。 数据库需要记录两种类型的信息—— 浏览器 ID (见 表 4.1),这是每个访问应用程序的用户独有的,以及使用计数器,它记录每个用户访问应用程序的次数。 通过跟踪这些信息,我们可以识别唯一用户并确保他们在被提示选择一个 订阅计划之前没有超过允许的免费访问次数。

浏览器 ID 使用计数器
28ec523f092 3
58c9f5702fd 6
c59523926d 10

表 4.1 – 数据库中收集的用户数据

现在我们已经制定了一个稳固的商业计划,我们可以继续前进并深入了解将支付服务集成到我们的 ChatGPT 应用程序中的技术细节。 然而,在我们能够这样做之前,我们需要初始化一个 SQL 数据库

初始化 SQL 数据库

SQL 数据库对于跟踪用户在我们的应用程序上执行访问次数至关重要,这反过来又使我们能够使用 Stripe API 实现支付机制。 拥有数据库,我们可以轻松地存储和检索与我们的用户 <st c="10352">及其与我们的应用程序的交互相关的数据,使我们能够无缝地管理支付</st> 过程。`

现在,让我们打开我们的 Code Bug Fixer 应用程序的 <st c="10499">app.py</st> 文件,并导入所有必要的库以访问 Stripe 和 <st c="10573">SQL 数据库:</st>

app.py

 from flask import Flask, request, render_template
from openai import OpenAI
import config <st c="10684">import hashlib</st>
<st c="10698">import sqlite3</st>
<st c="10778">app.py</st> file:

				*   `<st c="10790">hashlib</st>`<st c="10798">: Provides interfaces to secure hash algorithms.</st> <st c="10848">It is used to generate hash values of data.</st> <st c="10892">In our case, we will use</st> `<st c="10917">hashlib</st>` <st c="10924">to hash user information before storing it in the database for</st> <st c="10988">security purposes.</st>
				*   `<st c="11006">sqlite3</st>`<st c="11014">: This library provides a lightweight disk-based database that doesn’t require a separate server process and allows us to access the database using SQL commands.</st> <st c="11177">We will use it to create and manage a database to store</st> <st c="11233">user information.</st>
				*   `<st c="11250">stripe</st>`<st c="11257">: This is a third-party library that provides a Python client for the Stripe API, which allows us to handle payments in our application.</st> <st c="11395">We will use it to process payments made by users through</st> <st c="11452">our application.</st>

			<st c="11468">While the</st> `<st c="11479">sqlite3</st>` <st c="11486">and</st> `<st c="11491">hashlib</st>` <st c="11498">are built-in libraries in Python, you will need to install</st> `<st c="11558">stripe</st>`<st c="11564">. You can simply do that by opening a new VSCode terminal by going to</st> **<st c="11634">Terminal</st>** <st c="11643">|</st> **<st c="11645">New Terminal</st>** <st c="11657">and typing</st> <st c="11669">the following:</st>

$ pip install stripe


			<st c="11704">After successfully</st> <st c="11724">installing Stripe, you can proceed to configure the Stripe test key.</st> <st c="11793">To do so, simply navigate to the Stripe Dashboard, and then head over to the</st> **<st c="11870">Developers</st>** <st c="11881">tab, followed by the</st> **<st c="11902">API keys</st>** <st c="11910">section.</st> <st c="11920">From there, you can click on the option to reveal the test key, which will allow you to copy the test key</st> <st c="12026">for use.</st>
			<st c="12034">To create a new API key entry, make the required modifications to the files listed in your Code Bug</st> <st c="12135">Fixer project:</st>
			<st c="12149">config.py</st>

API_KEY = "<YOUR_OPENAI_API_KEY>" STRIPE_TEST_KEY = "<YOUR_STRIPE_API_TEST_KEY>"


			<st c="12240">app.py</st>

client = OpenAI(

api_key=config.API_KEY,

) config.py 文件,然后在 <st c="12431">app.py</st> 文件中检索此密钥,允许您的应用程序使用指定的密钥安全地与 Stripe API 通信。

        <st c="12540">下一步是</st> <st c="12561">在</st> `<st c="12569">initialize_database()</st>` <st c="12590">函数下添加到</st> `<st c="12627">app.py</st>`<st c="12633">中。此函数将创建一个 SQLite 数据库和一个包含两个列的用戶表,用于</st> `<st c="12721">指纹</st>` <st c="12732">和</st> `<st c="12741">使用计数器</st>`<st c="12754">,如</st> *<st c="12768">表 4.1</st>*<st c="12777">所示:</st>
 def initialize_database():
    conn = sqlite3.connect('app.db')
    c = conn.cursor()
    c.execute(
        '''CREATE TABLE IF NOT EXISTS users (fingerprint text primary key, usage_counter int)''')
    conn.commit()
    conn.close()
        <st c="12985">前面的函数通过使用 Python 中的</st> `<st c="13053">SQLite</st>` <st c="13059">库连接到一个新创建的</st> `<st c="13075">app.db</st>`<st c="13081">数据库,然后</st> <st c="13120">创建一个</st> `<st c="13160">c</st>`<st c="13161">,用于执行 SQL 命令并从数据库中检索结果。</st> <st c="13238">游标对象允许您对数据库执行各种操作,如创建表、插入数据以及</st> <st c="13358">更新数据。</st>

        <st c="13372">然后,我们使用游标对象执行一个创建名为</st> `<st c="13456">users</st>` <st c="13461">的表的 SQL 命令,该表位于连接的 SQLite 数据库中。</st> <st c="13496">此表有两个列,</st> `<st c="13524">fingerprint,</st>` <st c="13536">和</st> `<st c="13541">usage_counter</st>`<st c="13554">;</st> `<st c="13561">fingerprint</st>` <st c="13572">列将存储用户浏览器 ID,而</st> `<st c="13615">usage_counter</st>` <st c="13628">将存储特定用户的程序使用次数。</st> <st c="13693">`<st c="13697">主键</st>` <st c="13708">关键字指定</st> `<st c="13736">fingerprint</st>` <st c="13747">列是表的</st> `<st c="13777">主键。</st>`

        <st c="13787">最后,我们可以</st> `<st c="13804">提交</st>` <st c="13810">之前 SQL 命令对数据库所做的更改,使它们成为永久更改,并且</st> `<st c="13907">关闭</st>` <st c="13912">数据库连接,释放连接所使用的任何资源。</st>

        <st c="13996">这是为 Code Bug Fixer 应用程序初始化 SQL 数据库的方法。</st> <st c="14079">这些都是创建 SQL 数据库和配置 Stripe 测试密钥所必需的库。</st> <st c="14173">在下一步中,您将了解获取</st> `<st c="14238">指纹</st>` <st c="14249">浏览器的过程,这将帮助您识别使用</st> <st c="14322">您的应用程序的个别用户。</st>

        <st c="14339">获取浏览器指纹 ID</st>

        <st c="14372">为了跟踪和识别您 Web 应用程序的独特用户,您需要一种方法来获取他们的</st> <st c="14473">浏览器指纹。</st> <st c="14494">浏览器指纹是基于各种参数(如浏览器类型、屏幕分辨率和已安装字体)由浏览器生成的唯一</st> <st c="14527">标识符。</st> <st c="14655">在本节中,我们将探讨如何在 Python 中获取浏览器指纹 ID</st> <st c="14729">。</st>

        <st c="14739">在我们的应用程序中,为每个单独的任务创建一个专门的 Python 函数被认为是一种良好的实践,生成浏览器指纹也不例外。</st> <st c="14908">因此,在</st> `<st c="14997">initialize_database()</st>` <st c="15018">函数下创建一个名为</st> `<st c="14969">get_fingerprint()</st>` <st c="14986">的新函数是合适的:</st>
 def get_fingerprint():
    browser = request.user_agent.browser
    version = request.user_agent.version and float(
        request.user_agent.version.split(".")[0])
    platform = request.user_agent.platform
    string = f"{browser}:{version}:{platform}"
    fingerprint = hashlib.sha256(string.encode("utf-8")).hexdigest()
    print(fingerprint)
    return fingerprint
        <st c="15363">`<st c="15368">get_fingerprint()</st>` <st c="15385">`函数是一个 Flask 视图函数,它负责为与应用程序交互的每个用户生成一个唯一的浏览器指纹(在大多数情况下)。</st> <st c="15550">指纹是根据用户的浏览器类型、版本和平台生成的字符串的散列,用以唯一标识用户。</st>

        <st c="15669">重要提示</st>

        <st c="15684">浏览器指纹并不能保证对每个用户都是 100%唯一的,但浏览器指纹通常可以生成一个相对唯一的标识符,用以区分不同的用户。</st> <st c="15880">如 IP 地址或 MAC 地址这样的标识符更适合</st> <st c="15989">现实世界应用。</st>

        <st c="16013">首先,</st> <st c="16025">函数通过使用</st> `<st c="16091">request.user_agent</st>`<st c="16109">从请求对象中获取</st> `<st c="16043">user_agent</st>` <st c="16053">对象。此对象包含有关用户浏览器、平台和版本的信息。</st>

        <st c="16192">接下来,该函数通过将浏览器、版本和平台信息连接起来,并用冒号(</st>`<st c="16337">:</st>`<st c="16339">)分隔,构建一个字符串。</st> <st c="16342">这个字符串用作输入到</st> `<st c="16382">hashlib.sha256()</st>` <st c="16398">函数的输入,该函数使用</st> `<st c="16599">print()</st>` <st c="16606">语句生成输入字符串的哈希,以便我们可以在我们的</st> <st c="16662">VSCode 日志中验证指纹。</st>

        <st c="16674">该函数返回生成的指纹字符串。</st> <st c="16730">稍后,我们将指纹存储在 SQLite 数据库中,同时存储每个用户的用法计数器,以便应用程序可以跟踪用户访问应用程序的次数。</st> <st c="16928">这些信息用于确定用户是否需要付费才能继续使用</st> <st c="17014">该应用程序。</st>

        <st c="17030">现在,是时候通过获取每个用户在下一节中的应用使用次数来覆盖我们用户跟踪机制的最后一部分。</st>

        <st c="17173">跟踪应用程序用户</st>

        <st c="17200">在本节中,我们将</st> <st c="17221">深入探讨应用程序后端的使用计数器功能。</st> <st c="17299">具体来说,我们将检查</st> `<st c="17333">get_usage_counter()</st>` <st c="17352">和</st> `<st c="17357">update_usage_counter()</st>` <st c="17379">函数,这些函数负责检索和更新与用户浏览器指纹 ID 相关的使用计数器。</st> <st c="17508">这些函数在确定用户是否超出使用限制并应被提示付费以继续使用</st> <st c="17661">应用程序方面起着至关重要的作用。</st>

        <st c="17677">The</st> `<st c="17682">get_usage_counter()</st>` <st c="17701">函数负责从 SQLite 数据库中检索特定浏览器指纹的使用计数器。</st> <st c="17822">计数器跟踪具有该指纹的用户提交了多少次</st> <st c="17909">代码错误:</st>
 def get_usage_counter(fingerprint):
    conn = sqlite3.connect('app.db')
    c = conn.cursor()
    result = c.execute('SELECT usage_counter FROM users WHERE fingerprint=?', [fingerprint]).fetchone()
    conn.close()
    if result is None:
        conn = sqlite3.connect('app.db')
        c = conn.cursor()
        c.execute('INSERT INTO users (fingerprint, usage_counter) VALUES (?, 0)', [fingerprint])
        conn.commit()
        conn.close()
        return 0
    else:
        return result[0]
        <st c="18338">The</st> <st c="18342">函数接受</st> `<st c="18358">fingerprint</st>` <st c="18369">作为参数,因为它用于检索给定浏览器指纹的使用计数器。</st> <st c="18469">指纹作为应用程序每个用户的唯一标识符,该函数在数据库中查找与该指纹相关的使用计数器。</st> <st c="18645">它连接到</st> `<st c="18698">app.db</st>` <st c="18704">,然后创建一个可以执行数据库上 SQLite 命令的光标对象。</st>

        <st c="18787">然后,</st> `<st c="18798">c.execute()</st>` <st c="18809">命令创建一个名为</st> `<st c="18854">users</st>` <st c="18859">的新数据库表,其中包含名为</st> `<st c="18883">fingerprint</st>` <st c="18894">和</st> `<st c="18899">usage_counter</st>`<st c="18912">的两列。</st> <st c="18954">它仅在表不存在时创建表。</st>

        <st c="18968">该</st> `<st c="18973">结果</st>` <st c="18979">执行一个 SQL 查询以获取给定</st> `<st c="19027">fingerprint</st>` <st c="19040">的</st> `<st c="19062">usage_counter</st>` <st c="19073">列值</st> `<st c="19083">users</st>` <st c="19088">表。</st> <st c="19096">它是通过使用参数化查询和</st> `<st c="19146">fetchone()</st>` <st c="19156">方法来完成的。</st> <st c="19165">如果对于给定的指纹没有找到记录,结果将被设置为</st> `<st c="19240">None</st>` <st c="19244">对于</st> <st c="19249">新用户。</st>

        <st c="19259">一旦</st> <st c="19264">与数据库的连接关闭,函数将检查之前数据库查询的结果是否为</st> `<st c="19382">None</st>` <st c="19386">。</st> <st c="19395">如果是</st> `<st c="19404">None</st>`<st c="19408">,则意味着在</st> `<st c="19455">fingerprint</st>` <st c="19466">的</st> `<st c="19474">users</st>` <st c="19479">表中没有记录。</st> <st c="19487">在这种情况下,函数将执行以下操作:</st>

            1.  <st c="19533">连接到</st> <st c="19546">数据库。</st>

            1.  <st c="19559">创建一个</st> <st c="19570">游标对象。</st>

            1.  <st c="19584">插入一个新记录用于</st> `<st c="19610">指纹</st>` <st c="19621">,并带有</st> `<st c="19629">usage_counter</st>` <st c="19642">值为</st> `<st c="19649">0</st>`<st c="19653">。</st>

            1.  <st c="19654">将更改提交到</st> <st c="19678">数据库。</st>

            1.  <st c="19691">关闭</st> <st c="19699">连接。</st>

            1.  <st c="19714">返回</st> `<st c="19723">0</st>`<st c="19724">。</st>

        <st c="19725">如果结果不是</st> `<st c="19747">None</st>`<st c="19751">,则意味着在</st> `<st c="19810">fingerprint</st>` <st c="19821">的</st> `<st c="19829">users</st>` <st c="19834">表中已经存在一个记录。</st> <st c="19842">在这种情况下,函数返回记录的</st> `<st c="19894">usage_counter</st>` <st c="19907">列的值。</st> <st c="19930">本质上,这个函数旨在为新用户返回</st> `<st c="19991">0</st>` <st c="19992">的值,或者为那些已经在数据库中的用户返回使用次数。</st>

        <st c="20064">另一方面,</st> `<st c="20069">update_usage_counter()</st>` <st c="20091">函数负责更新给定浏览器指纹的数据库中的使用计数器。</st> <st c="20216">该函数接受两个参数——浏览器指纹和更新的使用</st> <st c="20297">计数器值:</st>
<st c="20311">def</st> update_usage_counter(fingerprint, usage_counter):
    conn = sqlite3.connect(<st c="20389">'app.db'</st>)
    c = conn.cursor()
    c.execute(<st c="20429">'UPDATE users SET usage_counter=?</st> <st c="20464">WHERE fingerprint=?',</st> [usage_counter, fingerprint])
    conn.commit()
    conn.close()
        <st c="20542">一旦连接到数据库并创建了一个版本游标,该函数就负责在每次使用我们的 Code Bug Fixer 应用后更新使用计数器。</st> <st c="20716">它使用游标对象的</st> `<st c="20728">execute</st>` <st c="20735">方法执行一个更新用户</st> `<st c="20808">usage_counter</st>` <st c="20821">字段的 SQL 语句,该用户具有提供的</st> `<st c="20850">fingerprint</st>`<st c="20859">。</st>

        <st c="20871">该 SQL 语句使用</st> `<st c="20895">占位符 ?</st>` <st c="20909">来指示</st> `<st c="20942">usage_counter</st>` <st c="20955">和</st> `<st c="20960">fingerprint</st>` <st c="20971">的值应插入的位置。</st> <st c="20992">要插入的值作为列表传递给</st> `<st c="21065">execute()</st>` <st c="21074">的第二个参数,其顺序与 SQL 语句中的顺序相同。</st> <st c="21122">WHERE</st> <st c="21131">子句确保更新仅应用于匹配指定</st> `<st c="21203">fingerprint</st>`<st c="21213">的行。</st>

        <st c="21225">总结来说,</st> `<st c="21241">get_usage_counter()</st>` <st c="21260">函数从 SQLite 数据库中检索用户浏览器指纹 ID 的使用计数器,而</st> `<st c="21370">update_usage_counter()</st>` <st c="21392">函数在每次使用 Code Bug Fixer 应用后更新给定指纹的数据库中的使用计数器值。</st> <st c="21517">这些函数对于确定用户是否已超过使用限制并应提示他们支付以继续使用应用程序至关重要。</st> <st c="21677">我们现在可以将迄今为止创建的所有函数集成到我们的 Code Bug Fixer 应用程序</st> `<st c="21775">index()</st>` <st c="21782">页面中。</st>

        <st c="21788">实现使用计数器</st>

        <st c="21820">在本节中,</st> <st c="21841">我们将把我们之前创建的所有函数集成到我们的 Code Bug Fixer 应用程序的</st> `<st c="21907">index()</st>` <st c="21914">页面中。</st> <st c="21955">通过这样做,我们将能够跟踪用户提交代码错误的次数以及他们是否已达到三次提交的限制,从而需要他们付费才能继续。</st> <st c="22157">此外,我们还将能够将每个提交与一个唯一的浏览器指纹关联起来,以防止用户使用</st> <st c="22305">不同的别名</st> 提交多个错误:
 @app.route("/", methods=["GET", "POST"])
def index(): <st c="22378">initialize_database()</st>
 <st c="22399">fingerprint = get_fingerprint()</st>
 <st c="22431">usage_counter = get_usage_counter(fingerprint)</st>
        <st c="22478">前面的代码</st> <st c="22498">片段执行了三个基本任务。</st> <st c="22538">首先,它初始化数据库,然后从数据库中检索用户的浏览器指纹并获取他们的当前使用计数器。</st> <st c="22684">如果用户数据库表不存在,则会创建该表。</st> <st c="22759">指纹变量唯一标识用户,并允许我们跟踪他们的</st> <st c="22842">使用计数器。</st>

        <st c="22856">初始化完成后,我们需要设置一条规则,当使用计数器超过一个特定数字时,将控制权传递到支付页面:</st> <st c="23003"></st>
 if request.method == "POST": <st c="23166">POST</st>, which indicates that the user has submitted a form on the website. In our case, this means that the user has submitted code for fixing in the Code Bug Fixer. Then, our app will check whether the user’s usage counter is greater than <st c="23404">3</st>. If it is, it means the user has exceeded their limit of free usage and should be directed to the payment page. The function returns a rendered template of the <st c="23566">payment.html</st> page. We also add a <st c="23599">print()</st> statement so that we can verify the counter increment in our logs.
			<st c="23673">After the usage counter is initialized and we have a mechanism to check whether it is greater than the allowed number of usages, the last step is to make sure that the usage counter increments every time the user utilizes the Code</st> <st c="23905">Bug Fixer:</st>

fixed_code_prompt = (f"修复此代码:\n\n{code}\n\n 错误:\n\n{error}." f" \n 仅回复修复后的代码。")

    fixed_code_completions = client.chat.completions.create(

        model=model_engine,

        messages=[

            {"role": "user", "content": f"{fixed_code_prompt}"},

        ],

        max_tokens=1024,

        n=1,

        stop=None,

        temperature=0.2,

    )

    fixed_code = fixed_code_completions.choices[0].message.content <st c="24289">usage_counter += 1</st>

print(usage_counter)

usage_counter变量增加 1,这意味着用户多使用了一次服务。之后,我们将更新数据库中用户的使用计数器值,该用户通过其浏览器指纹识别。这确保了使用计数器在用户会话之间持久存在,并反映了用户使用服务的总次数。我们还添加了一个print()语句,以便我们可以在日志中验证计数器的增加。

        <st c="24946">现在,您可以运行代码错误修复应用程序来验证您的使用跟踪方法是否成功。</st> <st c="25056">一旦代码错误修复应用程序启动并运行,您可以将一个有错误的代码和一个错误放入相关字段,然后点击</st> **<st c="25191">代码修复</st>** <st c="25199">按钮。</st> <st c="25208">执行此操作两次,以便您的使用计数器增加两次。</st> <st c="25285">一旦您收到 ChatGPT API 的响应以及</st> **<st c="25335">修复代码</st>** <st c="25345">和</st> **<st c="25350">说明</st>** <st c="25361">字段在您的代码错误修复应用程序中已填充,您就可以回到</st> **<st c="25430">终端</st>** <st c="25438">窗口并验证您的指纹和使用计数器是否显示(见</st> *<st c="25516">图 4</st>**<st c="25524">.3</st>*<st c="25526">)。</st>

        ![图 4.3 – 浏览器指纹和使用计数器记录](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_04_3.jpg)

        <st c="26060">图 4.3 – 浏览器指纹和使用计数器记录</st>

        `<st c="26122">3ae64fc…</st>` <st c="26131">这是您的特定浏览器指纹,而数字表示您当前使用该应用程序的次数。</st> <st c="26254">由于您向 ChatGPT API 发出了两次请求,计数器</st> <st c="26319">增加了两次。</st>

        <st c="26337">要确认新数据库的创建,您可以在项目目录中检查名为</st> `<st c="26412">app.db</st>` <st c="26418">的文件(见</st> *<st c="26450">图 4</st>**<st c="26458">.4</st>*<st c="26460">)。</st> <st c="26464">此文件将存储所有用户数据,并且即使您关闭并重新启动</st> <st c="26563">应用程序,它也会持续存在。</st>

        ![图 4.4 – 数据库显示](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_04_4.jpg)

        <st c="26692">图 4.4 – 数据库显示</st>

        <st c="26725">这是将主要后端功能添加到我们的 Code Bug Fixer 应用程序的</st> <st c="26738">最后一步。</st> <st c="26823">在下一节中,您将学习如何构建</st> `<st c="26876">/charge</st>` <st c="26883">页面,当用户的免费</st> <st c="26937">试用期结束时,用户将被重定向到该页面。</st>

        <st c="26948">向 ChatGPT 应用程序添加付款</st>

        <st c="26989">在本节中,我将指导您完成创建 Code Bug Fixer 中的付款页面和功能的流程。</st> <st c="27110">我们将创建一个与 Stripe 连接的付款页面,为用户提供三种不同的</st> <st c="27194">订阅计划:</st>

            +   **<st c="27213">月度计划</st>**<st c="27226">:用户每月将被收取 5 美元</st> <st c="27253">费用</st>

            +   **<st c="27264">季度计划</st>**<st c="27279">:用户每季度将被收取 12 美元</st> <st c="27307">费用</st>

            +   **<st c="27320">年度计划</st>**<st c="27332">:用户每年将被收取 50 美元</st> <st c="27360">费用</st>

        <st c="27370">我们还将创建一个确认页面,该页面将使用如下的简单声明来确认用户已购买的方案:</st> *<st c="27500">您已成功支付 12 美元用于无限访问 Code</st> * *<st c="27587">Bug Fixer 的季度计划。</st>*

        <st c="27597">接下来,您将学习如何创建</st> `<st c="27637">payment.html</st>` <st c="27649">文件。</st>

        <st c="27655">构建付款页面</st>

        <st c="27682">在这里,我们将创建一个完整的 HTML 文档,其中包含一个用于从用户收集付款信息的表单。</st> <st c="27692">我们将使用</st> **<st c="27809">Bulma CSS</st>** <st c="27818">框架来</st> <st c="27832">美化页面并包含</st> **<st c="27859">jQuery</st>** <st c="27865">以及</st> <st c="27874">Stripe API 来处理</st> <st c="27899">付款处理。</st>

        <st c="27918">页面将被分为三个列,每个列显示不同的支付计划选项。</st> <st c="28013">每个选项包括一个带有标题、副标题和计划描述的卡片。</st> <st c="28094">支付表单位于每个卡片的页脚中,它包括用于计划类型和支付金额的隐藏输入字段。</st> <st c="28224">使用 Stripe API 生成一个支付按钮,该按钮收集支付信息并启动支付处理(见</st> *<st c="28348">图 4</st>**<st c="28356">.5</st>*<st c="28358">)。</st>

        ![图 4.5 – 支付页面](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_04_5.jpg)

        <st c="28894">图 4.5 – 支付页面</st>

        <st c="28923">生成</st> <st c="28936">“</st> <st c="28987">模板</st> <st c="28996">”</st> 文件夹。</st> <st c="29005">这两个文件将被命名为</st> `<st c="29035">payments.html</st>` <st c="29048">和</st> `<st c="29053">charge.html</st>`<st c="29064">。一旦完成,Code Bug Fixer 项目的结构将如下所示:</st> <st c="29129">如下:</st>
 CodeBugFixer/
├── templates/
│   ├── charge.html
│   ├── index.html
│   └── payment.html
├── venv/
├── app.db
├── app.py
└── config.py
        <st c="29269">我们将从构建我们的</st> `<st c="29312">payments.html</st>` <st c="29325">页面头部开始:</st>
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.0/css/bulma.min.css">
    <script src="img/jquery.min.js"></script>
    <script src="img/"></script>
    <title>Payment</title>
</head>
</html>
        <st c="29733">头部</st> <st c="29743">包含文档正确显示所需的元数据和外部资源。</st> <st c="29845">字符集指定文档中使用的字符编码,在本例中为</st> `<st c="29927">UTF-8</st>` <st c="29932">,而 viewport 元标签确保文档在不同屏幕尺寸的设备上正确显示。</st>

        <st c="30069">`<st c="30074">link</st>`</st> 标签用于导入外部框架。</st> <st c="30078">我们将使用 Bulma CSS 框架,它提供了一套预设计的 CSS 样式,可以快速且容易地构建响应式网页。</st> <st c="30122">我们将使用 Bulma CSS 框架,它提供了一套预设计的 CSS 样式,可以快速且容易地构建响应式网页。</st>

        <st c="30256">然后,我们将导入 jQuery 库,这是一个流行的 JavaScript 库,它简化了操作 HTML 文档和处理事件的过程。</st> <st c="30416">第二个导入是 Stripe API 库,它提供了处理</st> <st c="30501">在线支付</st> 的功能。

        <st c="30517">现在,在</st> `<st c="30529"></head></st>`<st c="30536">,我们可以开始构建 HTML 文件的主体部分,它被包含在</st> `<st c="30620"><</st>``<st c="30621">body></st>` <st c="30626">标签内:</st>
 <body>
    <section class="section">
        <div class="container">
            <h1 class="title">Payment Options</h1>
            <div class="columns">
          </div>
        </div>
    </section>
</body>
        `<st c="30783">我们将使用</st>` `<st c="30800"><section></st>` `<st c="30809">元素</st>` `<st c="30809">,表示它是一个可以独立于其他元素进行样式的页面独立部分。</st>` `<st c="30924">有一个</st>` `<st c="30935"><div></st>` `<st c="30940">元素,其类为</st>` `<st c="30965">columns</st>` `<st c="30972">。</st>` `<st c="30972">该元素用于创建一个网格系统,用于在列中布局内容。</st>` `<st c="31050">这是一种创建响应式布局的常见方法,其中列的数量</st>` `<st c="31136">可能根据屏幕大小或使用的设备而变化。</st>` `<st c="31196">在这种情况下,列将包含用户可以选择的不同支付计划选项,每个选项都有其自己的功能和定价。</st>`

        `<st c="31346">现在,在</st>` `<st c="31363">列</st>` `<st c="31370"><div></st>` `<st c="31376">元素内部,我们可以创建三个列,代表之前提到的三个支付计划:</st>` `<st c="31453">:</st>`

        `<st c="31471">您可以在</st>` `<st c="31498">payments.html</st>` `<st c="31511">文件</st>` `<st c="31517">中找到完整的</st>` [<st c="31520">https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter04%20CodeBugFixer/templates/payment.html</st>](https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter04%20CodeBugFixer/templates/payment.html)<st c="31654">:</st>
 <div class="column">
    <div class="card">
        <div class="card-content">
            <p class="title">Monthly Plan</p>
            <p class="subtitle">$5 par month</p>
            <p>This plan will give you unlimited access
                to the code explanation and fixing services every month. You will be charged $5 every month.</p>
        </div>
        <footer class="card_footer">
            <form action="/charge" method="post">
                <input type="hidden" name="plan" value="monthly">
                <input type="hidden" name="amount" value="500">
                <script
                    src="img/checkout.js"
                    class="stripe-button"
                    data-key=<st c="32193">"<YOUR_PUBLIC_KEY>"</st> data-amount="500"
                    data-name="Monthly Plan"
                    data-description="$5 per month"
                    data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
                    data-locale="auto"
                    data-zip-code="false">
                </script>
            </form>
        </footer>
    </div>
        `<st c="32440">重要提示</st>`

        `<st c="32455">请确保将</st>` `<st c="32484">"<YOUR_PUBLIC_KEY>"</st>` `<st c="32503">标签替换为您从</st>` `<st c="32547">Stripe 账户</st>` `<st c="32547">获得的公钥。</st>`

        `<st c="32562">第一个</st>` `<st c="32573"><div></st>` `<st c="32578">具有</st>` `<st c="32594">列</st>` `<st c="32600">类别的元素</st>` `<st c="32660">负责创建一个类似卡片元素,用于展示提供给用户的月度计划信息。</st>` `<st c="32725">该卡片包含计划名称、订阅费用以及用户可以从该计划中期待的内容。</st>`

        `<st c="32849">使用</st>` `<st c="32854"><div></st>` `<st c="32859">具有</st>` `<st c="32875">卡片</st>` `<st c="32879">类别的元素</st>` `<st c="32976">用于创建展示月度订阅计划信息的卡片。</st>` `<st c="32976">在卡片内部,卡片内容使用</st>` `<st c="33030">card-content</st>` `<st c="33042">类</st>` `<st c="33050">定义。</st>` `<st c="33050">卡片内容由三个段落组成,第一个包含计划的标题,</st>` `<st c="33141">月度计划</st>` `<st c="33153">,第二个包含订阅费用,</st>` `<st c="33199">$5 每月</st>` `<st c="33211">,第三个提供计划的描述,突出订阅该计划的好处。</st>`

        <st c="33321">在页脚内部,定义了一个</st> `<st c="33343">表单</st>` <st c="33347">元素,该元素用于将订阅请求提交到服务器。</st> <st c="33432">表单的 action 属性设置为</st> `<st c="33470">/charge</st>`<st c="33477">,这表示订阅请求将被发送到服务器的</st> `<st c="33545">/charge</st>` <st c="33552">路由。</st> <st c="33574">我们将在稍后构建</st> `<st c="33592">/charge</st>` <st c="33599">页面的后端功能。</st> <st c="33629">此功能将确保在购买支付计划后向用户显示确认信息。</st>

        <st c="33736">表单包含两个隐藏的输入字段,用于发送计划的名称和值。</st> <st c="33819">在这种情况下,计划的名称设置为</st> `<st c="33859">monthly</st>`<st c="33866">,而金额属性设置为</st> `<st c="33914">500</st>`<st c="33917">,这代表订阅金额(以分计)。</st> <st c="33970">这些信息将被用于渲染</st> <st c="34014">确认页面。</st>

        <st c="34032">最后,在表单元素内部包含了一个脚本标签,该标签加载 Stripe 结账脚本。</st> <st c="34130">此脚本负责创建一个</st> `<st c="34494">data-locale</st>` <st c="34505">属性并将其设置为</st> `<st c="34519">auto</st>`<st c="34523">,这确保了支付表单的语言将根据用户的地理位置自动设置。</st> <st c="34628">`<st c="34632">data-zip-code</st>` <st c="34645">`属性设置为</st> `<st c="34666">false</st>`<st c="34671">,这意味着支付表单将不需要用户输入他们的</st> <st c="34748">邮编。</st>

        <st c="34757">如代码片段所示,季度计划和年度计划的列是以与月度计划相同的方式构建的。</st> <st c="34888">唯一的区别是计划的名称、副标题和成本值,以及计划隐藏输入字段和要收费的金额值。</st>

        <st c="35057">您可以通过在任何浏览器中显示</st> `<st c="35083">payment.html</st>` <st c="35095">页面来验证您的页面是否正常工作。</st> <st c="35149">您可以从</st> **<st c="35220">打开方式</st>** <st c="35229">选项中选择 HTML 文件并选择您喜欢的浏览器(见</st> *<st c="35243">图 4</st>**<st c="35251">.6</st>*<st c="35253">)。</st> <st c="35257">然后您应该看到一个支付页面,类似于在</st> *<st c="35325">图 4</st>**<st c="35333">.5</st>*<st c="35335">中显示的页面。</st>

        ![图 4.6 – 在浏览器中显示 HTML](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_04_6.jpg)

        <st c="35488">图 4.6 – 在浏览器中显示 HTML</st>

        <st c="35534">这就是您如何构建一个包含收集用户支付信息的表单的支付页面。</st> <st c="35546">我们使用 Bulma CSS 框架设计了支付页面,并使用 jQuery 和 Stripe API 处理支付处理。</st> <st c="35641">页面分为三个列,每列显示不同的支付计划选项,支付表单位于每张卡的页脚中。</st> <st c="35771">Stripe API 用于生成一个收集支付信息并启动</st> <st c="35801">支付处理</st> <st c="35811">的支付按钮。</st>

        <st c="36031">在下一节中,您将学习如何使用 Stripe API 在您的应用程序中创建处理用户支付的收费函数,并返回一个支付</st> <st c="36192">确认页面。</st>

        <st c="36210">确认用户支付</st>

        <st c="36235">在上一个部分中,您了解到当用户选择购买支付计划以访问您的应用程序时,我们将立即触发</st> <st c="36243">/charge</st> <st c="36248">页面,并为其提供所选计划的名称以及相应的支付金额</st> <st c="36289">(以分计)。</st>

        <st c="36294">我们可以在我们的</st> `<st c="36312">app.py</st>` <st c="36318">文件中的</st> `<st c="36335">index()</st>` <st c="36342">函数中构建</st> `<st c="36350">charge()</st>` <st c="36356">函数。</st> <st c="36366">此函数是 Code Bug Fixer 网络应用程序的一部分,负责处理用户选择定价计划并提交其支付信息时的</st> `<st c="36402">收费</st>` <st c="36408">过程。</st> <st c="36449">该函数在用户点击</st> `<st c="36457">payment.html</st>`<st c="36469">:</st>
 @app.route(<st c="36871">"/charge",</st> methods=[<st c="36892">"POST"</st>]) <st c="36903">def</st> charge():
    amount = int(request.form[<st c="36943">"amount"</st>])
    plan = str(request.form[<st c="36980">"plan"</st>])
    customer = stripe.Customer.create(
        email=request.form<st c="37044">["stripeEmail"],</st> source=request.form<st c="37081">["stripeToken"]</st> )
    charge = stripe.Charge.create(
        customer=customer.id,
        amount=amount,
        currency=<st c="37177">"usd",</st> description=<st c="37197">"App Charge"</st> ) <st c="37304">app.py</st> file here: <st c="37322">https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter04%20CodeBugFixer/app.py</st>.
			<st c="37441">The</st> `<st c="37446">@app.route("/charge", methods=["POST"])</st>` <st c="37485">decorator creates a route to handle a</st> `<st c="37524">POST</st>` <st c="37528">request sent to the</st> `<st c="37549">/charge</st>` <st c="37556">endpoint.</st> <st c="37567">This means that when the form in the HTML template</st> <st c="37618">is submitted, it will send a</st> `<st c="37647">POST</st>` <st c="37651">request to</st> <st c="37663">this endpoint.</st>
			<st c="37677">Both the</st> `<st c="37687">amount</st>` <st c="37693">and</st> `<st c="37698">plan</st>` <st c="37702">variables are assigned values that were previously sent by the user via a payment form, and they are used later in the function to create a new customer and charge the customer the appropriate amount based on the</st> <st c="37916">selected plan.</st>
			<st c="37930">Then, we can create a new Stripe customer object using the Stripe API.</st> <st c="38002">The</st> `<st c="38006">stripe.Customer.create()</st>` <st c="38030">method takes two arguments – the email address of the customer and the payment source.</st> <st c="38118">In this case, the email address is obtained from the</st> `<st c="38171">stripeEmail</st>` <st c="38182">parameter in the</st> `<st c="38200">POST</st>` <st c="38204">request sent by the Stripe checkout form, and the payment source is obtained from the</st> `<st c="38291">stripeToken</st>` <st c="38302">parameter.</st>
			<st c="38313">The</st> `<st c="38318">stripeToken</st>` <st c="38329">parameter</st> <st c="38339">is a unique identifier for the payment information provided by the user in the checkout form, such as credit card details or a payment app.</st> <st c="38480">Stripe uses this token to securely charge the user’s payment method for the specified amount.</st> <st c="38574">By passing the</st> `<st c="38589">stripeToken</st>` <st c="38600">parameter to the source argument of</st> `<st c="38637">stripe.Customer.create()</st>`<st c="38661">, the payment information is associated with the newly created customer object</st> <st c="38740">in Stripe.</st>
			<st c="38750">We can then use the Stripe API to create a charge object that is associated with the customer who provided their payment information.</st> <st c="38885">The</st> `<st c="38889">stripe.Charge.create()</st>` <st c="38911">method creates a new charge object in the Stripe API with the</st> <st c="38974">following arguments:</st>

				*   `<st c="38994">customer</st>`<st c="39003">: This is the ID of the Stripe customer object associated with the payment.</st> <st c="39080">The</st> `<st c="39084">customer.id</st>` <st c="39095">attribute is used to retrieve the ID of the customer object created in the</st> <st c="39171">previous step.</st>
				*   `<st c="39185">amount</st>`<st c="39192">: This is the amount of the charge in cents.</st> <st c="39238">The amount variable is set to the value passed in the</st> `<st c="39292">POST</st>` <st c="39296">request from</st> <st c="39310">the form.</st>
				*   `<st c="39319">currency</st>`<st c="39328">: This is the currency of the charge.</st> <st c="39367">In this case, it is set</st> <st c="39391">to</st> `<st c="39394">USD</st>`<st c="39397">.</st>
				*   `<st c="39398">description</st>`<st c="39410">: This is a brief description of the charge.</st> <st c="39456">In this case, it is set to</st> `<st c="39483">App Charge</st>`<st c="39493">.</st>

			<st c="39494">After creating the charge, the function uses Flask’s</st> `<st c="39548">render_template()</st>` <st c="39565">function to render the</st> `<st c="39589">charge.html</st>` <st c="39600">template and pass in the amount and plan variables.</st> <st c="39653">The</st> `<st c="39657">charge.html</st>` <st c="39668">template will be used to display a message to the user, indicating that their payment</st> <st c="39755">was successful.</st>
			<st c="39770">Our final task when building the application is to create the</st> `<st c="39833">charge.html</st>` <st c="39844">file.</st> <st c="39851">This file will be used to display a confirmation message to the user after a successful charge has been made.</st> <st c="39961">The</st> `<st c="39965">render_template</st>` <st c="39980">function used in the charge function of the</st> `<st c="40025">app.py</st>` <st c="40031">file specifies that the</st> `<st c="40056">charge.html</st>` <st c="40067">file will be used to render</st> <st c="40096">the message.</st>
			<st c="40108">You can now open the</st> `<st c="40130">charge.html</st>` <st c="40141">file that we created in the</st> `<st c="40170">templates</st>` <st c="40179">folder and add the</st> <st c="40199">following code:</st>

<head>
<meta charset="UTF-8">

<title>支付确认</title>
</head> <body>

支付确认

您已成功支付${{ amount / 100 }}美元用于{{ plan }}计划,以获得对 Code Bug Fixer 的无限制访问

</body>

			<st c="40495">In this simple HTML page, the</st> `<st c="40526"><body></st>` <st c="40532">section contains a heading that says</st> `<st c="40570">Payment Confirmation</st>`<st c="40590">. The</st> <st c="40596">paragraph below the heading uses curly braces to display the amount and plan variables passed from the</st> `<st c="40699">charge()</st>` <st c="40707">function.</st> <st c="40718">Specifically, it displays the amount variable divided by</st> `<st c="40775">100</st>` <st c="40778">(because the amount variable is in cents) and the</st> `<st c="40829">plan</st>` <st c="40833">variable for the user to confirm the payment they</st> <st c="40884">have made.</st>
			<st c="40894">When the</st> `<st c="40904">charge()</st>` <st c="40912">function is called and executed, it returns the</st> `<st c="40961">charge.html</st>` <st c="40972">file as a response, with the amount and plan variables passed as arguments to be rendered in the appropriate places in the</st> <st c="41096">HTML code.</st>
			<st c="41106">Now that the payments infrastructure has been added to your app, you can test it by navigating to the relevant pages and clicking on the payment buttons.</st> <st c="41261">You can follow the</st> <st c="41280">following steps:</st>

				1.  <st c="41296">Run the</st> `<st c="41305">app.py</st>` <st c="41311">file to start up your Code Bug</st> <st c="41343">Fixer app.</st>
				2.  <st c="41353">Create more than three bug-fixing requests to the ChatGPT API to be prompted to the</st> `<st c="41438">Payments</st>` <st c="41446">page (see</st> *<st c="41457">Figure 4</st>**<st c="41465">.5</st>*<st c="41467">).</st>
				3.  <st c="41470">Click on the</st> **<st c="41484">Pay with Card</st>** <st c="41497">button on one of the</st> <st c="41519">payment plans.</st>
				4.  <st c="41533">Enter the following sample credit</st> <st c="41567">card details in the pop-up window (see</st> *<st c="41607">Figure 4</st>**<st c="41615">.7</st>*<st c="41617">):</st>
    *   `<st c="41629">mrsmith@gmail.com</st>`
    *   `<st c="41661">4242 4242</st>` `<st c="41671">4242 4242</st>`
    *   `<st c="41695">09 /</st>` `<st c="41700">30</st>`
    *   `<st c="41719">424</st>`
				5.  <st c="41722">Click the</st> **<st c="41733">Pay</st>** <st c="41736">button:</st>

			![Figure 4.7 – Stripe payment information](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_04_7.jpg)

			<st c="41845">Figure 4.7 – Stripe payment information</st>
			<st c="41884">Once you have submitted your payment, you should be redirected to a payment confirmation page that displays a message indicating that your payment has been successfully processed, as shown in</st> *<st c="42077">Figure 4</st>**<st c="42085">.8</st>*<st c="42087">:</st>
			![Figure 4.8 – The confirmation page](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_04_8.jpg)

			<st c="42209">Figure 4.8 – The confirmation page</st>
			<st c="42243">In this section, you</st> <st c="42265">saw how to confirm user payments using the Stripe API in a Code Bug Fixer web application.</st> <st c="42356">We built</st> `<st c="42365">charge()</st>` <st c="42373">to handle the charge process when a user selects a pricing plan and submits their payment information.</st> <st c="42477">We also tested the payment infrastructure of the app using sample credit</st> <st c="42550">card details.</st>
			<st c="42563">Summary</st>
			<st c="42571">This chapter focused on the implementation of a payment infrastructure into a web application using the Stripe API.</st> <st c="42688">It provided instructions on how to set up a Stripe account, create API keys, and configure the payment settings.</st> <st c="42801">You saw the importance of selecting the appropriate business strategy, such as subscription or one-time payment, before implementing payment options.</st> <st c="42951">You also saw how to track user visits and usage using a SQL database and how to create payment plans on a payment page.</st> <st c="43071">Additionally, the chapter outlined the functions required to retrieve and update the usage counter and described how to implement them to track a user’s</st> <st c="43224">payment status.</st>
			<st c="43239">You learned how to build the</st> `<st c="43269">charge()</st>` <st c="43277">function, which handles the payment process when a user selects a pricing plan and submits their payment information.</st> <st c="43396">We covered the use of the Stripe API to create a new customer and charge object and render the</st> `<st c="43491">charge.html</st>` <st c="43502">template to display a confirmation message to the user.</st> <st c="43559">This section also provided instructions on how to test the payment feature using sample credit card details.</st> <st c="43668">The chapter provided a comprehensive guide on implementing a payment infrastructure in a web application, integrating the Stripe API and the ChatGPT API, from creating a Stripe account to handling payments and confirming</st> <st c="43889">user payments.</st>
			<st c="43903">In</st> *<st c="43907">Chapter 5</st>*<st c="43916">,</st> *<st c="43918">Quiz Generation App with ChatGPT and Django</st>*<st c="43961">, you will learn how to integrate the ChatGPT API with</st> **<st c="44016">Django</st>**<st c="44022">, a full stack web framework that comes with many built-in features and is designed to handle larger and more complex web applications than Flask.</st> <st c="44169">Django includes everything, from URL routing, database ORM, and an admin interface to authentication and security features, providing a more comprehensive framework for</st> <st c="44338">web development.</st>



第六章:5

使用 ChatGPT 和 Django 创建问答应用

在本章中,我们将深入探讨将 ChatGPT,一个前沿的 语言 模型,与 Django,广受赞誉的 Python 应用开发框架 相结合的激动人心的世界。 我们将探索如何构建一个动态且交互式的考试 生成应用,该应用利用 人工智能 (AI)。

在前几章中,我们主要关注了 Flask,一个轻量级和基本的 Web 框架。 然而,在本章中,我们将重点关注 Django,一个强大且高级的框架,它在构建一些最著名和最广泛使用的应用程序中发挥了关键作用,包括 Instagram、Dropbox 和 Pinterest。 您将有机会探索 Django 的功能,包括数据库管理、认证系统、管理界面以及 表单处理。

您将学习如何从头开始构建 Django 项目,包括设置环境和创建应用程序的基础组件。 我们将专注于创建问答应用的框架和视图。 您将探索 ChatGPT 和 Django 的集成,使您能够使用 AI 进行问答生成。 为了确保全面的学习体验,我们将介绍应用中的两个基本视图。 一个视图将允许用户通过输入学习材料和执行 ChatGPT API 来生成问答,相关的问题将被存储在数据库中。 另一个视图将使用户能够方便地下载之前 生成的测试。

在本章中,您将探索开发健壮的 Django 应用程序所必需的几个关键主题。 您将从安装 Django 并创建您的第一个运行项目开始,为您的应用程序打下基础。 之后,您将构建针对考试生成应用程序定制的 Django 视图,然后与 Django 集成 ChatGPT API 以在后台拦截响应。 为了提升用户体验,您将利用 Bootstrap 模板创建一个视觉上吸引人的界面。 此外,您将学习如何安全地将 ChatGPT 响应在数据库中存储和检索,确保数据完整性和安全性。 最后,本章将指导您将文件下载功能添加到您的应用程序中,完善您的技能集,并使您能够交付一个全面且功能齐全的 网络应用程序。

在本章中,我们将涵盖以下 主题:

  • 构建一个 Django 项目

  • 创建考试应用框架 和视图

  • 将 ChatGPT 和 Django 集成用于 测验生成

  • 存储和下载 生成的测验

在本章结束时,您将具备使用 ChatGPT API 生成任何提供的 学习材料派生的考试问题的知识和技能。

技术要求

在继续本章内容之前,您需要完成一些基本软件的安装。 此外,Django 网络框架的安装将在下一节中演示。

该项目有以下 技术先决条件:

  • 在您的 本地机器上安装 Python 3.7 或更高版本

  • 一个代码编辑器,推荐使用 VSCode 以获得 最佳体验

  • 一个 OpenAI API 密钥,用于访问必要的 API 功能

您可以在提供的 存储库 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API](https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API)中访问本章使用的代码示例。

构建 Django 项目

在本节中,我们将开始一段激动人心的旅程,构建一个作为我们测验生成应用基础的 Django 项目。 我们将引导您逐步设置和构建您的 Django 项目,确保您有一个坚实的基础来继续。 在本节结束时,您将拥有一个功能齐全的 Django 项目,可以基于 学习材料自动生成测验。

我们的冒险从 安装 Django 和创建新的 Django 项目开始。 我们将向您介绍设置开发环境的过程,包括 Python 和 Django 框架的安装。 在 Django 设置完成后,我们将使用命令行界面生成一个新的 Django 项目,为您提供必要的目录结构和初始 配置文件。

我们可以先创建一个名为 <st c="4443">QuizApp</st>的新 VSCode 项目。 现在,让我们点击 VSCode 的 <st c="4651">pip</st>

 $pip install Django

接下来,您可以在终端中运行以下命令来创建一个新的 Django 项目:

 $django-admin startproject quiz_project

当您运行此命令时,Django 的命令行工具,称为 <st c="4870">django-admin</st>,将创建一个具有指定名称的新项目目录, <st c="4941">quiz_project</st>。此目录将包含启动 Django 项目所需的文件和文件夹。

<st c="5046">startproject</st> 命令 通过生成以下文件来初始化项目结构: 以下文件:

  • <st c="5135">manage.py</st>:一个命令行工具,允许您与各种 Django 命令交互并管理 您的项目。

  • <st c="5252">quiz_project</st>:项目目录,其名称将与命令中指定的名称相同。 此目录作为您 Django 项目的根目录,包含配置文件和其他 项目特定组件。

在项目目录内,您将找到以下文件和目录:

  • <st c="5567">__init__.py</st>:一个空文件,标记目录为一个 Python 包

  • <st c="5640">settings.py</st>:配置文件,您在其中定义 Django 项目的各种设置,包括数据库设置、中间件和 已安装的应用程序

  • <st c="5796">urls.py</st>: 定义您项目 URL 与视图之间映射的 URL 配置文件。

  • <st c="5898">wsgi.py</st>: 用于部署的Web 服务器网关接口 (WSGI) 配置文件。

您可以通过定义模型、视图和模板以及根据应用程序的需求配置设置来进一步自定义和开发您的 Django 项目。

在 Django 中,一个项目是一组设置、配置和多个应用程序的集合,这些应用程序协同工作以创建一个网络应用程序。 另一方面,应用程序是 Django 项目中的一个模块化组件,它服务于特定的目的或功能。 因此,在我们的 <st c="6434">quiz_project</st>中,我们可以创建一个新的应用程序 如下:

 $cd quiz_project
$python manage.py startapp quiz_app

我们新创建的应用程序的目的将是生成 AI 问题并允许用户下载它们。 将根据指定的应用程序名称生成一个新目录, <st c="6716">quiz_app</st>。 此目录包含开发您的 Django 应用程序所需的必要文件和文件夹。 让我们探索 应用程序目录 内的典型项目结构和文件:

  • <st c="6889">admin.py</st>: 此文件用于将您的应用程序模型注册到 Django 管理界面。 您可以根据需要自定义模型在管理站点上的显示和交互方式。

  • <st c="7068">apps.py</st>: 此文件定义了应用程序配置,包括应用程序的名称,并在应用程序启动时使用初始化函数。

  • <st c="7217">models.py</st>: 在这里,您可以使用 Django 对象关系映射 (ORM) 来定义您的应用程序的数据模型。 模型代表您数据的结构,并定义了数据库中的表。

  • <st c="7402">tests.py</st>: 此文件用于编写您应用程序的测试。 您可以创建测试用例并运行它们,以确保应用程序的功能。

  • <st c="7540">views.py</st>: 此文件定义了处理 HTTP 请求并返回 HTTP 响应的函数或类。 该文件处理数据,与模型交互,并渲染模板以生成显示给用户的内 容。

  • <st c="7764">migrations/</st>: 该文件夹用于存储数据库迁移文件。 迁移是管理数据库模式随时间变化的一种方式。 它们允许您跟踪和应用数据库结构的增量更改,例如创建新表、修改现有表以及添加或 删除列。

测验生成应用程序的完整高级项目结构如下: 如下:

 quiz_project/
├── quiz_app
│   ├── migrations/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── quiz_project/
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
│   └── __init__.py
└──  manage.py

默认情况下,Django 包含几个内置应用程序,例如 <st c="8454">auth</st>, <st c="8460">admin</st>, <st c="8467">contenttypes</st>,和 <st c="8485">sessions</st>。这些应用程序都有自己的迁移需要应用以在数据库中创建包含默认用户数据的所需表。

Django 使用默认的 SQLite 数据库来存储数据。 我们可以运行以下命令来使用所有 现有模型初始化数据库: 现有模型初始化数据库:

 $python manage.py migrate

当你运行此命令时,Django 将检查这些默认应用中是否有任何挂起的迁移,并在必要时应用它们。 这确保了数据库模式被正确设置以支持 Django 内置功能,并由 命令输出进行验证:

 Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

一旦迁移都设置好了,你就可以启动开发服务器来 在本地运行你的 Django 项目:

<st c="10175">$python manage.py runserver</st> Watching for file changes with StatReloader
Performing system checks... System check identified no issues (0 silenced). May 26, 2023 - 18:59:08
Django version 4.2.1, using settings quiz_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

当你在终端中运行此命令时,Django 的 <st c="10546">manage.py</st> 脚本启动一个轻量级 Web 服务器,允许你在本地运行和测试你的 Django 应用程序。 要访问你的应用程序,你可以点击终端输出中提供的链接(http://127.0.0.1:8000/)或在浏览器中输入它。 此链接包含一个本地 IP 地址和一个端口,你可以通过该端口访问你的新应用程序(见 图 5**.1)。

图 5.1 – Django 欢迎屏幕

图 5.1 – Django 欢迎屏幕

在浏览器中看到 Django 欢迎页面意味着我们已经成功创建了我们的 Django 项目和应用。 在下一节中,我们将根据我们的 项目需求,通过定义模型、视图和模板以及配置 URL 路由来开始构建我们的应用程序。

创建考试应用程序框架和视图

在本节中,我们将关注构建我们的 Django 应用程序的基本结构。 我们将从探索 Django 设置开始,在那里你将学习如何配置重要方面,例如数据库连接和中间件组件。 理解和正确设置这些配置对于应用程序的平稳运行至关重要。 你的应用程序。

我们还将了解 Django 中的 URL 处理。你将发现如何使用 <st c="11895">urls.py</st> 文件定义 URL 模式,从而实现应用程序内的无缝导航。 我们还将介绍使用正则表达式进行动态 URL,以实现灵活和动态的路由。 此外,我们将指导你通过将基础模板集成到应用程序中,这将提供一致菜单、侧边栏和视图。 你的应用程序。

连接 Django 视图和 URL

在 Django 中,视图、应用 URL 和项目 URL 之间的关系构成了处理和路由 Web 请求的关键结构。 流程从视图开始,视图是负责处理特定 HTTP 请求并返回适当响应的 Python 函数或类。 每个视图对应于应用程序中的特定功能或页面。 这些视图可以通过分配唯一的 URL 向用户展示。 由于在 Django 中,一个项目可以有多个应用程序,因此这些 URL 首先在 <st c="12812">quiz_app/urls.py</st>中的应用级别定义。然后,这些 URL 被传递到位于 <st c="12878">urls.py</st> 文件中的项目级别,该文件位于我们的项目目录 <st c="12906">quiz_project</st> 中(参见 图 5**.2)。

图 5.2 – Django 视图/URL 架构

图 5.2 – Django 视图/URL 架构

<st c="13024">默认情况下,Django 在初始化项目时会自动生成</st> <st c="13072">quiz_project/urls.py</st> <st c="13092">文件。</st> 然而,需要注意的是,我们将在 urls.py 文件中手动创建一个新文件,该文件位于 quiz_app 文件夹内。 <st c="13249">与项目级别的</st> <st c="13274">urls.py</st> <st c="13281">文件不同,应用级别的</st> <st c="13292">urls.py</st> <st c="13299">文件不会自动生成,并且组织并定义特定于</st> <st c="13453">quiz_app</st> `内部功能的 URL 模式是至关重要的。

<st c="13462">现在,您可以打开</st> <st c="13481">quiz_app/views.py</st> <st c="13498">并编写以下</st> `Python 代码:

 from django.shortcuts import render
def home(request):
    return render(request, 'base.html')

<st c="13626">此代码</st> <st c="13637">演示了一个名为</st> <st c="13686">home</st> <st c="13690">的简单 Django 视图函数。</st> 该视图函数负责处理特定类型的请求,通常是 HTTP GET 请求,并生成适当的响应。

在函数内部,Django 快捷方式 <st c="13837">render</st> <st c="13879">函数用于渲染 HTML 模板。</st> 第一个参数, request ,代表传入的 HTTP 请求对象。 <st c="14006">该对象包含有关请求的信息,例如头部、数据和用户会话详情。</st> 第二个参数, base.html ,指定要渲染的模板。

<st c="14178">在构建</st> <st c="14199">base.html</st> <st c="14208">文件之前,我们需要确保用户可以访问</st> <st c="14242">home</st> <st c="14246">视图。</st> 为了实现这一点,我们需要在我们的 quiz_app/urls.py 文件中指定一个唯一的 URL:

 from django.urls import path
from . import views
urlpatterns = [
    path('', views.home, name='home'),
]

<st c="14461">在这里,</st> <st c="14472">urlpatterns</st> <st c="14483">变量是一个包含应用程序定义的 URL 模式的列表。</st> 目前,已指定了一个 URL 模式。 <st c="14623"> <st c="14627">path</st> <st c="14631">函数用于定义 URL 模式。</st> 它接受三个参数 - 第一个参数是 URL 模式本身,在本例中由空字符串 '' 表示。 `这个空字符串表示应用程序的根 URL 或基本 URL。

第二个参数, <st c="14904">views.home</st>, 指的是将处理此 URL 模式请求的视图函数。 第三个参数, <st c="15015">name='home'</st>, 为此 URL 模式提供了一个唯一的名称。 此名称可用于从应用程序的其他部分 引用 URL 模式,例如模板或其他 URL 配置。

最后,我们可以通过 修改 <st c="15294">quiz_project/urls.py</st>:

<st c="15316">from django.contrib import admin</st> from django.urls import <st c="15373">include</st>, path
urlpatterns = [
 <st c="15403">path('admin/', admin.site.urls),</st>
 <st c="15435">path('', include('quiz_app.urls')),</st> ]

提供的代码展示了我们 Django 项目中 URL 模式的配置。 就像在应用级别的 URL 文件中一样,这里 <st c="15612">urlpatterns</st> 变量包含项目 URL 名称的列表。 在这种情况下,指定了两个 URL 模式。

第一个 URL 模式是使用 <st c="15771">path</st> 函数和 <st c="15794">admin/</st> 参数定义的。 这将 <st c="15831">admin/</st> URL 模式与 Django 管理界面关联起来,从而允许访问管理仪表板和相关功能。 Django 管理页面通常默认设置,与我们 的 quiz 应用程序的功能无关。

<st c="16068">path('', include('quiz_app.urls'))</st> path 函数从 <st c="16147">quiz_app/urls.py</st>获取应用级别的 URL。第一个参数,一个空字符串 <st c="16202">''</st>,表示应用程序的根 URL 或基本 URL。 这意味着当用户访问项目的根 URL 时,此 URL 模式将被 匹配。

第二个参数, <st c="16382">include('quiz_app.urls')</st>, 指示 Django 包含在 <st c="16468">quiz_app.urls</st> 模块中定义的 URL 模式。 这意味着任何在 <st c="16536">quiz_app</st> 应用程序中指定的 URL 都将被匹配并 相应处理。

这是 URL 处理分层结构的模样。 我们从处理应用级 URL 的视图开始,这些 URL 定义了特定的 URL 模式,最终到项目级 URL,这些 URL 将请求路由到适当的应用级 URL。 这个过程通过代码示例进行了说明,突出了在应用和项目级别正确配置 URL 对于在 Django 应用程序中实现顺畅导航和功能的重要性。 Django 应用程序。

在接下来的部分中,我们将深入探讨构建 HTML 模板,包括必要的 <st c="17159">base.html</st> 文件。 模板在定义 Django 应用程序中网页的视觉结构和布局方面发挥着至关重要的作用。 通过构建和定制 HTML 模板,我们可以为我们的 测验应用程序 创建一个一致且视觉上吸引人的用户界面。

开发 Django 模板

在本节中,我们将专注于构建 <st c="17501">base.html</st> 模板并将 CSS 集成到我们的 Django 应用程序中。 <st c="17575">base.html</st> 模板是我们网页视觉结构和布局的基础。 为了增强我们应用程序的设计和样式,我们将利用外部 CSS 资源。 一个宝贵的资源是 Bootstrap 框架,它提供了一系列预设计的模板和组件。 我们将通过从官方 Bootstrap 网站(https://getbootstrap.com/docs/5.3/examples/)中寻找合适的模板的过程,您可以在那里探索各种示例并选择与您期望的美学 和功能相匹配的模板。

如果您使用 Google Chrome,可以轻松访问任何 Bootstrap 模板背后的代码。例如,对于这个项目,我们可以使用 Dashboard 模板,您可以通过以下链接访问: https://getbootstrap.com/docs/5.3/examples/dashboard/。正如您在 图 5.3**.3中可以看到的,可以通过右键单击 Dashboard 模板并选择 查看页面 源代码 选项来访问 HTML 代码。

Figure 5.3 – Viewing the page source in Chrome

图 5.3 – 在 Chrome 中查看页面源代码

通过这种方式 ,你可以从该模板中提取特定部分并将其集成到自己的应用程序中,从而实现易于定制和扩展。 这个过程为你的 Django 应用程序 奠定了坚实的基础。

首先,你可以在应用程序和项目文件夹之外的一个单独位置创建一个 <st c="19083">templates</st> 文件夹,遵循以下概述的推荐结构。 这种有组织的设置确保了你的 模板文件 的有效管理:

 quiz_project/
├── quiz_app
├── quiz_project/
└──  templates

<st c="19380">templates</st> 目录中,你将创建一个名为 <st c="19439">base.html</st>的新 HTML 文件,作为应用程序结构的基石。 在这个文件中,你可以开始包括相关的链接并定义设置应用程序整体上下文的头部部分:

 {% load static %}
<html lang="en" data-bs-theme="auto">
<head>
  <script src="img/color-modes.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Quiz App</title>
  <!-- Bootstrap CSS -->
  <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet" />
<!--  ; Custom styles for this template &ndash;&gt;-->
  <link href="{% static 'css/dashboard.css' %}" rel="stylesheet" />
</head>

第一 <st c="20125">{% load static %}</st>,是一个 Django 模板标签,允许我们加载静态文件,例如 CSS 样式表和 JavaScript 脚本,到我们的 HTML 模板中。 它使我们能够在 Django 项目中访问和使用这些文件。 在本节后面的内容中,我们将创建 <st c="20396">.css</st> 文件,并且它们将被自动传递到 HTML 中。

然后, <st c="20469">data-bs-theme</st> 属性用于自动主题处理。 此属性通常与 Bootstrap(一个流行的 CSS 框架)一起使用,根据用户的 设备设置自动在浅色和深色主题之间切换。

<st c="20696">head</st> 部分包含各种元标签和外部脚本和样式表引用。 这些元标签提供了有关网页字符编码和视口设置的详细信息。 它们确保网页正确渲染,并调整其布局以适应不同的 屏幕尺寸。

接下来,我们包含外部 CSS 样式表。 <st c="21042">{% static 'css/bootstrap.min.css' %}</st> <st c="21083">{% static 'css/dashboard.css' %}</st> 标签指的是我们将在 Django 项目中创建的静态 CSS 文件。 这些 CSS 文件提供了样式规则和格式化指令,定义了网页上元素的视觉外观。

一旦完成头部 ,我们可以使用以下代码片段来构建页面的主体:

 <body>
  <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
    <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="#">Quiz App</a>
    <div class="navbar-nav">
    </div>
  </header>
  <div class="container-fluid">
    <div class="row">
      <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-body-tertiary sidebar collapse">
      <div class="position-sticky pt-3 sidebar-sticky">
        <ul class="nav flex-column">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="">
              <span data-feather="home" class="align-text-bottom"></span>
              Questions Generator
            </a>
          </li>
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="/history">
              <span data-feather="file" class="align-text-bottom"></span>
              My Quiz
            </a>
          </li>
        </ul>
      </div>
    </nav>
    </div>
  </div>
  </body>
</html>

在这里,主体 由一个 <st c="22265"><header></st> 部分组成,其中包含一个导航栏。 导航栏包含测验应用的商标名称。 元素可以用来添加额外的导航项 (如果需要的话)。

在这个导航中,有一个 <st c="22503"><nav id="sidebarMenu"></st> 元素,它充当侧边菜单。 它包含可以按需定制的导航项列表。 每个导航项都由 <st c="22677"><li class="nav-item"></st> 及其关联的链接表示。 侧边栏内部我们将有两个主要链接:

  • “问题生成器”标签页:此标签页显示了 ChatGPT 测验生成工具

  • “我的测验”标签页:此标签页显示了用户迄今为止创建的所有测验,准备好 下载

现在我们已经完成了 <st c="22979">base.html</st>,我们可以添加样式文件。 为此,在你的 <st c="23087">quiz_project</st>中创建两个新的目录,分别命名为 <st c="23064">static/css</st> ,如下所示:

 quiz_project/
├── quiz_app
├── quiz_project/
│   ├── static/
│   └── css/
│      ├── dashboard.css
│      └── bootstrap.min.css
└──  templates

我们不必自己编写样式文件,可以直接从 <st c="23433">css</st> 文件夹中下载 CSS 文件。 您可以在以下位置找到我们项目所需的每个 CSS 文件的链接:

或者,您可以从我们的 GitHub 仓库 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API访问所有项目文件。

现在,让我们看看如何将这些 HTML 和 CSS 文件集成到我们的 Django 项目中。通过修改<st c="23945">settings.py</st> <st c="23956">文件</st>,我们可以指定 Django 应该查找静态文件(包括 HTML 模板和 CSS 文件)的目录。这种配置将确保我们的 Django 应用程序可以访问和利用所需的模板和 CSS 样式,在整个应用程序中提供视觉上吸引人且统一的用户体验。

首先,要将 HTML 文件添加到你的项目中,你可以在<st c="24400">settings.py</st> <st c="24411">文件</st>中简单地引用<st c="24369">templates</st> <st c="24378">目录</st>。为此,找到<st c="24439">TEMPLATES</st> <st c="24448">字典</st>并编辑<st c="24473">DIRS</st> <st c="24477">键</st>,如下所示:

 TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates', <st c="24573">'DIRS': [os.path.join(BASE_DIR, 'templates')],</st> 'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

这用于构建 Django 项目内<st c="24929">templates</st> <st c="24938">目录</st>的绝对路径。《st c="24977">BASE_DIR 指的是你的 Django 项目的基础目录,而<st c="25043">templates</st> <st c="25052">是存储你的模板文件的目录名称。</st>

通过设置<st c="25135">DIRS</st> <st c="25139">键</st>,你告诉 Django 将<st c="25176">templates</st> <st c="25185">目录</st>作为搜索模板文件的位置之一。这允许你将模板文件与你的应用程序目录分开组织,并提供一个中心位置来存储你的<st c="25389">HTML 模板</st>

我们还需要在<st c="25472">setting.py</st> <st c="25482">文件</st>的开头导入<st c="25437">os</st> <st c="25482">库</st>

<st c="25488">import os</st> from pathlib import Path

其次,要将所有 CSS 文件传递到你的 Django 项目中,你可以滚动到<st c="25612">settings.py</st> <st c="25623">文件</st>的底部并添加以下内容:

 # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/' <st c="25771">STATICFILES_DIRS = [os.path.join(BASE_DIR, 'quiz_project/static')]</st>
<st c="25837">STATIC_ROOT = os.path.join(BASE_DIR, 'static')</st> # Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

在这里,<st c="26050">STATICFILES_DIRS</st> <st c="26066">告诉 Django 在开发期间在哪里查找静态文件,而STATIC_ROOT 指定了静态文件将被收集以供部署的目录。` 这些设置确保了你的静态文件在开发和生产环境中都组织良好且可访问。这将使我们能够选择项目中的那些 CSS 文件。

本节解释了通过构建 <st c="26494">base.html</st> 模板,整合 CSS 资源如 Bootstrap,以及配置 <st c="26581">settings.py</st> 文件 来管理 Django 项目中的静态文件和模板的过程。 完成这些步骤后,您现在可以进入下一节运行您的 Django 应用程序。

运行您的 Django 应用程序

一旦您完成了上一节中涵盖的步骤,您就可以运行您的 Django 项目。 要运行 Django 应用程序,您需要再次访问您的终端或导航到您的 Django 项目的根目录, <st c="27003">quiz_project</st>,。 这是包含 <st c="27081">manage.py</st> 文件 的目录。 一旦您处于正确的目录,请执行以下命令:

 $python manage.py runserver

此命令启动开发服务器,允许您在本地运行 Django 应用程序进行测试和 开发。

重要提示

一个需要注意的重要提示是,Django 的开发服务器有一个有用的功能 称为 自动重新加载。这意味着您可以在修改代码的同时让服务器运行,服务器将自动检测这些更改并应用它们,而无需手动重启。

一旦 Django 开发服务器启动,您可以通过打开网页浏览器并输入以下 URL 来访问您的应用程序: <st c="27789">http://127.0.0.1:8000/</st> (见 图 5.4**.4)。 默认情况下,Django 在本地主机 <st c="27879">127.0.0.1</st> 上运行并使用端口 <st c="27903">8000</st>。前面的 URL 将使您的浏览器指向 Django 应用程序的首页。

Figure 5.4 – The quiz app initial page view

图 5.4 – Quiz 应用初始页面视图

在我们的 Django 应用程序中,我们可以观察到三个不同的部分:

  • 首先,在最上面,我们有一个标题区域,显示名称 Quiz App 在深色背景上。

  • 在左侧,我们找到了一个导航栏,其中包含两个标签,我们将其整合到了 <st c="28332">base.html</st> 文件中 – 问题生成器 我的测验。这些标签便于在应用程序的不同功能之间进行导航。 问题生成器 标签将用户引导到一个可以构建测验的区域,而 我的测验 标签则提供了一个下载测验的视图。

  • 最后,在导航栏的右侧,我们有工作区,用户可以与之交互并探索 我的测验 问题生成器 **功能。

这是您应用程序的初始视图,它展示了一个时尚现代的界面,具有用户友好的设计。 在下一节中,我们的注意力现在可以转向 开发应用程序的基本方面,这涉及到创建核心的 ChatGPT 测验 生成组件。

集成 ChatGPT 和 Django 用于测验生成

在本节中,我们将探讨使用 ChatGPT API 在 Django 应用程序中生成问题的激动人心的 任务。 这项强大的功能将允许你根据用户提供的文本输入创建交互式测验。 通过处理用户发出的 <st c="29414">POST</st> 请求并利用 ChatGPT API 的功能,你将能够动态生成有洞察力的提问,从而增强用户参与度和 知识获取。

该过程首先在你的 Django 应用程序中引入一个字段,用户可以在其中输入文本。 一旦用户通过点击提交按钮提交文本,应用程序就会利用 ChatGPT API 根据提供的文本生成相关且上下文准确的提问,魔法随之展开。 这些问题无缝地显示给用户,从而提供了一种互动和教育的体验。 通过自动化提问生成过程,你可以节省时间和精力,同时为用户提供有价值的内容。 因此,让我们深入探讨处理 <st c="30212">POST</st> 请求、构建用于提问创建的 ChatGPT API 函数以及最终以用户友好和直观的方式向用户展示生成的提问所涉及的步骤。

<st c="30390">构建测验生成文本区域和提交按钮</st>

在对时间顺序略有偏离的情况下,我们将首先对<st c="30549">base.html</st> <st c="30558">文件进行修改,以包含我们问题生成功能所需的组件。</st> <st c="30641">具体来说,我们将添加一个文本区域,用户可以在其中输入他们希望输入的文本,以及一个提交按钮,该按钮将触发问题生成过程。</st>

<st c="30788">您可以在导航栏菜单代码(在 <st c="30859"></nav></st> <st c="30865">标签下)下添加这些字段,如下所示:</st> <st c="30888"></st>

<st c="30903">base.html</st>

 </nav> <st c="30921"><main class="col-md-9 ms-sm-auto col-lg-10 px-md-4"></st><st c="30973">{% block content %}</st><st c="30993"><h1>Create a Quiz</h1></st><st c="31016"><form method="post" action=""></st><st c="31047">{% csrf_token %}</st><st c="31064"><textarea name="text" rows="5" cols="50" placeholder="Enter some text..."></textarea></st><st c="31150"><br></st><st c="31155"><input type="submit" value="Generate Questions"></st><st c="31204"></form></st><st c="31212">{% if questions %}</st><st c="31231"><h2>Generated Questions:</h2></st><st c="31261">{{ questions|linebreaks }}</st><st c="31288">{% endif %}</st><st c="31300">{% endblock %}</st><st c="31315"></main></st> </div>
  </div>
  </body>
</html>

<st c="31353">这代表了</st> <st c="31373"> <st c="31389">base.html</st> <st c="31398">文件中的部分,负责显示我们测验生成应用程序中与问题生成功能相关的用户界面元素。</st> <st c="31522"></st>

<st c="31545">在代码中,我们可以观察到 HTML 标签和 Django 模板语法的使用。</st> <st c="31625"> <st c="31629"><main></st> <st c="31635">标签定义了主要内容区域。</st> <st c="31671">在 <st c="31682"><main></st> <st c="31688">标签内部,我们有一个由 <st c="31737">{% block content %}</st> <st c="31756">和 <st c="31761">{% endblock %}</st> <st c="31775"> 定义的 Django 模板块,这允许动态内容插入。 这将确保我们可以稍后连接此块与我们的 Django 视图。`

<st c="31897">在这个块中,我们首先显示一个标题, <st c="32147">{% csrf_token %}</st> <st c="32163">模板标签确保表单提交的安全性。</st>

<st c="32221">在表单内部,我们发现 <st c="32247">textarea</st> <st c="32255">,它作为输入字段,用户可以输入他们希望生成问题的文本。</st> <st c="32368">它指定了行和列属性来定义文本输入区域的大小。</st> <st c="32454">此外,还有占位文本, <st c="32495">Enter some text...</st> <st c="32513">,为用户提供说明。</st> <st c="32542"></st>

<st c="32551">在 <st c="32562">textarea</st> <st c="32570">之后,我们有一个标题为 <st c="32611">生成问题</st> <st c="32629">的提交按钮,用户可以点击它来启动问题生成过程。</st> <st c="32698">当表单提交时,用户的输入将被发送到适当的视图进行进一步处理。</st> <st c="32784"></st>

在表单之后,有一个 <st c="32832">{% if questions %}</st> 语句,用于检查是否有生成的问答题。 如果有,则会出现一个标题, <st c="33057">{{ questions|linebreaks }}</st>。这种语法确保生成的问答题中的换行符在文本字段下正确显示。

最后,我们可以将 一个新的 样式表(稍后我们将构建它)添加到 <st c="33271">base.html</st> 文件中的 <st c="33293">head</st>部分:

 <!--  &lt;!&ndash; Custom styles for this template &ndash;&gt;-->
  <link href="{% static 'css/dashboard.css' %}" rel="stylesheet" /> <st c="33435"><link rel="stylesheet" type="text/css" href="{% static 'css/quiz_style.css' %}"></st> </head>

当你此时启动你的测验生成器时,你会看到虽然所有字段都是可见的,但它们的视觉呈现可能并不美观。 这是因为我们迄今为止只包含了 HTML 元素。 为了增强它们的视觉效果,我们需要引入一些 CSS 样式。 为此,你可以在 <st c="33871">quiz_style.css</st> 文件中创建一个新的 CSS 文件,该文件位于 <st c="33897">quiz_project/static/css</st> 目录下。 你可以在这里找到 CSS 文件的内容 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter05%20QuizApp/quiz_project/quiz_project/static/css/quiz_style.css

在这里,我们定义了 <st c="34167">body</st> <st c="34173">container</st> <st c="34188">main</st> 元素的风格。 <st c="34207">body</st> 元素被设置为使用 Arial 字体家族,并具有白色背景。 <st c="34288">container</st> 类指定最大宽度为 <st c="34333">960px</st>,而包含我们的应用程序的<st c="34350">main</st> 元素,也具有阴影效果和 <st c="34442">5px</st>的边框半径。

然后,我们可以定义 <st c="34489">textarea</st> <st c="34502">submit</st> 按钮元素的样式。 <st c="34530">textarea</st> 元素被设置为具有其父容器宽度的 <st c="34573">70%</st> ,颜色为浅灰色。 代表提交按钮的<st c="34630">input[type="submit"]</st> 元素具有蓝色背景色,当鼠标悬停 在其上时,光标变为指针。

<st c="34786">响应式样式</st> 部分使用媒体查询在视口的最大宽度为 <st c="34898">767px</st> 或更小时应用特定样式。 在这种情况下,它减少了.container <st c="34972">main</st> 元素的填充,将标题的字体大小减少到 <st c="35026">20px</st>,并调整了<st c="35063">textarea</st> <st c="35076">input[type="submit"]</st> 元素的填充。 这些样式确保了测验生成应用程序在视觉上吸引人,并能很好地适应不同的屏幕尺寸,提供更好的 用户体验。

到目前为止,我们已经 成功 构建了我们应用程序测验生成功能的整个用户界面。 我们的下一步是集成 ChatGPT API 服务并实现必要的视图。 正确答案应该在哪里以及如何显示

使用 Django 创建 ChatGPT API 视图

现在我们已经 完成了前端开发,我们将 探索如何将这个强大的 ChatGPT API 集成到我们的 Django 视图中,使我们能够利用 ChatGPT 的能力来生成 测验问题。

要求 ChatGPT 以特定结构生成响应可能是一项具有挑战性的任务,因为我们需要定义非常具体的指令,说明我们的测验中的问题应该如何生成。 考虑到这一点,我们的 ChatGPT 提示应该满足以下要求: 以下要求:

  • 一个变量应该传递我们想要创建问题的文本。 这将使我们的应用程序能够处理不同类型的 文本。

  • 提示应该包含以下指令,以指定 以下:

    • 问题的数量

    • 提示应该包含以下指令: 以下:

    • ChatGPT 应生成哪种类型的问题(多项选择、开放式回答等)

每次您想要设计一个 ChatGPT 提示并测试 API 响应是否符合您的提示定义时,创建这样的要求是一个好习惯。 基于您的 提示定义,检查 API 响应是否符合预期。

在您的 Django 项目中的<st c="36592">quiz_app</st> <st c="36600">文件夹内,您需要创建两个基本文件——</st> config.py <st c="36692">services.py</st> config.py 文件作为存储您的 ChatGPT API 密钥的容器,允许您在应用程序中安全地存储和访问它。 此密钥对于建立与 ChatGPT API 服务的连接至关重要。 另一方面,<st c="36922">services.py</st> `文件在容纳必要的函数中扮演着关键角色,这些函数将使您能够在 Django 视图中与 ChatGPT API 交互。 这些函数将促进与 API 的通信,允许您根据 用户输入 动态生成测验问题:

services.py

 from openai import OpenAI
from . import config
# API Token
client = OpenAI(
  api_key=config.API_KEY,
)
def generate_questions(text):
    # Define your prompt for generating questions
    prompt = f"Create a practice test with multiple choice questions on the following text:\n{text}\n\n" \
             f"Each question should be on a different line. Each question should have 4 possible answers. " \
             f"Under the possible answers we should have the correct answer." # Generate questions using the ChatGPT API
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": f"{prompt}"}],
        max_tokens = 3500,
        stop = None,
        temperature = 0.7
    )
    # Extract the generated questions from the API response
    questions = response.choices[0].message.content
    return questions

config.py

 API_KEY = "YOUR_API_KEY"

在这里,我们有一个 Python 函数,它使用 OpenAI 库与 ChatGPT API 交互,以生成测验问题。 首先,导入必要的依赖项,包括 OpenAI 库和本地的 <st c="38270">config</st> <st c="38276">模块</st>,该模块包含 API 密钥。</st> <st c="38310">使用导入的</st> config.API_KEY 值设置 API 密钥,以建立与 <st c="38404">ChatGPT API</st> 的连接。

The <st c="38421">generate_questions</st> 函数接受一个文本输入作为参数,该参数表示将从中生成问题的内容或上下文。 该函数通过将提供的文本整合到特定格式中,为 AI 模型创建基于给定内容的多个选择题做好准备。 该格式指导 AI 模型根据给定内容创建多项选择题。

正如您所看到的,给定 ChatGPT 提示的设计重点在于提供清晰的指令,以根据给定文本生成包含多项选择题的练习测试。 以下是设计背后的原因:

  • 清晰的指令:提示语首先明确说明任务的目的是创建一个包含多项选择题的练习测试。 这有助于设定生成内容的上下文和期望。

  • <st c="39228">{text}</st> 占位符表示应在该位置插入给定的文本。 这允许用户提供基于该文本的问题。

  • 结构化格式:提示指定每个问题应单独一行。 这有助于创建练习测试的结构化布局,使其更容易被人类和其他 Python 脚本 理解。

  • 多项选择题格式:提示中说明,每个问题应有四个可能的答案。 这表明生成的题目应遵循在测试和测验中常用的多项选择题格式

  • 指示正确答案:提示中提到,在可能的答案下,应提供正确答案。 这确保了生成的题目包括正确答案和选项,使学习者能够轻松地识别 正确答案。

使用 ChatGPT API,该函数 将带有准备好的提示的请求发送到 API。 API 响应包含生成的题目。 该函数从 API 响应中提取这些问题,并将它们作为 字符串变量 返回。

<st c="40374">问题</st> 变量现在可以在 <st c="40420">views.py</st> 文件中使用,以便将生成的题目传递到我们 <st c="40489">base.html</st> 前端文件中:

 from django.shortcuts import render <st c="40550">from .services import generate_questions</st> def home(request): <st c="40610">if request.method == 'POST':</st><st c="40638">text = request.POST['text']</st><st c="40666">questions = generate_questions(text)</st><st c="40703">context = {'questions': questions}</st><st c="40738">return render(request, 'base.html', context)</st> return render(request, 'base.html')

在这里,我们升级了 <st c="40841">home</st> 函数,该函数处理主页的渲染和基于用户输入生成测验问题。 收到请求后, <st c="40989">view</st> 函数检查请求的 HTTP 方法。 如果是 <st c="41053">POST</st> 请求,表示用户已提交表单,该函数将继续从请求的 <st c="41181">POST</st> 数据中提取文本输入,使用 <st c="41201">text</st> 键。 实际上,提交是通过选择我们的问题 <st c="41308">text</st> 文件来启动的。

然后,提取的文本被传递给 generate_questions 函数,该函数我们之前在 <st c="41471">services.py</st> 文件中定义。 此函数利用 ChatGPT API 根据提供的文本生成测验问题。 生成的测验问题存储在 <st c="41625">questions</st> 变量中。

为了在网页上显示生成的测验问题,创建了一个名为 <st c="41717">context</st> 的字典,其中包含 <st c="41745">questions</st> 键和包含生成的测验问题的相应值。 <st c="41828">context</st> 字典作为参数传递给 <st c="41879">render</st> 函数,以及 <st c="41911">request</st> 对象和模板文件 <st c="41949">base.html</st>。渲染的页面将能够访问 <st c="42002">questions</st> 变量并适当地显示它。

通过在你的 Django 应用程序的 <st c="42110">views.py</st> 文件中实现此代码, <st c="42129">home</st> 视图函数将根据用户输入处理测验问题的生成,并在收到 <st c="42284">POST</st> 请求时显示生成的测验问题。

在测试你的 Django 应用程序并使用 ChatGPT API 之前,你需要确保已安装 <st c="42408">openai</st> 库。 OpenAI 库提供了与 ChatGPT API 交互所需的工具和功能。 要安装库,你可以在终端窗口中键入以下命令:

 pip install openai

为了测试你的测验生成器应用程序,请按照以下步骤操作: 这些步骤:

  1. 请确保你的 Django 开发服务器正在运行。 如果尚未运行,请在终端或命令提示符中导航到你的 Django 项目根目录,并执行以下命令: 以下命令:

    <st c="42975">http://127.0.0.1:8000/</st>. This will direct you to the home page of your quiz generator application.
    
  2. 在主页上,你会看到一个文本区域,你可以输入一些文本。 粘贴或输入你想要生成测验问题的文本(见 图 5**.5)。

图 5.5 – 向测验生成应用程序添加文本

图 5.5 – 向测验生成应用程序添加文本

  1. 一旦你 输入了文本,点击 <st c="43794">POST</st> 请求到 服务器。

  2. 服务器将处理请求并根据提供的文本使用 ChatGPT API 生成测验问题。 生成的测验问题将在文本区域下方显示(见 图 5**.6)。

图 5.6 – 测验生成应用程序显示的问题

图 5.6 – 测验生成应用程序显示的问题

遵循这些 步骤后,你现在可以测试你的测验生成应用程序 并查看它是如何根据文本输入生成问题的。 请随意尝试不同的输入来探索你应用程序的功能。

在本节中,我们探讨了 ChatGPT 和 Django 在测验生成中的集成。 我们涵盖了创建用于生成问题的用户界面,包括 CSS 样式以增强视觉效果,使用 Django 实现 ChatGPT API 视图,并通过输入文本并基于它生成问题来测试测验生成应用程序 现在,我们可以构建一个数据库来存储生成的测验,并允许用户下载它们,这将在下一节中介绍。

存储和下载生成的测验

在本节中,你 将学习如何为你的测验生成应用程序构建测验下载功能。 通过集成数据库并为下载测验创建一个专门的页面,你将赋予用户访问和使用他们生成的测验的能力。 此功能将通过提供一种无缝保存和检索测验的方式,增强整体用户体验,使用户能够轻松地回顾和分享他们生成的 内容。

我们将探讨使用 Django 的模型和数据库管理功能将生成的测验保存到数据库中的过程。 通过定义适当的数据库结构和实现必要的视图和模板,你将能够创建一个用户友好的页面,用户可以在其中浏览和下载他们生成的测验。 有了这个功能,你的测验生成应用程序将提供一种全面的解决方案来生成、存储和访问测验,进一步丰富用户的互动和教育体验。

将测验保存到 SQLite 数据库

构建测验下载功能的关键方面之一是能够将生成的测验保存到数据库中。 SQLite 为此提供了一个简单 且高效的解决方案。 SQLite 是一个轻量级、无服务器、自包含的数据库引擎,它需要最少的设置和配置。 它非常适合小型应用,并且与 Python 无缝集成 \

首先,您需要修改 <st c="46882">generate_questions()</st> 函数以包含数据库功能。 在此函数中,您可以包含代码将生成的测验问题和选项保存到 SQLite 数据库中。 通过使用 Django 的模型定义适当的表结构,您可以轻松地将测验数据映射到数据库中的相应字段。 \

除了修改 <st c="47240">generate_questions()</st> 函数外,您还需要创建一个单独的函数来初始化数据库。 此函数将处理创建必要表和建立数据库连接等任务。 要创建它,请打开您的 <st c="47482">services.py</st> 文件,您可以在您的 <st c="47559">API_KEY</st> 定义下编写初始化函数: \

<st c="47578">import sqlite3</st> from openai import OpenAI
from . import config
# API Token
client = OpenAI(
  api_key=config.API_KEY,
) <st c="48001">initialize_database()</st> function is responsible for setting up the SQLite database to store the generated quizzes. It begins by establishing a connection to the SQLite database named <st c="48182">questions.db</st>. Then, the cursor serves as a handle for executing SQL statements and fetching results from the database. It allows us to execute SQL commands and retrieve data from the database.
			<st c="48374">The function then checks whether a table named</st> `<st c="48422">questions</st>` <st c="48431">exists in the database.</st> <st c="48456">This statement creates a table with three columns –</st> `<st c="48508">id</st>`<st c="48510">,</st> `<st c="48512">key</st>`<st c="48515">, and</st> `<st c="48521">value</st>`<st c="48526">. The</st> `<st c="48532">key</st>` <st c="48535">column will later take the first two words from the text you pass to ChatGPT and use them as the quiz name, while the</st> `<st c="48654">value</st>` <st c="48659">column will hold the</st> <st c="48681">complete quiz.</st>
			<st c="48695">After executing the table creation statement, the changes are committed to the database using</st> `<st c="48790">conn.commit()</st>`<st c="48803">. This ensures that the table creation is finalized and persisted in the database before the connection to the database is closed, using</st> `<st c="48940">conn.close()</st>` <st c="48952">to free up system resources and maintain good</st> <st c="48999">coding practices.</st>
			<st c="49016">Additionally, make sure to import the SQLite package to enable the utilization of the</st> <st c="49103">database functionalities.</st>
			<st c="49128">Now, we</st> <st c="49137">can modify our</st> `<st c="49152">generate_questions()</st>` <st c="49172">function to incorporate</st> <st c="49197">the database:</st>

def generate_questions(text): initialize_database()# 连接到 SQLite 数据库conn = sqlite3.connect('questions.db')cursor = conn.cursor() # 定义用于生成问题的提示

prompt = f"根据以下文本创建一个包含多项选择题的练习测试:\n{text}\n\n" \

        "每个问题应该单独占一行。每个问题应该有 4 个可能的答案。" \

        "在可能的答案下方,我们应该有正确答案。" # 使用 ChatGPT API 生成问题 \

response = client.chat.completions.create( \

    model="gpt-3.5-turbo", \

    messages=[{"role": "user", "content": f"{prompt}"}], \

    max_tokens = 3500, \

    stop = None, \

    temperature = 0.7 \

) \

# 从 API 响应中提取生成的问答 \

questions = response.choices[0].message.content <st c="49987"># Generate a unique key for the question</st><st c="50027">base_key = ' '.join(text.split()[:2])</st><st c="50065">key = base_key</st><st c="50080">index = 1</st><st c="50090">while key_exists(cursor, key):</st><st c="50121">key = f"{base_key} {index}"</st><st c="50149">index += 1</st><st c="50160"># Insert the questions into the database</st><st c="50201">value = questions</st><st c="50219">cursor.execute("INSERT INTO questions (key, value) VALUES (?, ?)", (key, value))</st><st c="50300">conn.commit()</st> return questions <st c="50332">def key_exists(cursor, key):</st><st c="50360">cursor.execute("SELECT COUNT(*) FROM questions WHERE key = ?", (key,))</st><st c="50431">count = cursor.fetchone()[0]</st><st c="50460">return count > 0</st>

			<st c="50477">Here is how the</st> <st c="50494">database</st> <st c="50503">implementation works:</st>

				1.  <st c="50524">Firstly, the function establishes a connection to the SQLite database named</st> `<st c="50601">questions.db</st>` <st c="50613">using the</st> `<st c="50624">sqlite3.connect()</st>` <st c="50641">method, similar to the</st> <st c="50665">previous function.</st>

    <st c="50683">To ensure the uniqueness of each question, the function generates a unique key by combining the first two words of the input text.</st> <st c="50815">If a question with the same key already exists in the database, it appends a numerical index to the key until a unique key is obtained.</st> <st c="50951">We verify the key by using the</st> `<st c="50982">key_exists()</st>` <st c="50994">method.</st>

				2.  <st c="51002">The</st> <st c="51007">function then inserts the generated questions into the SQLite database using the</st> `<st c="51088">cursor.execute()</st>` <st c="51104">method.</st> <st c="51113">The key and value (</st>`<st c="51132">questions</st>`<st c="51142">) are passed as parameters to the SQL query.</st> <st c="51188">Once the insertion is complete, the function calls</st> `<st c="51239">conn.commit()</st>` <st c="51252">to save the changes made to</st> <st c="51281">the database.</st>
				3.  <st c="51294">The</st> `<st c="51299">key_exists()</st>` <st c="51311">function takes a cursor object and a key as parameters, executes a SQL query to count the number of rows with the given key in the</st> `<st c="51443">questions</st>` <st c="51452">table, and returns</st> `<st c="51472">True</st>` <st c="51476">if a key exists in the table, or</st> `<st c="51510">False</st>` <st c="51515">otherwise.</st> <st c="51527">This function provides a convenient way to check for the existence of a key in the database before inserting new data or performing</st> <st c="51659">other operations.</st>
				4.  <st c="51676">To fetch the database, we can create the</st> `<st c="51718">print_all_questions()</st>` <st c="51739">function.</st> <st c="51750">It retrieves all the rows from the</st> `<st c="51785">questions</st>` <st c="51794">table in the SQLite database and returns them as</st> <st c="51844">a result:</st>

    ```

    def print_all_questions():

        initialize_database()

        conn = sqlite3.connect('questions.db')

        cursor = conn.cursor()

        # Retrieve all rows from the database

        cursor.execute("SELECT * FROM questions")

        rows = cursor.fetchall()

        return rows

    ```py

			<st c="52081">First, the function executes a</st> `<st c="52113">SQL SELECT</st>` <st c="52123">statement using the</st> `<st c="52144">SELECT * FROM questions</st>` <st c="52167">query.</st> <st c="52175">This query selects all the columns from the</st> `<st c="52219">questions</st>` <st c="52228">table.</st>
			<st c="52235">After executing the</st> `<st c="52256">SELECT</st>` <st c="52262">statement, the</st> <st c="52277">function retrieves all the rows returned by the query.</st> <st c="52333">The</st> `<st c="52337">fetchall()</st>` <st c="52347">method returns the result as a list of tuples, where each tuple represents a row from the table.</st> <st c="52445">Later, we will use this function as a part of the download functionality to download our quizzes from</st> <st c="52547">the database.</st>
			<st c="52560">Building the download quiz view</st>
			<st c="52592">Now, it’s time to explore the process of</st> <st c="52634">integrating download quiz views into your Django application.</st> <st c="52696">Download quiz views are essential to enable users to access and obtain the quizzes generated by the quiz generation app.</st> <st c="52817">First, navigate to the</st> `<st c="52840">views.py</st>` <st c="52848">file and add the following code under the</st> `<st c="52891">home</st>` <st c="52895">function:</st>

def history(request):

return render(request, 'donwload.html')

data = print_all_questions()

class TestListView(TemplateView):

template_name = 'download.html'

def get_context_data(self, **kwargs):

    context = super().get_context_data(**kwargs)

    context['data'] = data

    return context

def download(request, test_id):

test = next((t for t in data if t[0] == test_id), None)

if test:

    header = test[1]

    questions = test[2]

    filename = f'test_{test_id}.txt'

    with open(filename, 'w') as f:

        f.write(questions)

    file_path = os.path.join(os.getcwd(), filename)

    response = HttpResponse(open(file_path, 'rb'), content_type='text/plain')

    response['Content-Disposition'] = f'attachment; filename="{header}.txt"'

    return response

else:

    return HttpResponse("Test not found.")

			<st c="53656">The provided</st> <st c="53670">code demonstrates the additional functions included in the</st> `<st c="53729">views.py</st>` <st c="53737">file of our Django quiz generator.</st> <st c="53773">Let’s go through each function and</st> <st c="53808">its purpose:</st>

				1.  <st c="53820">The</st> `<st c="53825">history</st>` <st c="53832">function is a view function that renders the</st> `<st c="53878">download.html</st>` <st c="53891">template, which we will build in the next section.</st> <st c="53943">When a user visits the specified URL associated with this function, the template will be displayed, allowing them to view the history of quizzes available</st> <st c="54098">to download.</st>
				2.  <st c="54110">The</st> `<st c="54115">data</st>` <st c="54119">variable is assigned the value returned by the</st> `<st c="54167">print_all_questions()</st>` <st c="54188">function.</st> <st c="54199">This function retrieves all the rows from the database containing the generated quizzes.</st> <st c="54288">By storing the data in the</st> `<st c="54315">data</st>` <st c="54319">variable, it can be used later to populate the context for the</st> `<st c="54383">TestListView</st>` <st c="54395">view.</st>
				3.  <st c="54401">The</st> `<st c="54406">TestListView</st>` <st c="54418">class is a subclass of</st> `<st c="54442">TemplateView</st>`<st c="54454">, which provides a generic class-based view.</st> <st c="54499">It defines the template that will be used to display the downloaded quizzes – in this case, the</st> `<st c="54595">download.html</st>` <st c="54608">template.</st> <st c="54619">The</st> `<st c="54623">get_context_data()</st>` <st c="54641">method is overridden to add the</st> `<st c="54674">data</st>` <st c="54678">variable to the context, making it available in the template</st> <st c="54740">for rendering.</st>
				4.  <st c="54754">The</st> `<st c="54759">download()</st>` <st c="54769">function handles the download functionality for a specific quiz, identified by its</st> `<st c="54853">test_id</st>`<st c="54860">. It first searches for the quiz in the</st> `<st c="54900">data</st>` <st c="54904">variable using</st> `<st c="54920">test_id</st>`<st c="54927">. If the quiz is found, the header, questions, and filename are extracted.</st> <st c="55002">The questions are then written to a text file with the appropriate filename.</st> <st c="55079">The file path is determined, and an</st> `<st c="55115">HttpResponse</st>` <st c="55127">object is created with the file content and content type.</st> <st c="55186">The Content-Disposition header is set to</st> <st c="55227">specify the filename for the downloaded file.</st> <st c="55273">Finally, the response is returned to initiate the file download.</st> <st c="55338">If the quiz is not found, an</st> `<st c="55367">HttpResponse</st>` <st c="55379">object is returned, with a message indicating that the test was</st> <st c="55444">not found.</st>

			<st c="55454">At the beginning of the</st> `<st c="55479">views.py</st>` <st c="55487">file, you can add all the necessary imports for those functions to</st> <st c="55555">operate properly:</st>

import os

from django.http import HttpResponse

from django.shortcuts import render

from django.views.generic import TemplateView

from .services import generate_questions, print_all_questions


			<st c="55763">As you can see, the</st> `<st c="55784">HttpResponse</st>` <st c="55796">and</st> `<st c="55801">render</st>` <st c="55807">functions are imported from the Django framework.</st> <st c="55858">These functions are essential to generate and return HTTP responses.</st> <st c="55927">The</st> `<st c="55931">HttpResponse</st>` <st c="55943">class allows you to create custom HTTP responses, while the</st> `<st c="56004">render</st>` <st c="56010">function is used to render HTML templates and return the result as an</st> `<st c="56081">HttpResponse</st>` <st c="56093">object.</st> <st c="56102">The</st> `<st c="56106">TemplateView</st>` <st c="56118">class will be used later as a class-based view that will render the templates for the</st> <st c="56205">download view.</st>
			<st c="56219">By adding these functions to your</st> `<st c="56254">views.py</st>` <st c="56262">file, you enable the rendering of the download</st> `<st c="56357">download.html</st>` <st c="56370">template.</st> <st c="56381">In the next section, we will create the download template and add all necessary URLs to make the</st> **<st c="56478">My Quiz</st>** <st c="56485">download page accessible</st> <st c="56511">to users.</st>
			<st c="56520">Designing the download template</st>
			<st c="56552">If you have a close look at your</st> `<st c="56586">base.html</st>` <st c="56595">file, you</st> <st c="56606">will see that there are two buttons displayed inside the navigation bar –</st> `<st c="56799">home</st>` <st c="56803">view, allowing them to generate quizzes using the ChatGPT API.</st> <st c="56867">In this section, we will focus on the</st> **<st c="56905">My Quiz</st>** <st c="56912">page.</st> <st c="56919">We will ensure that once the user clicks the</st> **<st c="56964">My Quiz</st>** <st c="56971">button, they are sent to the</st> **<st c="57001">127.0.0.1/history</st>** <st c="57018">page.</st> <st c="57025">This page will show all views related to our download functionality, which we built in the</st> <st c="57116">previous section.</st>
			<st c="57133">To do that, we</st> <st c="57149">need to create a new HTML file that will be rendered once the user clicks on the</st> `<st c="57288">base.html</st>`<st c="57297">, with the only difference being that it will run a different set of functions (the download functions) in its</st> `<st c="57408">main</st>` <st c="57412">area.</st> <st c="57419">You can create your</st> `<st c="57439">downloads.html</st>` <st c="57453">inside the</st> `<st c="57465">templates/</st>` <st c="57475">directory:</st>

{% load static %}

<head> <title>Quiz App</title> </head> <body>
<div class="row">

<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-body-tertiary sidebar collapse">

<div class="position-sticky pt-3 sidebar-sticky">

    <ul class="nav flex-column">

    <li class="nav-item">

        <a class="nav-link active" aria-current="page" href="/">

        <span data-feather="home" class="align-text-bottom"></span>

        Questions Generator

        </a>

    </li>

    <li class="nav-item">

        <a class="nav-link active" aria-current="page" href="/history">

        <span data-feather="file" class="align-text-bottom"></span>

        我的测验

        </a>

    </li>

    </ul>

</div>

</nav>

			<st c="58717">After the</st> <st c="58728">navigation bar, where our working area is located, we can create a section where users can download quizzes.</st> <st c="58837">We can generate a list of quiz download links based on the data provided, displaying the quiz headers as clickable links for users to access and download</st> <st c="58991">the quizzes.</st>
			<st c="59003">Inside the</st> `<st c="59015"><main></st>` <st c="59021">element, there is an</st> `<st c="59043"><h1></st>` <st c="59047">heading tag that displays the text</st> `<st c="59083">Download Quiz</st>`<st c="59096">. This heading provides a clear title for the section, indicating its purpose to</st> <st c="59177">the users:</st>

下载测验

</body>

			<st c="59427">Below the heading, there is an</st> `<st c="59459"><ul></st>` <st c="59463">element that represents an unordered list.</st> <st c="59507">Within this list, there is a loop construct using Django’s template syntax, denoted by</st> `<st c="59594">{% for test in data %}</st>` <st c="59616">and</st> `<st c="59621">{% endfor %}</st>`<st c="59633">. This loop iterates over the</st> `<st c="59663">data</st>` <st c="59667">variable, which contains a list of quizzes or</st> <st c="59714">test data.</st>
			<st c="59724">For each iteration of the loop, a new list item,</st> `<st c="59774"><li></st>`<st c="59778">, is generated.</st> <st c="59794">Inside the list item, there is an anchor (</st>`<st c="59836"><a></st>`<st c="59840">) tag that serves as a hyperlink.</st> <st c="59875">The</st> `<st c="59879">href</st>` <st c="59883">attribute of the anchor tag is dynamically generated using Django’s template syntax and the</st> `<st c="59976">test</st>` <st c="59980">variable.</st> <st c="59991">This link points to the</st> `<st c="60015">/download/</st>` <st c="60025">URL, followed by</st> <st c="60043">the test.</st>
			<st c="60052">This section</st> <st c="60065">of</st> `<st c="60069">download.html</st>` <st c="60082">generates a main content area with a heading and a list of quiz download links.</st> <st c="60163">The loop ensures that each quiz in the</st> `<st c="60202">data</st>` <st c="60206">variable is represented as a separate list item with an appropriate hyperlink and</st> <st c="60289">display text.</st>
			<st c="60302">As a final step to set up the</st> `<st c="60392">urls.py</st>` <st c="60399">files.</st> <st c="60407">Those files are responsible for routing requests to the appropriate views.</st> <st c="60482">You need to define a URL pattern that maps to the history view, which will display the</st> `<st c="60599">urls.py</st>` <st c="60606">files, users will be able to access the</st> **<st c="60647">My Quiz</st>** <st c="60654">page and view their</st> <st c="60675">downloaded quizzes:</st>
			<st c="60694">quiz_project/urls.py</st>

from django.contrib import admin

from django.urls import include, path

urlpatterns = [

path('admin/', admin.site.urls),

path('', include('quiz_app.urls')),

path('history/', include('quiz_app.urls')),

]


			<st c="60917">quiz_app/urls.py</st>

from django.urls import path

from . import views

from .views import TestListView, download

urlpatterns = [

path('', views.home, name='home'),

path('history/', TestListView.as_view(), name='test_list'),

path('download/<int:test_id>', download, name='test_download'),

]


			<st c="61202">In the</st> `<st c="61210">quiz_project/urls.py</st>` <st c="61230">file, we define the URL patterns for the entire project.</st> <st c="61288">The</st> `<st c="61292">history/</st>` <st c="61300">path is mapped to the</st> `<st c="61323">quiz_app.urls</st>` <st c="61336">module, which contains the URL patterns specific to the quiz application.</st> <st c="61411">This configuration allows users to access the</st> **<st c="61457">My</st>** **<st c="61460">Quiz</st>** <st c="61464">page.</st>
			<st c="61470">In the</st> `<st c="61478">quiz_app/urls.py</st>` <st c="61494">file, we define the URL patterns for the quiz application specifically.</st> <st c="61567">We add the</st> `<st c="61578">history/</st>` <st c="61586">path that is mapped to the</st> `<st c="61614">TestListView</st>` <st c="61626">view class, which is responsible for displaying the</st> `<st c="61711">download/<int:test_id></st>` <st c="61733">path is mapped to the download view function, which handles the downloading of specific quizzes that the</st> <st c="61839">user selects.</st>
			<st c="61852">By</st> <st c="61856">configuring the URL patterns in these files, you enable users to navigate to different pages of your quiz app, such as the</st> **<st c="61979">Question Generator</st>** <st c="61997">page or the</st> **<st c="62010">My Quiz</st>** <st c="62017">page, from which the download page can be activated by accessing the</st> <st c="62087">corresponding URLs.</st>
			<st c="62106">Configuring the URL files marks the final stage in the creation of your application.</st> <st c="62192">To test the Django quiz app, you can run it from the terminal using the</st> <st c="62264">following command:</st>

$python manage.py runserver


			<st c="62310">Once the application is up and running, you can access it through your web browser.</st> <st c="62395">Start by navigating to the</st> **<st c="62422">Question Generator</st>** <st c="62440">page, where you can generate a few quizzes by providing the necessary inputs.</st> <st c="62519">After generating the quizzes, you can reboot the application by restarting</st> <st c="62594">the server.</st>
			<st c="62605">Next, navigate to the</st> **<st c="62628">My Quiz</st>** <st c="62635">tab, which should be available in the navigation menu.</st> <st c="62691">Clicking on this tab will take you to the page where you will see the names of all the quizzes you previously generated.</st> <st c="62812">This list will be populated based on the quizzes stored in the database.</st> <st c="62885">It provides a convenient overview of the quizzes you have created (see</st> *<st c="62956">Figure 5</st>**<st c="62964">.7</st>*<st c="62966">).</st>
			![Figure 5.7 – Downloading quizzes from the My Quiz page](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_05_7.jpg)

			<st c="62989">Figure 5.7 – Downloading quizzes from the My Quiz page</st>
			<st c="63043">To download a</st> <st c="63058">specific quiz as a text file, simply click on the desired quiz from the list.</st> <st c="63136">This action will trigger the download functionality implemented in the application.</st> <st c="63220">The quiz will be downloaded as a text file, which you can save to your local machine.</st> <st c="63306">This allows you to access and review the quiz offline, print it, or share it with others</st> <st c="63395">if needed.</st>
			<st c="63405">This is how we integrated the download quiz views into our Django application.</st> <st c="63485">We added functions to the</st> `<st c="63511">views.py</st>` <st c="63519">file, such as</st> `<st c="63534">history</st>` <st c="63541">to render the download</st> `<st c="63579">TestListView</st>` <st c="63591">to display downloaded quizzes, and</st> `<st c="63627">download</st>` <st c="63635">to handle quiz downloads.</st> <st c="63662">These functions enable users to access and obtain quizzes generated by the quiz generation app.</st> <st c="63758">We also created the</st> `<st c="63778">downloads.html</st>` <st c="63792">template, modified from</st> `<st c="63817">base.html</st>`<st c="63826">, to display the download functionality.</st> <st c="63867">The</st> `<st c="63871">urls.py</st>` <st c="63878">files were modified to define URL patterns, allowing access to the</st> **<st c="63946">My Quiz</st>** <st c="63953">page and quizzes to be downloaded.</st> <st c="63989">To test the application, we generated quizzes using the</st> **<st c="64045">Question Generator</st>** <st c="64063">page, and then we navigated to the</st> **<st c="64099">My Quiz</st>** <st c="64106">page to view and download</st> <st c="64133">our quizzes.</st>
			<st c="64145">Summary</st>
			<st c="64153">In this chapter, the focus was on building a Django project for a quiz generation application.</st> <st c="64249">We provided a step-by-step guide to set up and structure the project, including the installation of Django and important aspects such as database initialization, running a development server, and understanding the flow of views and URLs in Django.</st> <st c="64497">We also explored the concept of templates and demonstrated how to incorporate external CSS resources such as the</st> <st c="64610">Bootstrap framework.</st>
			<st c="64630">We also explained how to integrate ChatGPT and Django for quiz generation.</st> <st c="64706">We illustrated the process of adding a text input field and a submit button to the application’s interface, enabling users to generate relevant questions using the ChatGPT API.</st> <st c="64883">We also discussed how to test the quiz generator application and outlined the next steps, which involve building a database to store the generated questions.</st> <st c="65041">You learned how to store the generated quizzes in a SQLite database, using Django’s models and database management capabilities, and download the</st> <st c="65187">stored quizzes.</st>
			<st c="65202">This project was a comprehensive guide to building a Django-based quiz generation application, integrating ChatGPT for question generation, and implementing the functionality to download generated quizzes.</st> <st c="65409">You gained valuable experience in creating your own interactive applications</st> <st c="65486">with Django.</st>
			<st c="65498">In the next chapter,</st> *<st c="65520">Chapter 6</st>*<st c="65529">,</st> *<st c="65531">Language Translation Desktop App with the ChatGPT API and Microsoft Word</st>*<st c="65603">, you will learn how to create a language translation desktop app using Python and the ChatGPT API.</st> <st c="65703">We will explain how to integrate the ChatGPT API with Microsoft Word to translate Word documents into different languages.</st> <st c="65826">The chapter will cover the creation of a user interface using the</st> *<st c="65892">tkinter</st>* <st c="65899">library, allowing users to choose a target language and view real-time translations.</st> <st c="65985">It will also provide information on implementing language selection and file-browsing features, emphasizing the use of the powerful gpt-3.5-turbo language model for</st> <st c="66150">accurate translations.</st>

第三部分:用于桌面应用程序开发的 ChatGPT、DALL-E 和 Whisper API

在本部分,您的注意力将转向桌面应用程序的创建,扩展您在一系列人工智能 API 方面的专业知识。 您将通过无缝集成 ChatGPT 和 DALL-E API 来探索人工智能艺术,为您的应用程序注入吸引人的艺术能力。 此外,您将通过使用 Whisper API 探索语言翻译和转录领域。 在本部分中,您将接触到各种桌面应用程序框架,如 Tkinter、PyQt 和 Microsoft Office API,使您能够构建强大且功能丰富的应用程序。

本部分包含以下章节:

  • 第六章 使用 ChatGPT API 和 Microsoft Word 构建语言翻译桌面应用程序

  • 第七章 使用 PyQt 和 ChatGPT API 构建 Outlook 电子邮件回复生成器

  • 第八章**,使用 PyQt 和 ChatGPT API 构建论文生成工具

  • 第九章**,集成 ChatGPT 和 DALL-E API:构建端到端演示文稿生成器

  • 第十章**,使用 Whisper API 进行语音识别和语音合成

第七章:6

使用 ChatGPT API 和 Microsoft Word 的桌面语言翻译应用

在当今全球化的世界中,语言翻译已成为企业和个人有效跨越国界沟通的必要工具。 幸运的是,随着 自然语言处理 (NLP)和机器学习技术的进步,语言翻译比以往任何时候都更加准确和易于访问。 在本章中,我们将探讨如何使用 OpenAI ChatGPT API 和 Microsoft Word 构建语言翻译桌面应用程序。

在本章中,您将学习如何创建一个桌面应用程序,该程序可以使用强大的 ChatGPT API 实时翻译文本。 我们将逐步介绍将 API 与 Microsoft Word 集成的过程,使用户能够上传 Word 文档并将其翻译成多种语言。 我们还将介绍如何使用 Python tkinter 库构建简单的用户界面,使用户能够选择目标语言并查看翻译后的文本。 掌握这些技能后,您将能够开发自己的语言翻译应用,并提高您的 NLP 和机器学习能力。 学习

在本章中,我们将学习如何 执行以下操作:

  • 将 ChatGPT API 与 Microsoft Office集成

  • 使用 Tkinter构建用户界面

  • 将 Microsoft Word 文本与 ChatGPT API集成

到本章结束时,您将掌握开发一个简单但功能齐全的桌面应用程序的基本知识,通过无缝集成 ChatGPT API 与 Tkinter 和 Microsoft Word。 掌握这些技能后,您将能够利用 AI 驱动的语言翻译功能,并将其无缝集成到您选择的任何应用程序中,为您提供一种有效的工具,与来自不同语言背景的个人进行有效沟通。

技术要求

为了完成语言翻译桌面应用程序项目,以下是需要满足的 技术要求:

  • 在您的机器上安装了Python 3.7 或更高版本

  • 代码编辑器,例如 VSCode(推荐)

  • Python 虚拟环境

  • OpenAI API 密钥

  • 您的设备上可用的 Microsoft Word

在下一节中,您将了解如何有效地使用 <st c="2201">docx</st> Python 库来访问和提取 Word 文档中的信息。 这将使您能够无缝地将数据传递到 ChatGPT API 并利用其功能进行翻译。

您可以通过此 链接 在 GitHub 平台上找到本章中演示的代码片段:https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

将 ChatGPT API 与 Microsoft Office 集成

在本节中,我们将探讨如何设置我们的项目和安装 <st c="2699">docx</st> Python 库 以从 <st c="2760">docx</st> 库是一个 Python 包,它允许我们读取和写入 Microsoft Word (<st c="2842">.docx</st>) 文件,并提供一个方便的接口来访问存储在这些文件中的信息。

第一步是通过创建一个名为 <st c="3012">Translation App</st> 的新目录并使用 VSCode 加载它来启动您的作品。 这将使您拥有一个专门区域来构建和系统化您的翻译应用代码。 按照 第一章中概述的步骤,从终端窗口激活您的虚拟环境,《st c="3256">使用 ChatGPT API 开始 NLP 任务

要运行语言翻译桌面应用,您需要安装以下库:

  • <st c="3402">openai</st>:该 <st c="3416">openai</st> 库允许您与 OpenAI API 交互并执行各种 NLP 任务

  • <st c="3503">docx</st>:该 <st c="3515">docx</st> 库允许您使用 Python 读取和写入 Microsoft Word <st c="3572">.docx</st> 文件

  • <st c="3596">tkinter</st>:该 <st c="3611">tkinter</st> 库是一个内置的 Python 库,允许您为您的 图形用户界面 (GUIs) 创建 桌面应用

由于tkinter是一个内置库,因此无需安装,因为它已经存在于您的 Python 环境中。要安装openaidocx库,请访问 VSCode 终端,然后执行以下命令:

 pip install openai
pip install python-docx

要访问和读取 Word 文档的内容,您需要在项目中创建一个示例 Word 文件。以下是创建新 Word 文件的步骤:

  1. 在您的项目中,右键单击项目目录,选择files

  2. 右键单击files文件夹并选择New File

  3. 在出现的编辑字段中,输入一个带有.docx扩展名的文件名——例如,info.docx

  4. 按下Enter键来创建文件。

  5. 文件创建后,使用 Microsoft Word 打开它。

您现在可以向该文件添加一些文本或内容,稍后我们将使用 Python 中的docx库来访问和读取这些内容。例如,我们创建了一篇关于纽约市的文章。您可以在以下链接中找到完整的文章:纽约市。然而,您可以选择任何包含您想要分析的文本的 Word 文档:

<st c="4874">The United States’ most populous city, often referred to as New York City or NYC, is New York.</st> <st c="4970">In 2020, its population reached 8,804,190 people across 300.46 square miles, making it the most densely populated major city in the country and over two times more populous than the nation’s second-largest city, Los Angeles.</st> <st c="5195">The city’s population also exceeds that of 38 individual U.S.</st> <st c="5257">states.</st> <st c="5265">Situated at the southern end of New York State, New York City serves as the Northeast megalopolis and New York metropolitan area’s geographic and demographic center - the largest metropolitan area in the country by both urban area and population.</st> <st c="5512">Over 58 million people also live within 250 miles of the city.</st> <st c="5575">A significant influencer on commerce, health care and life sciences, research, technology, education, politics, tourism, dining, art, fashion, and sports, New York City is a global cultural, financial, entertainment, and media hub.</st> <st c="5807">It houses the headquarters of the United Nations, making it a significant center for international diplomacy, and is often referred to as the</st> <st c="5949">world’s capital.</st>

<st c="5965">Now that you have created the Word file inside your project, you can move on to the next step, which is to create a new Python file called</st> <st c="6105">app.py</st> inside the Translation App <st c="6138">root directory.</st> <st c="6155">This file will contain the code to read and manipulate the contents of the Word file using the</st> <st c="6250">docx</st> library. With the Word file and the Python file in place, you are ready to start writing the code to extract data from the document and use it in your application.`

<st c="6418">To test whether</st> <st c="6435">we can read Word files with</st> <st c="6463">the</st> <st c="6467">docx-python</st> <st c="6478">library, we can implement the following code in our</st> <st c="6531">app.py</st> <st c="6537">file:</st>

 import docx
doc = docx.Document("<full_path_to_docx_file>")
text = ""
for para in doc.paragraphs:
    text += para.text
print(text)

请确保将 <st c="6671">Make sure to replace</st> <st c="6693"><full_path_to_docx_file></st> with the actual path to your Word document file. <st c="6767">Obtaining the file path is a simple task, achieved by right-clicking on your</st> <st c="6844">.docx</st> file in VSCode and selecting the **<st c="6883">Copy Relative Path</st> option from the drop-down menu.`

完成选择后,运行 <st c="6967">app.py</st> 文件并验证输出。 此代码将读取您的 Word 文档内容并将其打印到控制台。 如果文本提取正确工作,您应该在控制台中看到文档的文本(见 图 6**.1)。 现在 <st c="7215">text</st> 变量包含 <st c="7253">info.docx</st> 作为 Python 字符串。

Figure 6.1 – Word text extraction console output

图 6.1 – Word 文本提取控制台输出

本节 提供了一个逐步指南,说明如何设置项目和安装用于从 Word 文档中提取文本的 <st c="7551">docx</st> Python 库。 本节还包括有关如何创建新的 Word 文件以及如何使用 <st c="7692">docx</st> 库通过 Python 读取和操作其内容的说明。 使用 Python。

在下一节中,我们将深入探讨构建 Tkinter 应用程序框架的过程。 您将学习如何创建一个带有小部件的基本窗口,以及如何使用几何管理器将它们定位在 屏幕上。

使用 Tkinter 构建用户界面

在本节中,我们将学习如何使用 <st c="8053">Tkinter</st> 库为我们文本翻译应用程序创建一个 GUI。 Tkinter 是 Python 的标准库,用于创建 GUI,它提供了一个简单高效的方式来创建窗口、按钮、文本字段和其他 图形元素。

如图 图 6**.2 所示的文本翻译应用程序将被设计成一个简单且用户友好的界面。 当您运行应用程序时,将有一个标签为 浏览 的按钮和一个包含要翻译成语言的列表的下拉菜单:

  1. 要将文本翻译,用户可以从 下拉菜单中选择他们想要翻译成的语言。

  2. 一旦选择了语言,用户可以点击 浏览 按钮并选择他们想要翻译的 Word 文件。

  3. 选择后,文件内容将使用 ChatGPT API 进行翻译,翻译后的文本将显示在窗口中央的大文本框中。 然后,用户可以复制并粘贴翻译后的文本,按需使用。

文本翻译应用被设计成一个简单高效的工具,用于将一种语言中的文本翻译成另一种语言。

图 6.2 – 文本翻译应用 UI

图 6.2 – 文本翻译应用 UI

重要提示

我们不需要指定要翻译的文本,因为 ChatGPT 语言模型被设计成能够自动识别 提示语言。

现在我们已经明确了基本设计,我们可以用 Tkinter 将其实现。

为了开始,我们需要从我们的 <st c="9567">app.py</st> 文件中删除之前添加的示例代码。 只需删除包含示例代码的所有代码行,这样我们就可以从一个干净的状态开始。

创建 Tkinter 窗口是构建我们的文本翻译应用的下一步。 您可以通过在 <st c="9827">app.py</st>中编写以下代码来实现这一点,该代码初始化了 Tkinter 类的新实例并设置了 应用程序窗口:

 from openai import OpenAI
import docx
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.title("Text Translator")
root.configure(bg="white")
header_font = ("Open Sans", 16, "bold")
header = tk.Label(root,
                  text="Text Translator",
                  bg="white",
                  font=header_font,
                  )
header.grid(row=0, column=0, columnspan=2, pady=20)
root.mainloop()

要开始构建 Tkinter 应用,我们首先需要导入必要的库。 我们将使用 <st c="10367">openai</st>, <st c="10375">docx</st>, 和 <st c="10385">tkinter</st> 库来完成这个项目。

接下来,我们需要创建我们应用程序的主窗口。 我们将使用 <st c="10507">Tk()</st> 方法来创建主窗口,这是 <st c="10526">tkinter</st> 库的一部分。 我们还将为我们的应用程序设置一个标题并将其背景颜色设置为白色。

我们还可以使用 <st c="10679">Label()</st> 方法来为我们的应用程序设置标题,该方法属于</st> tkinter<st c="10704">。我们可以将其文本设置为<st c="10729">文本翻译器</st>,背景颜色设置为<st c="10770">白色</st>,字体设置为<st c="10793">Open Sans</st>,大小为<st c="10819">16</st> ,并且为<st c="10828">粗体</st> 字体。 <st c="10841">然后我们将使用grid() <st c="10868">方法通过指定 <st c="10966">和 <st c="10977">值将标题放置在我们的应用程序窗口的特定位置,跨越两列,并具有小的填充。

我们将使用 <st c="11071">mainloop()</st> 方法来运行我们的应用程序,该方法属于 <st c="11092">tkinter</st><st c="11105">mainloop()</st> 方法是一个无限循环,用于运行应用程序,监听事件,如按钮点击或窗口大小调整,并在需要时更新显示。`它将持续监听事件,直到用户关闭窗口或退出 应用程序。

在创建应用程序窗口之后,下一步是向其中添加元素。 这些元素之一将是 浏览 按钮:

 browse_button = tk.Button(root, text="Browse",
                          bg="#4267B2", fg="black", relief="flat",
                          borderwidth=0, activebackground="#4267B2",
                          activeforeground="white")
browse_button.config(font=("Arial", 12, "bold"), width=10, height=2)
browse_button.grid(row=1, column=0, padx=20, pady=20)

重要提示

在调用<st c="11829">mainloop()</st> 方法之前添加所有元素是很重要的,以确保它们被正确地包含在应用程序窗口中。 <st c="11905">mainloop()</st> 应该始终是您的<st c="11955">app.py</st> 文件中的最后一行。

要创建一个按钮小部件,您可以在 <st c="12011">tk.Button()</st> 方法中,该方法属于 <st c="12037">tkinter</st> 库。 <st c="12054">按钮放置在根窗口中,其bg <st c="12141">参数将按钮的背景颜色设置为深蓝色,而fg <st c="12216">设置前景颜色为黑色`

同时, <st c="12264">relief</st> 被设置为 <st c="12281">flat</st> 以创建平面外观,并且 <st c="12319">borderwidth</st> 被设置为 <st c="12341">0</st> 以移除按钮的边框。 <st c="12379">然后,我们使用</st> activebackground<st c="12411">和</st>activeforeground<st c="12432">参数来设置按钮在被点击或</st>悬停` 时的颜色。

浏览 按钮下方,我们可以创建一个包含语言列表的下拉菜单:

 languages = ["Bulgarian", "Hindi", "Spanish", "French"]
language_var = tk.StringVar(root)
language_var.set(languages[0])
language_menu = tk.OptionMenu(root, language_var, *languages)
language_menu.config(font=("Arial", 12), width=10)
language_menu.grid(row=1, column=1, padx=20, pady=20)

语言列表包含用户可以选择的语言列表。 您可以将任何语言添加到该列表中,并且它将在 下拉菜单中显示给用户。

<st c="13065">language_var</st> 变量被创建为一个 <st c="13103">StringVar</st> 对象,并将其设置为列表中的第一种语言。 <st c="13163">language_var</st> 对象的 <st c="13172">set()</st> 方法随后被用来将其初始值设置为语言列表的第一个元素。 这样做是为了使语言下拉菜单的默认值为列表中的第一种语言,在本例中是 <st c="13403">Bulgarian</st>

然后,使用 <st c="13431">OptionMenu</st> 小部件和 <st c="13474">language_var</st> 变量以及 <st c="13504">*languages</st> 语法创建小部件,该语法将 <st c="13541">languages</st> 列表解包为单独的参数。 这将为下拉菜单设置可用选项为语言列表中的语言。 然后,我们在 应用程序窗口的第一行的第二列中配置和定位一个选项菜单小部件。

下一步是将文本字段添加到我们的 GUI 中。 <st c="13847">为此,您可以在</st> app.py<st c="13928">文件下方添加以下代码。</st>此代码创建了一个具有特定尺寸、颜色和属性的文本字段,然后使用 <st c="14059">grid positioning</st> 将其放置在窗口中:

 text_field = tk.Text(root, height=20, width=50, bg="white", fg="black",
                     relief="flat", borderwidth=0, wrap="word")
text_field.grid(row=2, column=0, columnspan=2, padx=20, pady=20)
text_field.grid_rowconfigure(0, weight=1)
text_field.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(2, weight=1)
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)

此代码将在 GUI 窗口中添加一个文本字段,该字段将用于显示 Word 文档的 ChatGPT 翻译。 在此, <st c="14595">Text</st> 小部件对象名为 <st c="14620">text_field</st> ,放置在根窗口内部。 <st c="14669">Text</st> 小部件用于显示和编辑多行文本。 然后,我们使用 <st c="14750">grid()</st> 方法将 <st c="14780">Text</st> 小部件定位在 GUI 上。 <st c="14808">padx</st> <st c="14817">pady</st> 参数在窗口中为小部件添加填充,以在它与其他小部件之间创建一些空间。

您可以通过使用 <st c="14946">text_field</st> 的配置来使主窗口在水平和垂直方向上扩展,使用 <st c="15022">grid_rowconfigure()</st> <st c="15046">grid_columnconfigure()</st> 方法。 这允许文本字段填充窗口中的可用空间。 然后,您还可以配置主窗口, <st c="15197">root</st>,以扩展它。 这些设置确保文本字段保持在窗口中心,并填充可用空间。

一旦您的 GUI 完成,您就可以启动应用程序,并确认您的 GUI 与 图 6**.2中显示的样式和属性完全一致。 通过单击语言 菜单,您可以访问并选择任何语言

这就是如何使用 Tkinter 库创建文本翻译应用的 GUI。 我们已经创建了主窗口、标题、 浏览 按钮,以及包含语言列表的下拉菜单。

尽管您已经完成了 GUI,但单击 浏览 按钮不会触发任何操作,因为它尚未连接到任何活动的 Python 函数。 我们将在下一节中修复这个问题,我们将创建两个核心函数,分别负责打开 Microsoft Word 文件和执行 翻译。

将 Microsoft Word 文本与 ChatGPT API 集成

在本节中,我们将逐步指导你如何使用 Python 创建两个核心函数,这些函数对于构建文本翻译应用程序至关重要。 第一个函数,<st c="16379">translate_text()</st>,使用 <st c="16545">browse_file()</st>,允许用户从他们的本地系统中浏览并选择一个 Word 文件,并触发文本翻译过程。 这两个函数将通过代码示例进行详细解释,以帮助你理解和在自己的项目中实现它们。

<st c="16797">使用 gpt-3.5-turbo 翻译 Word 文本</st>

在本节中,你将学习如何构建 <st c="16888">translate_text()</st> 函数。 此函数负责将 Microsoft Word 文件的文本翻译成用户通过 GUI 选择的语言。 我们将使用 OpenAI API,特别是 gpt-3.5-turbomodel,来翻译 文本。

在构建 <st c="17156">translate_text()</st> 函数之前,你需要在你的项目根目录下创建一个名为 <st c="17221">config.py</st> 的文件。 此文件将包含你的 OpenAI API 令牌,这是使用 OpenAI API 所必需的。 API 令牌应分配给名为 <st c="17404">API_KEY</st> 的变量,在 <st c="17419">config.py</st> 文件中:

<st c="17434">config.py</st>

 API_KEY = "<YOUR_CHATGPT_API_KEY>"

<st c="17479">app.py</st>

 import openai
import docx
import tkinter as tk
from tkinter import filedialog <st c="17565">import config</st>
<st c="17578">client = OpenAI(</st>
 <st c="17595">api_key=config.API_KEY,</st>
<st c="17619">)</st>

此步骤是必要的,以保持 API 令牌的安全,并防止其意外上传到 公共仓库。

在设置好 API 密钥后,你现在可以继续在 <st c="17838">app.py</st>中实现 <st c="17809">translate_text()</st> 函数,如下面的 代码片段 所示:

 def translate_text(file_location, target_language):
    doc = docx.Document(file_location)
    text = ""
    for para in doc.paragraphs:
        text += para.text
    model_engine = "gpt-3.5-turbo"
    response = client.chat.completions.create(        model=model_engine,
        messages=[
            {"role": "user", "content": "You are a professional language translator. "
                                        "Below I will ask you to translate text. "
                                        "I expect from you to give me the correct translation"
                                        "Can you help me with that?"},
            {"role": "assistant", "content": "Yes I can help you with that."},
            {"role": "user", "content": f"Translate the following text in {target_language} : {text}"}
        ]
    )
    translated_text = response.choices[0].message.content
    return translated_text

<st c="18583">The</st> <st c="18588">translate_text()</st> <st c="18604">函数接受两个参数 –</st> <st c="18637">file_location</st> <st c="18650">,这是要翻译的 Microsoft Word 文件的位置,以及</st> <st c="18723">target_language</st> <st c="18738">,这是要将文本翻译成的语言。</st> <st c="18790">函数的第一行使用</st> <st c="18830">docx</st> <st c="18834">模块打开位于</st> <st c="18876">at</st> <st c="18879">file_location</st> <st c="18892">的 Word 文档。</st> <st c="18895">接下来的几行代码创建一个空字符串 text,然后遍历文档中的每个段落,将每个段落的文本连接到文本字符串中。</st> <st c="19066">换句话说,我们可以从 Word 文档中提取所有文本并存储在一个</st> <st c="19151">单独的字符串中。</st>

<st c="19165">然后,使用 GPT-3.5 API 模型来翻译文本。</st> <st c="19225">将</st> <st c="19229">model_engine</st> <st c="19241">变量设置为 GPT-3.5 模型。</st> <st c="19280">创建一个</st> <st c="19282">response</st> <st c="19290">变量,通过调用</st> <st c="19326">client.chat.completions.create()</st> <st c="19358">方法,向 API 发送提示信息,请求将给定的文本翻译成</st> <st c="19467">指定的</st> <st c="19477">target_language</st> <st c="19492">。</st>

<st c="19493"> <st c="19498">messages</st> <st c="19506">参数是一个字典列表,代表用户和语言翻译器之间的对话。</st>

<st c="19619"> <st c="19624">messages</st> <st c="19632">变量用于将对话历史传递给语言模型进行翻译。</st> <st c="19718">对话</st> <st c="19735">由用户和助手使用</st> <st c="19808">ChatGPT API</st> <st c="19812">交换的消息组成。</st>

<st c="19820">让我们分解一下</st> <st c="19856">messages</st> <st c="19864">变量的设计:</st>

  1. <st c="19874">该变量是一个字典列表,其中每个字典代表一个包含两个</st> <st c="19967">键值对的消息:</st>

    • <st c="19983">role</st> <st c="19988">:这代表对话中参与者的角色。</st> <st c="20056">它可以是</st> <st c="20073">user</st> <st c="20077">或</st> <st c="20081">assistant</st> <st c="20090">。</st>

    • <st c="20091">content</st> <st c="20099">:这代表消息的实际内容。</st>

  2. <st c="20152">对话遵循一个模式,前两条消息建立上下文,最后一条消息提供要</st> <st c="20285">翻译的文本:</st>

    • <st c="20299">第一条消息来自用户的角色,解释了交互的</st> <st c="20370">上下文</st>

    • 第二条消息来自助手的角色,并确认其帮助

    • 第三条消息来自用户的角色,包含要翻译的文本,包括 目标语言

对话格式旨在为语言模型提供关于其需要执行的任务的上下文,使明确用户 希望助手将给定的文本翻译成指定的 目标语言。

The <st c="20807">role</st> 键指定消息是否来自用户或助手,而 <st c="20889">content</st> 键包含实际的消息文本。 最终的翻译文本是从 <st c="20982">response</st> 对象中获取并由函数返回的。

在将包含要翻译的文本和目标语言的文本发送到 GPT-3.5 API 模型后,响应将是一个包含模型生成的响应各种信息的 JSON 对象。 对于此模型,实际的翻译存储在响应的 <st c="21300">content</st> 字段中,该字段位于 <st c="21341">choices</st> 列表的第一个选择中。 因此,代码通过访问第一个选择的 <st c="21437">content</st> 字段来提取翻译文本,并将其分配给 <st c="21493">translated_text</st> 变量,然后该函数返回。

一旦我们将翻译文本处理成 Python 字符串,我们就可以将其显示给用户。 除此之外,我们还需要实现一个函数,使用 <st c="21805">browse_file()</st> 函数 建立我们的 Word 文件的路径:

 def browse_file():
    file_location = filedialog.askopenfilename(initialdir="/",
                                               title="Select file",
                                               filetypes=(("Word files", "*.docx"), ("all files", "*.*")))
    if file_location:
        # Get the selected language from the dropdown menu
        target_language = language_var.get()
        translated_text = translate_text(file_location, target_language)
        text_field.delete("1.0", tk.END)
        text_field.insert(tk.END, translated_text)

The <st c="22239">browse_file()</st> 函数创建一个文件对话框窗口,允许用户选择要翻译的 Word 文件。 如果用户选择了一个文件,该函数会从下拉菜单中检索所选语言,然后调用 <st c="22470">translate_text()</st> 函数,并将文件位置和目标语言作为参数。 一旦文本被翻译,该函数会清除文本字段,并将翻译后的文本 插入其中。

该函数打开一个文件对话框,让用户选择要翻译的 Word 文件。 其中, <st c="22758">initialdir</st> 参数设置文件对话框打开时显示的初始目录,而 <st c="22858">title</st> 参数设置文件对话框窗口的标题。 <st c="22920">filetypes</st> 参数指定用户可以在文件对话框中选择的文件类型。 在这种情况下,用户可以选择具有 <st c="23057">.docx</st> 扩展名的文件。 所选文件的路径存储在 <st c="23121">file_location</st> 变量中。

然后,我们检查是否已选择了一个文件;如果是的话,我们可以使用 <st c="23276">language_var.get()</st> 函数从下拉菜单中检索所选语言。 接着调用 <st c="23309">translate_text()</st> 函数,并将所选文件位置和目标语言作为参数传递,以将文件中的文本翻译为目标语言。

文本翻译完成后,我们可以删除文本字段中可能存在的任何文本,并将翻译后的文本插入到文本字段中。 文本字段是我们应用程序中显示翻译文本的 GUI 小部件。

最后,你可以向 <st c="23725">browse_button</st>添加另一个参数,确保在 <st c="23758">browse_file()</st> 函数被激活时,只需点击 `按钮:

 browse_button = tk.Button(root, text="Browse",
                          bg="#4267B2", fg="black", relief="flat",
                          borderwidth=0, activebackground="#4267B2",
                          activeforeground="white", <st c="24011">command=browse_file</st> parameter associates the <st c="24056">browse_file()</st> function with the <st c="24088">tk.Button</st> widget. When the button is clicked, the <st c="24138">browse_file()</st> function will be executed.
			<st c="24178">You can now run your application to start it and display its GUI window.</st> <st c="24252">From there, you can select the target language from the drop-down menu and click on the</st> **<st c="24340">Browse</st>** <st c="24346">button to select a Word file (see</st> *<st c="24381">Figure 6</st>**<st c="24389">.3</st>*<st c="24391">).</st>
			![Figure 6.3 – Browsing a Word file with the Text Translator app](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_06_3.jpg)

			<st c="24709">Figure 6.3 – Browsing a Word file with the Text Translator app</st>
			<st c="24771">Once the file is</st> <st c="24789">selected, the ChatGPT API will</st> <st c="24820">process your request, and the translated text will be displayed in the text field below the buttons, as shown in</st> *<st c="24933">Figure 6</st>**<st c="24941">.4</st>*<st c="24943">.</st>
			![Figure 6.4 – Text translated using the Text Translator app](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_06_4.jpg)

			<st c="25939">Figure 6.4 – Text translated using the Text Translator app</st>
			<st c="25997">In this section, you learned</st> <st c="26027">how to build</st> <st c="26040">the</st> `<st c="26044">translate_text()</st>` <st c="26060">function in Python using OpenAI’s GPT-3.5 Turbo model, translating text in a Microsoft Word file into a language selected by the user through a GUI.</st> <st c="26210">We also discussed how to build the</st> `<st c="26245">browse_file()</st>` <st c="26258">function to get the path to the Word file using the</st> **<st c="26311">Browse</st>** <st c="26317">button, displaying the translated text to</st> <st c="26360">the user.</st>
			<st c="26369">Summary</st>
			<st c="26377">In this chapter, you learned how to develop a text translation application that can translate text from a Microsoft Word file into a target language selected by the user.</st> <st c="26549">The chapter covered the integration of Microsoft Word with the ChatGPT API</st> <st c="26624">using Python.</st>
			<st c="26637">We learned how to use Tkinter to create a user interface for the text translation application.</st> <st c="26733">The user interface comprised a simple and user-friendly design that included a drop-down menu, with a list of languages to translate to, and a</st> **<st c="26876">Browse</st>** <st c="26882">button that allowed users to select a Word file.</st> <st c="26932">Once the user selected a file, the contents of the file were translated using the ChatGPT API, and the translated text was displayed in the large text field in the center of</st> <st c="27106">the window.</st>
			<st c="27117">We also saw how to set up a</st> `<st c="27146">docx</st>` <st c="27150">Python library to extract text from Word documents.</st> <st c="27203">The</st> `<st c="27207">docx</st>` <st c="27211">library provided an interface to access information stored in</st> <st c="27274">Word files.</st>
			<st c="27285">In the next chapter,</st> *<st c="27307">Chapter 7</st>*<st c="27316">,</st> *<st c="27318">Building an Outlook Email Reply Generator</st>*<st c="27359">, you will learn how to build an</st> **<st c="27392">Outlook</st>** <st c="27399">email reply generator application using the most advanced ChatGPT model –</st> **<st c="27474">GPT-4</st>**<st c="27479">. You will learn how to pass email data from Outlook to the ChatGPT API and use it to generate an original reply to a specific email.</st> <st c="27613">You will also learn how to automate the ChatGPT API prompt to get relevant</st> <st c="27688">email replies.</st>

第八章:7

构建 Outlook 电子邮件回复生成器

电子邮件沟通是我们个人和职业生活中不可或缺的一部分。 然而,撰写完美的电子邮件回复可能是一项耗时且具有挑战性的任务。 这就是人工智能 (AI) AI)**可以派上用场的地方。 使用 ChatGPT API **,你将学习如何生成既相关又个性化的自动电子邮件回复,这些回复与 发件人的消息相关。

许多公司已经开始使用人工智能来生成电子邮件回复以节省时间和提高生产力。 例如,谷歌的智能回复功能使用机器学习算法生成简短、简洁的电子邮件回复,这些回复与当前消息的内容上下文相关。 同样,我们 可以使用 OpenAI 最强大的 自然语言处理 (NLP) 模型,GPT-4,与 GPT-3 相比生成更复杂的回复,帮助我们开发个性化的 电子邮件回复。

在本章中,你将学习如何 构建 Outlook 电子邮件回复生成器 使用 OpenAI 的 GPT-4 语言模型。 你将能够构建一个应用程序,该应用程序可以自动生成针对特定电子邮件的原创 回复 集成 Outlook API 和 OpenAI 的 GPT-4。 这将帮助你通过自动化撰写精心设计的电子邮件回复的过程来节省时间和提高你的生产力。 你还将学习如何使用 Outlook API 将数据发送到 ChatGPT API,以及如何自动化 ChatGPT API 提示以获取相关的 电子邮件回复。

对于这个项目,除了 <st c="1477">tkinter</st> <st c="1489">openai</st> 库之外,我们还将使用 Python 中的 <st c="1521">win32com</st> 库来与 <st c="1796">win32com</st> 交互,我们可以轻松检索电子邮件消息的主题和正文,并将其用作 OpenAI 的 GPT-4 语言模型的输入。 <st c="1939">tkinter</st> <st c="1951">openai</st> 一起, <st c="1959">win32com</st> 为我们提供了一套全面的工具,用于构建功能强大且用户友好的电子邮件 回复生成器。

通过利用 <st c="2093">win32com</st> 库与 Microsoft Outlook 交互,您可以有效地使用 Outlook API 将数据发送到 ChatGPT API。 这种集成允许创建自动电子邮件回复,可以通过设计有效的提示进行增强。 为了简化流程,可以使用 <st c="2413">tkinter</st>构建一个简单的 GUI 桌面应用程序,使电子邮件回复生成器用户友好且高效。

在本章中,我们将涵盖以下主题:

  • 将 Outlook 数据传递到 ChatGPT API

  • 生成自动 电子邮件回复

在本章结束时,您将能够使用 NLP 技术和用户友好的 图形界面生成和发送原始电子邮件回复。

技术要求

为了完成本章,我们假设您已在您的设备上安装了 Microsoft Office 和 Outlook。 您可以在以下链接中学习如何安装 Microsoft Office: https://learn.microsoft.com/en-us/microsoft-365/admin/setup/install-applications?view=o365-worldwide

然而,我们将逐步讲解 Outlook API 的完整安装过程。 您的设备上安装了最新的 Microsoft Office 365 应用程序(Outlook)。

您需要以下内容:

  • 您的计算机上安装了 Python 3.11 或更高版本

  • 一个 OpenAI API 密钥

  • 一个代码编辑器,例如 VS Code(推荐)

  • 一个 Windows 操作系统

  • 您的设备上安装的 最新 Microsoft Office 365 应用程序(Outlook)

在下一节中,您将学习如何安装 Microsoft Outlook 和 <st c="3440">win32com</st> 库。 您还将学习如何将电子邮件数据从 Outlook 传递到 ChatGPT API 以实现自动电子邮件回复生成。

《Outlook 电子邮件回复生成器》 项目的代码可以在 GitHub 上找到 ,地址为 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

将 Outlook 数据传递到 ChatGPT API

要开始,我们将首先介绍设置开发环境的基本步骤 以构建 Outlook 邮件回复生成器。 在这里,你将开始安装 Microsoft Outlook 到你的电脑上,并 设置一个电子邮件账户。 一旦安装了所有库,我们将向你展示如何使用 <st c="4091">win32com</st> 库从 Outlook 提取电子邮件数据并将其传递给 ChatGPT API 以生成自动 电子邮件回复。

让我们设置你的项目以 构建 Outlook 邮件回复生成器。 为此,创建一个名为 <st c="4324">EmailReplyGenerator</st> 的新目录,并在 VS Code 中打开它。 一旦项目创建,你可以激活你的虚拟环境,创建一个名为 <st c="4472">app.py</st>的新 Python 文件,并开始编写从 Outlook 提取电子邮件数据并将其传递给 ChatGPT API 的代码。

为了完成项目设置,你还需要安装两个 Python 库。 你可以使用 <st c="4699">pip</st> 包管理器来安装这些库。 要开始,打开命令提示符或你的机器上的终端,并输入以下命令来安装 这两个库:

 $pip install openai
$pip install pywin32

安装这些库后,我们现在可以继续安全地处理 ChatGPT API 密钥,这将使我们能够在连接到 AI 时进行身份验证。 为此,让我们在我们的项目中创建一个名为 <st c="5117">config.py</st>的新文件。正如前一个项目所示,此文件将安全地存储项目中使用的所有 API 密钥。 现在,你可以在适当的文件中包含 API 令牌和必要的库。

使用此代码用于 API 令牌:

config.py

 API_KEY = "<YOUR_CHATGPT_API_KEY>"

使用此代码用于 库:

app.py

 from openai import OpenAI
import win32com.client
import tkinter as tk
import config
client = OpenAI(
  api_key=config.API_KEY,
)

<st c="5575">config.py</st> 文件安全地存储了 ChatGPT API 密钥,该密钥被导入到 <st c="5654">app.py</st> 文件中。 然后,API 密钥通过 <st c="5758">openai</st> 库与 ChatGPT API 建立安全连接。 此外,还导入了 <st c="5792">win32com.client</st> <st c="5812">tkinter</st> 库,分别用于处理 Outlook 电子邮件数据和创建图形用户 界面。

通过这些步骤,您可以确保项目得到正确设置,从而可以顺利地在您的设备上启动已安装的 Outlook 应用程序。 设备上启动已安装的 Outlook 应用程序。

设置 Outlook 应用程序

在本节中,我们将 指导您完成设置 Microsoft Outlook 应用程序的过程。 Microsoft Outlook 是由 Microsoft 开发的一款广泛使用的电子邮件客户端和个人信息管理器。 它是 Microsoft Office 应用程序套件的一部分,其中包括 Word、Excel 和 PowerPoint 等流行的生产力工具。 虽然 Microsoft Outlook 通常与 Microsoft 电子邮件服务相关联,但重要的是要注意,Outlook 可以与任何电子邮件账户一起使用,无论电子邮件提供商是谁。 这意味着即使用户来自 Gmail、Yahoo 或其他任何电子邮件服务提供商,他们也可以利用 Outlook 的功能和优势。 电子邮件服务。

要使用安装在您计算机上的 Outlook 打开并登录到您的电子邮件账户,请按照 以下步骤操作: 这些步骤:

  1. 启动 Microsoft Outlook:在您的计算机上找到 Outlook 应用程序图标,双击它以打开 程序。

  2. 设置新账户:首次打开 Outlook 时,您将能够登录到您的电子邮件地址。 只需输入您的电子邮件地址,然后点击 连接 按钮开始设置过程(见 图 7.1)。

Figure 7.1 – The Outlook email setup window

Figure 7.1 – The Outlook email setup window

  1. 遵循屏幕提示:Outlook 将尝试根据您的电子邮件地址自动配置账户设置。 您将看到确认消息,并且您的电子邮件账户将被添加到 Outlook。

  2. 访问您的电子邮件:设置过程完成后,您可以在 Outlook 导航面板中访问您的电子邮件。 您将能够在 Outlook 应用程序内查看、发送、接收和管理您的电子邮件消息,如图 图 7.2 所示。

Figure 7.2 – The Outlook desktop interface

Figure 7.2 – The Outlook desktop interface

到达 Outlook 应用程序界面后,您现在可以使用 Outlook API 来访问和使用 win32com.client 来管理您的 电子邮件数据。

使用 win32com 客户端访问电子邮件数据

在本节中,我们将指导您通过检索 Outlook 账户中最后 10 封电子邮件的主题,并在用户友好的下拉菜单中显示它们的过程。 您将学习如何使用 <st c="8883">win32com</st> 库与 Outlook 交互,访问电子邮件数据,并在 <st c="9027">tkinter</st>中填充下拉 菜单。这将使用户能够方便地选择他们想要生成回复的电子邮件。

为了实现这一点,我们将使用 <st c="9162">last_10_emails()</st> 函数。 在这个函数内部,我们将利用 <st c="9231">win32com.client</st> 库。 我们将连接到 Outlook 应用程序并访问默认的电子邮件收件箱文件夹。 从那里,我们将检索收件箱中的电子邮件消息集合:

 def last_10_emails():
    outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
    inbox = outlook.GetDefaultFolder(6)
    messages = inbox.Items
    emails = [messages.GetLast().Subject]
    email_number = 10
    for i in range(email_number):
        emails.append(messages.GetPrevious().Subject)
    return emails

前面的代码演示了如何使用 <st c="9811">win32com.client</st> 模块与 Outlook 应用程序交互,访问和操作电子邮件消息,具体步骤如下:

  1. 首先,我们将使用 <st c="9926">win32com.client.Dispatch()</st> 函数来创建与 Outlook 应用程序的连接。 此函数接受一个字符串参数, <st c="10052">Outlook.Application</st>,以指定我们想要访问的应用程序。

  2. 然后,我们将使用 <st c="10141">GetNamespace()</st> 方法,并使用 <st c="10172">MAPI</st> 参数来检索 Outlook 中的消息和协作服务命名空间。 此命名空间提供了访问各种 Outlook 对象 和文件夹的权限。

  3. 通过调用 <st c="10347">GetDefaultFolder(6)</st> ,我们检索默认的电子邮件 <st c="10398">收件箱</st> 文件夹。 参数 <st c="10416">6</st> 对应于 Outlook 命名空间中 <st c="10459">收件箱</st> 文件夹的索引。 这确保了我们访问正确的文件夹。 通过将结果分配给 <st c="10581">inbox</st> 变量,我们现在有了对 <st c="10628">收件箱</st> 文件夹的引用,这允许我们检索电子邮件消息并对它们进行操作。 <st c="10717">inbox.Items</st> 检索收件箱文件夹中的项目或电子邮件消息集合。 此集合被分配给 <st c="10841">messages</st> 变量。

  4. 要检索最新电子邮件的主题, <st c="10910">messages.GetLast().Subject</st> 将被使用。 <st c="10951">GetLast()</st> 返回集合中的最后一个电子邮件项,而 <st c="11014">.Subject</st> 检索该电子邮件的主题。 <st c="11060">我们现在可以将电子邮件主题包裹在一个列表中,以确保它是一个包含单个主题的列表。</st> 我们还可以定义一个名为 <st c="11198">email_number</st>的变量,它代表我们想要 检索主题的前置电子邮件数量。

除了 <st c="11318">GetList</st> 方法之外,您还可以使用以下 <st c="11387">win32com</st> 方法获取特定的电子邮件项:

  • <st c="11404">FindNext</st>: 此方法用于检索与指定 搜索条件 匹配的电子邮件集合中的下一个电子邮件项

  • <st c="11534">GetFirst</st>: 使用此方法,您可以从电子邮件集合中检索第一个电子邮件项,从而能够访问其内容 或属性

  • <st c="11676">GetNext</st>: 与 <st c="11712">GetFirst</st>结合使用,此方法检索集合中的下一个电子邮件项,便于对集合中所有电子邮件进行顺序访问

  • <st c="11851">GetPrevious</st>: 此方法补充 <st c="11890">GetFirst</st> ,并允许您检索电子邮件集合中当前访问项之前的电子邮件项,从而实现电子邮件的顺序向后访问

我们现在可以遍历前 10 个先前电子邮件的主题范围。 <st c="12071">在循环中,我们使用</st> GetPrevious().Subject<st c="12193">来访问迭代中当前电子邮件之前的电子邮件的主题。</st>此方法将指针移动到集合中的上一个电子邮件,并且 <st c="12348">.Subject</st> 检索电子邮件的 `主题。

对于每次迭代,我们使用 <st c="12471">append()</st> 方法将检索到的主题追加到电子邮件列表中。 `这将从最新开始构建一个电子邮件主题列表,并按时间顺序回溯。

循环完成后,我们就有了一个包含 10 个电子邮件主题的列表存储在电子邮件列表中。 <st c="12695">然后我们可以从</st> last_10_emails()<st c="12767">函数中返回此电子邮件主题列表,使其可用于我们的 Outlook 电子邮件</st>回复生成器。`

现在,我们可以专注于创建用户界面来显示电子邮件主题,并允许用户选择一个来生成 回复:

 root = tk.Tk()
root.title("Outlook Emails")
root.geometry("300x300")
email_subjects = last_10_emails()
selected_subject = tk.StringVar()
dropdown = tk.OptionMenu(root, selected_subject, *email_subjects)
dropdown.pack()
label = tk.Label(root, text="")
label.pack()
root.mainloop()

让我们分析一下前面 代码的每个部分:

  1. 首先,我们将使用 <st c="13410">tkinter</st> 库来初始化和配置应用程序的主要图形窗口。

    <st c="13426">root = tk.Tk()</st> 创建了一个主窗口对象,通常被称为根或顶级窗口。 此对象代表包含我们应用程序用户界面元素的 主窗口。

  2. 然后,我们可以将窗口的标题 设置为 <st c="13690">Outlook Emails</st>。这个标题将在窗口的标题栏中显示。 我们还将设置窗口的尺寸为 <st c="13816">300</st> 像素宽和 <st c="13836">300</st> 像素高。 这决定了窗口首次在 屏幕上显示时的初始大小。

  3. 在完成窗口模板后,我们可以初始化用于在用户界面中管理电子邮件主题的变量。 这里使用的 <st c="14088">last_10_emails()</st> 函数用于检索电子邮件主题列表。 该函数将 Outlook 应用程序中的最后 10 个电子邮件主题返回到 <st c="14263">email_subjects</st> 变量中。

  4. <st c="14292">selected_subject</st> 变量从 <st c="14328">StringVar</st> 对象创建了一个 <st c="14354">tkinter</st> 库。 此对象是一种特殊的变量类型,可以与各种 GUI 小部件相关联。 通过创建一个 <st c="14473">StringVar</st> 对象,我们有一个可以存储字符串值并轻松与 GUI 元素(如按钮或下拉菜单)相关联的变量。 这使我们能够在 我们的应用程序中跟踪和操作所选电子邮件主题。

  5. 然后,我们在用户界面中创建一个下拉菜单来显示邮件主题列表。 <st c="14807">OpenMenu</st> 小部件代表一个下拉菜单,用户可以从列表中选择一个选项。 <st c="14904">root</st> 参数指定下拉菜单应放置在我们的应用程序的主窗口中,而<st c="15022">selected_subject</st> 参数指定了将与下拉菜单关联的变量。 它表示将持有从下拉菜单中当前选中的邮件主题的变量。

    <st c="15227">*email_subjects</st> 参数使用<st c="15261">*</st> 运算符将<st c="15286">email_subjects</st> 列表解包成单独的项目。 这允许每个邮件主题都被视为<st c="15405">OptionMenu</st> 小部件的一个单独的参数,为下拉菜单提供选项列表。

  6. 然后,我们可以构建一个标签小部件并启动应用程序的主事件循环。 <st c="15565">label</st> 变量创建了一个标签小部件,用于在用户界面中显示文本或其他信息。 <st c="15673">text</st> 参数指定了标签中要显示的初始文本,在这种情况下是一个空字符串。 <st c="15783">label.pack()</st> 将小部件打包到主窗口中。

  7. 最后,<st c="15847">root.mainloop()</st> 启动主事件循环。 此方法负责处理用户事件,如鼠标点击或按钮按下,并相应地更新 GUI。 程序将保持在这个循环中,直到用户关闭应用程序窗口,确保应用程序保持响应性和交互性。

为了测试应用程序,让我们想象我们是一名软件工程师,收到了来自 我们同事的 10 封工作邮件。

现在,您可以执行您当前版本的 Outlook 邮件回复生成器。 一旦代码开始运行,将出现一个标题为 Outlook 邮件 的窗口。 此窗口包含一个下拉菜单,列出了来自 Outlook 应用程序的最后 10 封邮件主题,如图 7.3.3所示。

图 7.3 – 邮件回复生成器的最后 10 封邮件下拉菜单

图 7.3 – 电子邮件回复生成器的最后 10 封电子邮件下拉菜单

你现在可以从下拉菜单中选择一个电子邮件主题。 选择后,所选电子邮件主题的文本将被存储在 <st c="17159">selected_subject</st> 变量中,并在下拉菜单按钮内显示(见 图 7**.4)。

图 7.4 – 下拉菜单按钮内的所选电子邮件主题

图 7.4 – 下拉菜单按钮内的所选电子邮件主题

这些 是设置构建 Outlook 电子邮件回复生成器开发环境的必要步骤。 我们通过使用<st c="17562">win32com</st> 库从 Outlook 提取电子邮件数据并将其传递给 ChatGPT API 来演示了这一过程。 你还学习了如何使用<st c="17678">win32com</st> <st c="17686>tkinter<st c="17698">库来访问和显示电子邮件数据,以创建</st>GUI`。

在下一节中,你将使用 ChatGPT API 生成用户选择的特定电子邮件的 AI 回复,从而完成你的 Outlook 电子邮件回复生成器。 我们还将构建相应的按钮,让用户可以从桌面应用程序访问该功能。

生成自动电子邮件回复

现在,让我们 深入了解我们应用程序中自动回复 Outlook 电子邮件的关键功能实现。 我们将逐步讲解构建应用程序最后部分的过程,该部分利用 Outlook API 检索电子邮件数据,并利用上一节获取的数据,通过 ChatGPT API 生成原创回复。 在这里,你将学习如何无缝地将 ChatGPT API 集成到你的 Outlook 应用程序中。

我们将构建 <st c="18530">reply()</st> 函数,该函数是生成电子邮件回复的核心组件。 在这个函数中,你将从用户界面检索所选电子邮件主题,并使用它从 Outlook 获取相应的电子邮件内容。 我们将演示如何利用 ChatGPT API 根据电子邮件内容生成 AI 驱动的响应。 通过这个过程,你将获得在 ChatGPT 和 Outlook 之间传递数据的实践经验。

您可以在 reply() 函数上方 root.mainloop() 内部 app.py</st> <st c="19078">文件</st> <st c="19085">中包含该函数。</st> <st c="19085">请注意,</st> <st c="19099">root.mainloop()</st> <st c="19114">函数调用应该是</st> <st c="19177">tkinter 应用程序 中的最后一行代码。 这是因为 `root.mainloop() 启动了主事件循环,该循环负责处理用户事件并更新 GUI:

 def reply():
    email = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI").\
        GetDefaultFolder(6).Items.Item(selected_subject.get())
    response = client.chat.completions.create(
        model="gpt-4",
        max_tokens=1024,
        n=1,
        messages=[
            {"role": "user", "content": "You are a professional email writer"},
            {"role": "assistant", "content": "Ok"},
            {"role": "user", "content": f"Create a reply to this email:\n {email.Body}"}
        ]
    )
    reply = email.Reply()
    reply.Body = response.choices[0].message.content
    reply.Display()
    return

在这里,我们可以使用 win32com</st> <st c="19946">库</st> <st c="19956">从 Outlook 应用程序中检索选定的电子邮件内容。</st> <st c="19956">我们将通过</st> <st c="20007">Dispatch 方法 访问 Outlook 应用程序。 从那里,我们使用 GetDefaultFolder(6)</st> <st c="20057">检索</st> <st c="20052">Inbox 电子邮件文件夹,并根据从 selected_subject</st> <st c="20186">获得的主题检索特定的电子邮件项。生成的 `email 对象代表用户指定的主题的电子邮件,并且可以进一步用于生成回复或访问其他 电子邮件属性。

然后,我们可以利用 ChatGPT API 来生成对电子邮件的回复。 我们将调用 client.chat.completions.create() 方法,并提供几个参数来生成回复。 max_tokens 参数限制了生成的电子邮件回复的长度为 1,024 个标记。 通过调整此参数,您可以增加或减少标记的数量,以达到您所需的电子邮件回复长度。

正如您在这里所看到的,我们正在使用 最先进的 ChatGPT 模型GPT-4。与 GPT-3 相比,该模型训练的数据量显著更多,因此在解决复杂任务方面更加准确、事实性强、可靠性高,包括个性化的 电子邮件文案。

client.chat.completions.create() 方法是实现的关键部分,因为它利用 ChatGPT API 来生成自动电子邮件回复。 prompt 参数尤其重要,因为它设置了语言模型接收的初始输入。 在这种情况下,提示包括从 Outlook 获得的电子邮件内容,这作为生成 回复的上下文。

为了提高回复的质量和多样性,开发者可以尝试不同的提示。 通过制定更具体或多样化的提示,可以引导模型输出满足特定标准或针对不同情境定制的回复。 以下是一些替代方案:

  • 上下文提示: “你收到一位同事的邮件,请求你参加一个会议。 撰写一个 礼貌且简洁的回复,确认 你的出席。”

    在这个提示中,模型被明确指示回应同事的会议请求。 通过提供具体场景并要求“礼貌且简洁”的回复,生成的回复更有可能与期望的情境 和语气相符。

  • 情感提示: “你刚刚收到一封来自亲密朋友的邮件,分享了一些令人兴奋的消息。 草拟一个 温暖且热情的回复,向他们表示祝贺并分享 你的想法。”

    通过在提示中融入情感关键词,如“令人兴奋的消息”、“温暖”和“热情”,模型被鼓励产生传达快乐和支持感的回复,使其听起来更真实、更像人类。

  • 正式商务提示: “作为客户服务代表,你收到一封来自对近期产品问题不满的 客户的邮件。 撰写一个专业且富有同理心的回复,以解决他们的担忧并提供 解决方案。”

    在这里,提示设定了一个正式的商务背景,指示模型以 客户服务代表的身份回应处理不满的客户。 使用“同理心”一词强调了回复中表现出同情和帮助的重要性,这可能导致更真实和 体贴的回复。

  • 个性化提示: “你的最佳朋友给你发了一封邮件,分享了一些关于他们最近度假的令人兴奋的更新。 回复 时,用你真诚的兴奋之情,提出后续问题,并分享一些你生活中的事情。”

    这个提示 鼓励更个性化的回复,因为它具体说明了回复应该表达真诚的兴奋之情,并涉及提出后续问题。 通过强调分享发件人生活信息的互惠性,生成的回复可能会感觉更自然,更像是真实的对话。

  • 教学提示:“您收到一封来自同事的邮件,询问如何使用 一款新软件工具的详细说明。 如有必要,请提供带有清晰解释和视觉辅助的逐步指南。”

    在这种情况下,提示为模型生成包含详细说明的回复设置了明确的指令。 使用“逐步指南”和“清晰解释”等术语指导模型提供更信息丰富和 结构化的响应。

主题和邮件内容在生成回复中起着至关重要的作用。 选定的邮件主题作为用户想要回复的邮件的关键标识符。 一旦识别出邮件,其内容正文就被用作生成回复的上下文。 通过利用主题和邮件内容,回复函数确保 ChatGPT 生成的响应相关且具有上下文。 邮件内容提供了有关发件人查询或消息的必要信息,模型使用这些信息来构建连贯且 适当的回复。

与 ChatGPT 或任何外部 API 分享邮件内容,或任何此类事宜,都会引发有效的安全担忧。 这可以通过适当的隐私政策和用户同意机制来防止。 此外,使用安全的通信协议(例如 HTTPS)并与值得信赖的 API 提供商(如 OpenAI)合作,可以在传输 和处理过程中帮助保护数据。

在获取 ChatGPT API 响应后,我们可以通过使用 <st c="25213">email.Reply()</st>创建回复对象来准备邮件回复。然后,将回复的主体文本分配为从 ChatGPT <st c="25321">response</st> 参数中提取的响应文本。 这确保了 AI 生成的内容包含在回复中。

然后调用 <st c="25414">reply.Display()</st> 函数以在单独的窗口中显示回复,使用户能够在发送之前进行审查和可能的必要编辑。 <st c="25589">return</st> 语句表示 reply() 函数的结束,并将控制权返回到主程序,在那里我们将构建 回复 按钮:

<st c="25726">button = tk.Button(root, text="Generate Reply",</st>
 <st c="25774">command=reply)</st>
<st c="25789">button.pack()</st> root.mainloop()

该按钮与根窗口相关联,并显示文本 <st c="25921">command</st> 参数指定当按钮被点击时,之前构建的 <st c="25975">reply()</st> 函数应该被执行。 通过调用 <st c="26050">button.pack()</st>,按钮被包装在窗口中,允许它向用户显示。 这就是我们如何设置一个用户界面元素,当点击时触发 <st c="26215">reply()</st> 函数,从而在用户交互时生成电子邮件回复的方法。

一旦您启动 Outlook 电子邮件回复生成应用程序,您的应用程序窗口将显示一个名为 生成回复 的新按钮(见 图 7**.5)。

Figure 7.5 – The Generate Reply button

图 7.5 – 生成回复按钮

现在,您可以从下拉菜单中选择一封电子邮件,并点击 <st c="26736">reply()</st> 函数,将电子邮件内容传递给 ChatGPT API,并要求它根据该内容生成回复。 此过程将在 后台进行,几秒钟后,您的应用程序将打开 Outlook 回复窗口。 正如您在 图 7**.6中看到的那样,回复窗口将填充生成的 ChatGPT 对所选电子邮件的回复。

Figure 7.6 – An email reply generated by ChatGPT

图 7.6 – 由 ChatGPT 生成的电子邮件回复

为了验证生成的回复是否相关,您可以 检查所选电子邮件的内容和 ChatGPT 的回复,例如 以下内容:

  • 所选 电子邮件内容

    嗨,马丁,

    我有一个令人兴奋的新功能请求要向您提出。 我们的用户一直在要求一个提供账户活动概述和统计信息的个性化仪表板。

    如果您能开始这项功能的工作,并给出所需开发 工作量估计,我将不胜感激。

    问候,

    比尔。

  • GPT-4 API 回复

    亲爱的比尔,

    感谢您的邮件和提出如此令人兴奋的新 功能请求。

    个性化仪表板确实是一个极好的补充,将显著提升用户体验。 我理解一个能够为我们用户提供其账户活动全面概述的工具的重要性 和统计数据。

    我将立即开始初步工作以评估可能性。 这包括深入了解用户需求,定义必要的功能,以及分析工作 范围。

    考虑到这个功能的复杂性和范围,我预计初步估计将在一周内完成。 这将帮助我提供一个准确的开发 工作量估计。

    我期待着这个新功能可能对我们用户体验带来的积极影响。 感谢您将这项任务 交给我。

    最好的祝愿,

    马丁

除了生成相关回复外,您的应用程序还赋予用户在发送之前编辑人工智能生成的回复的能力。 此功能还允许他们解决任何小瑕疵或对回复进行调整,以确保电子邮件的最终版本完美无瑕。 通过提供审查和修改人工智能生成的回复的选项,用户对内容有更大的控制权,可以在发送 电子邮件之前根据其特定需求进行定制。

这标志着我们使用 Outlook 和 ChatGPT API 生成自动电子邮件回复的实现工作告一段落。 现在,您可以从 Outlook 中检索电子邮件数据,使用 ChatGPT API 生成人工智能驱动的回复,并将此功能集成到 Outlook 应用程序中,使用户在 发送之前能够审查和修改生成的回复。

摘要

在本章中,我们介绍了使用 Outlook 和 ChatGPT API 以及最先进的 GPT-4 模型开发 Outlook 电子邮件回复生成器的完整过程。 我们学习了如何使用 <st c="30210">win32com</st> 库从 Outlook 中检索电子邮件数据,并使用 <st c="30288">tkinter</st> 库在下拉菜单中显示电子邮件主题。 我们编写了连接到 Outlook 应用程序、访问默认电子邮件收件箱文件夹以及检索最后 10 个电子邮件主题的代码。 我们还介绍了用户界面的创建,包括主窗口、下拉菜单和 标签。

我们也学习了构建 <st c="30598">reply()</st> 函数的过程,该函数从 Outlook 中检索电子邮件数据,使用 ChatGPT API 生成 AI 驱动的响应,并在单独的窗口中显示生成的回复以供审查和编辑。 本章还解释了如何将 <st c="30841">reply()</st> 函数集成到应用程序中,以及如何在用户界面中创建一个触发 <st c="30946">reply()</st> 函数的按钮。 我们还通过从下拉菜单中选择电子邮件主题并使用 ChatGPT API 生成 AI 回复电子邮件来测试了应用程序。

在第 第八章中,你将学习如何将 ChatGPT API 与最受欢迎的应用程序开发 Python 框架之一 PyQT集成。你将构建一个能够就任何主题创建论文的论文生成工具。 在这里,我们将更进一步,向你展示如何直接从应用程序前端控制 API 令牌。 这将允许你指定响应的长度,从而确定从 ChatGPT API 收到的生成的论文。

第九章:8

使用 PyQt 和 ChatGPT API 的论文生成工具

在本章中,我们将深入探讨将 ChatGPT API 与最流行的 Python 框架之一用于 应用程序开发PyQt的激动人心的世界。您将构建一个用户友好的桌面论文生成工具,该工具由 PyQt 和 ChatGPT API 的集成提供动力,使用户能够轻松地生成关于任何主题的优秀文章。 在这里,您将获得有关构建 PyQt 桌面应用程序的设计阶段的有价值见解。

我们将引导您通过使用 PyQt 进行面向对象的方法设计桌面应用程序的过程,帮助您理解该框架中涉及的基本概念和组件。 在打下坚实基础之后,我们将转向利用 ChatGPT API 的能力。 您将学习如何将 API 集成到您的 PyQt 应用程序中,使您能够无缝生成文章。

通过结合 PyQt 和 ChatGPT API 的优势,您将能够创建一个交互式且智能的桌面应用程序,能够生成关于各种主题的优秀文章。 此外,我们将展示如何让用户能够直接从前端控制 API 令牌,赋予他们指定从 ChatGPT API 获得的文章响应长度的能力。 这种程度的定制化使用户能够根据特定要求调整生成的文章,无论是简洁的摘要还是 深入的分析。

在本章中,您将涵盖以下主题:

  • 使用 PyQT 构建桌面应用程序

  • 使用 ChatGPT API 创建论文生成方法

  • 控制 ChatGPT API 令牌

在本章结束时,您将熟练使用 PyQt 设计和开发桌面应用程序,为应用程序开发打下坚实基础。 此外,您还将进一步发展将 ChatGPT API 集成到您应用程序中的技能,让您更好地控制 AI 响应参数。

技术要求

在本章中,我们将演示完整的 <st c="2096">PyQt6</st> 安装。 然而,为了成功完成论文生成工具项目,您还应确保满足以下 技术先决条件:

  • 在您的机器上安装了 Python 3.7 或更高版本

  • 一个代码编辑器,例如 VS Code (推荐)

  • 一个 Python 虚拟环境

  • 一个 OpenAI API 密钥

  • 熟悉 Python 面向对象编程 (OOP) 概念

本章展示的代码片段可以在 GitHub 平台上找到。 通过访问以下 链接 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/tree/main/Chapter08 ArticleGenerator 可以获取代码。

在接下来的章节中,你将开始使用 PyQT 构建桌面应用程序的旅程。 你将深入了解 GUI 设计的复杂性,并学习如何利用 PyQT 的强大功能来开发一个视觉上吸引人且交互式的 桌面应用程序。

使用 PyQT 构建桌面应用程序

在本节中,你 将获得在 创建 PyQT 应用程序用户界面的各种组件的实际经验,例如窗口、标签、按钮、文本字段和下拉菜单。 在这里,你将设置项目,安装 <st c="3282">PyQt6</st> <st c="3292">docx</st> 库,并构建你的桌面 应用程序前端。

首先,让我们讨论一下 PyQt 库是什么,以及它与 Python 应用程序开发工具(如 Tkinter(见 表 8.1)有何不同。 PyQt 是一个强大的 Python 框架,广泛用于创建具有丰富 图形用户界面 (GUIs)的桌面应用程序。 它为开发者提供了一套全面的工具、类和功能,用于设计和构建直观且视觉上吸引人的应用程序。 PyQt 是围绕 流行的 Qt 框架的一个包装器,将 Qt 的广泛库和控件 无缝集成到 Python 中。

框架 基于 Qt (强大的 GUI 工具包) 内置 Python GUI 工具包 (Tkinter)
跨平台
许可 GPL 和商业 开源(Python 软件基金会
小部件库 广泛 有限
外观 和感觉 在所有平台上都有本地外观 仅在 一些平台上具有本地外观
文档 全面 且文档齐全 基本 但足够
流行度 在爱好 和工业界都受欢迎 标准库,在 Python 中广泛使用
学习曲线 适合初学者 适中 到陡峭
性能 通常由于 C++后端 通常由于 Python 后端
社区 支持 活跃的社区和 第三方模块 活跃的社区和 丰富的资源

表 8.1 – PyQt 与 Tkinter 的比较

重要注意事项

PyQt 有两种许可协议 – GNU 通用公共许可证 (GPL) 和商业许可。 GPL 允许你在遵守许可证条款和条件的情况下免费使用 PyQt,这些条件包括如果你分发应用程序,则必须提供应用程序的源代码。 如果你不想遵守 GPL 的要求或需要在专有、封闭源代码的项目中使用 PyQt,你可以从开发 PyQt 的 Riverbank Computing 公司购买商业许可。 商业许可允许你在不受 GPL 限制的情况下使用 PyQt。

PyQt 是一个 Python 框架,与 Tkinter 不同,Tkinter 是 Python 用于使用 Tk 工具包创建 GUI 的标准库。 PyQt 提供更广泛的控件和高度可定制的 外观。 它还提供了更 现代和美观的 GUI 外观。 现在你已经知道了 PyQt 是什么,我们可以设置你的项目并安装这个出色的 Python 桌面 应用程序框架。

设置文章生成工具项目

<st c="5695">让我们首先</st> <st c="5708">通过遵循我们已熟悉的步骤来配置我们的项目。</st> <st c="5789">你可以通过创建一个名为 <st c="5838">EssayGenerationTool</st> <st c="5857">的新目录并在 VS Code 中加载它来开始。</st> <st c="5885">一旦创建了项目目录,你就可以构建你的 Python 虚拟环境并创建一个名为 <st c="6001">app.py</st> <st c="6007">的 Python 文件,其中将包含邮件生成工具的主要代码。</st> <st c="6068">。</st>

<st c="6076">为了完成项目设置,你需要安装几个 Python 库。</st> <st c="6171">你可以使用 <st c="6187">pip</st> <st c="6190">包管理器来安装这些库。</st> <st c="6235">首先,在 VS Code 中打开一个终端并输入以下命令来安装所有必要的库:</st>

 pip install PyQt6
pip install openai
pip install python-docx

<st c="6407">此外,让我们通过创建 <st c="6485">config.py</st> <st c="6494">模块来设置必要的 OpenAI API 密钥。</st> <st c="6503">正如我们在以前的项目中看到的那样,此文件将作为我们项目中所有 API 密钥的安全存储位置。</st> <st c="6633">确保 <st c="6661">config.py</st> <st c="6670">文件位于与代码相同的目录中。</st> <st c="6719">然而,你必须避免将此文件推送到 Git 仓库,以保持其机密性并防止暴露 API 密钥。</st> <st c="6847">在安全存储 API 令牌后,你可以将其包含在相关文件中,并附带必要的库,如下面的代码片段所示:</st> <st c="6973">以下</st> <st c="7003">代码片段</st> <st c="7007">:</st>

<st c="7016">config.py</st>

 API_KEY = "<YOUR_CHATGPT_API_KEY>"

<st c="7061">app.py</st>

 import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QTextEdit, QComboBox
from openai import OpenAI
import docx
import config
client = OpenAI(
  api_key=config.API_KEY,
)

<st c="7278">app.py</st> <st c="7296">文件中,我们可以导入几个库来创建我们的桌面应用程序。</st> <st c="7370">从 <st c="7405">PyQt6</st> <st c="7410">导入的具体类代表不同的 GUI 组件,例如应用程序窗口、标签、文本字段、按钮和下拉菜单。</st> <st c="7530">此外,还导入了 <st c="7534">docx</st> <st c="7538">模块来处理将我们的 AI 生成文章导出为 <st c="7616">Microsoft</st> <st c="7626">Word 文档。</st>

<st c="7640">使用 PyQt 构建应用程序 GUI</st>

<st c="7679">在本节中,我们将探讨创建 PyQt</st> <st c="7699">应用程序的过程。</st> <st c="7757">我们将使用 <st c="7834">PyQt6</st> <st c="7839">库来为文章生成应用程序设置基础。</st> <st c="7849">你将构建的应用程序用户界面由各种小部件组成,如标签、输入字段、文本区域和按钮。</st>

要开始创建用于生成论文的 PyQt 应用程序的旅程,我们首先将创建初始应用程序窗口并设置应用程序启动逻辑。 如前所述,我们的应用程序将使用 <st c="8286">EssayGenerator</st> 类。

使用面向对象设计(OOD)与 PyQt 相结合是有益的,因为 PyQt 建立在 Qt 框架之上,而 Qt 框架本身是按照面向对象原则设计的。 通过将我们的代码与底层框架对齐,我们可以充分利用 PyQt 的强大功能和灵活性。 通过将应用程序功能封装在类中,我们可以轻松管理和维护我们的应用程序。 促进了代码的可重用性和可扩展性,因为类可以根据需要继承、修改和扩展。 <st c="8772">EssayGenerator</st> 类将继承自QWidget <st c="8825">类,这是 PyQt 中所有用户界面对象的基类:

 class EssayGenerator(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    def initUI(self):
        self.setWindowTitle("Essay Generator")
        self.setGeometry (300, 300, 1200, 800)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = EssayGenerator()
    ex.show()
    sys.exit(app.exec())

以下是我们的 PyQt 应用程序 的实现方式:

  1. 首先,我们在<st c="9253">QWidget</st> 类中将其作为EssayGenerator <st c="9304">类的基类,这使我们能够采用应用程序 GUI 中的所有<st c="9341">QWidget</st> 功能。</st> QWidget <st c="9396">是 PyQt 中的一个基本类,它提供了创建窗口、处理事件和管理布局的功能。</st> <st c="9510">虽然 PyQt中还有其他可用的替代基类,例如QMainWindow <st c="9595">用于更复杂的应用程序或<st c="9629">QDialog</st> 用于自定义对话框,但QWidget <st c="9669">在这里被选择,因为它作为大多数用户界面元素的通用基础,并为我们的论文生成应用程序中创建基本窗口提供了必要的功能。 `

  2. <st c="9859">The</st> <st c="9864">EssayGenerator</st> <st c="9878">类是一种特殊类型的控件,可用于创建 GUI 元素。</st> 在类内部,我们有 init 方法,它是 Python 中称为构造函数的 <st c="10014">特殊方法。</st> <st c="10066">当创建类的对象时,它会执行。</st> init 方法中,我们使用 <st c="10157">EssayGenerator</st> <st c="10171">类的</st> super() 关键字来调用父类 <st c="10218">__init__</st> <st c="10226">方法,</st> QWidget,并对其进行初始化。</st> 这确保了在执行任何针对 <st c="10409">EssayGenerator</st> `类的特定初始化之前,执行了父类中必要的设置。

  3. <st c="10430">然后,</st> <st c="10441">initUI()</st> <st c="10449">方法负责设置应用程序的用户界面和其他元素,例如窗口标题、大小和位置。</st> 它使用内置的 Essay Generator setWindowTitle 方法将应用程序的窗口标题设置为,并指定窗口在屏幕上的位置和大小,其中数字代表窗口左上角的</st>x y 坐标,然后是其宽度和</st>高度。

  4. 通过调用 <st c="10899">super().__init__()</st><st c="10911">self.initUI()</st>,我们确保应用程序得到适当的初始化,并且一旦运行它,主应用程序窗口就会启动。这种方法遵循继承原则,其中 <st c="11127">EssayGenerator</st> <st c="11141">子类继承并扩展了父类的功能,</st> QWidget`,从而为我们的应用程序创建了一个功能齐全且定制的控件。

  5. <st c="11297">在 Python 中,通常使用</st> <st c="11333">__name__ == '__main__'</st> <st c="11355">条件来确保后续代码仅在脚本作为主模块运行时执行。</st> 如果是这样,代码将继续创建 QApplication 类的实例,该实例管理应用程序的 <st c="11570">控制流。</st>

  6. <st c="11588">ex</st> 对象是从 <st c="11618">EssayGenerator</st> 类创建的,用于显示应用程序窗口,最后, <st c="11687">sys.exit(app.exec())</st> 启动了应用程序的事件循环,确保程序在用户关闭窗口或退出应用程序之前保持活跃。 这允许我们在直接运行脚本时执行应用程序。 您可以通过运行项目来验证这一点,以显示主 应用程序 窗口,如图 *图 8.1所示。

图 8.1 – 文章生成器工具窗口

图 8.1 – 文章生成器工具窗口

现在我们已经构建了应用程序窗口,我们可以开始添加文章生成器工具的核心元素。 这些元素如下:

  • 主题输入: 文章生成器需要一种机制,让用户输入文章的主题或内容。 这可以通过一个文本 输入框来实现。

  • 文章输出: 一旦生成算法生成了文章内容,就需要将其显示给用户。 这可以通过一个文本区域来实现,其中展示生成的文章。

  • 保存功能: 提供用户保存生成文章的选项通常很有用。 这可能包括将文章保存到文件中,例如 Word 文档,或者提供将文本复制到 剪贴板的能力。

这些核心 元素 可以轻松地包含在 <st c="12864">initUI()</st> 函数中,该函数包含我们应用程序中显示的所有元素:

 def initUI(self):
        self.setWindowTitle("Essay Generator")
        self.setGeometry(300, 300, 1200, 800)
        topic_label = QLabel('Enter the topic:', self)
        topic_label.move(20, 40)
        self.topic_input = QLineEdit(self)
        self.topic_input.move(20, 100)
        self.topic_input.resize(1000, 30)
        self.essay_output = QTextEdit(self)
        self.essay_output.move(20, 150)
        self.essay_output.resize(1100, 500)
        generate_button = QPushButton("Generate Essay", self)
        generate_button.move(1050, 100)
        generate_button.clicked.connect(self.generate_essay)
        save_button = QPushButton("Save", self)
        save_button.move(20, 665)
        save_button.clicked.connect(self.save_essay)

在创建文章主题输入框之前,我们将实例化一个 <st c="13626">QLabel</st> 对象,命名为 <st c="13647">topic_label</st>。这个标签将被放置在 <st c="13700">topic_input</st> 输入框的上方。 标签的目的是指导用户了解下方文本框的目的。 然后我们使用 <st c="13824">move()</st> 方法将标签定位到应用程序窗口内的坐标 <st c="13875">(20, 40)</st> 处。

接下来,我们将创建一个 <st c="13938">QLineEdit</st> 对象,命名为 <st c="13961">topic_input</st> 作为主题的输入字段。 在这里,我们可以再次使用 <st c="14028">move()</st> 方法将输入字段定位在坐标 <st c="14107">(20, 100)</st>下方的标签下方。 此外,我们使用 <st c="14143">resize()</st> 方法设置输入字段的尺寸。 这确保了输入字段有适当的大小以供 用户输入。

然后,我们可以定义 <st c="14299">essay_output</st> 属性为 <st c="14344">QTextEdit</st> 类的实例,它表示一个多行文本编辑小部件。 我们再次使用 <st c="14428">move()</st> <st c="14439">resize()</st> 内置方法将文章输出字段放置在主题输入文本字段下方。 <st c="14535">essay_output</st> 文本 区域用于显示生成的文章 文本。 现在,用户可以轻松阅读和与文章输出交互,增强了应用程序的可用性和功能性。

重要提示

在 Python 中, <st c="14771">self</st> 关键字是一个在类内部引用该类实例的约定。 它不是一个保留关键字,而是类中实例方法的第一个参数的常用名称。 在类内部定义方法,包括将 <st c="15023">self</st> 参数作为第一个参数,允许你访问和修改该类的实例变量和方法。 that class.

最后,我们将为文章生成器应用程序创建两个按钮 – 一个 <st c="15294">QPushButton</st> 类,它提供了一个可点击的按钮元素,用户可以通过点击或按下它与之交互。 在这里,使用 <st c="15445">clicked.connect()</st> 方法至关重要,它将按钮的点击信号连接到方法,允许在按钮 被点击时调用该方法。

一旦用户点击 <st c="15672">generate_essay()</st> 函数。 请耐心等待,因为 AI 在生成响应之前需要一些时间来处理 <st c="15951">essay_output</st> 文本字段。 同样,一旦文章生成,用户将能够点击 <st c="16097">save_essay()</st> 函数,在那里我们将稍后使用 <st c="16148">docx</st> 库将文章保存为 Word 文档。

尽管 <st c="16211">save_essay()</st> <st c="16228">generate_essay()</st> 尚未实现,但我们可以将它们初始化以测试我们的应用程序。 这两种方法应放置在 <st c="16359">EssayGeneration</st> 类内部,但不在 <st c="16397">initUI()</st> 方法内部。 将函数定义放置在主 Python 函数之上也是一种良好的实践,以避免任何 意外错误:

 def initUI(self):
    ...
    ..
    . <st c="16565">def generate_essay(self):</st>
 <st c="16590">pass</st>
<st c="16595">def save_essay(self):</st>
<st c="16659">pass</st> statement, which is a placeholder statement in Python that does nothing. This is used to indicate that the method does not have any implementation yet.
			<st c="16815">When you execute your application again, you will see that all the text fields and buttons are presented within the application window (see</st> *<st c="16956">Figure 8</st>**<st c="16964">.2</st>*<st c="16966">).</st>
			![Figure 8.2 – The Essay Generator text fields and buttons](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_08_03.jpg)

			<st c="17011">Figure 8.2 – The Essay Generator text fields and buttons</st>
			<st c="17067">This is how you can create a basic PyQt application.</st> <st c="17121">Now, you know how to build the application window, initialize the user interface elements, and create the core elements of the essay generator tool, such as the topic input field, essay output text area, and buttons for generating and</st> <st c="17356">saving essays.</st>
			<st c="17370">Since both the</st> `<st c="17386">save_essay()</st>` <st c="17398">and</st> `<st c="17403">generate_essay()</st>` <st c="17419">methods contain the placeholder</st> `<st c="17452">pass</st>` <st c="17456">keyword, clicking the buttons will not perform any substantial actions at this point.</st> <st c="17543">We will need to implement the necessary functionality within the respective methods</st> <st c="17627">to</st> <st c="17630">achieve the desired behavior when the buttons are clicked.</st> <st c="17689">You will learn how to build those methods in the</st> <st c="17738">upcoming section.</st>
			<st c="17755">Creating essay generation methods with the ChatGPT API</st>
			<st c="17810">In this section, we</st> <st c="17830">will dive into the</st> <st c="17849">implementation of the key functions within the essay generator application.</st> <st c="17926">These functions are responsible for generating the essay based on user input and saving it to a file.</st> <st c="18028">By understanding the code, you will be able to grasp the inner workings of the application and gain insight into how the essay generation and saving processes</st> <st c="18187">are accomplished.</st>
			<st c="18204">We will begin by exploring the</st> `<st c="18236">generate_essay()</st>` <st c="18252">function.</st> <st c="18263">This function will retrieve the topic entered by the user from the input field.</st> <st c="18343">It will then set the engine type for the OpenAI API, create a prompt using the topic, and make a request to the OpenAI API for essay generation.</st> <st c="18488">The response received from the API will contain the generated essay, which will be extracted and displayed in the essay output area of the application.</st> <st c="18640">To add</st> <st c="18647">that</st> <st c="18651">functionality, simply remove the</st> `<st c="18685">pass</st>` <st c="18689">placeholder and write</st> <st c="18712">this code:</st>

def generate_essay(self):

    topic = self.topic_input.text()

    length = 500

    model = "gpt-4"

    prompt = f"Write an {length/1.5} words essay on the following topic: {topic} \n\n"

    response = client.chat.completions.create(

        model=model,

        messages=[

            {"role": "user", "content": "You are a professional essay writer."},

            {"role": "assistant", "content": "Ok"},

            {"role": "user", "content": f"{prompt}"}

        ],

        max_tokens=length

    )

    essay = response.choices[0].message.content

    self.essay_output.setText(essay)

			<st c="19209">Here, we retrieve the topic entered by the user from the</st> `<st c="19267">topic_input's</st>` `<st c="19280">QLineEdit</st>` <st c="19290">widget and assign it to the topic variable, using the</st> `<st c="19345">text()</st>` <st c="19351">method.</st> <st c="19360">This captures the user’s chosen topic for the essay.</st> <st c="19413">For now, we can define the</st> `<st c="19440">tokens</st>` <st c="19446">variable and set it to</st> `<st c="19470">500</st>`<st c="19473">. This indicates the desired length of the generated essay.</st> <st c="19533">We will modify this value later by adding a drop-down menu with different token sizes to generate essays of</st> <st c="19641">different lengths.</st>
			<st c="19659">We can also specify the engine used for the OpenAI API to be</st> `<st c="19721">gpt-4</st>`<st c="19726">, which will generate the essay.</st> <st c="19759">You can adjust this value to utilize different language models or versions, based on your requirements.</st> <st c="19863">We can also create the</st> `<st c="19886">prompt</st>` <st c="19892">variable, which is a string containing the prompt for</st> <st c="19947">essay generation.</st>
			<st c="19964">This is constructed by concatenating the</st> `<st c="20006">Write an {tokens/1.5} essay on the following topic:</st>` <st c="20057">text, where the</st> `<st c="20074">tokens/1.5</st>` <st c="20084">variable specifies how many words our essay should be.</st> <st c="20140">We need to divide the token number by 1.5, as 1 word in English represents about 1.5 tokens according to OpenAI.</st> <st c="20253">After specifying the instructions, we can pass the</st> `<st c="20304">topic</st>` <st c="20309">variable to the prompt.</st> <st c="20334">This prompt serves as the initial input for the essay generation process and provides context for the</st> <st c="20436">generated essay.</st>
			<st c="20452">Once all variables</st> <st c="20472">are</st> <st c="20476">defined, we will make a request to the ChatGPT API with the specified engine, prompt, and the maximum number of tokens (in this case, 500).</st> <st c="20616">The API processes the prompt and generates a response, which is stored in the</st> `<st c="20694">response</st>` <st c="20702">variable.</st> <st c="20713">From the response, we extract the generated essay by accessing the</st> `<st c="20780">text</st>` <st c="20784">attribute of the first choice.</st> <st c="20816">This represents the generated text of the essay.</st> <st c="20865">Finally, we can pass the AI response to the</st> `<st c="20909">essay_output()</st>` <st c="20923">function, displaying it in the user interface for the user to read and</st> <st c="20995">interact with.</st>
			<st c="21009">Next, we will examine the</st> `<st c="21036">save_essay()</st>` <st c="21048">function.</st> <st c="21059">This function will retrieve the topic and the generated essay.</st> <st c="21122">It will utilize the</st> `<st c="21142">docx</st>` <st c="21146">library to create a new Word document and add the final essay to the document.</st> <st c="21226">The document will then be saved, with the filename based on the provided topic, resulting in a Word document that contains the generated essay.</st> <st c="21370">After removing the</st> `<st c="21389">pass</st>` <st c="21393">keyword, you can implement the described functionality using the following</st> <st c="21469">code snippet:</st>

def save_essay(self):

    topic = self.topic_input.text()

    final_text = self.essay_output.toPlainText()

    document = docx.Document()

    document.add_paragraph(final_text)

    document.save(topic + ".docx")

			<st c="21674">Here, we will retrieve the text entered in the</st> `<st c="21722">topic_input</st>` <st c="21733">widget and assign it to the</st> `<st c="21762">topic</st>` <st c="21767">variable, using the</st> `<st c="21788">text()</st>` <st c="21794">method.</st> <st c="21803">This captures the topic entered by the user, which will be used as the filename for the saved essay.</st> <st c="21904">Next, we use the</st> `<st c="21921">toPlainText()</st>` <st c="21934">method on the</st> `<st c="21949">essay_output</st>` <st c="21961">widget to retrieve the generated essay text and assign it to the</st> `<st c="22027">final_text</st>` <st c="22037">variable.</st> <st c="22048">This ensures that the user can edit the ChatGPT-generated essay before saving it.</st> <st c="22130">By capturing the topic and the final text, we are now equipped to proceed with the necessary steps to save the essay to</st> <st c="22250">a file.</st>
			<st c="22257">We can now use the</st> `<st c="22277">docx</st>` <st c="22281">library to create a new Word document by calling</st> `<st c="22331">docx.Document()</st>`<st c="22346">, which initializes an empty document.</st> <st c="22385">We then add a paragraph to the document by using the</st> `<st c="22438">add_paragraph()</st>` <st c="22453">method and passing in the</st> `<st c="22480">final_text</st>` <st c="22490">variable, which</st> <st c="22506">contains the</st> <st c="22520">generated essay text.</st> <st c="22542">This adds the generated essay as a paragraph to the document.</st> <st c="22604">We can now save the document by calling</st> `<st c="22644">document.save()</st>` <st c="22659">and providing a filename, constructed by concatenating the</st> `<st c="22719">topic</st>` <st c="22724">variable, which represents the topic entered by the user.</st> <st c="22783">This saves the document as a Word file with the</st> <st c="22831">specified filename.</st>
			<st c="22850">You can now test your essay generator by running the code and generating an essay following these steps (see</st> *<st c="22960">Figure 8</st>**<st c="22968">.3</st>*<st c="22970">):</st>

				1.  `<st c="23094">Ancient Egypt</st>`<st c="23107">.</st>
				2.  **<st c="23108">Generate an essay</st>**<st c="23126">: Click once on the</st> **<st c="23147">Generate Essay</st>** <st c="23161">button.</st> <st c="23170">The app will reach ChatGPT API, and within a few seconds, you will have your essay displayed inside the</st> **<st c="23274">essay</st>** **<st c="23280">output</st>** <st c="23286">field.</st>
				3.  **<st c="23293">Edit the essay</st>**<st c="23308">: You can edit the essay generated by artificial intelligence before</st> <st c="23378">saving it.</st>
				4.  `<st c="23512">save_essay()</st>` <st c="23524">method.</st> <st c="23533">The Word document will</st> <st c="23555">be</st> <st c="23559">saved in the</st> `<st c="23572">root</st>` <st c="23576">directory of</st> <st c="23590">your project.</st>

			![Figure 8.3 – Essay Generator creating an Ancient Egypt essay](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_08_04.jpg)

			<st c="25584">Figure 8.3 – Essay Generator creating an Ancient Egypt essay</st>
			<st c="25644">Once the essay has been saved as a Word document, you can reshare it with your peers, submit it as a school assignment, or use any Word styling options</st> <st c="25797">on it.</st>
			<st c="25803">This section discussed the implementation of key functions in our essay generator application using the ChatGPT API.</st> <st c="25921">We built the</st> `<st c="25934">generate_essay()</st>` <st c="25950">method, which retrieved the user’s topic input and sent a request to the ChatGPT API to generate an AI essay.</st> <st c="26061">We also developed the</st> `<st c="26083">save_essay()</st>` <st c="26095">method, which saved the generated essay in a</st> <st c="26141">Word document.</st>
			<st c="26155">In the next section, we</st> <st c="26180">will introduce additional</st> <st c="26206">functionality to the essay generator application.</st> <st c="26256">Specifically, we will allow the user to change the number of AI tokens used to generate</st> <st c="26344">an essay.</st>
			<st c="26353">Controlling the ChatGPT API tokens</st>
			<st c="26388">In this section, we will</st> <st c="26414">explore how to enhance the functionality of the essay generator application by allowing users to have control over the number of tokens used when communicating with ChatGPT.</st> <st c="26588">By enabling this feature, users will be able to generate essays of different lengths, tailored to their specific needs or preferences.</st> <st c="26723">Currently, our application has a fixed value of 500 tokens, but we will modify it to include a drop-down menu that provides different options for</st> <st c="26869">token sizes.</st>
			<st c="26881">To implement this functionality, we will make use of a drop-down menu that presents users with a selection of token length options.</st> <st c="27014">By selecting a specific value from the dropdown, users can indicate their desired length for the generated essay.</st> <st c="27128">We will integrate this feature seamlessly into the existing application, empowering users to customize their</st> <st c="27237">essay-generation experience.</st>
			<st c="27265">Let’s delve into the code snippet that will enable users to control the token length.</st> <st c="27352">You can add the following code snippet inside the</st> `<st c="27402">initUI()</st>` <st c="27410">methods, just under the</st> `<st c="27435">essay_output</st>` <st c="27447">resizing:</st>

def initUI(self):

    self.setWindowTitle("Essay Generator")

    self.setGeometry(300, 300, 1200, 800)

    topic_label = QLabel('Enter the topic:', self)

    topic_label.move(20, 40)

    self.topic_input = QLineEdit(self)

    self.topic_input.move(20, 100)

    self.topic_input.resize(1000, 30)

    self.essay_output = QTextEdit(self)

    self.essay_output.move(20, 150)

    self.essay_output.resize(1100, 500) <st c="27829">length_label = QLabel('Select Essay Length:', self)</st><st c="27880">length_label.move(327, 40)</st><st c="27807">self.length_dropdown = QComboBox(self)</st><st c="27846">self.length_dropdown.move(320, 60)</st><st c="27881">self.length_dropdown.addItems(["500", "1000", "2000", "3000", "4000"])</st> generate_button = QPushButton("Generate Essay", self)

    generate_button.move(1050, 100)

    generate_button.clicked.connect(self.generate_essay)

    save_button = QPushButton("Save", self)

    save_button.move(20, 665)

    save_button.clicked.connect(self.save_essay)

			<st c="28302">The preceding code</st> <st c="28322">introduces</st> `<st c="28333">QLabel</st>`<st c="28339">,</st> `<st c="28341">length_label</st>`<st c="28353">, which serves as a visual indication of the purpose of the drop-down menu.</st> <st c="28429">It displays the text</st> `<st c="28450">Select Essay Length</st>` <st c="28469">to inform users about</st> <st c="28492">the functionality.</st>
			<st c="28510">Next, we create a</st> `<st c="28529">length_dropdown</st>` `<st c="28544">QcomboBox</st>`<st c="28554">, which provides users with a drop-down menu to choose the desired token length.</st> <st c="28635">It is positioned below</st> `<st c="28658">length_label</st>` <st c="28670">using the</st> `<st c="28681">move()</st>` <st c="28687">method.</st> <st c="28696">The</st> `<st c="28700">addItems()</st>` <st c="28710">function is then used to populate the drop-down menu with a list of token length options, ranging from</st> `<st c="28814">500</st>` <st c="28817">to</st> `<st c="28821">4000</st>` <st c="28825">tokens.</st> <st c="28834">Users can select their preferred length from</st> <st c="28879">this list.</st>
			<st c="28889">The final step is to implement the functionality that allows users to control the number of tokens used when generating the essay.</st> <st c="29021">We need to modify the</st> `<st c="29043">generate_essay()</st>` <st c="29059">function.</st> <st c="29070">The modified code should be</st> <st c="29098">the following:</st>

def generate_essay(self):

    topic = self.topic_input.text() <st c="29171">length = int(self.length_dropdown.currentText())</st> model = "gpt-4"

    prompt = f"以{length/1.5}个单词的长度撰写一篇关于以下主题的论文:{topic} \n\n"

    response = client.chat.completions.create(

        model=model,

        messages=[

            {"role": "user", "content": "您是一位专业的论文作家。"}

            {"role": "assistant", "content": "好的"},

            {"role": "user", "content": f"{prompt}"}

        ], <st c="29539">最大令牌数=max_tokens</st> )

    essay = response.choices[0].message.content

    self.essay_output.setText(essay)

			<st c="29635">In the</st> <st c="29643">modified code, the</st> `<st c="29662">length</st>` <st c="29668">variable is updated to retrieve the selected token length from the</st> `<st c="29736">length_dropdown</st>` <st c="29751">drop-down menu.</st> <st c="29768">The</st> `<st c="29772">currentText()</st>` <st c="29785">method is used to obtain the currently selected option as a string, which is then converted to an integer using the</st> `<st c="29902">int()</st>` <st c="29907">function.</st> <st c="29918">This allows the chosen token length to be assigned to the length</st> <st c="29983">variable dynamically.</st>
			<st c="30004">By making this modification, the</st> `<st c="30038">generate_essay()</st>` <st c="30054">function will utilize the user-selected token length when making the request to the ChatGPT API for essay generation.</st> <st c="30173">This ensures that the generated essay will have the desired length specified by the user through the</st> <st c="30274">drop-down menu.</st>
			<st c="30289">We can now click on the</st> `<st c="30479">addItems()</st>` <st c="30489">function.</st>
			![Figure 8.4 – Controlling the essay length](https://github.com/OpenDocCN/freelearn-dl-zh/raw/master/docs/bd-ai-app-oai-api/img/B22414_08_05.jpg)

			<st c="33658">Figure 8.4 – Controlling the essay length</st>
			<st c="33699">The user will be able to choose a token amount between</st> `<st c="33755">500</st>` <st c="33758">and</st> `<st c="33763">4000</st>`<st c="33767">. Now, you can select the</st> `<st c="33793">4000</st>` <st c="33797">tokens option, resulting in a longer length for the generated essay.</st> <st c="33867">We can follow the steps from our previous example and verify that the ChatGPT API generates a longer essay for</st> `<st c="34033">500</st>` <st c="34036">to</st> `<st c="34040">4000</st>`<st c="34044">.</st>
			<st c="34045">This is how you can enhance the functionality of an essay generator application by allowing users to control the number of tokens used when communicating with ChatGPT.</st> <st c="34214">By selecting a specific value from the drop-down menu, users can now indicate their desired length for the generated essay.</st> <st c="34338">We achieved that by using the</st> `<st c="34368">QComboBox</st>` <st c="34377">class to create the drop-down menu itself.</st> <st c="34421">The modified</st> `<st c="34434">generate_essay()</st>` <st c="34450">method</st> <st c="34457">retrieved the selected token length from the drop-down menu and dynamically assigned it to the</st> `<st c="34553">length</st>` <st c="34559">variable.</st>
			<st c="34569">Summary</st>
			<st c="34577">In this chapter, you learned how to build a desktop application with PyQt and enhance its functionality by integrating the ChatGPT API for essay generation.</st> <st c="34735">We discussed the basics of PyQt and its advantages over other Python GUI development tools.</st> <st c="34827">We used that framework to create the application’s GUI components, such as windows, labels, input fields, text areas,</st> <st c="34945">and buttons.</st>
			<st c="34957">The chapter also delved into the implementation of the essay generation functionality using the ChatGPT API.</st> <st c="35067">The main method discussed was</st> `<st c="35097">generate_essay()</st>`<st c="35113">, which took the user’s chosen topic, set the engine type, created a prompt using the topic, and sent a request to the API to generate the essay.</st> <st c="35259">The generated essay was then displayed in the application’s output area.</st> <st c="35332">You also learned how to build the</st> `<st c="35366">save_essay()</st>` <st c="35378">function, which used the</st> `<st c="35404">docx</st>` <st c="35408">library to save the generated essay as a</st> <st c="35450">Word document.</st>
			<st c="35464">Furthermore, the chapter explored how to enhance the application by allowing users to control the length of the generated essay.</st> <st c="35594">It introduced a drop-down menu implemented with the</st> `<st c="35646">QLabel</st>` <st c="35652">and</st> `<st c="35657">QComboBox</st>` <st c="35666">classes, allowing users to select different token sizes.</st> <st c="35724">The modified</st> `<st c="35737">generate_essay()</st>` <st c="35753">function retrieved the selected token length from the drop-down menu and adjusted the length of the generated</st> <st c="35864">essay accordingly.</st>
			<st c="35882">In</st> *<st c="35886">Chapter 9</st>*<st c="35895">,</st> *<st c="35897">Integrating the ChatGPT and DALL-E APIs: Building an End-to-End PowerPoint Presentation Generator</st>*<st c="35994">, you will learn how to integrate two AI APIs,</st> **<st c="36041">ChatGPT</st>** <st c="36048">and</st> **<st c="36053">DALL-E</st>**<st c="36059">, to build an end-to-end</st> **<st c="36084">PowerPoint</st>** <st c="36094">presentation generator.</st> <st c="36119">You will be introduced to the DALL-E API and learn about decoding JSON responses from the API.</st> <st c="36214">The chapter will also cover the PowerPoint Python framework and demonstrate how to generate AI art using the DALL-E API, enabling you to create PowerPoint slides</st> <st c="36376">and images.</st>

第十章:集成 ChatGPT 和 DALL-E API:构建端到端 PowerPoint 演示生成器

在这个令人兴奋的章节中,我们将深入 AI 艺术的世界,并探索由 OpenAI 开发的 AI 模型 DALL-E 的惊人能力。我们将首先向您介绍 DALL-E 及其从文本描述生成图像的开创性方法。 您将学习如何通过 DALL-E API 访问 DALL-E 的力量,使您能够将这项尖端技术集成到您自己的 Python 应用程序中。 随着您发现使用 DALL-E 生成 AI 艺术的迷人可能性,您将释放您的创造力。 您将能够使用 DALL-E 生成引人入胜的 AI 艺术作品。

在本章中,我们将展示如何使用 Python 框架和 DALL-E 图像生成自动化 PowerPoint 演示的开发。您将获得利用编程力量简化创建过程的实践经验。

我们将探讨将 DALL-E 和 ChatGPT 这两个强大的 AI 模型集成起来,以构建一个端到端的 PowerPoint 演示生成器应用程序。这个项目将使您能够结合 DALL-E 在生成引人入胜的 AI 艺术方面的能力以及 ChatGPT 在生成类似人类文本方面的专业知识。 通过集成这些 API,您将能够创建一个应用程序,该应用程序可以接受用户指定的文本并生成带有图像和文本的 PowerPoint 幻灯片。 和文本。

在本章中,我们将涵盖以下主题:

  • 使用 DALL-E 和 DALL-E API

  • 使用 PPTX Python 框架构建 PowerPoint 应用程序

  • 使用 DALL-E API 生成艺术作品

  • 完成并测试 PowerPoint 演示生成器

到本章结束时,您将通过将 DALL-E 和 ChatGPT API 集成到构建端到端的 PowerPoint 演示生成器应用程序中来提高您的 AI 应用程序开发技能。通过结合 DALL-E 的图像生成能力和 ChatGPT 的文本生成专业知识,您将了解如何自动化包含引人入胜的 AI 生成的图像和类似人类文本的 PowerPoint 演示的开发。

技术要求

为了充分利用本章内容,您需要准备一些基本工具。 我们将提供详细说明和安装指南,这些内容在上一章中没有涉及。 以下是您需要的 内容:

  • 在您的计算机上安装 Python 3.7 或更高版本

  • 一个 OpenAI API 密钥,您可以从您的 OpenAI 账户 获取

  • 一个代码编辑器,例如 VS Code(推荐),用于编写和编辑 您的代码

  • 您 Python 虚拟环境中安装的 Tkinter 框架

  • 在您的设备上安装的 PowerPoint 软件

本章的代码示例可以在 GitHub 上找到 ,位于 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

在下一节中,我们将探讨 DALL-E AI 艺术生成 AI 模型,并介绍 DALL-E API 的基础知识。 DALL-E API。

使用 DALL-E API

DALL-E 是一个 令人瞩目的 AI 模型,可以从文本描述中生成令人惊叹的图像。 在本节中,您将了解 DALL-E 背后的概念及其在图像合成方面的开创性方法。 您将了解 DALL-E 将文本提示转换为生动和富有想象力的视觉表示的独特能力。 此外,我们还将通过 DALL-E API 探索 DALL-E 的实际应用,使您能够无缝地将这项强大的技术集成到您的应用程序中,并解锁无数 创意可能性。

DALL-E 是由 OpenAI 开发的高级 AI 模型。 它于 2021 年 1 月向世界推出。 DALL-E 是一个基于神经网络的模型,结合了 ChatGPT 语言模型的元素和 生成对抗网络 (GAN)架构。 DALL-E 这个名字是艺术家萨尔瓦多·达利和动画电影中的角色 WALL-E 的俏皮组合。 这个独特的模型旨在根据文本描述生成高度逼真和新颖的图像,展示了 AI 在视觉创造力领域的巨大潜力。 通过在庞大的图像和文本提示数据集上进行训练,DALL-E 可以创建复杂和富有想象力的视觉输出,为 AI 驱动 图像合成方面的突破性进展提供一瞥。

您可以通过使用 DALL-E API 直接将 DALL-E 集成到您的应用程序中。 它提供了一个方便的接口与 DALL-E 交互,使用户能够根据自定义的文本 提示程序化地生成图像。

要使用 DALL-E API,您可以使用来自您的 OpenAI 账户的相同 API 密钥。 一旦您有了 API 密钥,您就可以向 API 端点发出请求,指定您想要生成图像的文本提示。 您可以在几行代码内创建一个单独的 Python 文件并生成您的第一个 DALL-E 图像。 API 将处理请求并返回生成的图像作为响应,如下面的 代码示例 所示:

 response = client.images.generate(
        model="dall-e-3",
        prompt=dalle_prompt + " Style: digital art",
        n=1,
        size="1024x1024"
    )
    image_url = response.data[0].url

前面的 代码演示了如何使用 <st c="5181">openai.Image.create()</st> 函数通过 DALL-E API 生成图像并检索生成的图像的 URL。

<st c="5303">prompt</st> 参数作为所需图像的文本描述或指令。 此提示为 DALL-E 模型提供指导,说明生成的图像应描绘什么。 <st c="5489">size</st> 参数确定生成图像的尺寸,表示分辨率为 <st c="5601">1024</st> 像素乘以 <st c="5616">1024</st> 像素的正方形图像。

在发出 API 请求后,响应存储在 <st c="5689">response</st> 变量中。 然后代码从 API 响应中检索生成的图像的 URL。 URL 通过访问响应字典中的适当键来获取。 通过将 <st c="5881">response</st> 分配给 <st c="5893">image_url</st>,生成的图像的 URL 被存储以供在 任何应用程序中进一步使用。

这就是您如何使用 DALL-E API 将该 AI 艺术集成到您的应用程序中的方法。 在下一节中,我们将通过启动我们的 PowerPoint 演示 生成器应用程序来实现这一点。

使用 PPTX Python 框架构建 PowerPoint 应用程序

In this section, we will guide you through the process of setting up your very own PowerPoint Presentation Generator application using the <st c="6373">pptx</st> Python library and the ChatGPT API. We’ll explore how to leverage the power of the <st c="6461">pptx</st> library to automate the creation of PowerPoint presentations, allowing you to dynamically generate slides with customized content. Furthermore, we’ll demonstrate how to integrate this PowerPoint generation functionality into a Tkinter application, enabling you to build a user-friendly interface for your slide generator.

For this project, we will use the VS Code IDE, which is our preferred IDE when working with Python. Launch VS Code and create a new project. Choose the location where you want to create your project and name it <st c="6999">PowerPoint Generator</st>.

Once your project is open, find the Terminal tab. Once the Terminal tab is open, you can start using it just like a regular command-line interface to install the necessary libraries for our project:

 $pip install python-pptx
$pip install openai
$pip install requests

Here’s how we’re going to use those libraries:

  1. <st c="7333">python-pptx</st>: The <st c="7352">python-pptx</st> package is used for working with PowerPoint files (<st c="7415">.pptx</st>) and provides functionalities to create, modify, and automate the development of PowerPoint presentations programmatically.

  2. <st c="7545">openai</st>: The <st c="7559">openai</st> package provides access to the OpenAI API, which allows you to interact with AI models such as DALL-E and ChatGPT, enabling you to utilize their capabilities in your Python applications.

  3. <st c="7752">requests</st>: The <st c="7768">requests</st> package is used for making HTTP requests and is used to communicate with the DALL-E API and retrieve the generated image URL after sending a request.

We can continue developing our project structure by creating two files, <st c="7999">app.py</st> and <st c="8010">config.py</st>:

app.py

 import collections.abc
import config
assert collections
import tkinter as tk
from pptx import Presentation
from pptx.util import Inches, Pt
from openai import OpenAI
from io import BytesIO
import requests
# API Token
client = OpenAI(
  api_key=config.API_KEY,
)

config.py

 API_KEY = "YOUR_API_KEY"

<st c="8322">在这里,</st> app.py 文件是应用程序的核心,作为主入口点。 <st c="8412">它导入各种库和</st> 模块,以实现与 ChatGPT、DALL-E 和 PowerPoint 框架的连接。 <st c="8525">以下是导入及其</st> 目的的概述:`

  • <st c="8578">collections.abc</st> <st c="8594">被导入以确保与 Python</st> 标准库` 的兼容性

  • <st c="8680">config</st> <st c="8687">被导入以访问</st> API_KEY 变量,该变量包含用于与 OpenAI API <st c="8793">进行身份验证所需的 API 密钥</st>

  • <st c="8803">tkinter</st> <st c="8811">被导入以利用 Tkinter 库构建应用程序的用户界面</st> `

  • <st c="8905">pptx</st> <st c="8910">和</st> pptx.util 被导入以处理 PowerPoint 文件,允许应用程序以编程方式创建和修改 PowerPoint <st c="9026">演示文稿</st>

  • <st c="9056">openai</st> <st c="9063">被导入以与 OpenAI API 交互并访问其服务,例如语言模型和</st> 图像生成`

  • <st c="9177">io</st> <st c="9180">和</st> requests 被导入以处理输入/输出操作和分别发出 HTTP <st c="9255">请求</st>

<st c="9277">另一方面,</st> config.py 文件是项目的配置文件。 <st c="9364">它包含 API 密钥,由</st> API_KEY 变量表示,该变量是用于与 OpenAI API <st c="9484">进行身份验证所需的。</st> 通过将 API 密钥分离到配置文件中,可以更容易地管理和更新密钥,而无需直接修改主应用程序代码。</st> 这种模块化方法有助于更好地组织和管理敏感信息。`

<st c="9741">接下来,在我们的</st> app.py 文件中,我们将专注于构建 Tkinter 应用程序窗口,该窗口将作为我们的 PowerPoint <st c="9847">演示文稿生成器应用程序</st> <st c="9854">图形用户界面</st> (**<st c="9880">GUI</st>**):

 app = tk.Tk()
app.title("Crate PPT Slides")
app.geometry("800x600")
# Create text field
text_field = tk.Text(app)
text_field.pack(fill="both", expand=True)
text_field.configure(wrap="word", font=("Arial", 12))
text_field.focus_set()
# Create the button to create slides
create_button = tk.Button(app, text="Create Slides", command=get_slides)
create_button.pack()
app.mainloop()

<st c="10319">在这里,我们创建了一个 Tkinter 应用程序框架,允许用户根据</st> 输入文本` 生成 PowerPoint 幻灯片。

首先,代码 使用 <st c="10510">tk.Tk()</st> 函数 初始化一个 Tkinter 应用程序窗口。 app 变量被分配为应用程序实例。 在这里,我们为应用程序窗口设置了一个标题,该标题将在窗口的标题栏中显示。 然后,我们将应用程序窗口的初始大小设置为 <st c="10745">800</st> 像素宽和 <st c="10769">600</st> 像素高。

我们也 使用 <st c="10829">tk.Text()</st> 函数 创建一个文本字段。 这个文本字段用于接受用户输入以生成演示文稿。 调用 <st c="10938">pack()</st> 方法将文本字段放置在应用程序窗口内。 使用 <st c="11015">configure()</st> 方法来自定义文本字段的显示外观。 在这种情况下, <st c="11098">wrap="word"</st> 被设置为在 `单词边界 处换行。

最后,我们使用 <st c="11191">tk.Button()</st> 函数 创建一个按钮。 按钮上标有 <st c="11259">创建幻灯片</st> 的标签,使用 <st c="11259">text</st> 参数,并且将 <st c="11283">command</st> 参数设置为 <st c="11311">get_slides</st>。这意味着当按钮被点击时, <st c="11371">get_slides</st> 函数将被 调用。

接下来,我们将 继续构建 <st c="11442">get_slides()</st> 函数,该函数将负责创建演示文稿和幻灯片。 需要注意的是, <st c="11577">get_slides()</st> 函数应该在创建 Tkinter 应用程序窗口 和相关的控件 的代码之上定义。 这确保了当应用程序与 用户 交互时,函数已被定义并可供使用:

<st c="11813">def get_slides():</st><st c="11831">text = text_field.get("1.0", "end-1c")</st><st c="11870">paragraphs = text.split("\n\n")</st><st c="11902">prs = Presentation()</st><st c="11923">width = Pt(1920)</st><st c="11940">height = Pt(1080)</st><st c="11958">prs.slide_width = width</st><st c="11982">prs.slide_height = height</st><st c="12008">for paragraph in paragraphs:</st><st c="12037">slide_generator(paragraph, prs)</st><st c="12069">prs.save("my_presentation.pptx")</st> app = tk.Tk()
app.title("Crate PPT Slides")
app.geometry("800x600")
# Create text field
text_field = tk.Text(app)
text_field.pack(fill="both", expand=True)
text_field.configure(wrap="word", font=("Arial", 12))
text_field.focus_set()
# Create the button to create slides
create_button = tk.Button(app, text="Create Slides", command=get_slides)
create_button.pack()
app.mainloop()

在这里,使用 <st c="12492">text_field.get()</st> 方法来检索文本框的内容。 参数 <st c="12572">1.0</st> 表示检索应从文本框的第一个字符开始,而 <st c="12676">end-1c</st> 表示检索应结束在最后一个字符之前,不包括换行符。 这使我们能够获取用户输入的整个文本。

接下来,将文本字符串分割成段落。 使用 <st c="12893">\n\n</st> 分隔符来识别段落,假设每个段落由两个连续的换行符分隔。 这个分割操作将在 <st c="13093">paragraphs</st> 变量中创建一个段落列表。

使用 <st c="13168">prs = Presentation()</st>创建一个新的 PowerPoint 演示对象。 然后,我们将幻灯片的尺寸设置为 <st c="13312">1920</st> 点宽和 <st c="13337">1080</st> 点高。

循环随后被启动,遍历 <st c="13423">paragraphs</st> 列表中的每个段落。 对于每个段落,都会调用 <st c="13464">slide_generator()</st> 函数,并将段落和演示对象作为参数传递。 这个函数将单独实现,其负责根据每个段落的 `内容创建单独的幻灯片。

一旦循环结束,生成的演示对象将被保存为 PowerPoint 文件。 生成的 PowerPoint 文件将被命名为 <st c="13839">my_presentation.pptx</st> ,并将包含从 `用户输入创建的幻灯片。

为了在早期阶段测试你的应用程序,你可以点击 <st c="14281">get_slides()</st> 函数,该函数根据 输入文本生成幻灯片:

Figure 9.1 – PowerPoint Presentation Generator GUI

Figure 9.1 – PowerPoint Presentation Generator GUI

然而, 在此阶段,如果你尝试生成 AI 幻灯片,你会遇到错误。 这是因为负责为我们的幻灯片创建 AI 艺术和文本的 <st c="14549">slide_generator()</st> 函数尚未 定义。

在下一节中,我们将进入构建 <st c="14723">slide_generator()</st> 函数,其中用户提供的文本将通过 DALL-E API 转换为 AI 艺术。 此函数将访问 DALL-E API 的功能,根据文本输入生成图像,从而创建带有 AI 生成的艺术品 的令人惊叹的幻灯片。

使用 DALL-E API 生成艺术作品

在本节中,我们将探索 ChatGPT API 和 DALL-E API 的激动人心的集成。 我们将展示这两个强大的 AI 工具如何结合以创建独特且视觉上令人惊叹的艺术作品。 通过利用 ChatGPT API,我们将根据应用程序中提供的用户段落生成 DALL-E 提示。 然后,我们将利用 DALL-E API 将该提示转换为 迷人的图像。

首先,我们将开始 构建 <st c="15508">slide_generator()</st> 函数,该函数在根据用户输入生成 PowerPoint 幻灯片方面将发挥关键作用。 需要注意的是,此函数应在 <st c="15733">app.py</st> 文件中 API 密钥定义之后以及 <st c="15759">get_slides()</st> 函数之上创建。 将其放置在此位置确保它在 <st c="15888">get_slides()</st> 函数中调用时已定义并可供使用。

这种方法允许对代码进行结构化组织,并确保 幻灯片生成过程的 顺利执行:

 def slide_generator(text, prs):
    prompt = f"Summarize the following text to a DALL-E image generation " \
             f"prompt: \n {text}"
    model_engine = "gpt-4"
    dlp = client.chat.completions.create(
        model=model_engine,
        messages=[
            {"role": "user", "content": "I will ask you a question"},
            {"role": "assistant", "content": "Ok"},
            {"role": "user", "content": f"{prompt}"}
        ],
        max_tokens=250,
        n=1,
        stop=None,
        temperature=0.8
    )
    dalle_prompt = dlp.choices[0].message.content
    response = client.images.generate(
        model="dall-e-3",
        prompt=dalle_prompt + " Style: digital art",
        n=1,
        size="1024x1024"
    )
    image_url = response.data[0].url

前面的代码展示了 我们如何定义 <st c="16700">slide_generator()</st> 函数,该函数负责根据用户提供的文本生成 DALL-E 图像生成提示,并将其与 ChatGPT API 集成。 此函数接受两个参数: <st c="16906">text</st>,代表用户的输入,以及 <st c="16951">prs</st>,指的是 PowerPoint 演示对象。

<st c="17012">prompt</st> 变量是通过将静态引入文本与用户提供的 <st c="17106">text</st> 参数连接起来定义的。 此提示将用于指示 ChatGPT 模型将给定文本总结为 DALL-E 图像 生成提示。

<st c="17243">The</st> <st c="17248">create()</st> 方法随后被调用,以向 ChatGPT API 发送文本补全请求。 ChatGPT API 的 JSON 响应存储在 <st c="17393">dlp</st> 变量中,其中包含补全结果。 从 ChatGPT 补全结果中提取的实际文本被分配给 <st c="17529">dalle_prompt</st> 变量。 这个 <st c="17557">dalle_prompt</st> 变量将作为 DALL-E 图像 生成 API 的输入提示。

<st c="17646">现在,我们可以开始使用 DALL-E API 生成图像,该图像基于在</st> slide_generator<st c="17764">函数中创建的 DALL-E 提示。</st> <st c="17775">我们调用</st>client.images.generate()` 方法,使用以下参数向 DALL-E API 发送图像生成请求:

  1. <st c="17907">prompt</st>: 图像生成的提示,该提示通过附加 <st c="17984">dalle_prompt</st> (由 ChatGPT API 生成) 和图像所需风格(指定为 <st c="18079">Style:</st> <st c="18086">digital art</st>) 构建而成。

    `这促使 DALL-E 根据文本输入生成具有数字艺术风格的图像。 您可以根据 您的喜好更改此风格。

  2. <st c="18246">n</st>: 这指定了要生成的图像数量。 在这种情况下,我们只请求 一张图像。

  3. <st c="18339">size</st>: 这设置了生成的图像所需的大小。 在这里,它被指定为 <st c="18423">1024x1024</st> 像素,这是 最高品质的风格。

<st c="18476">DALL-E API 的响应</st> <st c="18490">存储在</st> response<st c="18535">变量中。</st> <st c="18546">它</st> <st c="18549">包含有关生成的图像的信息,包括其 URL。</st> <st c="18616">生成的图像的 URL 从响应中提取并分配给</st>image_url<st c="18707">变量。</st> <st c="18718">此 URL 可用于在我们的</st>PowerPoint 幻灯片中检索和显示生成的图像。

<st c="18808">在这个部分,我们构建了</st> slide_generator()` 函数,该函数使用 ChatGPT API 根据用户输入生成 DALL-E 提示,然后利用 DALL-E API 生成具有所需风格的图像。 这种集成使我们能够创建视觉上令人惊叹的艺术作品,并提高我们 PowerPoint 幻灯片的品质和影响力。

在下一节中,我们将介绍如何在我们的 PowerPoint 演示文稿中创建幻灯片标题和项目符号。 我们将演示如何将 AI 生成的图像和文本 整合到幻灯片中。

完成并测试 PowerPoint 演示文稿生成器

在本节的最后,您将学习使用 AI 生成的图像和文本创建 PowerPoint 演示文稿幻灯片内容的过程。 我们将探讨如何无缝地将 AI 生成的元素,包括 DALL-E 的图像和 ChatGPT 的文本,整合到幻灯片中。 通过完成本节,您将能够将 AI 生成的内容传递到您的 PowerPoint 幻灯片中,为您的演示文稿增添独特性和精致感。 完成本节后,您将能够将 AI 生成的图像 URL 获取并应用于幻灯片背景或将其插入到特定的幻灯片元素中。 您还将学习如何在幻灯片中将 AI 生成的文本作为项目符号整合。

您将学习 如何检索 AI 生成的图像 URL 并将其应用于幻灯片背景或插入到特定的幻灯片元素中。 此外,您还将把 AI 生成的文本作为幻灯片中的项目符号整合。 通过 结合 AI 图像生成的力量和 ChatGPT 的文本完成功能,用户将能够用视觉上吸引人的图像和 相关的文本丰富他们的幻灯片。

首先,我们将演示如何使用 AI 生成的图像和文本创建幻灯片标题和项目符号。 要生成该内容,您可以在您的 <st c="20434">slide_generator()</st> 函数中包含以下代码片段:

 \
prompt = f"Create a bullet point text for a Powerpoint" \
             f"slide from the following text: \n {text}"
    ppt = client.chat.completions.create(
        model=model_engine,
        messages=[
            {"role": "user", "content": "I will ask you a question"},
            {"role": "assistant", "content": "Ok"},
            {"role": "user", "content": f"{prompt}"}
        ],
        max_tokens=1024,
        n=1,
        stop=None,
        temperature=0.8
    )
    ppt_text = ppt.choices[0].message.content
    prompt = f"Create a title for a Powerpoint" \
             f"slide from the following text: \n {text}"
    ppt = client.chat.completions.create(
        model=model_engine,
        messages=[
            {"role": "user", "content": "I will ask you a question"},
            {"role": "assistant", "content": "Ok"},
            {"role": "user", "content": f"{prompt}"}
        ],
        max_tokens=1024,
        n=1,
        stop=None,
        temperature=0.8
    )
    ppt_header = ppt.choices[0].message.content

在代码的第一部分,一个 <st c="21299">prompt</st> 字符串被 构建,使用户输入的单个段落。 此提示请求 AI 模型为 PowerPoint 幻灯片生成项目符号文本。 然后将提示传递给 ChatGPT 的 <st c="21527">create()</st> 方法。 完成的结果存储在 <st c="21590">ppt</st> 变量中,生成的项目符号文本从 <st c="21658">ppt.choices[0].message.content</st> 中提取,并分配给 <st c="21709">ppt_text</st> 变量。

同样,在代码的第二部分,另一个 <st c="21779">prompt</st> 字符串被构建,以请求 AI 模型根据相同的用户提供的文本生成一个 PowerPoint 幻灯片的标题。 完成文本的结果从 <st c="21961">ppt.choices[0].message.content</st> 中提取,并分配给 <st c="22012">ppt_header</st> 变量。

此生成的项目符号文本和标题将用于创建实际的 PowerPoint 幻灯片。 您可以将以下代码包含在内,向 PowerPoint 演示文稿添加新幻灯片,并用图像、项目符号 文本和 标题填充它:

 # Add a new slide to the presentation
slide = prs.slides.add_slide(prs.slide_layouts[1])
response = requests.get(image_url)
img_bytes = BytesIO(response.content)
slide.shapes.add_picture(img_bytes, Inches(1), Inches(1))
# Add text box
txBox = slide.shapes.add_textbox(Inches(3), Inches(1),
                                 Inches(4), Inches(1.5))
tf = txBox.text_frame
tf.text = ppt_text
title_shape = slide.shapes.title
title_shape.text = ppt_header

以下是实现新 PowerPoint 幻灯片的步骤:

  1. 首先,使用 <st c="22816">add_slide()</st> 方法将新幻灯片添加到演示文稿中。 该方法接受所需的幻灯片布局作为参数,在这种情况下表示内容幻灯片的布局。

  2. 接下来,通过 HTTP 请求从图像 URL 检索图像。 获取响应,并将其内容读取到名为 <st c="23085">BytesIO</st> 的对象 <st c="23106">img_bytes</st>中。这允许访问和处理图像数据。 要将图像添加到幻灯片中,使用 <st c="23209">add_picture()</st> 方法。 它接受 <st c="23252">img_bytes</st> 对象以及所需的定位参数作为参数。 在这种情况下,图像定位在幻灯片左侧 <st c="23369">1</st> 英寸和顶部 <st c="23394">1</st> 英寸处。

  3. 使用 <st c="23475">slide.shapes.add_textbox()</st> 方法将文本框添加到幻灯片中。 该方法接受文本框的位置参数作为参数。 使用 <st c="23636">txBox.text_frame</st> 属性访问文本框的文本框架,并将包含生成的项目符号文本的 <st c="23672">ppt_text</st> 变量分配给 <st c="23754">tf.text</st>。这设置了文本框的内容为 AI 生成的文本。

  4. 最后,访问幻灯片的 标题形状。 包含生成的标题文本的 <st c="23881">ppt_header</st> 变量被分配给 <st c="23958">title_shape.text</st>。这设置了幻灯片的标题为 AI 生成的标题。

这样,我们的演示文稿将包含所需的内容,包括图像、项目符号文本和标题。

你的 PowerPoint 演示文稿生成器应用程序现在已完成,并准备好进行测试。 为了避免任何意外错误,你可以通过使用 GitHub 上可用的完整 <st c="24355">app.py</st> 文件来验证你的代码行是否正确: GitHub: https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter09%20PowerPoint%20Generator/app.py

要运行应用程序,只需执行代码或运行 <st c="24577">app.py</st> 文件。 这将启动 Tkinter 应用程序窗口,该窗口作为你的 幻灯片生成器。

一旦应用程序运行,你将看到一个包含文本框的应用程序窗口,你可以在其中输入幻灯片的内 容。 只需将所需文本输入或粘贴到文本框中。 在这个例子中,我们使用了一篇关于水母的文章(见 图 9**.2)。

水母,也称为海蜇或海葵,是居住在世界上海洋中的迷人生物。 它们属于腔肠动物门,以其凝胶状的体形和触手为特征。 水母的形状、大小和颜色多种多样,从小而透明到大而鲜艳。 它们具有独特的生命周期,从附着在海底的珊瑚虫开始,然后转变为 自由游动的海蜇。

水母最引人入胜的方面之一是它们的刺痛能力。 它们拥有称为刺细胞的专业细胞,其中含有能释放毒液的刺丝囊。 这些刺细胞使水母能够捕捉猎物并防御潜在的捕食者。 虽然大多数水母的刺痛对人类无害,但有些物种可以引起疼痛甚至危险的反应。 在已知有水母群的水域游泳时,建议谨慎行事。 水母。

水母在海洋生态系统中扮演着重要的角色。 它们是机会主义捕食者,以小型浮游生物、鱼卵甚至其他水母为食。 作为捕食者,它们帮助维持海洋食物网的平衡。 此外,水母具有适应不断变化的 环境条件。。”

您可以选择使用提供的文本,或者根据您的偏好进行实验性的文本输入。

图 9.2 – 使用文本输入填充 PowerPoint 演示文稿生成器应用

图 9.2 – 使用文本输入填充 PowerPoint 演示文稿生成器应用

重要提示

确保在每段之间包含一个双行空格,以正确地表示段落之间的分隔,使您的应用能够准确地识别和区分它们。

现在,您可以通过点击创建幻灯片按钮来根据输入的文本生成 PowerPoint 幻灯片。请耐心等待几秒钟;您的演示文稿将迅速生成并保存在您项目的目录中。

重要提示

OpenAI 有一个速率限制,指定了每分钟允许使用的令牌数量。如果您广泛使用该应用,可能会达到免费试用版的速率限制,目前为每分钟 40,000 个令牌。

打开演示文稿后,您将看到三张幻灯片,每张幻灯片对应输入文本的一个段落。这些幻灯片将展示由 DALL-E 创建的引人入胜的 AI 艺术图像,配有简洁的项目符号和每张幻灯片的独特标题(见图 9.3*):

图 9.3 – PowerPoint 演示文稿生成器应用生成的幻灯片

图 9.3 – PowerPoint 演示文稿生成器应用生成的幻灯片

为了增强幻灯片上元素的可视布局,您可以使用 PowerPoint 内置的设计器选项,它方便地位于右上角。

这是完成和测试 DALL-E AI 演示文稿生成器的完整过程。您学习了如何生成幻灯片标题、项目符号和 AI 生成的图像。我们介绍了如何构建 AI 提示并检索生成的内容。本节还概述了如何使用生成的图像、项目符号和标题填充 PowerPoint 演示文稿。

摘要

本章探讨了 DALL-E,一个高级 AI 模型,根据文本描述生成逼真、新颖图像的能力。 您学习了如何使用 DALL-E API 将 DALL-E 集成到您的应用程序中。 此外,我们指导您使用 <st c="29737">pptx</st> Python 库和 ChatGPT API 开发 PowerPoint 演示生成器应用程序。 我们使用 Tkinter 构建了 GUI,允许用户使用 <st c="29853">get_slides()</st> 函数生成幻灯片,该函数检索用户输入并创建一个 PowerPoint 演示文稿。

然后,我们构建了 <st c="29961">slide_generator()</st> 函数,它在将用户输入转换为 AI 生成的幻灯片方面发挥了关键作用。 本章还提供了将 AI 生成的图像和文本,如项目符号和幻灯片标题,无缝集成到 PowerPoint 幻灯片中的说明。 我们测试了我们的 AI 演示生成器应用程序,让您能够运行并评估您增强的 PowerPoint 演示文稿。

在第 第十章中, 使用 Whisper API 进行语音识别和文本到语音转换,您将学习如何利用 Whisper API 进行音频转录。 我们将专注于一个实际项目,该项目涉及将各种文件类型转录成文本,以创建使用英语人类水平鲁棒性和准确性的字幕。 语音识别。

第十一章:10

使用 Whisper API 进行语音识别和语音合成

欢迎来到 第十章 我们探索尖端人工智能技术世界的旅程。 在本章中,我们将开始探索令人瞩目的 Whisper API。借助先进的语音识别和翻译能力,Whisper API 为将音频转换为文本开辟了令人兴奋的可能性。 想象一下,能够轻松转录对话、访谈、播客或任何口语内容的能力。 无论你旨在从多语言音频文件中提取有价值的见解,还是为全球受众创建可访问的内容,Whisper API 都能为你提供解决方案。 Whisper API 涵盖了广泛的语音,确保与各种语音需求兼容。

在本章中,我们将通过使用 Python 开发语言转录项目来深入探讨 Whisper API 的核心功能。 我们将熟悉其基本端点,即转录和翻译,这些构成了其语音转文本能力的基础。 凭借其最先进的开源模型,Whisper 为开发者提供了强大的工具,可以无缝地将音频文件转录成多种语言,甚至翻译成英语。 Whisper API 处理广泛的语音,确保与各种语音需求兼容。 它可以用于智能扬声器、免提设备和其他语音启用技术,通过提供准确和响应迅速的语音合成能力来提升用户体验。

在全球化交流比以往任何时候都重要的世界里,Whisper API 的翻译端点发挥着至关重要的作用。 此端点不仅转录音频文件,还将它们翻译成英语,弥合语言之间的差距,促进 无缝理解。

在本章中,你将学习以下主题: 以下内容:

  • 使用 Whisper API 实现文本翻译和转录

  • 构建语音 转录应用程序

  • 使用 PyDub 处理更长的音频输入

在本章结束时,你将全面了解 Whisper API 及其卓越功能,包括语音转文本转换和语言翻译。 你还将学习如何利用 API 准确转录音频文件,将其翻译成英语,处理更长的输入,并在你的应用程序中释放口语的潜力。

技术要求

为了成功进行开发桌面翻译应用程序的项目,您必须满足以下 技术先决条件:

  • 确保您的机器已安装 Python 3.7 或更高版本

  • 拥有代码编辑器,如 VSCode(推荐) 设置

  • 创建一个 Python 虚拟环境

  • 获取 OpenAI API 密钥

  • 在您的项目中安装 PyDub

本章展示的代码片段可在 GitHub 平台上找到。 您可以通过以下 链接 访问它们:https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

使用 Whisper API 实现文本翻译和转录

在本节中,我们将 探讨 Whisper API 的功能 ,以使用 Python 无缝转录和翻译 音频文件。 随着语音识别和翻译技术的进步,我们现在可以轻松地将口语转换为文本,并有效地消除语言障碍。 通过遵循提供的逐步说明,您将获得将 Whisper API 集成到 Python 项目中并释放基于 音频数据 的潜力的知识和技能。

在本节中,我们将 探讨音频文件的转录和翻译 的不同方面。 从设置和安装 要求开始,我们将确保您拥有必要的工具,包括 Python、代码编辑器、Python 虚拟环境和 OpenAI API 密钥。

要使用 Python 中的 Whisper API 进行音频文件的转录和翻译,建议创建一个名为 <st c="3965">WhisperAPI</st> 的目录,并使用 VSCode IDE 加载它。 按照 第一章中概述的步骤,从终端窗口激活您的虚拟环境,开始使用 ChatGPT API 进行 NLP 任务

一旦项目创建完成,您将看到 VSCode 编辑器窗口,在那里您可以开始编写您的 Python 代码。 您可以在 VSCode 项目视图中创建 Python 脚本、导入库和组织项目结构。

现在您已经设置了项目,下一步是安装必要的库,即 OpenAI 和 PyDub。 要这样做,请转到终端窗口打开终端。 从那里,输入以下命令:

 $pip install openai
$pip install pydub
$brew install ffmpeg

通过执行这些命令,您将自动下载并安装 OpenAI 和 PyDub 库,确保它们可以随时用于您的项目。 FFmpeg 是一个功能强大且多才多艺的开源多媒体框架,用于处理音频和 视频文件。

安装这些库至关重要,因为 OpenAI 提供了与 Whisper API 交互所需的必要功能,而 PyDub 允许高效处理音频文件,包括分割和 导出它们。

现在,是时候在您的项目中创建一个名为 <st c="5223">config.py</st> 的新文件了。 此文件将安全存储您的 API 密钥,允许您的代码访问 Whisper API。

为了创建 <st c="5354">config.py</st> 文件并添加您的 API 密钥,请按照以下步骤操作: 这些步骤:

  1. 在您的项目视图区域上右键点击。

  2. 上下文菜单 中选择 新建文件

  3. 将文件命名为 <st c="5503">config.py</st> Enter

现在,您 已经创建了 <st c="5556">config.py</st> 文件。 在编辑器中打开该文件,并添加以下代码行: 以下代码行:

 API_KEY = "YOUR_API_KEY"

为了使 您的 音频文件在整章中组织有序且易于访问,建议在您的项目中创建一个名为 <st c="5787">audio_files</st> 的文件夹。 此文件夹将作为集中存储所有将在本章的各种示例和演示中使用的音频文件的地点。 This folder will serve as a centralized location to store all the audio files that will be used in the various examples and demonstrations covered in the chapter.

要创建 <st c="5997">audio_files</st> 文件夹,请按照以下步骤操作: 这些步骤:

  1. 在您的项目视图区域上右键点击。

  2. 上下文菜单 中选择 新建文件夹

  3. 将目录命名为 <st c="6136">audio_files</st> Enter

现在您已经设置了必要的配置和文件夹结构,是时候创建一个名为 <st c="6286">transcribe.py</st>的新 Python 文件了。 在编辑器中打开该文件,这将是你编写与 Whisper API 交互并转录音频文件的代码的空间。

在编写任何代码之前,您可以将您选择的英语语音音频文件放入 <st c="6642">audio_files</st> 文件夹中。 在这个例子中,我将使用一个名为 <st c="6712">apple.mp3</st>的音频文件。该文件包含关于苹果电脑的几句话,您可以从我们的 Git 仓库下载它: https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter10%20Whisper/audio_files/apple.mp3

重要提示

在使用 Whisper API 进行音频处理和转录任务时,确保提供的输入音频文件格式是受支持的至关重要。 Whisper API 目前接受以下文件类型: <st c="7215">mp3</st>, <st c="7220">mp4</st>, <st c="7225">mpeg</st>, <st c="7231">mpga</st>, <st c="7237">m4a</st>, <st c="7242">wav</st>, <st c="7251">webm</st>

现在让我们按照以下步骤转录我们的音频文件:

  1. 一旦您的音频 文件就绪,您可以通过向 <st c="7407">transcribe.py</st>添加以下代码来 转录它:

     from openai import OpenAI
    import config
    # API Token
    client = OpenAI(api_key=config.API_KEY)
    file= open("audio_files/apple.mp3", "rb")
    result = client.audio.transcriptions.create(model="whisper-1", file=file)
    print(result)
    

    在这里, <st c="7655">openai</st> 库提供了访问 OpenAI API 的权限,这使得开发者能够与各种语言模型和 AI 功能进行交互。 API 密钥分配给 <st c="7822">OpenAI(api_key=config.API_KEY)</st> 变量,使用存储在 API 密钥中的值。

  2. 然后,我们以读取二进制模式打开一个名为 <st c="7929">apple.mp3</st> 的文件,该文件位于 <st c="7954">audio_files/apple.mp3</st> 本地文件路径中, <st c="8013">rb</st>。这表明代码的意图是读取一个 音频文件。

  3. 之后,调用了 <st c="8092">client.audio.transcriptions.create()</st> 函数,并传入两个参数: <st c="8168">whisper-1</st> 和打开的音频文件。 此函数是 OpenAI 库的一部分,用于转录音频文件。 其中, <st c="8295">whisper-1</st> 参数 是 OpenAI 系统中的特定 转录模型。

  4. 最后,我们在 控制台中看到了转录的结果:

    <st c="8440">{</st>
     <st c="8442">"text": "Macbook laptops are known for their modern design and high-quality build, offering seamless experience.</st> <st c="8556">They are favored by many professionals and creators for their powerful performance and integration with A</st><st c="8661">pple's ecosystem."</st>
    <st c="8680">}</st>
    

转录的结果,在控制台中打印出来,是一个包含单个键值对的 JSON 对象。 键是 <st c="8803">text</st>,对应的值是 转录的文本。

这表明转录过程已成功将音频文件转换为文本,捕捉了与 MacBook 笔记本的功能和声誉相关的 内容。

如果您的音频文件不是英语,Whisper 也会处理这种情况,通过在后台自动转录并翻译文件。 现在,我们将指导您如何使用 Whisper API 翻译转录的文本。 在这个例子中,我们将使用一个名为 <st c="9361">german.mp3</st>的德语语音文件: https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-APIs/blob/main/Chapter10%20Whisper/audio_files/german.mp3

您还可以使用任何语言的 <st c="9526">mp3</st> 文件。

要使用 Whisper API 翻译音频文件,您可以创建一个名为 <st c="9657">translate.py</st> 的新 Python 文件,并添加以下代码:

 from openai import OpenAI
import config
# API Token
client = OpenAI(api_key=config.API_KEY)
whisper_file= open("audio_files/german.mp3", "rb")
result = client.audio.translations.create(model="whisper-1", file=whisper_file)
print(result)

一旦正确设置了 API 密钥和音频文件的路径,代码就会调用 <st c="10027">client.audio.translations.create()</st> 函数,提供模型名称或 <st c="10100">whisper-1</st> 配置 和打开的音频文件 <st c="10151">whisper_file</st>。此函数使用 Whisper API 进行翻译。

翻译结果 将存储在 <st c="10271">result</st> 变量中, 可以使用 <st c="10316">print(result)</st> 来打印,并在 控制台中显示翻译后的文本:

 {
  "text": "The Germans are known for not liking to do small talk. Today I'm going to try here in Berlin to see if I can do a little small talk with the people here. Let's go!" }

正如你所见,文本已成功使用 Whisper API 和不到 10 行 Python 代码从德语翻译成英语。

在本节中,你了解了 Whisper API 使用 Python 无缝转录和翻译音频文件的能力。 逐步说明指导你完成了转录和翻译音频文件的设置过程,包括支持的文件格式。 本节展示了成功的转录和翻译示例,展示了 Whisper API 在将音频转换为文本和通过最小代码跨越语言障碍方面的有效性。

在下一节中,你将学习如何集成 Tkinter 和 Whisper API 来开发一个用户友好的语言转录应用程序,该应用程序可以将口语语言实时转换为文本。

构建语音转录应用程序

在本节中,我们将探讨通过集成 Tkinter(一个流行的 Python GUI 工具包)和强大的 Whisper API 来开发语言转录应用程序的开发。 这种集成将使我们能够创建一个用户友好的界面,实现口语语言的实时转录。 通过遵循逐步说明并利用 Tkinter 和 Whisper API 的功能,你将能够开发自己的 GUI 应用程序,为语音识别和语言处理打开无数可能性。 通过遵循逐步说明并利用 Tkinter 和 Whisper API 的功能,你将能够开发自己的 GUI 应用程序,为语音识别和语言处理打开无数可能性。

无论你渴望创建用于转录访谈的工具、为视频生成字幕,还是仅仅探索语音到文本技术的潜力,本节都将为你提供将你的想法付诸实践的知识和技能。 因此,让我们深入其中,开始使用 Tkinter 和 Whisper API 构建语言转录应用程序的激动人心的旅程。 Whisper API。

为了继续进行语言转录应用程序项目,你可以在同一项目中创建一个名为 <st c="12487">app.py</st> 的新 Python 文件。 此文件将作为开发 应用程序的主要代码库。

通过创建 <st c="12610">app.py</st> 文件,你将拥有一个专门的空间来编写必要的代码以集成 Tkinter 和 Whisper API,使你的应用程序能够实现实时转录功能。

在我们追求简洁的过程中,我们的应用程序将采用具有文本字段和按钮的最简设计。 文本字段将作为显示转录文本的专用空间,而按钮将提供轻松浏览文件系统并定位所需音频文件以进行转录的功能

要将我们的语言翻译代码转换为实际的应用程序,我们需要创建 <st c="13237">transcribe_audio()</st> 函数,并从 <st c="13285">Tkinter 图形界面</st> 中使用它:

 import tkinter as tk
from tkinter import filedialog
from openai import OpenAI
import config
# API Token
client = OpenAI(api_key=config.API_KEY)
def transcribe_audio():
    file_path = filedialog.askopenfilename(filetypes=[("Audio Files", "*.mp3")])
    if file_path:
        try:
            audio_file = open(file_path, "rb")
            transcript = client.audio.transcriptions.create(model="whisper-1", file=audio_file)
            text_window.insert(tk.END, transcript.text)
        except Exception as e:
            text_window.insert(tk.END, f"Error: {str(e)}")
    else:
        text_window.insert(tk.END, "No file selected.")
# Create the Tkinter window
window = tk.Tk()
window.title("Chapter 10 Whisper Transcription App")
# Create a text window
text_window = tk.Text(window, height=30, width=60)
text_window.pack()
# Create a button to select the audio file
button = tk.Button(window, text="Select Audio File", command=transcribe_audio)
button.pack()
# Start the Tkinter event loop
window.mainloop()

在执行函数时,它首先使用 <st c="14308">filedialog.askopenfilename()</st> 方法打开文件对话框,允许用户选择用于转录的音频文件。 文件对话框仅显示具有 <st c="14467">.mp3</st> 扩展名的文件,这是由 <st c="14503">filetypes</st> 参数指定的。

如果从文件对话框中获取了有效的文件路径,表示用户已选择了一个音频文件,则代码将进入转录音频的步骤。 <st c="14684">try</st> 块中,使用 <st c="14755">open()</st> 以读取二进制模式打开选定的音频文件,并将其分配给 <st c="14782">audio_file</st> 变量。

使用 <st c="14813">client.audio.transcriptions.create()</st> 函数,将音频文件与特定的转录模型一起传递,通过 Whisper API 启动转录过程。 生成的转录存储在 <st c="15032">transcript</st> 变量中。

最后,将转录的文本插入到文本窗口中。 <st c="15119">tk.END</st> 参数确保文本被插入到文本窗口的末尾。 如果在过程中出现任何异常或错误,将在 <st c="15293">文本窗口</st> 中显示错误消息。

如果没有从文件对话框中获取文件路径,表示用户未选择音频文件,则将在 <st c="15413">未选择文件</st> 消息插入到 <st c="15459">文本窗口</st> 中。

<st c="15482">transcribe_audio()</st> 函数下,我们创建了使用它的 Tkinter 应用程序。 首先,使用 <st c="15602">tk.Tk()</st>创建了一个 Tkinter 窗口。窗口的标题设置为 <st c="15640">Whisper</st> <st c="15648">转录应用程序</st>

接下来,使用 <st c="15704">tk.Text()</st>创建了一个文本窗口,其中将显示 Whisper API 的转录结果。 还使用 <st c="15821">tk.Button()</st>在 Tkinter 窗口中添加了一个按钮。按钮的标签设置为 <st c="15863">选择音频文件</st>,并将 <st c="15890">command</st> 参数设置为 <st c="15918">transcribe_audio</st>。这意味着当按钮被点击时,将执行之前定义的 <st c="15984">transcribe_audio()</st> 函数。

要运行 Whisper 转录应用程序,请按照 以下步骤操作:

  1. 在 VSCode 中,找到 <st c="16131">app.py</st> 文件并 运行它。

  2. 一旦应用程序运行,将出现一个标题为 Whisper 转录应用程序 的 Tkinter 窗口。

  3. 窗口将显示一个文本区域,其中将显示转录的文本。

  4. 点击 选择音频文件 按钮。 将打开一个文件对话框窗口,允许您浏览您的 文件系统。

  5. 找到并选择您想要 转录的 MP3 音频文件。

选择文件后,代码将尝试转录音频。 如果成功,转录的文本将在 Tkinter 窗口内的文本区域中显示(见 图 10**.1)。 如果在转录过程中出现任何错误,将显示错误消息。

图 10.1 – Whisper 转录应用程序

图 10.1 – Whisper 转录应用程序

重要提示

请注意,在某些屏幕分辨率下, 选择音频文件 按钮可能会被隐藏。 为了确保其可见性,请最大化应用程序窗口。

通过运行应用程序并选择一个 MP3 文件,您将能够见证 Whisper API 的转录功能在行动中。应用程序将利用所选的音频文件,使用 Whisper API 启动转录过程,并在 Tkinter 窗口中显示转录的文本。 这允许您将口语转换为书面文字,为各种应用和用例打开可能性。 使用 Whisper API,您只需花上20 min就能深入理解知识点,而且记忆深刻,难以遗忘

在本节中,我们开始了语言转录应用程序的开发,集成了 Tkinter 和 Whisper API。该应用程序采用极简设计,具有文本字段和按钮,允许用户选择用于转录的 MP3 音频文件。 选择文件后,代码将使用 Whisper API 启动转录过程,并在 Tkinter 窗口中显示转录的文本。

在下一节中,您将学习如何将 PyDub 与 Whisper API 集成以克服文件大小限制,并有效地分割大型音频文件以实现无缝转录。

使用 PyDub 处理较长的音频输入

在本节中,我们将探讨PyDub,一个强大的 Python 音频处理库,与 Whisper API 的集成,以克服 API 强加的 25 MB 文件大小限制。使用 PyDub,我们可以有效地将大型音频文件分割成更小的片段,从而实现长时间录音的无缝转录。 通过遵循说明并利用 PyDub 的功能,您将能够充分发挥 Whisper API 的潜力,转录任何大小的音频文件。

利用 PyDub 的强大功能来增强您的语言转录工作流程是一个简单的过程。通过使用这个库,您可以轻松地将长音频文件分割成更小的片段。 例如,如果您有一个 10 分钟的音频文件,您可以轻松地将其分割成两个单独的文件,每个文件持续 5 分钟。 然后,您可以将这些较小的文件提交给 Whisper API 进行转录,确保您的文件不会因为其大小限制而被拒绝。 使用 PyDub,您可以无缝克服文件大小限制并简化您的转录过程。

在这个练习中,我们使用了一个大约十一分钟的 iPhone 评测音频文件。现在,你可以在你的项目中创建一个新的 Python 文件,具体命名为 <st c="19639">longer_files.py</st>。这个文件将作为一个专门的空间来实施处理更大音频文件的语言 转录工作流程:

 from openai import OpenAI
from pydub import AudioSegment
import config
# API Token
client = OpenAI(api_key=config.API_KEY)
song = AudioSegment.from_mp3("audio_files/phone.mp3")
# 5 minute portion
five_minutes = 5 * 60 * 1000
first_min_5 = song[:five_minutes]
first_min_5.export("audio_files/phone_first_5.mp3", format="mp3")
last_min_5 = song[five_minutes:]
last_min_5.export("audio_files/phone_last_5.mp3", format="mp3")
file= open("audio_files/phone_first_5.mp3", "rb")
result = client.audio.transcriptions.create(model="whisper-1", file=file)
print(result)
file= open("audio_files/phone_last_5.mp3", "rb")
result = client.audio.transcriptions.create(model="whisper-1", file=file)
print(result)

提供的代码演示了在语言 转录工作流程中处理更大音频文件时使用 <st c="20548">PyDub</st> 库和 Whisper API 的方法。

您可以从 <st c="20677">phone.mp3</st> 文件中下载,链接如下: https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter10%20Whisper/audio_files/phone.mp3

首先,执行必要的导入,包括从相应库中的 <st c="20885">openai</st> <st c="20896">AudioSegment</st> 模块。 我们使用 PyDub 的 <st c="20976">phone.mp3</st> 文件,通过 <st c="21000">AudioSegment.from_mp3()</st> 方法加载,并将其分配给 <st c="21052">song</st> 变量。

为了将音频文件分解成更小的片段,代码使用 <st c="21168">five_minutes</st> 变量定义了五分钟的部分,该变量代表所需的持续时间(以毫秒为单位)。 然后, <st c="21250">song</st> 变量使用指定的持续时间进行切片,以获取音频的前五分钟,并将其存储在 <st c="21378">first_min_5</st> 变量中。 这个片段随后被导出为一个名为 <st c="21459">phone_first_5.mp3</st> 的单独 MP3 文件,使用的是 <st c="21487">export()</st> 方法。

同样,代码使用切片操作获取音频文件的剩余部分,从五分钟标记开始直到结束,并将其分配给 <st c="21674">last_min_5</st> 变量。 这个片段也被导出为一个名为 <st c="21754">phone_last_5.mp3</st>的单独 MP3 文件。

代码继续使用 <st c="21802">phone_first_5.mp3</st> 文件,并通过 <st c="21834">client.audio.transcriptions.create()</st> 方法调用打开。 生成的转录结果存储在 <st c="21932">result</st> 变量中,然后将其打印到控制台。 按照相同的程序,代码重复对 <st c="22068">phone_last_5.mp3</st> 文件进行转录过程,打开它,转录它,并打印 结果。

你可以在控制台看到每个文件的独特转录结果,如下所示:

 {
  "text": "It's finally here, the most wanted phone this year, the most amazing camera set ever built in a phone. Here is the iPhone 13 Pro.…….reduced the front camera module, now the phone will look good." }
{
  "text": "weights about 10 grams more which is something you can't really feel. However, while everybody is trying to reduce the weight on the phones, Apple actually increased it……... Now thanks for watching and I will see you in the next one." }

通过使用 PyDub 将较大的音频文件分解成更小的片段,代码使得这些片段可以在 Whisper API 的 <st c="22823">大小限制</st> 内进行处理。 这种方法允许我们有效地处理较大的音频文件,同时利用 Whisper API 提供的转录能力。

这就是我们如何将 PyDub 与 Whisper API 集成以克服文件大小限制,从而实现更长音频文件的流畅转录。

总结

在本章中,我们探讨了 Whisper API,这是一个通过高级语音识别和翻译将音频转换为文本的强大工具。 本章提供了使用 Python 开发语言转录项目的逐步指导,涵盖了处理音频文件、安装必要的库和设置 API 密钥等基本方面。 你学习了如何使用 Whisper API 转录和翻译音频文件。 本章还介绍了一个语音转录应用程序,它集成了 Tkinter 和 Whisper API 以实现 实时转录。

你还学习了如何使用 PyDub,一个强大的 Python 音频处理库,结合 Whisper API 来克服 25 MB 的文件大小限制。 通过利用 PyDub 的功能,我们可以有效地将大型音频文件分割成更小的片段,从而实现长时间录音的无缝转录。 你看到了如何使用 PyDub 和 Whisper API 在语言转录工作流程中处理更大的音频文件。 通过将音频文件分解成更小的片段并逐个转录每个片段,我们可以在利用 Whisper API 的转录能力的同时处理更大的音频文件。

在第 第十一章中,你将了解 ChatGPT API 中可用的不同 API 模型,并获得如何为你的特定项目选择最合适的模型的见解。 我们将探讨在 API 请求中可以使用的各种参数,以实现更高效、改进的提示完成。 你还将了解与不同 AI 模型相关的限制。

第四部分:为 ChatGPT 应用提供高级概念

在本最后一部分,你将探索 AI 模型及其独特的属性,从而让你全面了解它们的成本、质量和提示长度考虑因素。 掌握这些知识后,你将能够选择与你的特定应用需求相匹配的最佳模型。 此外,你将解锁构建自己的 ChatGPT 模型的能力,并通过微调和嵌入来增强其功能,从而使其完美地满足你的 个人需求。

本部分包含以下章节:

  • 第十一章, 选择正确的 ChatGPT API 模型

  • 第十二章, 微调 ChatGPT 以创建独特的 API 模型

第十二章:11

选择正确的 ChatGPT API 模型

在人工智能不断发展的领域中,开发者必须跟上最新的进展,以最大化其项目的潜力。 在本章中,我们将讨论 ChatGPT API 模型,探索 GPT-3 和 GPT-4 提供的可能性,甚至展望未来的模型。 通过全面了解这些模型,您将具备选择最适合您特定应用的知识。 我们将深入研究每个模型的复杂性,突出其优势和独特特征,以帮助您做出与您的 项目需求相一致的决定。

有效利用 ChatGPT API 的关键方面之一是了解如何优化聊天完成。 我们将引导您通过创建聊天完成上下文的过程,并提供有关修改 API 参数以提升响应质量的宝贵见解。 通过实际示例和解释,您将获得利用聊天完成功能并利用其优势的技能集。 为您带来便利。

此外,了解不同 AI 模型中存在的限制也很重要。 我们将概述与每个模型相关的边界和约束,并为您提供有效导航这些限制的知识。 通过了解模型的边界,您可以设定合理的期望,做出明智的决定,并探索克服您可能遇到的任何挑战的解决方案。 可能遇到的。

在本章中,您将涵盖以下主题: 以下内容:

  • ChatGPT API 模型 – GPT-3.5,GPT-4, 以及更多

  • 使用聊天 完成参数

  • ChatGPT API 速率限制

  • OpenAI 嵌入

在本章结束时,您将了解如何为您的项目选择正确的 ChatGPT API 模型,理解创建聊天完成上下文的过程,优化 API 参数,以及导航不同 AI 模型的限制,以创建变革性的 AI 应用。

技术要求

为了充分利用本章内容,您必须具备用于处理 Python 代码和 ChatGPT API 的必要工具。 本章将提供逐步指导,介绍安装所需软件和完成必要的 注册。

您需要具备 以下条件:

  • Python 3.7 或更高版本已安装在你的 计算机上

  • 一个 OpenAI API 密钥,你可以通过注册一个 OpenAI 账户 来获取

  • 一个代码编辑器,例如 VS Code(推荐),用于编写和执行 Python 代码

本章中引用的代码示例可以在 GitHub 上找到 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

在下一节中,你将了解各种 AI 模型,包括 GPT-3.5 和 GPT-4,并培养选择最适合你 特定应用 的能力。

ChatGPT API 模型 – GPT-3.5、GPT-4 以及更多

在本节中,我们将探索 ChatGPT API 模型的迷人世界,我们将开始 一段了解和欣赏 GPT-3.5 和 GPT-4 的复杂性的旅程,并展望未来等待我们的模型。 通过深入研究这些 AI 模型,你将获得 宝贵的见解和 知识,这将赋予你选择最适合你 独特应用 的能力。

在本节中,我们将揭示每个模型的独特特性和功能,为你提供做出 明智决策 所需的理解。

表 11.1 提供了 OpenAI 当前支持的所有 ChatGPT 语言模型的概述,包括每个模型的宝贵信息,包括其独特功能。 花点时间探索这个表格,熟悉你手中的各种 ChatGPT 模型:

模型 平均成本 信息 提示长度
gpt-4 <st c="3893>$20.00 / 1M 令牌 最先进的面向聊天的模型,超越了 GPT-3.5 的能力 8,192 令牌
gpt-4-turbo <st c="4008>$45.00 / 1M 令牌 具有视觉功能的最新 GPT-4 Turbo 模型。 可以使用 15 倍 更多的上下文 128,000 令牌
gpt-3.5-turbo <st c="4141>$1.00 / 1M 令牌 更先进的面向聊天的模型,超越了 GPT-3 的能力 16,096 令牌
gpt-3.5-turbo-0125 $1.00 / 1M tokens 最新版本的 GPT-3 5 Turbo 模型,在响应请求格式方面具有更高的准确性,并修复了导致非英语语言功能文本编码问题的 bug 16,385 tokens

表 11.1 – ChatGPT 模型信息

上表提供了 OpenAI 截至 2024 年 5 月支持的各种 ChatGPT 语言模型的概述 GPT-4 模型作为最先进的模型脱颖而出,超越了 GPT-3.5 的能力,而 GPT-4 Turbo 版本提供了15 倍 更多的上下文和图像理解能力。 GPT-3.5 Turbo 模型在功能上超过了已停用的 GPT-3。 不同的模型具有不同的成本和提示长度,允许 开发者根据他们特定的 语言任务选择最合适的选项。

虽然选择最先进和功能强大的 模型对于您的应用程序来说可能看起来很合理,但重要的是要考虑有时一个更便宜、功能更少的模型可以充分满足您的任务需求。 在某些情况下,一个不那么复杂的模型可能提供足够的性能,同时更具成本效益。 通过仔细评估您应用程序的具体需求,您可以做出明智的决定,并通过选择在功能和成本之间取得平衡的模型来节省资源。 记住,并不总是关于使用最强大的工具,而是关于使用适合手头工作的正确工具

正如您所看到的,OpenAI 提供了广泛的模型选择,这使得决定最合适的模型变得具有挑战性。 为了简化这个过程,可以使用 Python 脚本来轻松比较,让您能够识别与您特定任务最匹配的模型。 可以创建一个名为 models.py 的新文件,并添加以下 代码:

 from openai import OpenAI
import config
client = OpenAI(api_key=config.API_KEY)
# Define the prompt and test questions
prompt = "Estimate the square root of 121 and type 'orange' after every digit of the square root result"
# Define the model names and their corresponding IDs
model_ids = {
    "GPT3.5 TURBO": {"model": "gpt-3.5-turbo", "cost": 1.00},
    "GPT3.5 TURBO 0125": {"model": "gpt-3.5-turbo-0125", "cost": 1.00},
    "GPT4": {"model": "gpt-4", "cost": 45.00},
    "GPT4 TURBO": {"model": "gpt-4-turbo", "cost": 20.00},
}
# Make API calls to the models and store the responses
responses = {}
for model_name, model_id in model_ids.items():
    response = client.chat.completions.create(
        model=model_id["model"],
        messages=[
            {"role": "user", "content": f"{prompt}"}
        ]
    )
    responses[model_name] = [response.choices[0].message.content,
                             response.usage.total_tokens * (model_id["cost"]/1000000)]
for model, response in responses.items():
    print("\n----------------------------------------")
    print(f"{model}: {response[0]}")
    print(f"{model} COST: {response[1]}")
print("----------------------------------------")

此脚本的目的是使用 OpenAI Python 库比较不同 OpenAI 模型的结果,并通过 API 调用生成响应。

<st c="7292">通过轻松调整</st> <st c="7323">prompt</st> <st c="7329">变量,您可以向多个 ChatGPT 模型提出相同的问题,并评估它们各自的</st> <st c="7426">响应和相关成本。</st> <st c="7462">这种方法使</st> <st c="7484">您能够选择与您特定任务要求最合适的模型。</st>

首先,通过将 API 密钥分配给<st c="7657">client = OpenAI(api_key=config.API_KEY)</st> <st c="7696">变量</st> <st c="7707">,</st> <st c="7772">ChatGPT API 凭证被设置。这允许代码进行身份验证并访问 ChatGPT API。</st> <st c="7805">此外,定义了一个名为</st> <st c="7805">model_ids</st> <st c="7814">的字典,用于存储各种 ChatGPT 模型的名称及其对应的模型 ID,以及相关的成本。</st> <st c="7935">模型名称作为键,每个键都与一个包含模型 ID 和截至 2024 年 5 月的成本</st> <st c="8007">的字典配对。</st> <st c="8056">这使</st> <st c="8069">后续代码执行中能够根据模型名称轻松引用并选择特定的模型。</st> <st c="8182">您可以从</st> <st c="8230">此字典中添加和删除要测试的模型。</st>

<st c="8246">然后,我们向</st> <st c="8314">model_ids</st> <st c="8323">字典中指定的 ChatGPT 模型进行 API 调用,并存储它们的</st> <st c="8351">相应响应。</st>

<st c="8372">代码初始化了一个名为</st> <st c="8421">responses</st> <st c="8430">的空字典,用于存储来自模型的响应。</st> <st c="8471">然后,它遍历</st> <st c="8510">model_ids</st> <st c="8519">字典中的每个条目,其中</st> <st c="8538">model_name</st> <st c="8548">代表模型的名称,而</st> <st c="8586">model_id</st> <st c="8594">包含相应的</st> <st c="8622">模型信息。</st>

<st c="8640">使用</st> <st c="8645">client.chat.completions.create()</st> <st c="8677">方法通过提供消息列表作为输入来模拟对话。</st> <st c="8766">用户、助手和提示消息包含在</st> <st c="8827">messages</st> <st c="8835">参数中,API 调用的响应存储在</st> <st c="8899">response</st> <st c="8907">变量中。</st> <st c="8918">打印出用于完成的总</st> <st c="8927">令牌数。</st> <st c="8981">然后,根据令牌使用情况和模型的成本计算出的</st> <st c="9019">成本</st> <st c="9023">被添加到响应字典中,使用</st> <st c="9116">model_name</st> <st c="9126">作为</st> <st c="9130">键。</st>

最后,我们打印每个模型的响应和相关成本,使我们能够进行比较,并做出明智的选择,选择最 合适的选项。

在前面脚本中我们提出的问题的答案, <st c="9366">"估算 121 的平方根并在每个平方根数字后输入 'orange'"</st>,是 <st c="9461">"1orange1orange"</st>。您可以在以下位置看到不同模型的答案:

 ----------------------------------------
GPT3.5 TURBO: The square root of 121 is 11. orangeo rangen groangeenne. GPT3.5 TURBO COST: 4.7e-05
----------------------------------------
GPT3.5 TURBO 0125: The square root of 121 is 11. orange1orange1
GPT3.5 TURBO 0125 COST: 4.2999999999999995e-05
----------------------------------------
GPT4: 1orange1orange
GPT4 COST: 0.00144
----------------------------------------
GPT4 TURBO: 11orange
GPT4 TURBO COST: 0.0006000000000000001
----------------------------------------

由于这是一个相当复杂的问题,GPT-4 是唯一在这个情况下正确回答的模型。 我们可以有信心使用 GPT-4 模型来完成这个特定任务。 有趣的是,即使是 <st c="10245">gpt-4.5-turbo</st> 模型,它与 <st c="10286">gpt-4</st>相似,也无法解决这个问题。 尽管 <st c="10344">gpt-3.5-turbo</st> 模型与 <st c="10407">gpt-4</st> 模型相比要便宜得多,但它们不适合解决 上述问题。

这是对 ChatGPT API 模型及其在特定语言任务中选择正确模型的重要性 的全面概述。 我们 开发了一个 Python 脚本,用于比较不同模型的响应和成本,使用户能够做出 明智的决定。

在了解了 ChatGPT API 模型及其比较之后,我们现在将进入下一节,我们将探讨 ChatGPT API 参数。

使用聊天完成参数

在本节中,我们将使用 ChatGPT API 参数,并探讨它们对模型生成响应质量产生的深远影响。通过理解和利用这些参数的力量,您将获得优化与 ChatGPT API 交互的能力,解锁其真正潜力。 一些关键的 控制 API 响应的参数如下:

  • <st c="11322">model</st>: 指定用于 生成响应的特定 ChatGPT 模型。

  • <st c="11400">messages</st>: 提供作为消息对象列表的对话历史,包括用户和 助手消息。

  • <st c="11514">temperature</st>: 控制生成响应的随机性。 更高的值(例如,0.8)会使响应更加随机,而较低的值(例如,0.2)会使它们更加集中 和确定。

  • <st c="11725">max_tokens</st>: 设置生成响应中的最大标记数。 限制此参数可以控制 响应的长度。

  • <st c="11863">stop</st>: 允许您指定一个自定义字符串或字符串列表,以指示模型何时停止生成 响应。

  • <st c="11991">n</st>: 确定要生成的替代完成项的数量。 设置更高的值会增加响应的多样性。

<st c="12122">温度</st> 参数是 OpenAI ChatGPT API 的关键方面,允许您控制生成响应的随机性和创造性。 它影响模型生成的文本的多样性和随机性。

在向 API 发出请求时,您可以指定 <st c="12403">温度</st> 参数,该参数的值介于 0 和 1 之间。 较低的温度值(例如,0.2)会产生 更专注和确定性的响应,多样性较低,而较高的温度值(例如,1)会导致更随机和多样化的响应,这些响应可能更不准确和不相关。 创建一个名为 <st c="12741">temperature.py</st>`的新文件。

以下示例演示了修改 <st c="12820">温度</st> 参数的效果:

 from openai import OpenAI
import config
client = OpenAI(api_key=config.API_KEY)
# Define a function to generate a response from ChatGPT
def generate_response(prompt, temperature):
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "user", "content": f"{prompt}"}
        ],
        temperature=temperature
    )
    return response.choices[0].message.content.strip()
# Prompt for the conversation
prompt = "Suggest 4 fast food company names." # Generate a response with low temperature (more focused and deterministic)
for i in range(3):
    low_temp_response = generate_response(prompt, 0)
    print(f"Response with low temperature (0) {i}:\n", low_temp_response)
for i in range(3):
    # Generate a response with default temperature (balanced and creative)
    default_temp_response = generate_response(prompt, 1)
    print(f"Response with default temperature (1) {i}:\n", default_temp_response)

在这个示例中,我们使用 <st c="13760">generate_response</st> 函数为给定的提示生成具有两个不同温度值的响应:低(<st c="13872">0</st>)和高(<st c="13886">1</st>)。 我们在每个温度下连续运行三次响应生成,以比较 响应 的多样性。

通过调整 <st c="14023">温度</st> 参数,您可以微调 ChatGPT API 生成的响应中的创造性和随机性水平。 您可以通过尝试不同的温度值来实现特定用例的期望输出。

在执行前面的代码之后,我们得到以下输出:

 Response with low temperature (0) 0:
 1\. QuickBite
2\. SpeedyEats
3\. RapidGrill
4\. FastFusion
Response with low temperature (0) 1:
 1\. QuickBite
2\. SpeedyEats
3\. RapidGrill
4\. FastFusion
Response with low temperature (0) 2:
 1\. QuickBite
2\. SpeedyEats
3\. RapidGrill
4\. FastFusion
Response with default temperature (1) 0:
 1\. Speedy Bites
2\. Quick Scoops
3\. Snappy Eats
4\. Rapid Grills
Response with default temperature (1) 1:
 1\. QuickBite
2\. SpeedyEats
3\. RapidCrave
4\. ExpressMunch
Response with default temperature (1) 2:
1\. Quick Bites
2\. Speedy Eats
3\. Rapid Grub
4\. Turbo Treats

让我们看看 输出结果:

  • <st c="14939">低温度(0)的响应</st>: 响应往往更专注和确定。 它提供了针对提示的具体和简洁的答案。 三个响应之间没有变化。

  • <st c="15140">高温响应(1)</st> <st c="15175">:响应更加随机和多样化。</st> <st c="15219">它可能会将意外和富有想象力的元素引入生成的文本中,但也可能偏离主题或产生不太连贯的答案。`

在某些情况下,增加 ChatGPT API 中的<st c="15363">n</st> <st c="15379">参数也可能有益。</st> <st c="15451">当您增加n 的值时,它决定了模型生成的替代<st c="15525">完成数量。</st> <st c="15561">当您想探索更广泛的可能响应范围或生成相同提示的多样化变体时,这可能很有用。</st>

创建一个名为<st c="15691">n_parameter.py</st> <st c="15731">的新文件。</st> <st c="15768">n</st> <st c="15769">的大小可以根据以下示例进行增加:</st> <st c="15792">:</st>

 from openai import OpenAI
import config
client = OpenAI(api_key=config.API_KEY)
# Define a function to generate a response from ChatGPT
def generate_response(prompt, n):
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "user", "content": f"{prompt}"}
        ],
        n=n,
        temperature=1
    )
    return response
# Prompt for the conversation
prompt = "Suggest 4 names for a cat." n_prompt = generate_response(prompt, 4)
print(n_prompt)
for choice in n_prompt.choices:
    print(f"-------------------------")
    print(f"Choice: {choice}")
    print(choice.message.content)
print(f"-------------------------")

在这里,我们要求 ChatGPT API 为我们猫的命名提示创建四个替代完成。 结果存储在<st c="16551">n_prompt</st> <st c="16559">变量中,并以 JSON 格式在控制台 中显示:`

 -------------------------
Choice: Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='1\. Luna  \n2\. Simba  \n3\. Bella  \n4\. Oliver', role='assistant', function_call=None, tool_calls=None))
1\. Luna
2\. Simba
3\. Bella
4\. Oliver
-------------------------
Choice: Choice(finish_reason='stop', index=1, logprobs=None, message=ChatCompletionMessage(content='1\. Willow\n2\. Fitz\n3\. Pancake\n4\. Luna', role='assistant', function_call=None, tool_calls=None))
1\. Willow
2\. Fitz
3\. Pancake
4\. Luna
-------------------------
Choice: Choice(finish_reason='stop', index=2, logprobs=None, message=ChatCompletionMessage(content='1\. Whiskers\n2\. Mittens\n3\. Luna\n4\. Jasper', role='assistant', function_call=None, tool_calls=None))
1\. Whiskers
2\. Mittens
3\. Luna
4\. Jasper
-------------------------
Choice: Choice(finish_reason='stop', index=3, logprobs=None, message=ChatCompletionMessage(content='14\. Luna \n15\. Toothless \n16\. Simba \n17\. Snowball', role='assistant', function_call=None, tool_calls=None))
14\. Luna
15\. Toothless
16\. Simba
17\. Snowball
-------------------------

如您所见,我们的<st c="17713">选择</st> <st c="17734">列表</st> <st c="17741">大小已增加到四个元素。</st> <st c="17784">这将提供四个不同的猫名,展示了通过增加n 参数所获得的响应多样性的增加。</st> <st c="17924">通过修改n <st c="17959">generate_response</st> <st c="17976">函数中的值,您可以尝试不同的数字来探索更广泛的建议或从 ChatGPT 模型生成更多创意和多样化的响应。`

通过增加<st c="18141">n</st> <st c="18156">,您增加了生成响应的多样性,这允许您探索不同的观点、创意想法或针对给定问题的替代解决方案。</st> <st c="18323">然而,需要注意的是,增加n 也会增加 API 成本和响应时间,因此在多样性和效率之间是一个权衡。 因此,如果您正在寻找更多样化的响应集或寻求创意灵感,增加<st c="18586">n</st> <st c="18587">参数可以是一个有价值的方法。</st>

<st c="18625"> <st c="18630">messages</st> <st c="18638">参数在 GPT-3.5 Turbo 模型的聊天完成中起着至关重要的作用,并允许与模型进行互动和动态的对话。</st> <st c="18782">此参数允许您通过提供消息列表作为输入来模拟对话,其中每个消息包含一个角色(“用户”或“助手”)和消息的内容。</st>

当使用<st c="18978">messages</st> <st c="18998">参数</st>时,适当地构建对话结构非常重要。 <st c="19079">该模型使用先前的消息来生成考虑对话历史</st> <st c="19183">的上下文感知响应。</st> <st c="19204">这意味着您可以通过构建先前的消息来创建引人入胜且互动的交流。</st> <st c="19303">现在,您可以创建一个名为</st> <st c="19334">messages.py</st>的`

<st c="19353">以下是一个演示在 GPT-3.5 Turbo 聊天完成中使用 <st c="19417">messages</st> <st c="19425">参数</st>的代码片段示例:

 from openai import OpenAI
import config
client = OpenAI(api_key=config.API_KEY)
# Define a function for chat completion
def chat_with_model(messages):
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages
    )
    return response.choices[0].message.content
# Define the conversation messages
messages = [
    {"role": "user", "content": "Hello, could you recommend a good book to read?"},
    {"role": "assistant", "content": "Of course! What genre are you interested in?"},
    {"role": "user", "content": "I enjoy fantasy novels."},
    {"role": "assistant", "content": "Great! I recommend 'The Name of the Wind' by Patrick Rothfuss."},
    {"role": "user", "content": "Thank you! Can you tell me a bit about the plot?"},
]
# Chat with the model
response = chat_with_model(messages)
print(response)

在前面的代码中,我们定义了<st c="20273">chat_with_model</st> <st c="20311">函数</st>,它接受<st c="20353">messages</st> <st c="20361">列表</st>作为输入。 <st c="20377">此函数使用</st> <st c="20400">client.chat.completions.create</st> <st c="20430">方法向 GPT-3.5 Turbo 模型发送请求。</st> <st c="20484">模型参数指定要使用的模型 - 在这种情况下,</st> <st c="20551">gpt-3.5-turbo</st> <st c="20564">。 <st c="20570">messages</st> <st c="20578">参数设置为定义的对话消息列表。</st>

<st c="20641">我们通过提供用户和助手的一系列消息来创建对话。</st> <st c="20679">每条消息包含角色(“用户”或“助手”)和消息的内容。</st> <st c="20739">消息按照它们在对话中出现的顺序进行结构化。</st>

通过使用<st c="20898">messages</st> <st c="20916">参数</st>,您可以与 GPT-3.5 Turbo 模型进行动态和互动的对话,使其适用于聊天机器人、虚拟助手等应用。

本节概述了在 ChatGPT API 中使用到的参数及其对响应质量的影响。它讨论了 <st c="21241">温度</st> 参数和 <st c="21271">n</st> 参数,这些参数决定了为增加响应多样性而生成替代完成项的数量。 我们还了解了 <st c="21411">消息</st> 参数以及它是如何使模型能够进行动态和交互式对话的,允许根据 对话历史进行上下文感知的响应。

在下一节中,你将了解对 ChatGPT API 施加的速率限制。你还将了解到在向 API 发起请求时,与不同 AI 模型相关的限制和约束。

ChatGPT API 速率限制

速率限制在维护 ChatGPT API 的稳定性和公平性方面发挥着至关重要的作用。对用户或客户端在特定时间段内可以访问的请求数量和令牌数量设置了限制。 OpenAI 实施速率限制的几个原因包括:

  • 防止滥用和误用:速率限制有助于保护 API 免受恶意行为者的攻击,他们可能会通过发送过多的请求来试图超载系统。 通过设置速率限制,OpenAI 可以减轻此类活动,并维护所有用户的 服务质量。

  • 确保公平访问:通过限制单个用户或组织可以发起的请求数量,速率限制确保每个人都有平等的机会使用 API。 这防止了少数用户垄断资源,从而对其他人造成 减速。

  • 管理服务器负载:通过速率限制,OpenAI 可以有效地管理其基础设施的整体负载。 通过控制传入请求的速率,服务器可以更有效地处理流量,最小化性能问题,并确保所有用户都能获得一致的体验。

速率限制可以 测量为 每分钟请求次数 (RPM) 和 每分钟令牌数 (TPM)。 ChatGPT API 的默认速率限制根据模型和账户 类型而异。 OpenAI 为用户提供五个等级,每个等级都有不同的速率限制。 随着您更频繁地使用 OpenAI API 并更多投资于他们的服务,您将自动升级到下一个使用等级。 这通常会导致各种模型上的速率限制提高,如 表 11.2所示:

等级 资格 使用限制
免费 用户必须处于 全部 $100 /
Tier 1 $5 付费 $100 /
Tier 2 $50 付费和 7+天 $500 /
Tier 3 $100 付费和 7+天 $1000 /
Tier 4 $250 付费和 14+天 $5000 /
Tier 5 $1,000 付费和 30+天 $10000 /

表 11.2 – ChatGPT 使用等级

以下为截至 2024 年 5 月 的 ChatGPT API Tier 4 的默认速率限制:

  • <st c="23820">gpt-4-turbo</st>:5,000 RPM, 600,000 TPM

  • <st c="23857">gpt-3.5-turbo</st>:3,500 RPM, 160,000 TPM

  • <st c="23896">text-embedding</st>:5,000 RPM, 5,000,000 TPM

  • <st c="23938">dall-e-2</st>:每分钟 50 张图片

  • <st c="23970">dall-e-3</st>:每分钟 7 张图片

当您达到最大令牌数或达到最大 RPM 时,您将收到速率限制警告。 例如,如果最大 RPM 是 60,您每秒可以发送 1 个请求。 如果您 尝试更频繁地发送请求,您需要引入短暂的休眠时间以避免触 发速率限制。

当发生速率限制错误时,这意味着您在指定的时间框架内已超出允许的请求数量。 错误信息将指示已达到的具体速率限制,并提供有关限制和您 当前使用情况的信息。

为了减轻速率限制错误并优化您的 API 使用,您可以采取以下几步:

  • 使用指数退避重试:实现指数退避是一种处理速率限制错误的可靠策略。当发生速率限制错误时,您可以在短暂的延迟后自动重试请求。 如果请求再次失败,您将在每次后续重试之前指数级增加延迟。 这种方法允许在不过度压倒系统的情况下进行有效的重试,如下所示:

     import backoff
    import openai
    import config
    from openai import OpenAI
    client = OpenAI(api_key=config.API_KEY)
    @backoff.on_exception(backoff.expo, openai.RateLimitError)
    def completions_with_backoff(**kwargs):
        return client.completions.create(**kwargs)
    completions_with_backoff(model="gpt-3.5-turbo-instruct", prompt="I was walking down the street,")
    
  • <st c="25581">max_tokens</st> 以及从您的输入字符数计算得出的估计令牌数。通过将 <st c="25693">max_tokens</st> 变量设置得接近您预期的响应大小,您可以减少令牌使用量以及您的 成本。

  • 批量请求:偶尔,您 可能会遇到一种情况,即您已经达到最大 RPM,但仍有许多未使用的令牌 剩余。在这种情况下,您可以选择通过将多个任务合并为一个 单独的请求来提高请求的效率。

速率限制对于维护 ChatGPT API 的稳定性、公平性和性能至关重要,可以防止滥用,并确保公平访问,而默认的速率限制根据账户类型而变化,并且诸如指数退避、优化 <st c="26380">max_tokens</st>和批量请求等技术可以帮助减轻速率限制错误并优化 API 使用。

在接下来的部分中,我们将学习关于 OpenAI 嵌入的内容,探讨其重要性、应用以及优化技术。我们还将介绍其应用,并提供在您的项目中最大化其效用的实用见解。

OpenAI 嵌入

在人工智能不断演变的领域中,非结构化数据的处理和解释提出了重大挑战。无论是文本、图像还是音频文件,理解这种复杂性对于开发稳健的软件解决方案至关重要。 这就是嵌入向量,通常称为 嵌入(embeddings)的技术成为关键。 通过将非结构化数据转换为结构化格式,嵌入促进了软件系统的高效处理。

OpenAI 提供了在创建嵌入方面表现卓越的尖端模型,尤其是在文本数据方面。这些嵌入在多种人工智能应用中发挥着关键作用,从 自然语言处理 (NLP) 到图像识别和推荐系统。</st c="27426">通过理解嵌入的基本原理,你将深入了解如何利用这些强大的工具来增强软件开发项目。

首先,让我们揭开嵌入(embeddings)的本质。

嵌入就像是数据的 DNA,提供了一种结构化的表示,计算机可以轻松理解和操作。想象一下,一个图书馆里充满了各种类型的书籍,每本书都代表人类知识和经验的独特方面。 现在,假设你被要求组织这个庞大的收藏。 你决定根据书籍的主题、主题 和内容进行分类。

为了实现这一点,你创建了一个复杂的系统,其中每本书都由一组属性表示——可能是它们的类型、作者、出版年份和主题。</st c="28249">这些属性共同形成每本书的多维向量,将其定位在一个反映其特性的概念空间中。</st c="28402">具有相似属性的书籍在这个空间中聚集在一起,反映了它们的主题或</st c="28493">概念上的相似性。

在这个类比中,嵌入(embeddings)充当组织图书馆的蓝图。通过将书籍的非结构化数据转换为结构化向量,嵌入使计算机能够导航并理解图书馆内容的复杂性。 正如图书管理员可以根据书籍的属性高效地定位书籍一样,算法可以根据其 嵌入表示来分析和操作数据。

OpenAI 通过其先进的嵌入模型将这一概念提升到了新的高度。 这些模型利用复杂的算法和庞大的数据集来捕捉文本数据的细微表示。 通过考虑不仅单个单词,还包括它们的上下文用法,OpenAI 的嵌入产生了更精确和有意义的 向量表示。

此外,OpenAI 的嵌入由最先进的机器学习技术支撑,使它们能够从大量数据中提取见解。 这种能力使嵌入能够识别和利用数据景观中的复杂模式和关系,超越了传统缩放和 降维方法的限制。 因此,OpenAI 的嵌入在识别和利用数据景观中的相似性和差异性方面具有卓越的能力。

接下来,我们将学习如何使用嵌入来比较两个句子的意义以寻找相似之处。 由于我们在比较之前将句子转换为向量,因此我们需要了解术语 余弦相似度。简洁的相似度度量提供了两个向量之间相似度程度的紧凑表示,允许对文本元素(如句子或文档)进行高效的比较和分类。 或文档。

余弦相似度通过测量两个向量之间角度的余弦值来量化两个向量之间的相似度。 它的范围从 -1 到 1,其中 1 表示完美的相似度,0 表示没有相似度,-1 表示 完美的不同度。

从我们之前提到的内容来看,如果我们想检查两个句子之间的相似度,我们需要使用 OpenAI API 找到它们的向量,并使用余弦相似度方法进行比较。 我们可以轻松地利用 Python 来完成这项工作,并将句子表示为向量,然后使用余弦相似度计算它们的简洁相似度。 以下是一个演示 此过程的 Python 脚本:

 from openai import OpenAI
import numpy as np
import config
from sklearn.metrics.pairwise import cosine_similarity
client = OpenAI(api_key=config.API_KEY)
def get_embedding(sentence, engine="text-embedding-3-large"):
    response = client.embeddings.create(
      input=sentence,
      model=engine
    )
    embedding = response.data[0].embedding
    return np.array(embedding)
def compare_sentences(sentence1, sentence2, engine="text-embedding-3-large"):
    embedding1 = get_embedding(sentence1, engine)
    embedding2 = get_embedding(sentence2, engine)
    # Compute cosine similarity
    similarity = cosine_similarity([embedding1], [embedding2])
    return similarity
# Example Usage
sentence1 = "I love reading books." sentence2 = "Reading is my favorite hobby." similarity_score = compare_sentences(sentence1, sentence2)
print("Similarity:", similarity_score)

在这里,代码导入了 必要的库,包括 OpenAI 的 API 客户端、用于数值计算的 NumPy 以及 scikit-learn 的 <st c="31765">cosine_similarity</st> 函数,用于计算余弦相似度。 它定义了一个函数, <st c="31850">get_embedding</st>,用于使用 OpenAI 的文本嵌入模型获取输入句子的嵌入。 然后, <st c="31947">compare_sentences</st> 函数利用 <st c="31988">get_embedding</st> 获取两个输入句子的嵌入,并计算它们的 余弦相似度。

一个示例用法展示了两个句子(我爱读书。 阅读是我最喜欢的爱好。)的比较,并打印出产生的相似度分数。 鉴于这些句子的语义邻近性,相似系数预计会很高, 接近 1。

执行代码后,代码返回以下 相似度分数:

 Similarity: [[0.69882148]]

这个分数表示高度相似,因为它超过了 0, 接近 1。

接下来,通过将<st c="32563">sentence2</st> 的值更改为 金融市场已经度过了更好的日子 并重新运行脚本,我们得到了一个 不同的结果:

 Similarity: [[0.0532481]]

余弦相似度系数显著下降,现在比之前低 10 多倍,更接近 0。 这反映了这两个句子之间存在的实质性差异。

通过使用嵌入和余弦相似度指标探索语义相似度,出现了引人注目的发现,揭示了这项技术的深远影响和实际应用。 通过比较具有不同程度语义相似度的句子,我们 观察到它们的文本内容和产生的相似度分数之间存在明显的相关性。 这强调了嵌入在捕捉和量化文本数据点之间语义关系方面的有效性。 这些见解超越了简单的句子比较,为各种应用提供了宝贵的实用性。 例如,在社会媒体数据的情感分析中,嵌入能够从 X(前身为 Twitter)等平台提取细微的意见,使企业和研究人员能够衡量公众情绪,追踪趋势,并指导决策。 此外,在推荐系统中,嵌入有助于根据其潜在的语义相似性识别相关项目或内容,增强用户体验,并推动参与度。 因此,嵌入在利用非结构化数据中嵌入的信息财富方面发挥着不可或缺的作用,使各个领域实现变革性进步。 的各个领域。

摘要

在本章中,我们探讨了各种 ChatGPT API 模型。 ChatGPT API 模型 – GPT-3.5、GPT-4 以及更高级的模型 部分,我们探讨了不同的 ChatGPT API 模型。 随后,我们为您提供了对这些 AI 模型及其特性的深入了解,使您能够为您的特定应用选择最合适的模型。 本章强调了在选择模型时考虑成本、质量和提示长度等因素的重要性,因为最先进和功能强大的模型并不总是最佳选择。 此外,我们使用 Python 比较了不同模型的响应和成本,有助于决策过程。

我们还关注了 ChatGPT API 的各种参数及其对响应质量的影响。 我们强调了如模型消息温度最大令牌数停止 n等关键参数,并解释了如何操作它们以优化与 ChatGPT API 的交互。 您了解了在保持 ChatGPT API 稳定性和公平性方面,速率限制的重要性。 最后,我们探讨了如何实施适当的策略,以提高使用 ChatGPT API 的效率和成本效益。

在第 12 章中,微调 ChatGPT 以创建独特的 API 模型,我们将深入了解微调 ChatGPT API 模型的过程。 本章旨在为您提供教授 ChatGPT 针对特定项目或应用定制信息的必要技能。 通过一系列案例研究,您将深入了解微调在现实世界中的应用,并受到鼓励进行创造性思考。 此外,我们将强调微调在开发 AI 应用中的成本节约潜力。

第十三章:12

微调 ChatGPT 以创建独特的 API 模型

在本章中,我们将探讨如何微调 ChatGPT API。 这一变革性过程赋予了开发者调整 ChatGPT API 响应行为以符合其特定需求的能力。 我们将深入微调的艺术,探索其中的复杂技术和关键因素。 通过掌握构建和部署我们自己的微调模型,我们将解锁以前所未有的方式增强我们的 AI 应用潜能。

ChatGPT 微调是一个涉及在特定数据集上训练预训练语言模型,例如 <st c="627">gpt-3.5-turbo</st>,以提高其性能并使其适应特定任务或领域的过程。 微调过程通常从一个精心策划和标记的数据集开始,并涉及使用迁移学习等技术在此数据集上训练模型。 在微调过程中,模型的参数被调整以使其更准确、更符合上下文,从而在目标领域生成响应。 通过微调,模型可以获取特定领域的知识、语言模式和细微差别,使其能够为特定应用或 用例生成更相关和连贯的响应。

我们将演示如何使用 JSONL 提示和 完成数据来微调 ChatGPT 以生成简洁的书籍摘要。

在本章中,我们将涵盖以下主题:

  • 微调 ChatGPT 和 数据集准备

  • 构建和使用 微调模型

技术要求

本章的技术要求如下列出:

  • 您的机器上已安装 Python 3.7 或更高版本

  • OpenAI API 密钥

  • 已安装 OpenAI Python

在接下来的章节中,我们将通过检查可用的模型、建立我们的开发环境以及熟悉我们即将构建的书籍摘要微调模型,开始我们的 ChatGPT 微调之旅。

您可以在 GitHub 上找到本章的所有代码示例 https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API

微调 ChatGPT 和数据集准备

在本节中,您将了解微调 ChatGPT 模型的过程。我们将讨论可用于微调的 ChatGPT 模型,并提供它们训练和使用的成本信息。 我们还将涵盖安装 <st c="2423">openai</st> 库以及在终端会话中设置 API 密钥作为环境变量的步骤。 本节将作为微调的概述,包括其好处以及训练微调模型所需的设置。

微调以多种方式增强了 API 模型的能力。首先,它比仅设计提示产生了更高的质量结果。 通过包含比提示中可以容纳的更多训练示例,微调使模型能够掌握更广泛的模式和细微差别。 其次,它通过使用更短的提示来减少令牌使用,从而实现更高效的处理。 此外,微调促进了低延迟请求,使交互更快、更响应。

GPT-3.5 已经在来自互联网的大量文本语料库上进行了广泛的预训练。当给出有限示例的提示时,它通常表现出理解预期任务并生成合理补全的能力——这被称为少样本学习 然而,微调通过利用更大的示例集,将少样本学习推进了一步,超越了提示的能力。这种全面的训练使模型在广泛的任务上表现出卓越的性能。 此外,它还提高了模型在处理各种任务时的性能。

如果一个模型已经经过微调,我们可以使用生成的模型,而无需传递任何进一步的训练数据。 表 12.1中,该表来自官方 OpenAI 定价页面https://openai.com/pricing,您可以看到所有可用于微调的 ChatGPT 模型,每个模型都附有关于它们每 1 百万令牌的训练和使用成本的详细信息,截至2024 年 5 月。

表 12.1 – ChatGPT 模型微调的价格

在微调过程中,有必要以 JSONL 文件的形式提供训练数据,并且训练令牌计数特指该文件中包含的用户和助手字段内使用的那些。 在该文件中,训练令牌计数特指该文件中包含的用户和助手字段内使用的那些。

JSONL 文档的每一行应包含一个 <st c="4561">用户</st> <st c="4570">助手</st> 字段,这些字段对应我们希望的训练数据,如下所示:

 {"messages": [{"role": "user", "content": "The Adventure Begins ->"}, {"role": "assistant", "content": "A thrilling tale of courage and discovery."}]}
{"messages": [{"role": "user", "content": "Secrets Unveiled ->"}, {"role": "assistant", "content": "An intriguing mystery that will keep you guessing until the end."}]}

这个片段是展示如何在 JSONL 文件中显示两条训练行的示例。 在接下来的章节中,我们将使用包含多个 <st c="5145">数据点</st>的完整 JSONL 文件。

我们的目标是开发一个专门为用户提供书籍生成简洁、一句话摘要的微调模型。 为了实现这一目标,我们将构建一个新的 JSONL 训练文件,其中包含提示字段中的书籍标题和完成字段中的相应摘要。 在完成训练阶段后,这个过程将使我们的模型具备根据用户提供的输入有效生成书籍摘要的必要技能。

JSONL 代表 JSON Lines 格式,这是一种基于文本的数据交换格式,其中文件中的每一行代表一个单独的 JSON 对象。 这种格式通常用于存储和交换结构化数据,使得以流式方式读取、写入和处理数据变得容易。

在训练阶段完成后,OpenAI 将为我们微调的模型提供一个独特且专有的名称。 这个独特的名称可以用于 ChatGPT 完成提示中,以有效地与 模型互动。

在开始准备 我们的数据集之前,我们需要确保创建一个名为 <st c="6288">Fine Tune</st>的新目录,并使用 VS Code 或你选择的任何其他编辑器打开它。 在激活我们在 第一章中设置的虚拟环境后,我们需要安装 <st c="6498">openai</st> 库。 为此,在 VS Code 中打开一个新的终端并输入以下内容:

 $ pip install --upgrade openai

这一行将确保 <st c="6663">openai</st> 包的最新版本已安装在你的设备上。

接下来,我们需要创建用于微调任务所需的文件。 从 VS Code 资源管理器 窗口中,创建 两个文件:

  • <st c="6839">main.py</st>:这里将存放用于微调 ChatGPT 模型

  • <st c="6916">train_data.jsonl</st>: 这将保存 JSONL 训练数据集

要从本地终端微调模型,您还需要在 <st c="7086">main.py</st> 文件中提供 ChatGPT API 密钥,如下所示: :

main.py

 import time
from openai import OpenAI
client = OpenAI(api_key=<st c="7247">openai</st> library. We initialize a client object of the <st c="7300">OpenAI</st> class with the provided API key to access OpenAI’s API services, enabling further interaction with ChatGPT through fine-tuning.
			<st c="7434">Finally, we can add the desired datasets with the appropriate format in our</st> `<st c="7511">train_data.jsonl</st>` <st c="7527">file.</st> <st c="7534">We will add a collection of book summaries, represented as user-assistant pairs.</st> <st c="7615">Each entry consists of a</st> `<st c="7640">user</st>` <st c="7644">field that introduces the book with a summary title, followed</st> <st c="7706">by an</st> `<st c="7713">assistant</st>` <st c="7722">field that provides a brief</st> <st c="7751">description of the book.</st> `<st c="7776">user</st>` <st c="7780">highlights different genres, themes, and emotions associated with the books, while</st> `<st c="7864">assistant</st>` <st c="7873">captures the essence of each story.</st> <st c="7910">The summaries encompass a variety of genres, including adventure, mystery, romance, science fiction, and fantasy.</st> <st c="8024">This JSONL file data will serve as a dataset to train a fine-tuned model to generate concise book summaries, based on</st> <st c="8142">user-provided input:</st>

{"messages": [{"role": "user", "content": "The Adventure Begins ->"}, {"role": "assistant", "content": "一段关于勇气和发现的惊险故事。"}]}

{"messages": [{"role": "user", "content": "Secrets Unveiled ->"}, {"role": "assistant", "content": "一个引人入胜的谜团,直到最后都会让你猜测。"}]}

{"messages": [{"role": "user", "content": "Love and Betrayal ->"}, {"role": "assistant", "content": "一段关于爱情、信任和欺骗的心碎故事。"}]}

{"messages": [{"role": "user", "content": "The Quest for Freedom ->"}, {"role": "assistant", "content": "一段引人入胜的自我发现和解放之旅。"}]}

{"messages": [{"role": "user", "content": "Beyond the Stars ->"}, {"role": "assistant", "content": "一部推动想象力边界的史诗科幻冒险。"}]}

{"messages": [{"role": "user", "content": "The Power Within ->"}, {"role": "assistant", "content": "对内在力量和韧性的深刻探索。"}]}

{"messages": [{"role": "user", "content": "Shadows of the Past ->"}, {"role": "assistant", "content": "关于救赎和面对过去幽灵的令人不安的故事。"}]}

{"messages": [{"role": "user", "content": "A World Apart ->"}, {"role": "assistant", "content": "对平行宇宙和选择力量的迷人探索。"}]}


			<st c="9501">You can find the full JSONL file on our Git</st> <st c="9546">repository:</st> [<st c="9558">https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter12%20FineTuning/train_data_prepared.jsonl</st>](https://github.com/PacktPublishing/Building-AI-Applications-with-ChatGPT-API/blob/main/Chapter12%20FineTuning/train_data_prepared.jsonl)<st c="9693">.</st>
			<st c="9694">This section provided an overview of fine-tuning ChatGPT models.</st> <st c="9760">It discussed how fine-tuning enhances few-shot learning and the necessity of providing training data in a JSONL file.</st> <st c="9878">We discussed the fine-tuned model that we will build to generate concise book summaries, based on user-provided input.</st> <st c="9997">We also covered the environment setup, which included the installation of the</st> `<st c="10075">openai</st>` <st c="10081">library and setting the</st> <st c="10106">API key.</st>
			<st c="10114">With our dataset prepared, we have laid the foundation to construct the fine-tuned model, a crucial step that will be explored in detail in the</st> <st c="10259">next section.</st>
			<st c="10272">Building and using the fine-tuned model</st>
			<st c="10312">In this section, we will explore the process of creating and utilizing a fine-tuned model using OpenAI’s library in Python.</st> <st c="10437">OpenAI offers newcomers the opportunity to take advantage of a $5 credit to access the ChatGPT API and its</st> <st c="10544">fine-tuning services.</st>
			<st c="10565">Fine-tuning involves building a specialized model based on an existing base model, and in our example, we will use the most advanced ChatGPT model available for fine-tuning, called</st> `<st c="10747">gpt-3.5-turbo</st>`<st c="10760">. We will improve the performance of that model for book</st> <st c="10817">summarization tasks.</st>
			<st c="10837">We will learn how to start a fine-tuning job, which</st> <st c="10889">uploads and processes the training data, and then we’ll monitor its progress until completion.</st> <st c="10985">Once the fine-tuning job is done, we will use the newly created fine-tuned model to generate text.</st> <st c="11084">We’ll learn how to</st> <st c="11103">make requests to the fine-tuned model using the completions API, and then we’ll cover how to manage and delete fine-tuned models</st> <st c="11232">if needed.</st>
			<st c="11242">We will begin by using our newly created JSONL file to create the fine-tuned model with the following code,</st> <st c="11351">inside</st> `<st c="11358">main.py</st>`<st c="11365">:</st>
			<st c="11367">main.py</st>

file = client.files.create(

file=open("train_data_prepared.jsonl", "rb"),

purpose="fine-tune"

)

打印(file)

tuned_model = client.fine_tuning.jobs.create(

training_file=file.id,

model="gpt-3.5-turbo"

)

打印(tuned_model)


			<st c="11594">This code segment illustrates the process of initiating the fine-tuning of a GPT model using the</st> `<st c="11692">openai</st>` <st c="11698">library.</st> <st c="11708">The</st> `<st c="11712">train_data_prepared.jsonl</st>` <st c="11737">file is opened in binary read mode, which contains the</st> <st c="11792">prepared training data in the JSONL format.</st> <st c="11837">This file is uploaded to OpenAI so that we can use it later for fine-tuning.</st> <st c="11914">Then, a fine-tuning job is initiated using the</st> `<st c="11961">fine_tuning.jobs</st>` <st c="11977">attribute.</st> <st c="11989">The training file for fine-tuning is specified with the</st> `<st c="12045">training_file</st>` <st c="12058">parameter, set to the ID of the previously uploaded file.</st> <st c="12117">The</st> `<st c="12121">model</st>` <st c="12126">parameter indicates the base model to be used for</st> <st c="12176">fine-tuning, which is set here to</st> `<st c="12211">gpt-3.5-turbo</st>`<st c="12224">. Finally, the details of the fine-tuning job are printed, providing information about the job ID and other</st> <st c="12332">relevant details:</st>

文件对象(id='file-UMMzAaCumnkHc8Vx5WwTAEs0', bytes=5329, created_at=1714533608, filename='train_data_prepared.jsonl', object='file', purpose='fine-tune', status='processed', status_details=None)

微调作业(id=ftjob-EZ2V9AS46DjaSv6jWy0S4Pt7。需要注意的是,模型不是立即创建的。创建模型的过程可能有所不同,可能需要几分钟到几小时。您可以通过查看状态参数来监控模型创建的状态,目前指示系统正在验证 JSONL 文件。

        <st c="13564">您可以通过在以下行中添加以下行来监控您模型的状况</st> `<st c="13652">main.py</st>` <st c="13659">文件:</st>
 job = client.fine_tuning.jobs.retrieve(tuned_model.id)
print(job.status)
while job.status != "succeeded":
    job = client.fine_tuning.jobs.retrieve(tuned_model.id)
    print(job.status)
    time.sleep(5)
print(job.fine_tuned_model)
        <st c="13886">此代码片段处理在上一段中启动的微调作业的监控。</st> <st c="13986">最初,</st> `<st c="14001">retrieve</st>` <st c="14009">方法被用来检索关于微调作业的详细信息。</st> <st c="14076">之前启动的微调作业的</st> `<st c="14080">id</st>` <st c="14082">,即</st> `<st c="14128">tuned_model.id</st>`<st c="14142">,作为参数传递给此</st> <st c="14177">方法。</st> <st c="14185">随后,打印作业的状态以提供其进度的初步指示。</st> <st c="14282">然后使用</st> `<st c="14284">while</st>` <st c="14289">循环来持续检查作业的状态,直到它达到</st> `<st c="14375">succeeded</st>` <st c="14384">状态。</st> <st c="14392">在循环中,再次使用</st> `<st c="14460">retrieve</st>` <st c="14468">方法检索作业的状态,并打印状态以跟踪任何变化。</st> <st c="14533">此外,循环中包含了一个</st> `<st c="14549">time.sleep(5)</st>` <st c="14562">语句,在每次状态检查之间引入五秒的暂停,以防止过多的 API 请求并确保有效利用资源。</st> <st c="14740">此迭代过程持续进行,直到作业状态转换为</st> `<st c="14809">succeeded</st>`<st c="14818">,表示微调过程的完成:</st>
 validating_files
validating_files
running
running
running
succeeded <st c="14942">ft:gpt-3.5-turbo-0125:personal::9Jv8aUuC</st> ChatCompletionMessage(content='An exhilarating journey of self-discovery and courage.', role='assistant', function_call=None, tool_calls=None)
        <st c="15125">一旦我们的模型成功编译,我们可以使用</st> `<st c="15204">job.fine_tuned_model</st>` <st c="15224">变量来显示模型名称。</st> <st c="15235">在这种情况下,你的模型名称是</st> `<st c="15268">ft:gpt-3.5-turbo-0125:personal::9Jv8aUuC</st>`<st c="15308">。我们可以使用这个名称进行任何 chant 完成,就像任何基础</st> `<st c="15376">gpt-3.5-turbo</st>` <st c="15389">和</st> `<st c="15394">gpt-4</st>` <st c="15399">标准模型一样。</st> <st c="15417">您可以使用以下代码进行简单快捷的测试。</st> <st c="15463">这允许您无缝地与您的微调模型交互并评估其性能,而无需</st> <st c="15581">任何复杂性:</st>

        <st c="15599">main.py</st>
 completion = client.chat.completions.create(
    model=job.fine_tuned_model,
    messages=[
        {"role": "user", "content": "The Adventure Begins ->"}
    ]
)
print(completion.choices[0].message.content)
        <st c="15795">在这里,我们只需提供我们的微调</st> <st c="15835">模型和一个书的名称,并期望它返回一个类似于我们 JSONL 文件中的描述。</st> <st c="15938">给定的示例包括几个参数和头信息,用于指定请求的详细信息。</st>

        <st c="16034">一旦执行请求,你将收到以下消息:</st>
 An exhilarating journey of self-discovery and courage
        <st c="16158">前面的输出是标准的 ChatGPT 响应,除了这里我们使用了我们微调过的书籍摘要模型。</st> <st c="16272">为了</st> <st c="16274">验证模型是否正常工作,您可以比较响应与我们在 JSONL 文件中为相应书籍提供的训练数据</st> <st c="16420">标题</st> <st c="16427">提示:</st>
 {"messages": [{"role": "user", "content": "The Adventure Begins ->"}, {"role": "assistant", "content": "<st c="16708">assistant</st> field from our training data is part of the same meaning as the ChatGPT API response. This means that the trained model shows an improved performance, incorporating the training data.
			<st c="16901">Finally, if you decide to remove or delete a fine-tuned model that you created, OpenAI provides a straightforward command that you can use.</st> <st c="17042">Execute the following command in your</st> `<st c="17080">main.py</st>` <st c="17087">file:</st>

client.models.delete(job.fine_tuned_model)


			<st c="17136">It is important to note that deleting a fine-tuned model should be done judiciously, as it permanently removes the model and its associated data.</st> <st c="17283">Therefore, it is advisable to carefully consider your decision and ensure that you no longer need the fine-tuned model before proceeding with the</st> `<st c="17428">deletion</st>` <st c="17437">command.</st>
			<st c="17446">In this section, we have</st> <st c="17471">explored the entire life cycle of fine-tuning models.</st> <st c="17526">Armed with this knowledge, you are now equipped to continue your journey of experimentation by constructing fine-tuned models that specialize in various tasks and incorporate a larger volume of training data entries.</st> <st c="17743">This opens a realm of possibilities to refine and enhance the performance of your models, enabling you to achieve even more</st> <st c="17867">impressive results.</st>
			<st c="17886">Summary</st>
			<st c="17894">In this chapter, we discussed the concept of fine-tuning within the ChatGPT API, exploring how it can help us to tailor ChatGPT API responses to our specific needs.</st> <st c="18060">By training a pre-existing language model on a diverse dataset, we enhanced the</st> `<st c="18140">gpt-3.5-turbo</st>` <st c="18153">model performance and adapted it to a particular task and domain.</st> <st c="18220">Fine-tuning enriched the model’s capacity to generate accurate and contextually fitting responses by incorporating domain-specific knowledge and language patterns.</st> <st c="18384">Throughout the chapter, we covered several key aspects of fine-tuning, including the available models for customization, the associated costs, data preparation using JSONL files, the creation of fine-tuned models, and the utilization of these models with the ChatGPT API.</st> <st c="18656">We underscored the significance of fine-tuning to achieve superior outcomes, reduce token consumption, and enable faster and more</st> <st c="18786">responsive interactions.</st>
			<st c="18810">Additionally, the chapter offered a comprehensive step-by-step guide on dataset preparation for fine-tuning.</st> <st c="18920">It dived into the process of data organization using a JSONL file.</st> <st c="18987">The dataset comprised prompt-completion pairs representing book summaries.</st> <st c="19062">The tool analyzed the data and proposed modifications, such as adding separators to user requests, eliminating unnecessary prefixes, and initiating assistant responses with whitespace characters.</st> <st c="19258">These modifications enhanced the model’s comprehension.</st> <st c="19314">Once the dataset was prepared and optimized, the chapter detailed the process of constructing and utilizing the fine-tuned model.</st> <st c="19444">It provided insights on initiating a fine-tuning job, monitoring its progress, and harnessing the fine-tuned model for text generation through the ChatGPT API.</st> <st c="19604">We emphasized the importance of fine-tuning in improving model performance and learned how to manage and delete fine-tuned models,</st> <st c="19735">as necessary.</st>
			<st c="19748">In this book, you embarked on a comprehensive journey into the world of ChatGPT and its API, gaining knowledge and skills to build a variety of powerful applications.</st> <st c="19916">You gradually built a ChatGPT clone, developed a SaaS application, integrated payment services, and explored frameworks such as Django and PyQt for web and desktop app development.</st> <st c="20097">You also discovered the possibilities of integration with Microsoft Word, Outlook, and PowerPoint, as well as transcribing audio files.</st> <st c="20233">You gained insights into selecting the right model and optimizing completions, and you even explored the realm of ChatGPT fine-tuning.</st> <st c="20368">With these skills, you are now well-equipped to create innovative AI applications and leverage the full potential of the</st> <st c="20489">ChatGPT API.</st>


posted @ 2026-03-25 10:28  布客飞龙II  阅读(0)  评论(0)    收藏  举报