如何使用ChatGPT辅助编程:通过引导自动生成编程代码

大型语言模型基本上是一台可以理解和生成文本的机器。取决于它的训练方式,有时模型可以生成文本以外的内容。ChatGPT就是这样一个大型语言模型。如果您正确提示,它可以生成编程代码。在这篇文章中,您将学习如何使 ChatGPT 为您生成程序。

如何使用ChatGPT辅助编程:通过引导自动生成编程代码
在线工具推荐:三维数字孪生场景工具 - GLTF/GLB在线编辑器 - Three.js AI自动纹理化开发 - YOLO 虚幻合成数据生成器 - 3D模型在线转换 -  3D模型预览图生成服务

大型语言模型基本上是一台可以理解和生成文本的机器。取决于它的训练方式,有时模型可以生成文本以外的内容。ChatGPT就是这样一个大型语言模型。如果您正确提示,它可以生成编程代码。在这篇文章中,您将学习如何使 ChatGPT 为您生成程序。具体来说,您将学习

  • 如何使 ChatGPT 引导您的编程项目
  • 如何使用 ChatGPT 作为您的编程助手

让我们开始吧。

使用ChatGPT作为您的编程助手
作者使用稳定扩散生成的图片。保留部分权利。

概述

这篇文章分为两部分;它们是:

  • 启动编程项目
  • 了解代码和生成函数片段

启动编程项目

让我们考虑一个简单的项目:你想要设置一个 REST API 服务器,它可以帮助你对提供的 URL 的整个网页进行“屏幕截图”。(可选)REST API 可以接受电子邮件地址的其他可选参数。在这种情况下,屏幕捕获不会返回,而是通过电子邮件发送出去。

这是一个涉及多个组件的项目。你需要一些可以像 REST API 服务器一样监听 HTTP 请求并做出相应响应的东西。您还需要一些东西来获取 URL 并像普通 Web 浏览器一样截取屏幕截图。其中还有一个逻辑,取决于是否提供了电子邮件地址;输出可以是返回的图像文件,也可以是发送带有附件的电子邮件。

如果您不熟悉如何创建 REST API 服务器或不知道可用的工具,可以向 ChatGPT 寻求帮助。只需在提示中写下所有细节并询问:

我需要创建一个 REST API 服务器,该服务器接受 URL 作为输入,将网页屏幕截图捕获为 JPEG 格式并将其作为输出返回。(可选)用户可以提供电子邮件地址作为附加输入。在这种情况下,屏幕截图应通过电子邮件发送而不是返回。你能帮我这个程序吗?

有了这个,ChatGPT产生以下建议:

当然!我可以帮你。要创建捕获网页屏幕截图并处理可选电子邮件功能的 REST API 服务器,您可以使用 Node.js以及一些其他包。以下是您可以遵循的步骤的概述:

1. 设置一个新的 Node.js 项目并使用 npm 对其进行初始化:
1
2
3
mkdir screenshot-api
cd screenshot-api
npm init
2. 安装必要的软件包。您需要 API 服务器、捕获屏幕截图和发送电子邮件:expresspuppeteernodemailer
1
npm install express puppeteer nodemailer
3. 使用 Express 创建文件并设置基本服务器:index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const express = require('express');
const app = express();
const port = 3000;
 
app.get('/screenshot', async (req, res) => {
  const url = req.query.url;
  const email = req.query.email;
 
  // Capture the screenshot using Puppeteer
 
  // Handle the response based on whether an email is provided
 
});
 
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});
4. 在路由内,使用 Puppeteer 捕获网页截图并相应地处理响应:/screenshot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const puppeteer = require('puppeteer');
 
app.get('/screenshot', async (req, res) => {
  const url = req.query.url;
  const email = req.query.email;
 
  // Launch Puppeteer
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
 
  // Navigate to the provided URL
  await page.goto(url);
 
  // Capture the screenshot
  const screenshotBuffer = await page.screenshot({ fullPage: true });
 
  // Close the browser
  await browser.close();
 
  // Handle the response based on whether an email is provided
  if (email) {
    // Send the email with the screenshot attachment using Nodemailer
 
  } else {
    // Send the screenshot as the response
    res.type('image/jpeg');
    res.send(screenshotBuffer);
  }
});
5.要处理发送带有屏幕截图附件的电子邮件,请在块内添加以下代码:if (email)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const nodemailer = require('nodemailer');
 
