| 870 | |
| 871 | |
| 872 | def enrich_metadata(record: dict[str, Any]) -> dict[str, Any]: |
| 873 | base = dict(record) |
| 874 | candidates: list[dict[str, Any]] = [base] |
| 875 | doi = normalize_whitespace(str(base.get("doi", ""))) |
| 876 | title = normalize_whitespace(str(base.get("title", ""))) |
| 877 | arxiv_id = normalize_whitespace(str(base.get("arxiv_id", ""))) |
| 878 | |
| 879 | if doi: |
| 880 | crossref = fetch_crossref_by_doi(doi) |
| 881 | if crossref: |
| 882 | candidates.append(crossref) |
| 883 | openalex = fetch_openalex_by_doi(doi) |
| 884 | if openalex: |
| 885 | candidates.append(openalex) |
| 886 | sem = choose_best_title_match(title or doi, search_semantic_scholar(doi, limit=3)) |
| 887 | if sem: |
| 888 | candidates.append(sem) |
| 889 | |
| 890 | if arxiv_id: |
| 891 | arxiv = safe_fetch_arxiv_entries(id_list=arxiv_id, max_results=1) |
| 892 | if arxiv: |
| 893 | candidates.append(arxiv[0]) |
| 894 | |
| 895 | if title: |
| 896 | sem = choose_best_title_match(title, search_semantic_scholar(title, limit=5)) |
| 897 | if sem: |
| 898 | candidates.append(sem) |
| 899 | oa = choose_best_title_match(title, search_openalex_by_title(title, limit=5)) |
| 900 | if oa: |
| 901 | candidates.append(oa) |
| 902 | cross = choose_best_title_match(title, search_crossref_by_title(title, limit=5)) |
| 903 | if cross: |
| 904 | candidates.append(cross) |
| 905 | arxiv = choose_best_title_match(title, safe_fetch_arxiv_entries(search_query=f'ti:"{title}"', max_results=5)) |
| 906 | if arxiv: |
| 907 | candidates.append(arxiv) |
| 908 | |
| 909 | merged = merge_metadata_records(*candidates) |
| 910 | if not merged.get("year") and merged.get("published") and re.match(r"^\d{4}", str(merged["published"])): |
| 911 | merged["year"] = str(merged["published"])[:4] |
| 912 | if merged.get("doi") and not merged.get("source_url"): |
| 913 | merged["source_url"] = f"https://doi.org/{merged['doi']}" |
| 914 | if merged.get("arxiv_id") and not merged.get("pdf_url"): |
| 915 | merged["pdf_url"] = f"https://arxiv.org/pdf/{merged['arxiv_id']}.pdf" |
| 916 | if merged.get("arxiv_id") and not merged.get("doi"): |
| 917 | merged["doi"] = f"10.48550/arXiv.{merged['arxiv_id']}" |
| 918 | if base.get("source_type") == "local_pdf": |
| 919 | if base.get("local_pdf_title_source"): |
| 920 | merged["local_pdf_title_source"] = base["local_pdf_title_source"] |
| 921 | elif is_probable_local_pdf_artifact_title(str(base.get("title", ""))): |
| 922 | merged["local_pdf_title_source"] = "local_pdf_stem_used" |
| 923 | if base.get("local_pdf_artifact_title") or is_probable_local_pdf_artifact_title(str(base.get("title", ""))): |
| 924 | merged["local_pdf_artifact_title"] = True |
| 925 | corrected_title = choose_local_pdf_corrected_title(base, candidates[1:]) |
| 926 | if corrected_title: |
| 927 | merged["title"] = corrected_title |
| 928 | merged["title_corrected_from_external_metadata"] = True |
| 929 | merged["paper_id"] = paper_id_for_record(merged) |