OpenAI-API-人工智能应用构建指南-全-
OpenAI API 人工智能应用构建指南(全)
原文:
zh.annas-archive.org/md5/f7ddf3ef1e7a30167428b93eec187cf2译者:飞龙
第一章:前言
-
ChatGPT API :使用它来释放类似人类的文本生成能力 -
Whisper API :使用它来增强语音识别和文本到语音的能力 -
DALL-E API :使用它来探索 AI 生成艺术的世界
本书面向对象
本书涵盖内容
为了充分利用这本书
在开始阅读本书之前,您对 Python 编程和 API 概念有一个基本的理解是非常重要的。
|
| --- | --- |
|
|
|
|
|
|
下载示例代码文件
<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>
联系我们
分享您的想法
一旦您阅读了《使用 OpenAI API 构建人工智能应用》
下载此书的免费 PDF 复印本
扫描二维码或访问以下 链接

-
提交您的购买 证明 -
这就完了! 我们将直接将您的免费 PDF 和其他优惠发送到您的 电子邮件
第一部分:开始使用 OpenAI API
-
第一章,使用 ChatGPT API 进行 NLP 任务入门 -
第二章,构建 ChatGPT 克隆版
第二章:1
开始使用 ChatGPT API 进行 NLP 任务
ChatGPT 是由
本章中,我们将探讨 ChatGPT 的基础知识以及如何使用它来执行 NLP 任务。
本章中,我们将涵盖以下主题:
-
ChatGPT 革命 -
从网络使用 ChatGPT
-
开始使用 ChatGPT API
-
设置您的 Python
开发环境 -
简单的 ChatGPT API 响应
到本章结束时,您将对该章内容有扎实的理解,了解 ChatGPT 及其如何高效地执行 NLP
技术要求
为了充分利用本章内容,您需要一些基本工具来处理 Python 代码和 ChatGPT API。
您需要以下内容:
-
在您的计算机上安装了
Python 3.7 或更高版本 -
一个 OpenAI API 密钥,可以通过注册一个 OpenAI 账户 来获取 -
一个代码编辑器,例如 VSCode (推荐),用于编写和运行 Python 代码 -
基本的 Python 编程经验 使用 Python
ChatGPT 革命
-
GPT-1 (2018) :拥有 1.17 亿个参数,并在多样化的网页集上进行训练。 它在各种 NLP 任务中表现出色,包括问答、情感分析和 语言翻译。 -
GPT-2 (2019) :拥有 15 亿个参数,并在超过 800 万个网页上进行训练。 它在语言理解和生成方面取得了显著的进步,并成为各种 NLP 应用中的广泛使用工具。 -
GPT-3 (2020) :拥有创纪录的 1750 亿个参数,为语言理解和生成设定了新的基准。 它被用于各种应用,包括聊天机器人、语言翻译和 内容创作。 -
GPT-3.5 :在 OpenAI 的持续优化和改进后发布。 在成本和性能比较中是目前最佳价值模型。 -
GPT-4 :能够以更高的精度解决难题,这得益于其更广泛的一般知识和 问题解决能力。
在下一节中,你将学习如何从网页上使用 ChatGPT。
从网页上使用 ChatGPT
创建 OpenAI 账户


ChatGPT 网页界面

除了这些,ChatGPT 允许用户轻松记录与模型交互的历史。
开始使用 ChatGPT API
获取 API 密钥


API token 和定价

<st c="17223">venv</st>
设置你的 Python 开发环境
-
安装 Python -
安装 VSCode IDE -
安装 <st c="18228">pip</st> -
设置 虚拟环境 -
安装所需的 Python 包
安装 Python 和 VSCode IDE
$ python --version

设置 Python 虚拟环境
-
在您的计算机上启动 VSCode。 -
使用文件资源管理器或 <st c="21665">ChatGPTResponse</st>。 -
创建文件夹后,通过选择 文件 | 打开文件夹 并导航到您刚刚创建的文件夹来在 VSCode 中打开它。 -
在打开的文件夹内,创建一个新的 Python 文件,您将在其中编写代码。 您可以通过在 <st c="21997">.py</st>扩展名上右键单击,例如 <st c="22017">app.py</st>。 -
通过选择 视图 | 终端 从菜单中打开 VSCode 的集成终端。 -
进入您的项目文件夹后,运行以下命令创建虚拟环境。 第二个 <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. -
要激活虚拟环境,请运行以下 终端命令: -
在 Windows 上,运行以下终端命令以激活 虚拟环境: <st c="22612">$ venv\Scripts\activate.bat</st> -
在 macOS 或 Linux 上,运行以下终端命令来激活虚拟环境: <st c="22731">$ source venv/b</st><st c="22747">in/activate</st>
-

ChatGPTResponse % source venv/bin/activate <st c="23141">(venv)</st> ChatGPTResponse % <st c="23166">(venv)</st> ChatGPTResponse %
pip 包安装器
<st c="23640">openai</st> <st c="23646">。如果您使用的是 Python 的较新版本,</st> <st c="23831">pip</st> <st c="23834">然后按下</st> *<st c="23860">Enter</st> <st c="23865">键来检查您的系统上是否已安装 pip。</st> <st c="23871">如果</st>
-
首先,从 get-pip.py 脚本从官方 Python 网站下载: https://bootstrap.pypa.io/get-pip.py 。 -
将文件保存到您容易访问的位置,例如桌面或 下载文件夹。 -
打开命令提示符或终端,导航到您保存 get-pip.py 文件的目录。 -
运行以下命令来安装 pip: python get-pip.py 。 -
安装完成后,您可以通过在命令提示符或终端中键入 pip 并按下 *Enter 键来验证 pip 是否已安装。
一个简单的 ChatGPT API 响应
使用 Python 与 ChatGPT API 结合是一个相对简单的过程。<st c="25220">CHATGPTRESPONSE</st> <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> <st c="25921">ChatGPT API</st>进行交互:
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")
<st c="26008">YOUR_API_KEY</st> <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>

<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 克隆
本章和本书的第一个应用将是一个
克隆应用将能够接收用户的输入,将其发送到 OpenAI 的 API,并实时接收响应,这些响应将显示给用户。
初始时,我们的聊天机器人将缺乏维持上下文对话的能力。
在本章中,我们将涵盖以下主题:
-
使用 Flask
创建一个 ChatGPT 克隆 -
生成 ChatGPT 克隆的
HTML -
截获 ChatGPT 的 API 端点
-
OpenAI 的 ChatGPT API 用于 文本生成 -
通过使用
AJAX 将用户输入从前端传递到后端 -
在前端显示生成的文本
-
保留和更新聊天上下文
当使用 Flask 构建一个 ChatGPT 克隆时,有一些事项需要牢记。
技术要求
为了充分利用本章内容,您将需要一些基本工具。
您将需要以下内容:
-
Python 3.7 或更高版本已安装在您的计算机上 -
OpenAI API 密钥 ,从您的OpenAI 账户 获取 -
一个代码编辑器,例如
VSCode(推荐) -
在您的 Python
虚拟环境 中安装的 Flask 框架
本章的代码示例可以在 GitHub
在下一节中,我们将开始使用 Flask 构建 ChatGPT 克隆,通过设置一个与 ChatGPT API 通信以生成对用户输入的响应的后端来构建 ChatGPT 克隆。
使用 Flask 创建 ChatGPT 克隆
要使用 Flask 创建一个 ChatGPT 克隆,您需要设置一个后端,该后端与 ChatGPT API 通信以生成对用户输入的响应。
-
要开始,创建一个新的文件夹并将其命名为 <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)
-
在 Flask 中,路由是用户可以访问的你的应用程序中的 URL 路径。 你可以使用 <st c="5055">@app.route</st>装饰器和 Python 函数来定义路由。 让我们创建一个显示 <st c="5134">Hello, World!</st>的路由,如下所示: @app.route("/") def index(): return "Hello, World!" -
最后,你可以使用 <st c="5258">app.run()</st>方法运行你的 Flask 应用程序。 这将允许你启动一个开发服务器,你可以在你的 网络浏览器 中访问它:if __name__ == "__main__": app.run() -
一旦你 创建了运行配置,你可以通过点击 <st c="5557">app.py</st>并选择 运行 选项来运行你的 Flask 应用程序。 然后你将在 运行 窗口中看到你的 Flask 应用的 URL,如图 图 2 **所示。 1 *:

