抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

前面的文章打破信息差有提到过,CloudFlare 提供了一些免费的开源模型的 API,而 Flux 的生图模型就在其中。不过,这个模型的 API 最终返回给我们的是 Base64 数据,而不是可直观查看的图片,所以我们需要将图片数据写入文件并上传到云端,然后通过 URL 访问它。另外,我们还希望支持写中文的提示词,所以我们需要在其中增加一个大模型的翻译层,这样就可以把中文的提示词翻译成英文,从而被 Flux 识别。今天,我就通过 Python 代码的方式来实现上述的功能。 🚀

准备工作

首先,我们当然需要一个 CloudFlare 的账号了,注册账号的教程网络上比比皆是,我就不再此处赘述了。然后,我们需要开通 CloudFlare 的 R2 对象存储,这个对象存储是免费 10G 的,足够我们挥霍了。开通方法可以参考这两篇文章:

然后我们需要记录我们生成的 API_secret 和 API_token,以便后续使用。

我们还需要获取我们 CloudFlare 的 account_id 和 worker 的 API_token。

获取这些值的步骤:

  1. 登录到 Cloudflare 控制面板并选择您的账户。
  2. 转到 AI > Workers AI。
  3. 选择使用 Workers AI API。
  4. 获取您的 API 令牌:
    • 选择获取 API 令牌。
    • 审查预填信息。
    • 选择继续到摘要。
    • 选择创建令牌。
    • 复制令牌值以备后用。
  5. 获取您的账户 ID:
    • 回到使用 Workers AI API 的屏幕(您最初的标签页)。
    • 在获取账户 ID 下,复制账户 ID 的值。
    • 如果您选择创建一个 API 令牌而不使用模板,该令牌将需要 Workers AI - 读取 和 Workers AI - 编辑 的权限。

代码实现

安装必要的包

pip install openai r2client httpx

导入相应的模块

import httpx
import base64
from r2client.R2Client import R2Client as r2
import tempfile
import datetime
import os
from openai import OpenAI

写一个 Python 类实现数据共享

class WorkerImage():
def __init__(self, account_id, api_token, r2_access_key, r2_secret_key, r2_bucket_name, r2_public_link):
"""
Parameters:
account_id (str): cloudflare account id
api_token (str): cloudflare api token
r2_access_key (str): r2 access key
r2_secret_key (str): r2 secret key
r2_bucket_name (str): the name of the r2 bucket
r2_public_link (str): the link to access the r2 bucket
"""
self.account_id = account_id
self.api_token = api_token
self.endpoint = (
f"https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/run/@cf/black-forest-labs/flux-1-schnell"
)
self.headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json",
}
self.r2_client = r2(
access_key=r2_access_key,
secret_key=r2_secret_key,
endpoint=f"https://{account_id}.r2.cloudflarestorage.com",
)
self.bucket_name = r2_bucket_name
self.link = r2_public_link

def _get_flux_image_data(self, prompt, num_steps):
payload = {
"prompt": prompt,
"num_steps": num_steps
}
response = httpx.post(
self.endpoint, headers=self.headers, json=payload)
if response.status_code == 400:
# raise error
return None
else:
image_data = base64.b64decode(response.json()['result']['image'])
return image_data

def _save_image_to_tmp_file(self, image_data):
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as f:
f.write(image_data)
temp_file_path = f.name
return temp_file_path

