当前位置:AIGC资讯 > AIGC > 正文

Datawhale AI夏令营第四期 AIGC方向 task02 初学者笔记

一、Prompt工程介绍:
1、概念:

Prompt工程,也称为提示工程或指令工程,是在自然语言处理(NLP)领域中一种重要的技术和方法。它主要用于指导预训练的大规模语言模型(Large Language Models, LLMs)生成高质量、准确且有针对性的输出。通过设计、实验和优化输入提示词(Prompt),Prompt工程能够引导预训练语言模型生成所需的响应或完成特定任务。

2、构成要素:
引导语或指示语:明确告诉模型需要完成什么样的任务。

下文信息:提供必要的背景知识,帮助模型更好地理解问题。

任务描述:明确地描述期望模型执行的具体任务。

输出格式指示:如果需要特定格式的输出,需要在Prompt中指明。

角色设定:为模型定义一个角色,以缩小问题范围并减少歧义。

3、应用:
指导模型行为:通过精确的Prompt,可以明确地告诉模型需要执行什么任务,比如回答问题、创作故事、提供建议等。

提高输出内容准确性:精心设计的Prompt可以帮助模型生成更准确、相关度更高的内容。

减少输出内容偏差:通过提供适当的指导,可以减少模型可能产生的偏见或错误信息。

规定输出格式:对于需要特定格式的输出,如表格、列表、段落等,可通过Prompt指定输出格式。

促进创造性应用:规范的Prompt可以激发模型创造力,生成新颖的想法、故事或艺术作品。

灵活调整:通过修改Prompt,可以在不改变模型本身的情况下调整其输出,从而实现快速迭代和测试。

二、代码展示:

!pip install simple-aesthetics-predictor

!pip install -v -e data-juicer

!pip uninstall pytorch-lightning -y
!pip install peft lightning pandas torchvision

!pip install -e DiffSynth-Studio

from modelscope.msdatasets import MsDataset

ds = MsDataset.load(
    'AI-ModelScope/lowres_anime',
    subset_name='default',
    split='train',
    cache_dir="/mnt/workspace/kolors/data"
)

import json, os
from data_juicer.utils.mm_utils import SpecialTokens
from tqdm import tqdm


os.makedirs("./data/lora_dataset/train", exist_ok=True)
os.makedirs("./data/data-juicer/input", exist_ok=True)
with open("./data/data-juicer/input/metadata.jsonl", "w") as f:
    for data_id, data in enumerate(tqdm(ds)):
        image = data["image"].convert("RGB")
        image.save(f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg")
        metadata = {"text": "二次元", "image": [f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg"]}
        f.write(json.dumps(metadata))
        f.write("\n")

data_juicer_config = """
# global parameters
project_name: 'data-process'
dataset_path: './data/data-juicer/input/metadata.jsonl'  # path to your dataset directory or file
np: 4  # number of subprocess to process your dataset

text_keys: 'text'
image_key: 'image'
image_special_token: '<__dj__image>'

export_path: './data/data-juicer/output/result.jsonl'

# process schedule
# a list of several process operators with their arguments
process:
    - image_shape_filter:
        min_width: 1024
        min_height: 1024
        any_or_all: any
    - image_aspect_ratio_filter:
        min_ratio: 0.5
        max_ratio: 2.0
        any_or_all: any
"""
with open("data/data-juicer/data_juicer_config.yaml", "w") as file:
    file.write(data_juicer_config.strip())

!dj-process --config data/data-juicer/data_juicer_config.yaml

import pandas as pd
import os, json
from PIL import Image
from tqdm import tqdm


texts, file_names = [], []
os.makedirs("./data/data-juicer/output/images", exist_ok=True)
with open("./data/data-juicer/output/result.jsonl", "r") as f:
    for line in tqdm(f):
        metadata = json.loads(line)
        texts.append(metadata["text"])
        file_names.append(metadata["image"][0])

df = pd.DataFrame({"text": texts, "file_name": file_names})
df.to_csv("./data/data-juicer/output/result.csv", index=False)

df

from transformers import CLIPProcessor, CLIPModel
import torch

model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

images = [Image.open(img_path) for img_path in df["file_name"]]
inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True)

outputs = model(**inputs)
logits_per_image = outputs.logits_per_image  # this is the image-text similarity score
probs = logits_per_image.softmax(dim=1)  # we can take the softmax to get the probabilities

probs

from torch.utils.data import Dataset, DataLoader

class CustomDataset(Dataset):
    def __init__(self, df, processor):
        self.texts = df["text"].tolist()
        self.images = [Image.open(img_path) for img_path in df["file_name"]]
        self.processor = processor

    def __len__(self):
        return len(self.texts)

    def __getitem__(self, idx):
        inputs = self.processor(text=self.texts[idx], images=self.images[idx], return_tensors="pt", padding=True)
        return inputs

dataset = CustomDataset(df, processor)
dataloader = DataLoader(dataset, batch_size=8)

for batch in dataloader:
    outputs = model(**batch)
    logits_per_image = outputs.logits_per_image
    probs = logits_per_image.softmax(dim=1)
    print(probs)

import torch
from diffusers import StableDiffusionPipeline

torch.manual_seed(1)
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16)
pipe = pipe.to("cuda")

prompt = "二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒"
negative_prompt = "丑陋、变形、嘈杂、模糊、低对比度"
guidance_scale = 4
num_inference_steps = 50

image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    guidance_scale=guidance_scale,
    num_inference_steps=num_inference_steps,
    height=1024,
    width=1024,
).images[0]

