|
|
@@ -1,466 +0,0 @@
|
|
|
-import os
|
|
|
-import sys
|
|
|
-import time
|
|
|
-import requests
|
|
|
-import json
|
|
|
-from typing import Dict, Any
|
|
|
-
|
|
|
-sys.path.append(os.path.join(os.path.dirname(__file__), '../tools/local/liblibai_controlnet'))
|
|
|
-from liblibai_client import LibLibAIClient
|
|
|
-
|
|
|
-# 常量配置 (根据文档)
|
|
|
-TEMPLATE_UUID = "e10adc3949ba59abbe56e057f20f883e" # SD1.5 & SDXL 通用自定义参数模板
|
|
|
-
|
|
|
-# 请确保这是一个有效的 SDXL 模型,这样才能匹配底下的 SDXL Canny 模型
|
|
|
-# 这里用的是代码里原本的 Checkpoint ID,请根据你们自己的 Liblib 模型库调整!
|
|
|
-DEFAULT_CHECKPOINT_ID = "0ea388c7eb854be3ba3c6f65aac6bfd3"
|
|
|
-
|
|
|
-class LibLibTestRunner:
|
|
|
- def __init__(self):
|
|
|
- self.client = LibLibAIClient()
|
|
|
- self.models = self._load_models_from_json()
|
|
|
-
|
|
|
- # 动态匹配基础算法 XL 的各种控制网模型
|
|
|
- self.sdxl_canny = self._get_model_uuid("线稿类", "Canny(硬边缘)", xl_only=True) or "b6806516962f4e1599a93ac4483c3d23"
|
|
|
- self.sdxl_softedge = self._get_model_uuid("线稿类", "SoftEdge(软边缘)", xl_only=True) or "dda1a0c480bfab9833d9d9a1e4a71fff"
|
|
|
- self.sdxl_lineart = self._get_model_uuid("线稿类", "Lineart(线稿)", xl_only=True) or "a0f01da42bf48b0ba02c86b6c26b5699"
|
|
|
- self.sdxl_openpose = self._get_model_uuid("姿态类", "OpenPose(姿态)", xl_only=True) or "2fe4f992a81c5ccbdf8e9851c8c96ff2"
|
|
|
-
|
|
|
- self._verify_models()
|
|
|
-
|
|
|
- def _load_models_from_json(self):
|
|
|
- json_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../data/liblibai_controlnet_models.json"))
|
|
|
- if os.path.exists(json_path):
|
|
|
- with open(json_path, "r", encoding="utf-8") as f:
|
|
|
- return json.load(f)
|
|
|
- return {}
|
|
|
-
|
|
|
- def _get_model_uuid(self, category, subtype, xl_only=True):
|
|
|
- if category in self.models and subtype in self.models[category]:
|
|
|
- for model in self.models[category][subtype]:
|
|
|
- if xl_only and model["base_algorithm"] != "基础算法 XL":
|
|
|
- continue
|
|
|
- return model["uuid"]
|
|
|
- return None
|
|
|
-
|
|
|
- def _verify_models(self):
|
|
|
- print("="*50)
|
|
|
- print("校验底模信息 (使用 api/model/version/get)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- models_to_verify = {
|
|
|
- "CheckPoint / 底模": DEFAULT_CHECKPOINT_ID,
|
|
|
- }
|
|
|
-
|
|
|
- for name, uuid in models_to_verify.items():
|
|
|
- info = self.client.get_model_version_info(uuid)
|
|
|
- status = f"{info.get('model_name', 'Unknown')} (Base: {info.get('baseAlgo', 'Unknown')})" if info else "Failed to verify"
|
|
|
- print(f"- {name}: [{uuid}] -> {status}")
|
|
|
- print("\n")
|
|
|
-
|
|
|
- def _submit_task(self, payload: dict) -> str:
|
|
|
- url = self.client.generate_auth_url("/api/generate/webui/text2img")
|
|
|
- print(f"Submitting payload...")
|
|
|
- resp = requests.post(url, json=payload, timeout=10)
|
|
|
- data = resp.json()
|
|
|
- if data.get("code") != 0:
|
|
|
- raise Exception(f"Submit task failed: {data.get('msg')} (code: {data.get('code')})")
|
|
|
- return data["data"]["generateUuid"]
|
|
|
-
|
|
|
- def _wait_and_print_result(self, task_id: str):
|
|
|
- print(f"Task submitted successfully! Task ID: {task_id}")
|
|
|
- print("Waiting for result...")
|
|
|
- timeout = 300
|
|
|
- start_time = time.time()
|
|
|
- while time.time() - start_time < timeout:
|
|
|
- task_data = self.client.query_task_status(task_id)
|
|
|
- status = task_data.get("generateStatus")
|
|
|
-
|
|
|
- if status == 5: # Success
|
|
|
- images = [img["imageUrl"] for img in task_data.get("images", [])]
|
|
|
- print(f"\n[SUCCESSS] Generated images: {images}")
|
|
|
-
|
|
|
- # --- 新增: 自动下载图片 ---
|
|
|
- output_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "output"))
|
|
|
- os.makedirs(output_dir, exist_ok=True)
|
|
|
- for i, img_url in enumerate(images):
|
|
|
- try:
|
|
|
- img_resp = requests.get(img_url)
|
|
|
- img_resp.raise_for_status()
|
|
|
- timestamp = int(time.time())
|
|
|
- filename = f"workflow_result_{timestamp}_{i}.png"
|
|
|
- filepath = os.path.join(output_dir, filename)
|
|
|
- with open(filepath, "wb") as f:
|
|
|
- f.write(img_resp.content)
|
|
|
- print(f"[{i}] 已自动保存到本地: {filepath}")
|
|
|
- except Exception as e:
|
|
|
- print(f"图片自动下载失败: {e}")
|
|
|
- return
|
|
|
- elif status in [6, 7]: # Failed or Cancelled
|
|
|
- print(f"\n[FAILED] Task failed. Audit status: {task_data.get('auditStatus')}")
|
|
|
- return
|
|
|
-
|
|
|
- print(".", end="", flush=True)
|
|
|
- time.sleep(5)
|
|
|
-
|
|
|
- print("\n[TIMEOUT] Wait for task timed out.")
|
|
|
-
|
|
|
- # 1. 纯文生图测试
|
|
|
- def test_text2img(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 1: 纯文生图 (Text to Image)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- payload = {
|
|
|
- "templateUuid": TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID,
|
|
|
- "prompt": "1girl, cute, beautiful landscape, masterpiece",
|
|
|
- "negativePrompt": "lowres, bad anatomy, text, error",
|
|
|
- "sampler": 15,
|
|
|
- "steps": 20,
|
|
|
- "cfgScale": 7.0,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "imgCount": 1
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
-
|
|
|
- # 2. 纯图生图测试
|
|
|
- def test_img2img(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 2: 纯图生图 (Image to Image)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- test_img_url = "https://liblibai-airship-temp.oss-cn-beijing.aliyuncs.com/aliyun-cn-prod/73ed6ae42b144d21bf566e05b5a6c138.png"
|
|
|
-
|
|
|
- payload = {
|
|
|
- "templateUuid": TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID,
|
|
|
- "mode": 0, # 0 代表图生图
|
|
|
- "sourceImage": test_img_url,
|
|
|
- "denoisingStrength": 0.75, # 去噪强度
|
|
|
- "prompt": "white line art, cat",
|
|
|
- "negativePrompt": "lowres, bad anatomy, error",
|
|
|
- "sampler": 15,
|
|
|
- "steps": 20,
|
|
|
- "cfgScale": 7.0,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "imgCount": 1
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
-
|
|
|
- # 3. 文生图 + ControlNet (Canny) 测试
|
|
|
- def test_text2img_controlnet(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 3: 文生图 + ControlNet (Text2Img with ControlNet Canny)")
|
|
|
- print("="*50)
|
|
|
- print("注意: 如果默认 Checkpoint 是 SD1.5, 下面配置的 SDXL Canny 模型可能会导致访问拒绝!")
|
|
|
-
|
|
|
- test_img_url = "https://liblibai-airship-temp.oss-cn-beijing.aliyuncs.com/aliyun-cn-prod/73ed6ae42b144d21bf566e05b5a6c138.png"
|
|
|
-
|
|
|
- payload = {
|
|
|
- "templateUuid": TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID,
|
|
|
- "prompt": "simple white line art, cat, black background",
|
|
|
- "negativePrompt": "lowres, bad anatomy",
|
|
|
- "sampler": 15,
|
|
|
- "steps": 20,
|
|
|
- "cfgScale": 7.0,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "imgCount": 1,
|
|
|
- "controlNet": [{
|
|
|
- "unitOrder": 1,
|
|
|
- "sourceImage": test_img_url,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "preprocessor": 1, # 1 = Canny
|
|
|
- "model": self.sdxl_canny,
|
|
|
- "controlWeight": 1.0,
|
|
|
- "startingControlStep": 0.0,
|
|
|
- "endingControlStep": 1.0,
|
|
|
- "pixelPerfect": 1,
|
|
|
- "controlMode": 0,
|
|
|
- "annotationParameters": {
|
|
|
- "canny": {
|
|
|
- "preprocessorResolution": 512,
|
|
|
- "lowThreshold": 100,
|
|
|
- "highThreshold": 200
|
|
|
- }
|
|
|
- }
|
|
|
- }]
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
-
|
|
|
- # 4. 文生图 + 边缘 (SoftEdge/HED)
|
|
|
- def test_text2img_softedge(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 4: 文生图 + SoftEdge (软边缘 控制网)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- # 测试用图片
|
|
|
- test_img_url = "https://liblibai-airship-temp.oss-cn-beijing.aliyuncs.com/aliyun-cn-prod/73ed6ae42b144d21bf566e05b5a6c138.png"
|
|
|
-
|
|
|
- payload = {
|
|
|
- "templateUuid": TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID,
|
|
|
- "prompt": "Soft edge artwork, beautiful soft lighting, cat",
|
|
|
- "negativePrompt": "lowres, bad anatomy",
|
|
|
- "sampler": 15,
|
|
|
- "steps": 20,
|
|
|
- "cfgScale": 7.0,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "imgCount": 1,
|
|
|
- "controlNet": [{
|
|
|
- "unitOrder": 1,
|
|
|
- "sourceImage": test_img_url,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "preprocessor": 5, # 5 = HED / 软边缘
|
|
|
- "model": self.sdxl_softedge,
|
|
|
- "controlWeight": 1.0,
|
|
|
- "startingControlStep": 0.0,
|
|
|
- "endingControlStep": 1.0,
|
|
|
- "pixelPerfect": 1,
|
|
|
- "controlMode": 0,
|
|
|
- "annotationParameters": {
|
|
|
- "hed": {
|
|
|
- "preprocessorResolution": 512
|
|
|
- }
|
|
|
- }
|
|
|
- }]
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
-
|
|
|
- # 5. 文生图 + 线稿 (Lineart)
|
|
|
- def test_text2img_lineart(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 5: 文生图 + Lineart (线稿 控制网)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- test_img_url = "https://liblibai-airship-temp.oss-cn-beijing.aliyuncs.com/aliyun-cn-prod/73ed6ae42b144d21bf566e05b5a6c138.png"
|
|
|
-
|
|
|
- payload = {
|
|
|
- "templateUuid": TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID,
|
|
|
- "prompt": "Detailed coloring, colorful fantasy style, masterpiece, cat",
|
|
|
- "negativePrompt": "lowres",
|
|
|
- "sampler": 15,
|
|
|
- "steps": 20,
|
|
|
- "cfgScale": 7.0,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "imgCount": 1,
|
|
|
- "controlNet": [{
|
|
|
- "unitOrder": 1,
|
|
|
- "sourceImage": test_img_url,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "preprocessor": 32, # 32 = Lineart Standard
|
|
|
- "model": self.sdxl_lineart,
|
|
|
- "controlWeight": 1.0,
|
|
|
- "startingControlStep": 0.0,
|
|
|
- "endingControlStep": 1.0,
|
|
|
- "pixelPerfect": 1,
|
|
|
- "controlMode": 0,
|
|
|
- "annotationParameters": {
|
|
|
- "lineart": {
|
|
|
- "preprocessorResolution": 512
|
|
|
- }
|
|
|
- }
|
|
|
- }]
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
-
|
|
|
- # 6. 文生图 + 骨骼 (OpenPose)
|
|
|
- def test_text2img_openpose(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 6: 文生图 + OpenPose (骨骼 控制网)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- # 测试用图片(最好使用含有人物动作的图)
|
|
|
- test_img_url = "https://liblibai-airship-temp.oss-cn-beijing.aliyuncs.com/aliyun-cn-prod/73ed6ae42b144d21bf566e05b5a6c138.png"
|
|
|
-
|
|
|
- payload = {
|
|
|
- "templateUuid": TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID,
|
|
|
- "prompt": "1girl, dancing pose, beautiful dress",
|
|
|
- "negativePrompt": "lowres",
|
|
|
- "sampler": 15,
|
|
|
- "steps": 20,
|
|
|
- "cfgScale": 7.0,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "imgCount": 1,
|
|
|
- "controlNet": [{
|
|
|
- "unitOrder": 1,
|
|
|
- "sourceImage": test_img_url,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "preprocessor": 14, # 14 = OpenPose Full
|
|
|
- "model": self.sdxl_openpose,
|
|
|
- "controlWeight": 1.0,
|
|
|
- "startingControlStep": 0.0,
|
|
|
- "endingControlStep": 1.0,
|
|
|
- "pixelPerfect": 1,
|
|
|
- "controlMode": 0,
|
|
|
- "annotationParameters": {
|
|
|
- "openposeFull": {
|
|
|
- "preprocessorResolution": 512
|
|
|
- }
|
|
|
- }
|
|
|
- }]
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
-
|
|
|
- # 7. 局部重绘 (Inpaint Mode 4)
|
|
|
- def test_inpaint_mode4(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 7: 局部重绘 (Inpaint Mode 4 蒙版重绘)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- test_img_url = "https://liblibai-airship-temp.oss-cn-beijing.aliyuncs.com/aliyun-cn-prod/73ed6ae42b144d21bf566e05b5a6c138.png"
|
|
|
- test_mask_url = test_img_url # 仅作演示,实际应用中应当是一个黑底白色的蒙版图片
|
|
|
-
|
|
|
- payload = {
|
|
|
- # Inpainting 可能需要特殊模板,如不兼容请参考文档
|
|
|
- "templateUuid": TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID,
|
|
|
- "mode": 4, # 4 = Inpaint 蒙版重绘
|
|
|
- "sourceImage": test_img_url,
|
|
|
- "denoisingStrength": 0.5,
|
|
|
- "prompt": "A completely different background, sci-fi city",
|
|
|
- "negativePrompt": "lowres",
|
|
|
- "sampler": 15,
|
|
|
- "steps": 20,
|
|
|
- "cfgScale": 7.0,
|
|
|
- "width": 512,
|
|
|
- "height": 512,
|
|
|
- "imgCount": 1,
|
|
|
- "inpaintParam": {
|
|
|
- "maskImage": test_mask_url,
|
|
|
- "maskBlur": 4,
|
|
|
- "inpaintArea": 0
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
- # 8. 人像换脸 (InstantID)
|
|
|
- def test_instantid_faceswap(self):
|
|
|
- print("\n" + "="*50)
|
|
|
- print("TEST 8: 人像换脸 (InstantID)")
|
|
|
- print("="*50)
|
|
|
-
|
|
|
- # Note: InstantID faceswap uses a UNIQUE templateUuid
|
|
|
- INSTANT_ID_TEMPLATE_UUID = "7d888009f81d4252a7c458c874cd017f"
|
|
|
-
|
|
|
- face_img_url = "https://liblibai-online.liblib.cloud/img/081e9f07d9bd4c2ba090efde163518f9/49943c0b-4d79-4e2f-8c55-bc1e5b8c69d8.png"
|
|
|
- pose_img_url = "https://liblibai-online.liblib.cloud/img/081e9f07d9bd4c2ba090efde163518f9/e713676d-baaa-4dac-99b9-d5d814a29f9f.png"
|
|
|
-
|
|
|
- payload = {
|
|
|
- "templateUuid": INSTANT_ID_TEMPLATE_UUID,
|
|
|
- "generateParams": {
|
|
|
- "checkPointId": DEFAULT_CHECKPOINT_ID, # 仅 XL模型支持人像换脸
|
|
|
- "prompt": "Asian portrait,A young woman wearing a green baseball cap, close shot, background is coffee store, masterpiece, best quality, ultra resolution",
|
|
|
- "width": 768,
|
|
|
- "height": 1152,
|
|
|
- "sampler": 20,
|
|
|
- "steps": 35,
|
|
|
- "cfgScale": 2.0,
|
|
|
- "imgCount": 1,
|
|
|
- "controlNet": [
|
|
|
- {
|
|
|
- "unitOrder": 1, # 第一步:先识别要用的人像人脸
|
|
|
- "sourceImage": face_img_url,
|
|
|
- "width": 1080,
|
|
|
- "height": 1432
|
|
|
- },
|
|
|
- {
|
|
|
- "unitOrder": 2, # 第二步:再识别要参考的人物面部朝向
|
|
|
- "sourceImage": pose_img_url,
|
|
|
- "width": 1024,
|
|
|
- "height": 1024
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
- }
|
|
|
- task_id = self._submit_task(payload)
|
|
|
- self._wait_and_print_result(task_id)
|
|
|
-
|
|
|
-
|
|
|
-if __name__ == "__main__":
|
|
|
- try:
|
|
|
- runner = LibLibTestRunner()
|
|
|
-
|
|
|
- print("选择要测试的模式:")
|
|
|
- print("1. 纯文生图 (Text2Img)")
|
|
|
- print("2. 纯图生图 (Img2Img)")
|
|
|
- print("3. 硬边缘控制 (Canny ControlNet)")
|
|
|
- print("4. 软边缘控制 (SoftEdge ControlNet)")
|
|
|
- print("5. 线稿控制 (Lineart ControlNet)")
|
|
|
- print("6. 骨骼控制 (OpenPose ControlNet)")
|
|
|
- print("7. 局部重绘 (Inpaint Mode=4)")
|
|
|
- print("8. 人像换脸 (InstantID)")
|
|
|
- print("9. 全部测试 (All)")
|
|
|
-
|
|
|
- if len(sys.argv) > 1:
|
|
|
- choice = sys.argv[1]
|
|
|
- else:
|
|
|
- # 默认测试文生图以验证 API Key 最基本权限
|
|
|
- choice = "1"
|
|
|
-
|
|
|
- if choice == "1":
|
|
|
- runner.test_text2img()
|
|
|
- elif choice == "2":
|
|
|
- runner.test_img2img()
|
|
|
- elif choice == "3":
|
|
|
- runner.test_text2img_controlnet()
|
|
|
- elif choice == "4":
|
|
|
- runner.test_text2img_softedge()
|
|
|
- elif choice == "5":
|
|
|
- runner.test_text2img_lineart()
|
|
|
- elif choice == "6":
|
|
|
- runner.test_text2img_openpose()
|
|
|
- elif choice == "7":
|
|
|
- runner.test_inpaint_mode4()
|
|
|
- elif choice == "8":
|
|
|
- runner.test_instantid_faceswap()
|
|
|
- elif choice == "9":
|
|
|
- runner.test_text2img()
|
|
|
- runner.test_img2img()
|
|
|
- runner.test_text2img_controlnet()
|
|
|
- # 省略后面的测试避免同时发生太多请求...
|
|
|
- else:
|
|
|
- print("Unknown choice.")
|
|
|
-
|
|
|
- except Exception as e:
|
|
|
- print(f"\n[FATAL ERROR] {e}")
|