引言
今天我要和大家分享一个超级酷炫的项目——我的第一次AI全栈应用开发之旅,这个项目涉及从前端到后端再到AI模型的整合,最终实现了一个可以根据用户提问来回答问题的小程序,希望我的分享能给正在探索AI世界的你带来一些灵感和帮助。
1. 准备工作
- 1.建立文件夹
在项目中创建三个文件夹,分别存放后端、前端和AI大模型的内容。这样做的好处是让项目更加井井有条,避免了代码的混乱,就像整理房间一样,把衣服放在衣柜里,鞋子放在鞋柜里,这样找东西的时候就方便多了。
- 2.
user.json文件的使用
在backend文件夹下创建一个user.json文件。这个文件的作用是模拟数据库,存储我们要展示的用户数据列表。它就像一个迷你版的数据仓库,存放着我们项目的宝贵信息。
以下是我的user.json文件中的内容:
2. 接下来 实战开始!
2.1 一点点的后端
- 1.初始化项目
运行npm init -y,这会生成一个package.json文件,记录项目的初始配置。
- 2. 安装json-server:
使用npm i json-server命令安装json-server,这是一个轻量级的假API服务器,非常适合用于开发阶段。
- 3.设置脚本
在package.json里添加如下脚本:
```json
"scripts": {
"dev": "json-server --watch user.json --port 3001"
}
```
这个脚本的作用是在本地启动一个监听user.json文件变化的服务,并通过端口3001对外提供服务,合理利用 package.json 中的脚本功能,不仅可以让个人的开发流程更加流畅高效,也能为团队合作带来便利。
- 4.运行服务
执行npm run dev,如果你的眼前突然出现了一堆API路径的信息,恭喜你,你的后端服务已经成功启动了!
别急着庆祝,我们还没有结束。点击控制台给出的“Endpoints”链接,你会发现一个新的世界——API的详细信息页面展现在你面前。这里列出了所有可用的API路径,以及它们各自的功能说明。是不是感觉瞬间高大上了起来?
是不是感觉很酷炫呢?但这只是冰山一角,接下来的内容会让你更加惊喜不断。准备好了吗?我们继续前行!
2.2 前端部分的实现
- 1.创建文件
在frontend文件夹内创建一个index.html文件,这是我们的前端界面。
- 2.引入Bootstrap框架
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
通过这条语句,我们在HTML文档中引入了Twitter Bootstrap框架的CSS样式文件。Bootstrap是一个强大的前端框架,它提供了大量的预定义样式和组件,使得网页布局变得轻松愉快。
- 3.使用Bootstrap布局类名
<div class="container">
<div class="row col-md-6 col-md-offset-3">
<table class="table table-striped" id="user_table">
<thead>
<tr>
<th>id</th>
<th>姓名</th>
<th>家乡</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot></tfoot>
</table>
</div>
</div>
这里我们使用了Bootstrap提供的类名来创建一个居中且美观的表格。container类让内容居中显示,col-md-6 col-md-offset-3则让表格在中等及以上屏幕尺寸下占据一半宽度,并且水平居中。table table-striped类让表格具有条纹效果,看起来更加清爽。
- 4.使用
fetch()函数实现前后端的数据交互
fetch()是一个非常强大的工具,它允许我们轻松地发起网络请求,获取或发送数据。下面是一段示例代码:
<script>
fetch('http://localhost:3001/users')
// then 方法,它在请求成功时被调用
.then(res => res.json())
//then 方法,它会在 JSON 数据解析完成后被调用
.then(users => {
console.log(users);
})
</script>
indexhtml运行后就会出现这样的结果了,这标志着前端与后端的成功会师,也是你迈向全栈开发的第一步。
5. 动态生成表格:让你的数据“活”起来!
<script>
//获取表格的tbody
const tableBody = document.querySelector('table tbody');
fetch('http://localhost:3001/users')
// then 方法,它在请求成功时被调用
.then(res => res.json())
//then 方法,它会在 JSON 数据解析完成后被调用
.then(users => {
usersData = users;
//遍历数组
for (let user of users) {
console.log(user);
// 创建一个新的 HTML < tr > 元素
const tr = document.createElement('tr');
// 将新创建的行添加到表格的 tbody 中
tableBody.appendChild(tr);
// for in json 对象遍历
for (let key in user) {
// 创建一个新的 HTML < td > 元素
const td = document.createElement('td');
td.innerText = user[key];
tr.appendChild(td);
console.log(key, user[key]);
}
}
})
</script>
这段代码进一步完善了之前的逻辑,不仅获取数据,还动态生成表格行和单元格,这样一来,我们的用户数据就可以优雅地展示在界面上了,感觉像是在做一场魔术表演,让数据瞬间出现在屏幕上!
下面是运行结果的截图:
这样,我们就完全实现了前后端的结合,让数据从后端数据库中“活”了起来,呈现在用户的面前。
- 6. 理解前后端交互
为了更好地理解前后端交互的过程,下面是一些图片,希望可以帮助你加强对HTTP的理解:
通过HTTP协议,前后端之间建立了一个高效、可靠的沟通渠道。每一次请求与响应的交互,都是为了让用户体验更加顺畅、页面加载更快、数据传递更准确,了解HTTP协议不仅有助于我们构建更好的Web应用,还能让我们在遇到问题时,快速定位原因并找到解决方案。
2.3 AI大模型的建立
在frontend中的配置:
- 1.使用框架内的布局类名
<div class="container">
<div class="row col-md-6 col-md-offset-3">
<table class="table table-striped" id="user_table">
<thead>
<tr>
<th>id</th>
<th>姓名</th>
<th>家乡</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot></tfoot>
</table>
<div class="row">
<form name="aiForm" action="http://www.baidu.com">
<div class="from-group">
<label for="questionInput">提问</label>
<input type="text" id="questionInput" class="form-control" name="question" placeholder="请输入问题"
required>
</div>
<button type="submit" class="btn btn-default" name="btn">查询</button>
<p id="message"></p>
</form>
</div>
</div>
这里我们使用了Bootstrap提供的类名来创建一个居中且美观的表格,并且加入了一个表单让用户输入问题。
- 2. 编写表单提交事件
为了使我们的应用能够与AI模型进行交互并完成问答功能,我们需要在前端JavaScript代码中编写表单提交事件。以下是完整的代码示例:
<script>
const tableBody = document.querySelector('table tbody');
let usersData;
fetch('http://localhost:3001/users')
.then(res => res.json())
.then(users => {
usersData = users;
for (let user of users) {
console.log(user);
const tr = document.createElement('tr');
tableBody.appendChild(tr);
for (let key in user) {
const td = document.createElement('td');
td.innerText = user[key];
tr.appendChild(td);
console.log(key, user[key]);
}
}
})
// 表单提交事件
const oForm = document.forms['aiForm'];
oForm.addEventListener('submit', (e) => {
console.log(e);
e.preventDefault();
// const question = oFrom.question.value;
const question = oForm.question.value.trim();
if (!question) {
//alert 弹窗
alert('请输入问题');
return;
}
fetch(`http://localhost:1314/api?question=${question}&data=${JSON.stringify(usersData)}`)
// 解析响应数据为 JSON 格式 二进制 => json
.then(data => data.json())
.then(data => {
console.log(data)
document.getElementById('message').innerText = data.result;
})
})
</script>
这段JavaScript代码负责从后端获取用户数据并动态填充表格,同时处理表单提交事件,将用户的提问发送给AI模型进行回答。当用户点击“查询”按钮时,我们会阻止默认行为,检查输入是否为空,然后发送请求到后端API,最后将得到的回答显示在页面上。
在LLM的 main.js 中的配置:
- 1.基本配置
确保你已经完成了OpenAI和.env文件的配置,如果你还不清楚如何配置,可以参考这篇文章:
# OpenAI新篇章:一起探索多模态应用的无限可能!
- 2.llm中的代码
接下来,我们来看看如何在main.js中配置LLM,让它能够接收前端的请求并调用OpenAI的API来生成回答。
// node 内置的http 模块
const http = require('http');
const OpenAi = require('openai');
const url = require('url'); // node 内置 查询url的模块
const dotenv = require('dotenv');
dotenv.config();
// 实例化
const client = new OpenAi({
apiKey: process.env.OPENAI_API_KEY,
baseUrl: process.env.OPENAI_API_BASE_URL
});
const getCompletion = async (prompt, model = "gpt-3.5-turbo") => {
// 用户提的问题
const messages = [{
role: 'user',
content: prompt
}];
// AIGC chat 接口
const response = await client.chat.completions.create({
model: model,
messages: messages,
// LLM 生成内容的随机性
temperature: 0.1
})
return response.choices[0].message.content
}
//req 表示请求对象,res 表示响应对象
const server = http.createServer(async (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*'); // 允许所有来源访问,也可以指定具体的域名,如'http://example.com'
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); // 允许的请求方法
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 允许的请求头
const parsedUrl = url.parse(req.url, true);
const queryObj = parsedUrl.query;
console.log(parsedUrl.query);
const prompt = `
${queryObj.data}
请根据上面的json数据,回答${queryObj.question}这个问题
`;
const result = await getCompletion(prompt);
let info = {
result
}
res.statusCode = 200;
res.setHeader('Content-Type', 'text/json');
res.end(JSON.stringify(info))
})
//监听端口 1314
server.listen(1314)
在main.js中,首先引入了必要的模块,包括http用于创建HTTP服务器,OpenAi用于调用OpenAI的API,url用于解析URL,dotenv用于加载环境变量。然后,使用环境变量中的API密钥和基础URL实例化了OpenAI客户端。接着,定义了getCompletion函数,用于构建用户提问的消息并调用OpenAI的API获取回复。创建HTTP服务器时,设置了跨域请求头,解析了请求URL并提取查询参数,构建了提示信息,调用了getCompletion函数获取OpenAI的回复,构建了响应对象并设置了响应状态码和内容类型,最后发送了响应。服务器监听端口1314。
如果你觉得这段代码比较复杂,相关内容可以用AI自己学习一下,例如HTTP请求和响应、Node.js基础、OpenAI API的使用和跨域请求的概念
注意:在使用时一定要使用node main.js保证llm中的main.js处于启动的状态
- 3.最后就可以实现问答
可以通过http查看结果是否成功:
也可以在集成终端中看到你提出的问题和页面中存在的数据:
通过这次实践,我发现AI技术真的很强大,而且结合全栈开发可以让我们的应用变得更加智能和有趣。希望大家也能动手尝试一下,相信你们会有更多惊喜发现!
结语
这就是我的第一个全栈AI应用开发经历啦!从后端的数据提取到前端的展示,再到AI驱动的问答系统,整个过程既充满挑战又非常有趣,希望这篇文章能帮助到大家!