Replace ImageEdit with ImageAgent for Qwen Image 2.0

Supports text-to-image, single-image edit and multi-image fusion (0-3
reference images) via a single tool. Renames imageEditModel config to
imageModel (default qwen-image-2.0) and adds imageWatermark toggle.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-22 15:47:08 +08:00
parent 98bb1066c4
commit 39b49bb302
4 changed files with 44 additions and 34 deletions

View File

@@ -91,8 +91,10 @@ reasoningModelExtraBody: ''
visualModelExtraBody: ''
# 百炼平台API KEY
dashScopeApiKey: ''
# 百炼平台图片编辑模型
imageEditModel: 'qwen-image-edit'
# 百炼平台图像模型(文生图 + 图像编辑)
imageModel: 'qwen-image-2.0'
# 是否在生成图片右下角添加 Qwen-Image 水印
imageWatermark: false
# 百炼平台TTS模型
ttsModel: 'qwen-tts'
# Jina API Key
@@ -280,7 +282,7 @@ JChatGPT 默认配置为使用阿里云百炼平台的通义千问系列模型
6. **GroupManageAgent** - 群管理功能(如禁言)
7. **SendSingleMessage/CompositeMessage** - 发送消息
8. **SendVoiceMessage** - 发送语音消息
9. **ImageEdit** - 图像编辑
9. **ImageAgent** - 图像生成与编辑(文生图、单图编辑、多图融合)
10. **WeatherService** - 天气查询
11. **SearchChatHistory** - 按关键词、发送者、时间范围搜索群聊消息历史(依赖 mirai-hibernate-plugin

View File

@@ -848,8 +848,8 @@ object JChatGPT : KotlinPlugin(
// 视觉代理
VisualAgent(),
// 图像编辑模型
ImageEdit(),
// 图像生成与编辑
ImageAgent(),
// 天气服务
WeatherService(),

View File

@@ -50,8 +50,11 @@ object PluginConfig : AutoSavePluginConfig("Config") {
@ValueDescription("百炼平台API KEY")
val dashScopeApiKey: String by value("")
@ValueDescription("百炼平台图片编辑模型")
val imageEditModel: String by value("qwen-image-edit")
@ValueDescription("百炼平台图像模型支持文生图与图像编辑。可选qwen-image-2.0 / qwen-image-2.0-pro / qwen-image-edit-max / qwen-image-edit-plus 等")
val imageModel: String by value("qwen-image-2.0")
@ValueDescription("是否在生成的图片右下角添加 Qwen-Image 水印")
val imageWatermark: Boolean by value(false)
@ValueDescription("百炼平台TTS模型")
val ttsModel: String by value("qwen-tts")

View File

@@ -22,29 +22,30 @@ import kotlinx.serialization.json.putJsonObject
import top.jie65535.mirai.JChatGPT
import top.jie65535.mirai.PluginConfig
class ImageEdit : BaseAgent(
class ImageAgent : BaseAgent(
tool = Tool.function(
name = "imageEdit",
description = "可通过调用图像编辑模型来修改图片。备注:该方法成本较高,非必要尽量不要调用。编辑图片前无需识别图片内容,图像编辑模型自己会理解图片内容!",
name = "imageAgent",
description = "调用千问图像模型生成或编辑图片。不传 image_urls 即纯文生图;" +
"传 1~3 张图片可进行编辑、修改或多图融合。" +
"备注:该方法成本较高,非必要尽量不要调用。" +
"编辑图片前无需识别图片内容,模型自己会理解图片内容。",
parameters = Parameters.buildJsonObject {
put("type", "object")
putJsonObject("properties") {
putJsonObject("image_url") {
put("type", "string")
put("description", "原始图片地址")
putJsonObject("image_urls") {
put("type", "array")
putJsonObject("items") {
put("type", "string")
}
put("description", "参考图片地址列表,可传 0~3 张。" +
"不传或为空即纯文生图;传 1 张为编辑;多张为融合,输出比例与最后一张对齐。")
}
putJsonObject("prompt") {
put("type", "string")
put("description", "正向提示词,用来描述需要对图片进行修改的要求")
put("description", "提示词,描述期望生成或修改的画面内容")
}
// putJsonObject("negative_prompt") {
// put("type", "string")
// put("description", "反向提示词,用来描述不希望在画面中看到的内容,可以对画面进行限制。" +
// "示例值:低分辨率、错误、最差质量、低质量、残缺、多余的手指、比例不良等。")
// }
}
putJsonArray("required") {
add("image_url")
add("prompt")
}
}
@@ -58,25 +59,29 @@ class ImageEdit : BaseAgent(
get() = PluginConfig.dashScopeApiKey.isNotEmpty()
override val loadingMessage: String
get() = "图中..."
get() = "图中..."
override suspend fun execute(args: JsonObject?): String {
requireNotNull(args)
val imageUrl = args.getValue("image_url").jsonPrimitive.content
val prompt = args.getValue("prompt").jsonPrimitive.content
// val negativePrompt = args["negative_prompt"]?.jsonPrimitive?.content
val imageUrls = args["image_urls"]?.jsonArray
?.map { it.jsonPrimitive.content }
?: emptyList()
val response = httpClient.post(API_URL) {
contentType(ContentType("application", "json"))
header("Authorization", "Bearer " + PluginConfig.dashScopeApiKey)
setBody(buildJsonObject {
put("model", PluginConfig.imageEditModel)
put("model", PluginConfig.imageModel)
putJsonObject("input") {
putJsonArray("messages") {
addJsonObject {
put("role", "user")
putJsonArray("content") {
addJsonObject {
put("image", imageUrl)
for (url in imageUrls) {
addJsonObject {
put("image", url)
}
}
addJsonObject {
put("text", prompt)
@@ -85,11 +90,11 @@ class ImageEdit : BaseAgent(
}
}
}
// if (negativePrompt != null) {
// putJsonObject("parameters") {
// put("negative_prompt", negativePrompt)
// }
// }
putJsonObject("parameters") {
put("n", 1)
put("prompt_extend", true)
put("watermark", PluginConfig.imageWatermark)
}
}.toString())
}
@@ -102,10 +107,10 @@ class ImageEdit : BaseAgent(
.getValue("message").jsonObject
.getValue("content").jsonArray[0].jsonObject
.getValue("image").jsonPrimitive.content
"图片已编辑完发送时请务必包含完整的url和查询参数因为下载地址存在鉴权![图片]($url)"
"图片已发送时请务必包含完整的url和查询参数因为下载地址存在鉴权![图片]($url)"
} catch (e: Throwable) {
JChatGPT.logger.error("图像编辑结果解析异常", e)
JChatGPT.logger.error("图像生成结果解析异常", e)
responseJson
}
}
}
}