poster2json 0.9.2__tar.gz → 0.9.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {poster2json-0.9.2 → poster2json-0.9.4}/PKG-INFO +1 -1
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/extract.py +23 -49
- {poster2json-0.9.2 → poster2json-0.9.4}/pyproject.toml +1 -1
- {poster2json-0.9.2 → poster2json-0.9.4}/LICENSE.md +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/README.md +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/__init__.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/__main__.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/cli.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/funders.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/gui.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/identifiers.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/language.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/normalize.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/orcid.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/ror.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/schemas/poster_schema.json +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/standards.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/tests/__init__.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/tests/conftest.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/utils.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/validate.py +0 -0
- {poster2json-0.9.2 → poster2json-0.9.4}/poster2json/xy_cut.py +0 -0
|
@@ -1417,7 +1417,7 @@ def _generate(model, tokenizer, prompt: str, max_tokens: int) -> str:
|
|
|
1417
1417
|
EXTRACTION_PROMPT = """Convert this scientific poster text to JSON format.
|
|
1418
1418
|
|
|
1419
1419
|
CRITICAL RULES:
|
|
1420
|
-
1. Extract ALL required fields: creators, titles, publicationYear, subjects, descriptions
|
|
1420
|
+
1. Extract ALL required fields: creators, titles, publicationYear, subjects, descriptions
|
|
1421
1421
|
2. Create SEPARATE sections for EACH distinct topic/header found in the poster
|
|
1422
1422
|
3. Use the poster's OWN section headers exactly as they appear. Lines prefixed with "## " indicate detected headers from the poster layout. Standard headers (Abstract, Introduction, Methods, Results, Discussion, Conclusions, References, Acknowledgements) are common examples, but always prefer the poster's actual headers over generic ones.
|
|
1423
1423
|
4. Each section must have its OWN "sectionTitle" and "sectionContent"
|
|
@@ -1435,9 +1435,7 @@ JSON SCHEMA (all top-level fields are REQUIRED):
|
|
|
1435
1435
|
"publicationYear": null,
|
|
1436
1436
|
"subjects": [{{"subject": "keyword1"}}, {{"subject": "keyword2"}}, {{"subject": "keyword3"}}],
|
|
1437
1437
|
"descriptions": [{{"description": "A 3-4 sentence summary of the full poster...", "descriptionType": "Abstract"}}],
|
|
1438
|
-
"conference": null,
|
|
1439
1438
|
"researchField": null,
|
|
1440
|
-
"version": null,
|
|
1441
1439
|
"content": {{
|
|
1442
1440
|
"sections": [
|
|
1443
1441
|
{{"sectionTitle": "Introduction", "sectionContent": "Full verbatim text of this section from the poster..."}},
|
|
@@ -1452,14 +1450,10 @@ JSON SCHEMA (all top-level fields are REQUIRED):
|
|
|
1452
1450
|
EXTRACTION NOTES:
|
|
1453
1451
|
- publicationYear: Extract if a year is printed on the poster. If not found, set to null.
|
|
1454
1452
|
- subjects: Extract 3-5 keywords from poster content
|
|
1455
|
-
- descriptions: Write a 3-4 sentence summary of the full poster
|
|
1456
|
-
- titles: If the poster title is ALL CAPS, convert to proper Title Case preserving acronyms (e.g. "RESEARCH ON SARS-CoV-2" not "RESEARCH ON SARS-COV-2")
|
|
1457
|
-
- conference: Extract from text visible on the poster (header, footer, logos). If not found, set to null.
|
|
1458
|
-
- imageCaptions/tableCaptions: Include captions for figures/tables on the poster. If none exist, use [].
|
|
1459
|
-
- version: Extract if printed on the poster. If not found, set to null.
|
|
1460
|
-
- rightsList: OPTIONAL - include if license/copyright info found on poster
|
|
1453
|
+
- descriptions: Write a 3-4 sentence summary of the full poster.
|
|
1454
|
+
- titles: If the poster title is ALL CAPS, convert to proper Title Case preserving acronyms (e.g. "RESEARCH ON SARS-CoV-2" not "RESEARCH ON SARS-COV-2")- imageCaptions/tableCaptions: Include captions for figures/tables on the poster. If none exist, use [].
|
|
1461
1455
|
- researchField: MUST be exactly one of: "Health Sciences" | "Life Sciences" | "Physical Sciences" | "Social Sciences" — or null if unclear.
|
|
1462
|
-
- GROUNDING: For metadata fields (
|
|
1456
|
+
- GROUNDING: For metadata fields (publicationYear), only extract values that appear as text on the poster. If not found, use null. For section content, copy ALL text verbatim — do not skip or shorten.
|
|
1463
1457
|
|
|
1464
1458
|
POSTER TEXT TO CONVERT:
|
|
1465
1459
|
{raw_text}
|
|
@@ -1467,12 +1461,11 @@ POSTER TEXT TO CONVERT:
|
|
|
1467
1461
|
OUTPUT VALID JSON ONLY:"""
|
|
1468
1462
|
|
|
1469
1463
|
FALLBACK_PROMPT = """Convert poster text to JSON. REQUIRED FIELDS:
|
|
1470
|
-
1. creators, titles, publicationYear, subjects, descriptions,
|
|
1464
|
+
1. creators, titles, publicationYear, subjects, descriptions, content
|
|
1471
1465
|
2. SEPARATE section for EACH header found in the poster text. Use the poster's own headers. Lines starting with "## " are detected headers.
|
|
1472
1466
|
3. Copy ALL text EXACTLY verbatim — every line of poster text must appear in a section
|
|
1473
1467
|
4. If title is ALL CAPS, convert to Title Case preserving acronyms (SARS-CoV-2, not SARS-COV-2)
|
|
1474
|
-
5.
|
|
1475
|
-
6. imageCaptions/tableCaptions: for figures/tables on the poster. If none, use [].
|
|
1468
|
+
5. imageCaptions/tableCaptions: for figures/tables on the poster. If none, use [].
|
|
1476
1469
|
|
|
1477
1470
|
{{
|
|
1478
1471
|
"creators": [{{"name": "LastName, FirstName", "givenName": "FirstName", "familyName": "LastName", "affiliation": ["Institution"]}}],
|
|
@@ -1480,9 +1473,7 @@ FALLBACK_PROMPT = """Convert poster text to JSON. REQUIRED FIELDS:
|
|
|
1480
1473
|
"publicationYear": null,
|
|
1481
1474
|
"subjects": [{{"subject": "keyword1"}}, {{"subject": "keyword2"}}],
|
|
1482
1475
|
"descriptions": [{{"description": "3-4 sentence summary of the full poster", "descriptionType": "Abstract"}}],
|
|
1483
|
-
"conference": null,
|
|
1484
1476
|
"researchField": null,
|
|
1485
|
-
"version": null,
|
|
1486
1477
|
"content": {{
|
|
1487
1478
|
"sections": [{{"sectionTitle": "Header", "sectionContent": "Full verbatim text of this section..."}}]
|
|
1488
1479
|
}},
|
|
@@ -2012,6 +2003,17 @@ def _postprocess_json(
|
|
|
2012
2003
|
# Drop LLM-hallucinated formats — set deterministically from file extension
|
|
2013
2004
|
result.pop("formats", None)
|
|
2014
2005
|
|
|
2006
|
+
# version is a fixed provenance marker, not extracted by the model.
|
|
2007
|
+
result["version"] = "Posters.science automated"
|
|
2008
|
+
|
|
2009
|
+
# descriptionType is auto-filled to its default; only the description text
|
|
2010
|
+
# (the summary) is model-generated.
|
|
2011
|
+
descs = result.get("descriptions")
|
|
2012
|
+
if isinstance(descs, list):
|
|
2013
|
+
for d in descs:
|
|
2014
|
+
if isinstance(d, dict) and d.get("description"):
|
|
2015
|
+
d["descriptionType"] = "Abstract"
|
|
2016
|
+
|
|
2015
2017
|
# Ensure caption fields exist and normalize with auto-generated IDs
|
|
2016
2018
|
for key, ctype in [("imageCaptions", "fig"), ("tableCaptions", "table")]:
|
|
2017
2019
|
if key not in result:
|
|
@@ -2019,35 +2021,9 @@ def _postprocess_json(
|
|
|
2019
2021
|
elif isinstance(result[key], (dict, list)):
|
|
2020
2022
|
result[key] = _normalize_captions(result[key], caption_type=ctype)
|
|
2021
2023
|
|
|
2022
|
-
#
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
cn = conf.get("conferenceName", "")
|
|
2026
|
-
if isinstance(cn, str) and _is_placeholder(cn):
|
|
2027
|
-
conf.pop("conferenceName", None)
|
|
2028
|
-
# Ground-truth check: conference name must appear in the poster text
|
|
2029
|
-
cn = conf.get("conferenceName", "")
|
|
2030
|
-
if isinstance(cn, str) and cn and raw_text:
|
|
2031
|
-
cn_lower = cn.lower().strip()
|
|
2032
|
-
if cn_lower not in raw_text.lower():
|
|
2033
|
-
result["conference"] = None
|
|
2034
|
-
conf = None
|
|
2035
|
-
if conf is not None:
|
|
2036
|
-
cl = conf.get("conferenceLocation", "")
|
|
2037
|
-
if isinstance(cl, str) and _is_placeholder(cl):
|
|
2038
|
-
conf.pop("conferenceLocation", None)
|
|
2039
|
-
cu = conf.get("conferenceUrl", "")
|
|
2040
|
-
if isinstance(cu, str) and _is_placeholder(cu):
|
|
2041
|
-
conf.pop("conferenceUrl", None)
|
|
2042
|
-
# Fix 4: validate conferenceUri is a real URL
|
|
2043
|
-
for uri_key in ("conferenceUri", "conferenceUrl"):
|
|
2044
|
-
val = conf.get(uri_key, "")
|
|
2045
|
-
if isinstance(val, str) and val and not val.startswith(("http://", "https://")):
|
|
2046
|
-
conf.pop(uri_key, None)
|
|
2047
|
-
# Collapse to null if no meaningful fields remain
|
|
2048
|
-
meaningful = {k for k, v in conf.items() if v}
|
|
2049
|
-
if not meaningful:
|
|
2050
|
-
result["conference"] = None
|
|
2024
|
+
# Conference is not extracted by the model at all; it is supplied by the
|
|
2025
|
+
# repository or entered on the platform. Drop anything the model emits.
|
|
2026
|
+
result.pop("conference", None)
|
|
2051
2027
|
|
|
2052
2028
|
# Publisher is auto-set by posters.science — strip if the LLM emitted one
|
|
2053
2029
|
result.pop("publisher", None)
|
|
@@ -2249,11 +2225,9 @@ def _postprocess_json(
|
|
|
2249
2225
|
if isinstance(title_obj, dict) and "title" in title_obj:
|
|
2250
2226
|
title_obj["title"] = _clean_unicode_artifacts(title_obj.get("title", ""))
|
|
2251
2227
|
|
|
2252
|
-
#
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
result["rightsList"] = normalize_rights_list(result["rightsList"])
|
|
2228
|
+
# Licenses are not extracted from the poster by the model; rights are
|
|
2229
|
+
# provided by the repository or platform upstream. Drop any the model emits.
|
|
2230
|
+
result.pop("rightsList", None)
|
|
2257
2231
|
|
|
2258
2232
|
# Cleanup + dedupe subjects
|
|
2259
2233
|
if "subjects" in result:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|