File size: 4,583 Bytes
9c6961c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from openai import OpenAI
import re

client = OpenAI()

# --- Fernández Huerta formula ---
def fernandez_huerta_score(text: str) -> float:
    sentences = re.split(r'[.!?]+', text)
    sentences = [s.strip() for s in sentences if s.strip()]
    n_sentences = len(sentences) if sentences else 1

    words = text.split()
    n_words = len(words) if words else 1

    vowels = "aeiouáéíóúüAEIOUÁÉÍÓÚÜ"
    n_syllables = sum(sum(1 for ch in word if ch in vowels) for word in words)

    return 206.84 - 0.60 * (n_syllables / n_words * 100) - 1.02 * (n_words / n_sentences)


# --- Prompt templates for each label ---
LABEL_PROMPTS = {
    "easy": """Texto original:
{original_text}

Reescribe el texto en un lenguaje muy simple, frases cortas y vocabulario fácil, adecuado para estudiantes de 5º a 7º grado.
El resultado debe seguir lógicamente el texto original y mantener el mismo significado.
No añadas información nueva, no elimines detalles importantes ni cambies los hechos.
""",
    "intermediate": """Texto original:
{original_text}

Reescribe el texto con una complejidad moderada, frases más largas y vocabulario variado, adecuado para secundaria/bachillerato (8º a 12º grado).
El resultado debe seguir lógicamente el texto original y mantener el mismo significado.
No añadas información nueva, no elimines detalles importantes ni cambies los hechos.
""",
    "hard": """Texto original:
{original_text}

Reescribe el texto con lenguaje técnico, detallado y especializado, adecuado para universidad o profesionales.
El resultado debe seguir lógicamente el texto original y mantener el mismo significado.
No añadas información nueva, no elimines detalles importantes ni cambies los hechos.
"""
}


# --- Generate text for a label ---
def generate_label_text(original_text: str, label: str) -> str:
    prompt = LABEL_PROMPTS[label].format(original_text=original_text)
    response = client.chat.completions.create(
        model="gpt-5-mini",  # first try with mini
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content.strip()


# --- Regenerate if FH score is out of range ---
def regenerate_label_text(original_text: str, old_text: str, label: str, target_range: tuple) -> str:
    prompt = f"""Texto original:
{original_text}

Texto generado (necesita ajuste):
{old_text}

El texto anterior no cumple con el rango de legibilidad {target_range}.
Reescribe nuevamente el texto en el nivel "{label}", ajustando la dificultad 
para que el puntaje de Fernández Huerta quede dentro del rango {target_range}.
El resultado debe seguir lógicamente el texto original y mantener el mismo significado.
No añadas información nueva, no elimines detalles importantes ni cambies los hechos.
"""
    response = client.chat.completions.create(
        model="gpt-5",  # use stronger model for regeneration
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content.strip()



# --- Target ranges for FH ---
RANGES = {
    "easy": (70, 100),
    "intermediate": (50, 70),
    "hard": (0, 50)
}


# --- Full pipeline for one topic ---
def generate_synthetic_data(original_text: str, original_language: str, topic: str, data_id: int):
    results = {
        "id": data_id,
        "original_text_language": original_language,
        "source_topic": topic,
        "readability_versions": {}
    }

    for label, target_range in RANGES.items():
        # Step 1: generate
        text = generate_label_text(original_text, label)

        # Step 2: check FH score
        score = fernandez_huerta_score(text)
        if not (target_range[0] <= score <= target_range[1]):
            text = regenerate_label_text(original_text, text, label, target_range)


        # Step 4: save
        results["readability_versions"][label] = {
            "readability_level": label,
            "fernandez_huerta_range": f"{target_range[0]}-{target_range[1]}",
            "target_audience": (
                "Estudiantes de primaria/media (5º a 7º grado)" if label == "easy" else
                "Secundaria/Bachillerato (8º a 12º grado)" if label == "intermediate" else
                "Profesionales / Universidad o posgrado"
            ),
            "text": text
        }

    return results


# --- Example usage ---
if __name__ == "__main__":
    original_text = "Se diagnosticó osteoartritis bilateral en un paciente de 61 años con dolor en la ingle."
    data = generate_synthetic_data(original_text, "es", "Osteoartritis de cadera", 1)
    print(data)