跳到主要内容

用 CRS 生成一张中文教学图

· 阅读需 8 分钟

一张快速排序图,至少要把三件事画清楚:哪个数是基准,分区后哪些数在左边、哪些在右边,以及递归排序改变了什么。只给模型一句“画一张快速排序图”,这些决定就都交给了它。

下面这张图来自一次实际的 CRS 图像生成请求。输入数组、基准和分区结果先写进提示词,再让模型安排数字方块、颜色和箭头。

快速排序教学图:以4为基准分区,再递归处理左右两组

图中的分区行仍是未排序的两组;递归后才显示有序结果。点击图片查看原尺寸。

这是一张分治概念示意图:它省略了中间的递归层,也不对应某种原地快排实现的逐次交换。历史样例生成于 2026-09-08,输出为 1536 × 1024 的 PNG。

接下来用同一个例子,走一遍从提示词到 PNG 的过程。你需要已有的 CRS 服务地址,以及一把允许调用对应模型的 CRS API Key;这里不涉及部署 CRS。

先写清楚要表达的内容​

这次选择数组末尾的 4 作为基准。分区后,小于它的数是 [3, 2, 1],大于它的数是 [6, 8, 5, 7]。这两组此时还没有排好序;递归处理之后,才分别变成 [1, 2, 3] 和 [5, 6, 7, 8]。

这些数值关系应该由作者给定。否则,一张排版整齐的图,也可能把“分区”和“排序”画成同一步。

下面是提示词中决定内容的部分,示例包里有包含版面要求的完整 prompt.txt:

输入数组:[6, 3, 8, 2, 5, 1, 7, 4]。
选择最后一个元素 4 作为基准。
分区为 [3, 2, 1]、[4]、[6, 8, 5, 7],这一步不要提前排序。
接着展示左右两组递归排序后的结果。
最终数组为 [1, 2, 3, 4, 5, 6, 7, 8]。
用蓝色表示左组、橙色表示基准、绿色表示右组,箭头对应处理顺序。

数字和处理顺序确定之后,再补“白底、中文大字、横向版面”等要求。配色的作用是让同一组数字在不同步骤里容易辨认,而不是给图片增加科技感。

用示例脚本生成图片​

下载示例包,解压后进入 crs-image-examples 目录。主路径使用其中的 generate_image.py:它读取 ChatEnv 配置,用 curl 发请求,再提取图片。这是独立示例脚本,不是 ChatImg 内置命令。

以下命令面向 macOS/Linux 的 Bash,需要 Python 3.10 或更高版本。已有合适的 Python 环境和 ChatEnv 时可以复用;否则先创建环境。示例使用 ChatEnv 0.2.11:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install "chatenv==0.2.11"
curl --version

保存地址、Key 和承载模型​

创建名为 crs 的配置,不切换全局默认配置。已有同名配置时跳过这一步:

chatenv new -t oai crs

打开 ~/.chatarch/envs/OpenAI/crs.env,填写这三个字段。若设置了 CHATARCH_HOME,对应文件位于该目录的 envs/OpenAI/crs.env:

OPENAI_API_BASE=https://crs.example.com/openai/v1
OPENAI_API_KEY=<YOUR_CRS_API_KEY>
OPENAI_API_MODEL=gpt-5.5

把示例域名和占位 Key 换成自己的值。OPENAI_API_BASE 填到 /openai/v1,脚本会拼接 /responses。这里使用的承载模型是历史样例中的 gpt-5.5;你的服务必须向这把 Key 开放所选模型。

图片模型、尺寸和质量由下一条命令指定,不需要再往这个配置里添加图片模型字段。

发送请求​

在包含 generate_image.py 和 prompt.txt 的目录执行:

python generate_image.py \
--profile crs \
--image-model gpt-image-2 \
--size 1536x1024 \
--quality medium \
--prompt-file prompt.txt \
--output quicksort.png