image.save("example_image.png")
image

from PIL import Image

torch.manual_seed(1)
image = pipe(
    prompt="二次元,日系动漫,演唱会的观众席,人山人海,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,舞台上衣着华丽的歌星们在唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("1.jpg")

torch.manual_seed(1)
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,露出憧憬的神情",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("2.jpg")

torch.manual_seed(2)
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,露出憧憬的神情",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("3.jpg")

torch.manual_seed(5)
image = pipe(
    prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙,对着流星许愿,闭着眼睛,十指交叉,侧面",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,扭曲的手指,多余的手指",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("4.jpg")

torch.manual_seed(0)
image = pipe(
    prompt="二次元,一个紫色中等长度头发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("5.jpg")

torch.manual_seed(1)
image = pipe(
    prompt="二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("6.jpg")

torch.manual_seed(7)
image = pipe(
    prompt="二次元,紫色长发少女,穿着黑色连衣裙,试衣间,心情忐忑",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("7.jpg")

torch.manual_seed(0)
image = pipe(
    prompt="二次元,紫色长发少女,穿着黑色礼服,连衣裙,在台上唱歌",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("8.jpg")

import numpy as np
from PIL import Image


images = [np.array(Image.open(f"{i}.jpg")) for i in range(1, 9)]
image = np.concatenate([
    np.concatenate(images[0:2], axis=1),
    np.concatenate(images[2:4], axis=1),
    np.concatenate(images[4:6], axis=1),
    np.concatenate(images[6:8], axis=1),
], axis=0)
image = Image.fromarray(image).resize((1024, 2048))
image

三、代码分析:
1、数据处理:

数据加载与预处理:

首先,使用modelscope.msdatasets加载了一个名为AI-ModelScope/lowres_anime的数据集,这是一个二次元低分辨率动漫图像的数据集。接着,通过遍历数据集中的每个样本,将图像转换为RGB格式并保存到指定路径。同时,为每个图像生成一个包含文本("二次元")和图像路径的元数据文件metadata.jsonl。

数据清洗与过滤:

使用data-juicer工具(通过dj-process命令)对图像数据进行进一步处理,包括形状过滤和长宽比过滤,以确保图像满足一定的质量要求。处理后的结果保存在result.jsonl文件中,并转换成CSV格式以便于后续操作。

2、图像-文本相似度分析(使用CLIP模型):
加载预训练的CLIP模型(CLIPModel.from_pretrained("openai/clip-vit-base-patch32"))和对应的处理器(CLIPProcessor)。将清洗后的图像和对应的文本("二次元")作为输入,通过CLIP模型计算图像-文本的相似度得分。使用CustomDataset和DataLoader将数据和模型整合到PyTorch的数据加载流程中,以便进行批量处理。

3、图像生成(使用StableDiffusionPipeline):
加载预训练的StableDiffusion模型(StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4")),并配置到CUDA上进行加速。使用不同的prompt(包含详细的描述信息)和negative_prompt(排除不希望出现的元素)来指导模型生成图像。通过调整cfg_scale(引导强度)、num_inference_steps(推理步数)等参数来控制生成图像的质量和细节。将生成的图像保存到本地文件中,并进行展示或进一步处理。

四、实践:
1、更换提示词:


2、操作过程具体看task 01;

3、生成图片展示:

总结

### 文章总结
#### 一、Prompt工程介绍
**1. 概念**
- **Prompt工程**(也称为提示工程或指令工程)是自然语言处理(NLP)中的一种技术方法,用于指导预训练的大规模语言模型(LLMs)生成高质量、准确且有针对性的输出。通过精心设计、实验和优化输入提示词(Prompt),该技术能够引导模型执行特定任务。
**2. 构成要素**
- **引导语或指示语**:明确告诉模型任务要求。
- **下文信息**:提供必要背景知识,帮助模型理解问题。
- **任务描述**:详细阐述期望模型执行的具体任务。
- **输出格式指示**:如果需要特定格式的输出,需在Prompt中指定。
- **角色设定**:为模型定义角色,缩小问题范围并减少歧义。
**3. 应用**
- **指导模型行为**:精确控制模型任务执行,如回答问题、创作故事等。
- **提高输出准确性**:优化Prompt设计以提升内容的准确度和相关性。
- **减少偏差**:通过适当指导减少模型偏见和错误信息。
- **规定输出格式**:通过Prompt指定输出格式如表格、列表等。
- **促进创造性**:规范的Prompt激发模型创作能力。
- **灵活调整**:不改变模型本身,通过修改Prompt快速迭代和测试输出。
#### 二、代码展示
代码展示部分包括数据处理、图像-文本相似度分析(使用CLIP模型)、图像生成(使用StableDiffusionPipeline)。
- **数据处理**:使用`modelscope.msdatasets`加载数据集,对数据进行遍历、清洗与过滤,并保存到指定路径和文件格式。
- **图像-文本相似度分析**:利用CLIP模型计算图像与其描述文本("二次元")的相似度得分,利用`DataLoader`进行批量处理。
- **图像生成**:加载StableDiffusion模型,通过调整不同的prompt和negative_prompt,以及配置参数如引导强度和推理步数,生成高质量的二次元图像,并保存展示。
#### 三、代码分析
**1. 数据处理**
- 数据集加载与预处理:加载动漫图像数据集,转换并保存图像,生成元数据文件。
- 数据过滤:使用data-juicer工具进行图像形状和长宽比过滤,确保数据质量。
**2. 图像-文本相似度分析**
- 加载并使用CLIP模型,计算图像与文本描述("二次元")之间的相似度得分。
- 使用自定义数据集和`DataLoader`进行批量处理。
**3. 图像生成**
- 加载并配置StableDiffusion模型,使用CUDA加速生成图像。
- 通过精确控制的Prompt和negative_prompt引导模型生成多样化的二次元图像,调整参数优化图像质量。
#### 四、实践
建议通过**更换不同的提示词**(Prompt)来观察并体验图像生成的多样性和灵活性。具体操作可参考任务01中的详细步骤。生成的图片可以进一步展示或用于其他分析。

更新时间 2024-08-18