用 AI 自动生成壁纸标题、描述和 SEO Slug

0 阅读6分钟

用 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 的生成有两个来源:

  1. AI 生成的 seo_slug(优先):翻译阶段同步产出
  2. 代码生成的 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_zhtitle_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~60s20 个中文标题 + 描述
Translate~30s20 个英文标题 + 描述 + SEO slug
Slug~10s20 个语义化 URL

之前手动写一个 Pack 的内容需要 2-3 小时。

技术选型小结

决策选择原因
AI SDKVercel 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