test_lib.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import requests
  2. import time
  3. import hmac
  4. import hashlib
  5. import uuid
  6. import base64
  7. import os
  8. import sys
  9. from dotenv import load_dotenv
  10. # 设置 UTF-8 输出编码(Windows 兼容)
  11. if sys.platform == 'win32':
  12. sys.stdout.reconfigure(encoding='utf-8')
  13. load_dotenv()
  14. class LibLibControlNet:
  15. def __init__(self):
  16. self.ak = os.getenv("LIBLIBAI_ACCESS_KEY") or "你的AccessKey"
  17. self.sk = os.getenv("LIBLIBAI_SECRET_KEY") or "你的SecretKey"
  18. self.domain = "https://openapi.liblibai.cloud"
  19. # 先替换为更通用的模板ID(避免旧ID失效)
  20. # 文生图模板(必须是 1.5 体系的模板)
  21. self.TEMPLATE_UUID = "e10adc3949ba59abbe56e057f20f883e"
  22. # SD1.5 底模
  23. self.CHECKPOINT_ID = "0ea388c7eb854be3ba3c6f65aac6bfd3"
  24. # SD1.5 Canny(来自你给的官方表)
  25. self.CANNY_MODEL_ID = "b6806516962f4e1599a93ac4483c3d23"
  26. def _generate_signature(self, uri):
  27. ts = str(int(time.time() * 1000))
  28. nonce = uuid.uuid4().hex
  29. sign_str = f"{uri}&{ts}&{nonce}"
  30. dig = hmac.new(self.sk.encode(), sign_str.encode(), hashlib.sha1).digest()
  31. signature = base64.urlsafe_b64encode(dig).rstrip(b"=").decode()
  32. return f"{self.domain}{uri}?AccessKey={self.ak}&Timestamp={ts}&SignatureNonce={nonce}&Signature={signature}"
  33. def submit_canny_task(self, image_url, prompt):
  34. uri = "/api/generate/webui/text2img"
  35. url = self._generate_signature(uri)
  36. payload = {
  37. "templateUuid": self.TEMPLATE_UUID,
  38. "generateParams": {
  39. "checkPointId": self.CHECKPOINT_ID,
  40. "prompt": prompt,
  41. "negativePrompt": "lowres, bad anatomy, text, error, extra digit, fewer digits, cropped, worst quality, low quality",
  42. "sampler": 15,
  43. "steps": 20,
  44. "cfgScale": 7.0, # 修复:改为浮点数(部分版本要求)
  45. "width": 512,
  46. "height": 512,
  47. "imgCount": 1,
  48. "seed": -1,
  49. "controlNet": [
  50. {
  51. "unitOrder": 1,
  52. "sourceImage": image_url,
  53. "width": 512,
  54. "height": 512,
  55. "preprocessor": 1,
  56. "annotationParameters": {
  57. "canny": {
  58. "preprocessorResolution": 512,
  59. "lowThreshold": 100,
  60. "highThreshold": 200
  61. }
  62. },
  63. "model": self.CANNY_MODEL_ID,
  64. "controlWeight": 1.0,
  65. "startingControlStep": 0.0,
  66. "endingControlStep": 1.0,
  67. "pixelPerfect": 1,
  68. "controlMode": 0,
  69. "resizeMode": 1
  70. }
  71. ]
  72. }
  73. }
  74. try:
  75. print(f"📤 提交ControlNet生图任务...")
  76. print(f"🔍 请求URL: {url}")
  77. print(f"🔍 请求Payload: {payload}") # 打印完整参数
  78. resp = requests.post(
  79. url,
  80. headers={"Content-Type": "application/json"},
  81. json=payload,
  82. timeout=10
  83. )
  84. # 打印完整响应(关键调试信息)
  85. print(f"🔍 响应状态码: {resp.status_code}")
  86. print(f"🔍 响应内容: {resp.text}")
  87. result = resp.json()
  88. if result.get("code") == 0:
  89. task_id = result["data"]["generateUuid"]
  90. print(f"✅ 任务提交成功!任务ID: {task_id}")
  91. return task_id
  92. else:
  93. print(f"❌ 任务提交失败: {result.get('msg')}")
  94. return None
  95. except Exception as e:
  96. print(f"❌ 提交任务异常: {str(e)}")
  97. return None
  98. def poll_task_status(self, task_id):
  99. uri = "/api/generate/webui/status"
  100. max_retry = 60
  101. retry_count = 0
  102. while retry_count < max_retry:
  103. try:
  104. url = self._generate_signature(uri)
  105. resp = requests.post(
  106. url,
  107. headers={"Content-Type": "application/json"},
  108. json={"generateUuid": task_id},
  109. timeout=10
  110. )
  111. resp.raise_for_status()
  112. result = resp.json()
  113. if result.get("code") != 0:
  114. print(f"❌ 查询状态失败: {result.get('msg')}")
  115. return None
  116. data = result.get("data", {})
  117. status = data.get("generateStatus")
  118. if status == 5:
  119. img_url = data["images"][0]["imageUrl"]
  120. print(f"🎉 生图成功!最终图片URL: {img_url}")
  121. return img_url
  122. elif status in [6, 7]:
  123. print(f"❌ 任务失败: {data.get('generateMsg', '未知错误')}")
  124. return None
  125. else:
  126. print(f"⏳ 任务处理中(状态码: {status}),已等待{retry_count*5}秒...")
  127. except Exception as e:
  128. print(f"❌ 轮询异常: {str(e)}")
  129. retry_count += 1
  130. time.sleep(5)
  131. print(f"❌ 任务轮询超时(超过5分钟)")
  132. return None
  133. if __name__ == "__main__":
  134. client = LibLibControlNet()
  135. # 替换为更稳定的公开测试图
  136. PUBLIC_IMAGE_URL = "https://liblibai-airship-temp.oss-cn-beijing.aliyuncs.com/aliyun-cn-prod/73ed6ae42b144d21bf566e05b5a6c138.png"
  137. PROMPT = "simple white line art, cat, black background, 512x512" # 简化提示词(避免过长)
  138. task_id = client.submit_canny_task(PUBLIC_IMAGE_URL, PROMPT)
  139. if task_id:
  140. client.poll_task_status(task_id)