// Create a transporter using your email service provider's details
const transporter = nodemailer.createTransport({
  service: 'your-email-service-provider',
  auth: {
    user: 'your-email@example.com',
    pass: 'your-email-password',
  },
});
 
// Define the email options
const mailOptions = {
  from: 'your-email@example.com',
  to: email,
  subject: 'Web Page Screenshot',
  text: 'Please find the attached screenshot.',
  attachments: [
    {
      filename: 'screenshot.jpg',
      content: screenshotBuffer,
    },
  ],
};
 
// Send the email
transporter.sendMail(mailOptions, (error, info) => {
  if (error) {
    console.error(error);
    res.status(500).send('Failed to send email.');
  } else {
    console.log(`Email sent: ${info.response}`);
    res.send('Screenshot emailed successfully!');
  }
});

确保将 、 替换为实际电子邮件服务提供商的详细信息。'your-email-service-provider''your-email@example.com''your-email-password'

6. 最后,启动服务器:

1
node index.js

现在,当您向 发出 GET 请求时,服务器将捕获所提供 URL 的屏幕截图。如果电子邮件地址也作为 提供,服务器会将屏幕截图作为电子邮件附件发送,而不是直接返回。http://localhost:3000/screenshot?url={URL}email={EMAIL}

请记住处理错误,并根据您的要求添加任何必要的错误检查或验证。

就是这样!您现在有一个基本的 REST API 服务器,该服务器可以捕获网页屏幕截图并选择性地通过电子邮件发送它们。请随时根据您的需要进一步增强它。

这是一个非常详细的结果,告诉您如何完成此编程任务。响应涵盖了所有要求,但您应该注意到,当您没有在提示中明确指定时,ChatGPT 将为您做出一些设计决策,例如使用哪种编程语言。

在第一次运行时考虑所有细节并不容易,但 ChatGPT 的性质允许您提供后续提示来修改答案,例如:

对于上述问题,我想使用Python和FastAPI作为Web框架,Selenium作为Web浏览器。你能重写这个吗?

来自 ChatGPT 的响应现在变为:

当然!以下是该解决方案的修订版本,使用Python,FastAPI作为Web框架,Selenium用于Web浏览器自动化。

1. 安装必要的软件包。您需要 来运行服务器和管理 Web 驱动程序:fastapiuvicornseleniumwebdriver_manager
1
2
pip install fastapi uvicorn selenium webdriver_manager
 
2. 创建一个名为的新文件并导入所需的模块:main.py
1
2
3
4
5
6
7
8
9
10
11
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from pydantic import BaseModel
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import WebDriverException
from io import BytesIO
 
app = FastAPI()
 
3. 定义一个请求模型来处理输入数据:
1
2
3
4
class ScreenshotRequest(BaseModel):
    url: str
    email: str = None
 
4.创建捕获网页屏幕截图的路线:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@app.get("/screenshot")
async def capture_screenshot(request: ScreenshotRequest):
    options = Options()
    options.headless = True
 
    try:
        # Set up the Chrome webdriver
        driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
        driver.set_window_size(1280, 720)
 
        # Navigate to the provided URL
        driver.get(request.url)
 
        # Capture the screenshot
        screenshot = driver.get_screenshot_as_png()
        screenshot_buffer = BytesIO(screenshot)
 
        # Close the browser
        driver.quit()
 
        if request.email:
            # Send the email with the screenshot attachment
 
            return "Screenshot emailed successfully!"
        else:
            # Return the screenshot as a response
            return FileResponse(screenshot_buffer, media_type="image/png")
    except WebDriverException:
        raise HTTPException(status_code=400, detail="Failed to capture screenshot.")
 
5. 使用 Uvicorn 启动服务器:
1
uvicorn main:app --reload

现在,当您向 发出 GET 请求时,服务器将捕获所提供 URL 的屏幕截图。如果电子邮件地址也以 形式提供,则可以使用请求中的字段处理发送带有屏幕截图附件的电子邮件。http://localhost:8000/screenshot?url={URL}email={EMAIL}email

请记住处理错误,并根据您的要求添加任何必要的错误检查或验证。

注意:此解决方案假定您的计算机上安装了 Chrome。如果您使用的是其他浏览器,则需要相应地调整网络驱动程序。

就是这样!您现在有一个使用 Python、FastAPI 和 Selenium 的 REST API 服务器来捕获网页屏幕截图并处理可选的电子邮件功能。

您可以看到,除了引用“上述问题”之外,您在后续提示中没有提供任何不必要的细节,但 ChatGPT 可以准确地将 Node.js 实现“翻译”为 Python 并使用您指定的库。