<st c="6020">Hello, World!</st>

<st c="7173">config.py</st> <st c="7200">config</st> <st c="7233">app.py</st>
API_KEY = "YOUR_API_KEY"
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()
<st c="7648">config.py</st> <st c="7681">.gitignore</st>
<st c="7804">index()</st>
@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>

<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>`

<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>

<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 应用程序
-
第三章 , 使用 Flask 创建和部署代码错误修复应用程序 -
第四章 , 将代码错误修复应用程序与支付服务集成 -
第五章 **,使用 ChatGPT 和 Django 的测验生成应用程序
第四章:3
使用 Flask 创建和部署代码错误修复应用程序
在本章中,我们将深入探讨使用
为了开发此 SaaS 应用程序,我们将利用一个你可能已经非常熟悉的工具,即用于在 Python 中构建网络应用的 Flask 框架。我们的目标是熟练掌握这个框架,以构建一个有效且可扩展的 Web 应用程序,能够为用户提供高效的代码错误解决方案。
-
执行多个 ChatGPT API 请求 -
设置代码错误 修复器项目 -
实现代码错误 修复器后端 -
使用文本区域 和容器 -
测试代码错误 修复器应用 -
将 ChatGPT 应用部署到
Azure 云 中
技术要求
本项目的技术要求如下
-
在
你的机器上安装了 Python 3.7 或更高版本 -
一个代码编辑器,例如
VSCode(推荐) -
一个 Python 虚拟环境 -
在
虚拟环境 中安装的 Flask 网络框架 -
一个 OpenAI API 密钥 -
访问云托管服务,例如 Microsoft Azure
本章中的代码示例可以在 GitHub 上找到
执行多个 ChatGPT API 请求
<st c="2128">app.py</st>
-
请求 1 :ChatGPT 使用有错误的代码和错误信息来修复 代码 -
请求 2 :ChatGPT 使用有错误的代码和错误信息,用普通英语向用户解释错误


<st c="4086">CodeBugFixer</st> <st c="4132">templates</st> <st c="4212">config.py</st> <st c="4226">app.py</st>
设置 Code Bug Fixer 项目
<st c="4456">CodeBugFixer</st>
<st c="4927">CodeBugFixer</st>
-
首先,在项目的根目录中创建两个新的 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 密钥 和密码。 -
接下来,在项目的根目录中创建一个名为 <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. -
在终端窗口中,你可以按照以下方式安装任何必要的库: (venv)$ pip install flask (venv)$ pip install openai -
最后,为了在您的 <st c="6142">CodeBugFixer</st>应用程序中建立使用 ChatGPT API 的基础,您需要将以下代码添加到 <st c="6201">config.py</st>和 <st c="6215">app.py</st>:
API_KEY = <Your API Key>
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> <st c="6615"><Your API Key></st>
<st c="6689">app.py</st> <st c="6769">Flask</st> <st c="6877">config.py</st> <st c="6988">render_template</st> <st c="6954">index.html</st>
<st c="7028">CodeBugFixer</st> <st c="7219">config.py</st> <st c="7233">app.py</st> <st c="7251">config.py</st> <st c="7311">app.py</st> <st c="7367">index.html</st> <st c="7418">app.py</st>
<st c="7534">index()</st> <st c="7642">GET</st> <st c="7650">POST</st> <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> <st c="8183">您可以在</st>
@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> <st c="8618">如果请求方法是</st> <st c="8702">index.html</st> <st c="8712">模板中提交了表单。</st>
<st c="9037">代码</st> <st c="9041">和</st> <st c="9046">错误</st> <st c="9051">变量中分别检索用户的输入。</st> <st c="9168">然后使用提取的</st> <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> <st c="9955">此变量随后用于指定用于文本补全的 OpenAI 语言模型。</st> <st c="10072">gpt-3.5-turbo</st> `
<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>
<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>
<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>
<st c="13116">index.html</st>
使用文本区域和容器
<st c="13492">CodeBugFixer</st>
<st c="13831">index.html</st> <st c="13896">templates</st>
<!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>
<st c="14263"><title></st> <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>
<st c="15528"><form></st> <st c="15550">action</st> <st c="15574">"/"</st> <st c="15586">method</st> <st c="15610">post</st><st c="15737">POST</st> <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>

最后,我们将向我们的应用程序添加一些 CSS 来样式化 HTML 元素。
你可以在<st c="17958">title</st> <st c="17979">head</st> <st c="17991">index.html</st>
<title>Code Bug Fixer</title>
<style type="text/css">
body {
font-family: Arial sans-serif;
background-color: #f6f7f9;
}
首先,让我们
.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 <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> <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>
<st c="21786">CodeBugFixer</st>
<st c="22015">CodeBugFixer</st>
测试代码错误修复应用程序
代码错误修复器应用程序可以修复任何编程语言,使其成为一个多功能的工具。
**我们的 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>
**为了在代码错误修复器应用程序中修复此代码,请按照以下步骤操作:
-
将代码粘贴到
输入 代码 字段中。 -
将错误粘贴到
输入 错误 字段中。 -
左键单击
代码 修复 按钮。
完成列出的步骤后,固定代码和 ChatGPT API 生成的解释将显示在相应的字段中。

图 3.4 – 代码错误修复器处理一些 Python 代码
为了确保固定代码正确运行,您可以通过在 Python IDE(如 VSCode 或任何其他在线 Python 编译器)中运行它来测试它。
**最后,为了验证代码错误修复器应用程序可以与任何编程语言一起工作,让我们尝试修复以下
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>

<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>

<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>

