Files

271 lines
9.9 KiB
Python

import spacy
import spacy.lang.en
import re
import random
import itertools
import emoji
import logging
import json
class AnyType(str):
def __ne__(self, __value: object) -> bool:
return False
any_typ = AnyType("*")
nlp = spacy.load("en_core_web_sm")
# List of words to remove from stop words list
remove_stop_word_tokens = [
'and', 'he', 'she', 'it', 'his',
'its', 'with', 'without', 'before', 'after', 'during', 'around', 'among',
'between', 'through', 'across', 'behind', 'below', 'beside', 'by', 'over',
'under', 'into', 'onto', 'upon', 'along', 'above', 'near', 'from',
'towards', 'to', 'up', 'down', 'in', 'on', 'off', 'out', 'at', 'of', 'not',
'no', 'none', 'never', 'neither', 'nor', 'only', 'just', 'who', 'whose',
'whom', 'what', 'where', 'any', 'all', 'each', 'every', 'either', 'both',
'all', 'both', 'another', 'such', 'some', 'few', 'several', 'many', 'much',
'most', 'more', 'less', 'eight', 'eleven', 'fifteen', 'fifty', 'five',
'forty', 'four', 'hundred', 'nine', 'one', 'six', 'sixty', 'ten', 'third',
'three', 'twelve', 'twenty', 'two', 'alone', 'against', 'down', "again",
"almost", "already", "always", "anyone", "anything", "anywhere", "around",
"back", "become", "becomes", "becoming", "beyond", "full", "further",
"get", "give", "go", "here", "hereafter", "hereby", "herein", "hereupon",
"mostly", "often", "once", "part", "put", "seem", "seemed", "seeming",
"seems", "take", "together", "top", "toward", "until", "used", "using",
"various", "via", "within", "about", "because", "but", "can",
"cannot", "could", "do", "does", "doing", "done", "even", "for", "if",
"is", "was", "were", "may", "might", "must", "or", "please", "really",
"should", "since", "so", "that", "these", "this", "those", "though",
"thus", "unless", "until", "while", "will", "would", "yet"
]
# Remove the words from the stop words list
for word in remove_stop_word_tokens:
if word in nlp.Defaults.stop_words:
nlp.Defaults.stop_words.remove(word)
if nlp.vocab[word].is_stop:
nlp.vocab[word].is_stop = False
# Print the remaining stop words
remaining_stop_words = list(nlp.Defaults.stop_words)
remaining_stop_words.sort()
print("TTools - Stop Words: " + ", ".join(remaining_stop_words))
class TToolsExtractJson:
"""
This class extracts and processes JSON objects from a given string,
randomizes the extracted values, and outputs them as a comma-separated string.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"input_string": ("STRING", {
"multiline": True
}),
"seed": ("INT", {
"default": 0,
"min": 0,
"max": 0xFFFFFFFFFFFFFFFF
}),
"max_length": ("INT", {
"default": 10,
"min": 0,
"max": 999999999
}),
"min_part_length": ("INT", {
"default": 10,
"min": 0,
"max": 999999999
}),
"max_part_length": ("INT", {
"default": 10,
"min": 0,
"max": 999999999
}),
"remove_stop_words": ("BOOLEAN", {
"forceInput": False
})
},
}
RETURN_TYPES = ("STRING", )
FUNCTION = "doit"
CATEGORY = "utils"
def remove_stop_words(self, text):
return ' '.join(token.text for token in nlp(text) if not token.is_stop)
def remove_emoji(self, text):
return ''.join(char for char in text if not emoji.is_emoji(char))
def extract_json_objects(self, text):
json_pattern = re.compile(r'\{[^\}]*\}', re.DOTALL)
json_objects = []
for json_str in json_pattern.findall(text):
if re.fullmatch(r'\{[^\}]*\}', json_str):
try:
json_objects.append(
json.loads(re.sub(r'\\[n"\\]', '', json_str)))
except json.JSONDecodeError:
print("Invalid JSON format, discarding entry: ", json_str)
return json_objects
def extract_values(self, json_objects):
return [
str(item) for obj in json_objects for k, v in obj.items()
for item in (v if isinstance(v, list) else [v])
]
def extract_and_process_json_from_string(self, text_content):
json_objects = self.extract_json_objects(text_content)
return self.extract_values(json_objects)
def doit(self,
input_string,
max_length=10,
min_part_length=14,
max_part_length=100,
seed=0,
remove_stop_words=False):
random.seed(seed)
input_string = input_string.lower()
#print("Initial input string: ", input_string)
values = self.extract_and_process_json_from_string(input_string)
replacements = [
('_', ' '),
('/', ' and '),
('\\', ' and '),
(':', ','),
('"', ','),
('.', ','),
('[', ','),
(']', ','),
('{', ','),
('}', ','),
('&', ' and '),
('+', ' and '),
('$', 'currency value of '),
('%', ' percent'),
('@', ' at '),
('#', ' number '),
('<', ' less than '),
('>', ' greater than '),
('=', ' equals '),
('*', ' '),
('\n', ','),
]
def apply_replacements(value):
for old, new in replacements:
value = value.replace(old, new)
return value
#Remove whitespace before after or multiple spaces within
values = [re.sub(r" {2,}", " ", value.strip()) for value in values]
values = sorted(set(values), key=len, reverse=True)
values = [apply_replacements(v) for v in values]
values = [re.sub(r" {2,}", " ", value.strip()) for value in values]
values = sorted(set(values), key=len, reverse=True)
values = sorted(set(
itertools.chain.from_iterable(v.split(',') for v in values)),
key=len,
reverse=True)
values = [re.sub(r" {2,}", " ", value.strip()) for value in values]
# print("Initial value count: ", len(values))
# print("Extracted values: ")
if remove_stop_words:
# print("Values before removing stop words: ")
values = [self.remove_stop_words(v) for v in values]
# print("Values after removing stop words: ")
# print("Value count after processing: ", len(values))
#sort values
values.sort(key=len, reverse=True)
# remove duplicate values
values = list(dict.fromkeys(values))
# print("Value count after removing duplicates: ", len(values))
# Sort the values by length
values.sort(key=len, reverse=False)
# filter values based on length and remove "and " from the beginning
values = [
value[4:] if value.startswith("and ") else value
for value in values
if min_part_length <= len(value) <= max_part_length
]
# print("Value count after filtering by length: ", len(values))
# Find the midpoint
midpoint = len(values) // 2
# Split the values into short and long
short_values = values[:midpoint]
long_values = values[midpoint:]
# Determine the number of values to select from each list
num_short = min(len(short_values), int(max_length * 0.8))
num_long = min(len(long_values), max_length - num_short)
# Randomly select values from each list
selected_short_values = random.sample(short_values, num_short)
selected_long_values = random.sample(long_values, num_long)
# Combine the selected values
selected_values = selected_short_values + selected_long_values
#sort values
values.sort(key=len, reverse=True)
# remove duplicate values
values = list(dict.fromkeys(values))
output_string = ", ".join(str(v) for v in selected_values)
# print("Final output string: ", output_string)
return (output_string, )
class TToolsSD3ResolutionSolver:
"""
Provides a resolution close to 1 megapixel with dimensions as multiples of 64.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"x": ("INT", {"display": "number", "default": 1024}),
"y": ("INT", {"display": "number", "default": 1024}),
"max_long_side": ("INT", {"display": "number", "default": 1280}),
"format": (["Portrait", "Landscape"], {"default": "Portrait"}),
"skip_if_mulof64": ("BOOLEAN", {"default": False}),
},
}
RETURN_TYPES = ("INT","INT",)
RETURN_NAMES = ("Width","Height",)
FUNCTION = "solve"
CATEGORY = "utils"
def solve(self, x, y, format, max_long_side, skip_if_mulof64):
if skip_if_mulof64 and x % 64 == 0 and y % 64 == 0:
return x, y
scale = (1000000 / (x * y)) ** 0.5
x_adjusted, y_adjusted = (int(x * scale) // 64) * 64, (int(y * scale) // 64) * 64
width, height = (max(x_adjusted, y_adjusted), min(x_adjusted, y_adjusted)) if format == 'Landscape' else (min(x_adjusted, y_adjusted), max(x_adjusted, y_adjusted))
if max(width, height) > max_long_side:
scale = max_long_side / max(width, height)
width, height = int(width * scale), int(height * scale)
return width, height
NODE_CLASS_MAPPINGS = {
"TTools SD3 Resolution Solver": TToolsSD3ResolutionSolver,
"TTools Extract JSON": TToolsExtractJson
}
NODE_DISPLAY_NAME_MAPPINGS = {
"TToolsSD3ResolutionSolver": "TTools SD3 Resolution Solver",
"TToolsExtractJson": "TTools Extract JSON",
}