""" TAU Platform v4.0 - Synthetic Data Variation Generator מחולל וריאציות לייצור דאטה סינתטי מגוון לאימון מודל שפה. הרעיון: מעובדה בסיסית אחת, ליצור עשרות ניסוחים שונים כדי שהמודל ילמד את הכללים ולא רק ישנן. """ import random import re from typing import List, Dict, Tuple, Optional from dataclasses import dataclass @dataclass class Fact: """עובדה בסיסית עם מרכיביה""" subject: str # הנושא (סוכרת, חוזה, מניה) predicate: str # הפועל/קשר (היא, נחשב, מוגדר) object: str # המושא/הגדרה domain: str # תחום (רפואה, משפט, פיננסים) def __str__(self): return f"{self.subject} {self.predicate} {self.object}" class VariationGenerator: """מחולל וריאציות לעובדות""" # תבניות משפט בעברית SENTENCE_TEMPLATES = [ # הגדרות "{subject} {predicate} {object}", "{subject} מוגדר כ{object}", "{subject} נחשב ל{object}", "{subject} הוא {object}", "{subject} היא {object}", "{subject} זה {object}", # שאלות ותשובות "מהו {subject}? {object}", "מהי {subject}? {object}", "מה זה {subject}? {object}", "{subject} - {object}", # הסברים "{object} - כך מוגדר {subject}", "כאשר מדברים על {subject}, הכוונה ל{object}", "{subject} משמעותו {object}", "המונח {subject} מתאר {object}", # יחסים "{subject} קשור ל{object}", "{subject} מאופיין ב{object}", "ל{subject} יש קשר ל{object}", # פורמלי "הגדרת {subject}: {object}", "{subject} (הגדרה): {object}", "בהקשר זה, {subject} הוא {object}", ] # מילות קישור וסגנון CONNECTORS = ["כלומר", "דהיינו", "במילים אחרות", "למעשה", "בפועל", "בעצם"] EMPHASES = ["בעיקר", "בעיקרו של דבר", "במהותו", "ביסודו"] HEDGES = ["בדרך כלל", "לרוב", "בממוצע", "באופן כללי", "בסך הכל"] # תחיליות וסיומות PREFIXES = [ "", "חשוב לדעת: ", "יש לציין ש", "ראוי להזכיר ש", "מעניין לדעת ש", "בקצרה: ", ] SUFFIXES = [ "", ".", " - מידע חשוב.", " (הגדרה בסיסית).", " - כך בקצרה.", ] def __init__(self, domain_vocab: Optional[Dict[str, List[str]]] = None): """ Args: domain_vocab: מילון מונחים לפי תחום להרחבת וריאציות """ self.domain_vocab = domain_vocab or {} def generate_variations(self, fact: Fact, num_variations: int = 20) -> List[str]: """ יצירת וריאציות מעובדה בסיסית. Args: fact: העובדה המקורית num_variations: מספר וריאציות לייצר Returns: רשימת וריאציות טקסטואליות """ variations = set() # set למניעת כפילויות # הוספת המשפט המקורי variations.add(str(fact)) attempts = 0 max_attempts = num_variations * 10 while len(variations) < num_variations and attempts < max_attempts: attempts += 1 variation = self._create_single_variation(fact) if variation and len(variation) > 10: # מינימום אורך variations.add(variation) return list(variations) def _create_single_variation(self, fact: Fact) -> str: """יצירת וריאציה בודדת""" # בחירת תבנית template = random.choice(self.SENTENCE_TEMPLATES) # מילוי התבנית text = template.format( subject=fact.subject, predicate=fact.predicate, object=fact.object ) # הוספת תחילית אקראית if random.random() < 0.3: text = random.choice(self.PREFIXES) + text # הוספת סיומת אקראית if random.random() < 0.3: text = text.rstrip('.') + random.choice(self.SUFFIXES) elif not text.endswith('.'): text += '.' # הוספת מילת קישור אקראית if random.random() < 0.2: connector = random.choice(self.CONNECTORS) parts = text.split(' ', 3) if len(parts) > 2: text = f"{parts[0]} {parts[1]}, {connector}, {' '.join(parts[2:])}" return text def generate_qa_pairs(self, fact: Fact, num_pairs: int = 10) -> List[Tuple[str, str]]: """ יצירת זוגות שאלה-תשובה מעובדה. Returns: רשימת טאפלים (שאלה, תשובה) """ qa_templates = [ (f"מה זה {fact.subject}?", f"{fact.subject} {fact.predicate} {fact.object}."), (f"מהו {fact.subject}?", f"{fact.object}."), (f"מהי {fact.subject}?", f"{fact.object}."), (f"הגדר {fact.subject}", f"{fact.subject} {fact.predicate} {fact.object}."), (f"הסבר מהו {fact.subject}", f"{fact.subject} מוגדר כ{fact.object}."), (f"מה המשמעות של {fact.subject}?", f"המשמעות היא {fact.object}."), (f"תאר את {fact.subject}", f"{fact.subject} הוא {fact.object}."), (f"מה אתה יודע על {fact.subject}?", f"{fact.subject} {fact.predicate} {fact.object}."), (f"ספר לי על {fact.subject}", f"{fact.subject} - {fact.object}."), (f"האם {fact.subject} קשור ל{fact.object}?", f"כן, {fact.subject} {fact.predicate} {fact.object}."), ] return qa_templates[:num_pairs] def generate_negations(self, fact: Fact) -> List[str]: """יצירת משפטי שלילה (לאימון על מה לא נכון)""" negations = [ f"{fact.subject} אינו {fact.object} - זה לא מדויק.", f"לא נכון ש{fact.subject} הוא {fact.object}.", f"טעות לחשוב ש{fact.subject} זה {fact.object}.", ] return negations class DomainDataGenerator: """מחולל דאטה לתחום ספציפי""" def __init__(self, domain: str): self.domain = domain self.variation_gen = VariationGenerator() self.facts: List[Fact] = [] def add_fact(self, subject: str, predicate: str, obj: str): """הוספת עובדה לתחום""" self.facts.append(Fact(subject, predicate, obj, self.domain)) def add_facts_from_dict(self, facts_dict: Dict[str, str], predicate: str = "הוא"): """הוספת עובדות ממילון {נושא: הגדרה}""" for subject, obj in facts_dict.items(): self.add_fact(subject, predicate, obj) def generate_training_data(self, variations_per_fact: int = 20) -> List[str]: """יצירת כל דאטה האימון""" all_data = [] for fact in self.facts: # וריאציות רגילות variations = self.variation_gen.generate_variations(fact, variations_per_fact) all_data.extend(variations) # זוגות שאלה-תשובה (כטקסט רציף) qa_pairs = self.variation_gen.generate_qa_pairs(fact) for q, a in qa_pairs: all_data.append(f"{q} {a}") return all_data def get_stats(self) -> Dict: """סטטיסטיקות על הדאטה""" return { 'domain': self.domain, 'num_facts': len(self.facts), 'estimated_variations': len(self.facts) * 30, # ~20 variations + 10 QA } # ============================================================================= # דוגמאות לתחומים שונים # ============================================================================= def create_medical_domain() -> DomainDataGenerator: """יצירת דאטה לתחום הרפואי""" gen = DomainDataGenerator("רפואה") medical_facts = { "סוכרת": "מחלה של רמת סוכר גבוהה בדם", "לחץ דם גבוה": "מצב בו הלחץ בעורקים גבוה מהנורמה", "אנמיה": "מחסור בתאי דם אדומים או המוגלובין", "אסתמה": "מחלת דרכי נשימה עם התקפי קוצר נשימה", "אלרגיה": "תגובת יתר של מערכת החיסון לחומר זר", "דלקת ריאות": "זיהום בריאות הגורם לדלקת", "שבץ מוחי": "פגיעה באספקת הדם למוח", "אוטם שריר הלב": "חסימת אספקת דם לשריר הלב", "כולסטרול": "שומן בדם הדרוש לגוף אך מזיק בעודף", "אינסולין": "הורמון המווסת את רמת הסוכר בדם", } gen.add_facts_from_dict(medical_facts) return gen def create_legal_domain() -> DomainDataGenerator: """יצירת דאטה לתחום המשפטי""" gen = DomainDataGenerator("משפט") legal_facts = { "חוזה": "הסכם משפטי מחייב בין שני צדדים או יותר", "נזיקין": "ענף משפטי העוסק בפיצוי על נזקים", "עבירה פלילית": "מעשה אסור שהעונש עליו נקבע בחוק", "תביעה אזרחית": "הליך משפטי לפתרון סכסוך בין אזרחים", "ערעור": "בקשה לבחינה מחדש של פסק דין", "צו מניעה": "הוראת בית משפט להימנע מפעולה מסוימת", "עדות": "מתן גרסה בבית משפט על עובדות", "פסק דין": "החלטה סופית של בית המשפט", "ייפוי כוח": "הסמכה לאדם אחר לפעול בשמך", "התיישנות": "פקיעת זכות תביעה עקב חלוף זמן", } gen.add_facts_from_dict(legal_facts) return gen def create_finance_domain() -> DomainDataGenerator: """יצירת דאטה לתחום הפיננסי""" gen = DomainDataGenerator("פיננסים") finance_facts = { "מניה": "יחידת בעלות בחברה הנסחרת בבורסה", "אגרת חוב": "הלוואה לחברה או ממשלה עם ריבית קבועה", "תיק השקעות": "אוסף נכסים פיננסיים של משקיע", "דיבידנד": "חלוקת רווחי החברה לבעלי המניות", "אינפלציה": "עליית מחירים כללית לאורך זמן", "ריבית": "תשלום עבור שימוש בכסף של אחר", "שער חליפין": "ערך מטבע אחד ביחס לאחר", "קרן נאמנות": "מכשיר השקעה משותף למספר משקיעים", "נזילות": "היכולת להמיר נכס למזומן במהירות", "סיכון": "האפשרות להפסד בהשקעה", } gen.add_facts_from_dict(finance_facts) return gen # ============================================================================= # ניסוי ראשי # ============================================================================= def run_generation_demo(): """הדגמת מחולל הוריאציות""" print("=" * 70) print("מחולל וריאציות לדאטה סינתטי") print("=" * 70) # יצירת דאטה רפואי medical = create_medical_domain() legal = create_legal_domain() finance = create_finance_domain() print(f"\n📊 סטטיסטיקות:") for domain in [medical, legal, finance]: stats = domain.get_stats() print(f" {stats['domain']}: {stats['num_facts']} עובדות → ~{stats['estimated_variations']} וריאציות") # דוגמה לוריאציות print("\n" + "=" * 70) print("דוגמה: וריאציות לעובדה רפואית") print("=" * 70) fact = Fact("סוכרת", "היא", "מחלה של רמת סוכר גבוהה בדם", "רפואה") gen = VariationGenerator() variations = gen.generate_variations(fact, num_variations=15) print(f"\nעובדה מקורית: {fact}") print(f"\n{len(variations)} וריאציות:") for i, var in enumerate(variations, 1): print(f" {i}. {var}") # שאלות ותשובות print("\n" + "=" * 70) print("זוגות שאלה-תשובה:") print("=" * 70) qa_pairs = gen.generate_qa_pairs(fact, num_pairs=5) for q, a in qa_pairs: print(f" ש: {q}") print(f" ת: {a}") print() # יצירת דאטה מלא print("=" * 70) print("יצירת דאטה אימון מלא") print("=" * 70) all_data = [] for domain in [medical, legal, finance]: domain_data = domain.generate_training_data(variations_per_fact=20) all_data.extend(domain_data) print(f" {domain.domain}: {len(domain_data)} משפטים") print(f"\n סה\"כ דאטה אימון: {len(all_data)} משפטים") return all_data if __name__ == "__main__": training_data = run_generation_demo()