# 大语言模型聊天网站设计文档 ## 概述 本项目是一个全栈大语言模型聊天网站,支持用户与AI进行实时对话。系统采用前后端分离架构,前端使用Vue.js构建用户界面,后端使用Node.js提供API服务,通过调用兼容OpenAI格式的第三方API实现智能对话功能。 ### 核心特性 - 实时AI对话体验 - 对话历史记录与管理 - 用户会话状态保持 - 响应式Web界面 - 高性能缓存机制 - 轻量级本地数据存储 ### 技术栈 - **前端**: Vue.js 3, Vue Router, Pinia, Axios, Element Plus - **后端**: Node.js, Express.js, SQLite3, LRU-Cache - **包管理**: pnpm - **数据库**: SQLite (本地文件数据库) - **第三方集成**: OpenAI兼容API服务 ## 系统架构 ### 整体架构图 ```mermaid graph TB subgraph "客户端" A[Vue.js前端] A1[聊天界面] A2[历史记录] A3[用户设置] end subgraph "服务端" B[Node.js后端] B1[Express路由] B2[会话管理] B3[缓存层] B4[数据访问层] end subgraph "数据存储" C[SQLite数据库] C1[用户表] C2[对话表] C3[消息表] end subgraph "外部服务" D[第三方LLM API] D1[OpenAI兼容接口] end A -->|HTTP/WebSocket| B B -->|SQL查询| C B -->|API调用| D B3 -->|LRU缓存| B2 ``` ### 数据流架构 ```mermaid sequenceDiagram participant U as 用户 participant F as Vue前端 participant B as Node.js后端 participant C as LRU缓存 participant DB as SQLite participant API as 第三方LLM API U->>F: 发送消息 F->>B: POST /api/chat/send B->>C: 检查缓存 alt 缓存命中 C-->>B: 返回缓存结果 else 缓存未命中 B->>DB: 保存用户消息 B->>API: 调用LLM API API-->>B: 返回AI回复 B->>DB: 保存AI回复 B->>C: 更新缓存 end B-->>F: 返回对话结果 F-->>U: 显示AI回复 ``` ## 前端架构 ### 组件层次结构 ```mermaid graph TD A[App.vue] --> B[Layout组件] B --> C[Header组件] B --> D[Sidebar组件] B --> E[Main组件] E --> F[ChatView] E --> G[HistoryView] E --> H[SettingsView] F --> I[ChatInput] F --> J[MessageList] F --> K[TypingIndicator] J --> L[MessageItem] L --> M[UserMessage] L --> N[AIMessage] D --> O[ConversationList] O --> P[ConversationItem] ``` ### 组件定义 #### 核心聊天组件 **ChatView.vue** - 主聊天界面 - 管理当前对话状态 - 处理消息发送逻辑 - 实现消息流式显示 **MessageList.vue** - 消息列表容器 - 虚拟滚动优化 - 消息懒加载 - 自动滚动到底部 **ChatInput.vue** - 消息输入组件 - 多行文本输入 - 发送按钮状态管理 - 快捷键支持(Ctrl+Enter) #### 布局组件 **Layout.vue** - 主布局容器 - 响应式布局设计 - 侧边栏展开/收缩 - 移动端适配 **Sidebar.vue** - 侧边栏组件 - 对话历史列表 - 新建对话按钮 - 对话搜索功能 ### 状态管理架构 使用Pinia进行状态管理,主要包含以下Store: **chatStore.js** - 聊天状态管理 ```javascript { currentConversation: null, messages: [], isLoading: false, isTyping: false } ``` **conversationStore.js** - 对话管理 ```javascript { conversations: [], activeConversationId: null, searchQuery: '' } ``` **userStore.js** - 用户设置 ```javascript { settings: { theme: 'light', fontSize: 'medium', autoSave: true } } ``` ### 路由配置 ```javascript const routes = [ { path: '/', component: Layout, children: [ { path: '', redirect: '/chat' }, { path: '/chat/:id?', component: ChatView }, { path: '/history', component: HistoryView }, { path: '/settings', component: SettingsView } ] } ] ``` ### API集成层 **apiClient.js** - HTTP客户端封装 - Axios实例配置 - 请求/响应拦截器 - 错误处理机制 - 重试逻辑 **chatApi.js** - 聊天相关API ```javascript export const chatApi = { sendMessage: (conversationId, message) => {}, getConversations: () => {}, getMessages: (conversationId) => {}, createConversation: () => {}, deleteConversation: (id) => {} } ``` ## 后端架构 ### API端点设计 #### 对话管理端点 | 方法 | 路径 | 描述 | 请求体 | 响应 | |------|------|------|--------|------| | POST | `/api/conversations` | 创建新对话 | `{ title?: string }` | `{ id, title, createdAt }` | | GET | `/api/conversations` | 获取对话列表 | - | `[{ id, title, lastMessage, updatedAt }]` | | GET | `/api/conversations/:id` | 获取对话详情 | - | `{ id, title, messages }` | | DELETE | `/api/conversations/:id` | 删除对话 | - | `{ success: true }` | #### 消息处理端点 | 方法 | 路径 | 描述 | 请求体 | 响应 | |------|------|------|--------|------| | POST | `/api/chat/send` | 发送消息 | `{ conversationId, message, stream? }` | `{ message, response }` | | GET | `/api/messages/:conversationId` | 获取消息历史 | - | `[{ id, role, content, timestamp }]` | ### 数据模型设计 #### 数据库表结构 **conversations表** ```sql CREATE TABLE conversations ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL DEFAULT '新对话', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` **messages表** ```sql CREATE TABLE messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id INTEGER NOT NULL, role TEXT NOT NULL CHECK (role IN ('user', 'assistant')), content TEXT NOT NULL, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE ); ``` ### 业务逻辑层 #### 对话服务 (ConversationService) ```javascript class ConversationService { // 创建新对话 async createConversation(title) {} // 获取对话列表 async getConversations() {} // 获取对话详情 async getConversationById(id) {} // 删除对话 async deleteConversation(id) {} // 更新对话标题 async updateConversationTitle(id, title) {} } ``` #### 聊天服务 (ChatService) ```javascript class ChatService { constructor(llmApiClient, cache) { this.llmApiClient = llmApiClient; this.cache = cache; } // 处理用户消息 async processMessage(conversationId, userMessage) { // 1. 保存用户消息到数据库 // 2. 构建上下文(包含历史消息) // 3. 调用LLM API // 4. 保存AI回复到数据库 // 5. 更新缓存 // 6. 返回结果 } // 流式响应处理 async processStreamMessage(conversationId, userMessage) {} } ``` #### LLM API客户端 (LLMApiClient) ```javascript class LLMApiClient { constructor(apiConfig) { this.baseURL = apiConfig.baseURL; this.apiKey = apiConfig.apiKey; this.model = apiConfig.model; } // 调用聊天完成API async createChatCompletion(messages, options = {}) { const response = await fetch(`${this.baseURL}/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: this.model, messages: messages, stream: options.stream || false, max_tokens: options.maxTokens || 2000, temperature: options.temperature || 0.7 }) }); return response; } } ``` ### 缓存策略 #### LRU缓存配置 ```javascript const LRU = require('lru-cache'); const cache = new LRU({ max: 500, // 最大缓存条目数 maxAge: 1000 * 60 * 30 // 30分钟过期 }); // 缓存键策略 const getCacheKey = (conversationId, messageHash) => { return `conv:${conversationId}:msg:${messageHash}`; }; ``` #### 缓存使用场景 1. **对话上下文缓存** - 缓存最近的对话上下文,减少数据库查询 2. **API响应缓存** - 对相同输入的LLM响应进行缓存 3. **用户会话缓存** - 缓存用户会话信息 ### 中间件系统 #### 请求日志中间件 ```javascript const requestLogger = (req, res, next) => { console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`); next(); }; ``` #### 错误处理中间件 ```javascript const errorHandler = (err, req, res, next) => { console.error('Error:', err); res.status(500).json({ error: 'Internal Server Error', message: process.env.NODE_ENV === 'development' ? err.message : '服务器内部错误' }); }; ``` #### 速率限制中间件 ```javascript const rateLimit = require('express-rate-limit'); const chatRateLimit = rateLimit({ windowMs: 1 * 60 * 1000, // 1分钟 max: 20, // 限制每个IP每分钟最多20次请求 message: '请求过于频繁,请稍后再试' }); ``` ## 项目结构 ``` chat-website/ ├── package.json ├── pnpm-workspace.yaml ├── README.md ├── .gitignore ├── frontend/ │ ├── package.json │ ├── vite.config.js │ ├── index.html │ ├── src/ │ │ ├── main.js │ │ ├── App.vue │ │ ├── components/ │ │ │ ├── layout/ │ │ │ │ ├── Layout.vue │ │ │ │ ├── Header.vue │ │ │ │ └── Sidebar.vue │ │ │ ├── chat/ │ │ │ │ ├── ChatView.vue │ │ │ │ ├── MessageList.vue │ │ │ │ ├── MessageItem.vue │ │ │ │ ├── ChatInput.vue │ │ │ │ └── TypingIndicator.vue │ │ │ └── common/ │ │ │ ├── Loading.vue │ │ │ └── ErrorMessage.vue │ │ ├── stores/ │ │ │ ├── index.js │ │ │ ├── chat.js │ │ │ ├── conversation.js │ │ │ └── user.js │ │ ├── api/ │ │ │ ├── client.js │ │ │ ├── chat.js │ │ │ └── conversation.js │ │ ├── router/ │ │ │ └── index.js │ │ ├── styles/ │ │ │ ├── main.css │ │ │ ├── variables.css │ │ │ └── components.css │ │ └── utils/ │ │ ├── helpers.js │ │ └── constants.js │ └── public/ │ └── favicon.ico └── backend/ ├── package.json ├── app.js ├── server.js ├── config/ │ ├── database.js │ └── llm.js ├── routes/ │ ├── index.js │ ├── chat.js │ └── conversations.js ├── services/ │ ├── ConversationService.js │ ├── ChatService.js │ └── LLMApiClient.js ├── models/ │ ├── database.js │ ├── Conversation.js │ └── Message.js ├── middleware/ │ ├── auth.js │ ├── rateLimit.js │ ├── logger.js │ └── errorHandler.js ├── utils/ │ ├── cache.js │ └── helpers.js └── database/ ├── schema.sql └── chat.db ``` ## 测试策略 ### 前端测试 #### 单元测试 (Vitest) - 组件逻辑测试 - Store状态管理测试 - 工具函数测试 #### 组件测试 (Vue Test Utils) - 组件渲染测试 - 用户交互测试 - Props和Events测试 #### E2E测试 (Playwright) - 完整对话流程测试 - 跨浏览器兼容性测试 - 移动端响应式测试 ### 后端测试 #### 单元测试 (Jest) **API端点测试** ```javascript describe('Chat API', () => { test('should send message successfully', async () => { const response = await request(app) .post('/api/chat/send') .send({ conversationId: 1, message: '你好' }); expect(response.status).toBe(200); expect(response.body).toHaveProperty('response'); }); }); ``` **服务层测试** ```javascript describe('ChatService', () => { test('should process message correctly', async () => { const chatService = new ChatService(mockApiClient, mockCache); const result = await chatService.processMessage(1, '测试消息'); expect(result).toHaveProperty('userMessage'); expect(result).toHaveProperty('aiResponse'); }); }); ``` #### 集成测试 - 数据库操作测试 - 第三方API集成测试 - 缓存机制测试 #### 性能测试 - API响应时间测试 - 并发请求处理测试 - 内存使用监控