尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

影墨·今颜模型Node.js调用实战:构建轻量级AI绘画Web应用

影墨·今颜模型Node.js调用实战:构建轻量级AI绘画Web应用 影墨·今颜模型Node.js调用实战构建轻量级AI绘画Web应用最近在捣鼓AI绘画应用发现很多开发者都想快速搭建一个自己的AI画板但往往被复杂的模型部署和前后端联调劝退。其实用Node.js配合现有的AI模型API完全可以快速构建一个轻量级的Web应用。今天我就以“影墨·今颜”这个模型为例带你走一遍从零搭建一个具备小红书风格画廊的AI绘画应用的全过程。整个过程不涉及复杂的深度学习框架重点在于工程落地和前后端协作非常适合想快速验证产品想法的全栈开发者。1. 项目目标与环境准备我们的目标是构建一个最小可行产品MVP用户在前端输入文字描述后端调用“影墨·今颜”模型的API生成图片并将结果展示在一个美观的画廊页面上。整个应用会包含用户会话管理和简单的图片缓存以提升体验。首先确保你的开发环境已经就绪。1.1 Node.js安装及环境配置这是整个项目的基石。如果你还没安装Node.js可以去官网下载长期支持版LTS。安装过程很简单一路点击“下一步”即可。安装完成后打开终端或命令行工具输入以下命令来验证安装是否成功node --version npm --version如果能看到版本号比如v18.x.x和9.x.x说明安装成功。npm是Node.js的包管理器我们后面安装依赖全靠它。接下来为我们的项目创建一个独立的目录并初始化mkdir ai-painting-webapp cd ai-painting-webapp npm init -y这会在当前目录生成一个package.json文件它记录了项目信息和依赖。1.2 获取模型API访问凭证要调用“影墨·今颜”模型你需要拥有其API的访问权限和密钥。这通常需要在提供该模型的平台上注册账号并创建应用来获取。假设你已获得了一个API密钥通常是一长串字符如sk-xxxxxxxxxxxx和API的基础地址Endpoint。重要提示请务必妥善保管你的API密钥不要将它直接硬编码在客户端代码中也不要上传到公开的代码仓库如GitHub。我们稍后会将其放在后端的环境变量里。2. 后端服务搭建Node.js与Express后端负责接收前端的生成请求调用AI模型API并返回结果。我们选用Express框架因为它轻量且灵活。2.1 初始化后端项目并安装依赖在项目根目录下我们创建一个server文件夹来存放后端代码。mkdir server cd server npm init -y然后安装必要的依赖包npm install express cors dotenv axiosexpress: Web框架。cors: 处理跨域请求方便前后端分离开发。dotenv: 从.env文件加载环境变量。axios: 用于向后端发起HTTP请求这里我们用它来调用“影墨·今颜”的API。同时安装开发依赖nodemon它可以在我们修改代码后自动重启服务提升开发效率。npm install --save-dev nodemon接着修改server目录下的package.json在scripts部分添加启动命令{ scripts: { start: node index.js, dev: nodemon index.js } }2.2 创建核心后端服务文件在server目录下创建以下几个文件1..env文件这个文件用来存储敏感信息记得把它加入.gitignore。PORT3001 AI_API_KEY你的_影墨今颜_API_密钥 AI_API_BASE_URL模型API的基础地址2.index.js文件这是后端服务的入口。require(dotenv).config(); const express require(express); const cors require(cors); const axios require(axios); const app express(); const port process.env.PORT || 3001; // 中间件 app.use(cors()); // 允许跨域 app.use(express.json()); // 解析JSON格式的请求体 // 内存中的简单缓存和会话存储生产环境请换用Redis等 const imageCache new Map(); const userSessions new Map(); // 健康检查端点 app.get(/health, (req, res) { res.json({ status: OK, message: AI Painting Server is running. }); }); // 图片生成端点 app.post(/api/generate, async (req, res) { try { const { prompt, sessionId } req.body; if (!prompt) { return res.status(400).json({ error: Prompt is required. }); } // 检查缓存中是否有相同提示词的结果 const cacheKey prompt.toLowerCase().trim(); if (imageCache.has(cacheKey)) { console.log(Cache hit for prompt: ${prompt}); return res.json({ success: true, imageUrl: imageCache.get(cacheKey), cached: true }); } console.log(Calling AI API for prompt: ${prompt}); // 调用“影墨·今颜”模型API const aiResponse await axios.post( ${process.env.AI_API_BASE_URL}/generate, // 请替换为实际的API路径 { prompt: prompt, negative_prompt: low quality, blurry, distorted, // 负面提示词提升质量 width: 512, height: 512, num_inference_steps: 20 }, { headers: { Authorization: Bearer ${process.env.AI_API_KEY}, Content-Type: application/json } } ); // 假设API返回的数据中包含图片的URL或Base64编码 const generatedImageUrl aiResponse.data.image_url || aiResponse.data.data; // 存入缓存 imageCache.set(cacheKey, generatedImageUrl); // 如果提供了sessionId关联生成记录简化版 if (sessionId) { if (!userSessions.has(sessionId)) { userSessions.set(sessionId, []); } userSessions.get(sessionId).push({ prompt, imageUrl: generatedImageUrl, timestamp: new Date() }); } res.json({ success: true, imageUrl: generatedImageUrl, cached: false }); } catch (error) { console.error(Generation error:, error.response?.data || error.message); res.status(500).json({ success: false, error: Failed to generate image., details: error.response?.data || error.message }); } }); // 获取用户历史记录端点 app.get(/api/history/:sessionId, (req, res) { const history userSessions.get(req.params.sessionId) || []; res.json({ success: true, history }); }); app.listen(port, () { console.log(Server listening on port ${port}); });这段代码构建了一个简单的后端服务提供了生成图片和查询历史记录的功能并实现了基于内存的请求缓存和会话管理。请注意AI_API_BASE_URL和请求体结构需要根据“影墨·今颜”模型API的实际文档进行调整。现在在server目录下运行npm run dev你的后端服务就应该在http://localhost:3001启动起来了。3. 前端界面开发Vue 3与画廊设计前端的目标是提供一个简洁易用的界面并展示生成的作品。我们使用Vue 3的组合式API和Element Plus组件库来快速搭建。3.1 初始化Vue项目回到项目根目录我们使用Vite来创建Vue项目因为它速度更快。npm create vuelatest frontend按照提示操作项目名称可以就叫frontend在选择特性时确保选中TypeScript和Element Plus或者你可以在创建后手动安装。创建完成后进入前端目录并安装依赖cd frontend npm install为了调用我们自己的后端还需要安装axiosnpm install axios3.2 构建小红书风格画廊页面我们主要修改src/App.vue文件。目标是创建一个包含输入区、生成按钮和图片画廊的页面。template div classapp-container header classapp-header h1 我的AI画坊/h1 p classsubtitle用文字生成你的专属“影墨·今颜”/p /header main classmain-content !-- 输入区域 -- div classinput-section el-input v-modelprompt :autosize{ minRows: 3, maxRows: 5 } typetextarea placeholder描述你心中的画面吧例如一只戴着贝雷帽的橘猫在巴黎咖啡馆的窗边晒太阳油画风格 keyup.entergenerateImage / div classaction-bar el-button typeprimary :loadingisGenerating clickgenerateImage {{ isGenerating ? 创作中... : 开始创作 }} /el-button el-button clickclearHistory清空我的画廊/el-button span classsession-id会话ID: {{ sessionId }}/span /div /div !-- 画廊区域 -- div classgallery-section h2我的作品集/h2 div v-ifhistory.length 0 classempty-state p这里还没有作品哦输入描述生成第一张图吧/p /div div v-else classimage-grid div v-for(item, index) in history :keyindex classimage-card div classcard-header span classprompt-text{{ item.prompt }}/span span classtime{{ formatTime(item.timestamp) }}/span /div img :srcitem.imageUrl :altitem.prompt loadonImageLoad / div classcard-actions el-button sizesmall clickdownloadImage(item.imageUrl, item.prompt)下载/el-button el-button sizesmall typeinfo clickregenerate(item.prompt)重新生成/el-button /div /div /div /div /main /div /template script setup langts import { ref, onMounted } from vue import axios from axios import { ElMessage } from element-plus const prompt ref() const isGenerating ref(false) const history refArray{prompt: string, imageUrl: string, timestamp: Date}([]) const sessionId ref() // 生成一个简单的会话ID const generateSessionId () { return sess_ Math.random().toString(36).substring(2, 11) } // 页面加载时初始化会话并加载历史记录 onMounted(() { const savedSessionId localStorage.getItem(ai_paint_session_id) if (savedSessionId) { sessionId.value savedSessionId fetchHistory() } else { sessionId.value generateSessionId() localStorage.setItem(ai_paint_session_id, sessionId.value) } }) // 调用后端生成图片 const generateImage async () { if (!prompt.value.trim()) { ElMessage.warning(请输入描述文字哦~) return } isGenerating.value true try { const response await axios.post(http://localhost:3001/api/generate, { prompt: prompt.value, sessionId: sessionId.value }) if (response.data.success) { const newItem { prompt: prompt.value, imageUrl: response.data.imageUrl, timestamp: new Date() } history.value.unshift(newItem) // 新作品放在最前面 if (response.data.cached) { ElMessage.success(从缓存中找到啦) } else { ElMessage.success(创作完成) } prompt.value // 清空输入框 } else { throw new Error(response.data.error) } } catch (error: any) { console.error(生成失败:, error) ElMessage.error(生成失败: ${error.response?.data?.details || error.message}) } finally { isGenerating.value false } } // 获取当前会话的历史记录 const fetchHistory async () { try { const response await axios.get(http://localhost:3001/api/history/${sessionId.value}) if (response.data.success) { history.value response.data.history } } catch (error) { console.error(获取历史记录失败:, error) } } // 重新生成某条描述对应的图片 const regenerate (oldPrompt: string) { prompt.value oldPrompt generateImage() } // 下载图片 const downloadImage (url: string, promptText: string) { const link document.createElement(a) link.href url link.download AI绘画_${promptText.substring(0, 20)}.png document.body.appendChild(link) link.click() document.body.removeChild(link) } // 清空本地历史前端视图 const clearHistory () { history.value [] ElMessage.info(本地画廊已清空) } // 图片加载完成后的回调可用于懒加载优化 const onImageLoad (event: Event) { // console.log(Image loaded, event.target) } // 格式化时间显示 const formatTime (date: Date) { return new Date(date).toLocaleTimeString([], { hour: 2-digit, minute: 2-digit }) } /script style scoped .app-container { max-width: 1200px; margin: 0 auto; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif; } .app-header { text-align: center; margin-bottom: 40px; } .app-header h1 { font-size: 2.5rem; margin-bottom: 10px; color: #333; } .subtitle { font-size: 1.1rem; color: #666; } .input-section { background: #f9f9f9; padding: 25px; border-radius: 12px; margin-bottom: 30px; box-shadow: 0 2px 12px rgba(0,0,0,0.05); } .action-bar { margin-top: 15px; display: flex; gap: 15px; align-items: center; } .session-id { font-size: 0.85rem; color: #888; margin-left: auto; } .gallery-section h2 { font-size: 1.8rem; margin-bottom: 20px; color: #333; padding-bottom: 10px; border-bottom: 2px solid #eee; } .empty-state { text-align: center; padding: 60px 20px; color: #999; font-size: 1.1rem; } .image-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 25px; } .image-card { background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.08); transition: transform 0.3s ease, box-shadow 0.3s ease; } .image-card:hover { transform: translateY(-5px); box-shadow: 0 8px 30px rgba(0,0,0,0.12); } .card-header { padding: 15px; background: #fafafa; border-bottom: 1px solid #eee; } .prompt-text { display: block; font-size: 0.95rem; color: #555; margin-bottom: 5px; line-height: 1.4; } .time { font-size: 0.8rem; color: #aaa; } .image-card img { width: 100%; height: 250px; object-fit: cover; display: block; } .card-actions { padding: 12px 15px; display: flex; justify-content: space-between; background: #fafafa; } /style这个前端页面模仿了小红书卡片式的设计风格包含了完整的交互逻辑。现在在frontend目录下运行npm run dev前端应用通常会启动在http://localhost:5173。确保后端服务也在运行这样前后端就能联动了。4. 前后端联调与部署建议当你在前端输入描述并点击“开始创作”后前端会向后端的/api/generate发送请求。后端收到请求后会先检查内存缓存如果命中则直接返回否则调用“影墨·今颜”的API。生成成功后图片URL会返回给前端并展示在画廊中。在开发过程中你可能会遇到跨域问题但我们已经在后端使用了cors()中间件所以应该没问题。如果API调用失败请重点检查.env文件中的AI_API_KEY和AI_API_BASE_URL是否正确。后端调用AI API的请求体格式、URL路径是否与官方文档一致。网络连接是否正常。当MVP在本地跑通后你可以考虑将其部署到云服务器或容器平台。这里有几个简单的方向后端部署可以将server目录下的代码部署到任何支持Node.js的云平台。记得在平台的环境变量配置中设置AI_API_KEY和AI_API_BASE_URL。前端部署在frontend目录下运行npm run build生成的dist文件夹可以部署到静态网站托管服务。缓存与数据库当前使用的是内存缓存服务器重启数据会丢失。生产环境建议替换为 Redis 等持久化缓存用户历史记录可以存入数据库。安全性增加API调用频率限制、请求验证等。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。
返回列表