参考链接:直接在前端调用 GPT-3 API
效果图:
小技巧:
1. shift+enter是发送消息的快捷键
2. 有本地聊天记录功能
3. 按delete按钮可以删除包括这条之后的记录
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>ChatGPT Web Example</title>
<style>
body {
font-family: "Helvetica Neue", Arial, sans-serif;
}
h1 {
margin-bottom: 20px;
text-align: center;
}
#chatbox {
border: 1px solid gray;
height: calc(100vh - 180px);
margin-bottom: 20px;
overflow-y: scroll;
padding: 10px;
}
.message {
margin-bottom: 10px;
font-size: 18px;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
.user-message {
color: forestgreen;
text-align: right;
}
.assistant-message {
color: darkolivegreen;
}
.warning-message {
color: red;
}
.chatgpt-message {
text-align: left;
}
#input-container {
display: flex;
align-items: center;
justify-content: center;
padding-right: 5%;
}
#inputbox {
font-size: 1rem;
margin-right: 10px;
padding: 10px;
width: 100%;
}
#submit {
background-color: cornflowerblue;
border: none;
border-radius: 5px;
box-sizing: border-box;
color: white;
cursor: pointer;
float: right;
padding: 10px 20px;
width: 80px;
}
</style>
</head>
<body>
<div id="chatbox">
<!-- 消息列表 -->
</div>
<div id="input-container">
<textarea id="inputbox" type="text" placeholder="请输入您的问题" rows="5"></textarea>
<button id="submit" loading="true">提交</button>
</div>
</body>
<script>
/* 官方文档[https://platform.openai.com/docs/guides/chat] */
const chatboxEl = document.getElementById("chatbox");
const inputEl = document.getElementById("inputbox");
const submitEl = document.getElementById("submit");
const endpoint = "https://api.openai.com/v1/chat/completions"; //如api过时,请查询官网
const apiKey = "sk-"; //换成自己的API Key
const delayTime = 60000; // 超时时间为60秒
const model = "gpt-3.5-turbo";
const temperature = 1; // 回答随机度
const max_tokens = 1000;
const historyMessageNum = 10;
let historyMessage = [];
let messageIdx = 0;
function addMessage(text, sender) {
historyMessage.push({ role: sender, content: text });
localStorage.setItem("localMessage", JSON.stringify(historyMessage));
const messageEl = document.createElement("div");
const preEl = document.createElement("pre");
messageEl.classList.add("message");
messageEl.classList.add(`${sender}-message`);
preEl.textContent = text;
messageEl.appendChild(preEl);
if (sender == 'user') {
const delEl = document.createElement("button");
delEl.classList.add("delete");
delEl.innerText = "delete";
const nowIdx = (historyMessage.length - 1);
delEl.onclick = function () {
deleteMessage(nowIdx);
};
messageEl.appendChild(delEl);
}
chatboxEl.appendChild(messageEl);
chatboxEl.scrollTop = chatboxEl.scrollHeight;
}
deleteMessage = (idx) => {
const msgEls = document.querySelectorAll('.message');
msgEls.forEach((el, i) => {
if (i >= idx) {
el.parentNode.removeChild(el);
}
})
historyMessage = historyMessage.slice(0, idx);
localStorage.setItem("localMessage", JSON.stringify(historyMessage));
}
async function getResponseFromAPI() {
const controller = new AbortController();
const signal = controller.signal;
const timeout = setTimeout(() => {
controller.abort();
}, delayTime);
const messages = historyMessage
.filter((v) => ["system", "user", "assistant"].includes(v.role))
.slice(-historyMessageNum); // 最近消息
const response = await fetch(endpoint, {
signal,
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
model,
messages,
max_tokens,
n: 1,
stop: null,
temperature,
}),
});
clearTimeout(timeout);
const result = await response.json();
return result.choices[0].message;
}
function init() {
submitEl.addEventListener("click", async () => {
const input = inputEl.value;
addMessage(input, "user");
inputEl.value = "";
// 显示加载动画
submitEl.innerHTML = "等待中...";
submitEl.setAttribute("disabled", true);
// 使用 OpenAI API 获取 ChatGPT 的回答
getResponseFromAPI(input)
.then((response) => {
addMessage(response.content, response.role);
})
.catch((error) => {
addMessage(
error.name === "AbortError" ? "Network Error" : error.message,
"warning"
);
})
.finally(() => {
// 隐藏加载动画
submitEl.innerHTML = "提交";
submitEl.removeAttribute("disabled");
});
});
document.addEventListener("keydown", function (event) {
if (event.shiftKey && event.keyCode === 13) {
submitEl.click();
event.preventDefault();
}
});
const localMessage = localStorage.getItem("localMessage") ? JSON.parse(localStorage.getItem("localMessage")) : []
chatboxEl.innerHTML = '';
localMessage.forEach(v => addMessage(v.content, v.role));
}
init();
</script>
</html>