<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
将代码错误修复应用程序与支付服务集成
-
设置 SQL 用户数据库 -
向 ChatGPT 应用程序添加支付 功能
技术要求
-
在您的 机器上安装了 Python 3.7 或更高版本 -
代码编辑器,例如 VSCode(推荐) -
Python 虚拟环境 -
一个 OpenAI API 密钥 -
一个 Stripe 账户和 API 密钥
介绍和集成 Stripe 支付
-
访问 Stripe 网站: https://stripe.com/ 。 -
点击页面右上角的 登录 按钮。 -
点击 创建 账户 按钮。 -
填写注册表单,提供您的个人或业务信息。 您需要提供您的姓名、电子邮件地址和密码(见 图 4 **.1 )。 -
通过点击 Stripe 发送给您的验证电子邮件中的链接来确认您的电子邮件地址。 -
提供您的 业务详细信息,例如您的 公司名称、地址和税务识别号 (可选)。 -
设置您的支付设置。 您可以选择接受所有主要信用卡和借记卡的支付,以及像 Apple Pay 和 Google Pay 这样的数字钱包支付(可选)。


-
发布密钥 用于客户端,以安全地向 Stripe 发送请求。 它没有任何访问你账户的权限,可以公开分享。 这个密钥通常放置在 应用程序前端。 -
秘密密钥 用于服务器端,以向 Stripe 发送请求,并且 具有完全访问你账户的权限,包括进行收费的能力。 它应该保密,并且永远不应该公开分享。 这个密钥通常放置在 应用程序后端。 -
测试密钥 用于测试环境,以执行测试交易而不收取任何费用。 它像秘密密钥一样工作,但只影响测试数据,并且不应该在生产中使用。
在
您可以使用
在下一节中,您将学习如何为 Code Bug Fixer 应用程序设置 SQL 用户数据库。
设置 SQL 用户数据库
在将支付基础设施集成到您的应用程序之前,确定您的业务策略至关重要,这关系到您将如何向您的 Web 应用程序用户收费。
-
订阅计划 :这是一种定期付款模式,允许用户定期支付服务或产品费用,例如按月或按年支付。 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.
初始化 SQL 数据库
<st c="10352">及其与我们的应用程序的交互相关的数据,使我们能够无缝地管理支付</st>
<st c="10499">app.py</st> <st c="10573">SQL 数据库:</st>
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>"
<st c="12240">app.py</st>
client = OpenAI(
api_key=config.API_KEY,
) <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>
<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>

<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>

<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>

<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>

<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>

<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>

<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 创建问答应用
在前几章中,我们主要关注了 Flask,一个轻量级和基本的 Web 框架。
-
构建一个 Django 项目 -
创建考试应用框架 和视图 -
将 ChatGPT 和 Django 集成用于 测验生成 -
存储和下载 生成的测验
技术要求
-
在您的 本地机器上安装 Python 3.7 或更高版本 -
一个代码编辑器,推荐使用 VSCode 以获得 最佳体验 -
一个 OpenAI API 密钥,用于访问必要的 API 功能
构建 Django 项目
<st c="4443">QuizApp</st><st c="4651">pip</st>
$pip install Django
$django-admin startproject quiz_project
<st c="4870">django-admin</st><st c="4941">quiz_project</st>
<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 ) 配置文件。
<st c="6434">quiz_project</st>
$cd quiz_project
$python manage.py startapp quiz_app
<st c="6716">quiz_app</st>
-
<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
<st c="8454">auth</st><st c="8460">admin</st><st c="8467">contenttypes</st><st c="8485">sessions</st>
$python manage.py migrate
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
<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.
<st c="10546">manage.py</st>

创建考试应用程序框架和视图
在本节中,我们将
我们还将了解 Django 中的 URL 处理。<st c="11895">urls.py</st>
连接 Django 视图和 URL
<st c="12812">quiz_app/urls.py</st><st c="12878">urls.py</st> <st c="12906">quiz_project</st>

图 5.2 – Django 视图/URL 架构
<st c="13024">默认情况下,Django 在初始化项目时会自动生成</st> <st c="13072">quiz_project/urls.py</st> <st c="13092">文件。</st> <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> `
<st c="13462">现在,您可以打开</st> <st c="13481">quiz_app/views.py</st> <st c="13498">并编写以下</st> `
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>
在函数内部,Django 快捷方式 <st c="13837">render</st> <st c="13879">函数用于渲染 HTML 模板。</st> <st c="14006">该对象包含有关请求的信息,例如头部、数据和用户会话详情。</st>
<st c="14178">在构建</st> <st c="14199">base.html</st> <st c="14208">文件之前,我们需要确保用户可以访问</st> <st c="14242">home</st> <st c="14246">视图。</st>
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> <st c="14623"> <st c="14627">path</st> <st c="14631">函数用于定义 URL 模式。</st>
<st c="14904">views.home</st><st c="15015">name='home'</st>
<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> ]
<st c="15612">urlpatterns</st>
<st c="15771">path</st> <st c="15794">admin/</st> <st c="15831">admin/</st>
<st c="16068">path('', include('quiz_app.urls'))</st> <st c="16147">quiz_app/urls.py</st><st c="16202">''</st>
<st c="16382">include('quiz_app.urls')</st><st c="16468">quiz_app.urls</st> <st c="16536">quiz_app</st>
<st c="17159">base.html</st>
开发 Django 模板
<st c="17501">base.html</st> <st c="17575">base.html</st>

