【实战】 Vue 3、Anything LLM + DeepSeek本地化项目(开篇)

实战项目介绍

千呼万唤始出来~,经过长达10天的构思,实战项目最终还是产生了一些自认为有效想法,一起期待后续的落地笔记吧。

注意:实战项目的核心目的是巩固加深对Vue3的应用,因此其他辅助工程的搭建上会尽量简化,起到辅助作用即可,如有问题欢迎留言探讨~

项目目标

开发一款基于 Vue 3 的 AI 智能知识库与对话系统,具备以下功能:

  • 智能问答:基于上传的文档(如 PDF、TXT、DOCX 等)提供精准的问答服务。
  • 多轮对话:支持上下文理解,实现多轮对话。
  • 文档上传与管理:支持多种文档格式的上传、嵌入和管理。
  • 联网搜索:结合联网搜索能力,提供更全面的答案。
  • 用户注册与登录:支持用户账户管理。
  • 对话历史记录:保存用户的对话历史,支持查看和导出。
  • 友好的用户界面:提供简洁、直观的前端交互体验。

技术选型与架构设计

前端

  • Vue 3:现代前端框架,提供响应式数据绑定和组件化开发。
  • Pinia:状态管理库,替代 Vuex,提供更简洁的 API。
  • Element Plus:UI 组件库,提供丰富的组件和样式。
  • Axios:用于与后端 API 进行数据交互。

后端

  • Node.js+Express:轻量级后端框架,用于处理 API 请求。
  • DeepSeek API:提供 AI 对话和知识库问答能力。
  • Ollama:本地部署的语言模型,支持离线使用。

数据库

  • MongoDB:用于存储用户信息、文档和对话记录。
  • LanceDB或Pinecone:向量数据库,用于存储文档嵌入。

环境准备工作

Vue3项目搭建

方法一:使用 Vue CLI 搭建

安装 Vue CLI 如果尚未安装 Vue CLI,可以通过以下命令全局安装:

bash 复制代码
npm install -g @vue/cli

或者使用国内镜像源加速安装:

bash 复制代码
npm install -g @vue/cli --registry=https://registry.npmmirror.com

创建项目 在终端中运行以下命令创建 Vue 3 项目

bash 复制代码
vue create ai-vue-project

按提示选择默认的 Vue 3 模板或手动选择特性(如 Vue Router、Vuex 等)。

进入项目目录并安装依赖

bash 复制代码
cd ai-vue-project
npm install

启动开发服务器

bash 复制代码
npm run serve

方法二:使用 Vite 搭建

安装 Node.js 确保已安装 Node.js,版本需在 12.0.0 以上。安装完成后,通过以下命令检查版本:

bash 复制代码
node -v

创建项目 使用 Vite 创建 Vue 3 项目:

bash 复制代码
npm create vite@latest ai-vue-project -- --template vue

或者使用 TypeScript 模板:

bash 复制代码
npm create vite@latest ai-vue-project -- --template vue-ts

进入项目目录并安装依赖

bash 复制代码
cd ai-vue-project
npm install

启动开发服务器

bash 复制代码
npm run dev

其他说明 推荐使用Vite

ViteVue 3的官方推荐构建工具,具有以下优势:

  • 启动速度快:冷启动速度极快,无需等待。
  • 热重载高效:代码修改后可以即时更新,无需手动刷新。
  • 支持TypeScript:与TypeScript配合良好,提供更好的开发体验。

后续学习

Vue3 Pania安装

具体安装内容可以直接传送到文章《【涅槃】Vue3学习笔记(五)》按步骤进行安装使用,这里就不在重复赘述了。

官方文档和更多资源

Element Plus安装

Element Plus 是 Vue 3 的官方 UI 组件库,基于 Element UI 重构,提供了丰富的组件和主题配置,适用于构建现代化的 Vue 3 应用。

安装 Element Plus

在 Vue 3 项目中安装 Element Plus,可以使用以下命令:

bash 复制代码
npm install element-plus --save

或者使用yarn

bash 复制代码
yarn add element-plus

全局引入 Element Plus

