【前端功能】Hexo博客AI助手功能实现指南(集成DeepSeek/智谱GLM-4)
一、前言
在AI技术快速发展的时代,为个人博客添加智能助手功能已成为提升用户体验的重要手段。本文详细介绍如何在Hexo博客中实现一个美观实用的AI助手,支持多种AI模型接入(智谱GLM-4、DeepSeek等),并提供完整的代码实现。
特别值得一提的是,智谱AI推出的GLM-4模型目前提供了免费版本(glm-4-flash),可以零成本为你的博客增添智能交互能力。
二、功能特点
实现后的AI助手功能将具备以下特点:
- 美观的浮动聊天窗口:支持深色/浅色模式自动适配
- 多种模型支持:可接入智谱GLM-4、DeepSeek等多种AI模型
- 两种实现版本:完整版(API调用)和基础版(预设问答,无需API)
- 流畅的用户体验:打字动画、加载提示、Markdown渲染支持
- 响应式设计:完美适配移动端和桌面端
- 本地记忆功能:保存聊天历史,提供连续对话体验
三、实现步骤
(一)准备工作
1. 所需资源
- 已搭建的Hexo博客
- 智谱AI平台账号(使用GLM-4时需要)或DeepSeek账号
- 基本的JavaScript和CSS知识
2. 注册智谱AI账号(可选)
如果选择使用智谱GLM-4模型:
- 访问智谱AI官网
- 完成注册并登录
- 在个人中心创建API密钥并保存
(二)创建必要文件
在博客的source/js
目录下创建以下文件:
ai-assistant.js
(API版本)
ai-assistant-basic.js
(基础版本,可选)
在博客的source/css
目录下创建:
(三)编写CSS样式
创建美观的UI界面,以下是核心CSS代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
| .ai-assistant-container { position: fixed; bottom: 70px; right: 20px; width: 350px; height: 450px; background-color: #fff; border-radius: 16px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); display: flex; flex-direction: column; z-index: 1000; overflow: hidden; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); border: 1px solid rgba(0, 0, 0, 0.1); }
[data-user-color-scheme='dark'] .ai-assistant-container { background-color: #2d2d2d; border-color: #444; color: #f0f0f0; }
.ai-assistant-toggle { position: fixed; bottom: 20px; right: 20px; width: 50px; height: 50px; border-radius: 50%; background: linear-gradient(135deg, #6e8efb 0%, #a777e3 100%); color: white; border: none; box-shadow: 0 3px 15px rgba(0, 0, 0, 0.25); cursor: pointer; z-index: 1000; display: flex; align-items: center; justify-content: center; font-size: 20px; transition: all 0.3s ease; animation: float 3s ease-in-out infinite; }
@keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-6px); } 100% { transform: translateY(0px); } }
.ai-assistant-message { display: flex; margin-bottom: 15px; }
.ai-assistant-message.user-message { justify-content: flex-end; }
.message-avatar { width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 8px; }
.user-message .message-avatar { background-color: #e9f5ff; color: #4a89dc; }
.bot-message .message-avatar { background-color: #f5f0ff; color: #a777e3; }
.message-content { max-width: 70%; padding: 10px 14px; border-radius: 18px; font-size: 14px; line-height: 1.5; }
.user-message .message-content { background-color: #4a89dc; color: white; border-top-right-radius: 4px; }
.bot-message .message-content { background-color: #f0f0f0; color: #333; border-top-left-radius: 4px; }
[data-user-color-scheme='dark'] .bot-message .message-content { background-color: #3a3a3a; color: #e0e0e0; }
.ai-assistant-loading { display: flex; align-items: center; justify-content: center; height: 20px; }
.ai-assistant-loading span { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background-color: #888; margin: 0 3px; animation: bounce 1.4s infinite ease-in-out both; }
.ai-assistant-loading span:nth-child(1) { animation-delay: -0.32s; }
.ai-assistant-loading span:nth-child(2) { animation-delay: -0.16s; }
@keyframes bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1.0); } }
|
(四)实现智谱GLM-4版本(完整版)
以下是使用智谱GLM-4模型的JavaScript实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
(function() { 'use strict'; const config = { botName: '博客智能助手', welcomeMessage: '你好!我是博客助手,有什么可以帮到你的吗?', placeholder: '输入你的问题...', apiKey: '', apiEndpoint: 'https://open.bigmodel.cn/api/paas/v4/chat/completions', modelName: 'glm-4-flash-250414', maxTokens: 2000, temperature: 0.7 }; let chatContainer, chatMessages, userInput, sendButton, toggleButton; function init() { createChatUI(); bindEvents(); addBotMessage(config.welcomeMessage); loadChatHistory(); } function createChatUI() { chatContainer = document.createElement('div'); chatContainer.className = 'ai-assistant-container'; chatContainer.innerHTML = ` <div class="ai-assistant-header"> <div class="ai-assistant-title"> <i class="fas fa-robot"></i> ${config.botName} </div> <div class="ai-assistant-actions"> <button class="ai-assistant-minimize">—</button> <button class="ai-assistant-close">×</button> </div> </div> <div class="ai-assistant-messages"></div> <div class="ai-assistant-input-container"> <textarea class="ai-assistant-input" placeholder="${config.placeholder}" rows="1"></textarea> <button class="ai-assistant-send"> <i class="fas fa-paper-plane"></i> </button> </div> `; toggleButton = document.createElement('button'); toggleButton.className = 'ai-assistant-toggle'; toggleButton.innerHTML = '<i class="fas fa-robot"></i>'; toggleButton.title = '打开AI助手'; document.body.appendChild(chatContainer); document.body.appendChild(toggleButton); chatMessages = chatContainer.querySelector('.ai-assistant-messages'); userInput = chatContainer.querySelector('.ai-assistant-input'); sendButton = chatContainer.querySelector('.ai-assistant-send'); chatContainer.classList.add('collapsed'); } async function fetchAIResponse(message) { if(!config.apiKey) { return '抱歉,AI助手尚未配置API密钥。请联系博客管理员设置API密钥。'; } try { const response = await fetch(config.apiEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${config.apiKey}` }, body: JSON.stringify({ model: config.modelName, messages: [ { role: 'system', content: '你是一个友好、专业的博客助手,负责回答访客的问题。你的回答应当简洁、专业、有帮助性。' }, { role: 'user', content: message } ], max_tokens: config.maxTokens, temperature: config.temperature }) }); const data = await response.json(); if(data.error) { console.error('API错误:', data.error); return `抱歉,AI服务出现问题:${data.error.message || '未知错误'}`; } return data.choices[0].message.content; } catch(error) { console.error('网络请求错误:', error); return '抱歉,连接AI服务时出现错误。请检查网络连接或稍后再试。'; } } if(document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
|
(五)实现DeepSeek版本
如果你想使用DeepSeek API,只需修改配置部分:
1 2 3 4 5 6 7 8 9 10 11
| const config = { botName: '博客智能助手', welcomeMessage: '你好!我是博客助手,有什么可以帮到你的吗?', placeholder: '输入你的问题...', apiKey: '', apiEndpoint: 'https://api.deepseek.com/v1/chat/completions', modelName: 'deepseek-chat', maxTokens: 2000, temperature: 0.7 };
|
(六)基础版实现(无需API)
如果不想申请API密钥或担心API使用成本,可以使用基础版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
(function() { 'use strict'; const faqs = [ { keywords: ['博客', '内容', '文章', '写什么'], answer: '这个博客主要分享技术学习笔记、编程技巧和问题解决方案,涵盖后端开发、前端技术、数据库和Linux等领域的内容。' }, { keywords: ['联系', '作者', '博主', '交流'], answer: '你可以通过以下方式联系博主:\n1. 在文章下方留言评论\n2. 通过"关于"页面的社交媒体链接' }, ]; function generateResponse(message) { message = message.toLowerCase(); for (const faq of faqs) { if (faq.keywords.some(keyword => message.includes(keyword.toLowerCase()))) { return faq.answer; } } return '抱歉,我目前无法回答这个问题。你可以尝试浏览博客分类或使用搜索功能查找相关内容。'; } })();
|
(七)引入AI助手到博客中
在Hexo主题的配置文件中添加自定义JS和CSS:
1 2 3 4 5
| custom_js: - /js/ai-assistant.js custom_css: - /css/ai-assistant.css
|
四、高级功能
(一)保护API密钥安全
为了避免API密钥在前端暴露,可以使用代理服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| exports.handler = async function(event) { if (event.httpMethod !== 'POST') { return { statusCode: 405, body: 'Method Not Allowed' }; }
try { const body = JSON.parse(event.body); const { message } = body; const response = await fetch('https://open.bigmodel.cn/api/paas/v4/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.ZHIPUAI_API_KEY}` }, body: JSON.stringify({ model: 'glm-4-flash-250414', messages: [{ role: 'user', content: message }], max_tokens: 2000, temperature: 0.7 }) }); const data = await response.json(); return { statusCode: 200, body: JSON.stringify(data) }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: error.message }) }; } };
|
(二)实现多轮对话记忆
保存对话历史,实现上下文连续对话:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| let conversationHistory = [];
async function sendMessageWithContext(message) { conversationHistory.push({ role: 'user', content: message }); const messagesWithContext = [ { role: 'system', content: '你是一个友好、专业的博客助手,负责回答访客的问题。' }, ...conversationHistory ]; if(messagesWithContext.length > 10) { messagesWithContext = [ messagesWithContext[0], ...messagesWithContext.slice(messagesWithContext.length - 9) ]; } conversationHistory.push({ role: 'assistant', content: aiResponse }); return aiResponse; }
|
(三)添加语音输入功能
使用Web Speech API实现语音输入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const voiceButton = document.createElement('button'); voiceButton.className = 'ai-assistant-voice'; voiceButton.innerHTML = '<i class="fas fa-microphone"></i>'; inputContainer.appendChild(voiceButton);
voiceButton.addEventListener('click', function() { if ('webkitSpeechRecognition' in window) { const recognition = new webkitSpeechRecognition(); recognition.lang = 'zh-CN'; recognition.interimResults = false; recognition.onresult = function(event) { const transcript = event.results[0][0].transcript; userInput.value = transcript; sendMessage(); }; recognition.start(); } else { alert('抱歉,您的浏览器不支持语音识别功能'); } });
|
五、常见问题解决
(一)API调用失败
如果遇到API调用失败的问题:
- API密钥错误:确认API密钥是否正确复制
- 网络问题:检查网络连接是否正常
- 请求格式错误:确保请求体格式符合API要求
- 添加重试机制:
1 2 3 4 5 6 7 8 9 10 11
| async function fetchWithRetry(url, options, retries = 3) { try { return await fetch(url, options); } catch(error) { if(retries > 0) { console.log(`请求失败,剩余重试次数: ${retries-1}`); return fetchWithRetry(url, options, retries - 1); } throw error; } }
|
(二)深色模式适配问题
如果深色模式显示不正确,可能需要修改CSS变量或添加更多适配规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| :root { --ai-primary-color: #4a89dc; --ai-text-color: #333; --ai-bg-color: #fff; }
[data-user-color-scheme='dark'] { --ai-primary-color: #5d9cff; --ai-text-color: #f0f0f0; --ai-bg-color: #2d2d2d; }
.ai-assistant-header { background-color: var(--ai-primary-color); }
|
六、总结
通过本文介绍的方法,我们可以为Hexo博客添加一个美观实用的AI助手功能。无论是选择接入智谱GLM-4的免费模型,还是使用DeepSeek等其他AI服务,或者仅实现基础版预设问答,都能为博客访客提供更好的交互体验。
特别值得一提的是,智谱AI提供的GLM-4-Flash模型目前完全免费使用,这使得个人博客站长也能零成本享受AI带来的便利。
希望这篇教程对你有所帮助,赶快为你的博客添加一个智能助手吧!
参考资料
- 智谱AI官方文档
- Hexo官方文档
- DeepSeek API文档