<st c="19083">templates</st>
quiz_project/
├── quiz_app
├── quiz_project/
└── templates
<st c="19380">templates</st> <st c="19439">base.html</st>
{% 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 –>-->
<link href="{% static 'css/dashboard.css' %}" rel="stylesheet" />
</head>
<st c="20125">{% load static %}</st><st c="20396">.css</st>
<st c="20469">data-bs-theme</st>
<st c="20696">head</st>
<st c="21042">{% static 'css/bootstrap.min.css' %}</st> <st c="21083">{% static 'css/dashboard.css' %}</st>
<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>
-
<st c="23523">dashboard.css</st>: https://getbootstrap.com/docs/5.3/examples/dashboard/dashboard.css -
<st c="23606">bootstrap.min.css</st>: https://getbootstrap.com/docs/5.3/dist/css/bootstrap.min.css
现在,让我们看看如何将这些 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 <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 在开发期间在哪里查找静态文件,而
<st c="26494">base.html</st> <st c="26581">settings.py</st>
运行您的 Django 应用程序
<st c="27003">quiz_project</st><st c="27081">manage.py</st>
$python manage.py runserver
<st c="27789">http://127.0.0.1:8000/</st> <st c="27879">127.0.0.1</st> <st c="27903">8000</st>

-
首先,在最上面,我们有一个标题区域,显示名称 Quiz App 在深色背景上。 -
在左侧,我们找到了一个导航栏,其中包含两个标签,我们将其整合到了 <st c="28332">base.html</st>文件中 – 问题生成器 和 我的测验 。这些标签便于在应用程序的不同功能之间进行导航。 问题生成器 标签将用户引导到一个可以构建测验的区域,而 我的测验 标签则提供了一个下载测验的视图。 -
最后,在导航栏的右侧,我们有工作区,用户可以与之交互并探索 我的测验 和 问题生成器 **功能。
集成 ChatGPT 和 Django 用于测验生成
<st c="29414">POST</st>
<st c="30212">POST</st>
<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 模板块,这允许动态内容插入。
<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>
<!-- <!– Custom styles for this template –>-->
<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>
<st c="33871">quiz_style.css</st> <st c="33897">quiz_project/static/css</st>
<st c="34167">body</st><st c="34173">container</st><st c="34188">main</st> <st c="34207">body</st> <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>
使用 Django 创建 ChatGPT API 视图
-
一个变量应该传递我们想要创建问题的文本。 这将使我们的应用程序能够处理不同类型的 文本。 -
提示应该包含以下指令,以指定 以下: -
问题的数量 个 -
提示应该包含以下指令: 以下: -
ChatGPT 应生成哪种类型的问题(多项选择、开放式回答等)
-
<st c="36592">quiz_app</st> <st c="36600">文件夹内,您需要创建两个基本文件——</st> <st c="36692">services.py</st> <st c="36922">services.py</st> `
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
API_KEY = "YOUR_API_KEY"
<st c="38270">config</st> <st c="38276">模块</st>,该模块包含 API 密钥。</st> <st c="38310">使用导入的</st> <st c="38404">ChatGPT API</st> 的连接。
<st c="38421">generate_questions</st>
-
清晰的指令 :提示语首先明确说明任务的目的是创建一个包含多项选择题的练习测试。 这有助于设定生成内容的上下文和期望。 -
<st c="39228">{text}</st>占位符表示应在该位置插入给定的文本。 这允许用户提供基于该文本的问题。 -
结构化格式 :提示指定每个问题应单独一行。 这有助于创建练习测试的结构化布局,使其更容易被人类和其他 Python 脚本 理解。 -
多项选择题格式 :提示中说明,每个问题应有四个可能的答案。 这表明生成的题目应遵循在测试和测验中常用的多项选择题格式 。 -
指示正确答案 :提示中提到,在可能的答案下,应提供正确答案。 这确保了生成的题目包括正确答案和选项,使学习者能够轻松地识别 正确答案。
<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> <st c="41053">POST</st> <st c="41181">POST</st> <st c="41201">text</st> <st c="41308">text</st>
<st c="41471">services.py</st> <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>
<st c="42110">views.py</st> <st c="42129">home</st> <st c="42284">POST</st>
<st c="42408">openai</st>
pip install openai
-
请确保你的 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. -
在主页上,你会看到一个文本区域,你可以输入一些文本。 粘贴或输入你想要生成测验问题的文本(见 图 5 **.5 )。

-
一旦你 输入了文本,点击 <st c="43794">POST</st>请求到 服务器。 -
服务器将处理请求并根据提供的文本使用 ChatGPT API 生成测验问题。 生成的测验问题将在文本区域下方显示(见 图 5 **.6 )。

存储和下载生成的测验
将测验保存到 SQLite 数据库
<st c="46882">generate_questions()</st>
<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):
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><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>
<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>
下载测验
- {{ test.1 }}
<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>

<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
-
第六章 , 使用 ChatGPT API 和 Microsoft Word 构建语言翻译桌面应用程序 -
第七章 , 使用 PyQt 和 ChatGPT API 构建 Outlook 电子邮件回复生成器 -
第八章 **,使用 PyQt 和 ChatGPT API 构建论文生成工具 -
第九章 **,集成 ChatGPT 和 DALL-E API:构建端到端演示文稿生成器 -
第十章 **,使用 Whisper API 进行语音识别和语音合成
第七章:6
使用 ChatGPT API 和 Microsoft Word 的桌面语言翻译应用
-
将 ChatGPT API 与 Microsoft Office 集成 -
使用 Tkinter
构建用户界面 的 -
将 Microsoft Word 文本与 ChatGPT API 集成
技术要求
-
在您的机器上安装了
Python 3.7 或更高版本 的 -
代码编辑器,例如 VSCode(推荐) -
Python 虚拟环境 -
OpenAI API 密钥 -
您的设备上可用的 Microsoft Word
<st c="2201">docx</st>
将 ChatGPT API 与 Microsoft Office 集成
<st c="2699">docx</st> <st c="2760">docx</st> <st c="2842">.docx</st>
<st c="3012">Translation App</st>
-
<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 环境中。要安装openai和docx库,请访问 VSCode 终端,然后执行以下命令:
pip install openai
pip install python-docx
要访问和读取 Word 文档的内容,您需要在项目中创建一个示例 Word 文件。以下是创建新 Word 文件的步骤:
-
在您的项目中,右键单击项目目录,选择
files。 -
右键单击
files文件夹并选择New File。 -
在出现的编辑字段中,输入一个带有
.docx扩展名的文件名——例如,info.docx。 -
按下Enter键来创建文件。
-
文件创建后,使用 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> <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>
<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> <st c="6767">Obtaining the file path is a simple task, achieved by right-clicking on your</st> <st c="6844">.docx</st> **<st c="6883">Copy Relative Path</st>
<st c="6967">app.py</st> <st c="7215">text</st> <st c="7253">info.docx</st>

<st c="7551">docx</st> <st c="7692">docx</st>
使用 Tkinter 构建用户界面
<st c="8053">Tkinter</st>
-
要将文本翻译,用户可以从 下拉菜单中选择他们想要翻译成的语言。 -
一旦选择了语言,用户可以点击 浏览 按钮并选择他们想要翻译的 Word 文件。 -
选择后,文件内容将使用 ChatGPT API 进行翻译,翻译后的文本将显示在窗口中央的大文本框中。 然后,用户可以复制并粘贴翻译后的文本,按需使用。

<st c="9567">app.py</st>
<st c="9827">app.py</st>
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()
<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> <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">然后我们将使用 <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">按钮放置在根窗口中,其 <st c="12141">参数将按钮的背景颜色设置为深蓝色,而 <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> <st c="12411">和</st><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>
<st c="13847">为此,您可以在</st> <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)
<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> <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>
将 Microsoft Word 文本与 ChatGPT API 集成
在本节中,我们将逐步指导你如何使用 Python 创建两个核心函数,这些函数对于构建文本翻译应用程序至关重要。 <st c="16379">translate_text()</st><st c="16545">browse_file()</st>
<st c="16797">使用 gpt-3.5-turbo 翻译 Word 文本</st>
在本节中,你将学习如何构建 <st c="16888">translate_text()</st>
<st c="17156">translate_text()</st> <st c="17221">config.py</st> <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 密钥后,你现在可以继续在 <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>
-
<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>
-
-
<st c="20152">对话遵循一个模式,前两条消息建立上下文,最后一条消息提供要</st><st c="20285">翻译的文本:</st>-
<st c="20299">第一条消息来自用户的角色,解释了交互的</st><st c="20370">上下文</st> -
第二条消息来自助手的角色,并确认其帮助 -
第三条消息来自用户的角色,包含要翻译的文本,包括 目标语言
-
<st c="20807">role</st> <st c="20889">content</st> <st c="20982">response</st>
<st c="21300">content</st> <st c="21341">choices</st> <st c="21437">content</st> <st c="21493">translated_text</st>
<st c="21805">browse_file()</st>
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)
<st c="22239">browse_file()</st> <st c="22470">translate_text()</st>
<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>
<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>

<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>

<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 电子邮件回复生成器
许多公司已经开始使用人工智能来生成电子邮件回复以节省时间和提高生产力。
<st c="1477">tkinter</st> <st c="1489">openai</st> <st c="1521">win32com</st> <st c="1796">win32com</st> <st c="1939">tkinter</st> <st c="1951">openai</st> <st c="1959">win32com</st>
<st c="2093">win32com</st> <st c="2413">tkinter</st>
-
将 Outlook 数据传递到 ChatGPT API -
生成自动 电子邮件回复
技术要求
-
您的计算机上安装了 Python 3.11 或更高版本 。 -
一个 OpenAI API 密钥 -
一个代码编辑器,例如 VS Code(推荐) -
一个 Windows 操作系统 -
您的设备上安装的 最新 Microsoft Office 365 应用程序(Outlook)
<st c="3440">win32com</st>
将 Outlook 数据传递到 ChatGPT API
<st c="4091">win32com</st>
<st c="4324">EmailReplyGenerator</st> <st c="4472">app.py</st>
<st c="4699">pip</st>
$pip install openai
$pip install pywin32
<st c="5117">config.py</st>
API_KEY = "<YOUR_CHATGPT_API_KEY>"
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> <st c="5654">app.py</st> <st c="5758">openai</st> <st c="5792">win32com.client</st> <st c="5812">tkinter</st>
设置 Outlook 应用程序
-
启动 Microsoft Outlook :在您的计算机上找到 Outlook 应用程序图标,双击它以打开 程序。 -
设置新账户 :首次打开 Outlook 时,您将能够登录到您的电子邮件地址。 只需输入您的电子邮件地址,然后点击 连接 按钮开始设置过程(见 图 7 .1 )。

-
遵循屏幕提示 :Outlook 将尝试根据您的电子邮件地址自动配置账户设置。 您将看到确认消息,并且您的电子邮件账户将被添加到 Outlook。 -
访问您的电子邮件 :设置过程完成后,您可以在 Outlook 导航面板中访问您的电子邮件。 您将能够在 Outlook 应用程序内查看、发送、接收和管理您的电子邮件消息,如图 图 7 .2 所示。

使用 win32com 客户端访问电子邮件数据
<st c="8883">win32com</st> <st c="9027">tkinter</st>
<st c="9162">last_10_emails()</st> <st c="9231">win32com.client</st>
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>
-
首先,我们将使用 <st c="9926">win32com.client.Dispatch()</st>函数来创建与 Outlook 应用程序的连接。 此函数接受一个字符串参数, <st c="10052">Outlook.Application</st>,以指定我们想要访问的应用程序。 -
然后,我们将使用 <st c="10141">GetNamespace()</st>方法,并使用 <st c="10172">MAPI</st>参数来检索 Outlook 中的消息和协作服务命名空间。 此命名空间提供了访问各种 Outlook 对象 和文件夹的权限。 -
通过调用 <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>变量。 -
要检索最新电子邮件的主题, <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>,并允许您检索电子邮件集合中当前访问项之前的电子邮件项,从而实现电子邮件的顺序向后访问 。
<st c="12071">在循环中,我们使用</st> <st c="12193">来访问迭代中当前电子邮件之前的电子邮件的主题。</st><st c="12348">.Subject</st>
<st c="12471">append()</st>
<st c="12695">然后我们可以从</st> <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()
-
首先,我们将使用 <st c="13410">tkinter</st>库来初始化和配置应用程序的主要图形窗口。 <st c="13426">root = tk.Tk()</st>创建了一个主窗口对象,通常被称为根或顶级窗口。 此对象代表包含我们应用程序用户界面元素的 主窗口。 -
然后,我们可以将窗口的标题 设置为 <st c="13690">Outlook Emails</st>。这个标题将在窗口的标题栏中显示。 我们还将设置窗口的尺寸为 <st c="13816">300</st>像素宽和 <st c="13836">300</st>像素高。 这决定了窗口首次在 屏幕上显示时的初始大小。 -
在完成窗口模板后,我们可以初始化用于在用户界面中管理电子邮件主题的变量。 这里使用的 <st c="14088">last_10_emails()</st>函数用于检索电子邮件主题列表。 该函数将 Outlook 应用程序中的最后 10 个电子邮件主题返回到 <st c="14263">email_subjects</st>变量中。 -
<st c="14292">selected_subject</st>变量从 <st c="14328">StringVar</st>对象创建了一个 <st c="14354">tkinter</st>库。 此对象是一种特殊的变量类型,可以与各种 GUI 小部件相关联。 通过创建一个 <st c="14473">StringVar</st>对象,我们有一个可以存储字符串值并轻松与 GUI 元素(如按钮或下拉菜单)相关联的变量。 这使我们能够在 我们的应用程序中跟踪和操作所选电子邮件主题。 -
然后,我们在用户界面中创建一个下拉菜单来显示邮件主题列表。 <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>小部件的一个单独的参数,为下拉菜单提供选项列表。 -
然后,我们可以构建一个标签小部件并启动应用程序的主事件循环。 <st c="15565">label</st>变量创建了一个标签小部件,用于在用户界面中显示文本或其他信息。 <st c="15673">text</st>参数指定了标签中要显示的初始文本,在这种情况下是一个空字符串。 <st c="15783">label.pack()</st>将小部件打包到主窗口中。 -
最后, <st c="15847">root.mainloop()</st>启动主事件循环。 此方法负责处理用户事件,如鼠标点击或按钮按下,并相应地更新 GUI。 程序将保持在这个循环中,直到用户关闭应用程序窗口,确保应用程序保持响应性和交互性。

<st c="17159">selected_subject</st>

<st c="17562">win32com</st> <st c="17678">win32com</st> <st c="17686>和<st c="17698">库来访问和显示电子邮件数据,以创建</st>
生成自动电子邮件回复
<st c="18530">reply()</st>
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
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">DispatchGetDefaultFolder(6)</st> <st c="20057">检索</st> <st c="20052">Inboxselected_subject</st> <st c="20186">获得的主题检索特定的电子邮件项。生成的
client.chat.completions.create()max_tokens
client.chat.completions.create()prompt
为了提高回复的质量和多样性,开发者可以尝试不同的提示。
-
上下文提示 : “你收到一位同事的邮件,请求你参加一个会议。撰写一个 礼貌且简洁的回复,确认 你的出席。” 在这个提示中,模型被明确指示回应同事的会议请求。
通过提供具体场景并要求“礼貌且简洁”的回复,生成的回复更有可能与期望的情境 和语气相符。 -
情感提示 : “你刚刚收到一封来自亲密朋友的邮件,分享了一些令人兴奋的消息。草拟一个 温暖且热情的回复,向他们表示祝贺并分享 你的想法。” 通过在提示中融入情感关键词,如“令人兴奋的消息”、“温暖”和“热情”,模型被鼓励产生传达快乐和支持感的回复,使其听起来更真实、更像人类。
-
正式商务提示 : “作为客户服务代表,你收到一封来自对近期产品问题不满的客户的邮件。 撰写一个专业且富有同理心的回复,以解决他们的担忧并提供 解决方案。” 在这里,提示设定了一个正式的商务背景,指示模型以
客户服务代表的身份回应处理不满的客户。 使用“同理心”一词强调了回复中表现出同情和帮助的重要性,这可能导致更真实和 体贴的回复。 -
个性化提示 : “你的最佳朋友给你发了一封邮件,分享了一些关于他们最近度假的令人兴奋的更新。回复 时,用你真诚的兴奋之情,提出后续问题,并分享一些你生活中的事情。” 这个提示 鼓励更个性化的回复,因为它具体说明了回复应该表达真诚的兴奋之情,并涉及提出后续问题。 通过强调分享发件人生活信息的互惠性,生成的回复可能会感觉更自然,更像是真实的对话。 -
教学提示 :“您收到一封来自同事的邮件,询问如何使用 一款新软件工具的详细说明。 如有必要,请提供带有清晰解释和视觉辅助的逐步指南。” 在这种情况下,提示为模型生成包含详细说明的回复设置了明确的指令。 使用“逐步指南”和“清晰解释”等术语指导模型提供更信息丰富和 结构化的响应。
<st c="25213">email.Reply()</st><st c="25321">response</st>
<st c="25414">reply.Display()</st> <st c="25589">return</st>
<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>

<st c="26736">reply()</st>

-
所选 电子邮件内容 : 嗨,马丁, 我有一个令人兴奋的新功能请求要向您提出。 我们的用户一直在要求一个提供账户活动概述和统计信息的个性化仪表板。 。 如果您能开始这项功能的工作,并给出所需开发 工作量估计,我将不胜感激。 问候, 比尔。 -
GPT-4 API 回复 : 亲爱的比尔, 感谢您的邮件和提出如此令人兴奋的新 功能请求。 个性化仪表板确实是一个极好的补充,将显著提升用户体验。 我理解一个能够为我们用户提供其账户活动全面概述的工具的重要性 和统计数据。 我将立即开始初步工作以评估可能性。 这包括深入了解用户需求,定义必要的功能,以及分析工作 范围。 考虑到这个功能的复杂性和范围,我预计初步估计将在一周内完成。 这将帮助我提供一个准确的开发 工作量估计。 我期待着这个新功能可能对我们用户体验带来的积极影响。 感谢您将这项任务 交给我。 最好的祝愿, 马丁
摘要
<st c="30210">win32com</st> <st c="30288">tkinter</st>
<st c="30598">reply()</st> <st c="30841">reply()</st> <st c="30946">reply()</st>
第九章:8
使用 PyQt 和 ChatGPT API 的论文生成工具
-
使用 PyQT 构建桌面应用程序 -
使用 ChatGPT API 创建论文生成方法 -
控制 ChatGPT API 令牌
技术要求
<st c="2096">PyQt6</st>
-
在您的机器上安装了 Python 3.7 或更高版本 。 -
一个代码编辑器,例如 VS Code (推荐) -
一个 Python 虚拟环境 -
一个 OpenAI API 密钥 -
熟悉 Python 面向对象编程 ( OOP ) 概念
使用 PyQT 构建桌面应用程序
<st c="3282">PyQt6</st> <st c="3292">docx</st>
设置文章生成工具项目
<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>
<st c="8286">EssayGenerator</st>
<st c="8772">EssayGenerator</st> 类将继承自 <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())
-
首先,我们在 <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">在这里被选择,因为它作为大多数用户界面元素的通用基础,并为我们的论文生成应用程序中创建基本窗口提供了必要的功能。` -
<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>`类的特定初始化之前,执行了父类中必要的设置。 -
<st c="10430">然后,</st><st c="10441">initUI()</st><st c="10449">方法负责设置应用程序的用户界面和其他元素,例如窗口标题、大小和位置。</st>它使用内置的 Essay Generator setWindowTitle 方法将应用程序的窗口标题设置为,并指定窗口在屏幕上的位置和大小,其中数字代表窗口左上角的</st>x 和y 坐标,然后是其宽度和</st>高度。 -
通过调用
<st c="10899">super().__init__()</st>和<st c="10911">self.initUI()</st>,我们确保应用程序得到适当的初始化,并且一旦运行它,主应用程序窗口就会启动。这种方法遵循继承原则,其中 <st c="11127">EssayGenerator</st><st c="11141">子类继承并扩展了父类的功能,</st>QWidget `,从而为我们的应用程序创建了一个功能齐全且定制的控件。 -
<st c="11297">在 Python 中,通常使用</st><st c="11333">__name__ == '__main__'</st><st c="11355">条件来确保后续代码仅在脚本作为主模块运行时执行。</st>如果是这样,代码将继续创建 QApplication 类的实例,该实例管理应用程序的 <st c="11570">控制流。</st> -
<st c="11588">ex</st>对象是从 <st c="11618">EssayGenerator</st>类创建的,用于显示应用程序窗口,最后, <st c="11687">sys.exit(app.exec())</st>启动了应用程序的事件循环,确保程序在用户关闭窗口或退出应用程序之前保持活跃。 这允许我们在直接运行脚本时执行应用程序。 您可以通过运行项目来验证这一点,以显示主 应用程序 窗口,如图 *图 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>
<st c="14771">self</st> <st c="15023">self</st>
<st c="15294">QPushButton</st> <st c="15445">clicked.connect()</st>
<st c="15672">generate_essay()</st> <st c="15951">essay_output</st> <st c="16097">save_essay()</st> <st c="16148">docx</st>
<st c="16211">save_essay()</st> <st c="16228">generate_essay()</st> <st c="16359">EssayGeneration</st> <st c="16397">initUI()</st>
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>

<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>

<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>

<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 的惊人能力。
在本章中,我们将展示如何使用 Python 框架和 DALL-E 图像生成自动化 PowerPoint 演示的开发。您将获得利用编程力量简化创建过程的实践经验。
我们将探讨将 DALL-E 和 ChatGPT 这两个强大的 AI 模型集成起来,以构建一个端到端的 PowerPoint 演示生成器应用程序。
在本章中,我们将涵盖以下主题:
-
使用 DALL-E 和 DALL-E API
-
使用 PPTX Python 框架构建 PowerPoint 应用程序
-
使用 DALL-E API 生成艺术作品
-
完成并测试 PowerPoint 演示生成器
到本章结束时,您将通过将 DALL-E 和 ChatGPT API 集成到构建端到端的 PowerPoint 演示生成器应用程序中来提高您的 AI 应用程序开发技能。
技术要求
-
在您的计算机上安装 Python 3.7 或更高版本 -
一个 OpenAI API 密钥,您可以从您的 OpenAI 账户 获取 -
一个代码编辑器,例如 VS Code(推荐),用于编写和编辑 您的代码 -
您 Python 虚拟环境中安装的 Tkinter 框架 -
在您的设备上安装的 PowerPoint 软件
使用 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>
<st c="5303">prompt</st> <st c="5489">size</st> <st c="5601">1024</st> <st c="5616">1024</st>
<st c="5689">response</st> <st c="5881">response</st> <st c="5893">image_url</st>
使用 PPTX Python 框架构建 PowerPoint 应用程序
<st c="6373">pptx</st> <st c="6461">pptx</st>
<st c="6999">PowerPoint Generator</st>
$pip install python-pptx
$pip install openai
$pip install requests
-
<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. -
<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. -
<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.
<st c="7999">app.py</st> <st c="8010">config.py</st>
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,
)
API_KEY = "YOUR_API_KEY"
<st c="8322">在这里,</st> <st c="8412">它导入各种库和</st> <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> <st c="9364">它包含 API 密钥,由</st> <st c="9484">进行身份验证所需的。</st> 通过将 API 密钥分离到配置文件中,可以更容易地管理和更新密钥,而无需直接修改主应用程序代码。</st>
<st c="9741">接下来,在我们的</st> <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>
<st c="10510">tk.Tk()</st> <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>
<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><st c="13312">1920</st> <st c="13337">1080</st>
<st c="13423">paragraphs</st> <st c="13464">slide_generator()</st>
<st c="13839">my_presentation.pptx</st>
<st c="14281">get_slides()</st>

