Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image Annotation Moderation and FLUX Model Integration #65

Merged
merged 53 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
2f6160e
adding blackforest labs models
dylanuys Aug 12, 2024
2adec09
temporarily disabling real image challenges to maximize data production
dylanuys Aug 12, 2024
c81a4a7
adding cpu offload
dylanuys Aug 12, 2024
b3b4f60
adding arg for flux generation
dylanuys Aug 12, 2024
aaaedd5
calling flux generation with new args in constants.py
dylanuys Aug 12, 2024
8af1cc6
pulling in latest from main
dylanuys Aug 20, 2024
e5e9f60
constants update for flux mirror gen
dylanuys Aug 20, 2024
fa19189
adding cache dir to model loads
dylanuys Aug 20, 2024
4bec465
temp notebooks for flux tests
dylanuys Aug 20, 2024
51d39f8
typo
dylanuys Aug 20, 2024
31ccd59
updating guidance_scale
dylanuys Aug 21, 2024
02dcea8
Added Meta's Llama-3.1-8B-Instruct model for annotation moderation.
benliang99 Aug 22, 2024
f6de46e
Upgraded BLIP2 model to 6.7B param version
benliang99 Aug 23, 2024
ddc06ad
Replaced Llama-3.1-8B-Instruct model with Unsloth's ungated version.
benliang99 Aug 23, 2024
e128200
Updated requirements with Unsloth model dependency.
benliang99 Aug 23, 2024
cf16da4
Clear image generation annotation models from GPU after generating im…
benliang99 Aug 24, 2024
bdb3693
Fixed usage of generation args, updated image generation helper funct…
benliang99 Aug 24, 2024
d6199a9
Added gpu-specific diffusion model loading for parallelization
benliang99 Sep 9, 2024
cd5b897
Fixed docstring indent
benliang99 Sep 9, 2024
aed5346
Added gpu specification for synthetic image generation
benliang99 Sep 9, 2024
160dd66
Added dataset gen GPU delegation shell script and SDXL to constants
benliang99 Sep 17, 2024
2f7fab5
Removed HF token
benliang99 Sep 17, 2024
7ea024d
Fixed specification of torch.dtype for SDXL
benliang99 Sep 17, 2024
56b2cec
Reformatting empty lines, added stress test script.
benliang99 Sep 18, 2024
46b2cdd
Added temporary stress testing prints
benliang99 Sep 18, 2024
f7ed8f3
Added all diffusion models and updated generate args
benliang99 Sep 18, 2024
585f42f
Added float16 tensor tflop specs metric
benliang99 Sep 19, 2024
3e5128f
Set default GPU for diffusion models to cuda if no gpu_id specified. …
benliang99 Sep 19, 2024
46fcaef
Merged with testnet
benliang99 Sep 19, 2024
c1e2ac9
Reverted merge
benliang99 Sep 19, 2024
75981ca
Merge branch 'main' into llm-annotation-moderation
benliang99 Sep 23, 2024
949df9b
Merged Main, Testnet into branch
benliang99 Sep 23, 2024
be629c4
Removed unnecessary imports
benliang99 Sep 23, 2024
b220f12
Added diffusion model verification/loading at the end of validator se…
benliang99 Sep 23, 2024
6285d92
Added validator model verification script for initial model download …
benliang99 Sep 23, 2024
8c51b22
Fixed typo.
benliang99 Sep 23, 2024
2fd800b
Added check for model presence in cache
benliang99 Sep 23, 2024
8e3c6bc
Reinstated necessary pipeline imports
benliang99 Sep 23, 2024
4cb39cc
PEP8 class spacing
benliang99 Sep 23, 2024
8ea2b54
Notebook cleanup.
benliang99 Sep 23, 2024
a4204f8
ImageAnnotationGenerator doc/class strings
benliang99 Sep 23, 2024
4aaf558
SyntheticImageGenerator docstring updates
benliang99 Sep 24, 2024
a90c2c6
Merge with testnet
benliang99 Oct 2, 2024
1c59491
Removed legacy (unused) directory
benliang99 Oct 2, 2024
b31b17c
Renamed and moved validator model verification to bitmind/validator/,…
benliang99 Oct 2, 2024
6cadbbd
Added validator-specific unit testing
benliang99 Oct 3, 2024
e817257
Added unit test for generating images. Added PEP8 docstrings.
benliang99 Oct 3, 2024
0625df5
Merge testnet into llm-annotation-moderation
benliang99 Oct 15, 2024
9b4c612
Correct WANDB_PROJECT constantexit
benliang99 Oct 15, 2024
fc1d817
Update setup fields
benliang99 Oct 15, 2024
17ee8f5
Fixed axon undefined
benliang99 Oct 15, 2024
fa90608
Added conditional cuda usage
benliang99 Oct 15, 2024
d2cf985
Merge remote-tracking branch 'origin/testnet' into llm-annotation-mod…
benliang99 Oct 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions autoupdate_validator_steps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
echo $CONDA_PREFIX
$CONDA_PREFIX/bin/pip install -e .
$CONDA_PREFIX/bin/python bitmind/download_data.py
$CONDA_PREFIX/bin/python verify_validator_models.py
benliang99 marked this conversation as resolved.
Show resolved Hide resolved
echo "Autoupdate steps complete :)"
46 changes: 41 additions & 5 deletions bitmind/constants.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import os
import torch


