JairoDanielMT's picture
Upload folder using huggingface_hub
4ef6c2b verified
Raw
History Blame Contribute Delete
7.4 kB
import sqlite3
import json
import os
import uuid
from typing import List, Dict, Any
from src.ontology.models import OntologyRecord
class DatasetCurator:
def __init__(self, db_path: str, output_dir: str):
self.db_path = db_path
self.output_dir = output_dir
self.nsfw_terms = set()
os.makedirs(output_dir, exist_ok=True)
def load_nsfw_terms(self):
"""Load NSFW terms from the database to use for classification."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
# Load from special_all and special_s_e
for table in ["special_all", "special_s_e"]:
cursor.execute(f"SELECT value FROM {table}")
for row in cursor.fetchall():
term = row[0].strip().lower()
if term:
self.nsfw_terms.add(term)
conn.close()
print(f"Loaded {len(self.nsfw_terms)} NSFW terms.")
def is_nsfw(self, text: str) -> bool:
"""Check if a string contains NSFW terms using word boundaries."""
if not text:
return False
text_lower = text.lower()
# For performance, we can do a quick word-set check first for single-word terms
import re
words = set(re.findall(r'\w+', text_lower))
if not words.isdisjoint(self.nsfw_terms):
return True
# Then check for multi-word terms (if any)
# For now, most seem to be single words or joined words.
# If we have multi-word terms, we'd need re.search with \b
for term in self.nsfw_terms:
if " " in term:
if re.search(rf"\b{re.escape(term)}\b", text_lower):
return True
return False
def process_table(self, table_name: str, category: str, canonical_col: str = "value"):
"""Process a standard table with 'id' and 'value' columns."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute(f"SELECT * FROM {table_name}")
rows = cursor.fetchall()
# Get column names
cursor.execute(f"PRAGMA table_info({table_name})")
cols = [col[1] for col in cursor.fetchall()]
records = []
for row in rows:
data = dict(zip(cols, row))
canonical = data[canonical_col]
# Basic normalization: strip and lowercase
canonical = canonical.strip().lower()
# Create OntologyRecord
record = OntologyRecord(
id=str(uuid.uuid4()),
canonical=canonical,
aliases=[], # We'll populate aliases later if needed
category=category,
source=f"db:{table_name}",
nsfw=self.is_nsfw(canonical),
synthetic=False,
confidence=1.0
)
records.append(record.model_dump())
conn.close()
return records
def process_characters(self):
"""Process the characters table which has a different schema."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
# We might want to join with franchises
query = """
SELECT c.id, c.name, c.core_tags, f.name as franchise
FROM characters c
LEFT JOIN franchises f ON c.franchise_id = f.id
"""
cursor.execute(query)
rows = cursor.fetchall()
records = []
for row in rows:
cid, name, core_tags, franchise = row
canonical = name
aliases = []
# Clean up canonical name: "Name from Franchise" -> "Name"
# or "Name (Variant)" -> "Name"
clean_name = canonical
if " from " in clean_name:
clean_name = clean_name.split(" from ")[0].strip()
if " (" in clean_name:
# Extract variant and add it to attributes or description later
# For now, just get the base name
clean_name = clean_name.split(" (")[0].strip()
if clean_name != canonical:
aliases.append(canonical) # Add the original as alias
canonical = clean_name
tags = []
if core_tags:
tags = [t.strip() for t in core_tags.split(",")]
# Ensure unique aliases and exclude canonical
aliases = list(set(a for a in aliases if a.lower() != canonical.lower()))
description = f"Character from {franchise}" if franchise else ""
metadata = {
"franchise": franchise,
"default_attributes": tags
}
record = OntologyRecord(
id=str(uuid.uuid4()),
canonical=canonical,
aliases=aliases,
category="character",
description=description,
tags=tags,
source="db:characters",
nsfw=self.is_nsfw(canonical) or self.is_nsfw(" ".join(aliases)),
synthetic=False,
confidence=1.0,
metadata=metadata
)
records.append(record.model_dump())
conn.close()
return records
def run(self):
self.load_nsfw_terms()
datasets = {
"characters.json": self.process_characters(),
"clothing.json": self.process_table("outfit", "clothing"),
"hairstyles.json": self.process_table("hairstyle", "hairstyle"),
"hair_colors.json": self.process_table("hair_color", "hair_color"),
"eye_colors.json": self.process_table("eyes", "eye_color"),
"scenes.json": self.process_table("scenario", "scene"),
"emotions.json": self.process_table("emotion", "emotion"),
"poses.json": self.process_table("pose", "pose"),
"accessories.json": self.process_table("extras", "accessory"),
"lighting.json": self.process_table("lighting", "lighting"),
"styles.json": self.process_table("style", "style"),
"effects.json": self.process_table("special_elements", "effect")
}
# Also process the special tables as entries themselves
datasets["nsfw_all.json"] = self.process_table("special_all", "special", "value")
datasets["nsfw_s_e.json"] = self.process_table("special_s_e", "special", "value")
# Save all
stats = {}
for filename, data in datasets.items():
file_path = os.path.join(self.output_dir, filename)
with open(file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
stats[filename] = len(data)
print("Dataset processing complete.")
print(json.dumps(stats, indent=2))
if __name__ == "__main__":
curator = DatasetCurator("fine_prompt_sdxl.db", "data/ontology")
curator.run()