File size: 2,451 Bytes
6f54a86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import json


def load_config(config_path="configs/config.json"):
    with open(config_path, "r", encoding="utf-8") as f:
        config = json.load(f)
    return config

def load_prompts(path="configs/prompts.json"):
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)["system_prompts"]

def load_md(file_path):
    with open(file_path, "r", encoding="utf-8") as f:
        text = f.read()
    return text


def extract_title_from_md(text: str, default: str) -> str:
    """Extrae un título legible desde el contenido Markdown.



    Nueva heurística (pensada para tus .md normalizados):

    - Prioriza el primer encabezado Markdown que empiece por '#'.

    - Ignora líneas que sean solo año/número o termos genéricos como "Article".

    - Si no hay encabezado válido, usa la primera línea de texto no vacía que no sea solo año/número/genérico.

    - Si todo falla, devuelve ``default``.

    """

    if not text:
        return default

    def _es_generico_ou_numero(line: str) -> bool:
        """Detecta líneas poco informativas: solo número/año o rótulos genéricos."""
        val = line.strip()
        if not val:
            return True

        # Solo dígitos ("2007", "69", etc.)
        if val.isdigit():
            return True

        # Año de 4 dígitos aislado
        if len(val) == 4 and val.isdigit():
            return True

        lower = val.lower()
        genericos = {
            "article",
            "artigo",
            "artículo",
            "issue",
            "number",
            "número",
        }
        if lower in genericos:
            return True

        return False

    lines = [l.rstrip("\n") for l in text.splitlines()]

    # 1) Buscar primer heading "#" que no sea genérico/numérico
    for raw_line in lines:
        line = raw_line.strip()
        if not line:
            continue
        if line.startswith("#"):
            candidate = line.lstrip("#").strip()
            if candidate and not _es_generico_ou_numero(candidate):
                return candidate

    # 2) Si no hay heading válido, buscar primera línea de texto informativa
    for raw_line in lines:
        line = raw_line.strip()
        if not line:
            continue
        if not _es_generico_ou_numero(line):
            return line

    # 3) Fallback
    return default