本文为您介绍如何使用EAS部署SD API服务,以及如何使用API进行模型推理。
背景信息
部署SD API服务与WebUI应用采用相同的基础镜像支撑,您可以参考5分钟使用EAS一键部署Stable Diffusion AIGC绘画了解部署细节。
SD API服务支持同步和异步两种部署模式(部署同步服务、部署异步服务),您可以分别发送同步和异步接口请求(调用同步服务、调用异步服务),并根据请求结果验证模型效果。发送同步接口请求时,客户端会同步等待结果返回。发送异步接口请求时,客户端不再同步等待结果,通过订阅的方式在请求计算完成后等待服务端的结果推送。您可以根据具体的使用场景来选择部署和调用模式。
此外,EAS基于原生SDWebUI接口增加了一些新特性。在API接口中除了必填参数外,还可以添加一些可选参数,以实现更加丰富的功能或定制化需求,详情请参见API额外支持的参数。
前提条件
-
已开通PAI(EAS)后付费,并创建默认工作空间。具体操作,请参见开通PAI并创建默认工作空间。
-
已创建通用型NAS文件系统,用来存放模型文件。具体操作,请参见创建文件系统。
-
已创建OSS Bucket存储空间,用来存放生成的图片。具体操作,请参见控制台创建存储空间。
部署同步服务
支持以下两种部署方式,您可以根据使用场景选择合适的部署方式。初次部署时,推荐使用方式一。
部署方式一:控制台一键部署
-
进入PAI-EAS 模型在线服务页面。
-
登录PAI控制台。
-
在左侧导航栏单击工作空间列表,在工作空间列表页面中单击待操作的工作空间名称,进入对应工作空间内。
-
在工作空间页面的左侧导航栏选择模型部署>模型在线服务(EAS),进入PAI-EAS 模型在线服务页面。
-
-
在PAI-EAS 模型在线服务页面,单击部署服务。
-
在部署服务页面,配置以下关键参数。
参数
描述
服务名称
自定义服务名称。本案例使用的示例值为:sdapi_demo。
部署方式
选择镜像部署服务。
镜像选择
在PAI平台镜像列表中选择stable-diffusion-webui;镜像版本选择3.2。
说明
由于版本迭代迅速,部署时镜像版本选择最高版本即可。
模型配置
单击填写模型配置,进行模型配置。
-
建议同时配置OSS挂载和NAS挂载。其中OSS路径用来存放生成的图片,NAS路径用来存放模型。
-
您也可以单独使用OSS挂载或NAS挂载。
-
当选择NAS挂载时,切换模型和出图速度更快。
-
当选择OSS挂载时,OSS上传文件更方便,但是切换模型和出图速度比NAS慢很多。
-
同时配置OSS挂载和NAS挂载时,配置方法如下:
-
OSS挂载
-
将OSS路径配置为已创建的OSS Bucket路径。
-
挂载路径配置为:
/code/stable-diffusion-webui/data-oss
。
-
-
NAS挂载
-
NAS挂载点:选择已创建的NAS文件系统和挂载点。
-
NAS源路径:配置为
/
。 -
挂载路径:配置为
/code/stable-diffusion-webui/data-nas
。
-
运行命令
将运行命令更新为以下配置:
./webui.sh --listen --port=8000 --skip-version-check --no-hashing --no-download-sd-model --skip-install --api --filebrowser --data-dir data-nas
。端口号:配置为8000。
资源组种类
选择公共资源组。
资源配置方法
选择常规资源配置。
资源配置选择
选择GPU类型,实例规格推荐使用ml.gu7i.c16m60.1-gu30(性价比最高)。
专有网络配置
系统会自动匹配与NAS所在VPC相连通的专有网络,无需进行额外的修改。
-
-
单击部署,等待一段时间即可完成模型部署。
当模型状态为运行中时,服务部署成功。
部署方式二:JSON独立部署
-
按照部署方式一的操作步骤,打开部署服务页面。
-
在对应配置编辑区域单击JSON独立部署,然后在编辑框中配置以下内容。
{ "metadata": { "instance": 1, "name": "sd_v32", }, "containers": [ { "image": "eas-registry-vpc..cr.aliyuncs.com/pai-eas/stable-diffusion-webui:3.2", "script": "./webui.sh --listen --port=8000 --skip-version-check --no-hashing --no-download-sd-model --skip-install --api --filebrowser --data-dir data-nas", "port": 8000 } ], "cloud": { "computing": { "instance_type": "ml.gu7i.c16m60.1-gu30", "instances": null }, "networking": { "vpc_id": "vpc-t4nmd6nebhlwwexk2****", "vswitch_id": "vsw-t4nfue2s10q2i0ae3****", "security_group_id": "sg-t4n85ksesuiq3wez****" } }, "storage": [ { "oss": { "path": "oss://examplebucket/data-oss", "readOnly": false }, "properties": { "resource_type": "model" }, "mount_path": "/code/stable-diffusion-webui/data-oss" }, { "nfs": { "path": "/", "server": "726434****-aws0.ap-southeast-1.nas.aliyuncs.com" }, "properties": { "resource_type": "model" }, "mount_path": "/code/stable-diffusion-webui/data-nas" } ] }
其中:
-
metadata.name:自定义模型服务名称。
-
containers.image:其中需要替换为当前地域ID。关于如何查询地域ID,请参见地域和可用区。
-
cloud.networking:配置专有网络,包括vpc_id(专有网络ID)、vswitch_id(交换机ID)和security_group_id(安全组ID),且配置的专有网络需要与通用型NAS文件系统一致。
-
storage.oss.path:配置为已创建的OSS Bucket路径。
-
storage.nfs.server:配置为已创建的NAS文件系统。
-
-
单击部署,等待一段时间即可完成模型部署。
当模型状态为运行中时,服务部署成功。
调用同步服务
同步服务部署成功后,您可以参照以下操作步骤发送同步接口请求。
-
查询调用信息。
服务部署成功后,单击服务方式列下的调用信息,在调用信息对话框中的公网地址调用页签查询服务访问地址和Token。
-
使用以下几种方式发送同步接口请求。
使用curl命令发送服务请求
示例如下:
curl --location --request POST '/sdapi/v1/txt2img' \ --header 'Authorization: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "prompt":"cut dog ", "steps":20 }'
其中:
-
:替换为步骤1中查询到的服务访问地址。
-
:替换为步骤1中查询到的服务Token。
命令执行成功后,系统会返回图片的Base64位编码。
使用Python发送服务请求
参考API发送服务请求。
-
示例1:使用如下Python代码发送服务请求,返回图片文件。
import requests import io import base64 from PIL import Image, PngImagePlugin url = "" payload = { "prompt": "puppy dog", "steps": 20, "n_iter": 2 } session = requests.session() session.headers.update({"Authorization": ""}) response = session.post(url=f'{url}/sdapi/v1/txt2img', json=payload) if response.status_code != 200: raise Exception(response.content) data = response.json() # 同步接口可直接返回图片的base64,但推荐使用返回图片地址。 for idx, im in enumerate(data['images']): image = Image.open(io.BytesIO(base64.b64decode(im.split(",", 1)[0]))) png_payload = { "image": "data:image/png;base64," + im } resp = session.post(url=f'{url}/sdapi/v1/png-info', json=png_payload) pnginfo = PngImagePlugin.PngInfo() pnginfo.add_text("parameters", resp.json().get("info")) image.save(f'output-{idx}.png', pnginfo=pnginfo)
其中:
-
:替换为步骤1中查询到的服务访问地址。
-
:替换为步骤1中查询到的服务Token。
代码执行成功后,系统会在当前所在目录返回图片文件。
-
-
示例二:使用如下Python代码发送服务请求,返回图片地址。
import requests import oss2 url = "" # 对应部署EAS服务时,storage挂载OSS文件夹对应的mount_path。 mount_path = "/code/stable-diffusion-webui/data-oss" # 对应部署EAS服务时,storage中选择的OSS地址。 oss_url = "oss://examplebucket/data-oss" # 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 auth = oss2.Auth('', '') # Endpoint以杭州为例,其它Region请按实际情况填写。 bucket = oss2.Bucket(auth, '', '') payload = { "alwayson_scripts": { "sd_model_checkpoint": "deliberate_v2.safetensors", "save_dir": "/code/stable-diffusion-webui/data-oss/outputs" }, "steps": 30, "prompt": "girls", "batch_size": 1, "n_iter": 2, "width": 576, "height": 576, "negative_prompt": "ugly, out of frame" } session = requests.session() session.headers.update({"Authorization": ""}) response = session.post(url=f'{url}/sdapi/v1/txt2img', json=payload) if response.status_code != 200: raise Exception(response.content) data = response.json() for idx, path in enumerate(data['parameters']['image_url'].split(',')): url = path.replace(mount_path, oss_url) print(idx, path, url) # 下载OSS文件到本地文件。 bucket.get_object_to_file(url[len("oss:///"):], f'output-{idx}.png')
其中:
-
:替换为步骤1中查询到的服务访问地址。
-
:替换为步骤1中查询到的服务Token。
-
auth:将和替换为阿里云账户的AccessKey ID和AccessKey Secret。
-
:表示OSS对外服务的访问域名,例如华东1(杭州)配置为
http://oss-cn-hangzhou.aliyuncs.com
。更多详细内容,请参见访问域名和数据中心。 -
:替换为已创建的OSS Bucket名称。
代码执行成功后,系统返回如下结果。您可以前往OSS控制台,在部署服务时配置的OSS路径中查看已生成的图片。
0 /code/stable-diffusion-webui/data-oss/outputs/txt2img-grids/2023-08-03/grid-b2565642-8ec0-4250-aa9e-f8402e7b87f7.png oss://examplebucket/aohai-singapore/outputs/txt2img-grids/2023-08-03/grid-b2565642-8ec0-4250-aa9e-f8402e7b87f7.png 1 /code/stable-diffusion-webui/data-oss/outputs/txt2img-images/2023-08-03/dc380f1f-efa0-4681-9b1a-298e2513b929-4084873146.png oss://examplebucket/aohai-singapore/outputs/txt2img-images/2023-08-03/dc380f1f-efa0-4681-9b1a-298e2513b929-4084873146.png 2 /code/stable-diffusion-webui/data-oss/outputs/txt2img-images/2023-08-03/3df9fd96-7c5a-487a-8e43-24f87c042806-4084873147.png oss://examplebucket/aohai-singapore/outputs/txt2img-images/2023-08-03/3df9fd96-7c5a-487a-8e43-24f87c042806-4084873147.png
-
此外,您还可以在请求数据中使用Lora和Controlnet数据格式,以实现特定的功能。
请求数据中使用Lora模型配置
发送服务请求时,您可以直接在请求体上加入
来增加Lora。更多详细内容,请参见Lora。
请求体配置示例如下:
{ "prompt":"girls ", "steps":20, "save_images":true }
请求数据中使用Controlnet数据格式
API请求数据中使用Controlnet数据格式可以方便地对图像进行一些常见的变换操作,比如使图像保持水平或垂直等。具体配置方法,请参见txt2img使用controlnet的数据格式。
-
此外,EAS基于原生SDWebUI接口支持了一些新特性,您可以在请求数据中添加一些可选参数用于实现更加丰富的功能或定制化需求。具体操作,请参见API额外支持的参数。
部署异步服务
为了解决大量请求导致的排队等待问题,EAS内置了队列服务可以协助您管理大量请求。您可以使用异步调用方式推送请求,并订阅相关结果,以获得更高效的请求处理体验。部署异步服务的具体操作步骤如下:
-
进入部署服务页面,具体操作,请参见部署同步服务。
-
在对应配置编辑区域单击JSON独立部署,然后在编辑框中配置以下内容。更多关于队列服务的配置详情,请参见异步推理与队列服务。
{ "metadata": { "name": "sd_async", "instance": 1, "rpc.work_threads": 1, "type": "Async" }, "cloud": { "computing": { "instance_type": "ml.gu7i.c16m60.1-gu30", "instances": null }, "networking": { "vpc_id": "vpc-bp1t2wukzskw9139n****", "vswitch_id": "vsw-bp12utkudylvp4c70****", "security_group_id": "sg-bp11nqxfd0iq6v5g****" } }, "queue": { "cpu": 1, "max_delivery": 1, "memory": 4000, "resource": "" }, "storage": [ { "oss": { "path": "oss://examplebucket/aohai-singapore/", "readOnly": false }, "properties": { "resource_type": "model" }, "mount_path": "/code/stable-diffusion-webui/data-oss" }, { "nfs": { "path": "/", "server": "0c9624****-fgh60.cn-hangzhou.nas.aliyuncs.com" }, "properties": { "resource_type": "model" }, "mount_path": "/code/stable-diffusion-webui/data-nas" } ], "containers": [ { "image": "eas-registry-vpc.cn-hangzhou.cr.aliyuncs.com/pai-eas/stable-diffusion-webui:3.2", "script": "./webui.sh --listen --port 8000 --skip-version-check --no-hashing --no-download-sd-model --skip-install --api --nowebui --time-log", "port": 8000 } ] }
相较于同步服务的部署,以下是异步服务的配置变更。更多关于关键参数的配置详情,请参见部署方式二:JSON独立部署。
-
删除以下参数:
-
metadata.enable_webservice
-
删除containers.script中配置的–filebrowser,加快服务启动速度。
-
-
新增以下参数:
-
metadata.type:配置为Async。
-
metadata.rpc.work_threads:配置为1,单个实例只允许并发处理一个请求。
-
queue.max_delivery:配置为1,消息处理错误后不允许重试。
-
containers.script配置中新增–nowebui(加快启动速度)和–time-log(记录接口响应时间)。
-
-
-
单击部署,等待一段时间即可完成模型部署。
调用异步服务
异步服务部署成功后,您可以根据实际需求选择发送同步接口请求或异步接口请求。关于发送同步接口请求和异步接口请求的更多内容,请参见异步推理与队列服务。
发送异步接口请求并订阅结果
-
查询调用信息。
服务部署成功后,单击服务方式列下的调用信息,在调用信息对话框中的异步调用页签,在公网输入请求地址页签查询服务访问地址和Token。
-
异步推送请求。
说明
-
异步队列对输入请求和输出结果的大小都有限制,通常不建议超过8 KB。因此,在发送请求时,需要满足以下两个条件:
-
如果请求数据中包含图片,建议使用URL来传递图片信息。SDWebUI内部会自动下载并解析这些图片数据。
-
为了确保返回结果中没有原始图片数据,建议您使用save_dir来指定生成图片的保存路径。具体操作,请参见API额外支持的参数。
-
-
默认情况下,EAS无法连接互联网。如果您使用image_link参数配置的图片链接是互联网图片地址,为了能够正常访问这些图片,您需要参考配置网络连通和公网连接及白名单配置进行公网链接配置。
使用Python SDK
示例代码如下:
import requests url = "" session = requests.session() session.headers.update({"Authorization": ""}) prompts = ["cute dog", "cute cat", "cute girl"] for i in range(5): p = prompts[i % len(prompts)] payload = { "prompt": p, "steps": 20, "alwayson_scripts": { "save_dir": "/code/stable-diffusion-webui/data-oss/outputs/txt2img" }, } response = session.post(url=f'{url}/sdapi/v1/txt2img?task_id=txt2img_{i}', json=payload) if response.status_code != 200: exit(f"send request error:{response.content}") else: print(f"send {p} success, index is {response.content}") for i in range(5): p = prompts[i % len(prompts)] payload = { "prompt": p, "steps": 20, "alwayson_scripts": { "save_dir": "/code/stable-diffusion-webui/data-oss/outputs/img2img", "image_link": "https://eas-cache-cn-hangzhou.oss-cn-hangzhou-internal.aliyuncs.com/stable-diffusion-cache/tests/boy.png", }, } response = session.post(url=f'{url}/sdapi/v1/img2img?task_id=img2img_{i}', json=payload) if response.status_code != 200: exit(f"send request error:{response.content}") else: print(f"send {p} success, index is {response.content}")
其中:
-
:替换为步骤1中查询到的服务访问地址。
-
:替换为步骤1中查询到的服务Token。
说明
-
可以支持WebUI服务的所有POST接口,按照需求请求对应路径。
-
如果您需要在该服务中透传业务属性,可以使用url参数的方式指定属性标签。例如,您可以在response的url参数中添加参数
?task_id=task_abc
来指定标签为task_id,并且该信息会在服务的输出结果中的tags字段中体现。
代码执行成功后,系统输出如下结果。您的结果以实际为准。
使用Java SDK
示例代码如下。使用Java编写客户端代码时,需要使用Maven管理项目。因此,您必须在pom.xml文件中添加客户端所需的依赖包。具体操作,请参见Java SDK使用说明。
import com.aliyun.openservices.eas.predict.http.HttpConfig; import com.aliyun.openservices.eas.predict.http.QueueClient; import com.aliyun.openservices.eas.predict.queue_client.QueueUser; import org.apache.commons.lang3.tuple.Pair; import java.util.HashMap; public class SDWebuiAsyncPutTest { public static void main(String[] args) throws Exception { // 创建队列服务客户端。 String queueEndpoint = "http://166233998075****.cn-hangzhou.pai-eas.aliyuncs.com"; String queueToken = "xxxxx=="; // 输入队列为服务名+自定义请求path。 String inputQueueName = "/sdapi/v1/txt2img"; // 输入队列,往输入队列添加数据,推理服务会自动从输入队列中读取请求数据。 QueueClient inputQueue = new QueueClient(queueEndpoint, inputQueueName, queueToken, new HttpConfig(), new QueueUser()); // 清除队列数据!!! 请谨慎使用。 // input_queue.clear(); // 往输入队列添加数据。 int count = 5; for (int i = 0; i < count; ++i) { // 请求数据。 String data = "{ " + " \"prompt\": \"cute dog\", " + " \"steps\":20, " + " \"alwayson_scripts\":{ " + " \"save_dir\":\"/code/stable-diffusion-webui/data-oss/outputs/txt2img\" " + " } " + " }"; // 自定义tag。 HashMap map = new HashMap(1); map.put("task_id", "txt2img_" + i); Pair entry = inputQueue.put(data.getBytes(), map); System.out.println(String.format("send success, index is %d, request_id is %s", entry.getKey(), entry.getValue())); // 队列服务支持多优先级队列,可通过put函数设置数据优先级,默认优先级为0, 高优先数据可设置优先级为1。 // inputQueue.put(data.getBytes(), 0L, null); } // 关闭客户端。 inputQueue.shutdown(); inputQueueName = "/sdapi/v1/img2img"; inputQueue = new QueueClient(queueEndpoint, inputQueueName, queueToken, new HttpConfig(), new QueueUser()); for (int i = 0; i < count; ++i) { // 请求数据。 String data = "{ " + " \"prompt\": \"cute dog\", " + " \"steps\":20, " + " \"alwayson_scripts\":{ " + " \"save_dir\":\"/code/stable-diffusion-webui/data-oss/outputs/img2img\", " + " \"image_link\":\"https://eas-cache-cn-hangzhou.oss-cn-hangzhou-internal.aliyuncs.com/stable-diffusion-cache/tests/boy.png\" " + " } " + " }"; HashMap map = new HashMap(1); map.put("task_id", "img2img_" + i); Pair entry = inputQueue.put(data.getBytes(), map); System.out.println(String.format("send success, index is %d, requestId is %s", entry.getKey(), entry.getValue())); } // 关闭客户端。 inputQueue.shutdown(); } }
其中:
-
queueEndpoint:配置为步骤1中获取的服务访问地址。请参考示例代码进行相应的配置。
-
queueToken:配置为步骤1中获取的服务Token信息。
-
:替换为已部署的异步服务名称。
说明
如果您需要在服务中透传业务属性,可以在put函数中设置tag参数。在示例中,您可以参考自定义tag的用法。这些信息会在输出结果的tags属性中体现。
代码执行成功后,系统输出如下结果。您的结果以实际为准。
send success, index is 21, request_id is 05ca7786-c24e-4645-8538-83d235e791fe send success, index is 22, request_id is 639b257a-7902-448d-afd5-f2641ab77025 send success, index is 23, request_id is d6b2e127-eba3-4414-8e6c-c3690e0a487c send success, index is 24, request_id is 8becf191-962d-4177-8a11-7e4a450e36a7 send success, index is 25, request_id is 862b2d8e-5499-4476-b3a5-943d18614fc5 send success, index is 26, requestId is 9774a4ff-f4c8-40b7-ba43-0b1c1d3241b0 send success, index is 27, requestId is fa536d7a-7799-43f1-947f-71973bf7b221 send success, index is 28, requestId is e69bdd32-5c7b-4c8f-ba3e-e69d2054bf65 send success, index is 29, requestId is c138bd8f-be45-4a47-a330-745fd1569534 send success, index is 30, requestId is c583d4f8-8558-4c8d-95f7-9c3981494007 Process finished with exit code 0
-
-
异步订阅结果。
使用Python SDK
示例代码如下:
import json import oss2 from eas_prediction import QueueClient sink_queue = QueueClient('139699392458****.cn-hangzhou.pai-eas.aliyuncs.com', 'sd_async/sink') sink_queue.set_token('') sink_queue.init() mount_path = "/code/stable-diffusion-webui/data-oss" oss_url = "oss:///aohai-singapore" # 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 auth = oss2.Auth('', '') # Endpoint以杭州为例,其它Region请按实际情况填写。 bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '') watcher = sink_queue.watch(0, 5, auto_commit=False) for x in watcher.run(): if 'task_id' in x.tags: print('index {} task_id is {}'.format(x.index, x.tags['task_id'])) print(f'index {x.index} data is {x.data}') sink_queue.commit(x.index) try: data = json.loads(x.data.decode('utf-8')) for idx, path in enumerate(data['parameters']['image_url'].split(',')): url = path.replace(mount_path, oss_url) # 下载OSS文件到本地文件。 bucket.get_object_to_file(url[len("oss:///"):], f'{x.index}-output-{idx}.png') print(f'save {url} to {x.index}-output-{idx}.png') except Exception as e: print(f'index {x.index} process data error {e}')
其中:
-
sink_queue:您需要更新该参数配置的服务访问地址和名称。如何查询服务访问地址,请参见查询调用信息。请参考示例代码进行相应的配置。
-
:配置为步骤1中获取的服务Token信息。
-
oss_url:替换为部署服务时配置的OSS路径。
-
:替换为已创建的OSS Bucket名称。
-
bucket:本方案以杭州地域为例配置了Endpoint,如果您在其他地域部署的服务,需要根据实际情况进行配置。更多详细内容,请参见访问域名和数据中心。
说明
-
需要主动进行commit操作,也可以设置
auto_commit=True
来自动进行commit操作。 -
如果consumer不再消费数据,需要及时关闭以释放资源。
-
您也可以使用curl命令或者调用同步接口来获取订阅接口,详情请参见异步推理与队列服务。
代码执行成功后,系统输出如下结果。您的结果以实际为准。您可以前往OSS控制台,在部署服务时配置的OSS路径中查看已生成的图片。
index 1 task_id is txt2img_0 index 1 data is b'{"images":[],"parameters":{"id_task":null,"status":0,"image_url":"/code/stable-diffusion-webui/data-oss/outputs/txt2img/txt2img-images/2023-08-16/ad2e270b-dfcc-4ec3-8718-f19824857834-919429454.png","seed":"919429454","error_msg":"","total_time":88.55384421348572},"info":""}' save oss:///aohai-singapore/outputs/txt2img/txt2img-images/2023-08-16/ad2e270b-dfcc-4ec3-8718-f19824857834-919429454.png to 1-output-0.png index 2 task_id is txt2img_1 index 2 data is b'{"images":[],"parameters":{"id_task":null,"status":0,"image_url":"/code/stable-diffusion-webui/data-oss/outputs/txt2img/txt2img-images/2023-08-16/374ceae2-deb5-4448-b213-cfdb11a53892-3273662200.png","seed":"3273662200","error_msg":"","total_time":2.76196551322937},"info":""}' save oss:///aohai-singapore/outputs/txt2img/txt2img-images/2023-08-16/374ceae2-deb5-4448-b213-cfdb11a53892-3273662200.png to 2-output-0.png index 3 task_id is txt2img_2 index 3 data is b'{"images":[],"parameters":{"id_task":null,"status":0,"image_url":"/code/stable-diffusion-webui/data-oss/outputs/txt2img/txt2img-images/2023-08-16/a37a0384-2ed4-42f9-9166-fe0fd80c624c-210444956.png","seed":"210444956","error_msg":"","total_time":2.7492804527282715},"info":""}' save oss:///aohai-singapore/outputs/txt2img/txt2img-images/2023-08-16/a37a0384-2ed4-42f9-9166-fe0fd80c624c-210444956.png to 3-output-0.png index 4 task_id is txt2img_3 index 4 data is b'{"images":[],"parameters":{"id_task":null,"status":0,"image_url":"/code/stable-diffusion-webui/data-oss/outputs/txt2img/txt2img-images/2023-08-16/482dcc64-4848-48f8-b9fd-7f0d3992f1ae-198191449.png","seed":"198191449","error_msg":"","total_time":2.8161191940307617},"info":""}' save oss:///aohai-singapore/outputs/txt2img/txt2img-images/2023-08-16/482dcc64-4848-48f8-b9fd-7f0d3992f1ae-198191449.png to 4-output-0.png
使用Java SDK
示例代码如下:
import com.aliyun.openservices.eas.predict.http.HttpConfig; import com.aliyun.openservices.eas.predict.http.QueueClient; import com.aliyun.openservices.eas.predict.queue_client.DataFrame; import com.aliyun.openservices.eas.predict.queue_client.QueueUser; import com.aliyun.openservices.eas.predict.queue_client.WebSocketWatcher; public class SDWebuiAsyncWatchTest { public static void main(String[] args) throws Exception { // 创建队列服务客户端。 String queueEndpoint = "http://166233998075****.cn-hangzhou.pai-eas.aliyuncs.com"; String queueToken = "xxxxx=="; // 输出队列名为 服务名+"/sink"。 String sinkQueueName = "/sink"; // 输出队列,推理服务处理输入数据后会将结果写入输出队列。 QueueClient sinkQueue = new QueueClient(queueEndpoint, sinkQueueName, queueToken, new HttpConfig(), new QueueUser()); // 清除队列数据!!! 请谨慎使用。 // sinkQueue.clear(); // 订阅队列,获取队列数据。 WebSocketWatcher watcher = sinkQueue.watch(0L, 5L, false, false, null); try { while (true) { DataFrame df = watcher.getDataFrame(); if (df.getTags().containsKey("task_id")) { System.out.println(String.format("task_id = %s", df.getTags().get("task_id"))); } System.out.println(String.format("index = %d, data = %s, requestId = %s", df.getIndex(), new String(df.getData()), df.getTags().get("requestId"))); sinkQueue.commit(df.getIndex()); } } catch (Exception e) { System.out.println("watch error:" + e.getMessage()); e.printStackTrace(); watcher.close(); } // 关闭客户端。 sinkQueue.shutdown(); } }
其中:
-
queueEndpoint:配置为步骤1中获取的服务访问地址。请参考示例代码进行相应的配置。
-
queueToken:配置为步骤1中获取的服务Token信息。
-
:替换为已部署的异步服务名称。
说明
-
需要主动进行commit操作,也可以设置
auto_commit=True
来自动进行commit操作。 -
如果consumer不再消费数据,需要及时关闭以释放资源。
-
您也可以使用curl命令或者调用同步接口来获取订阅接口,详情请参见异步推理与队列服务。
代码执行成功后,系统输出如下结果。您的结果以实际为准。您可以前往OSS控制台对应的路径下查看已生成的图片。
2023-08-04 16:17:31,497 INFO [com.aliyun.openservices.eas.predict.queue_client.WebSocketWatcher] - WebSocketClient Successfully Connects to Server: 1396993924585947.cn-hangzhou.pai-eas.aliyuncs.com/116.62.4.210:80 task_id = txt2img_0 index = 21, data = {"images":[],"parameters":{"id_task":null,"status":0,"image_url":"/code/stable-diffusion-webui/data-oss/outputs/txt2img/txt2img-images/2023-08-04/54363a9d-24a5-41b5-b038-2257d43b8e79-412510031.png","seed":"412510031","error_msg":"","total_time":2.5351321697235107},"info":""}, requestId = 05ca7786-c24e-4645-8538-83d235e791fe task_id = txt2img_1 index = 22, data = {"images":[],"parameters":{"id_task":null,"status":0,"image_url":"/code/stable-diffusion-webui/data-oss/outputs/txt2img/txt2img-images/2023-08-04/0c646dda-4a53-43f4-97fd-1f507599f6ae-2287341785.png","seed":"2287341785","error_msg":"","total_time":2.6269655227661133},"info":""}, requestId = 639b257a-7902-448d-afd5-f2641ab77025 task_id = txt2img_2 index = 23, data = {"images":[],"parameters":{"id_task":null,"status":0,"image_url":"/code/stable-diffusion-webui/data-oss/outputs/txt2img/txt2img-images/2023-08-04/4d542f25-b9cc-4548-9db2-5addd0366d32-1158414078.png","seed":"1158414078","error_msg":"","total_time":2.6604185104370117},"info":""}, requestId = d6b2e127-eba3-4414-8e6c-c3690e0a487c task_id = txt2img_3
-
发送同步接口请求
部署异步服务后,仍然支持使用指定服务名称的方式同步请求WebUI接口。您可以使用curl命令或Python客户端请求WebUI服务来验证模型效果和服务可用性。具体操作步骤如下:
-
查询调用信息。
服务部署成功后,单击服务方式列下的调用信息,在调用信息对话框中的同步调用页签,在公网地址调用页签查询服务访问地址和Token。
-
使用curl命令发送服务请求。示例如下:
curl -v --location '/sdapi/v1/sd-models' \ --header 'Authorization: '
其中:
-
:替换为步骤1中查询到的服务访问地址。
-
:替换为步骤1中查询到的服务Token。
命令执行成功后,返回当前服务支持的模型列表。
-
EAS基于原生SDWebUI接口支持了一些新特性,您可以在请求数据中添加一些可选参数用于实现更加丰富的功能或定制化需求。具体操作,请参见API额外支持的参数。
API额外支持的参数
EAS基于原生SDWebUI接口支持了一些新特性,在API接口中除了必填参数以外,还可以添加一些可选参数用于实现更加丰富的功能或定制化需求:
-
可以指定SD模型、VAE模型以及保存目录。
-
支持通过URL输入参数,并返回相应的状态码。
-
生成的图片和ControlNet所对应的图片可以通过URL进行访问。
具体使用示例如下:
txt2img请求和返回示例
请求数据格式示例如下:
{
"alwayson_scripts": {
"sd_model_checkpoint": "deliberate_v2.safetensors",
"save_dir": "/code/stable-diffusion-webui/data-oss/outputs",
"sd_vae": "Automatic"
},
"steps": 20,
"prompt": "girls",
"batch_size": 1,
"n_iter": 2,
"width": 576,
"height": 576,
"negative_prompt": "ugly, out of frame"
}
其中关键参数说明如下:
-
sd_model_checkpoint:指定SD模型参数,并且可以自动切换到大模型。
-
sd_vae:指定VAE模型。
-
save_dir:指定生成图片的保存路径。
发送同步接口请求示例如下:
#验证同步接口,获取服务调用入口。
curl --location --request POST '/sdapi/v1/txt2img' \
--header 'Authorization: ' \
--header 'Content-Type: application/json' \
--data-raw '{
"alwayson_scripts": {
"sd_model_checkpoint": "deliberate_v2.safetensors",
"save_dir": "/code/stable-diffusion-webui/data-oss/outputs",
"sd_vae": "Automatic"
},
"prompt": "girls",
"batch_size": 1,
"n_iter": 2,
"width": 576,
"height": 576,
"negative_prompt": "ugly, out of frame"
}'
返回数据格式示例如下:
{
"images": [],
"parameters": {
"id_task": "14837",
"status": 0,
"image_url": "/code/stable-diffusion-webui/data-oss/outputs/txt2img-grids/2023-07-24/grid-29a67c1c-099a-4d00-8ff3-1ebe6e64931a.png,/code/stable-diffusion-webui/data-oss/outputs/txt2img-images/2023-07-24/74626268-6c81-45ff-90b7-faba579dc309-1146644551.png,/code/stable-diffusion-webui/data-oss/outputs/txt2img-images/2023-07-24/6a233060-e197-4169-86ab-1c18adf04e3f-1146644552.png",
"seed": "1146644551,1146644552",
"error_msg": "",
"total_time": 32.22393465042114
},
"info": ""
}
发送异步接口请求示例如下:
# 将数据直接送入异步队列。
curl --location --request POST '/sdapi/v1/txt2img' \
--header 'Authorization: ' \
--header 'Content-Type: application/json' \
--data-raw '{
"alwayson_scripts": {
"sd_model_checkpoint": "deliberate_v2.safetensors",
"id_task": "14837",
"uid": "123",
"save_dir": "tmp/outputs"
},
"prompt": "girls",
"batch_size": 1,
"n_iter": 2,
"width": 576,
"height": 576,
"negative_prompt": "ugly, out of frame"
}'
img2img请求数据格式示例
请求数据格式示例如下:
{
"alwayson_scripts": {
"image_link":"https://eas-cache-cn-hangzhou.oss-cn-hangzhou-internal.aliyuncs.com/stable-diffusion-cache/tests/boy.png",
"sd_model_checkpoint": "deliberate_v2.safetensors",
"sd_vae": "Automatic",
"save_dir": "/code/stable-diffusion-webui/data-oss/outputs"
},
"prompt": "girl",
"batch_size": 1,
"n_iter": 2,
"width": 576,
"height": 576,
"negative_prompt": "ugly, out of frame",
"steps": 20, # Sampling steps
"seed": 111,
"subseed": 111, # Variation seed
"subseed_strength": 0, # Variation strength
"seed_resize_from_h": 0, # Resize seed from height
"seed_resize_from_w": 0, # Resize seed from width
"seed_enable_extras": false, # Extra
"sampler_name": "DDIM", # Sampling method
"cfg_scale": 7.5, # CFG Scale
"restore_faces": true, # Restore faces
"tiling": false, # Tiling
"init_images": [], # image base64 str, default None
"mask_blur": 4, # Mask blur
"resize_mode": 1, # 0 just resize, 1 crop and resize, 2 resize and fill, 3 just resize
"denoising_strength": 0.75, # Denoising strength
"inpainting_mask_invert": 0, #int, index of ['Inpaint masked', 'Inpaint not masked'], Mask mode
"inpainting_fill": 0, #index of ['fill', 'original', 'latent noise', 'latent nothing'], Masked content
"inpaint_full_res": 0, # index of ["Whole picture", "Only masked"], Inpaint area
"inpaint_full_res_padding": 32, #minimum=0, maximum=256, step=4, value=32, Only masked padding, pixels
#"image_cfg_scale": 1, # resized by scale
#"script_name": "Outpainting mk2", # 使用的script名字,不使用的话不要加这个字段
#"script_args": ["Outpainting", 128, 8, ["left", "right", "up", "down"], 1, 0.05] # 对应script脚本的参数,此处依次对应: 固定字段, pixels, mask_blur, direction, noise_q, color_variation
}
返回数据格式示例如下:
{
"images":[],
"parameters":{
"id_task":"14837",
"status":0,
"image_url":"/data/api_test/img2img-grids/2023-06-05/grid-0000.png,/data/api_test/img2img-images/2023-06-05/00000-1003.png,/data/api_test/img2img-images/2023-06-05/00001-1004.png",
"seed":"1003,1004",
"error_msg":""
},
"info":""
}
txt2img使用controlnet的数据格式
请求数据格式如下:
{
"alwayson_scripts": {
"sd_model_checkpoint": "deliberate_v2.safetensors", #模型名称,需要带着
"save_dir": "/code/stable-diffusion-webui/data-oss/outputs",
"controlnet":{
"args":[
{
"image_link": "https://pai-aigc-dataset.oss-cn-hangzhou.aliyuncs.com/pixabay_images/00008b87bf3ff6742b8cf81c358b9dbc.jpg",
"enabled": true,
"module": "canny",
"model": "control_v11p_sd15_canny",
"weight": 1,
"resize_mode": "Crop and Resize",
"low_vram": false,
"processor_res": 512,
"threshold_a": 100,
"threshold_b": 200,
"guidance_start": 0,
"guidance_end": 1,
"pixel_perfect": true,
"control_mode": "Balanced",
"input_mode": "simple",
"batch_images": "",
"output_dir": "",
"loopback": false
}
]
}
},
# 主要参数
"prompt": "girls",
"batch_size": 1,
"n_iter": 2,
"width": 576,
"height": 576,
"negative_prompt": "ugly, out of frame"
}
返回数据格式示例如下:
{
"images":[],
"parameters":{
"id_task":"14837",
"status":0,
"image_url":"/data/api_test/txt2img-grids/2023-06-05/grid-0007.png,/data/api_test/txt2img-images/2023-06-05/00014-1003.png,/data/api_test/txt2img-images/2023-06-05/00015-1004.png",
"seed":"1003,1004",
"error_msg":"",
"image_mask_url":"/data/api_test/controlnet_mask/2023-06-05/00000.png,/data/api_test/controlnet_mask/2023-06-05/00001.png"
},
"info":""
}
内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家
阿里云企业补贴进行中: 马上申请
腾讯云限时活动1折起,即将结束: 马上收藏
同尘科技为腾讯云授权服务中心。
购买腾讯云产品享受折上折,更有现金返利:同意关联,立享优惠
转转请注明出处:https://www.yunxiaoer.com/164269.html