这是一个很棒的结果,尽管您可能仍然需要完善代码。一个例子是浏览器屏幕大小肯定会影响网页的呈现方式,但大小在上面是硬编码的,因为您没有指定它应该在提示中调整。完善生成的代码的另一个潜在原因是捕获其他编码样式问题或添加针对安全问题的防御措施。

总之,与其他用例一样,您在提示中输入的足够清晰的细节越多,是有用响应的关键。在编程任务的情况下,布置细节至关重要

  • 目标是什么
  • 什么是输入和输出格式
  • 程序应该使用哪些工具
  • 程序可能遇到的不同情况是什么,以及应该如何处理这些情况

了解代码和生成函数片段

有时,您要编写的不是大型程序,而是较小的函数。你可以要求 ChatGPT 使用类似于上面的提示为你生成一个函数,只是你需要指定输出格式,比如函数或类。

事实上,你也可以反过来做,即向 ChatGPT 提供一个代码,并要求它用英语解释。它有时很有用,尤其是破译其他人的代码。让我们考虑以下示例:

请解释以下代码在做什么:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
```
float det(float** a, float k) {
  float s = 1, ret = 0, **b;
  int i, j, m, n, c;
  if (k == 1) {
    return a[0][0];
  } else {
    b = (float**) malloc(sizeof(float*)*k);
    for (i = 0; i < k; i++)
      b[i] = (float*) malloc(sizeof(float)*k);
    ret = 0;
    for (c = 0; c < k; c++) {
      m = 0;
      n = 0;
      for (i = 0; i < k; i++) {
        for (j = 0; j < k; j++) {
          b[i][j] = 0;
          if (i != 0 && j != c) {
            b[m][n] = a[i][j];
            if (n < (k - 2))
              n++;
            else {
              n = 0;
              m++;
            }
          }
        }
      }
      ret = ret + s * (a[0][c] * det(b, k - 1));
      s = s * -1;
    };
    for (i = 0; i < k; i++)
      free(b[i]);
    };
    free(b);
  return ret;
}
```

这个提示很简单:只有一个关键字,“解释”。但请注意如何向 ChatGPT 提供代码:反引号的使用遵循 Markdown 的代码围栏语法来引用程序。这有助于确定哪些是您的指令,哪些不是。

虽然这不是一个很长的程序,但 ChatGPT 非常详细地解释了代码。它还在高层次上确定了意图,即计算矩阵的行列式。以下是响应:

您提供的代码是使用拉普拉斯展开计算方阵行列式的递归实现。

以下是代码功能的分步细分:
  1. 该函数采用两个参数:指向表示矩阵的 2D 数组 () 和矩阵大小的指针 ()。detfloat** afloat k
  2. 它声明了一些变量:符号、行列式值和临时矩阵。sret**b
  3. 它检查是否等于 1。如果是这样,则意味着我们已经达到了 1×1 矩阵的基本情况,并且该函数返回矩阵中的单个值,这是行列式。k
  4. 如果大于 1,则继续计算。k
  5. 它为大小为 x 的临时矩阵动态分配内存。bkk
  6. 它初始化为 0。ret
  7. 它进入一个循环,循环遍历矩阵第一行的每一列。a
  8. 在循环内部,它将索引重置为 0。mn
  9. 它进入一个嵌套循环,该循环遍历矩阵的每个元素。a
  10. 在嵌套循环中,它将临时矩阵中位置 的元素设置为 0。bmn
  11. 它检查当前元素是否不在第一行 () 中,也不在当前列 () 中。i != 0j != c
  12. 如果元素不在第一行或当前列中,它将值从矩阵复制到位置 ,的临时矩阵。abmn
  13. 它更新索引,并根据下一个元素在 中的位置。mnb
  14. 在嵌套循环之后,它通过使用临时矩阵和大小递归调用函数来计算子矩阵的行列式。bdetbk - 1
  15. 它将子矩阵的行列式乘以符号(交替符号)。s
  16. 它将符号乘以 -1 以将符号切换为下一次迭代。s
  17. 它将符号的乘积、第一行 () 中的元素和子矩阵的行列式添加到运行和中。a[0][c]ret
  18. 循环继续到下一列。
  19. 循环后,它释放为临时矩阵的每一行分配的内存。b
  20. 它释放了为临时矩阵分配的内存。b
  21. 最后,它返回计算出的行列式值。ret