WANDB_PROJECT = 'bitmind-subnet'
WANDB_PROJECT = 'bitmind'
benliang99 marked this conversation as resolved.
Show resolved Hide resolved
WANDB_ENTITY = 'bitmindai'

DATASET_META = {
"real": [
{"path": "bitmind/open-images-v7", "create_splits": False},
benliang99 marked this conversation as resolved.
Show resolved Hide resolved
{"path": "bitmind/ffhq-256", "create_splits": False},
{"path": "bitmind/celeb-a-hq", "create_splits": False}
{"path": "bitmind/celeb-a-hq", "create_splits": False},
{"path": "bitmind/MS-COCO-unique-256", "create_splits": False}
],
"fake": [
{"path": "bitmind/realvis-xl", "create_splits": False},
Expand Down Expand Up @@ -39,19 +41,36 @@
{
"path": "stabilityai/stable-diffusion-xl-base-1.0",
"use_safetensors": True,
"torch_dtype": torch.float16,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

torch_dtype is no longer hardcoded, so it must be specified in the pipeline / DIFFUSER_ARGS.

"variant": "fp16",
"pipeline": "StableDiffusionXLPipeline"
},
{
"path": "SG161222/RealVisXL_V4.0",
"use_safetensors": True,
"torch_dtype": torch.float16,
"variant": "fp16",
"pipeline": "StableDiffusionXLPipeline"
},
{
"path": "Corcelio/mobius",
"use_safetensors": True,
"torch_dtype": torch.float16,
"pipeline": "StableDiffusionXLPipeline"
},
{
"path": 'black-forest-labs/FLUX.1-dev',
"use_safetensors": True,
"torch_dtype": torch.bfloat16,
"generate_args": {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguments decided based on experimental generation latencies.

"guidance_scale": 2,
"num_inference_steps": {"min": 50, "max": 125},
"generator": torch.Generator("cuda"),
benliang99 marked this conversation as resolved.
Show resolved Hide resolved
"height": [512, 768],
"width": [512, 768]
},
"enable_cpu_offload": False,
"pipeline": "FluxPipeline"
}
]
}
Expand All @@ -60,16 +79,30 @@

TARGET_IMAGE_SIZE = (256, 256)

PROMPT_TYPES = ('random', 'annotation')
PROMPT_TYPES = ('random', 'annotation', 'none')

PROMPT_GENERATOR_ARGS = {
m['model']: m for m in VALIDATOR_MODEL_META['prompt_generators']
}

PROMPT_GENERATOR_NAMES = list(PROMPT_GENERATOR_ARGS.keys())

# args for .from_pretrained
DIFFUSER_ARGS = {
m['path']: {k: v for k, v in m.items() if k != 'path' and k != 'pipeline'}
m['path']: {
k: v for k, v in m.items()
if k not in ('path', 'pipeline', 'generate_args', 'enable_cpu_offload')
} for m in VALIDATOR_MODEL_META['diffusers']
}

GENERATE_ARGS = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New field for generation arguments, which FLUX-1.dev can utilize.

m['path']: m['generate_args']
for m in VALIDATOR_MODEL_META['diffusers']
if 'generate_args' in m
}

DIFFUSER_CPU_OFFLOAD_ENABLED = {
m['path']: m.get('enable_cpu_offload', False)
for m in VALIDATOR_MODEL_META['diffusers']
}

Expand All @@ -79,4 +112,7 @@

DIFFUSER_NAMES = list(DIFFUSER_ARGS.keys())

IMAGE_ANNOTATION_MODEL = "Salesforce/blip2-opt-2.7b-coco"
IMAGE_ANNOTATION_MODEL = "Salesforce/blip2-opt-6.7b-coco"

TEXT_MODERATION_MODEL = "unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bit"
# "meta-llama/Meta-Llama-3.1-8B-Instruct"
Empty file removed bitmind/miner/__init__.py
Empty file.
13 changes: 6 additions & 7 deletions bitmind/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@
import base64
import torch

def b64_encode(image):
if isinstance(image, torch.Tensor):
image = transforms.ToPILImage()(image.cpu().detach())
image_bytes = BytesIO()
image.save(image_bytes, format="JPEG")
return base64.b64encode(image_bytes.getvalue())

def prepare_image_synapse(image: Image):
"""
Expand All @@ -43,7 +37,12 @@ def prepare_image_synapse(image: Image):
Returns:
ImageSynapse: An instance of ImageSynapse containing the encoded image and a default prediction value.
"""
b64_encoded_image = b64_encode(image)
if isinstance(image, torch.Tensor):
image = transforms.ToPILImage()(image.cpu().detach())

image_bytes = BytesIO()
image.save(image_bytes, format="JPEG")
b64_encoded_image = base64.b64encode(image_bytes.getvalue())
return ImageSynapse(image=b64_encoded_image)