def get_translate_promt(self, prompt):
flux_system_prompt = """
你是一个基于Flux.1模型的提示词生成机器人。根据用户的需求,自动生成符合Flux.1格式的绘画提示词。虽然你可以参考提供的模板来学习提示词结构和规律,但你必须具备灵活性来应对各种不同需求。最终输出应仅限提示词,无需任何其他解释或信息。你的回答必须全部使用英语进行回复我!

### **提示词生成逻辑**:

1. **需求解析**:从用户的描述中提取关键信息,包括:
- 角色:外貌、动作、表情等。
- 场景:环境、光线、天气等。
- 风格:艺术风格、情感氛围、配色等。
- 其他元素:特定物品、背景或特效。

2. **提示词结构规律**:
- **简洁、精确且具象**:提示词需要简单、清晰地描述核心对象,并包含足够细节以引导生成出符合需求的图像。
- **灵活多样**:参考下列模板和已有示例,但需根据具体需求生成多样化的提示词,避免固定化或过于依赖模板。
- **符合Flux.1风格的描述**:提示词必须遵循Flux.1的要求,尽量包含艺术风格、视觉效果、情感氛围的描述,使用与Flux.1模型生成相符的关键词和描述模式。

3. **仅供你参考和学习的几种场景提示词**(你需要学习并灵活调整,"[ ]"中内容视用户问题而定):
- **角色表情集**:
场景说明:适合动画或漫画创作者为角色设计多样的表情。这些提示词可以生成展示同一角色在不同情绪下的表情集,涵盖快乐、悲伤、愤怒等多种情感。

提示词:An anime [SUBJECT], animated expression reference sheet, character design, reference sheet, turnaround, lofi style, soft colors, gentle natural linework, key art, range of emotions, happy sad mad scared nervous embarrassed confused neutral, hand drawn, award winning anime, fully clothed

[SUBJECT] character, animation expression reference sheet with several good animation expressions featuring the same character in each one, showing different faces from the same person in a grid pattern: happy sad mad scared nervous embarrassed confused neutral, super minimalist cartoon style flat muted kawaii pastel color palette, soft dreamy backgrounds, cute round character designs, minimalist facial features, retro-futuristic elements, kawaii style, space themes, gentle line work, slightly muted tones, simple geometric shapes, subtle gradients, oversized clothing on characters, whimsical, soft puffy art, pastels, watercolor

- **全角度角色视图**:
场景说明:当需要从现有角色设计中生成不同角度的全身图时,如正面、侧面和背面,适用于角色设计细化或动画建模。

提示词:A character sheet of [SUBJECT] in different poses and angles, including front view, side view, and back view

- **80 年代复古风格**:
场景说明:适合希望创造 80 年代复古风格照片效果的艺术家或设计师。这些提示词可以生成带有怀旧感的模糊宝丽来风格照片。

提示词:blurry polaroid of [a simple description of the scene], 1980s.

- **智能手机内部展示**:
场景说明:适合需要展示智能手机等产品设计的科技博客作者或产品设计师。这些提示词帮助生成展示手机外观和屏幕内容的图像。

提示词:a iphone product image showing the iphone standing and inside the screen the image is shown

- **双重曝光效果**:
场景说明:适合摄影师或视觉艺术家通过双重曝光技术创造深度和情感表达的艺术作品。

提示词:[Abstract style waterfalls, wildlife] inside the silhouette of a [man]’s head that is a double exposure photograph . Non-representational, colors and shapes, expression of feelings, imaginative, highly detailed

- **高质感电影海报**:
场景说明:适合需要为电影创建引人注目海报的电影宣传或平面设计师。

提示词:A digital illustration of a movie poster titled [‘Sad Sax: Fury Toad’], [Mad Max] parody poster, featuring [a saxophone-playing toad in a post-apocalyptic desert, with a customized car made of musical instruments], in the background, [a wasteland with other musical vehicle chases], movie title in [a gritty, bold font, dusty and intense color palette].

- **镜面自拍效果**:
场景说明:适合想要捕捉日常生活瞬间的摄影师或社交媒体用户。

提示词:Phone photo: A woman stands in front of a mirror, capturing a selfie. The image quality is grainy, with a slight blur softening the details. The lighting is dim, casting shadows that obscure her features. [The room is cluttered, with clothes strewn across the bed and an unmade blanket. Her expression is casual, full of concentration], while the old iPhone struggles to focus, giving the photo an authentic, unpolished feel. The mirror shows smudges and fingerprints, adding to the raw, everyday atmosphere of the scene.

- **像素艺术创作**:
场景说明:适合像素艺术爱好者或复古游戏开发者创造或复刻经典像素风格图像。

提示词:[Anything you want] pixel art style, pixels, pixel art

- **以上部分场景仅供你学习,一定要学会灵活变通,以适应任何绘画需求**:

4. **Flux.1提示词要点总结**:
- **简洁精准的主体描述**:明确图像中核心对象的身份或场景。
- **风格和情感氛围的具体描述**:确保提示词包含艺术风格、光线、配色、以及图像的氛围等信息。
- **动态与细节的补充**:提示词可包括场景中的动作、情绪、或光影效果等重要细节。
- **其他更多规律请自己寻找**
---

**问答案例1**:
**用户输入**:一个80年代复古风格的照片。
**你的输出**:A blurry polaroid of a 1980s living room, with vintage furniture, soft pastel tones, and a nostalgic, grainy texture, The sunlight filters through old curtains, casting long, warm shadows on the wooden floor, 1980s,

**问答案例2**:
**用户输入**:一个赛博朋克风格的夜晚城市背景
**你的输出**:A futuristic cityscape at night, in a cyberpunk style, with neon lights reflecting off wet streets, towering skyscrapers, and a glowing, high-tech atmosphere. Dark shadows contrast with vibrant neon signs, creating a dramatic, dystopian mood
"""
client = OpenAI(
# This is the default and can be omitted
api_key=self.api_token,
base_url=f"https://api.cloudflare.com/client/v4/accounts/{self.account_id}/ai/v1",
max_retries=5,
)
chat_completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": flux_system_prompt,
},
{
"role": "user",
"content": prompt,
}
],
model="@cf/meta/llama-3.1-70b-instruct",
)
return chat_completion.choices[0].message.content

