aardio 文档
aardio 范例: Qwen-Image 文生图/魔搭
相关范例:Z-Image 文生图
//相关范例:Z-Image 文生图 https://www.aardio.com/zh-cn/docs/examples/AI/image/modelscope-z-image.html
import crypt;
import inet.http;//界面线程导入 inet.http 则 plus 控件可支持从网址加载图像
import win.ui.simpleWindow;
import fonts.fontAwesome;
import web.rest.jsonClient;
import win.ui;
/*DSG{{*/
var winform = win.form(text="魔搭 - 文生图";right=1150;bottom=700;bgcolor=0xF5F5F5;border="none")
winform.add(
bkplus={cls="bkplus";text="种子 (Seed):";left=745;top=285;right=900;bottom=305;align="left";anchors={top=1;right=1};color=0x666666;z=9};
btnCopy={cls="plus";text="复制图像 / 图像文件";left=921;top=631;right=1110;bottom=680;align="left";anchors={right=1;bottom=1};bgcolor=0x27AE60;border={radius=6};color=0xFFFFFF;disabled=1;font=LOGFONT(h=-14;weight=600);iconStyle={align="left";font=LOGFONT(h=-14;name='FontAwesome');padding={left=17;top=1}};iconText='\uF0EA';notify=1;textPadding={left=37};z=18};
btnGenerate={cls="plus";text="生成图像";left=742;top=631;right=902;bottom=680;align="left";anchors={right=1;bottom=1};bgcolor=0x3498DB;border={radius=6};color=0xFFFFFF;font=LOGFONT(h=-15;weight=600);iconStyle={align="left";font=LOGFONT(h=-16;name='FontAwesome');padding={left=17;top=1}};iconText='\uF1FC';notify=1;textPadding={left=37};z=17};
btnOpenKeyUrl={cls="plus";text="设置 API 接口";left=745;top=122;right=869;bottom=145;align="left";anchors={top=1;right=1};color=0x3498DB;iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome')};iconText='\uF08E';notify=1;textPadding={left=18};z=10};
chkRandomSeed={cls="plus";text="随机种子";left=745;top=346;right=848;bottom=371;align="left";anchors={top=1;right=1};color=0x3C3C3C;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-15;name='FontAwesome');padding={left=8}};iconText='\uF096';notify=1;textPadding={left=28};z=14};
comboQuality={cls="combobox";left=745;top=245;right=1105;bottom=270;anchors={top=1;right=1;bottom=1};edge=1;items={"auto","low","medium","high","xhigh","max"};mode="dropdownlist";z=12};
comboSize={cls="combobox";left=745;top=184;right=1105;bottom=209;anchors={top=1;right=1};edge=1;items={"1:1(2048x2048)","4:3(2400x1792)","3:4(1792x2400)","3:2(2528x1696)","2:3(1696x2528)","16:9(2752x1536)","9:16(1536x2752)"};mode="dropdownlist";z=11};
editPrompt={cls="edit";left=30;top=565;right=710;bottom=680;anchors={left=1;right=1;bottom=1};autohscroll=false;bgcolor=0xFFFFFF;edge=1;multiline=1;vscroll=1;z=16};
editSeed={cls="edit";text="42";left=745;top=309;right=1105;bottom=334;anchors={top=1;right=1};edge=1;multiline=1;z=13};
labelPrompt={cls="bkplus";text="提示词 (Prompt):";left=30;top=540;right=200;bottom=560;align="left";anchors={left=1;bottom=1};color=0x999999;font=LOGFONT(h=-13;weight=600);z=5};
labelQuality={cls="bkplus";text="质量 (Quality):";left=745;top=221;right=930;bottom=241;align="left";anchors={top=1;right=1};color=0x666666;z=7};
labelSize={cls="bkplus";text="尺寸 (Size):";left=745;top=160;right=930;bottom=180;align="left";anchors={top=1;right=1};color=0x666666;z=6};
labelTip={cls="plus";left=767;top=556;right=1069;bottom=607;anchors={right=1;bottom=1};border={color=0x008000;radius=16;width=1};hide=1;z=8};
picturebox={cls="plus";text="请在下方输入提示词生成图像";left=30;top=57;right=710;bottom=500;anchors={left=1;top=1;right=1;bottom=1};border={color=0xEEEEEE;radius=8;width=1};color=0x999999;font=LOGFONT(h=-16);iconStyle={font=LOGFONT(h=-60;name='FontAwesome')};iconText='\uF03E';notify=1;repeat="scale";textPadding={top=100};z=2};
progressBar={cls="plus";left=812;top=138;right=1023;bottom=349;anchors={top=1;right=1;bottom=1};bgcolor=0xECF0F1;border={radius=3};forecolor=0x3498DB;hide=1;z=15};
titleBar={cls="bkplus";left=0;top=0;right=1150;bottom=46;anchors={left=1;top=1;right=1};bgcolor=0x2C3E50;z=1};
titleIcon={cls="bkplus";text='\uF03E';left=15;top=6;right=55;bottom=42;anchors={left=1;top=1};color=0x3498DB;font=LOGFONT(h=-20;name='FontAwesome');z=4};
titleText={cls="bkplus";text="魔搭 Qwen Image 2.1 文生图";left=2;top=10;right=336;bottom=34;anchors={left=1;top=1};color=0xFFFFFF;font=LOGFONT(h=-16;weight=700);z=3}
)
/*}}*/
import fsys.table;
var configImage = fsys.table(io.appData("aardio/std/examples/AI/images/modelscope.table"),{
edit = "text";
comboSize = "2048x2048";
editPrompt = `A cinematic photo of a tiny astronaut riding a corgi on Mars, dramatic sunset, ultra detailed, 35mm lens.`;
selItem = 1;
itemData = [{
url="https://api-inference.modelscope.cn/v1";
key= "";
model="Qwen/Qwen-Image-2.1";
temperature=1;
}]
});
var aiChatConfig = configImage.itemData[[configImage.selItem]] : {} ;
winform.bindConfig( configImage,{
edit = "text";
combobox = "selText";
} );
winform.editPrompt.setPadding(5,5,5,5);
winform.progressBar.setPieRange(0,100);
winform.progressBar.orphanWindow(true);
var tempImageDir = io.tmpname();
io.createDir(tempImageDir);
winform.lastImagePath = null;
winform.lastImageExt = "png";
winform.showTip = function(str){
winform.labelTip.text = str;
winform.labelTip.show(true);
winform.setTimeout(
function(){
winform.labelTip.show(false);
},5000
);
}
winform.setBusy = function(busy){
if(busy){
winform.btnGenerate.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
winform.btnCopy.disabled = true;
}
else{
winform.btnGenerate.disabledText = null;
}
}
winform.btnGenerate.oncommand = function(){
var prompt = string.trim(winform.editPrompt.text);
if(!#prompt){
return winform.msgbox("请输入提示词。","提示","warn");
}
if(!aiChatConfig[["url"]]){
return winform.msgbox("请先配置 API 接口。",,"warn");
}
var size = winform.comboSize.selText || "(2048x2048)";
size = string.match(size,"\((.+)\)");
var quality = winform.comboQuality.selText || "auto";
var steps = ({
low = 15; // 快速预览
medium = 30; // 平衡模式
high = 40; // 官方标准推荐
xhigh = 45; // 复杂高质
max = 50; // 魔搭 API 允许的最大上限
auto = 30; // 默认对齐官方标准
})[quality] : 40; // 未指定或非法参数兜底为 40
if(winform.chkRandomSeed.checked){
winform.editSeed.text = ..math.random(99999)
}
var seed = winform.editSeed.text;
winform.picturebox.background = null;
winform.picturebox.foreground = null;
winform.picturebox.iconText = '\uF03E';
winform.picturebox.text = "正在连接魔搭图像模型...";
winform.text = "魔搭文生图 - 生成中";
winform.btnCopy.text = "复制图像 / 图像文件";
winform.btnCopy.iconText = '\uF0EA';
winform.lastImagePath = null;
winform.lastImageExt = outputFormat;
winform.setBusy(true);
thread.invoke(
function(winform, aiChatConfig, prompt, size, steps, seed ){
import web.rest.jsonClient;
var http = web.rest.jsonClient(,aiChatConfig.proxy);
import string.escape2;
http.setAuthToken(string.escape2(aiChatConfig.key));
http.setTimeouts(15000,300000,300000);
http.setHeaders({
"X-ModelScope-Async-Mode":"true",
"X-ModelScope-Task-Type":"image_generation"
});
//声明 HTTP API
var ai = http.api("https://api-inference.modelscope.cn/v1");
winform.picturebox.text = "正在生成图像,请稍候...";
//向服务器提交生成任务
var imageData, err = ai.images.generations(
model = "Qwen/Qwen-Image-2.1";
prompt = prompt;
size = size,
steps = steps;
seed = seed;
);
//获取任务 ID,直接下标 [[]] 操作符遇到 null 值返回 null 而不报错
var taskId = imageData[["task_id"]];
if(taskId){
winform.progressBar.show(true);
for(i=1;60){ // 最多尝试 60 次(5分钟)
winform.progressBar.progressPos = 40 + i;
thread.delay( 2000 + (3000/50 * steps) ); // 等待5秒
//查询任务执行结果
var result, err2 = ai.tasks[taskId].get();
err = err2;
var status = result[["task_status"]];
if(status == "SUCCEED"){
var url = result.output_images[1];
var imagePath = io.tmpname(time.format("%Y%m%d_%H%M%S") , inet.url.getFileName(url))
winform.picturebox.background = url;
winform.picturebox.text = null;
winform.picturebox.iconText = null;
winform.btnCopy.disabled = false;
winform.text = "魔搭文生图 - 生成成功";
winform.lastImagePath = imagePath;
winform.lastImageExt = ext;
if(revisedPrompt){
winform.showTip("已生成图像,双击图像可放大预览。魔搭 返回了优化后的提示词。");
}
else{
winform.showTip("已生成图像,双击图像可放大预览。");
}
//下载图像
http.receiveFile(imagePath).get(url);
winform.showTip("已生成图像,双击图像可放大预览。");
break
}
elseif(status == "FAILED"){
err = "FAILED"
}
if(err) break;
}
}
winform.progressBar.show(false);
winform.setBusy(false);
if(err) {
var msg = err || resultData[["error"]][["message"]] || resultData[["message"]] || rawText || "未知错误";
winform.picturebox.text = "生成失败";
winform.picturebox.iconText = '\uF057';
winform.msgboxErr(err,"魔搭 API 请求失败");
}
},winform,aiChatConfig,prompt, size, steps, seed
);
}
winform.btnCopy.oncommand = function(){
var imagePath = winform.lastImagePath;
if(!imagePath || !io.exists(imagePath)){
return winform.showTip("请先生成图像。");
}
if(winform.btnCopy.text == "打开图像文件"){
raw.explore(imagePath,"/select");
winform.showTip("已打开图像所在位置。");
winform.btnCopy.text = "复制图像 / 图像文件";
winform.btnCopy.iconText = '\uF0EA';
}
else{
import win.clip.bitmap;
win.clip.bitmap.writeHtml(imagePath);
import win.clip.file;
win.clip.file.write(imagePath,"copy",false);
winform.btnCopy.text = "打开图像文件";
winform.btnCopy.iconText = '\uF1C5';
winform.showTip("已复制图像与图像文件。");
}
}
winform.picturebox.onMouseDoubleClick = function(wParam,lParam){
var imagePath = winform.lastImagePath;
if(!imagePath || !io.exists(imagePath)){
return winform.msgboxErr("请先生成图像。","错误");
}
var frmPreview = win.form(text="图像预览";right=757;bottom=466;bgcolor=0xFFFFFF;border="none")
frmPreview.add(
btnClose={cls="close";text="×";left=725;top=3;right=753;bottom=31;bgcolor=0xCC8B94;anchors={top=1;right=1};font=LOGFONT(h=-21);notify=1;z=2};
picturebox={cls="plus";left=0;top=0;right=758;bottom=467;bgcolor=0xFFFFFF;anchors={left=1;top=1;right=1;bottom=1}foreRepeat="scale";notify=1;repeat="scale";z=1}
)
frmPreview.onActivateApp = function(activated){ if(!activated) frmPreview.close(); }
frmPreview.onCancel = function(){ frmPreview.close(); }
frmPreview.picturebox.onMouseDoubleClick = function(){ frmPreview.close(); }
frmPreview.picturebox.foreground = imagePath;
frmPreview.fullscreen();
frmPreview.btnClose.oncommand = function(){ frmPreview.close(); }
frmPreview.btnClose.show(true);
}
winform.btnOpenKeyUrl.oncommand = function(){
import web.rest.aiChat.settingForm;
table.assign(configImage,{
title = "GPT Image 2.5 - 接口设置"; // 标题
hyperlink1Title = "获取 key"; // key 输入框显示嵌入链接
allowKatex = false;
});
if(!configImage.itemData){
configImage.itemData = []
}
if(configImage.itemData[configImage.selItem]){
configImage.itemData[configImage.selItem].reasoning = {
effort = winform.comboQuality.selText;
}
configImage.save()
}
//打开 AI 设置窗口,参数 2 指定配置文件
var frmSetting = web.rest.aiChat.settingForm(mainForm,configImage);
if( frmSetting.doModal(mainForm) ){
aiChatConfig = configImage.itemData[configImage.selItem];
if(aiChatConfig){
effort = aiChatConfig.reasoning[["effort"]]
if((effort==="none")||(effort==="minimal")){
effort = "auto";
}
winform.comboQuality.selText = effort
}
}
}
winform.onDestroy = function(){
import fsys;
fsys.delete(tempImageDir);
}
winform.btnGenerate.skin({
background={
default=0xFF3498DB;
hover=0xFF2980B9;
active=0xFF1F618D;
disabled=0xFFBDC3C7;
};
color={
default=0xFFFFFFFF;
disabled=0xFF7F8C8D;
}
});
winform.btnCopy.skin({
background={
default=0xFF27AE60;
hover=0xFF229954;
active=0xFF1E8449;
disabled=0xFFBDC3C7;
};
color={
default=0xFFFFFFFF;
disabled=0xFF7F8C8D;
}
});
winform.btnOpenKeyUrl.skin({
color={
default=0xFF3498DB;
hover=0xFF2980B9;
active=0xFF1F618D;
}
});
winform.chkRandomSeed.skin({
color={
default=0xFF3C3C3C;
hover=0xFF0078D4;
active=0xFF005A9E;
disabled=0xFFAAAAAA;
};
checked={
iconText='\uF046'
}
});
winform.chkRandomSeed.checked = true;
win.ui.simpleWindow(winform);
winform.show();
win.loopMessage();
Markdown 格式