stability platform
說明文件 & 功能介紹:
(有空再補充說明)
-
Parameters:參數說明文件
-
Text-to-Image
-
Image-to-Image
-
Inpainting + Masking
-
CLIP Guidance
-
Animation
-
Image Upscaling
-
Multi-prompting
-
Variants
取得 API keys 的連結:DreamStudio by stability.ai
安裝
pip install stability_sdk
import
from stability_sdk import client
import stability_sdk.interfaces.gooseai.generation.generation_pb2 as generation
# 其他 import...
程式範例
已移除部分備註
answers = stability_api.generate(
prompt="Oil painting ...",
seed=992446758,
steps=50, # Defaults to 30
cfg_scale=8.0, # Defaults to 7.0
width=1024 # Defaults to 512 or 1024 depending on the engine
height=1024, # Defaults to 512 or 1024 depending on the engine
samples=1, # Defaults to 1
sampler=generation.SAMPLER_K_DPMPP_2M # Defaults to k_dpmpp_2m
)
for resp in answers:
for artifact in resp.artifacts:
if artifact.finish_reason == generation.FILTER:
warnings.warn(
"Your request activated the API's safety filters and could not be processed."
"Please modify the prompt and try again.")
if artifact.type == generation.ARTIFACT_IMAGE:
img = Image.open(io.BytesIO(artifact.binary))
img.save(str(artifact.seed)+ ".png")
文字冒險遊戲
CYOA:Create Your Own Adventure Game
老師用 Flask 架站,而非 Node.js。
system_directive = """
You, 'assistant', are telling me, 'user', an interactive choose-your-own-adventure story.
...
""".strip()
def get_caption_from_chat_response(chat_response_object: Mapping) -> str:
"""
:raises: AttributeError if no caption is found
"""
return re.search(r"Caption:(.*)(?:\n|$)", chat_response_object["content"]).group(1).strip()
def is_valid_cyoa(chat_response_object) -> bool:
try:
get_caption_from_chat_response(chat_response_object)
except AttributeError:
return False
return (
bool(re.search(r"Story:(.*)(?:\n|$)", chat_response_object["content"]))
and bool(re.search(r"Choice1:(.*)(?:\n|$)", chat_response_object["content"]))
and bool(re.search(r"Choice2:(.*)(?:\n|$)", chat_response_object["content"]))
)
@retry(
stop=stop_after_attempt(3),
retry=retry_if_not_result(is_valid_cyoa) | retry_if_exception_type(
APIConnectionError) | retry_if_exception_type(APIError) | retry_if_exception_type(RateLimitError),
)
def generate_cyoa_next_message(messages) -> Mapping:
messages_payload = [{"role": "system", "content": system_directive}]
# Filter out our image_url we sneak into their API call
messages_payload.extend([{k: v for k, v in message.items(
) if k != "cyoa_image_base64"} for message in messages])
print("************************************")
print("************************************")
print("************************************")
print(messages_payload)
# The ChatCompletion API has the gpt-3.5-turbo model available to it. As of Q1 2023, it's 1/10th the cost of text-davinci-003 at $0.002/1K tokens.
chat_response = openai.ChatCompletion.create(
model="gpt-4",
messages=messages_payload,
frequency_penalty=1.0,
temperature=0.8,
)
log.info(f"Chat generated in {chat_response.response_ms} milliseconds")
log.debug(f"Chat Response: {chat_response}")
return chat_response.choices[0].message.to_dict()
def generate_image_base64_dalle(image_caption, dimensions=(512, 512)):
try:
image_response = openai.Image.create(
prompt=(image_caption[:1000]),
n=1,
size=f"{dimensions[0]}x{dimensions[1]}",
response_format="b64_json",
)
log.debug(f"Image Response: {image_response}")
base64_image = image_response["data"][0]["b64_json"]
except openai.InvalidRequestError as e:
log.warn(
f"Skipping image generation. Image prompt was rejected by OpenAI: {e.args}")
return None
except (APIConnectionError, APIError, RateLimitError, ServiceUnavailableError) as e:
# We don't retry these because the story is more important than the images. Don't slow the story down
# if we simply miss a single image.
log.warn(f"Temporary API error. Skipping image generation: {e.args}")
return None
else:
return base64_image
def generate_image_base64_stability(image_caption, dimensions=(512, 512)):
STABILITY_ENGINE_ID = "stable-diffusion-512-v2-1" # "stable-diffusion-v1-5"
# The latter arg is a default
STABILITY_API_HOST = os.getenv("API_HOST", "https://api.stability.ai")
STABILITY_API_KEY = os.environ["STABILITY_API_KEY"]
print(f"Generating image with caption: {image_caption[:1000]}")
response = requests.post(
f"{STABILITY_API_HOST}/v1/generation/{STABILITY_ENGINE_ID}/text-to-image",
headers={"Content-Type": "application/json", "Accept": "application/json",
"Authorization": f"Bearer {STABILITY_API_KEY}"},
json={
"text_prompts": [{"text": image_caption[:1000]}],
"cfg_scale": 7,
"clip_guidance_preset": "FAST_BLUE",
"height": dimensions[1],
"width": dimensions[1],
"samples": 1,
"steps": 50,
},
)
if response.status_code != 200:
log.warn(
f"Skipping image generation. Stability response was {response.status_code}: {response.text}")
return None
else:
data = response.json()
return data["artifacts"][0]["base64"]
@app.route("/cyoa", methods=["POST"])
def cyoa():
request_json = request.get_json()
assert "messages" in request_json
if len(request_json["messages"]) != 0:
assert request_json["messages"][0]["role"] == "user"
assert request_json["messages"][-1]["role"] == "user"
# Note: In a production context, you should validate this input.
messages = request_json["messages"].copy()
chat_response_object = generate_cyoa_next_message(messages)
messages.append(chat_response_object)
t_image = time.time()
try:
image_caption = get_caption_from_chat_response(chat_response_object)
except AttributeError:
log.warn("Skipping image generation. GPT response did not have a caption.")
return {"messages": messages}
# Continue on to generate an image and affix it to the last message
# image_base64 = generate_image_base64_dalle(image_caption)
image_base64 = generate_image_base64_stability(
"A first person view in the style of detailed fantasy art: " + image_caption)
if image_base64:
# ...
# Optionally, store the image locally
# ...
messages[-1]["cyoa_image_base64"] = image_base64
log.info(
f"Image generated and saved in {time.time() - t_image} seconds")
return {"messages": messages}