Skip to content

hy-image-v3.5-preview 多轮对话 API 使用文档 ​

基于腾讯混元 Hy-Image-3.5-preview 模型的多轮对话式生图/编辑接口,通过 /v1/images/generations 端点以 Chat/Messages 协议提交单轮或多轮上下文,同步返回图片结果。第一轮提交文本指令与参考图后,响应中的 assembled_history(assistant + tool + assistant 三条已拼接好的回灌消息)随上下文保存为 JSON 文件;第二轮读取该文件,用上一轮生成的图片替换原始参考图,按「第一轮 messages + assembled_history + 本轮新 user 指令」拼接请求,实现多轮连续编辑。session 字段用于一致性哈希调度,同一会话落到同一推理实例以提升 KV-cache 命中率;输出最高支持 4096×4096(4K),返回的图片地址为有效期 12 小时的临时签名 URL。

🌐 请求地址 ​

text
https://www.dmxapi.cn/v1/images/generations

WARNING

请妥善保管您的 API Key!严禁将密钥泄露给他人、硬编码到代码中或提交到公开的代码仓库。如果怀疑密钥已泄露,请立即前往 DMXAPI 官网重新生成。

模型名称 ​

  • hy-image-v3.5-preview

多轮对话(第一轮)示例代码 ​

python
import base64
import json
import os
from datetime import datetime
from pathlib import Path

import requests

# ===============================================================
# 步骤1: 配置 API 连接信息
# ===============================================================

# DMXAPI 服务端点地址
url = "https://www.dmxapi.cn/v1/images/generations"

# DMXAPI 密钥 (请替换为您自己的密钥)
# 获取方式: 登录 DMXAPI 官网 -> 个人中心 -> API 密钥管理
api_key = "sk-***********************************************"

# ===============================================================
# 步骤2: 配置请求头
# ===============================================================

headers = {
    "Authorization": f"Bearer {api_key}",    # Bearer token 认证方式
    "Content-Type": "application/json",      # 指定请求体为 JSON 格式
}

# ===============================================================
# 步骤3: 配置请求参数
# ===============================================================

# 参考图来源,可以填写本地图片路径,也可以填写公网图片 URL
image_source = "https://cdn.jsdelivr.net/gh/opencv/opencv/samples/data/fruits.jpg"

