Qwen3-VL-FP8:终极多模态AI视觉语言模型
**导语**:Qwen3-VL系列推出FP8量化版本,在保持原始模型性能的同时实现算力成本大幅降低,推动多模态大模型向更广泛的产业应用迈出关键一步。## 行业现状:多模态AI的性能与效率平衡难题随着GPT-4V、Gemini等模型的问世,多模态AI已从实验室走向产业落地,但"高性能=高成本"的行业痛点始终存在。据Gartner最新报告,企业级多模态模型部署成本中,硬件资源占比高达62%,其
如何扩展Express-Mongoose-ES6-REST-API:添加新模块完整指南
Express-Mongoose-ES6-REST-API是一个基于Node.js的RESTful API微服务开发框架,它结合了Express和Mongoose的强大功能,并采用ES6语法编写,提供了代码覆盖率和JsonWebToken身份验证功能。本指南将详细介绍如何为这个框架添加新模块,帮助开发者快速扩展项目功能。
1. 理解项目结构
在开始添加新模块之前,首先需要了解Express-Mongoose-ES6-REST-API的项目结构。主要目录和文件如下:
- config/: 包含配置文件,如config.js、express.js等
- server/: 应用程序的主要代码目录
- auth/: 身份验证相关代码
- helpers/: 辅助工具和类,如APIError.js
- tests/: 测试文件
- user/: 用户模块相关代码
每个功能模块通常包含以下文件:
[module].model.js: 数据模型定义[module].controller.js: 业务逻辑处理[module].route.js: 路由定义[module].test.js: 单元测试
2. 创建新模块的步骤
2.1 创建模型文件
首先,我们需要创建一个新的模型文件。模型定义了数据结构和数据库交互方法。以创建一个"Post"模块为例,在server/post/目录下创建post.model.js文件:
const Promise = require('bluebird');
const mongoose = require('mongoose');
const httpStatus = require('http-status');
const APIError = require('../helpers/APIError');
/**
* Post Schema
*/
const PostSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
content: {
type: String,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
createdAt: {
type: Date,
default: Date.now
}
});
/**
* Statics
*/
PostSchema.statics = {
/**
* Get post
* @param {ObjectId} id - The objectId of post.
* @returns {Promise<Post, APIError>}
*/
get(id) {
return this.findById(id)
.exec()
.then((post) => {
if (post) {
return post;
}
const err = new APIError('No such post exists!', httpStatus.NOT_FOUND);
return Promise.reject(err);
});
},
/**
* List posts in descending order of 'createdAt' timestamp.
* @param {number} skip - Number of posts to be skipped.
* @param {number} limit - Limit number of posts to be returned.
* @returns {Promise<Post[]>}
*/
list({ skip = 0, limit = 50 } = {}) {
return this.find()
.sort({ createdAt: -1 })
.skip(+skip)
.limit(+limit)
.exec();
}
};
module.exports = mongoose.model('Post', PostSchema);
2.2 创建控制器文件
接下来,创建控制器文件post.controller.js,处理业务逻辑:
const Post = require('./post.model');
/**
* Load post and append to req.
*/
function load(req, res, next, id) {
Post.get(id)
.then((post) => {
req.post = post; // eslint-disable-line no-param-reassign
return next();
})
.catch(e => next(e));
}
/**
* Get post
* @returns {Post}
*/
function get(req, res) {
return res.json(req.post);
}
/**
* Create new post
* @property {string} req.body.title - The title of post.
* @property {string} req.body.content - The content of post.
* @property {string} req.body.author - The author of post.
* @returns {Post}
*/
function create(req, res, next) {
const post = new Post({
title: req.body.title,
content: req.body.content,
author: req.body.author
});
post.save()
.then(savedPost => res.json(savedPost))
.catch(e => next(e));
}
/**
* Update existing post
* @property {string} req.body.title - The title of post.
* @property {string} req.body.content - The content of post.
* @returns {Post}
*/
function update(req, res, next) {
const post = req.post;
post.title = req.body.title;
post.content = req.body.content;
post.save()
.then(savedPost => res.json(savedPost))
.catch(e => next(e));
}
/**
* Get post list.
* @property {number} req.query.skip - Number of posts to be skipped.
* @property {number} req.query.limit - Limit number of posts to be returned.
* @returns {Post[]}
*/
function list(req, res, next) {
const { limit = 50, skip = 0 } = req.query;
Post.list({ limit, skip })
.then(posts => res.json(posts))
.catch(e => next(e));
}
/**
* Delete post.
* @returns {Post}
*/
function remove(req, res, next) {
const post = req.post;
post.remove()
.then(deletedPost => res.json(deletedPost))
.catch(e => next(e));
}
module.exports = { load, get, create, update, list, remove };
2.3 创建路由文件
然后,创建路由文件post.route.js,定义API端点:
const express = require('express');
const postCtrl = require('./post.controller');
const router = express.Router(); // eslint-disable-line new-cap
router.route('/')
/** GET /api/posts - Get list of posts */
.get(postCtrl.list)
/** POST /api/posts - Create new post */
.post(postCtrl.create);
router.route('/:postId')
/** GET /api/posts/:postId - Get post */
.get(postCtrl.get)
/** PUT /api/posts/:postId - Update post */
.put(postCtrl.update)
/** DELETE /api/posts/:postId - Delete post */
.delete(postCtrl.remove);
/** Load post when API with postId route parameter is hit */
router.param('postId', postCtrl.load);
module.exports = router;
2.4 注册新路由
最后,需要在主路由文件中注册新创建的路由。编辑index.route.js文件:
const express = require('express');
const userRoutes = require('./server/user/user.route');
const authRoutes = require('./server/auth/auth.route');
const postRoutes = require('./server/post/post.route'); // 导入新路由
const router = express.Router(); // eslint-disable-line new-cap
// TODO: use glob to match *.route files
/** GET /health-check - Check service health */
router.get('/health-check', (req, res) =>
res.send('OK')
);
// mount user routes at /users
router.use('/users', userRoutes);
// mount auth routes at /auth
router.use('/auth', authRoutes);
// mount post routes at /posts // 注册新路由
router.use('/posts', postRoutes);
module.exports = router;
3. 添加测试文件
为了确保新模块的功能正常,建议添加测试文件post.test.js:
const request = require('supertest-as-promised');
const httpStatus = require('http-status');
const chai = require('chai');
const expect = chai.expect;
const app = require('../../index');
chai.config.includeStack = true;
describe('## Post API', () => {
let post = {
title: 'Test Post',
content: 'This is a test post',
author: '56c78793516564681e041791' // 替换为实际的用户ID
};
describe('# POST /api/posts', () => {
it('should create a new post', (done) => {
request(app)
.post('/api/posts')
.send(post)
.expect(httpStatus.OK)
.then((res) => {
expect(res.body.title).to.equal(post.title);
expect(res.body.content).to.equal(post.content);
post = res.body;
done();
})
.catch(done);
});
});
describe('# GET /api/posts', () => {
it('should get all posts', (done) => {
request(app)
.get('/api/posts')
.expect(httpStatus.OK)
.then((res) => {
expect(res.body).to.be.an('array');
done();
})
.catch(done);
});
});
// 可以添加更多测试用例...
});
4. 验证新模块
完成以上步骤后,你可以通过以下步骤验证新模块是否正常工作:
- 启动应用程序:
npm start - 使用API测试工具(如Postman)发送请求到新创建的API端点:
- POST /api/posts - 创建新文章
- GET /api/posts - 获取所有文章
- GET /api/posts/:postId - 获取特定文章
- PUT /api/posts/:postId - 更新文章
- DELETE /api/posts/:postId - 删除文章
5. 总结
通过以上步骤,你已经成功地为Express-Mongoose-ES6-REST-API框架添加了一个新的"Post"模块。这个过程可以应用于任何其他新模块的创建,只需按照相同的模式创建模型、控制器、路由和测试文件,并在主路由中注册新路由即可。
这种模块化的设计使得项目易于扩展和维护,每个功能模块都有清晰的职责划分,符合RESTful API的设计原则。希望本指南能帮助你更好地理解和使用Express-Mongoose-ES6-REST-API框架。
更多推荐
所有评论(0)