File size: 6,489 Bytes
2e818da
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""Focused tests for `duplicate_candidate_ratio` (Task 8, required gap-close).

Task 7's diagnostic record used `document_diversity` as its only diversity
proxy for the dedup decision -- this is the canonical retrieval-behavior
measure (`duplicate_candidate_ratio`, named in the plan preamble) it was
missing. These tests exercise the measurement in isolation, as pure
data-in/data-out, with no Chroma/DB/observability boundary involved -- the
mechanism (over-fetch + dedup + truncate) is tested separately in
`tests/rag/test_dedup_mechanism.py`, and this file is the "supporting,
behavior-neutral measurement addition" the task brief calls out as
verified on its own.

Fixture note on the Jaccard math: for two texts that differ in exactly one
token out of N shared tokens, intersection = N-1 and union = N+1, so
jaccard = (N-1)/(N+1). To clear the 0.8 threshold with margin, fixtures below
use base phrases of >= 12 tokens (jaccard ~0.86-0.93 for a single differing
trailing token) rather than short phrases that would land under 0.8.
"""

from __future__ import annotations

from app.observability.retrieval import (
    candidate_stats,
    duplicate_candidate_ratio,
    find_duplicate_indices,
    is_near_duplicate,
)

# 12-token base phrases with essentially no shared vocabulary between groups,
# so a single trailing "variant N" token difference clears 0.8 within a
# group while cross-group pairs land far below it.
_ALPHA = "alpha membrane transport channel proteins regulate ion flow across the lipid bilayer"
_BETA = "beta ribosome translation machinery assembles polypeptide chains from messenger rna transcripts today"


def _variant(base: str, n: str) -> str:
    return f"{base} variant {n}"


def _c(text: str, **meta) -> dict:
    return {"text": text, **meta}


# --- is_near_duplicate --------------------------------------------------


def test_identical_text_is_near_duplicate():
    assert is_near_duplicate("the quick brown fox", "the quick brown fox") is True


def test_completely_different_text_is_not_near_duplicate():
    assert (
        is_near_duplicate(
            "mitochondria produce cellular energy through respiration",
            "ribosomes translate messenger rna into polypeptide chains",
        )
        is False
    )


def test_case_and_whitespace_differences_still_count_as_near_duplicate():
    assert is_near_duplicate("Hello   World", "hello world") is True


def test_one_word_difference_in_long_overlapping_chunk_is_near_duplicate():
    # Models the chunker's 64-char-overlap adjacency: two chunks sharing all
    # but one trailing token (e.g. a section-marker suffix differs).
    a = _variant(_ALPHA, "one")
    b = _variant(_ALPHA, "two")
    assert is_near_duplicate(a, b) is True


def test_different_base_phrase_with_shared_suffix_is_not_near_duplicate():
    # Same trailing "variant one" suffix, but otherwise unrelated core text --
    # must NOT be flagged just because a few filler words match.
    a = _variant(_ALPHA, "one")
    b = _variant(_BETA, "one")
    assert is_near_duplicate(a, b) is False


def test_empty_strings_are_near_duplicate_of_each_other():
    assert is_near_duplicate("", "") is True


# --- find_duplicate_indices ---------------------------------------------


def test_find_duplicate_indices_keeps_first_occurrence_per_group():
    candidates = [
        _c(_variant(_ALPHA, "one")),
        _c(_variant(_ALPHA, "two")),  # dup of [0]
        _c(_variant(_BETA, "one")),
        _c(_variant(_ALPHA, "three")),  # dup of [0]
        _c(_variant(_BETA, "two")),  # dup of [2]
    ]
    dups = find_duplicate_indices(candidates)
    assert dups == {1, 3, 4}


def test_find_duplicate_indices_empty_list():
    assert find_duplicate_indices([]) == set()


def test_find_duplicate_indices_no_duplicates():
    candidates = [
        _c(_variant(_ALPHA, "one")),
        _c(_variant(_BETA, "one")),
        _c("gamma mitochondrial electron transport chain produces atp"),
    ]
    assert find_duplicate_indices(candidates) == set()


# --- duplicate_candidate_ratio -------------------------------------------


def test_duplicate_candidate_ratio_empty_list_is_zero():
    assert duplicate_candidate_ratio([]) == 0.0


def test_duplicate_candidate_ratio_no_duplicates_is_zero():
    candidates = [
        _c(_variant(_ALPHA, "one")),
        _c(_variant(_BETA, "one")),
    ]
    assert duplicate_candidate_ratio(candidates) == 0.0


def test_duplicate_candidate_ratio_all_but_first_are_duplicates():
    candidates = [
        _c(_variant(_ALPHA, "one")),
        _c(_variant(_ALPHA, "two")),
        _c(_variant(_ALPHA, "three")),
    ]
    # First occurrence is kept (not counted as a duplicate); the other two
    # are near-duplicates of it -> 2 of 3 flagged.
    assert duplicate_candidate_ratio(candidates) == 2 / 3


def test_duplicate_candidate_ratio_partial():
    candidates = [
        _c(_variant(_ALPHA, "one")),
        _c(_variant(_ALPHA, "two")),  # dup of [0]
        _c(_variant(_BETA, "one")),
        _c("gamma mitochondrial electron transport chain produces atp via oxidative phosphorylation"),
    ]
    assert duplicate_candidate_ratio(candidates) == 0.25


# --- candidate_stats (integration of all three measures) -----------------


def test_candidate_stats_includes_duplicate_candidate_ratio():
    candidates = [
        _c(_variant(_ALPHA, "one"), document_id="doc-a", source="paper-a"),
        _c(_variant(_ALPHA, "two"), document_id="doc-a", source="paper-a"),
        _c(_variant(_BETA, "one"), document_id="doc-b", source="paper-b"),
    ]
    stats = candidate_stats(candidates)
    assert stats["raw_candidate_count"] == 3
    assert stats["document_diversity"] == 2
    assert stats["section_diversity"] == 2
    assert stats["duplicate_candidate_ratio"] == 1 / 3


def test_candidate_stats_is_a_pure_function_of_the_list_its_given():
    """Same yardstick regardless of which pipeline produced the list -- the
    function has no notion of pipeline_version at all, it only looks at the
    candidates handed to it."""
    naive_style = [
        _c(_variant(_ALPHA, "one"), document_id="doc-a"),
        _c(_variant(_ALPHA, "two"), document_id="doc-a"),
    ]
    deduped_style = [
        _c(_variant(_ALPHA, "one"), document_id="doc-a"),
        _c(_variant(_BETA, "one"), document_id="doc-b"),
    ]
    assert candidate_stats(naive_style)["duplicate_candidate_ratio"] == 0.5
    assert candidate_stats(deduped_style)["duplicate_candidate_ratio"] == 0.0