| 2127 | |
| 2128 | |
| 2129 | def extract_caption_lines(pdf_text: str, kind: str) -> list[dict[str, str]]: |
| 2130 | grouped: dict[str, dict[str, str]] = {} |
| 2131 | scores: dict[str, int] = {} |
| 2132 | order: list[str] = [] |
| 2133 | lines = [clean_pdf_line(line) for line in pdf_text.splitlines()] |
| 2134 | if kind == "figure": |
| 2135 | pattern = re.compile( |
| 2136 | r"^((?:" |
| 2137 | r"supplementary\s+fig(?:ure)?\.?\s*\d+[a-z]?" |
| 2138 | r"|extended\s+data\s+fig(?:ure)?\.?\s*\d+[a-z]?" |
| 2139 | r"|scheme\.?\s*\d+[a-z]?" |
| 2140 | r"|algorithm\.?\s*\d+[a-z]?" |
| 2141 | r"|fig(?:ure)?\.?\s*[AS]?\d+[a-z]?" |
| 2142 | r"|图\.?\s*[A-Z]?\d+[a-z]?" |
| 2143 | r"))(?!\.\d)(?:[::.。,\s、|—–-]+|$)(.*)$", |
| 2144 | re.IGNORECASE, |
| 2145 | ) |
| 2146 | else: |
| 2147 | pattern = re.compile( |
| 2148 | r"^((?:" |
| 2149 | r"supplementary\s+table\.?\s*\d+[a-z]?" |
| 2150 | r"|extended\s+data\s+table\.?\s*\d+[a-z]?" |
| 2151 | r"|table\.?\s*[AS]?\d+[a-z]?" |
| 2152 | r"|表\.?\s*[A-Z]?\d+[a-z]?" |
| 2153 | r"))(?!\.\d)(?:[::.。,\s、|—–-]+|$)(.*)$", |
| 2154 | re.IGNORECASE, |
| 2155 | ) |
| 2156 | for idx, line in enumerate(lines): |
| 2157 | if not line: |
| 2158 | continue |
| 2159 | match = pattern.match(line) |
| 2160 | if not match: |
| 2161 | continue |
| 2162 | label = normalize_caption_label(match.group(1)) |
| 2163 | caption = normalize_whitespace(match.group(2)) |
| 2164 | if not caption and idx + 1 < len(lines): |
| 2165 | caption = normalize_whitespace(lines[idx + 1]) |
| 2166 | key = caption_label_key(label) |
| 2167 | if not key: |
| 2168 | continue |
| 2169 | candidate = {"id": label, "caption": caption} |
| 2170 | score = caption_preference_score(label, caption) |
| 2171 | if key not in grouped: |
| 2172 | grouped[key] = candidate |
| 2173 | scores[key] = score |
| 2174 | order.append(key) |
| 2175 | continue |
| 2176 | if score > scores[key]: |
| 2177 | grouped[key] = candidate |
| 2178 | scores[key] = score |
| 2179 | return [grouped[key] for key in order] |
| 2180 | |
| 2181 | |
| 2182 | def infer_paper_type(title: str, abstract: str) -> tuple[str, str]: |