这条命令会真正调用服务并消耗相应额度。gpt-image-2 同样需要在该服务上可用;不要仅凭模型名称猜测权限。

成功后,目录里会有三份文件:

文件用来做什么
quicksort.png打开、检查和使用的图片
quicksort.request.json本次提交的模型、提示词和图像参数,不含认证 Key
quicksort.sse服务返回的事件流,保留完整图像结果,便于排查或重新解码

脚本还会打印格式、尺寸和 SHA-256。如果输出文件名已经存在,它会停止;下一次生成请换一个名字,避免覆盖旧图和对应记录。

请求里为什么有两个模型​

这条调用走的是 Responses API 的图像工具。外层模型接收请求并调用工具,工具里的模型负责绘图。上面的配置和命令会形成这样的对应关系:

请求位置本例的值职责
外层 modelgpt-5.5接收提示词,发起图像工具调用
tools 中的 modelgpt-image-2按要求生成图片

因此,想换绘图模型,应修改 --image-model;想换承载模型,应修改配置中的 OPENAI_API_MODEL,或显式传入 --host-model。两者不是同一个参数的两种写法。

tool_choice 指定 image_generation,stream: true 要求流式返回。你可以打开生成的 quicksort.request.json 看完整请求;Key 通过认证头发送,不在这个文件里。

为什么不能把响应直接另存为 PNG​

这个接口返回的是 SSE 事件流,不是图片文件。图片的完整 Base64 数据位于 image_generation_call 输出项的 result 字段,可能出现在两个位置:

  • response.output_item.done 事件中的 item.result;
  • response.completed 事件中的 response.output[].result。

示例脚本同时处理这两个位置,并等待整条请求以 completed 状态结束。只有预览图片、流中断,或者图片输出后又出现失败事件,都不会被当成成功结果保存。

如果生成已经成功,只是需要重新提取文件,可以直接使用保存的响应:

python generate_image.py \
--decode quicksort.sse \
--output quicksort-copy.png

这条命令只读本地文件,不会再次请求模型。若它仍报“没有完整结果”,应先检查原响应是否真的完成,而不是把一个不完整的预览当成最终图片。

图片生成成功,还要检查内容​

对于开头这张图,检查重点不是“像不像教材”,而是每一行有没有表达正确:

  • 输入数组是否仍是 [6, 3, 8, 2, 5, 1, 7, 4],基准是否标在 4 上。
  • 分区行是否保留 [3, 2, 1] 与 [6, 8, 5, 7],没有提前排成有序数组。
  • 箭头是否从两组指向各自的递归结果,最终数组是否完整、没有漏数或重复。
  • 缩放到实际课件或文章宽度后,数字、中文和箭头是否仍能读清。

这张图能说明“选基准、分区、递归处理”的关系,却不能替代某个快排实现的执行轨迹。如果要讲指针移动和交换过程,需要先列出那段代码的实际步骤,再据此设计另一张图。

换成别的教学主题时,也从这些可检查的内容开始:要画哪些对象,它们有什么关系,哪些步骤不能省略。再把描述写进 prompt.txt,用新的输出文件名生成。

补充:不用 ChatEnv,直接使用 curl​

如果不使用 ChatEnv,示例包也提供了 request.json 和 curl_image_tool.sh。它们调用同一个接口,需要 curl、jq 和 Base64 解码工具。

在 Bash 中读入 Key,再运行脚本:

export CRS_API_BASE='https://crs.example.com/openai/v1'
read -r -s -p 'CRS API Key: ' CRS_API_KEY
printf '\n'
export CRS_API_KEY
bash curl_image_tool.sh request.json quicksort-curl.png

这也是一次新的生成请求,不是前面 Python 路径的下一步。修改图像内容时,编辑 request.json 中的 input_text;两条路径选一条即可。认证头通过标准输入交给 curl,Key 不写入请求 JSON 或 curl 参数。

示例与源码​

编辑判断