boilerplate-like text ("copyright", publisher fragments)
HTML/XML artifact hints
too-short abstract length
low alphabetic character ratio
Apply policy for invalid/missing abstract:
keep_title_only (default): keep record with Title: ...
discard: drop row from embedding input
conditional: keep title-only only when title quality is acceptable
Build final embedding input text:
with valid abstract:
Title: {title}\nAbstract: {abstract_clean}
fallback:
Title: {title}
Hash final text:
text_hash = digest(text, algo = "xxhash64")
used by embed_corpus() resume logic (id + text_hash)
Cleaning Flow Diagram
flowchart TD
A[Input rows: id, title, abstract] --> B[Normalize whitespace and NA handling]
B --> C[Strip simple HTML/XML tags]
C --> D[Remove duplicated title prefix from abstract]
D --> E[Compute quality signals]
E --> E1[Placeholder phrase]
E --> E2[Boilerplate/artifact hint]
E --> E3[Length threshold]
E --> E4[Alphabetic-ratio threshold]
E1 --> F{Abstract valid?}
E2 --> F
E3 --> F
E4 --> F
F -->|yes| G[Build text: Title + Abstract]
F -->|no| H{no_abstract_policy}
H -->|keep_title_only| I[Build text: Title only]
H -->|conditional| J[Title quality check]
J -->|pass| I
J -->|fail| K[Discard row]
H -->|discard| K
G --> L[Compute text_hash]
I --> L
K --> M[No embedding request]
L --> N[Return id, text, text_hash + flags]
Why These Rules
The implementation deliberately avoids aggressive NLP preprocessing (stemming/stopword removal/full punctuation stripping), because modern embedding models generally perform better on natural text.
The default approach targets obvious noise while preserving semantics:
Keep recall by default (title-only fallback).
Protect precision by suppressing known junk patterns.
Preserve reproducibility via deterministic text_hash.
Enable auditing via provenance columns.
Mode Behavior (lenient, balanced, strict)
mode controls threshold aggressiveness.
Conceptually:
lenient: minimal filtering, retain more abstracts
balanced (default): moderate filtering
strict: stronger filtering, discard more weak abstracts
In practice, mode adjusts defaults such as:
minimum abstract length
minimum alphabetic character ratio
You can override thresholds explicitly via:
min_chars
min_alpha_ratio
Example: Default Cleaning
library(openalexVectorComp)df <-data.frame(id =c("W1", "W2", "W3"),title =c("Biodiversity and ecosystem resilience","Ocean circulation dynamics","Land-use transition analysis" ),abstract =c("Biodiversity and ecosystem resilience are central to adaptation planning.","No abstract available","<p>Published by Example Press</p>" ),stringsAsFactors =FALSE)cleaned <-clean_abstract_for_embedding(df)cleaned[, c("id", "text_quality", "abstract_kept", "discard_reason", "text")]
Expected interpretation:
W1: likely title_abstract
W2: placeholder -> fallback title_only
W3: boilerplate/artifact may become title_only (mode-dependent)
Example: Before/After on Individual Cases
The following example demonstrates three outcomes in one run:
kept as title_abstract
fallback to title_only
removed (discard policy)
examples <-data.frame(id =c("A1", "A2", "A3", "A4"),title =c("Ecosystem service valuation","Marine heatwave impacts","Forest carbon accounting","Urban biodiversity monitoring" ),abstract =c(# duplicated title prefix -> should be removed from abstract start"Ecosystem service valuation examines policy trade-offs and uncertainty.",# placeholder -> invalid abstract"No abstract available",# boilerplate/short artifact -> likely invalid"<p>Copyright 2025 Elsevier. All rights reserved.</p>",# clean abstract"We present a field protocol for repeat biodiversity monitoring in cities." ),stringsAsFactors =FALSE)# Keep title-only fallback for invalid abstractskeep_case <-clean_abstract_for_embedding( examples,mode ="balanced",no_abstract_policy ="keep_title_only")keep_case[, c("id", "text_quality", "abstract_kept", "discard_reason", "text")]# Discard invalid abstracts entirelydiscard_case <-clean_abstract_for_embedding( examples,mode ="balanced",no_abstract_policy ="discard")discard_case[, c("id","text_quality","abstract_kept","discard_reason","text")]
Interpretation:
In keep_case, A2/A3 are retained as title_only.
In discard_case, invalid rows are not returned at all.
A1 shows title-prefix cleanup before building final text.
Rows with empty/NAid or text are dropped before embedding.
Output Provenance and Auditability
When using default cleaner flags, embedding output parquet includes cleaning provenance columns in addition to embedding metadata (provider, model_id, created_at, text_hash, V1..Vd).
This makes it straightforward to:
analyze quality tiers (title_abstract vs title_only)