payload = {
    # 【model】(string, 必填) 调用的模型名称
    # 取值: hy-image-v3.5-preview
    "model": "hy-image-v3.5-preview",

    # 【session】(string, 可选) 会话 ID
    # 用于推理服务一致性哈希调度:同 session 的多轮请求会落到同一推理实例,
    # 提升 KV-cache 命中率;多轮对话建议整条会话保持同一 session 值
    "session": "demo-session-001",

    # 【messages】(array[object], 必填) 多轮会话内容,时间从旧到新排列
    # 服务端会取数组中最后一个 role=user 的消息作为本轮生图指令,
    # 其余对象作为历史上下文一并透传(用于多轮编辑)
    "messages": [
        {
            # 【role】(string, 必填) 角色
            # 支持 user / assistant / tool;tool 角色仅在
            # 「把上一轮生图结果回灌作为下一轮上下文」时出现
            "role": "user",

            # 【content】(array[object], 可选) 该轮的具体内容
            "content": [
                {
                    # 【type】(string, 必填) 内容类型,text 或 image_url
                    "type": "text",

                    # 【text】(string, 可选) 当 type=text 时使用,表示具体文本
                    "text": "给图中的主体带上圣诞小帽,并将整体色调调整为圣诞色"
                },
                {
                    "type": "image_url",

                    # 【image_url】(object, 可选) 当 type=image_url 时使用
                    # 结构为 {"url": "..."},支持 http(s) 公网 URL 或
                    # data:image/...;base64,... 形态
                    # 单图大小 ≤ 20MB,图片总数量 ≤ 20 张
                    # (超过时服务端按轮次由远到近自动截断)
                    "image_url": {
                        "url": image_source
                    }
                }
            ]
        }
    ],

    # 【size】(string, 可选) 生成尺寸,格式 ${宽}x${高}
    # 宽、高均为正整数,取值范围 [256, 8192]
    # 宽 × 高(面积)不超过 16777216,即最高支持 4096x4096(4K)
    # 不传或传空串时,由模型基于 prompt 语义与 generate_max_pixels 自主决定尺寸
    "size": "1024x1024",

    # 【seed】(integer, 可选) 生成种子
    # int64 类型,取值范围 [0, 2^63-1];为 0 或不传时服务端随机分配,负值将被拒绝
    "seed": 0,

    # 【generate_max_pixels】(integer, 可选) 生成图片的目标面积(像素数)
    # 仅在未传 size 时生效,支持 3 个枚举档位:
    #   - 1048576: 1K(1024x1024)
    #   - 2359296: 1.5K(默认档位)
    #   - 4194304: 2K
    # 传入非枚举中间值时按最近面积归档;该参数最高档位为 2K
    # 注意:与 size 同时传入时以 size 为准;本示例已传 size,故此处注释掉
    # "generate_max_pixels": 4194304,

    # 【resize_max_pixels】(integer, 可选) 输入参考图面积上限(像素数)
    # 原图面积不超过阈值时原样透传;超过阈值时按比例等比缩放到接近阈值后再送入模型
    # 不传时默认 1048576(1024x1024)
    "resize_max_pixels": 1048576,

    # 【footnote】(string, 可选) 业务自定义水印内容
    # 最长 16 个字符(按 utf8.RuneCount 计算,不区分中英文),生成在图片右下角
    "footnote": "DMXAPI",

    # 【use_search_tool】(object, 可选) 外部搜索增强开关
    # 结构固定为 {"value": true} 或 {"value": false},当前默认关闭
    "use_search_tool": {
        "value": False
    }
}

# 本地图片路径的 Base64 转换逻辑(公网 URL 无需转换)

# 与 API 支持的格式保持一致:png / jpeg / jpg
IMAGE_MIME_TYPES = {
    ".jpg": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".png": "image/png",
}

MAX_IMAGE_SIZE = 20 * 1024 * 1024


def convert_image(source):
    # 公网 URL 直接传递
    if source.startswith(("http://", "https://")):
        return source

    # 本地文件不存在时抛出错误
    if not os.path.isfile(source):
        raise FileNotFoundError(f"图片不存在:{source}")

    # 检查图片格式
    extension = os.path.splitext(source)[1].lower()
    mime_type = IMAGE_MIME_TYPES.get(extension)

    if mime_type is None:
        raise ValueError(f"不支持的图片格式:{extension}")

    # 检查图片大小
    if os.path.getsize(source) > MAX_IMAGE_SIZE:
        raise ValueError("图片大小不能超过 20MB")

    # 读取本地图片并转换为 Base64 Data URL
    with open(source, "rb") as image_file:
        encoded_image = base64.b64encode(
            image_file.read()
        ).decode("ascii")

    return f"data:{mime_type};base64,{encoded_image}"


# 将参考图统一转换为可传输格式
payload["messages"][0]["content"][1]["image_url"]["url"] = (
    convert_image(
        payload["messages"][0]["content"][1]["image_url"]["url"]
    )
)

# ===============================================================
# 步骤4: 发送请求并输出结果
# ===============================================================

# 发送 POST 请求到 API 服务器
response = requests.post(
    url,
    headers=headers,
    json=payload,
    timeout=300
)

print("HTTP 状态码:", response.status_code)

try:
    result = response.json()
    print(json.dumps(result, indent=2, ensure_ascii=False))
except ValueError:
    result = {}
    print(response.text)

response.raise_for_status()

if result.get("error"):
    raise RuntimeError(
        json.dumps(result["error"], ensure_ascii=False)
    )

