CoolFace
Apppublic

StarTripper/ticket_ordering

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
problem_generator.py335 linesDownload Raw Back to root
1import re2import numpy as np3from enum import Enum4from typing import DefaultDict5from models import ThreadComment, Ticket, TicketHeuristic6 7 8rng = np.random.default_rng(42)9 10 11class GenerationDifficulty(Enum):12    Easy = 013    Medium = 114    Hard = 215 16 17NAMES = [18    "Aarav", "Emma", "Liam", "Olivia", "Noah", "Ava", "Sophia", "Isabella", "Mia", "Charlotte",19    "Amir", "Fatima", "Hassan", "Layla", "Omar", "Yasmin", "Ali", "Zara", "Ibrahim", "Noor",20    "Wei", "Yuki", "Hiroshi", "Mei", "Sora", "Jin", "Minho", "Haruto", "Aiko", "Ren",21    "Carlos", "Sofia", "Mateo", "Lucia", "Diego", "Valentina", "Juan", "Camila", "Luis", "Elena",22    "Ethan", "Abigail", "James", "Emily", "Benjamin", "Ella", "Lucas", "Scarlett", "Henry", "Grace",23    "Arjun", "Priya", "Rohan", "Ananya", "Vikram", "Sneha", "Kiran", "Isha", "Rahul", "Neha",24    "Leo", "Chloe", "Gabriel", "Lily", "Samuel", "Zoe", "Daniel", "Hannah", "Matthew", "Aria",25    "Alexander", "Nina", "Mikhail", "Anastasia", "Ivan", "Svetlana", "Dmitry", "Olga", "Sergey", "Irina",26    "Kwame", "Ama", "Kofi", "Zuri", "Abena", "Tariq", "Amina", "Malik", "Imani", "Nia",27    "Oscar", "Freja", "Lars", "Ingrid", "Bjorn", "Astrid", "Erik", "Sigrid", "Magnus", "Elin"28]29 30 31DIFFICULTY_UNCERTAINTY_MAP = {32    GenerationDifficulty.Easy: 0.0,33    GenerationDifficulty.Medium: 0.0833,34    GenerationDifficulty.Hard: 0.1666,35}36 37 38CRITERIA = [39    "severity",        # how bad40    "fix ease",        # how easy to fix41    "scope backend",   # backend impact42    "scope frontend",  # frontend impact43    "user impact",     # perceived impact44]45CRITERIA_DIST_RANGES = {46    "severity": (0.15, 1.9),47    "fix ease": (0.2, 1.7),48    "scope backend": (0.5, 1.0),49    "scope frontend": (0.0, 0.5),50    "user impact": (0.5, 2.9),51}52 53ISSUE_TYPES = [54    ("crash", {55        "severity": 0.9,56        "fix ease": 0.8,57        "user impact": 0.9,58    }),59    ("failure", {60        "severity": 0.75,61        "fix ease": 0.7,62        "user impact": 0.8,63    }),64    ("bug", {65        "severity": 0.4,66        "fix ease": 0.4,67        "user impact": 0.5,68    }),69    ("slowdown", {70        "severity": 0.35,71        "fix ease": 0.5,72        "user impact": 0.6,73    }),74    ("feature request", {75        "severity": 0.05,76        "fix ease": 0.1,77        "user impact": 0.3,78    }),79]80 81SYSTEM_PARTS = [82    ("lookup API", {83        "scope backend": 1.0,84        "scope frontend": 0.1,85        "user impact": 0.1,86    }),87    ("bot API", {88        "scope backend": 1.0,89        "scope frontend": 0.0,90        "user impact": 0.1,91    }),92    ("login system", {93        "scope backend": 0.5,94        "scope frontend": 0.5,95        "user impact": 1.0,96    }),97    ("automatic curation", {98        "scope backend": 0.8,99        "scope frontend": 0.3,100        "user impact": 0.25,101    }),102    ("relationship routing", {103        "scope backend": 0.75,104        "scope frontend": 0.25,105        "user impact": 0.2,106    }),107    ("trend tracker", {108        "scope backend": 0.9,109        "scope frontend": 0.2,110        "user impact": 0.2,111    }),112]113 114MODIFIERS = [115    ("minor", {116        "severity": 0.1,117        "fix ease": 0.9,118        "user impact": 0.1,119    }),120    ("intermittent", {121        "severity": 0.2,122        "fix ease": 0.4,123        "user impact": 0.2,124    }),125    ("random", {126        "severity": 0.5,127        "fix ease": 0.1,128        "user impact": 0.45,129    }),130    ("unexpected", {131        "severity": 0.8,132        "fix ease": 0.5,133        "user impact": 0.75,134    }),135    ("severe", {136        "severity": 0.75,137        "fix ease": 0.5,138        "user impact": 0.8,139    }),140    ("critical", {141        "severity": 0.9,142        "fix ease": 0.5,143        "user impact": 0.9,144    }),145    ("disastrous", {146        "severity": 1.0,147        "fix ease": 0.5,148        "user impact": 1.0,149    }),150]151 152CONTEXTS = [153    "during normal usage",154    "under heavy user load",155    "under heavy API load",156    "fixed time after deployment",157    "after db migration",158]159 160ACTIONS = [161    "pressing action button {random}",162    "opening dashboard",163    "registering on platform",164    "updating {random} multiple times within {random2} seconds",165    "removing post",166    "replying to user",167    "submitting poll",168    "making post"169]170 171NEW_TEMPLATES = [172    "{modifier} {issue} affecting {system} {context}",173    "{issue} in {system} triggered by {action}",174    "{modifier} {issue} when {action} in {system}",175    176    "users experience {modifier} {issue} in {system} {context}",177    "multiple users report {issue} while {action}",178    "user reports {issue} after {action} {context}",179 180    "{action} leads to {modifier} {issue} in {system}",181    "{system} shows {modifier} behavior when {action}",182    183    "{issue} detected in {system} {context}",184    "{modifier} degradation in {system} {context}",185    186    "{issue} in {system} after {action} {context}",187    "{modifier} issue observed in {system} when {action} {context}",188 189    "{modifier} {issue} impacting users during {context}",190    "{issue} causing failures in {system} under {context}",191]192 193 194def fill_action(action_template):195    fillers = [196        "profile", "settings", "feed", "post", "account",197        "preferences", "notification settings"198    ]199    numbers = ["2", "3", "5", "10", "30"]200 201    result = action_template202    result = result.replace("{random}", rng.choice(fillers))203    result = result.replace("{random2}", rng.choice(numbers))204    return result205 206 207def maybe(value, probability=0.7):208    return value if rng.random() < probability else ""209 210 211def clean_text(text):212    text = re.sub(r"\s+", " ", text)213    return text.strip()214 215 216def combine_scores(217    issue, system, modifier,218    219    uncertainty = 0.0,220    importances = {221        "severity": 0.2,222        "fix ease": 0.2,223        "scope backend": 0.2,224        "scope frontend": 0.2,225        "user impact": 0.2,226    }227):228    scores = DefaultDict(float)229 230    for key, value in issue.items():231        scores[key] += value232    for key, value in system.items():233        scores[key] += value234    for key, value in modifier.items():235        scores[key] += value236 237    combined_score = 0.0238    for criteria in CRITERIA:239        _min, _max  = CRITERIA_DIST_RANGES[criteria]240        scores[criteria] -= _min241        scores[criteria] /= _max - _min242 243        scores[criteria] += rng.uniform(-uncertainty, +uncertainty)244 245        scores[criteria] = min(scores[criteria], 1.0)246        scores[criteria] = max(scores[criteria], 0.0)247 248        scores[criteria] *= importances[criteria]249 250        combined_score += scores[criteria]251 252    combined_score = min(combined_score, 1.0)253    combined_score = max(combined_score, 0.0)254 255    return combined_score256 257 258def generate_ticket_data(259    uncertainty = 0.0,260    importances = {261        "severity": 0.2,262        "fix ease": 0.2,263        "scope backend": 0.2,264        "scope frontend": 0.2,265        "user impact": 0.2,266    }267):268    template = rng.choice(NEW_TEMPLATES)269 270    issue_name, issue_vals = rng.choice(ISSUE_TYPES) # type: ignore271    system_name, system_vals = rng.choice(SYSTEM_PARTS) # type: ignore272    modifier_name, modifier_vals = rng.choice(MODIFIERS) # type: ignore273    context = rng.choice(CONTEXTS)274    action_template = rng.choice(ACTIONS)275 276    action = fill_action(action_template)277 278    text = template.format(279        modifier=maybe(modifier_name),280        issue=issue_name,281        system=system_name,282        context=context,283        action=action,284    )285    combined_score = combine_scores(286        issue_vals, system_vals, modifier_vals,287        uncertainty=uncertainty,288        importances=importances289    )290 291    return clean_text(text), combined_score292 293 294def generate_problem_statement(difficulty: GenerationDifficulty = GenerationDifficulty.Medium) -> tuple[str, list[Ticket]]:295    rng = np.random.default_rng(42 + difficulty.value)296 297    criteria_str = rng.choice(CRITERIA)298    criteria_importances = {299        "severity": 0.2,300        "fix ease": 0.2,301        "scope backend": 0.2,302        "scope frontend": 0.2,303        "user impact": 0.2,304    }305    for key in criteria_importances:306        if key == criteria_str: criteria_importances[key] = 0.8307        else: criteria_importances[key] = 0.05308 309    uncertainty = DIFFICULTY_UNCERTAINTY_MAP[difficulty]310 311    ids = set()312    tickets_with_scores = []313    for _ in range(rng.integers(5, 10)):314        while True:315            id = rng.integers(0, 15, dtype=int)316            if id not in ids:317                ids.add(id)318                break319 320        text, score = generate_ticket_data(uncertainty, criteria_importances)321 322        ticket = Ticket(323            id=id,324            thread=[ThreadComment(user=rng.choice(NAMES), content=text)],325            heuristic=TicketHeuristic()326        )327 328        tickets_with_scores.append((ticket, score))329 330    tickets_with_scores.sort(key=lambda x: x[1])331 332    tickets = [t for t, _ in tickets_with_scores]333 334    return criteria_str, tickets335