likes
comments
collection
share

传统前后端如何引入AI成为AI全栈项目?一个demo让你彻底理解前言 曾经也想在自己的传统项目中引入ai,让自己的项目变

作者站长头像
站长
· 阅读数 70

前言

曾经也想在自己的传统项目中引入ai,让自己的项目变得“聪明起来”,奈何苦于生不逢时,但现如今,2024AI元年的到来,一切皆有可能,手里有AI,一切可可能。接下来就以一个实战demo,让你彻底理解,前端+后端+AI,为你展示一个AI全栈项目如何搭建。

项目搭建

项目结构

本次ai全栈项目是一个ai_user项目(可以输入自己的问题,让AI回答关于user上的问题),在fullstack文件夹下创建ai_user文件夹,其中又包含前端frontend、后端backend、AI ai_server文件夹

传统前后端如何引入AI成为AI全栈项目?一个demo让你彻底理解前言 曾经也想在自己的传统项目中引入ai,让自己的项目变

前端

前端主要负责页面的搭建、展示,用户的交互。

传统前后端如何引入AI成为AI全栈项目?一个demo让你彻底理解前言 曾经也想在自己的传统项目中引入ai,让自己的项目变 结构搭建非常简单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ai_user</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
    <div class="container">
        <div class="row col-md-6 col-md-offset-3">
            <h1>AI能力驱动的userData</h1>
            <table class="table table-striped" id="user_table">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>姓名</th>
                        <th>家乡</th>
                    </tr>
                </thead>
                <tbody>
                    <!-- <tr>
                        <td>1</td>
                        <td>陈总</td>
                        <td>武汉</td>
                    </tr>
                    <tr>
                        <td>2</td>
                        <td>罗总</td>
                        <td>厦门</td>
                    </tr> -->
                </tbody>
            </table>

        </div>
        <div class="row col-md-6 col-md-offset-3">
            <form name="aiForm" method="get" >
                <div class="form-group">
                    <label for="questionInput">向AI助理提问:</label>
                    <input type="text" name="question" class="form-control" id="questionInput"
                        placeholder="请输入您想问的users相关问题">
                </div>
                <button type="submit" class="btn btn-default">提交</button>
            </form>
        </div>
        <div class="row" id="message">
        </div>
    </div>
</body>

</html>

知识点:

  1. css不用自己写,我们通过link引入了bootstrap库,需要用的时候,只需要去网上翻阅一下他们的使用手册就可以轻松使用!例如row、col-md-6这些类
  2. 页面展示的数据不用写死,而是通过后端传入数据,我们再刚开始页面搭建之初可以先写死看看效果。
  3. <label> 标签的 for 属性与 <input> 元素的 id 属性相互配合,当用户点击 <label> 文本时,与该 label 对应的具有相同 id 的 <input> 元素会自动获得焦点,这极大地提升了表单交互的便利性和易用性。它使得用户可以更直观、便捷地与表单元素进行交互,而无需精确地点击到小小的输入框区域。这就是一种极其友好的体验,照顾所有人包括存在视力障碍的人员。
  4. placeholder 属性主要用于<input>等表单元素,它的作用是在输入框为空时显示一个提示性的文本,用于提示用户该输入框期望输入的内容类型或格式等信息。当用户开始在输入框中输入内容时,这个提示文本会自动消失。它有助于为用户提供更明确的输入引导,提升用户体验。

接下来,我们需要编写后端接口,为前端提供数据

后端接口编写

  1. 初始化

在我们的backend文件夹下,首先我们在终端执行初始化命令,将其初始化为一个后端项目

npm init -y
  • 初始化成功,将会在backend文件夹下生成一个package.json,项目描述文件
  1. 安装json-server

在我们的backend文件夹下,安装json-server库

npm i json-server
  1. 创建json数据文件

在backend文件夹下创建users.json文件,伪造数据,通过json-server服务为前端提供数据

{
    "users": [
        {
            "id": 1,
            "name": "陈总",
            "hometown": "北京"
        },
        {
            "id": 2,
            "name": "李总",
            "hometown": "上海"
        },
        {
            "id": 3,
            "name": "恬总",
            "hometown": "上海"
        },
        {
            "id": 4,
            "name": "钟总",
            "hometown": "深圳"
        },
        {
            "id": 5,
            "name": "王总",
            "hometown": "武汉"
        }
    ]
}
  1. 修改package.json项目描述文件 在项目描述文件夹中,添加新的脚本命令,后续我们只要启动这个脚本,后端打开服务器,就可以为前端提供数据源
  "scripts": {
    "dev": "json-server user.json"
  },
  1. 启动服务器

在终端执行命令,启动json-server服务

npm run dev

启动完毕之后,后端就会启动3000端口的服务器,执行我们名称为dev的json-server脚本,以user.json为数据源。

传统前后端如何引入AI成为AI全栈项目?一个demo让你彻底理解前言 曾经也想在自己的传统项目中引入ai,让自己的项目变 后端服务启动之后,我们的前端通过fetch请求,请求后端3000端口的数据,并将这些数据渲染到我们的form表单中

接下来前后端就已经完成,我们在前端界面中还嵌入了提问unput框和提交按钮,目的是为后续ai服务提供按钮,我们通过input框输入问题,向ai提问,接下来就到了AI一展身手的时候了

AI赋能

前端后端+AI全栈,接下来让我们一起走向AI Native,成为全栈工程师

