码龙大大头像
关注
使用蓝耘MaaS构建Markdown博文配图生成器:模型接入、并行任务与CORS处理封面图

使用蓝耘MaaS构建Markdown博文配图生成器:模型接入、并行任务与CORS处理

写技术文章时,配图工作往往占用不少时间——封面需要概括主题,正文插图需对应具体段落,生成后还可能要调整标题、比例或局部元素。过去我的做法是逐段整理提示词,分别生成和修改图片,流程分散且重复。这次我尝试把这些步骤整合到一个工具中,记录下实现过程中涉及模型接入、任务编排和本地开发环境问题的处理方式。

工具概览

这个工具暂命名为「博文视觉生成器」。上传 Markdown 文档后,可以运行“AI 智能规划配图”,也可以单独选择全文或某个段落,生成封面或正文插图。

  • 文本模型:通过蓝耘MaaS接入 GLM5.3(控制台模型ID为 glm-5.3)。
  • 视觉模型:图像生成和编辑使用 Sense U1.5 Lite。

项目使用 Vue 3 + Vite 开发,是一个纯前端应用,不含业务后端。界面分左右两栏:左侧是博文文档区(支持上传、编辑、预览和段落选择),右侧是视觉创作区(可选择封面/插图、风格与比例)。

整体调用链路如下:

Markdown 全文或选中段落

蓝耘MaaS · GLM5.3

理解内容、抽取主题与信息层级
生成视觉指令

商汤 · Sense U1.5 Lite

根据视觉指令生成封面或正文插图

图片编辑器

上传或复用生成结果
继续通过自然语言改图

一、模型服务选型与接入配置

1.1 选型考虑

项目需要在Codex中开发,同时前端要调用文本模型分析长文章,因此接入方式、模型参数清晰度和排错便利性是主要考量。蓝耘MaaS提供OpenAI兼容接口,可以复用现有请求层,只需替换base_url、api_key和模型ID。

接入前检查了以下配置项:

  1. 接口协议:文档提供OpenAI兼容调用示例。
  2. 模型字段:确认上下文长度是否能覆盖长文任务,并记录实际调用ID glm-5.3。
  3. 模型切换方式:同类兼容接口便于后续对照测试。
  4. 密钥与用量查询:API Key按项目创建,资源包页面可查看剩余量。

蓝耘接口文档
图1 蓝耘接口文档

蓝耘用量监控
图2 蓝耘用量监控

蓝耘模型列表
图3 蓝耘模型列表

1.2 Codex 与 CC Switch 配置

日常使用Codex时,有时额度用尽,需通过CC Switch切换其他模型服务。CC Switch可以保存多个供应商配置,在界面中切换Provider,更新Codex的模型、端点和认证信息,无需手工编辑配置文件。

Codex使用 ~/.codex/config.toml 保存Provider、模型与端点设置。对于只提供OpenAI Chat Completions接口的第三方服务,需要启用本地路由,将Codex的Responses请求转换为上游支持的格式。

1.3 创建项目专用API Key

在MaaS控制台创建仅限本项目的API Key,确认模型ID为 glm-5.3,并核对OpenAI兼容的基础地址。独立密钥便于隔离问题,测试结束后可停用。

创建API Key
图4 创建API Key

1.4 在CC Switch中配置Provider

CC Switch中新增自定义Provider,关键字段如下:

CC Switch 字段应填写的内容说明
Provider 名称蓝耘-GLM5.3仅用于识别
Base URL控制台提供的OpenAI兼容基础地址不是控制台网页地址
API Key项目专用Key不提交到仓库
模型glm-5.3实际调用ID
接口格式按接口文档选择若只有Chat Completions,需打开本地路由

注意:是否开启本地路由取决于上游接口格式,而非模型名称。配置后保存并启用,检查 ~/.codex/config.toml 确认 model_provider、model 和 base_url 已更新。

CC Switch配置
图5 CC Switch配置

配置后进行连通性测试,确保接口可用。

接口连通测试
图6 接口连通测试

1.5 验证Codex模型切换

