大家好,我是创业时长五年半的张总,喜欢唱、跳、rap、篮球。
最近一年我们做了几款AI产品,主要是SD绘画和AI Chat类产品,所以对于各类AI产品开发略有些心得。接下来我会分享如何从0到1开发各种各样的AI产品,以及关于技术、产品、和运营的一些见解。
本文是 《开发ChatGPT聊天机器人的100种姿势》 系列文章的第二篇,我会用N种方式教你从一个简单对话框写到一个完整的应用,每个姿势都力求舒服。
📚系列文章
系列源码可以在Github中查看:GitHub - miaoihan/100way-to-build-ai: 开发AI应用的100种姿势
🚀 码上掘金
🕶所见即所得
📒正文
因为ChatGPT的API请求是无状态的,因此它并不会记住你们之前的对话。
我们人与人之间对话时,当你预备说出下一句话的时候,你的大脑会从你的记忆体里读取你们之前的对话信息,再通过神经元进行信息交互,让大脑中控制语言的中枢,把句子输出。
那么我们要如何实现记忆功能?
很简单,我们只要把完整的对话记录都发给ChatGPT,就能实现带记忆的对话功能了。
我们在之前18行最简代码的基础之上,给messages加上一轮模拟对话,通过将完整的messages传给ChatGPT,他就能记住你们的对话内容了
👨💻开始操作
- 18行最简代码
<html>
<head>
<script>
const headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Authorization", "Bearer sk-UgtZ6M4qw7Ycfzok0cC1E8C690A04b92B38e381c4c5661D5");
const body = JSON.stringify({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: "你好" }],
});
const requestOptions = { method: 'POST', headers, body };
fetch("https://ai98.vip/v1/chat/completions", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
</script>
</head>
</html>
- 将
messages: [{ role: "user", content: "你好" }]这一句话,扩展成一段历史对话
const body = JSON.stringify({
model: "gpt-3.5-turbo",
messages: [
{ role: "user", content: "你好,我是枫" },
{ role: "assistant", content: "你好,有什么可以帮助你的吗?" },
{ role: "user", content: "还记得我是谁么?" },
],
});
改动对比:
- 22行完整代码(最简记忆功能)
<html>
<head>
<script>
const headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Authorization", "Bearer sk-UgtZ6M4qw7Ycfzok0cC1E8C690A04b92B38e381c4c5661D5");
const body = JSON.stringify({
model: "gpt-3.5-turbo",
messages: [
{ role: "user", content: "你好,我叫阿枫" },
{ role: "assistant", content: "你好,有什么可以帮助你的吗?" },
{ role: "user", content: "还记得我叫什么名字么?" },
],
});
const requestOptions = { method: 'POST', headers, body };
fetch("https://ai98.vip/v1/chat/completions", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
</script>
</head>
</html>
- 控制台查看结果
如果GPT回复了你的名字,那么恭喜你🎉,你的第一个带记忆功能的AI对话应用也写好了
🔥开始实战
既然已经知道如何实现记忆功能,那么我们就来做一个可以接受用户输入,并保存对话信息的最简AI对话机器人。
🕺开发步骤
-
先做产品需求
- 有输入框,接受用户输入
- 有按钮,可以发送信息
- 可以看到用户和AI的对话记录
-
然后搞产品原型,长这样👇
- 最后,开始开发,GO🤘
- 涉及到
DOM的一些基础知识,不熟悉的可以看资料:DOM 概述 - Web API | MDN- 文中代码并不是最优的,除非必要,不会引入任何无关的概念
- 为了小白读者,注释写的很详细
4. 写好UI
<head>
<title>Chat Application</title>
<style>
/* 略 */
</style>
</head>
<body>
<!-- 实现用户输入,点击按钮发送请求,获取响应结果,并显示在页面上 -->
<div id="conversation-history"></div>
<input type="text" id="input">
<button onclick="chat()">chat</button>
</body>
5. 新增chat方法
/**
* 聊天函数
* 1. 获取用户输入
* 2. 将用户输入添加到对话记录中
* 3. 发送请求到GPT接口
* 4. 将AI的回复添加到对话记录中
* 5. 将对话记录显示在页面上
*/
function chat() {
// 获取用户输入
const userInput = document.getElementById("input").value;
// 发送后清空输入框
document.getElementById("input").value = ''
// 将用户输入添加到对话记录中
conversationHistory.push({ role: "user", content: userInput });
// 更新DOM,将对话信息挂载到页面上
appendToConversationHistory("user", userInput)
const requestOptions = {
method: 'POST', headers,
body: JSON.stringify({
model: "gpt-3.5-turbo",
messages: conversationHistory,
})
};
fetch("https://ai98.vip/v1/chat/completions", requestOptions)
.then(response => response.json())
.then(result => {
// 根据OpenAI返回的数据结构拿值
const aiResponse = result.choices[0].message.content;
console.log(conversationHistory);
// 将AI的回复添加到对话记录中
conversationHistory.push({ role: "assistant", content: aiResponse });
appendToConversationHistory("assistant", aiResponse)
})
.catch(error => console.log('error', error));
}
6. 新增DOM更新方法appendToConversationHistory
// 更新DOM,将对话信息挂载到页面上
function appendToConversationHistory(role, content) {
const historyContainer = document.getElementById("conversation-history");
// 添加css样式
const messageElement = document.createElement("div");
messageElement.classList.add(`${role}-message`);
// 插入消息内容
const contentElement = document.createElement("span");
contentElement.textContent = `${role}: ${content}`;
messageElement.appendChild(contentElement);
// 挂载消息元素
historyContainer.appendChild(messageElement);
};
7. 60行完整代码(无注释版)
<html>
<head>
<title>Chat Application</title>
<style>
#conversation-history {
margin-bottom: 1rem;
border: 1px solid #ccc;
padding: 0.5rem;
}
.user-message {
color: #007BFF;
}
.assistant-message {
color: #28A745;
}
</style>
</head>
<body>
<div id="conversation-history"></div>
<input type="text" id="input">
<button onclick="chat()">chat</button>
<script>
const headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Authorization", "Bearer sk-UgtZ6M4qw7Ycfzok0cC1E8C690A04b92B38e381c4c5661D5");
let conversationHistory = [];
function chat() {
const userInput = document.getElementById("input").value;
document.getElementById("input").value = ''
conversationHistory.push({ role: "user", content: userInput });
appendToConversationHistory("user", userInput)
const requestOptions = {
method: 'POST', headers,
body: JSON.stringify({
model: "gpt-3.5-turbo",
messages: conversationHistory,
})
};
fetch("https://ai98.vip/v1/chat/completions", requestOptions)
.then(response => response.json())
.then(result => {
const aiResponse = result.choices[0].message.content;
console.log(conversationHistory);
conversationHistory.push({ role: "assistant", content: aiResponse });
appendToConversationHistory("assistant", aiResponse)
})
.catch(error => console.log('error', error));
}
function appendToConversationHistory(role, content) {
const historyContainer = document.getElementById("conversation-history");
const messageElement = document.createElement("div");
messageElement.classList.add(`${role}-message`);
const contentElement = document.createElement("span");
contentElement.textContent = `${role}: ${content}`;
messageElement.appendChild(contentElement);
historyContainer.appendChild(messageElement);
};
</script>
</body>
</html>
8. 最终效果
📖 知识点
-
最简单实现记忆的方法就是携带全部的对话记录,当然这样随着对话的轮数越来越多,消耗的token也会越来越多
-
不同的大模型会有不同的
token上限,最近比较火的kimi就是因为号称“百万上下文”而出圈 -
除了传递所有对话历史,我们也可以用其他的策略来节省一些token
-
总结过往对话记录
当历史对话记录超过一定token时,我们就把之前的对话记录总结一下,生成一个更简短的summary history取代之前的对话
-
保留N轮对话记录
当历史对话记录超过N轮对话时,就把之前的对话“忘记”,这样就能记住最近N次的对话,也能省token
-
📢下期预告
-
📜 支持
Stream流式对话(打字机效果) -
🌀 新增加载中的css动效
效果预览:
Sige
🤘关于我
- 🎤 唱、跳、rap、篮球: 热爱艺术和运动
- 💡 全栈开发者:开发上主要是Node.js技术栈,也懂点产品和运营
- 🚀 连续创业者:公司开了五年半了,目前
还没黄
如果你对搞AI、搞产品、搞开发、搞流量有兴趣,那么请多多关注我吧,
干货持续更新中...❤️