我们在前端html页面中最后添加了一个div,id为message,目的就是拿到ai的回到之后嵌入到这里,提前挖好了坑。我们只需要为form表单添加一个submit监听事件

  1. 项目初始化

在ai_server文件夹下启动终端,执行初始化命令

npm init -y

2.安装openai 在ai_server文件夹下启动终端,执行安装openai命令

npm i openai

3.安装dotenv Dotenv 是一个 Node.js 的第三方模块,用于加载环境变量。它的作用是从一个名为 .env 的文件中加载环境变量,并将这些变量添加到 Node.js 的 process.env 对象中,使得在应用程序中可以轻松地访问这些环境变量。

npm i dotenv

4.创建main.js入口文件

// ai openai, :8888/users?question=
// node 的内置模块 
// - 搭建http服务 
const http = require('http');
const url = require('url');
const OpenAI = require('openai');
require('dotenv').config();

const client = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY,
    //proxy 代理
    baseURL: 'https://api.chatanywhere.tech/v1'
})


const server = http.createServer(async function (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');

    // http 基于请求响应的简单协议 req  请求   res 响应
    if (req.url.indexOf('/users') >= 0) {
        // users  ai 服务
        const parsedUrl = url.parse(req.url, true);
        // console.log(parsedUrl);
        // 解构
        const { question, users } = parsedUrl.query;
        console.log(question, users)
        const prompt = `
        ${users}
        请根据以上用户的json数据,回答${question}这个问题.
        如果回答不了,就返回不清楚
        `

        const response = await client.chat.completions.create({
            model: 'gpt-3.5-turbo',
            messages: [{ role: "user", content: prompt }],
            temperature: 0, // 控制输出的随机性,0表示更确定的输出
        });

        const result = response.choices[0].message.content || '';
        console.log(result);

        let info = {
            message: result
        }
        res.statusCode = 200;
        res.setHeader('Content-Type', 'text/json');
        res.end(JSON.stringify(info))
    }
    // console.log(req.url, '////');
    res.end('hello');
})

server.listen(8888, function () {
    console.log('服务器启动了')
})

  • 引入node内置模块http、url,我们还下载了openai的包,也通过require引入一下
  • 创建openai的实例对象
  • 在服务器的处理函数中,设置了跨域访问的相关头部信息。否则会报错
  • 当请求的 URL 中包含 /users 时,解析请求参数中的问题和用户数据,构建提示语,然后使用 OpenAI客户端发送请求获取回答,并将结果以特定格式返回给客户端。
  • 最后启动服务器监听 8888 端口

前端js

<script>
        const oMessage = document.querySelector('#message')
        const oBody = document.querySelector('#user_table tbody')
        const oForm = document.forms['aiForm'];
        let usersData = [];
        fetch('http://localhost:3000/users')
            .then(data => data.json())
            .then(users => {
                usersData = users;
                // console.log(usersData);
                // console.log(users);
                oBody.innerHTML = users.map(user => `
                <tr>
                    <td>${user.id}</td>
                    <td>${user.name}</td>
                    <td>${user.hometown}</td>
                </tr>
            `).join('')
            })

        oForm.addEventListener('submit', function (event) {
            // 组织表单的默认行为 例如跳转到action
            event.preventDefault();
            // name 属性去找  性能更好 
            const question = this["question"].value.trim();
            // console.log(question);
            fetch(`http://localhost:8888/users?question=${question}&users=${JSON.stringify(usersData)}`)
                .then(data => data.json())
                .then(res => {
                    console.log(res)
                    document.querySelector('#message').innerHTML = res.message
                })
        })
    </script>

注意点:

  1. 为什么要使用join(“”)
  • oBody.innerHTML存在隐式类型转换,如果不用join(""),数组中的每个元素转换成字符串时,数组中的每个元素是以逗号分隔的,对每一个元素进行字符串拼接时会把逗号也添加进去,如果存在逗号,我们将每一个tr、td渲染近html时就会存在错误,因此需要用join对每一个元素的逗号进行去除。
  1. 为什么要使用this?
const question = this["question"].value.trim();

我们为事件进行了监听,此时的this就会指向触发事件的元素,在这里我们的submit监听事件中的this就指向oForm元素也就是我们的表单标签

表单标签比较特殊,通过表单标签加中括号名字,可以轻松访问到名字为question的输入框,并通过value获取值,其实我们可以通过id的方式去获取,但是我们通过name去获取的话,性能会更好,当表单被提交时,表单元素的值会被发送到服务器。name 属性用于标识每个表单元素,以便服务器可以正确地处理这些值。如果使用 id 来获取元素,服务器可能无法正确识别表单元素的值。

 <form name="aiForm" method="get" action="https://www.baidu.com">
                <div class="form-group">
                    <label for="questionInput">向AI助理提问:</label>
                    <input type="text" name="question" class="form-control" id="questionInput"
                        placeholder="请输入您想问的users相关问题">
                </div>
                <button type="submit" class="btn btn-default">提交</button>
            </form>

总结

通过这一次实战demo,我成功圆梦,将ai引入传统编程,这也是我们真正走向AI全栈开发的坚实一步,未来,前后端的界限一定会越来越模糊,ai的存在,让一切都成为了可能。手里有AI,一切可可能。

如有不清楚的地方,欢迎私信讨论,创作不易,希望各位朋友一键三连,让我们一起努力,全面拥抱ai。

转载自:https://juejin.cn/post/7379806770363711515
评论
请登录