<st c="14549">slide_generator()</st>
<st c="14723">slide_generator()</st>
使用 DALL-E API 生成艺术作品
<st c="15508">slide_generator()</st> <st c="15733">app.py</st> <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> <st c="16906">text</st><st c="16951">prs</st>
<st c="17012">prompt</st><st c="17106">text</st>
<st c="17243">The</st> <st c="17248">create()</st> <st c="17393">dlp</st> <st c="17529">dalle_prompt</st> <st c="17557">dalle_prompt</st>
<st c="17646">现在,我们可以开始使用 DALL-E API 生成图像,该图像基于在</st> <st c="17764">函数中创建的 DALL-E 提示。</st> <st c="17775">我们调用</st>
-
<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 根据文本输入生成具有数字艺术风格的图像。 您可以根据 您的喜好更改此风格。 -
<st c="18246">n</st>: 这指定了要生成的图像数量。 在这种情况下,我们只请求 一张图像。 -
<st c="18339">size</st>: 这设置了生成的图像所需的大小。 在这里,它被指定为 <st c="18423">1024x1024</st>像素,这是 最高品质的风格。
<st c="18476">DALL-E API 的响应</st> <st c="18490">存储在</st> <st c="18535">变量中。</st> <st c="18546">它</st> <st c="18549">包含有关生成的图像的信息,包括其 URL。</st> <st c="18616">生成的图像的 URL 从响应中提取并分配给</st><st c="18707">变量。</st> <st c="18718">此 URL 可用于在我们的</st>
<st c="18808">在这个部分,我们构建了</st>
完成并测试 PowerPoint 演示文稿生成器
<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> <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> <st c="21961">ppt.choices[0].message.content</st> <st c="22012">ppt_header</st>
# 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
-
首先,使用 <st c="22816">add_slide()</st>方法将新幻灯片添加到演示文稿中。 该方法接受所需的幻灯片布局作为参数,在这种情况下表示内容幻灯片的布局。 -
接下来,通过 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>英寸处。 -
使用 <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 生成的文本。 -
最后,访问幻灯片的 标题形状。 包含生成的标题文本的 <st c="23881">ppt_header</st>变量被分配给 <st c="23958">title_shape.text</st>。这设置了幻灯片的标题为 AI 生成的标题。
<st c="24355">app.py</st>
<st c="24577">app.py</st>
您可以选择使用提供的文本,或者根据您的偏好进行实验性的文本输入。