切换Provider后,重新打开Codex,给出一个具体但不消耗过多额度的任务,例如阅读Vue项目目录结构并给出状态管理建议。验证Codex能否响应、模型名是否来自当前Provider,以及项目上下文是否可读取。

Codex模型验证
图7 Codex模型验证

Codex理解项目
图8 Codex理解项目

二、项目创建与初始化

2.1 创建项目

通过初始Prompt生成Vue 3 + Vite项目框架,后续多轮对话补充页面布局、并行任务、图片编辑和错误重试等功能。markdown-it 负责将Markdown转为HTML,dompurify 清理渲染结果。图片生成和编辑请求统一放在 src/services,页面组件只处理状态和交互。

输入初始Prompt
图9 输入初始Prompt

追加开发Prompt
图10 追加开发Prompt

项目目录结构
图11 项目目录结构

2.2 页面模型配置

右上角“模型配置”弹窗中填写文本模型和图像模型的服务地址、接口路径、模型ID和API Key。保存后配置写入localStorage,页面顶部显示配置状态。

三、核心实现

3.1 文本模型做视觉策划,而非直接生图

直接让图像模型读全文,容易只抓住表面关键词。因此将“理解文章”和“生成图片”拆开。上传Markdown后,提取标题和内容块,用户可选择全文或段落。createImagePrompt 将选中内容、图片用途、比例和风格发送给GLM5.3,请求中的 model 为 glm-5.3。

核心调用(简化,省略错误处理):

const payload = {
  model,
  messages: [
    { role: 'system', content: visualDirectorPrompt },
    {
      role: 'user',
      content: `请根据以下${scopeName}生成一条${targetName}指令。

文章标题:${documentTitle}
画面比例:${ratio}
视觉风格:${style}

--- 内容开始 ---
${source}
--- 内容结束 ---`,
    },
  ],
  temperature: 0.45,
  stream: false,
}

visualDirectorPrompt 约束了输出内容:封面概括全文,插图解释段落;图片中的文字(标题、数字、技术名词)由图像模型生成;只保留一个主标题和不超过三项核心信息;描述构图、层级、配色和留白;不添加原文没有的事实;最终只返回图像指令,不含解释或JSON。

3.2 统一生图和改图工作流

右侧创作区没有将“智能生成”和“图片编辑”硬切为两个页面。用户生成图片后可点击“编辑图片”进入近全屏编辑器;也可先点击“编辑已有图片”上传本地图片。

编辑器保留图片版本列表,编辑指令只描述“要改什么”,例如“把背景改成浅色网格,保留中间标题和流程结构”。编辑时把当前图片、修改要求和输出比例一起发送。

文生图请求:

const payload = {
  model,
  prompt,
  n: 1,
  size: editSizeByRatio[ratio] || 'auto',
  output_format: 'png',
  response_format: 'b64_json',
  watermark: true,
  prompt_extend: true,
}

图片编辑请求(/images/edits):

const payload = {
  model,
  images: [{ image_url: imageUrl }],
  prompt: instruction,
  n: 1,
  size: editSizeByRatio[ratio] || 'auto',
  response_format: 'b64_json',
  watermark: true,
  prompt_extend: true,
}

前端不负责二次排字,视觉指令、原图和比例交给模型,标题与技术名词与画面一同生成。

四、实际遇到的问题与处理

4.1 本地开发CORS限制

页面从 http://localhost:5173 直接请求图像接口时触发跨域错误。使用Vite代理解决:

const sensenovaProxy = {
  target: 'https://token.sensenova.cn',
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/api\/sensenova/, ''),
}

export default defineConfig({
  server: {
    proxy: {
      '/api/sensenova': sensenovaProxy,
    },
  },
})

请求层将目标地址改写为同源代理路径:

if (target.origin === 'https://token.sensenova.cn') {
  return `/api/sensenova${target.pathname}${target.search}`
}

修改后生图和改图接口正常。注意此代理仅开发预览有效,公开部署需服务端配置反向代理或后端代调。