Expand Down
76 changes: 0 additions & 76 deletions bitmind/synthetic_image_generation/combine_datasets.py

This file was deleted.

88 changes: 77 additions & 11 deletions bitmind/synthetic_image_generation/image_annotation_generator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Transformer models
from transformers import AutoProcessor, Blip2ForConditionalGeneration
from transformers import Blip2Processor, Blip2ForConditionalGeneration, pipeline

# Logging and progress handling
from transformers import logging as transformers_logging
Expand All @@ -14,28 +14,89 @@

from bitmind.image_dataset import ImageDataset
from bitmind.synthetic_image_generation.utils import image_utils
from bitmind.constants import HUGGINGFACE_CACHE_DIR

disable_progress_bar()

class ImageAnnotationGenerator:
benliang99 marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, model_name: str, device: str = 'auto'):
self.device = torch.device('cuda' if torch.cuda.is_available() and device == 'auto' else 'cpu')
def __init__(
self, model_name: str, text_moderation_model_name: str, device: str = 'auto',
apply_moderation: bool = True
):
self.device = torch.device(
'cuda' if torch.cuda.is_available() and device == 'auto' else 'cpu'
)

self.model_name = model_name
self.processor = AutoProcessor.from_pretrained(self.model_name)
self.processor = Blip2Processor.from_pretrained(
self.model_name, cache_dir=HUGGINGFACE_CACHE_DIR
)
self.model = None
self.load_model()

def load_model(self):
self.model = Blip2ForConditionalGeneration.from_pretrained(self.model_name, torch_dtype=torch.float16)

self.apply_moderation = apply_moderation
self.text_moderation_model_name = text_moderation_model_name
self.text_moderation_pipeline = None

def load_models(self):
bt.logging.info(f"Loading image annotation model {self.model_name}")
self.model = Blip2ForConditionalGeneration.from_pretrained(
self.model_name,
torch_dtype=torch.float16,
cache_dir=HUGGINGFACE_CACHE_DIR
)
self.model.to(self.device)
bt.logging.info(f"Loaded image annotation model {self.model_name}")
bt.logging.info(f"Loading annotation moderation model {self.text_moderation_model_name}...")
if self.apply_moderation:
self.text_moderation_pipeline = pipeline(
"text-generation",
model=self.text_moderation_model_name,
model_kwargs={"torch_dtype": torch.bfloat16},
device_map="auto"
)
bt.logging.info(f"Loaded annotation moderation model {self.text_moderation_model_name}.")

def clear_gpu(self):
bt.logging.debug(f"Clearing GPU memory after generating image annotation")
self.model.to('cpu')
del self.model
if self.text_moderation_pipeline:
self.text_moderation_pipeline = None
gc.collect()
torch.cuda.empty_cache()

def moderate_description(self, description: str, max_new_tokens: int = 80) -> str:
"""
Uses the text moderation pipeline to make the description more concise and neutral.
"""
messages = [
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[INST] and [/INST] tokens are used here to signify the beginning and end of instructions. Without them, the model repeats the prompt in its answer.

{
"role": "system",
"content": ("[INST]You always concisely rephrase given descriptions, eliminate redundancy, "
"and remove all specific references to individuals by name. You do not respond with"
"anything other than the revised description.[/INST]")
},
{
"role": "user",
"content": description
}
]
try:
moderated_text = self.text_moderation_pipeline(messages, max_new_tokens=max_new_tokens,
pad_token_id=self.text_moderation_pipeline.tokenizer.eos_token_id,
return_full_text=False)

if isinstance(moderated_text, list):
return moderated_text[0]['generated_text']
bt.logging.error("Failed to return moderated text.")
else:
bt.logging.error("Moderated text did not return a list.")

return description # Fallback to the original description if no suitable entry is found
except Exception as e:
bt.logging.error(f"An error occurred during moderation: {e}", exc_info=True)
return description # Return the original description as a fallback

def generate_description(self,
image: PIL.Image.Image,
verbose: bool = False,
Expand All @@ -56,8 +117,7 @@ def generate_description(self,
transformers_logging.set_verbosity_error()

description = ""
prompts = ["A picture of", "The setting is", "The background is", "The image type/style is"]

prompts = ["An image of", "The setting is", "The background is", "The image type/style is"]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced "A picture of" with "An image of" because I noticed qualitative improvements in my experiments. This makes sense because "picture" is more constrained than "Image" in my opinion. Could use further testing.

for i, prompt in enumerate(prompts):
description += prompt + ' '
inputs = self.processor(image, text=description, return_tensors="pt").to(self.device, torch.float16)
Expand All @@ -80,11 +140,17 @@ def generate_description(self,

if not verbose:
transformers_logging.set_verbosity_info()


if description.startswith(prompts[0]):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for the moderation model repeating the prompt in its response.

description = description[len(prompts[0]):]

# Remove any trailing spaces and ensure the description ends with a period
description = description.strip()
if not description.endswith('.'):
description += '.'
if self.apply_moderation:
moderated_description = self.moderate_description(description)
return moderated_description
return description

def generate_annotation(
Expand Down
Loading
Loading