用 AI 自动生成壁纸标题、描述和 SEO Slug
200+ 张壁纸手写标题描述不现实,我用 Qwen-VL 视觉模型 + 文本模型搭了一条三步流水线。
壁纸平台最头疼的不是代码,是内容。
每张壁纸需要:中文标题、中文描述、英文标题、英文描述、SEO Slug。一个 Pack 里 20 张壁纸,算下来 100+ 条文案。手写?一天写不完一个 Pack。
WallpaperSense 目前有 200+ 张壁纸、20+ 个 Pack,全部内容由 AI 自动生成。下面分享具体的实现方案。
三步流水线:Extract - Translate - Slug
AI 内容生成被设计为异步任务,分三个阶段严格顺序执行:
Extract(提取) -> 视觉模型看图,生成中文标题和描述
|
Translate(翻译) -> 文本模型将中文翻译为英文
|
Slug(URL 优化) -> 从英文标题提取关键词,生成 SEO 友好的 URL slug
为什么不直接生成英文?因为我的壁纸面向中文和英文两个市场。中文到英文的翻译质量比直接让 AI 生成英文要好——中文输出更稳定,翻译时可以加更多约束。
阶段一:Extract——让 AI 看图说话
壁纸的标题和描述不能靠文本推理,得让 AI 看到图片。我用的是通义千问的视觉模型 qwen-vl-max,通过 Vercel AI SDK 的 OpenAI 兼容协议调用:
import { createOpenAI } from '@ai-sdk/openai';
import { generateText } from 'ai';
export async function describeWallpaper(input: WallpaperDescribeInput) {
const config = await getVisionConfig();
const provider = createOpenAI({ baseURL: config.baseUrl, apiKey: config.apiKey });
const { text } = await generateText({
model: provider.chat(config.model),
messages: [{
role: 'user',
content: [
{ type: 'text', text: prompt },
{ type: 'image', image: new URL(input.imageUrl) },
],
}],
temperature: 0.7,
});
return parseJsonResponse<WallpaperDescribeResult>(text);
}
关键设计:
- 传缩略图 URL 而不是原图:原图可能 40MB,视觉模型只需要看到画面内容,400x800 的缩略图完全够用
- 分辨率作为 Prompt 上下文:告诉模型这是 4K 还是 8K 壁纸,让生成的描述包含分辨率信息
Prompt 工程经验
写 Prompt 踩了不少坑。最初生成的内容模板化严重,每张图都是"这是一幅xx风格的壁纸,展现了xx场景"。优化后的要点:
不要:
- "这张壁纸展示了..." -> AI 几乎每次都会用这个开头
- 要求"详细描述画面中的每个元素" -> 会变成流水账
要:
- 直接用场景句:"晨雾笼罩的山间溪流"
- 限制字数:标题 15-25 字,描述 50-80 字
- 给具体示例:提供 3-5 个优质标题让 AI 参考风格
- 包含分辨率和设备信息:既是 SEO 需要,也是用户关心的
阶段二:Translate——精准翻译而非重新生成
翻译不是简单的 API 调用。壁纸标题翻译有几个特殊要求:
const prompt = `You are a professional translator...
Rules:
- Keep brand names unchanged
- Do NOT transliterate Chinese titles into pinyin
For example "枫韵东方" should NOT become "Feng Yun Dong Fang"
- Title fields: keep concise but include subject, style, resolution
- Description fields: describe scene, mood, resolution in natural language
- Also generate a "seo_slug" field - URL-friendly, 3-5 keywords
`;
不拼音化是最重要的规则。很多 AI 模型遇到中文专有名词会直接用拼音,比如"枫韵东方"变成"Feng Yun Dong Fang"——对英文用户毫无意义。正确做法是意译:"Oriental Maple Charm"。
翻译时同时生成 SEO Slug 是一个效率优化——反正 AI 已经在处理英文内容了,顺便提取关键词生成 slug 几乎零成本。
阶段三:Slug——语义化的 URL
SEO Slug 的生成有两个来源:
- AI 生成的 seo_slug(优先):翻译阶段同步产出
- 代码生成的 fallback:如果 AI 结果无效,用
generateSeoSlug()从英文标题提取
最终 slug 格式:{关键词}-{entity_id前8位}
seaside-stairs-summer-healing-5f8ee3d4
japanese-mountain-wildflower-valley-8k-a3b2c1d4
加 ID 后缀的原因是避免重复——两张"日落海滩"壁纸不能共用同一个 URL。
波次执行(Wave Execution)
三个步骤有严格依赖:没有中文描述就没法翻译,没有英文翻译就没法生成 slug。
任务处理器每次被调用时,按优先级检查:
async processPendingTasks(limit: number) {
const WAVES = [AiTaskStep.EXTRACT, AiTaskStep.TRANSLATE, AiTaskStep.SLUG];
let currentStep = null;
for (const step of WAVES) {
const { data: peek } = await aiContentTaskDAO.findPending(1, step);
if (peek?.length) {
currentStep = step;
break;
}
}
// 本轮只处理 currentStep 类型的任务
const { data: tasks } = await aiContentTaskDAO.findPending(limit, currentStep);
// ...
}
效果:如果还有 Extract 任务没完成,不会开始 Translate。全部 Extract 完成后,才轮到 Translate。这保证了数据一致性。
Pack 描述:不看图,看全局
Pack(主题包)的描述生成和单张壁纸不同——不是看图,而是综合信息:
export async function describePack(ctx: PackDescribeContext) {
// 输入:内部名称、壁纸数量、设备分布、子壁纸标题列表
const prompt = buildPackDescribePrompt({
internalName: 'japanese-mountain-wildflower',
wallpaperCount: 20,
phoneCount: 8, desktopCount: 8, tabletCount: 4,
wallpaperTitles: ['雾中山间野花', '晨曦下的山谷', ...],
});
}
用文本模型(qwen-plus)而不是视觉模型,因为 Pack 描述需要的是概括能力而非识图能力。把所有子壁纸的标题作为上下文传入,让 AI 归纳出 Pack 的整体主题。
翻译存储设计
翻译内容存在独立的 entity_translations 表中,而不是在 wallpapers 表上加 title_zh、title_en 字段:
entity_translations:
entity_type: 'wallpaper' | 'pack'
entity_id: uuid
field_name: 'title' | 'description' | 'name' | 'seo_slug'
locale: 'zh' | 'en' | 'ja' | ...
value: text
优点:
- 动态扩展语言:加日语只需要新建 Translate 任务,不用改表结构
- 字段级粒度:可以只翻译标题不翻译描述
- AI 结果回写主表:英文翻译完成后同步写回
wallpapers.title,保证向后兼容
容错和重试
AI 调用不稳定是常态。整个系统的容错机制:
- JSON 解析容错:AI 有时返回 markdown 代码块包裹的 JSON,解析器会自动剥离
- Skip 逻辑:如果目标语言已有翻译且
overwrite=false,跳过不重复生成 - 重试机制:失败任务自动标记,最多重试 3 次
- Stuck 检测:处理中超过 5 分钟的任务自动重置为 pending
效果
一个 20 张壁纸的 Pack,AI 完成全部内容生成大约需要 2-3 分钟:
| 步骤 | 耗时 | 内容 |
|---|---|---|
| Extract | ~60s | 20 个中文标题 + 描述 |
| Translate | ~30s | 20 个英文标题 + 描述 + SEO slug |
| Slug | ~10s | 20 个语义化 URL |
之前手动写一个 Pack 的内容需要 2-3 小时。
技术选型小结
| 决策 | 选择 | 原因 |
|---|---|---|
| AI SDK | Vercel AI SDK (@ai-sdk/openai) | 统一的 OpenAI 兼容协议,切换模型零成本 |
| 视觉模型 | qwen-vl-max | 中文识图效果好,价格合理 |
| 文本模型 | qwen-plus | 翻译质量稳定,上下文能力强 |
| 配置存储 | 数据库 system_configs 表 | 运行时切换模型/key,无需重新部署 |
| 任务架构 | 异步任务队列 + 前端轮询 | 适配 Vercel Hobby 10 秒超时 |
如果你对 AI 生成的壁纸内容效果感兴趣,可以访问 WallpaperSense 看实际效果——每一条标题、描述和 URL 都是 AI 生成的。
标签: #AI #prompt工程 #qwen #内容生成 #独立开发 #SEO #nextjs