# 打印第一轮生成的图片地址(临时签名 URL,有效期 12 小时,请及时下载转存)
if result.get("data"):
    print("\n第一轮图片地址:")
    print(result["data"][0].get("url"))

# assembled_history:服务端拼好的「下一轮回灌消息序列」,
# 结构与请求体 messages 元素完全一致,典型为 3 条对象:
#   1. role=assistant(含 reasoning + tool_calls,描述本轮思考与工具调用)
#   2. role=tool(含工具产出图的中间 URL,tool_call_id 与第 1 条一致)
#   3. role=assistant(只含收尾文本,例如「你请求的图片已完成。」)
# 多轮编辑时直接把该数组原样追加到下一轮 messages 即可
assembled_history = result.get("assembled_history")

if not assembled_history:
    raise RuntimeError("响应中没有 assembled_history")

# 将第一轮上下文保存为 JSON 文件,供第二轮代码读取
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

context_path = Path(__file__).with_name(
    f"hunyuan_round1_{timestamp}.json"
)

with context_path.open("w", encoding="utf-8") as file:
    json.dump(
        {
            "model": payload["model"],
            "session": payload["session"],
            "messages": payload["messages"],
            "assembled_history": assembled_history,
            "latest_image_url": (
                result.get("data", [{}])[0].get("url")
            )
        },
        file,
        ensure_ascii=False,
        indent=2
    )

print(f"\n第一轮上下文已保存:{context_path}")

返回示例 ​

