Spaces:
Runtime error
Runtime error
| """Spec paper-module layout: filename mapping and generated artifacts. | |
| Defines the canonical ``papers/<slug>/`` module: the mapping from the pipeline's | |
| internal content keys to the public spec filenames, plus the deterministic | |
| builders for the new spec artifacts (``paper.md``, ``metadata.json``, | |
| ``sources.json``). Pure and testable — no I/O here; the Export agent writes. | |
| """ | |
| from __future__ import annotations | |
| from typing import Any | |
| from researchlink.schemas.paper import PaperExtraction, PaperMetadata | |
| from researchlink.schemas.provenance import MetadataProvenance | |
| #: Internal pipeline content key -> on-disk spec filename. | |
| SPEC_RENAME: dict[str, str] = { | |
| "digest.md": "summary.md", | |
| "literature-review.md": "related_work.md", | |
| "implementation-link.md": "implementation.md", | |
| "reproducibility.md": "reproduction.md", | |
| "teaching-path.md": "study_notes.md", | |
| } | |
| #: The public spec module files a complete module should contain. | |
| SPEC_FILES: tuple[str, ...] = ( | |
| "paper.md", | |
| "metadata.json", | |
| "sources.json", | |
| "bibtex.bib", | |
| "summary.md", | |
| "claims.md", | |
| "related_work.md", | |
| "implementation.md", | |
| "reproduction.md", | |
| "study_notes.md", | |
| "review.md", | |
| ) | |
| def spec_filename(internal_key: str) -> str: | |
| """Map an internal content key to its on-disk name (identity if unmapped).""" | |
| return SPEC_RENAME.get(internal_key, internal_key) | |
| def paper_markdown(meta: PaperMetadata, extraction: PaperExtraction) -> str: | |
| """Deterministic structured Markdown of the paper (verbatim extraction).""" | |
| lines = [ | |
| f"# {meta.title}", | |
| "", | |
| "> Machine-extracted paper content. Verbatim from the source PDF/text; " | |
| "no interpretation added. Fields may be incomplete — verify against the original.", | |
| "", | |
| f"- **Year:** {meta.year or '[needs-verification]'}", | |
| f"- **Venue:** {meta.venue or '[needs-verification]'}", | |
| f"- **Authors:** {', '.join(meta.authors_provisional[:12]) or '[needs-verification]'}", | |
| f"- **Paper URL:** {meta.paper_url or 'N/A'}", | |
| f"- **Code URL:** {meta.code_url or 'N/A'}", | |
| f"- **Pages extracted:** {extraction.page_count or 'unknown'}", | |
| "", | |
| "## Abstract", | |
| "", | |
| extraction.abstract or "_[needs-verification] no abstract extracted_", | |
| "", | |
| "## Section Headings", | |
| "", | |
| ] | |
| if extraction.section_headings: | |
| lines += [f"- {h}" for h in extraction.section_headings] | |
| else: | |
| lines.append("_[needs-verification] no section headings extracted_") | |
| if extraction.full_text: | |
| lines += ["", "## Full Extracted Text", "", "```text", extraction.full_text.strip(), "```"] | |
| return "\n".join(lines) + "\n" | |
| SCHEMA_VERSION = "0.1" | |
| def _confidence_label(value: float) -> str: | |
| return "high" if value >= 0.6 else "medium" if value >= 0.4 else "low" | |
| def build_metadata_json( | |
| provenance: MetadataProvenance, | |
| meta: PaperMetadata, | |
| model_slug: str = "unknown-model", | |
| ) -> tuple[dict[str, Any], dict[str, Any]]: | |
| """Split provenance into (metadata.json payload, sources.json payload). | |
| Both are versioned. metadata.json carries provenance-tracked fields (each with | |
| a human-readable confidence label); sources.json wraps the per-source records | |
| as ``{type, url, accessed_at, status}``. | |
| """ | |
| data = provenance.model_dump(mode="json") | |
| raw_sources = data.pop("sources", []) | |
| # Add a readable confidence label alongside the numeric confidence. | |
| for name in provenance.FIELD_NAMES: | |
| field = data.get(name) | |
| if isinstance(field, dict): | |
| field["confidence_label"] = _confidence_label(field.get("confidence", 0.0)) | |
| payload: dict[str, Any] = { | |
| "schema_version": SCHEMA_VERSION, | |
| "slug": meta.slug, | |
| "generated_by_model": model_slug, | |
| "conflicts": provenance.conflicts(), | |
| "fields": data, | |
| } | |
| sources_payload: dict[str, Any] = { | |
| "schema_version": SCHEMA_VERSION, | |
| "sources": [ | |
| { | |
| "type": s.get("name"), | |
| "url": s.get("url"), | |
| "accessed_at": s.get("retrieved_at"), | |
| "status": "ok" if s.get("ok", True) else "error", | |
| "error": s.get("error"), | |
| "fields": list((s.get("fields") or {}).keys()), | |
| } | |
| for s in raw_sources | |
| ], | |
| } | |
| return payload, sources_payload | |