在项目的入口文件(如main.jsmain.ts)中,全局引入 Element Plus 和其样式文件:

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';

const app = createApp(App);

app.use(ElementPlus);
app.mount('#app');

按需引入组件 如果你只想引入部分组件,可以通过以下方式按需引入。例如,引入ElButtonElMessage

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import { ElButton, ElMessage } from 'element-plus';
import 'element-plus/dist/index.css';

const app = createApp(App);

app.component('ElButton', ElButton);
app.config.globalProperties.$message = ElMessage;

app.mount('#app');

在组件中使用ElButton

vue 复制代码
<template>
  <div>
    <el-button type="primary" @click="showMessage">点击我</el-button>
  </div>
</template>

<script setup>
import { ElMessage } from 'element-plus';

function showMessage() {
  ElMessage('这是一个消息提示');
}
</script>

使用 Element Plus 的主题配置 Element Plus 支持主题配置,可以通过修改变量来自定义样式。在项目中创建一个样式文件(如src/styles/element-custom.scss),并覆盖默认变量:

scss 复制代码
// src/styles/element-custom.scss
@use 'element-plus/theme-chalk/src/index' as *;

$--color-primary: teal; // 修改主题颜色

然后在main.jsvite.config.js中引入自定义样式文件:

javascript 复制代码
import 'element-plus/dist/index.css';
import './styles/element-custom.scss';

使用 TypeScript 支持

Element Plus 提供了完整的 TypeScript 类型定义。如果你的项目使用了 TypeScript,可以直接享受类型提示和自动补全功能。

例如,使用ElMessage的 TypeScript 类型:

typescript 复制代码
import { ElMessage } from 'element-plus';

const showMessage = (message: string) => {
  ElMessage({
    message,
    type: 'success',
  });
};

使用 Element Plus 的国际化支持 Element Plus 支持国际化,可以通过安装element-plus/es/locale来使用其他语言。例如,使用中文:

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import zhCn from 'element-plus/es/locale/lang/zh-cn';

const app = createApp(App);

app.use(ElementPlus, {
  locale: zhCn,
});
app.mount('#app');

示例:创建一个简单的表单

以下是一个使用 Element Plus 创建的简单表单示例:

vue 复制代码
<template>
  <div>
    <el-form label-width="100px">
      <el-form-item label="用户名">
        <el-input v-model="form.username"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input type="password" v-model="form.password"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup>
import { reactive } from 'vue';
import { ElMessage } from 'element-plus';

const form = reactive({
  username: '',
  password: '',
});

const submitForm = () => {
  if (form.username && form.password) {
    ElMessage('表单提交成功');
  } else {
    ElMessage.error('用户名和密码不能为空');
  }
};
</script>

官方文档和资源

Axios使用

在 Vue 3 项目中使用 Axios 进行 HTTP 请求是一种常见的选择。Axios 是一个基于 Promise 的 HTTP 客户端,支持浏览器和 Node.js 环境,非常适合用于与后端 API 交互。

安装 Axios

在项目中安装 Axios,运行以下命令

bash 复制代码
npm install axios

或者使用yarn

bash 复制代码
yarn add axios

创建 Axios 实例

为了更好地管理请求和响应,建议创建一个 Axios 实例,并在其中配置默认参数(如基础 URL、超时时间等)。在项目中创建一个src/axios.js文件:

javascript 复制代码
// src/axios.js
import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://api.example.com', // 设置基础 URL
  timeout: 5000, // 设置超时时间
});