4.2 并行任务提升效率

最初一次只能处理一张图,全篇配图耗时较长。改为独立任务并行执行——先为每条建议创建任务,再立即调用 executeTask,每个任务独立维护 prompting、generating、completed、failed 状态。

taskList.forEach((item) => {
  const newTask = {
    id: `task-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
    title: item.title,
    status: 'pending',
    // ... 其他字段
  }
  tasks.value.unshift(newTask)
  executeTask(newTask)
})

单任务失败不阻塞其他任务。当前仅少量配图,直接并行足够;若需大规模生成,后续可加并发上限和等待队列。

4.3 失败任务保留与重试

生图接口偶发网络中断或服务端错误。失败后不删除任务,而是改为 failed 状态,显示错误信息,并提供“重试”和“重新下发”按钮。

async function executeTask(task) {
  task.status = 'prompting'
  task.error = ''
  try {
    task.prompt = await createImagePrompt(/* ... */)
    task.status = 'generating'
    task.imageUrl = (await generateImage(task.prompt)).imageUrl
    task.status = 'completed'
  } catch (error) {
    task.status = 'failed'
    task.error = toErrorMessage(error)
  }
}

function retryTask(taskId) {
  const task = tasks.value.find(item => item.id === taskId)
  if (task) executeTask(task)
}

重试沿用原文章、类型、风格和比例,无需重新填写。目前整条链路重跑,后续可缓存已成功的视觉指令,仅重试生图阶段。

五、效果实测

5.1 上传Markdown

上传包含多个章节、操作步骤和技术名词的Markdown文章,程序正确读取一级标题、字符数、文件大小和内容块数量。

上传Markdown
图12 上传Markdown

界面分区清晰:顶部项目名和配置入口;中间左文档右视觉控制台;底部生图任务列表。文档区可在编辑和预览间切换。

5.2 AI智能策划全篇配图

点击“AI 智能策划全篇配图”后,GLM5.3通读文章,优先处理封面、核心流程、参数对比和操作重点,给出标题、理由及对应段落。

全文配图方案
图13 全文配图方案

确认方案后,并行创建所有任务,每项任务独立生成视觉指令并调用图像接口。

配图并行生成
图14 配图并行生成

任务卡片显示当前阶段和等待时间,图片完成后直接展示,并可展开查看视觉指令。

配图生成完成
图15 配图生成完成

此次生成的封面和正文插图均能对应文章主题与具体段落,未变成泛化的背景图。并行任务中个别失败不影响其他任务。

5.3 图片编辑

点击任务卡片中的“微调”或另行上传图片,用自然语言说明修改要求,无需重写整条生图提示词。

图片编辑窗口
图16 图片编辑窗口

例如要求将画面右侧的平板改成两台(安卓平板和iPad),同时保留标题、电脑主体、配色和整体构图。

图片编辑结果
图17 图片编辑结果

每次编辑生成新版本,原图保留,版本列表可来回切换比较。

5.4 配图回填与导出

图片完成后可逐张插入对应段落,或点击“一键插入到文章”统一处理。封面放在标题附近,正文插图根据任务中保存的段落定位;匹配不到则追加到文末。

插入并导出文章
图18 插入并导出文章

导出文件在原名称后加“配图版”,不覆盖原始Markdown。图片集中放入 images 子目录。

导出文章预览
图19 导出文章预览

重新打开导出的文章,封面和正文插图位置正确,原标题、段落和代码块未被改动。

六、总结与后续方向

本项目通过蓝耘MaaS接入GLM5.3作为文本模型,用于开发阶段(Codex协作)和运行阶段(将全文/段落转换为结构化图像指令),图像生成与编辑由Sense U1.5 Lite负责。两组接口独立,便于分别排查问题。

当前版本是可运行的MVP,后续计划:

  • 使用后端代理保护长期密钥;
  • 持久化生成记录、提示词对比和调用日志;
  • 利用调用记录比较不同文本模型在“长文理解→视觉指令”任务中的表现差异。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/baronbool/article/details/164212403

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--