json
{
  "assembled_history": [
    {
      "role": "assistant",
      "content": [
        { "type": "text", "text": "这个任务需要图片生成,我将调用生成工具。" }
      ],
      "reasoning": "这张参考图展示了一组色彩鲜艳的水果,包括橙子、猕猴桃、柠檬和青柠,背景还有一些紫色的物品。...",
      "tool_calls": [
        {
          "id": "generate@call_0",
          "type": "function",
          "function": {
            "name": "generate",
            "arguments": "{\"source_image_indices_list\":\"[\\\"nrwh\\\"]\",\"recaption\":\"...\"}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "generate@call_0",
      "content": [
        {
          "type": "image_url",
          "image_url": {
            "url": "http://hunyuan-image-result-tob-1258344703.cos.ap-guangzhou.myqcloud.com/text2image2/strategy/upload/20261009/71b5ec1ec99afaf71dc9a7a3ba1d7d42_1791540400551614785_8259.png?..."
          }
        }
      ]
    },
    {
      "role": "assistant",
      "content": [
        { "type": "text", "text": "你请求的图片已完成。" }
      ]
    }
  ],
  "created": 1791540401,
  "data": [
    {
      "width": 1024,
      "height": 1024,
      "source": "generate",
      "tool_call_id": "generate@call_0",
      "url": "https://aigc-output-image-1326893053.cos.ap-guangzhou.myqcloud.com/1310445046/1310445046-WandImage-81c3ef0e2f114b3aa649b9730791038f_0.png?..."
    }
  ],
  "id": "1310445046-WandImage-81c3ef0e2f114b3aa649b9730791038f",
  "model": "HY-Image-3.5-Preview-4090-Tob-v1.2",
  "object": "image.chat.completion.chunk",
  "request_id": "2c88abfa-0325-4420-972c-892ebd8e2092",
  "round": 0,
  "tokenhub_usage": {
    "total_tokens": 15000
  }
}

多轮对话(第二轮)示例代码 ​

python
"""
╔═══════════════════════════════════════════════════════════════╗
║          hy-image-v3.5-preview 多轮对话(第二轮)              ║
╚═══════════════════════════════════════════════════════════════╝

📝 功能说明:
   本脚本演示如何读取第一轮保存的上下文 JSON,拼接多轮 messages
   并发起第二轮编辑请求

═══════════════════════════════════════════════════════════════
"""

import copy
import json
from datetime import datetime
from pathlib import Path

import requests

# ═══════════════════════════════════════════════════════════════
# 🔑 步骤1: 配置 API 连接信息
# ═══════════════════════════════════════════════════════════════

# 🌐 DMXAPI 服务端点地址
url = "https://www.dmxapi.cn/v1/images/generations"

# 🔐 DMXAPI 密钥 (请替换为您自己的密钥)
# 获取方式: 登录 DMXAPI 官网 -> 个人中心 -> API 密钥管理
api_key = "sk-***********************************************"

# ═══════════════════════════════════════════════════════════════
# 📋 步骤2: 配置请求头
# ═══════════════════════════════════════════════════════════════

headers = {
    "Authorization": f"Bearer {api_key}",    # Bearer token 认证方式
    "Content-Type": "application/json",      # 指定请求体为 JSON 格式
}

# ═══════════════════════════════════════════════════════════════
# 💬 步骤3: 读取第一轮上下文并拼接多轮请求参数
# ═══════════════════════════════════════════════════════════════

# 查找第一轮代码保存的上下文 JSON 文件(取最新的一份)
context_files = sorted(
    Path(__file__).parent.glob("hunyuan_round1_*.json")
)

if not context_files:
    raise FileNotFoundError(
        "没有找到第一轮上下文,请先运行第一段代码"
    )

context_path = context_files[-1]

with context_path.open("r", encoding="utf-8") as file:
    context = json.load(file)

print(f"正在读取:{context_path}")


def find_image_url(value):
    # 在嵌套结构中递归查找第一张图片的 URL
    if isinstance(value, dict):
        if value.get("type") == "image_url":
            image = value.get("image_url")

            if isinstance(image, dict):
                image = image.get("url")

            if isinstance(image, str):
                return image

        for item in value.values():
            result = find_image_url(item)

            if result:
                return result

    elif isinstance(value, list):
        for item in value:
            result = find_image_url(item)

            if result:
                return result

    return None


def convert_http_to_https(value):
    # 将历史消息中的 HTTP 地址递归转换为 HTTPS
    if isinstance(value, dict):
        for key, item in value.items():
            if (
                key == "url"
                and isinstance(item, str)
                and item.startswith("http://")
            ):
                value[key] = "https://" + item[7:]
            else:
                convert_http_to_https(item)

    elif isinstance(value, list):
        for item in value:
            convert_http_to_https(item)


original_messages = copy.deepcopy(context["messages"])
assembled_history = copy.deepcopy(
    context["assembled_history"]
)

# 优先使用第一轮生成的最终图片
current_image_url = context.get("latest_image_url")

if not current_image_url:
    current_image_url = find_image_url(assembled_history)

if not current_image_url:
    raise RuntimeError("没有找到上一轮生成的图片地址")

if current_image_url.startswith("http://"):
    current_image_url = "https://" + current_image_url[7:]

# 将历史消息中的 HTTP 地址转换为 HTTPS
convert_http_to_https(assembled_history)

# 用上一轮生成的图片替换原来的本地 Base64 图片
for message in original_messages:
    content = message.get("content", [])

    if not isinstance(content, list):
        continue

    for item in content:
        if item.get("type") != "image_url":
            continue

        image_url = item.get("image_url")

        if isinstance(image_url, dict):
            image_url["url"] = current_image_url
        else:
            item["image_url"] = {
                "url": current_image_url
            }

# 按官方格式拼接多轮 messages:
# 第 N+1 轮请求的 messages = 第 N 轮的 messages(含首条 user)
#   + 第 N 轮响应中的 assembled_history(assistant + tool + assistant 三条)
#   + 本轮新的 user 消息
messages = []

messages.extend(original_messages)
messages.extend(assembled_history)

messages.append({
    "role": "user",
    "content": [
        {
            "type": "text",
            "text": "将图里的主体的圣诞小帽换成牛仔帽,并将整体色调调整为西部牛仔风格",
        }
    ]
})

payload = {
    # 【model】(string, 必填) 调用的模型名称,与第一轮保持一致
    "model": context["model"],

    # 【session】(string, 可选) 会话 ID
    # 与第一轮保持同一 session 值,使多轮请求落到同一推理实例,
    # 提升 KV-cache 命中率
    "session": context["session"],

    # 【messages】(array[object], 必填) 多轮会话内容,时间从旧到新排列
    # 服务端会取数组中最后一个 role=user 的消息作为本轮生图指令,
    # 其余对象(含 assembled_history 回灌的历史)作为上下文一并透传
    "messages": messages
}

# ═══════════════════════════════════════════════════════════════
# 📤 步骤4: 发送请求并输出结果
# ═══════════════════════════════════════════════════════════════

# 发送 POST 请求到 API 服务器
response = requests.post(
    url,
    headers=headers,
    json=payload,
    timeout=300
)

print("HTTP 状态码:", response.status_code)

try:
    result = response.json()
    print(json.dumps(result, indent=2, ensure_ascii=False))
except ValueError:
    result = {}
    print(response.text)

response.raise_for_status()

if result.get("error"):
    raise RuntimeError(
        json.dumps(result["error"], ensure_ascii=False)
    )

if not result.get("data"):
    raise RuntimeError("响应中没有图片数据")

# 打印第二轮生成的图片地址(临时签名 URL,有效期 12 小时,请及时下载转存)
print("\n第二轮图片地址:")
print(result["data"][0].get("url"))

# 将第二轮上下文保存为 JSON 文件,可用于继续第三轮及后续编辑
if result.get("assembled_history"):
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

    output_path = Path(__file__).with_name(
        f"hunyuan_round2_{timestamp}.json"
    )

    with output_path.open("w", encoding="utf-8") as file:
        json.dump(
            {
                "model": payload["model"],
                "session": payload["session"],
                "messages": payload["messages"],
                "assembled_history": result["assembled_history"],
                "latest_image_url": result["data"][0].get("url")
            },
            file,
            ensure_ascii=False,
            indent=2
        )

    print(f"\n第二轮上下文已保存:{output_path}")

返回示例 ​

json
{
  "assembled_history": [
    {
      "role": "assistant",
      "content": [
        { "type": "text", "text": "这个任务需要生成图片,所以我正在调用生成工具。" }
      ],
      "reasoning": "用户本轮要求将上一轮生成的 img_ntth 中的圣诞小帽换成牛仔帽,并将整体色调调整为西部牛仔风格。...",
      "tool_calls": [
        {
          "id": "generate@call_0",
          "type": "function",
          "function": {
            "name": "generate",
            "arguments": "{\"source_image_indices_list\":\"[\\\"ntth\\\"]\",\"recaption\":\"...\"}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "generate@call_0",
      "content": [
        {
          "type": "image_url",
          "image_url": {
            "url": "http://hunyuan-image-result-tob-1258344703.cos.ap-guangzhou.myqcloud.com/text2image2/strategy/upload/20261009/f5d3ad520d4addcc01b994d16b40118a_1791540477629303614_2301.png?..."
          }
        }
      ]
    },
    {
      "role": "assistant",
      "content": [
        { "type": "text", "text": "你请求的图片已完成。" }
      ]
    }
  ],
  "created": 1791540478,
  "data": [
    {
      "width": 1568,
      "height": 1472,
      "source": "generate",
      "tool_call_id": "generate@call_0",
      "url": "https://aigc-output-image-1326893053.cos.ap-guangzhou.myqcloud.com/1310445046/1310445046-WandImage-5873bc84b0c74c2c91f4b02086245225_0.png?..."
    }
  ],
  "id": "1310445046-WandImage-5873bc84b0c74c2c91f4b02086245225",
  "model": "HY-Image-3.5-Preview-4090-Tob-v1.2",
  "object": "image.chat.completion.chunk",
  "request_id": "a9bbf473-da73-44a0-92d6-eb92b21e8cad",
  "round": 0,
  "tokenhub_usage": {
    "total_tokens": 15000
  }
}

© 2026 DMXAPI hy-image-v3.5-preview 多轮对话

一个 Key 用全球大模型