当前位置: 首页 > news >正文

智能助手(利用GPT搭建智能系统)

项目介绍

本项目旨在打造一个基于通义千问模型的智能助手,能够理解用户指令并自动生成可执行的 JavaScript 代码。该代码可直接调用预设接口,完成指定操作,并返回执行结果。通过大模型的理解与生成能力,实现从自然语言到接口调用的自动化流程,提升开发效率与交互体验。

功能特点

  • 自然语言理解:能够准确理解用户的指令和意图
  • 代码生成:自动生成符合要求的JavaScript代码
  • 接口调用:支持与预设接口的无缝对接
  • 实时反馈:提供执行结果的即时反馈

技术架构

后端服务

  • 基于Node.js构建的图书管理系统服务
  • RESTful API接口设计
  • 支持图书的增删改查等基础操作

前端界面

  • 基于现代Web技术栈开发
  • 提供直观的用户交互界面

API接口

系统提供以下主要接口:

  • 获取图书列表
  • 获取图书详情
  • 添加新图书
  • 更新图书信息
  • 删除图书

项目结构

├── book-system-server/     # 图书管理系统服务端
│   ├── src/                # 源代码目录
│   │   ├── app.js         # 应用入口
│   │   ├── config/        # 配置文件
│   │   ├── controllers/   # 控制器
│   │   ├── routes/        # 路由定义
│   │   └── utils/         # 工具函数
│   └── package.json       # 项目依赖
└── code/                  # 智能助手核心代码├── src/               # 源代码目录│   ├── app.js         # 应用入口│   ├── config/        # 配置文件│   ├── utils/         # 工具函数│   └── webui/         # Web界面└── package.json       # 项目依赖

开发环境

  • Node.js环境
  • 开发IDE:IntelliJ IDEA
  • 服务地址:http://localhost:5000
  • 前台页面:http://localhost:3000

使用说明

  1. 确保已安装Node.js环境
  2. 克隆项目到本地
  3. 分别在book-system-server和code目录下运行:
npm install
  1. 启动服务

  2. 启动服务前需要配置apiKey

源码下载

智能助手

演示截图

系统首页
在这里插入图片描述

查看接口文档
在这里插入图片描述

核心源码

code/src/app.js

const { exec } = require('child_process');
const express = require('express');
const fs = require('fs');
const path = require('path');
const logger = require('./utils/logger');
const config = require('./config/config');
const { callGpt } = require('./utils');const app = express();app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, './webui')));app.get('/api/docs', (req, res) => {const docPath = path.join(__dirname, 'config', '接口文档.md');fs.readFile(docPath, 'utf-8', (err, data) => {if (err) {logger.error('读取接口文档失败:', err);return res.status(500).json({ error: '无法读取接口文档' });}res.type('text/markdown').send(data);});
});app.post('/api/ask', async (req, res) => {const { text, history } = req.body;if (!text || typeof text !== 'string') {return res.status(400).json({ error: '缺少或无效的 text 参数' });}const apiKey = config.apiKey;if (!apiKey) {return res.status(500).json({ error: '未配置有效的 API Key' });}logger.info('开始调用 GPT 接口,请求体:', { text });try {const gptResponse = await callGpt(apiKey, text, history);logger.info('GPT 接口调用成功,响应内容:', gptResponse);res.json({status: 'success',answer: gptResponse});} catch (error) {logger.error('调用 GPT 接口出错:', error.message);res.status(500).json({status: 'error',message: '调用 GPT 失败'});}
});app.post('/api/run-code', (req, res) => {const code = req.body.code;if (!code) {return res.status(400).json({ status: 'error', message: '缺少代码内容' });}// 创建临时文件路径const tempFilePath = path.join(__dirname, 'tempScript.js');// 写入代码到文件fs.writeFileSync(tempFilePath, code);// 使用 node 执行脚本exec(`node ${tempFilePath}`, (error, stdout, stderr) => {fs.unlinkSync(tempFilePath); // 删除临时文件if (error) {return res.json({status: 'error',message: stderr || error.message});}res.json({status: 'success',output: stdout});});
});// 启动服务器
app.listen(config.server.port, config.server.host, () => {logger.info(`转发服务器启动在 http://${config.server.host}:${config.server.port}`);
});module.exports = app;

code/src/utils/index.js

