LFM2.5-1.2B-Thinking-GGUF项目实战:基于Vue的前端AI对话界面开发
1. 项目背景与目标
最近AI对话应用越来越火,但很多开发者只关注后端模型能力,忽略了前端交互体验。实际上,一个流畅、美观的前端界面能显著提升用户满意度。本文将带你用Vue.js开发一个完整的AI对话Web界面,重点解决几个关键问题:如何优雅地展示流式响应、如何管理对话历史、如何增强Markdown和代码的显示效果。
这个项目特别适合有一定Vue基础,想进入AI应用开发的开发者。完成后你将获得一个可直接复用的前端模板,稍加修改就能接入各种大模型API。
2. 环境准备与项目初始化
2.1 基础环境搭建
首先确保你的开发环境已经准备好:
- Node.js 16.x或更高版本
- npm或yarn包管理器
- Vue CLI(可选,本文使用Vite)
打开终端,执行以下命令创建新项目:
npm create vite@latest ai-chat-frontend --template vue cd ai-chat-frontend npm install2.2 安装必要依赖
我们需要几个关键库来构建完整功能:
npm install axios markdown-it highlight.js sse.js- axios:用于HTTP请求
- markdown-it:Markdown渲染
- highlight.js:代码高亮
- sse.js:处理服务器发送事件(SSE)
3. 核心功能实现
3.1 基础页面结构
在src/App.vue中搭建基础布局:
<template> <div class="app-container"> <header class="app-header"> <h1>AI对话助手</h1> </header> <main class="chat-container"> <div class="message-list"> <!-- 对话历史将在这里渲染 --> </div> <div class="input-area"> <textarea v-model="userInput" placeholder="输入你的问题..."></textarea> <button @click="sendMessage">发送</button> </div> </main> </div> </template>3.2 接入后端API
在src目录下创建api.js文件,封装API调用逻辑:
import axios from 'axios'; const api = axios.create({ baseURL: 'http://你的后端地址/api', timeout: 30000 }); export const sendMessage = async (message, history) => { try { const response = await api.post('/chat', { message, history }); return response.data; } catch (error) { console.error('API调用失败:', error); throw error; } };3.3 实现流式响应
对于大模型响应,流式传输能显著提升用户体验。修改api.js添加SSE支持:
import { EventSourcePolyfill } from 'sse.js'; export const streamMessage = (message, history, onMessage) => { const eventSource = new EventSourcePolyfill(`${baseURL}/stream`, { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message, history }), method: 'POST' }); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); onMessage(data); }; eventSource.onerror = (error) => { console.error('SSE错误:', error); eventSource.close(); }; return eventSource.close; };4. 增强功能实现
4.1 Markdown渲染与代码高亮
创建src/utils/markdown.js:
import MarkdownIt from 'markdown-it'; import hljs from 'highlight.js'; const md = new MarkdownIt({ highlight: (str, lang) => { if (lang && hljs.getLanguage(lang)) { try { return hljs.highlight(str, { language: lang }).value; } catch (__) {} } return ''; } }); export const renderMarkdown = (content) => { return md.render(content); };在组件中使用:
<template> <div v-html="renderedContent" class="markdown-content"></div> </template> <script> import { renderMarkdown } from '../utils/markdown'; export default { props: ['content'], computed: { renderedContent() { return renderMarkdown(this.content); } } }; </script>4.2 对话历史管理
使用Pinia或Vuex管理对话状态。这里以Composition API为例:
import { ref } from 'vue'; export function useChatHistory() { const history = ref([]); const addMessage = (role, content) => { history.value.push({ role, content }); }; const clearHistory = () => { history.value = []; }; return { history, addMessage, clearHistory }; }5. 完整组件实现
下面是整合所有功能的完整Chat组件示例:
<template> <div class="chat-container"> <div class="message-list"> <div v-for="(msg, index) in history" :key="index" :class="['message', msg.role]" > <div v-html="renderMarkdown(msg.content)"></div> </div> <div v-if="isLoading" class="message assistant"> <div class="typing-indicator">...</div> </div> </div> <div class="input-area"> <textarea v-model="userInput" @keydown.enter.exact.prevent="sendMessage" placeholder="输入你的问题..." ></textarea> <button @click="sendMessage" :disabled="isLoading"> {{ isLoading ? '发送中...' : '发送' }} </button> </div> </div> </template> <script setup> import { ref, computed } from 'vue'; import { streamMessage } from '../api'; import { renderMarkdown } from '../utils/markdown'; const userInput = ref(''); const history = ref([]); const isLoading = ref(false); const currentStream = ref(null); const sendMessage = async () => { if (!userInput.value.trim() || isLoading.value) return; const userMessage = userInput.value; userInput.value = ''; history.value.push({ role: 'user', content: userMessage }); isLoading.value = true; let assistantMessage = ''; history.value.push({ role: 'assistant', content: assistantMessage }); const closeStream = streamMessage( userMessage, history.value.slice(0, -1), (data) => { if (data.content) { assistantMessage += data.content; history.value[history.value.length - 1].content = assistantMessage; } } ); currentStream.value = closeStream; }; </script>6. 样式优化与响应式设计
添加一些基础样式提升用户体验:
.chat-container { max-width: 800px; margin: 0 auto; height: 100vh; display: flex; flex-direction: column; } .message-list { flex: 1; overflow-y: auto; padding: 1rem; } .message { margin-bottom: 1rem; padding: 0.75rem 1rem; border-radius: 1rem; max-width: 80%; } .message.user { background: #e3f2fd; margin-left: auto; } .message.assistant { background: #f5f5f5; margin-right: auto; } .input-area { display: flex; padding: 1rem; border-top: 1px solid #eee; } textarea { flex: 1; padding: 0.75rem; border: 1px solid #ddd; border-radius: 0.5rem; resize: none; min-height: 50px; max-height: 150px; } button { margin-left: 0.5rem; padding: 0 1rem; background: #1976d2; color: white; border: none; border-radius: 0.5rem; cursor: pointer; } .markdown-content pre { background: #f5f5f5; padding: 1rem; border-radius: 0.5rem; overflow-x: auto; } .typing-indicator::after { content: '...'; animation: typing 1.5s infinite; } @keyframes typing { 0% { content: '.'; } 33% { content: '..'; } 66% { content: '...'; } }7. 项目总结与扩展建议
通过这个项目,我们实现了一个功能完整的AI对话前端界面。核心亮点包括流畅的流式响应、良好的Markdown支持以及简洁美观的UI设计。实际开发中,你可能还需要考虑以下几点:
- 添加对话历史持久化,使用localStorage或IndexedDB保存会话
- 实现多会话管理,允许用户创建多个对话线程
- 添加打字机效果,使AI回复更加生动
- 集成语音输入输出功能
- 添加主题切换和个性化设置
这个前端模板可以轻松适配各种后端AI模型API,只需调整api.js中的接口地址和参数格式即可。对于更复杂的应用,可以考虑使用WebSocket替代SSE以获得双向通信能力。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。