Download code/old/synthetic_data_generationV2.py from shahidul034/readCtrl_lambda: direct link, hf CLI and curl.
- Browser
- Download file 6.97 kB
-
https://huggingface.co/shahidul034/readCtrl_lambda/resolve/main/code/old/synthetic_data_generationV2.py
- Command line
-
hf download hf://shahidul034/readCtrl_lambda/code/old/synthetic_data_generationV2.py
-
curl -L -o synthetic_data_generationV2.py https://huggingface.co/shahidul034/readCtrl_lambda/resolve/main/code/old/synthetic_data_generationV2.py
6.97 kB
| import os | |
| import json | |
| from openai import OpenAI | |
| import tqdm | |
| import re | |
| from FH_es import fernandez_huerta | |
| # Initialize client (ensure you have OPENAI_API_KEY in env vars) | |
| client = OpenAI(api_key=json.load(open('/home/mshahidul/api.json', 'r'))['openai_api_key']) | |
| PROMPTS_ES = { | |
| "B1": """Eres un asistente que reescribe resúmenes de casos clínicos para niñas y niños de primaria (aprox. 6–11 años). | |
| Escribe SIEMPRE en español claro. | |
| Objetivo de legibilidad (aprox. Fernández–Huerta): 70–100. | |
| Restricciones de forma (cumple todas): | |
| - Longitud total: 45–90 palabras. | |
| - Oraciones: 4–6 oraciones. | |
| - Promedio de palabras por oración: 8–12. | |
| - Palabras: prefiere palabras cortas (1–2 sílabas). Evita tecnicismos. Si un término médico es inevitable, explícalo con 3–8 palabras sencillas. | |
| - Conectores simples: “y”, “pero”, “porque”. Evita oraciones subordinadas largas. | |
| - No inventes información. Sé fiel al artículo y al resumen experto. | |
| - Prohibido: viñetas, listas, emojis, abreviaturas técnicas, explicaciones de pronunciación, títulos/cabeceras. | |
| Tono y contenido: | |
| - Amable, tranquilizador, sin alarmar. | |
| - Destaca 1–3 ideas principales. Explica hallazgos normales con calma; anormalidades con lenguaje sencillo y breve. | |
| Responde solo con el resumen (sin prefacios, sin notas).""", | |
| "B2": """Eres un asistente que reescribe resúmenes de casos clínicos para estudiantes de secundaria (aprox. 11–17 años). | |
| Escribe SIEMPRE en español claro. | |
| Objetivo de legibilidad (aprox. Fernández–Huerta): 55–65. | |
| Restricciones de forma (cumple todas): | |
| - Longitud total: 90–140 palabras. | |
| - Oraciones: 5–8 oraciones. | |
| - Promedio de palabras por oración: 12–18. | |
| - Palabras: evita jerga innecesaria. Puedes usar términos médicos comunes con una breve explicación (3–10 palabras) la primera vez. | |
| - Conectores permitidos: “porque”, “aunque”, “sin embargo”, “por eso”. Oraciones compuestas moderadas. | |
| - No inventes información. Sé fiel al artículo y al resumen experto. | |
| - Prohibido: viñetas, listas, emojis, explicaciones de pronunciación, títulos/cabeceras. | |
| Tono y contenido: | |
| - Claro y empático. | |
| - Distingue hallazgos normales y anormales, e incluye posibles pasos siguientes cuando sea útil. | |
| Responde solo con el resumen (sin prefacios, sin notas).""", | |
| "B3": """Eres un asistente que reescribe resúmenes de casos clínicos para lectores con nivel universitario (17+), sin especialización médica. | |
| Escribe SIEMPRE en español claro. | |
| Objetivo de legibilidad (aprox. Fernández–Huerta): 40–55. | |
| Restricciones de forma (cumple todas): | |
| - Longitud total: 140–220 palabras. | |
| - Oraciones: 6–10 oraciones. | |
| - Promedio de palabras por oración: 18–25. | |
| - Palabras: se permiten términos técnicos de uso común; define brevemente solo los poco conocidos. Se aceptan oraciones subordinadas si mantienen claridad. | |
| - Conectores: “sin embargo”, “por lo tanto”, “además”, “no obstante”, “en consecuencia”. | |
| - No inventes información. Sé fiel al artículo y al resumen experto. | |
| - Prohibido: viñetas, listas, emojis, explicaciones de pronunciación, títulos/cabeceras. | |
| Tono y contenido: | |
| - Preciso y empático. | |
| - Estructura más detallada: contexto breve, hallazgos clave, implicaciones y posibles próximos pasos. | |
| Responde solo con el resumen (sin prefacios, sin notas).""" | |
| } | |
| FH_TARGETS = { | |
| "B1": (70, 100), | |
| "B2": (55, 65), | |
| "B3": (40, 55), | |
| } | |
| def count_syllables(word): | |
| # Simple Spanish syllable counter | |
| word = word.lower() | |
| word = re.sub(r'[^a-záéíóúüñ]', '', word) | |
| return len(re.findall(r'[aeiouáéíóúü]+', word)) | |
| def generate_synthetic_summary(article, gold_summary, band, lang='es'): | |
| prompt_user = f"""Artículo: | |
| {article} | |
| Resumen experto: | |
| {gold_summary} | |
| Tarea: | |
| Genera un resumen en la banda {band} indicada por el sistema. Responde solo con el resumen.""" | |
| response = client.chat.completions.create( | |
| model="gpt-4.1-mini", # <-- Check this model name! | |
| messages=[ | |
| {"role": "system", "content": PROMPTS_ES[band]}, | |
| {"role": "user", "content": prompt_user} | |
| ], | |
| temperature=0.4, | |
| ) | |
| return response.choices[0].message.content.strip() | |
| def revise_to_band(text, band): | |
| adjustments = { | |
| "B1": "Acorta oraciones a 8–12 palabras, usa palabras más comunes y evita tecnicismos.", | |
| "B2": "Ajusta oraciones a 12–18 palabras y limita tecnicismos con breve explicación.", | |
| "B3": "Usa 18–25 palabras por oración, permite frases subordinadas y vocabulario más técnico.", | |
| } | |
| msg = f"""Reescribe el texto para que cumpla la banda {band}: | |
| - {adjustments[band]} | |
| - Mantén fidelidad al contenido. | |
| Devuelve solo el texto revisado, sin comentarios.""" | |
| r = client.chat.completions.create( | |
| model="gpt-4.1-mini", | |
| messages=[ | |
| {"role": "system", "content": PROMPTS_ES[band]}, | |
| {"role": "user", "content": text}, | |
| {"role": "user", "content": msg} | |
| ], | |
| temperature=0.3, | |
| ) | |
| return r.choices[0].message.content.strip() | |
| def build_synthetic_dataset(input_path, output_path, max_samples=None): | |
| """Generate synthetic dataset from a JSON file with {fulltext, summary}""" | |
| results = [] | |
| seen_articles = set() | |
| if os.path.exists(output_path): | |
| with open(output_path, 'r') as f: | |
| results = json.load(f) | |
| seen_articles = set(r['article'] for r in results) | |
| with open(input_path, "r") as f: | |
| data = json.load(f) | |
| for item in tqdm.tqdm(data): | |
| if max_samples and len(results) >= max_samples: | |
| break | |
| article, gold = item["fulltext"], item["summary"] | |
| if article in seen_articles: | |
| continue | |
| temp = {} | |
| for band in ["B1", "B2", "B3"]: | |
| synthetic = generate_synthetic_summary(article, gold, band) | |
| fh = fernandez_huerta(synthetic) | |
| lo, hi = FH_TARGETS[band] | |
| if fh is None or not (lo <= fh <= hi): | |
| synthetic = revise_to_band(synthetic, band) | |
| temp[band] = synthetic | |
| results.append({ | |
| "article": article, | |
| "gold_summary": gold, | |
| "synthetic_summary": temp | |
| }) | |
| seen_articles.add(article) | |
| if len(results) % 5 == 0: | |
| print(f"Processed {len(results)} samples, saving progress...") | |
| with open(output_path, "w") as f: | |
| json.dump(results, f, ensure_ascii=False, indent=4) | |
| with open(output_path, "w") as f: | |
| json.dump(results, f, ensure_ascii=False, indent=4) | |
| # Example usage: | |
| lang = "es" | |
| path = f"/home/mshahidul/readctrl/data/testing_data_gs/multiclinsum_gs_train_{lang}.json" | |
| build_synthetic_dataset(path, f"/home/mshahidul/readctrl/generating_data/{lang}_synthetic.json", max_samples=100) |