const path = require("path");
const fs = require("fs/promises");async function callGpt(apiKey, questionText, history) {const docPath = path.join(__dirname, '../config', '接口文档.md');const context = await fs.readFile(docPath, 'utf-8');const response = await fetch("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", {method: "post",headers: {"Content-Type": "application/json","Authorization": `Bearer ${apiKey}`},body: JSON.stringify({model: "qwen-plus",messages: [{role: "assistant",content: "这是我的接口文档,你可以将该文档作为上下文,从中获取信息,文档信息如下:" + context,},{role: "assistant",content: "我会向你进行一些提问,最终都是为了一些操作服务,例如查询什么信息,添加什么信息,修改什么信息等;如我未提供一些必要信息时,你需要向我进行一些提问,让我补充信息;" +"记住如果是查询类的,你可以进行一些默认设定,例如查常用的,或者给定一些默认情况等;但如果是涉及到变更操作的,如新增、修改、删除等,你都需要先向我询问并获取一些必要信息。",},{role: "assistant",content: "需要注意,你是一个助手,用户是日常生活中的普通人,并不是计算机领域的人员,所以你输出的一些内容需要不包含什么专业词汇,而且需要更多的引导,这方面需要重点注意;" +"同时在缺少部分条件时,你可以预设一些条件,然后后续说明即可,用户可以再更改。",},{role: "assistant",content: "当不需要额外信息或信息补充完成时你需要借助上述接口文档来实现前述的操作,通过 nodejs 和 axios 来调用接口,将相关代码输出给我,需要是完整的代码,代码放在一个文件中即可,要求返回的内容中只有一段JavaScript代码,方便我提取;" +"需要注意的是,并不是每次回答你都需要返回要执行的代码,只有在你觉得信息已经获取够了就可以采用代码进行操作了;然后需要注意的是代码里面不要出现 console 的日志输出,因为我在执行代码时会将输出的日志也记录到返回中,这些日志会影响我的返回结果。",},...history,{role: "assistant",content: questionText,}]}),});if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}return response.json();
}module.exports = {callGpt,
}

code/src/webui/index.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><link rel="icon" href="favicon.ico" type="image/x-icon"><link rel="stylesheet" href="css/style.css">
</head>
<body><div class="container"><div class="terminal" id="terminalContainer"><div class="terminal-header"><div class="terminal-title">智能助手</div><div class="terminal-controls"><button id="configBtn" class="config-btn">查看接口文档</button><span class="control minimize"></span><span class="control maximize"></span><span class="control close"></span></div></div><div class="terminal-body"><div id="output"></div><div class="command-line"><span class="prompt">$</span><input type="text" id="commandInput" autofocus></div></div></div></div><!-- 查看接口文档弹窗 --><div id="configModal" class="modal"><div class="modal-content"><div class="modal-header"><h2>查看接口文档</h2><span class="close-modal">&times;</span></div><div class="modal-body"></div></div></div><script src="js/marked.min.js"></script><script src="js/settings.js"></script><script src="js/terminal.js"></script>
</body>
</html>

code/src/webui/js/terminal.js