def get_image(self, prompt, num_steps):
image_data = self._get_flux_image_data(prompt, num_steps)
if image_data:
local_file = self._save_image_to_tmp_file(image_data)
# delete local file
# get date time as newfile name
newfilename = f"{datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.png"
self.r2_client.upload_file(
self.bucket_name, local_file, newfilename)
os.remove(local_file)
return f"{self.link}/{newfilename}"
else:
print("image data is None,please check your inputs")
return None

使用方法

首先初始化类:

work = WorkerImage(account_id, api_token, r2_access_key, r2_secret_key, r2_bucket_name, r2_public_link)

注意,我们要把准备工作里获取的这些值填入 WorkerImage 类中来初始化它。

  • account_id:CloudFlare 账户 ID
  • api_token:CloudFlare Worker 的 API token
  • r2_access_key:CloudFlare R2 的 S3 access id
  • r2_secret_key:CloudFlare R2 的 S3 access key
  • r2_bucket_name:CloudFlare R2 的 S3 存储桶名(你自己手动创建的)
  • r2_public_link:CloudFlare R2 的访问链接,如果你设置了自定义域可以选择你自己的或者它提供的 dev 结尾的域名

然后,我们首先获取翻译后的提示词,调用:

newprompt = worker.get_translate_promt(prompt="一个80年代复古风格的照片,一个男孩手里拿着一罐可乐站在长城上看向镜头.")
print(newprompt)

##a blurry polaroid photograph of a young boy standing on the Great Wall of China, holding a can of soda, with a curious, blissful expression on his face, wearing a red hat, and a backpack, set against the rugged, ancient stones, and the misty, mountains in the background, soft pastel tones, warm, nostalgic lighting, with a subtle, retro film grain, taken in the 1980s.

下一步则把这个提示词输入到画图程序中即可:

url = worker.get_image(prompt=newprompt, num_steps=8)
print(url)
image

总结

我们这个类其实就是一个综合性的管道,首先调用 WorkerAI 的文本生成大模型,将用户输入的中文提示词翻译为英文,并美化增加细节。然后我们将生成的提示词给 Flux 大模型来画图即可。通过这种方式,我们可以轻松地生成并上传图片,同时支持中文提示词。 🎨✨

Bonus time

我将上述代码部署到了我自己的网站,现在你可以通过我的网站来体验该过程:

完整的代码也可以通过谷歌的colab访问:

评论