Skip to content

FIX PlagiarismScorer: verbatim fast path matched sub-word substrings - #2388

Merged
hannahwestra25 merged 3 commits into
microsoft:mainfrom
WatchTree-19:fix-plagiarism-scorer-subword-substring
Aug 14, 2026
Merged

FIX PlagiarismScorer: verbatim fast path matched sub-word substrings#2388
hannahwestra25 merged 3 commits into
microsoft:mainfrom
WatchTree-19:fix-plagiarism-scorer-subword-substring

Conversation

@WatchTree-19

Copy link
Copy Markdown
Contributor

Description

PlagiarismScorer._plagiarism_score has a fast path that returns 1.0 when the reference appears verbatim in the response. That check used a raw string test (reference in response), but every metric in the scorer is word-level: the text is tokenized with lowercasing and punctuation removal before LCS / Levenshtein / Jaccard are computed. The raw check was inconsistent with that tokenization in both directions:

  • False positive: a short reference that is only a substring of a longer response word scored full plagiarism. For example reference="cat" against response="concatenate the results" returned 1.0 for all three metrics, because "cat" is a substring of "concatenate" even though cat never appears as a word.
  • Missed match: a word-level verbatim copy that differed only in case or punctuation did not take the fast path (it happened to fall through to the metric, which usually recovered, but the shortcut itself was wrong).

The fix compares the tokenized sequences instead: the reference tokens must appear as a contiguous run inside the response tokens. This keeps the fast path consistent with the case/punctuation-insensitive word-level semantics the metrics already use.

This continues the small correctness pass on the converters/scorers (cf. #2133, #2137, #2278, #2279).

Tests and Documentation

Added regression tests in tests/unit/score/test_plagiarism_scorer.py:

  • a sub-word substring ("cat" vs "concatenate the results") now scores 0.0 for every metric,
  • a word-level verbatim copy differing in case/punctuation still scores 1.0,
  • a direct unit test for the new _is_contiguous_sublist helper.

Full file passes: pytest tests/unit/score/test_plagiarism_scorer.py -> 37 passed. ruff check and black clean. No documentation changes needed (internal scoring behavior only).

…strings

The verbatim-match shortcut in _plagiarism_score used a raw string check
(reference in response). The rest of the scorer is word-level: it tokenizes
with lowercasing and punctuation removal before computing LCS / Levenshtein /
Jaccard. The raw check was inconsistent with that in both directions:

  - false positive: a short reference that is only a substring of a longer
    response word scored 1.0 (e.g. reference 'cat' vs response 'concatenate
    the results' returned full plagiarism for every metric).
  - missed match: a word-level verbatim copy differing only in case or
    punctuation did not take the fast path.

Compare the tokenized sequences instead, so the fast path matches the same
word-level semantics the metrics use. Adds regression tests.
Comment thread pyrit/score/float_scale/plagiarism_scorer.py Outdated
Comment thread pyrit/score/float_scale/plagiarism_scorer.py
@WatchTree-19

Copy link
Copy Markdown
Contributor Author

thanks Hannah, adopted both. made _is_contiguous_sublist keyword-only, and switched to the separator-join containment check - using \0 as the separator since it can't appear in whitespace-split tokens, so it keeps the token-boundary matching while dropping the per-position slice cost. verified it agrees with the old version across the tests (37 passing), ruff/black clean.

- make _is_contiguous_sublist keyword-only per the repo policy
- replace the per-position slice comparison with a separator-join
  containment check (O(n) instead of O(n*m)); uses a NUL separator that
  cannot appear in whitespace-split tokens so matches stay on token
  boundaries
- update the call site and unit tests to the keyword-only signature
@hannahwestra25 hannahwestra25 self-assigned this Aug 14, 2026

@hannahwestra25 hannahwestra25 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for contributing :)

@hannahwestra25
hannahwestra25 added this pull request to the merge queue Aug 14, 2026
Merged via the queue into microsoft:main with commit f049e1a Aug 14, 2026
54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants