Skip to main content

NSTS

NSTS determines the validity timestamp of a webpage: the date that best represents its current primary content. It combines a symbolic date extractor (CPE), an OpenAI semantic reasoner (PSR), and confidence-based selection between their candidates.

Installation

python -m pip install NSTS

Python 3.10 or newer is required. Runtime dependencies install automatically. Import the NSTS class from the lowercase nsts package.

Determine a timestamp from a URL

Set OPENAI_API_KEY and APIFY_API_TOKEN in the environment of your Python process, then run:

from nsts import NSTS

nsts = NSTS()
result = nsts.get_timestamps(url="https://www.example.com/article")
print(result)

With only a URL, NSTS fetches the page text through Apify, fetches HTML metadata over HTTP, and uses OpenAI for semantic reasoning. Live service calls use your accounts and may incur their normal charges.

Use text and HTML you already have

If you already have the URL and page text, pass both to get_timestamps:

from nsts import NSTS

url = "https://example.com/article"
text = " Published on 2020-05-17. "

nsts = NSTS()
result = nsts.get_timestamps(url=url, text=text)
print(result)

Supplying nonempty text avoids Apify crawling, so APIFY_API_TOKEN is not needed. NSTS still fetches HTML metadata from the URL, and the default mode still requires OPENAI_API_KEY.

If you also have the HTML, supply it to avoid fetching page content entirely:

from nsts import NSTS

url = "https://example.com/article"
text = " Published on 2020-05-17. "
html = '<html><head><title>Example</title></head><body>Published on 2020-05-17.</body></html>'

nsts = NSTS()
result = nsts.get_timestamps(url=url, text=text, html=html)
print(result)

The default mode still calls OpenAI even when text and HTML are supplied. Omitted or empty text triggers Apify fetching; omitted or empty HTML triggers HTTP metadata fetching.

Choose a mode and LLM model

extraction_method Behavior Credentials
"nsts" (default) Combines symbolic and semantic candidates using confidence. OpenAI; Apify if fetching text.
"psr" Uses semantic reasoning. OpenAI; Apify if fetching text.
"cpe" Uses deterministic date patterns. Apify only if fetching text.

Specify the mode and model when constructing NSTS:

from nsts import NSTS

nsts = NSTS(
    extraction_method="nsts",
    llm_model="gpt-4o-mini",
)

gpt-4o-mini is the default. To use another model, set llm_model to a model your OpenAI account supports for Chat Completions with function tools. The model setting applies to nsts and psr; cpe does not use an LLM.

Read the result

Every determination example above assigns the returned dictionary to result. To access the selected timestamp:

print(result["timestamp"])

The dictionary also includes the candidates and confidence:

Field Meaning
url Input webpage URL.
timestamp Selected validity timestamp, possibly a partial date or empty string.
cpe_timestamp Symbolic candidate when CPE ran.
psr_timestamp Semantic candidate when PSR ran.
system_confidence PSR confidence, including high, low, conflicted, or none; may be empty if PSR did not run or failed.

These are estimates. A date mentioned in content can differ from the page's validity date; semantic modes help distinguish those cases.

Corpus-Level Use

IGD is a corpus-level denoising step. Use it when processing multiple pages from the same source or domain, then determine a timestamp for each cleaned item. Call remove_boilerplate once on the corpus; get_timestamps does not automatically perform corpus denoising.

The following example illustrates the workflow with two records. Replace them with your corpus. The default neural mode requires OPENAI_API_KEY; supplied nonempty text and HTML avoid page fetching.

from nsts import NSTS

nsts = NSTS(
    min_len=30,
    min_repeatance_ratio=0.01,
    min_docs=30,
)

corpus_data = [
    {"url": "...", "text": "Header... Unique 1... Footer...", "html": "<html>...</html>"},
    {"url": "...", "text": "Header... Unique 2... Footer...", "html": "<html>...</html>"},
]

cleaned_corpus = nsts.remove_boilerplate(corpus_data)

for item in cleaned_corpus:
    result = nsts.get_timestamps(
        url=item["url"],
        text=item["text"],
        html=item["html"],
    )
    print(f"{item['url']}: {result['timestamp']}")

The following settings control corpus denoising:

Parameter Default Meaning
min_len 30 Minimum text-pattern length in characters considered for removal. Increase it to focus on longer repeated blocks.
min_repeatance_ratio 0.01 Fraction of corpus documents in which a pattern must occur, subject to the min_docs minimum. Increase it to require broader repetition in larger corpora.
min_docs 30 Minimum number of documents containing a pattern before removal. Set a smaller positive integer for a smaller corpus.

The document threshold is max(min_docs, int(len(corpus_data) * min_repeatance_ratio)). With the default min_docs=30, a pattern must occur in at least 30 documents, so the two-item illustration above does not remove repeated patterns. With 10,000 documents and the default ratio, the threshold is 100 documents. For a smaller corpus, set min_docs=2 to allow removal of patterns shared by at least two documents. The ratio can still require a higher document count; lowering the ratio alone does not lower min_docs. The above example illustrates the workflow; removal also requires a shared pattern that meets min_len.

Supply dictionaries with url and string text fields and, optionally, html. The returned list contains cleaned text with the original URL and supplied HTML; additional custom fields are not retained. Keep your original records separately if you need those fields.

Research and examples

The repository contains runnable examples, benchmark datasets/results, reproduction instructions, and the paper's citation. Benchmark tools and data are not installed with this library. See issues for problem reports.

Released under the MIT license.

Metadata

Release files for NSTS 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for NSTS 0.1.0
File Size Uploaded
nsts-0.1.0.tar.gz 18.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for NSTS 0.1.0
File Interpreter ABI Platform
nsts-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 39.3 kB

Release files / nsts-0.1.0.tar.gz

Download URL nsts-0.1.0.tar.gz
Size 18.9 kB
Tags Source
SHA-256 checksum
How to use checksums
10bb880bac69deb539407bd3872523bf75c8a1078cf27fe7bf79b01f4af1972b
BLAKE2b-256 checksum
How to use checksums
f73d02b0acafb6935bbd2a04beac11b3224dc407c39e002d813d88a71a219722
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release files / nsts-0.1.0-py3-none-any.whl

Download URL nsts-0.1.0-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6e51e367d867ac129bfa717585304982642fce8a101d66f42932e03d62b2b638
BLAKE2b-256 checksum
How to use checksums
80a3ef5a5759bbe12dd2a5f6d50ae9c2157a813061a60876377436b4809ec65f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page