文章开始之前,推荐一些别人写的很好的文章!感兴趣的也可以去读一下哦!
今日推荐:MySQL索引原理揭秘:构建高效数据库的核心技术
文章链接:https://cloud.tencent.com/developer/article/2471823
文章总结了MySQL的经典三个技术问题,从原理上剖析问题的重点,是一篇非常值得深度的文章,对初学者非常有用。
🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。 🏆《近期荣誉》:2022年度博客之星TOP2,2023年度博客之星TOP2,2022年华为云十佳博主,2023年华为云十佳博主等。 🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。 🏆🎉欢迎 👍点赞✍评论⭐收藏
随着人工智能技术的快速发展,越来越多的开发者开始利用像ChatGPT这样的智能助手来提升工作效率和解决问题。然而,如何有效地与这些智能工具进行沟通,尤其是在软件开发领域,往往决定了最终的结果和体验。这就引出了“提示工程”(Prompt Engineering)的概念——通过优化问题的表达方式,使AI更好地理解需求和上下文。
本文将深入探讨面向软件开发的提示工程,重点介绍如何构建高效的提问策略,以便让ChatGPT更准确地理解您的意图和需求。我们将分享一些实用的技巧和示例,帮助您明确问题、提供必要的上下文,并引导AI生成更符合期待的回答。
无论您是刚入门的开发者,还是希望提高与AI互动能力的资深工程师,这篇文章都将为您提供有价值的见解和实践建议。让我们一起探索如何通过有效的提问,让ChatGPT成为您软件开发过程中的得力助手,助力项目的顺利推进!
OpenAI 提供了一些关于 Prompt 的指导性建议:
此外,我们还可以提供案例,并尽可能提供足够的上下文,以帮助模型更好地理解问题的背景和意图。接下来将举一些例子,让读者有更直观的感受。
我们通过对比,再来感受下清晰、明确的 Prompt是怎样的。
先看一个粗略的 Prompt:
请用JavaScript 写一个贪吃蛇的游戏。
得到html文件和js文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>贪吃蛇游戏</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #333;
}
canvas {
background-color: #000;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<script src="snake.js"></script>
</body>
</html>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const canvasSize = canvas.width;
const tileCount = canvasSize / gridSize;
let snake = [{ x: 10, y: 10 }];
let direction = { x: 0, y: 0 };
let food = { x: 15, y: 15 };
let score = 0;
function getRandomFoodPosition() {
const x = Math.floor(Math.random() * tileCount);
const y = Math.floor(Math.random() * tileCount);
return { x, y };
}
function drawRect(x, y, color) {
ctx.fillStyle = color;
ctx.fillRect(x * gridSize, y * gridSize, gridSize, gridSize);
}
function update() {
const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };
if (head.x === food.x && head.y === food.y) {
snake.unshift(head);
score += 10;
food = getRandomFoodPosition();
} else {
snake.pop();
snake.unshift(head);
}
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount || snake.slice(1).some(segment => segment.x === head.x && segment.y === head.y)) {
resetGame();
}
}
function draw() {
ctx.clearRect(0, 0, canvasSize, canvasSize);
snake.forEach(segment => drawRect(segment.x, segment.y, 'lime'));
drawRect(food.x, food.y, 'red');
ctx.fillStyle = 'white';
ctx.font = '16px Arial';
ctx.fillText(`Score: ${score}`, 10, 20);
}
function resetGame() {
snake = [{ x: 10, y: 10 }];
direction = { x: 0, y: 0 };
score = 0;
food = getRandomFoodPosition();
}
window.addEventListener('keydown', (e) => {
switch (e.key) {
case 'ArrowUp':
if (direction.y === 0) direction = { x: 0, y: -1 };
break;
case 'ArrowDown':
if (direction.y === 0) direction = { x: 0, y: 1 };
break;
case 'ArrowLeft':
if (direction.x === 0) direction = { x: -1, y: 0 };
break;
case 'ArrowRight':
if (direction.x === 0) direction = { x: 1, y: 0 };
break;
}
});
function gameLoop() {
update();
draw();
}
resetGame();
setInterval(gameLoop, 100);
感兴趣的读者可以试试,ChatGPT立刻就能生成一个可运行的贪吃蛇游戏的代码。原因很简单,贪吃蛇是一个大众熟知的游戏,ChatGPT已经把相关源代码都存储在它的知识库了。
那么如何让 ChatGPT 输出一个定制化的贪吃蛇游戏的代码呢?我们举一个例子:
请用JavaScript 写一个贪吃蛇游戏,要求如下:
1.点击方向键时游戏开始,程序会选择一个随机的方向作为蛇的移动方向。可以用方向键控制贪吃蛇移动。
2.开始时,贪吃蛇用一个绿色的方格表示,食物用红色方格表示,食物与贪吃蛇间隔一段距离。
3.贪吃蛇每吃一点食物就增加一个坐标的长度,增加部分的色与蛇的颜色一样。
4.游戏每一局有一个积分、开始时积分为0。贪吃蛇每吃一个食物、增加2的幂次方积分。比如第一次增加1分,第二次增加2分,第五次增加16分。
5.游戏在贪吃蛇撞墙或撞到自己时结束,游戏结束时,在游戏区域显示最终的积分。
6.游戏区域是一个400x400像素的矩形区域,由20x20个方格组成。
7.所有CSS和JavaSenpt代码都写在同一个HTML文件中。
得到代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>贪吃蛇游戏</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
#gameArea {
width: 400px;
height: 400px;
background-color: #000;
display: grid;
grid-template-columns: repeat(20, 20px);
grid-template-rows: repeat(20, 20px);
position: relative;
}
.snake {
background-color: green;
grid-column-start: 1;
grid-row-start: 1;
}
.food {
background-color: red;
}
#score {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 16px;
}
#gameOver {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 24px;
display: none;
}
</style>
</head>
<body>
<div id="gameArea">
<div id="score">积分: 0</div>
<div id="gameOver">游戏结束!<br>最终积分: <span id="finalScore"></span></div>
</div>
<script>
const gameArea = document.getElementById('gameArea');
const scoreDisplay = document.getElementById('score');
const gameOverDisplay = document.getElementById('gameOver');
const finalScoreDisplay = document.getElementById('finalScore');
const gridSize = 20;
const gridCount = 20;
let snake = [{ x: 10, y: 10 }];
let food = { x: 15, y: 15 };
let direction = { x: 0, y: 0 };
let nextDirection = { x: 0, y: 0 };
let score = 0;
let moveInterval;
let moveSpeed = 200;
let power = 1;
document.addEventListener('keydown', startGame);
function startGame(event) {
if (direction.x === 0 && direction.y === 0) {
switch (event.key) {
case 'ArrowUp':
nextDirection = { x: 0, y: -1 };
break;
case 'ArrowDown':
nextDirection = { x: 0, y: 1 };
break;
case 'ArrowLeft':
nextDirection = { x: -1, y: 0 };
break;
case 'ArrowRight':
nextDirection = { x: 1, y: 0 };
break;
}
direction = { ...nextDirection };
moveInterval = setInterval(moveSnake, moveSpeed);
document.removeEventListener('keydown', startGame);
document.addEventListener('keydown', changeDirection);
}
}
function changeDirection(event) {
switch (event.key) {
case 'ArrowUp':
if (direction.y === 0) nextDirection = { x: 0, y: -1 };
break;
case 'ArrowDown':
if (direction.y === 0) nextDirection = { x: 0, y: 1 };
break;
case 'ArrowLeft':
if (direction.x === 0) nextDirection = { x: -1, y: 0 };
break;
case 'ArrowRight':
if (direction.x === 0) nextDirection = { x: 1, y: 0 };
break;
}
}
function moveSnake() {
direction = { ...nextDirection };
const newHead = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };
if (newHead.x < 0 || newHead.x >= gridCount || newHead.y < 0 || newHead.y >= gridCount || isCollision(newHead)) {
endGame();
return;
}
snake.unshift(newHead);
if (newHead.x === food.x && newHead.y === food.y) {
score += Math.pow(2, power);
power++;
scoreDisplay.textContent = '积分: ' + score;
generateFood();
} else {
snake.pop();
}
drawGame();
}
function isCollision(position) {
return snake.some(segment => segment.x === position.x && segment.y === position.y);
}
function generateFood() {
let newFoodPosition;
do {
newFoodPosition = {
x: Math.floor(Math.random() * gridCount),
y: Math.floor(Math.random() * gridCount)
};
} while (isCollision(newFoodPosition));
food = newFoodPosition;
}
function drawGame() {
gameArea.innerHTML = `<div id="score">积分: ${score}</div><div id="gameOver">游戏结束!<br>最终积分: <span id="finalScore"></span></div>`;
snake.forEach(segment => {
const snakeElement = document.createElement('div');
snakeElement.style.gridColumnStart = segment.x + 1;
snakeElement.style.gridRowStart = segment.y + 1;
snakeElement.classList.add('snake');
gameArea.appendChild(snakeElement);
});
const foodElement = document.createElement('div');
foodElement.style.gridColumnStart = food.x + 1;
foodElement.style.gridRowStart = food.y + 1;
foodElement.classList.add('food');
gameArea.appendChild(foodElement);
}
function endGame() {
clearInterval(moveInterval);
finalScoreDisplay.textContent = score;
gameOverDisplay.style.display = 'block';
}
drawGame();
</script>
</body>
</html>
我们罗列了一些具体的需求,包括游戏玩法规则、展示的样式、输出的形式等。ChatGPT生成代码时,会将这些需求都考虑进去。
一开始,我们对游戏的运行过程可能不是很清楚,对ChatGPT生成的效果也不好判断,那么我们该怎么把问题描述清楚呢?通常我们用递进的方式,一边与ChatGPT交互,一边根据结果不断地调整Prompt、直到符合我们的预期。需求描述越清晰,ChatGPT的表现就越好。
有时候,你的目标可能在你心中有明确的图景,但不容易用命令式的语言描述出来,这时就可以提供一些案例让ChatGPT学习。
比如,你要让ChatGPT帮助做命名实体识别,从文本中提取出人名、公司名等作为文本标签,可以用案例的方式告诉ChatGPT你想要的结果是怎样的。
阅读下面的文本,提取2种实体类型:公司名、人名
期望格式:
公司名:<逗号分隔的公司名称列表>
人名:<逗号分隔的人名列表>
##
案例文本:华为宣布突破ERP系统封锁 任正非孟晚舟发声
公司名:华为
人名:任正非,孟晚舟
##
文本:特斯拉的创始人兼CEO埃隆·马斯克(Elon Musk)也因此成为世界上最富有人,他的个人财富达到了近3000亿美元,超过了亚马逊杰夫·贝索斯(Jeff Bezos)和微软的比尔·盖茨(Bill Gates)
ChatGPT学得很到位,它不仅理解了“公司名”和“人名”的含义,还学到了输出格式。
ChatGPT的背后是大语言模型(LargeLanguage Model,LLM),它学习并吸收了全世界的知识,形成了自己的智慧。但它不了解你,包括你的想法、你的目的和你的要求。回想一下,我们在工作中给别人交代任务时,也需要考虑对方是否了解这个任务的背景如果对方不了解,你就需要把背景介绍清楚。ChatGPT也需要尽可能详细地描述你交给它的任务背景。
在写程序时,我们经常遇到错误或者运行结果不符合预期,这时候可以让ChatGPT帮忙进行分析。
比如,有个简单的使用指针交换两个数的代码,运行结果不符合预期,想要ChatGPT帮忙看看。我们可以把代码复制上来,并把问题描述清楚。
我正在学习C语言,写了以下程序,想要实现a和b的交换:
但是在运行结果中,a和b并没有交换,请问为什么?
#include<stdio.h>
void swap(int *a, int *b)
{
int *k;
k= a;a = b; b = k;
}
int main()
{
int a=3,b=6,*x=&a,*y= &b;
swap( x,y);
print£( "%d,%d ",a,b);
}
得到正确的代码
#include<stdio.h>
void swap(int *a, int *b)
{
int k;
k = *a; // 将 a 指向的值存入 k
*a = *b; // 将 b 指向的值存入 a 指向的位置
*b = k; // 将 k 的值存入 b 指向的位置
}
int main()
{
int a = 3, b = 6;
swap(&a, &b); // 传递 a 和 b 的地址
printf("%d, %d\n", a, b); // 输出交换后的值
return 0;
}
我故意将刚才的代码改错,让它编译不通过,我们可以这样问ChatGPT。
我正在学习C语言,我写了以下程序,想要实现a和b的交换。
但是编译报错了,错误信息是:
error: no matching function for call to 'swap'
程序代码是:
#include<stdio.h>
void swap(int *a, int *b)
{
int *k;
k= a;a = b; b = k;
}
int main()
{
int a=3,b=6;
swap( a,b);
print£( "%d,%d ",a,b);
}
请帮我看看问题在哪,如何修改?
注意看,我将上面的描述分成了4段:第一段描述问题背景;第二段给出编译报错信息;第三段给出源代码,用把代码包裹起来,表示代码是用C语言写的;第四段向ChatGPT发问。
得到代码
#include<stdio.h>
void swap(int *a, int *b)
{
int k;
k = *a; // 将 a 指向的值存入 k
*a = *b; // 将 b 指向的值存入 a 指向的位置
*b = k; // 将 k 的值存入 b 指向的位置
}
int main()
{
int a = 3, b = 6;
swap(&a, &b); // 传递 a 和 b 的地址
printf("%d, %d\n", a, b); // 输出交换后的值
return 0;
}
以上分析得很好,编译问题修改正确。更进一步地,ChatGPT认为我的期望是交换两个数,因此把不能正确交换的问题也一起修改了,表现超出预期。
我们经常会看一些别人写的代码,比如开源代码,或者公司交接的历史项目。有的代码写得清晰明了,注释也丰富,让人如沐春风。但更多看到的是没有注释,甚至注释与代码对不上的情况。
在尝试让ChatGPT帮我分析代码之后,我发现代码阅读效率提高了,心情也愉悦了对于很长的代码文件,为了不超过 token 数量的限制,我们可以按函数接口来划分。
请分析下这段代码的功能,并加上注释:
void InitDaemon()
{
pid_t pid;
if((pid=fork())!=0)
{
exit( 0);
}
setsid();
signal(SIGHUP,SIG_IGN);
signal(SIGPIPE,SIG_IGN);
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGCHLD,SIG_IGN);
struct sigaction sig;
sig.sa_handler =SIG_IGN;
sig,sa_flags =0;
sigemptyset(&sig.sa_mask);
sigaction( SGHUP,&sig,NULL);
if((pid=fork())!=0)
{
exit(0);
}
exit(0);
umask(0);
setpgrp();
}
得到代码
void InitDaemon()
{
pid_t pid;
// 第一次fork,创建子进程,父进程退出
if((pid = fork()) != 0)
{
exit(0); // 父进程退出,子进程继续执行
}
// 创建新会话,使子进程成为会话首进程,脱离控制终端
setsid();
// 忽略一些信号
signal(SIGHUP, SIG_IGN); // 忽略挂起信号,防止进程被终止
signal(SIGPIPE, SIG_IGN); // 忽略管道破裂信号
signal(SIGTTOU, SIG_IGN); // 忽略后台写终端信号
signal(SIGTTIN, SIG_IGN); // 忽略后台读终端信号
signal(SIGCHLD, SIG_IGN); // 忽略子进程退出信号,防止僵尸进程
// 设置忽略信号的处理方式
struct sigaction sig;
sig.sa_handler = SIG_IGN; // 设置处理程序为忽略
sig.sa_flags = 0; // 无附加标志
sigemptyset(&sig.sa_mask); // 清空信号集
sigaction(SIGHUP, &sig, NULL); // 忽略挂起信号
// 第二次fork,创建孙子进程,子进程退出
if((pid = fork()) != 0)
{
exit(0); // 子进程退出,孙子进程继续执行
}
// 终止初始化进程,正式进入守护进程状态
exit(0);
// 将文件权限掩码设为0,以确保守护进程创建的文件具有最大的权限
umask(0);
// 将进程组ID设置为当前进程的PID,独立于任何终端
setpgrp();
}
在使用模型时,以下8个最佳实践已被反复验证,建议在使用时遵循。当然,也鼓励根据自己的任务需求进行探索,找到适合自己的 Prompt。
1) 使用最新的模型。
2) 在提示开始处放置说明,并使用###或"""分隔说明和上下文。
3) 尽可能详细地描述所需上下文、结果、长度、格式、风格等。
4) 给出示例以说明需求:展示所需内容的示例,这样模型更容易理解。
当你提供特定的格式要求时,模型的响应更好。这也使得编程解析多个输出更加可靠。
5) 先尝试让模型0样本生成,不行的话再给出少量样本试试,若还不行,再去做大量样本的训练。
微调: 微调就是给模型更多的样本进行学习训练,这里就不举例了。
6) 在说明中使用清晰、精确的语言。
7) 不要只说不要做什么,而要说该怎么做。
8) 使用具体的词汇来帮助模型生成正确的代码。
在上面的代码示例中,添加“import”提示,告诉模型应该使用Python编写(类似用SELECT作为SQL语句的开头提示)。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。