一、认识通义千问
1、通义千问的自我介绍
Prompt1:通义千问,请介绍一下自己。
回答效果不是很好,重新调调整提示词
Prompt2:通义千问,请介绍一下自己,并讲述一下自己有什么能力。
可以看到,这次的回答相比较前面的回答详细了许多。然后,可以聚焦到知识问答,让通义千问回答的更详细一些。
Prompt3:通义千问,请详细介绍一下你的“知识问答”的能力。
二、利用通义千问辅助阅读代码
首先,将baseline1的代码整理为一段代码:
!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、分析代码的主体结构
Prompt1
你是一个优秀的python开发工程师,现在我们需要你帮我们分析这个代码的主体框架,你需要把代码按照工作流分成几部分,用中文回答我的问题。{此处替换前面的代码}
返回结果
这段代码可以分为以下几个主要的工作流程部分:
1. 环境设置与依赖安装:
- 安装必要的Python包,如`simple-aesthetics-predictor`, `data-juicer`, `peft`, `lightning`, `pandas`, `torchvision`, `DiffSynth-Studio`。
- 卸载`pytorch-lightning`并重新安装。
2. 数据集加载与处理:
- 从ModelScope加载`lowres_anime`数据集。
- 遍历数据集,将图像转换为RGB格式并保存到磁盘,同时创建一个JSONL文件存储每张图片的路径和对应的描述文本。
3. 数据过滤与转换:
- 创建`data_juicer`配置文件,用于定义数据处理规则,包括图像尺寸过滤和宽高比过滤。
- 使用`data_juicer`工具处理数据,应用过滤器,并输出处理后的结果。
4. 数据整理与特征提取:
- 将处理后的数据读取到Pandas DataFrame中,方便后续操作。
- 利用CLIP模型(Contrastive Language-Image Pre-training)计算图像和文本的相似度分数。
5. 自定义数据集与DataLoader:
- 创建一个自定义PyTorch数据集`CustomDataset`,用于封装图像和文本数据。
- 构建`DataLoader`以便于批处理和数据加载。
6. 图像生成:
- 使用`StableDiffusionPipeline`从`diffusers`库生成图像,根据给定的提示和负面提示生成二次元风格的图像。
- 保存生成的图像到磁盘,并进行多次尝试以生成不同场景下的图像。
7. 图像拼接:
- 最后,将生成的图像按行和列拼接成一个大的图像,并调整大小,以方便展示或进一步处理。
整个流程涉及数据集的加载、预处理、特征提取、自定义数据集构建、图像生成以及最终的图像拼接,覆盖了从数据处理到深度学习模型应用的完整过程。
可以看到,统一千问有较强的代码理解能力,概括了代码不同功能模块。
2、逐行解释代码
Prompt2
你是一个优秀的python开发工程师,现在我们需要你帮我们逐行分析这个代码,并返回注释后的代码清单。用中文回答我的问题。{此处替换前面的代码}
返回结果
以下是带有更详细注释的代码清单:
# 使用pip命令行工具安装simple-aesthetics-predictor库
!pip install simple-aesthetics-predictor
# 以可编辑模式安装data-juicer库及其依赖项,并在安装过程中显示详细输出
!pip install -v -e data-juicer
# 卸载pytorch-lightning库,使用-y参数确认卸载而无需交互式确认
!pip uninstall pytorch-lightning -y
# 安装peft(用于微调模型)、lightning(PyTorch Lightning库)、pandas(数据分析库)和torchvision(计算机视觉库)等库
!pip install peft lightning pandas torchvision
# 再次以可编辑模式安装DiffSynth-Studio库,这通常意味着从本地文件系统或版本控制系统安装
!pip install -e DiffSynth-Studio
# 导入ModelScope的数据集模块,用于加载和管理数据集
from modelscope.msdatasets import MsDataset
# 加载名为'AI-ModelScope/lowres_anime'的数据集,选择默认子集的训练数据,缓存目录设置为"/mnt/workspace/kolors/data"
ds = MsDataset.load(
'AI-ModelScope/lowres_anime',
subset_name='default',
split='train',
cache_dir="/mnt/workspace/kolors/data"
)
# 导入json模块,用于处理JSON数据;os模块,用于操作系统相关功能;SpecialTokens类,可能用于标记特殊符号;tqdm库,用于显示进度条
import json, os
from data_juicer.utils.mm_utils import SpecialTokens
from tqdm import tqdm
# 创建训练图像存储目录,如果目录已经存在,则exist_ok=True参数确保不会抛出错误
os.makedirs("./data/lora_dataset/train", exist_ok=True)
# 创建data-juicer输入数据目录,同样如果目录存在则不会引发异常
os.makedirs("./data/data-juicer/input", exist_ok=True)
# 打开"data/data-juicer/input/metadata.jsonl"文件以写入模式,准备记录元数据
with open("./data/data-juicer/input/metadata.jsonl", "w") as f:
# 遍历数据集中的每一个元素,使用tqdm显示进度条
for data_id, data in enumerate(tqdm(ds)):
# 将图像转换为RGB颜色模式,这是许多图像处理库的常用要求
image = data["image"].convert("RGB")
# 将图像保存到指定目录下,文件名为数据ID对应的.jpg格式
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"]}
# 将元数据字典转换为JSON字符串,写入文件,每条数据后追加换行符
f.write(json.dumps(metadata))
f.write("\n")
# 定义一个YAML格式的字符串,作为data-juicer的数据处理配置文件
data_juicer_config = """
# 全局参数
project_name: 'data-process'
dataset_path: './data/data-juicer/input/metadata.jsonl' # 数据集文件路径
np: 4 # 处理数据集的子进程数量
text_keys: 'text' # 数据集中包含文本信息的键名
image_key: 'image' # 数据集中包含图像信息的键名
image_special_token: '<__dj__image>' # 特殊标记,用于标识图像
export_path: './data/data-juicer/output/result.jsonl' # 处理后的数据输出文件路径
# 处理调度,定义一系列过滤和处理操作
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
"""
# 将配置字符串写入"data/data-juicer/data_juicer_config.yaml"文件中
with open("data/data-juicer/data_juicer_config.yaml", "w") as file:
file.write(data_juicer_config.strip())
# 调用dj-process命令,使用上述配置文件来处理数据集
!dj-process --config data/data-juicer/data_juicer_config.yaml
# 导入pandas库,用于数据处理和分析;再次导入os和json模块;导入PIL库的Image模块,用于图像处理
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)
# 打开"data/data-juicer/output/result.jsonl"文件,读取处理后的数据
with open("./data/data-juicer/output/result.jsonl", "r") as f:
# 遍历文件的每一行,使用tqdm显示进度条
for line in tqdm(f):
# 解析每一行的JSON数据,将其转换为Python字典
metadata = json.loads(line)
# 将文本信息添加到texts列表中
texts.append(metadata["text"])
# 将图像文件路径添加到file_names列表中
file_names.append(metadata["image"][0])
# 使用texts和file_names列表创建一个DataFrame,列名分别为"text"和"file_name"
df = pd.DataFrame({"text": texts, "file_name": file_names})
# 将DataFrame保存为CSV文件,不保存索引
df.to_csv("./data/data-juicer/output/result.csv", index=False)
# 显示DataFrame的内容
df
# 导入CLIP模型和处理器类
from transformers import CLIPProcessor, CLIPModel
import torch
# 加载预训练的CLIP模型,使用"openai/clip-vit-base-patch32"版本
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
# 加载预训练的CLIP处理器,用于数据预处理,同样使用"openai/clip-vit-base-patch32"版本
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
# 从DataFrame中读取图像文件路径,打开图像并存储为列表
images = [Image.open(img_path) for img_path in df["file_name"]]
# 使用处理器预处理图像和文本数据,返回PyTorch的张量,设置return_tensors参数为"pt"表示返回PyTorch的Tensor类型
inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True)
# 将预处理后的数据送入CLIP模型,获取模型输出
outputs = model(**inputs)
# 获取图像和文本之间的相似度得分
logits_per_image = outputs.logits_per_image
# 计算图像和文本匹配的概率分布
probs = logits_per_image.softmax(dim=1)
# 显示计算出的概率分布
probs
# 导入PyTorch的Dataset和DataLoader类,用于构建数据集和数据加载器
from torch.utils.data import Dataset, DataLoader
# 定义自定义数据集类CustomDataset,继承自Dataset类
class CustomDataset(Dataset):
# 初始化方法,接收DataFrame和处理器作为参数
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
# 使用CustomDataset类创建数据集实例
dataset = CustomDataset(df, processor)
# 创建数据加载器,用于在训练时批量加载数据,设置批处理大小为8
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)
# 导入torch库,用于生成随机种子
import torch
# 设置随机种子,确保生成结果的可重复性
torch.manual_seed(1)
# 加载预训练的Stable Diffusion模型,使用"CompVis/stable-diffusion-v-1-4"版本,使用半精度浮点数(float16)
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16)
# 将模型移动到CUDA设备上,以便在GPU上运行
pipe = pipe.to("cuda")
# 设置生成图像的提示(prompt),负面提示(negative prompt),指导尺度(guidance scale),推理步数(inference steps)等参数
prompt = "二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒"
negative_prompt = "丑陋、变形、嘈杂、模糊、低对比度"
guidance_scale = 4
num_inference_steps = 50
# 使用Stable Diffusion模型生成图像,参数包括prompt、negative_prompt、guidance_scale、num_inference_steps等
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
# 使用相同的逻辑生成多个图像,每次使用不同的prompt和文件名保存图像
# 下面的代码重复了上述过程,生成多个图像并保存到磁盘
# 导入numpy库,用于数组操作;再次导入PIL库的Image模块,用于图像处理
import numpy as np
from PIL import Image
# 加载所有生成的图像,并将它们转换为NumPy数组形式
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)
# 将拼接后的图像调整大小为1024x2048像素
image = Image.fromarray(image).resize((1024, 2048))
# 显示最终拼接后的图像
image
三、实战演练——基于话剧的连环画制作
1、数据准备
Prompt
尺寸1024*768 CFG=4.08 采样步数30
Positive Prompt:
1、沙漠,卡通风格,两人,坠毁的飞机,一名飞行员穿着黑色飞行服和黑色手套,一个小王子有黄色头发,穿着红色披肩和绿色长衫,两人正对,飞行员在沙地上画画
2、卡通风格,在光秃秃的小行星上,一个小王子有黄色头发,穿着红色披肩和绿色长衫,除了一朵玫瑰花盛开,别无他物
3、卡通风格,在光秃秃的小行星上,一个小王子有黄色头发,穿着红色披肩和绿色长衫,一朵玫瑰花盛开,玫瑰花说谎,小王子感到被欺骗
4、卡通风格,在小行星上,两个人,一个小王子有黄色头发,穿着红色披肩和绿色长衫,脸上露出不安。一个酒鬼穿着破烂的灰色衣服,拿着酒瓶,酩酊大醉
5、卡通风格,在沙漠中,一个小王子有黄色头发,穿着红色披肩和绿色长衫,一条蛇在地上说话,远处的高山上有一座玫瑰庄园
6、卡通风格,在玫瑰园中,一个小王子有黄色头发,穿着红色披肩和绿色长衫,与一只狐狸说话,王子感到豁然开朗
7、沙漠,卡通风格,两人,一个小王子有黄色头发,穿着红色披肩和绿色长衫,一名穿着黑色飞行服和黑色手套的飞行员,两人在一口井旁边休息,非常满足
8、沙漠,卡通风格,穿着黑色飞行服和黑色手套的飞行员,脸上很悲伤,一个小王子有黄色头发,穿着红色披肩和绿色长衫,被蛇咬了,躺在旁边的地上,脸上很安详
Negative Prompt:
统一为 模糊,低分辨率
结果展示