// 请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么,例如添加 Token
    config.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`;
    return config;
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response) => {
    // 对响应数据做点什么
    return response;
  },
  (error) => {
    // 对响应错误做点什么
    if (error.response.status === 401) {
      // 处理 401 未授权错误
      console.error('未授权,请重新登录');
    }
    return Promise.reject(error);
  }
);

export default instance;

在组件中使用 Axios

在 Vue 3 组件中,可以通过导入 Axios 实例来发送请求。以下是一个示例:

示例:获取用户数据

vue 复制代码
<template>
  <div>
    <h1>用户信息</h1>
    <p v-if="loading">加载中...</p>
    <p v-if="error" style="color: red">{{ error }}</p>
    <div v-if="user">
      <p>用户名:{{ user.name }}</p>
      <p>邮箱:{{ user.email }}</p>
    </div>
    <button @click="fetchUser">获取用户信息</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from '@/axios'; // 导入自定义的 Axios 实例

const user = ref(null);
const loading = ref(false);
const error = ref(null);

const fetchUser = async () => {
  loading.value = true;
  error.value = null;

  try {
    const response = await axios.get('/user'); // 使用 Axios 实例发送请求
    user.value = response.data;
  } catch (err) {
    error.value = err.message || '请求失败';
  } finally {
    loading.value = false;
  }
};
</script>

使用 Axios 进行表单提交

Axios 也支持发送 POST 请求,例如提交表单数据:

示例:提交登录表单

vue 复制代码
<template>
  <div>
    <h1>登录</h1>
    <p v-if="error" style="color: red">{{ error }}</p>
    <form @submit.prevent="login">
      <div>
        <label for="username">用户名:</label>
        <input type="text" id="username" v-model="formData.username" />
      </div>
      <div>
        <label for="password">密码:</label>
        <input type="password" id="password" v-model="formData.password" />
      </div>
      <button type="submit">登录</button>
    </form>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from '@/axios';

const formData = ref({
  username: '',
  password: '',
});
const error = ref(null);

const login = async () => {
  error.value = null;

  try {
    const response = await axios.post('/login', formData.value);
    console.log('登录成功', response.data);
    alert('登录成功');
  } catch (err) {
    error.value = err.response?.data?.message || '登录失败';
  }
};
</script>

全局配置 Axios

如果你希望在项目中全局使用 Axios,可以在main.js中进行配置:

javascript 复制代码
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import axios from 'axios';

const app = createApp(App);

// 将 Axios 挂载到 Vue 的全局属性上
app.config.globalProperties.$axios = axios;

app.mount('#app');

然后在组件中通过this.$axios使用 Axios:

javascript 复制代码
this.$axios.get('/user').then((response) => {
  console.log(response.data);
});

注意事项

  1. 拦截器
  • 请求拦截器可以用于统一设置请求头(如 Token)。
  • 响应拦截器可以用于统一处理错误(如 401 重定向到登录页)。
  1. 环境变量
  • 可以使用环境变量来区分开发环境和生产环境的 API 地址。例如:
javascript 复制代码
const instance = axios.create({
  baseURL: import.meta.env.VITE_API_URL || 'https://api.example.com',
});
  1. 错误处理
  • 在实际项目中,建议对错误进行更详细的处理,例如显示错误提示或记录日志。

VueRouter了解与使用

参考笔记《【涅槃】Vue3学习笔记(三)》VueRouter的使用。

Node.js+Express搭建用户认证

用户认证方式的实现:Session 认证和JWT 认证。这两种方式都适用于 Node.js+Express,可以根据你的应用场景选择合适的方案。

方案 1:使用 Session 认证

1.安装依赖

bash 复制代码
npm install express express-session bcryptjs body-parser

2.配置 Express 和 Session

javascript 复制代码
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const bcrypt = require('bcryptjs');

const app = express();
const port = 3000;

// 中间件
app.use(bodyParser.json());
app.use(session({
  secret: 'your_secret_key', // 替换为你的密钥
  resave: false,
  saveUninitialized: true
}));

// 模拟用户数据
const users = [
  {
    id: 1,
    username: 'admin',
    password: bcrypt.hashSync('password123', 10) // 使用 bcrypt 加密密码
  }
];

// 登录接口
app.post('/login', async (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username);

  if (!user || !bcrypt.compareSync(password, user.password)) {
    return res.status(401).send({ message: 'Invalid credentials' });
  }

  req.session.user = user; // 将用户信息存储到 session 中
  res.send({ message: 'Login successful', user: user.username });
});

// 获取用户信息接口
app.get('/profile', (req, res) => {
  if (!req.session.user) {
    return res.status(401).send({ message: 'Unauthorized' });
  }

  res.send({ message: 'Welcome to your profile', user: req.session.user.username });
});

// 登出接口
app.post('/logout', (req, res) => {
  req.session.destroy();
  res.send({ message: 'Logout successful' });
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

方案 2:使用 JWT 认证

1.安装依赖

bash 复制代码
npm install express jsonwebtoken bcryptjs body-parser

2.配置 Express 和 JWT

javascript 复制代码
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const bodyParser = require('body-parser');

const app = express();
const port = 3000;

// 中间件
app.use(bodyParser.json());

// 模拟用户数据
const users = [
  {
    id: 1,
    username: 'admin',
    password: bcrypt.hashSync('password123', 10) // 使用 bcrypt 加密密码
  }
];

// JWT 密钥
const secretKey = 'your_secret_key'; // 替换为你的密钥

// 登录接口
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username);

  if (!user || !bcrypt.compareSync(password, user.password)) {
    return res.status(401).send({ message: 'Invalid credentials' });
  }

  // 生成 JWT
  const token = jwt.sign({ id: user.id, username: user.username }, secretKey, { expiresIn: '1h' });

  res.send({ message: 'Login successful', token });
});

// 验证 JWT 的中间件
const authenticateToken = (req, res, next) => {
  const token = req.headers['authorization'];

  if (!token) {
    return res.status(401).send({ message: 'Unauthorized' });
  }

  jwt.verify(token, secretKey, (err, user) => {
    if (err) {
      return res.status(403).send({ message: 'Forbidden' });
    }

    req.user = user;
    next();
  });
};

// 获取用户信息接口
app.get('/profile', authenticateToken, (req, res) => {
  res.send({ message: 'Welcome to your profile', user: req.user.username });
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

两种方案的对比

特性 Session 认证 JWT 认证
状态存储 服务器端存储(Session) 客户端存储(Token)
适用场景 适合需要服务器端维护用户状态的场景 适合无状态、前后端分离的场景
安全性 需要保护 Session ID 需要保护 JWT 密钥
扩展性 可能需要额外的存储(如 Redis) 无状态,易于扩展
实现复杂度 中等 较低

总结

  • 如果你的应用是传统的服务端渲染应用,或者需要服务器端维护用户状态,可以使用Session 认证。
  • 如果你的应用是前后端分离的现代 Web 应用,推荐使用JWT 认证,因为它无状态、易于扩展,且实现简单。

根据你的具体需求选择合适的认证方式即可!

支持项目的基础搭建及储备工作已经基本完成,软件环境支持如下:

以下内容需要大家结合实际情况自行去搜索安装,后续所有的实战开发内容需要下边的软件环境做支撑否则无法进行。

  1. ollama如何将deepseek模型本地化部署
  2. MongoDb安装及客户端链接工具(MongoDB Compass)
  3. 知识库工具AnythingLLM的安装
相关推荐
计算机学姐13 分钟前
基于Asp.net的驾校管理系统
vue.js·后端·mysql·sqlserver·c#·asp.net·.netcore
ZXT6 小时前
面试精讲 - vue3组件之间的通信
vue.js
念九_ysl6 小时前
深入解析Vue3单文件组件:原理、场景与实战
前端·javascript·vue.js
Jenna的海糖6 小时前
vue3如何配置环境和打包
前端·javascript·vue.js
灵感__idea7 小时前
Vuejs技术内幕:数据响应式之3.x版
前端·vue.js·源码阅读
鱼樱前端7 小时前
📚 Vue Router 4 核心知识点(Vue3技术栈)面试指南
前端·javascript·vue.js
计算机-秋大田7 小时前
基于Spring Boot的宠物健康顾问系统的设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·课程设计
程序员大澈8 小时前
1个基于 Three.js 的 Vue3 组件库
javascript·vue.js
程序员大澈8 小时前
3个 Vue Scoped 的核心原理
javascript·vue.js
计算机学姐8 小时前
基于Asp.net的教学管理系统
vue.js·windows·后端·sqlserver·c#·asp.net·visual studio