图 9.2 – 使用文本输入填充 PowerPoint 演示文稿生成器应用
重要提示
确保在每段之间包含一个双行空格,以正确地表示段落之间的分隔,使您的应用能够准确地识别和区分它们。
现在,您可以通过点击创建幻灯片按钮来根据输入的文本生成 PowerPoint 幻灯片。请耐心等待几秒钟;您的演示文稿将迅速生成并保存在您项目的主目录中。
重要提示
OpenAI 有一个速率限制,指定了每分钟允许使用的令牌数量。如果您广泛使用该应用,可能会达到免费试用版的速率限制,目前为每分钟 40,000 个令牌。
打开演示文稿后,您将看到三张幻灯片,每张幻灯片对应输入文本的一个段落。这些幻灯片将展示由 DALL-E 创建的引人入胜的 AI 艺术图像,配有简洁的项目符号和每张幻灯片的独特标题(见图 9

图 9.3 – PowerPoint 演示文稿生成器应用生成的幻灯片
为了增强幻灯片上元素的可视布局,您可以使用 PowerPoint 内置的设计器选项,它方便地位于右上角。
这是完成和测试 DALL-E AI 演示文稿生成器的完整过程。您学习了如何生成幻灯片标题、项目符号和 AI 生成的图像。我们介绍了如何构建 AI 提示并检索生成的内容。本节还概述了如何使用生成的图像、项目符号和标题填充 PowerPoint 演示文稿。
摘要
<st c="29737">pptx</st> <st c="29853">get_slides()</st>
<st c="29961">slide_generator()</st>
第十一章:10
使用 Whisper API 进行语音识别和语音合成
-
使用 Whisper API 实现文本翻译和转录 -
构建语音 转录应用程序 -
使用 PyDub 处理更长的音频输入
技术要求
-
确保您的机器已安装 Python 3.7 或更高版本 。 -
拥有代码编辑器,如 VSCode(推荐) 设置 -
创建一个 Python 虚拟环境 -
获取 OpenAI API 密钥 -
在您的项目中安装 PyDub
使用 Whisper API 实现文本翻译和转录
<st c="3965">WhisperAPI</st>
$pip install openai
$pip install pydub
$brew install ffmpeg
<st c="5223">config.py</st>
<st c="5354">config.py</st>
-
在您的项目视图区域上右键点击。 -
从 上下文菜单 中选择 新建文件 。 -
将文件命名为 <st c="5503">config.py</st>并 按 Enter 。
<st c="5556">config.py</st>
API_KEY = "YOUR_API_KEY"
<st c="5787">audio_files</st>
<st c="5997">audio_files</st>
-
在您的项目视图区域上右键点击。 -
从 上下文菜单 中选择 新建文件夹 。 -
将目录命名为 <st c="6136">audio_files</st>并 按 Enter 。
<st c="6286">transcribe.py</st>
<st c="6642">audio_files</st> <st c="6712">apple.mp3</st>
<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>
-
一旦您的音频 文件就绪,您可以通过向 <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 密钥中的值。 -
然后,我们以读取二进制模式打开一个名为 <st c="7929">apple.mp3</st>的文件,该文件位于 <st c="7954">audio_files/apple.mp3</st>本地文件路径中, <st c="8013">rb</st>。这表明代码的意图是读取一个 音频文件。 -
之后,调用了 <st c="8092">client.audio.transcriptions.create()</st>函数,并传入两个参数: <st c="8168">whisper-1</st>和打开的音频文件。 此函数是 OpenAI 库的一部分,用于转录音频文件。 其中, <st c="8295">whisper-1</st>参数 是 OpenAI 系统中的特定 转录模型。 -
最后,我们在 控制台中看到了转录的结果: <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>
<st c="8803">text</st>
<st c="9361">german.mp3</st>
<st c="9526">mp3</st>
<st c="9657">translate.py</st>
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)
<st c="10027">client.audio.translations.create()</st> <st c="10100">whisper-1</st> <st c="10151">whisper_file</st>
<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!" }
构建语音转录应用程序
<st c="12487">app.py</st>
<st c="12610">app.py</st>
<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> <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> <st c="15602">tk.Tk()</st><st c="15640">Whisper</st> <st c="15648">转录应用程序</st>
<st c="15704">tk.Text()</st><st c="15821">tk.Button()</st><st c="15863">选择音频文件</st><st c="15890">command</st> <st c="15918">transcribe_audio</st><st c="15984">transcribe_audio()</st>
-
在 VSCode 中,找到 <st c="16131">app.py</st>文件并 运行它。 -
一旦应用程序运行,将出现一个标题为 Whisper 转录应用程序 的 Tkinter 窗口。 -
窗口将显示一个文本区域,其中将显示转录的文本。 -
点击 选择音频文件 按钮。 将打开一个文件对话框窗口,允许您浏览您的 文件系统。 -
找到并选择您想要 转录的 MP3 音频文件。