总之,该代码通过沿第一行执行拉普拉斯展开来递归计算方阵的行列式。它使用临时矩阵来存储通过排除第一行和所选列获得的子矩阵。递归一直持续到达到 1×1 矩阵的基数。

跟进以改进代码

乍一看,这段代码并不容易理解。可能有一种方法可以使其更易于阅读。事实上,ChatGPT 在这种情况下可以做得很好,只需一个非常简单的后续提示:

为了清楚起见,您可以重写此代码并添加注释吗?

这里的关键字是“为了清楚起见”和“添加评论”。ChatGPT 提供以下内容作为响应:

当然!下面是代码的修订版本,其中包含解释每个步骤的注释:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
float determinant(float** matrix, int size) {
  float sign = 1; // Sign of the determinant
  float result = 0; // Determinant value
  float** submatrix; // Temporary submatrix
  int i, j, m, n, c; // Loop variables
 
  // Base case: 1x1 matrix
  if (size == 1) {
    return matrix[0][0];
  }
  else {
    // Allocate memory for the temporary submatrix
    submatrix = (float**)malloc(sizeof(float*) * size);
    for (i = 0; i < size; i++) {
      submatrix[i] = (float*)malloc(sizeof(float) * size);
    }
 
    // Calculate the determinant
    for (c = 0; c < size; c++) {
      m = 0;
      n = 0;
 
      // Create the submatrix by excluding the first row and the current column
      for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
          submatrix[i][j] = 0;
 
          // Copy values to the submatrix
          if (i != 0 && j != c) {
            submatrix[m][n] = matrix[i][j];
 
            // Update submatrix indices
            if (n < (size - 2)) {
              n++;
            }
            else {
              n = 0;
              m++;
            }
          }
        }
      }
 
      // Calculate the determinant of the submatrix recursively
      result += sign * matrix[0][c] * determinant(submatrix, size - 1);
 
      // Flip the sign for the next iteration
      sign *= -1;
    }
 
    // Free the memory allocated for the submatrix
    for (i = 0; i < size; i++) {
      free(submatrix[i]);
    }
    free(submatrix);
 
    return result;
  }
}
 
我在代码的每个重要部分上方添加了注释,以解释它的作用。这应该使代码更具可读性和更易于理解。

这个版本无疑更容易阅读。

此外,您可以要求更多。例如要求捕获代码中的错误或潜在的安全问题。让我们让 ChatGPT 生成一些单元测试代码:

你能给我几个单元测试用例来确保这个函数运行良好吗?

不需要任何进一步的解释,以下是响应:

当然!以下是一些单元测试用例,用于验证函数的正确性:determinant

测试用例 1:2×2 矩阵
1
2
3
4
5
float matrix1[2][2] = {{2, 3},
                       {1, 4}};
float** ptrMatrix1 = (float**)matrix1;
float det1 = determinant(ptrMatrix1, 2);
// Expected output: 5
测试用例 2:3×3 矩阵
1
2
3
4
5
6
float matrix2[3][3] = {{6, 1, 1},
                       {4, -2, 5},
                       {2, 8, 7}};
float** ptrMatrix2 = (float**)matrix2;
float det2 = determinant(ptrMatrix2, 3);
// Expected output: -306
测试用例 3:4×4 矩阵
1
2
3
4
5
6
7
float matrix3[4][4] = {{1, 0, 2, -1},
                       {3, 0, 0, 5},
                       {2, 1, 4, -3},
                       {1, 0, 5, 0}};
float** ptrMatrix3 = (float**)matrix3;
float det3 = determinant(ptrMatrix3, 4);
// Expected output: -20
这些测试用例涵盖不同大小(2×2、3×3 和 4×4)的矩阵,并包括正、负和零行列式值。通过将计算出的行列式值与预期输出进行比较,可以验证函数是否正常工作。determinant

但很明显,单元测试代码遗漏了一个极端情况:1×1 矩阵。这表明ChatGPT并不总是完美的。您应该仅将其用作助手,而不应将其用作替代品。您应始终验证结果。

总结

在这篇文章中,您看到了 ChatGPT 如何帮助您编程。它不仅可以生成代码作为对您的问题的回答的一部分,还可以找出您提供的代码的意图。具体来说,您已经了解到:

  • 您可以使用 ChatGPT 为您的软件项目生成初始代码,或为函数生成测试代码
  • 你可以让ChatGPT向你解释代码
  • 你可以利用 ChatGPT 来重构和清理代码

3D建模学习工作室 翻译整理,转载请注明出处!

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号