用 CRS 生成一张中文教学图
一张快速排序图,至少要把三件事画清楚:哪个数是基准,分区后哪些数在左边、哪些在右边,以及递归排序改变了什么。只给模型一句“画一张快速排序图”,这些决定就都交给了它。
下面这张图来自一次实际的 CRS 图像生成请求。输入数组、基准和分区结果先写进提示词,再让模型安排数字方块、颜色和箭头。

图中的分区行仍是未排序的两组;递归后才显示有序结果。点击图片查看原尺寸。
这是一张分治概念示意图:它省略了中间的递归层,也不对应某种原地快排实现的逐次交换。历史样例生成于 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 的图像工具。外层模型接收请求并调用工具,工具里的模型负责绘图。上面的配置和命令会形成这样的对应关系:
| 请求位置 | 本例的值 | 职责 |
|---|---|---|
外层 model | gpt-5.5 | 接收提示词,发起图像工具调用 |
tools 中的 model | gpt-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 参数。