class Terminal {constructor() {this.output = document.getElementById('output');this.terminalBody = document.getElementsByClassName('terminal-body')[0];this.commandLine = document.getElementsByClassName('command-line')[0];this.input = document.getElementById('commandInput');this.commandHistory = [];this.historyIndex = -1;this.history = [];this.commands = {help: this.showHelp.bind(this),clear: this.clear.bind(this),};this.setupEventListeners();this.printWelcome();this.setupFocusHandlers();this.focusInput();}setupEventListeners() {this.input.addEventListener('keydown', (e) => {if (e.key === 'Enter') {this.executeCommand().then(_ => {});} else if (e.key === 'ArrowUp') {e.preventDefault();this.navigateHistory('up');} else if (e.key === 'ArrowDown') {e.preventDefault();this.navigateHistory('down');}});}async executeCommand() {const command = this.input.value.trim();if (!command) return;this.commandHistory.push(command);this.historyIndex = this.commandHistory.length;this.println('');this.appendText("<span>$</span>");this.println(` ${command}`);this.input.value = '';const [cmd, ...args] = command.split(' ');if (cmd === "help" || cmd === "clear") {const handler = this.commands[cmd];try {if (handler) {await handler(args);} else {this.println(`命令未找到: ${cmd}`);}} catch (error) {this.println(`错误: ${error.message}`);}} else {this.input.blur();this.commandLine.style.display = "none";let dots = 0;this.erase();this.println('.'.repeat(dots));const interval = setInterval(() => {dots = (dots + 1) % 4;this.erase();this.println('.'.repeat(dots));}, 500);try {const response = await fetch('/api/ask', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ text: command, history: this.history })});const result = await response.json();clearInterval(interval);this.erase();this.output.innerHTML = this.output.innerHTML.replace("<span>$</span>", "$");if (result.status === "success") {const text = result.answer['choices'][0].message.content;await this.handleText(text);// 将本次交互加入 historythis.history.push({ role: 'assistant', content: command },{ role: 'system', content: text });}this.commandLine.style.display = "block";this.input.focus();} catch (error) {this.println(`错误: ${error.message}`);}}}async handleText(text) {if (text.includes("```javascript") || text.includes("```js")) {const codeRegex = /```(?:javascript|js)\n([\s\S]*?)```/;const match = text.match(codeRegex);if (match && match[1]) {const code = match[1];this.println('');this.println('正在执行代码...');try {const res = await fetch('/api/run-code', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ code })});const data = await res.json();if (data.status === 'success') {this.println('\n✅ 执行结果:');this.println('');this.println(data.output || '(无输出)');} else {this.println('\n❌ 执行错误:');this.println(data.message);}} catch (err) {this.println('\n❌ 网络错误:');this.println(err.message);}}} else {this.println('');this.println(text);}}navigateHistory(direction) {if (direction === 'up' && this.historyIndex > 0) {this.historyIndex--;} else if (direction === 'down' && this.historyIndex < this.commandHistory.length) {this.historyIndex++;}this.input.value = this.commandHistory[this.historyIndex] || '';}println(text) {const escapedText = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');this.output.innerHTML += escapedText + '\n';this.terminalBody.scrollTop = this.terminalBody.scrollHeight;}appendText(text) {this.output.innerHTML += text;this.terminalBody.scrollTop = this.terminalBody.scrollHeight;}erase() {const innerHTML = this.output.innerHTML;const lastIndexOf = innerHTML.lastIndexOf("<span>$</span>");const indexOf = innerHTML.indexOf("\n", lastIndexOf);if (indexOf !== -1) {this.output.innerHTML = innerHTML.substring(0, indexOf + 1);}this.terminalBody.scrollTop = this.terminalBody.scrollHeight;}clear() {this.output.innerHTML = '';}printWelcome() {this.println('欢迎使用智能助手');this.println('输入 help 查看当前智能助手的功能');this.println('');}showHelp() {this.println(`
可用命令:help           查看当前智能助手的功能clear          清空终端[text]         通过自然语言调用功能`);}setupFocusHandlers() {const terminalContainer = document.getElementById('terminalContainer');terminalContainer.addEventListener('click', () => {this.focusInput();});this.input.addEventListener('click', (e) => {e.stopPropagation();});window.addEventListener('focus', () => {this.focusInput();});document.addEventListener('visibilitychange', () => {if (!document.hidden) {this.focusInput();}});}focusInput() {if (this.input && !('ontouchstart' in window)) {this.input.focus();}}
}const terminal = new Terminal();
http://www.lqws.cn/news/551413.html

相关文章:

  • Netty 的 PooledByteBuf与PooledHeapByteBuf​​
  • Day44 预训练模型
  • MySQL 连接指定端口后,为什么实际仍是 3306?
  • 【深度学习新浪潮】MoE技术入门(简要版)
  • 基于JavaWeb的校园失物招领系统设计与实现
  • 智能制造数字孪生集成交付生态链:智慧产线极速克隆,孪生重构生产周期
  • 飞牛OS安装zerotier组自己的虚拟局域网
  • 利用python实现NBA数据可视化
  • 数学术语之源——(矩阵或行列式的)秩数(rank)
  • UE--Slate 焦点、捕获,输入处理与玩家控制器的关系
  • 基于STM32设计的扫地机器人
  • 从代码学习深度学习 - 自然语言推断与数据集 PyTorch版
  • 什么是 A/B 测试?
  • 机器学习4——参数估计之贝叶斯估计
  • clion与keil分别配置项目宏定义
  • Java-IO流(二)
  • 快慢指针深度解析
  • Object
  • MYSQL-InnoDB逻辑存储结构 详解
  • 机器学习5——非参数估计
  • 数据库外连接详解:方式、差异与关键注意事项
  • openGL学习(基本窗口)
  • 深入学习MySQL的页分裂(Page Split)
  • 策略模式与工厂模式的黄金组合:从设计到实战
  • yaml 导致的原型污染 -- GPN CTF 2025 Secure by Default
  • 《高等数学》(同济大学·第7版)第九章 多元函数微分法及其应用第五节多元函数微分学的几何应用
  • Redis 单线程的“天花板”与集群的必要性
  • 三、java项目自动部署流水线搭建
  • oracle内存参数调整
  • 【C++】string的模拟实现