通过运行应用程序并选择一个 MP3 文件,您将能够见证 Whisper API 的转录功能在行动中。20 min就能深入理解知识点,而且记忆深刻,难以遗忘。
在本节中,我们开始了语言转录应用程序的开发,集成了 Tkinter 和 Whisper API。
在下一节中,您将学习如何将 PyDub 与 Whisper API 集成以克服文件大小限制,并有效地分割大型音频文件以实现无缝转录。
使用 PyDub 处理较长的音频输入
在本节中,我们将探讨
利用 PyDub 的强大功能来增强您的语言转录工作流程是一个简单的过程。
在这个练习中,我们使用了一个大约十一分钟的 iPhone 评测音频文件。<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>
<st c="20677">phone.mp3</st>
<st c="20885">openai</st> <st c="20896">AudioSegment</st> <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> <st c="21487">export()</st>
<st c="21674">last_min_5</st> <st c="21754">phone_last_5.mp3</st>
<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." }
<st c="22823">大小限制</st>
总结
第四部分:为 ChatGPT 应用提供高级概念
-
第十一章 , 选择正确的 ChatGPT API 模型 -
第十二章 , 微调 ChatGPT 以创建独特的 API 模型
第十二章:11
选择正确的 ChatGPT API 模型
-
ChatGPT API 模型 – GPT-3.5,GPT-4, 以及更多 -
使用聊天 完成参数 -
ChatGPT API 速率限制 -
OpenAI 嵌入
技术要求
-
Python 3.7 或更高版本已安装在你的 计算机上 -
一个 OpenAI API 密钥,你可以通过注册一个 OpenAI 账户 来获取 -
一个代码编辑器,例如 VS Code(推荐),用于编写和执行 Python 代码
ChatGPT API 模型 – GPT-3.5、GPT-4 以及更多
| <st c="3893>$20.00 / |
|||
| <st c="4008>$45.00 / |
|||
| <st c="4141>$1.00 / |
|||
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("----------------------------------------")
<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
----------------------------------------
<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 参数,并探讨它们对模型生成响应质量产生的深远影响。
-
<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>
<st c="12403">温度</st> <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>
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">当您增加 <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">这将提供四个不同的猫名,展示了通过增加 所获得的响应多样性的增加。</st> <st c="17924">通过修改 <st c="17959">generate_response</st> <st c="17976">函数中的值,您可以尝试不同的数字来探索更广泛的建议或
通过增加<st c="18141">n</st> <st c="18156">,您增加了生成响应的多样性,这允许您探索不同的观点、创意想法或针对给定问题的替代解决方案。</st> <st c="18323">然而,需要注意的是,增加 <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 施加的速率限制。
ChatGPT API 速率限制
速率限制在维护 ChatGPT API 的稳定性和公平性方面发挥着至关重要的作用。
-
防止滥用和误用 :速率限制有助于保护 API 免受恶意行为者的攻击,他们可能会通过发送过多的请求来试图超载系统。 通过设置速率限制,OpenAI 可以减轻此类活动,并维护所有用户的 服务质量。 -
确保公平访问 :通过限制单个用户或组织可以发起的请求数量,速率限制确保每个人都有平等的机会使用 API。 这防止了少数用户垄断资源,从而对其他人造成 减速。 -
管理服务器负载 :通过速率限制,OpenAI 可以有效地管理其基础设施的整体负载。 通过控制传入请求的速率,服务器可以更有效地处理流量,最小化性能问题,并确保所有用户都能获得一致的体验。
-
<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 张图片
-
使用指数退避重试 :实现指数退避是一种处理速率限制错误的可靠策略。 当发生速率限制错误时,您可以在短暂的延迟后自动重试请求。 如果请求再次失败,您将在每次后续重试之前指数级增加延迟。 这种方法允许在不过度压倒系统的情况下进行有效的重试,如下所示: 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,但仍有许多未使用的令牌 剩余。 在这种情况下,您可以选择通过将多个任务合并为一个 单独的请求来提高请求的效率。
<st c="26380">max_tokens</st>
在接下来的部分中,我们将学习关于 OpenAI 嵌入的内容,探讨其重要性、应用以及优化技术。
OpenAI 嵌入
在人工智能不断演变的领域中,非结构化数据的处理和解释提出了重大挑战。
OpenAI 提供了在创建嵌入方面表现卓越的尖端模型,尤其是在文本数据方面。
首先,让我们揭开嵌入(embeddings)的本质。
嵌入就像是数据的 DNA,提供了一种结构化的表示,计算机可以轻松理解和操作。
为了实现这一点,你创建了一个复杂的系统,其中每本书都由一组属性表示——可能是它们的类型、作者、出版年份和主题。</st c="28249">这些属性共同形成每本书的多维向量,将其定位在一个反映其特性的概念空间中。</st c="28402">具有相似属性的书籍在这个空间中聚集在一起,反映了它们的主题或</st c="28493">概念上的相似性。
在这个类比中,嵌入(embeddings)充当组织图书馆的蓝图。
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)
<st c="31765">cosine_similarity</st> <st c="31850">get_embedding</st><st c="31947">compare_sentences</st> <st c="31988">get_embedding</st>
Similarity: [[0.69882148]]
<st c="32563">sentence2</st>
Similarity: [[0.0532481]]
摘要
在本章中,我们探讨了各种 ChatGPT API 模型。
第十三章:12
微调 ChatGPT 以创建独特的 API 模型
<st c="627">gpt-3.5-turbo</st>
-
微调 ChatGPT 和 数据集准备 -
构建和使用 微调模型
技术要求
-
您的机器上已安装 Python 3.7 或更高版本 -
OpenAI API 密钥 -
已安装 OpenAI Python 库
微调 ChatGPT 和数据集准备
在本节中,您将了解微调 ChatGPT 模型的过程。<st c="2423">openai</st>
微调以多种方式增强了 API 模型的能力。
GPT-3.5 已经在来自互联网的大量文本语料库上进行了广泛的预训练。
如果一个模型已经经过微调,我们可以使用生成的模型,而无需传递任何进一步的训练数据。

在微调过程中,有必要以 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."}]}
<st c="5145">数据点</st>的完整 JSONL 文件。
<st c="6288">Fine Tune</st><st c="6498">openai</st>
$ pip install --upgrade openai
<st c="6663">openai</st>
-
<st c="6839">main.py</st>:这里将存放用于微调 ChatGPT 模型 -
<st c="6916">train_data.jsonl</st>: 这将保存 JSONL 训练数据集
<st c="7086">main.py</st>
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=
微调作业(id=
<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>

浙公网安备 33010602011771号