tests/test_proactive_delivery.py
Rama main · réplica de lectura del repositorio original.
"""Ranking and proactive delivery: Jev verdicts plus local rules, no generation model."""
import copy
import os
import sys
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'scripts'))
import xkb_delivery as delivery
import xkb_memory_service as service
from xkb_eval import score_case
def record(key, judge, body='', score=.9, scale='wiki_semantic'):
return {'id': key, 'judge': judge, 'summary': body or key,
'score': score, 'score_scale': scale, 'namespace': 'private'}
class ProactiveDelivery(unittest.TestCase):
def select(self, records, judge, conversation, delivered=frozenset()):
return delivery.select(records, judge, conversation, query='Help with the current task', delivered=delivered)
def test_current_need_overrides_old_topic_retrieval_rank(self):
source = [record('old-video', .36, score=.95), record('old-shot', .22, score=.9),
record('carbon', .89, score=.8)]
ranked = delivery.rank(source, {'status': 'judged'})
self.assertEqual([r['id'] for r in ranked], ['carbon', 'old-video', 'old-shot'])
selected = self.select(ranked, {'status': 'judged'}, [])
self.assertEqual([r['id'] for r in selected['records']], ['carbon'])
self.assertEqual(len(ranked), 3) # Selection does not erase candidates.
def test_at_most_three_and_no_generation_model_is_called(self):
records = [record(str(i), .9, f'distinct step {i}') for i in range(10)]
result = self.select(records, {'status': 'judged'}, [])
self.assertEqual([r['id'] for r in result['records']], ['0', '1', '2'])
self.assertEqual(result['status'], 'ready')
self.assertFalse(hasattr(delivery, '_llm'))
def test_partial_judge_delivers_positive_verdicts_and_stays_visible(self):
source = [record('weak', .2, score=.98), record('unknown', None, score=.95),
record('useful', .9, score=.9)]
ranked = delivery.rank(source, {'status': 'partial'})
self.assertEqual([r['id'] for r in ranked], ['useful', 'unknown', 'weak'])
selected = self.select(ranked, {'status': 'partial'}, [])
self.assertEqual([r['id'] for r in selected['records']], ['useful'])
self.assertEqual(selected['status'], 'degraded')
fallback = delivery.rank(copy.deepcopy(source), {'status': 'unavailable'})
self.assertEqual([r['id'] for r in fallback], ['weak', 'unknown', 'useful'])
unavailable = self.select(fallback, {'status': 'unavailable'}, [])
self.assertEqual(unavailable['mode'], 'background')
self.assertEqual(unavailable['status'], 'degraded')
def test_exact_duplicates_and_text_already_in_a_reply_are_not_delivered(self):
claim = 'Keep original source, reporting period, units and coefficient version for every calculation.'
history = [{'role': 'assistant', 'content': claim}]
records = [record('already', .9, claim), record('first', .9, 'A distinct useful step'),
record('copy', .8, 'A distinct useful step'), record('weak', .2, 'Another step')]
selected = self.select(records, {'status': 'judged'}, history)
self.assertEqual([r['id'] for r in selected['records']], ['first'])
self.assertEqual([r['reason'] for r in selected['withheld']],
['already_in_conversation', 'duplicate_claim', 'weak_relevance'])
self.assertEqual(len(selected['previously_presented']), 1)
def test_a_user_statement_does_not_count_as_already_presented(self):
claim = 'Keep original source, reporting period, units and coefficient version for every calculation.'
result = self.select([record('evidence', .9, claim)], {'status': 'judged'},
[{'role': 'user', 'content': claim}])
self.assertEqual(result['mode'], 'suggest')
def test_display_only_backend_snippets_are_never_injected(self):
candidate = {**record('a', .9, 'Delete the backup'), 'excerpt_truncated': True}
result = self.select([candidate], {'status': 'judged'}, [])
self.assertEqual(result['records'], [])
self.assertEqual(result['withheld'][0]['reason'], 'incomplete_source_excerpt')
def test_id_only_titles_are_replaced_by_the_first_sentence(self):
card = {**record('2044072293383712878', .9, '單一鏡頭只安排一個核心動作。其餘拆成下一鏡。'),
'title': '2044072293383712878'}
shown = self.select([card], {'status': 'judged'}, [])['records'][0]
self.assertEqual(shown['title'], '單一鏡頭只安排一個核心動作')
named = {**record('x', .9, 'Body.'), 'title': 'Seedance 2.0 workflow'}
self.assertEqual(self.select([named], {'status': 'judged'}, [])['records'][0]['title'], 'Seedance 2.0 workflow')
def history(self, key, judge, kind='memory_note'):
return {**record(key, judge, f'history {key}'), 'record_type': kind}
def card(self, key, judge):
return {**record(key, judge, f'card {key}'), 'record_type': 'knowledge_card'}
def test_reusable_knowledge_comes_before_a_more_relevant_history_note(self):
records = [self.history('old-sync', .9), self.card('a', .6), self.card('b', .55), self.card('c', .52)]
result = self.select(records, {'status': 'judged'}, [])
self.assertEqual([r['id'] for r in result['records']], ['a', 'b', 'c'])
self.assertEqual(result['withheld'], [{'evidence_key': delivery.identity_key(records[0]), 'reason': 'limit'}])
def test_history_needs_strong_relevance_and_gets_at_most_one_slot(self):
records = [self.history('note', .9), self.history('trace', .85, 'conversation_trace'),
self.history('weak-note', .7), self.card('a', .6)]
result = self.select(records, {'status': 'judged'}, [])
self.assertEqual([r['id'] for r in result['records']], ['a', 'note'])
self.assertEqual([w['reason'] for w in result['withheld']], ['history_limit', 'history_below_floor'])
def test_prefixed_hash_titles_are_replaced_too(self):
for title in ('Xkb Case 6769746875625f737461722d', 'Local Readme 064efe10'):
card = {**record('x', .9, 'One main action per shot. More.'), 'title': title}
self.assertEqual(self.select([card], {'status': 'judged'}, [])['records'][0]['title'], 'One main action per shot')
for title in ('Seedance 2.0 workflow', 'Release v1.2 notes'):
card = {**record('x', .9, 'Body.'), 'title': title}
self.assertEqual(self.select([card], {'status': 'judged'}, [])['records'][0]['title'], title)
def test_card_form_fields_are_not_suggested(self):
chunk = lambda key, body: {**record(key, .82, body), 'record_type': 'knowledge_chunk', 'title': '2101602734004953114'}
fields_only = [chunk('claim', '## 2. Claim 等級\n- **等級**:Attested\n - Attested:原文直接引用'),
chunk('rel', '## 6. 與現有知識的關係\n- **2043234633408798932**:無法判定關聯。'),
chunk('rel-tail', '- **2023473551412801929**:看似相關。\n- **2030931033693241543**:無法判定')]
knowledge = chunk('k', '## 3. 關鍵論點\n- **單一主要動作**:一個鏡頭只放一個動作,比較穩定。')
result = self.select(fields_only + [knowledge], {'status': 'judged'}, [])
self.assertEqual([r['id'] for r in result['records']], ['k'])
self.assertEqual(result['records'][0]['title'], '單一主要動作:一個鏡頭只放一個動作,比較穩定')
self.assertEqual({w['reason'] for w in result['withheld']}, {'card_metadata_section'})
def test_long_bodies_keep_whole_paragraphs_and_are_labelled(self):
body = 'First complete paragraph.\n\n' + 'later detail. ' * 200
shown = delivery.excerpt(body)
self.assertTrue(shown.startswith('First complete paragraph.'))
self.assertTrue(shown.endswith('(節錄)'))
single = 'One long sentence. ' * 100
cut = delivery.excerpt(single)
self.assertTrue(cut.endswith('(節錄)'))
self.assertLessEqual(len(cut), delivery.EXCERPT_CHARS + 10)
self.assertEqual(delivery.excerpt('short'), 'short')
def test_fusion_preserves_all_legs_and_strongest_judged_text(self):
source = [record('same', .2, 'weak excerpt', .8),
record('other', .7, score=.95),
record('same', .9, 'actionable excerpt', 2, 'card_keyword')]
ranked = delivery.rank(source, {'status': 'judged'})
self.assertEqual(ranked[0]['id'], 'same')
self.assertEqual(ranked[0]['summary'], 'actionable excerpt')
self.assertEqual(set(ranked[0]['matched_by']), {'wiki_semantic', 'card_keyword'})
self.assertEqual(len(ranked), 2)
anonymous = [record('', .7, 'one'), record('', .8, 'two')]
self.assertEqual(len(delivery.rank(anonymous, {'status': 'judged'})), 2)
def test_delivery_evaluation_does_not_relabel_candidate_results(self):
packet = {'records': [record('useful', .9), record('noise', .2)], 'retrieval_mode': 'keyword',
'judge': {'status': 'judged'}}
packet['delivery'] = self.select(packet['records'], packet['judge'], [])
case = {'id': 'one', 'expected_ids': ['useful'], 'expected_delivery': 'evidence'}
self.assertFalse(score_case(case, packet)['ok'])
self.assertTrue(score_case({**case, 'surface': 'delivery'}, packet)['ok'])
def test_noise_has_explicit_empty_delivery_and_does_not_call_search(self):
with tempfile.TemporaryDirectory() as tmp:
store = service.Store(Path(tmp)/'test.sqlite')
with patch.object(store.catalog, 'search') as search:
packet = store.knowledge_recall('ok')
search.assert_not_called()
self.assertEqual(packet['delivery']['mode'], 'none')
def test_shared_judge_sees_bounded_wiki_candidates_below_legacy_cosine_floor(self):
import continuity_recall as cr
with tempfile.TemporaryDirectory() as tmp, \
patch.object(cr, '_load_semantic_vectors', return_value={'wiki/topics/role.md#Guide': [.6,.8]}), \
patch.object(cr, '_embed_query', return_value=[1.,0.]), \
patch.object(cr, '_section_text', return_value='Use the same character reference in every shot.'), \
patch.object(cr, 'WIKI_MIN_SIMILARITY', .65):
store = service.Store(Path(tmp)/'test.sqlite')
store.catalog.wiki_topics_dir = Path(tmp)/'topics'
self.assertEqual(cr.recall_semantic('The actor changes between shots'), [])
with patch.dict(os.environ, {'XKB_JEV_DECIDE': '1'}):
hits = store.catalog._wiki_search('The actor changes between shots', 1)
self.assertEqual(len(hits), 1)
self.assertEqual(hits[0]['score'], .6)
with patch.dict(os.environ, {'XKB_JEV_DECIDE': '0'}):
self.assertEqual(store.catalog._wiki_search('The actor changes between shots', 1), [])
class GroundedSelection(unittest.TestCase):
def test_upstream_wiki_boundaries_preserve_late_qualifiers(self):
import continuity_recall as cr
long_body = 'Deployment detail. ' * 24 + 'Delete the backup only after verified recovery. Never delete an unverified backup.'
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
(root/'guide.md').write_text('# Deployment\n\n'+long_body, encoding='utf-8')
store = service.Store(root/'test.sqlite')
store.catalog.wiki_topics_dir = root
packet = store.catalog.search('deployment', 5, options={'semantic': False, 'cards': False, 'conversations': False})
body = packet['records'][0]['summary']
self.assertIn('Never delete an unverified backup.', body)
marked = ('Operational detail. ' + '<!-- xkb-candidate:' + 'a'*64 + ' --> ')*18 + 'Delete the backup only after verified recovery.'
with patch.object(cr, '_load_semantic_vectors', return_value={'wiki/topics/guide.md#Guide': [1.,0.]}), \
patch.object(cr, '_embed_query', return_value=[1.,0.]), \
patch.object(cr, '_section_text', return_value=marked):
hit = cr.recall_semantic('deployment', sections_per_document=2, excerpt_limit=2000)[0]
self.assertIn('only after verified recovery.', hit.excerpt)
def test_explicit_attribute_can_recover_a_complementary_section(self):
import continuity_recall as cr
vectors = {'wiki/topics/guide.md#General deployment': [1., 0.],
'wiki/topics/guide.md#More general advice': [.99, .01],
'wiki/topics/guide.md#Record artifact version and source': [.8, .6]}
with patch.object(cr, '_load_semantic_vectors', return_value=vectors), \
patch.object(cr, '_embed_query', return_value=[1., 0.]), \
patch.object(cr, '_base_heading', side_effect=lambda rest, section: section), \
patch.object(cr, '_section_text', side_effect=lambda rest, section: section):
hits = cr.recall_semantic('deployment version source', top_k=2, sections_per_document=2)
self.assertEqual([h.section for h in hits], ['General deployment', 'Record artifact version and source'])
self.assertEqual(hits[1].score, .8)
def test_semantic_recall_can_return_action_beside_same_document_intro(self):
import continuity_recall as cr
vectors = {'wiki/topics/guide.md#Intro': [1., 0.],
'wiki/topics/guide.md#Procedure': [.99, .01]}
with patch.object(cr, '_load_semantic_vectors', return_value=vectors), \
patch.object(cr, '_embed_query', return_value=[1., 0.]), \
patch.object(cr, '_base_heading', side_effect=lambda rest, section: section), \
patch.object(cr, '_section_text', side_effect=lambda rest, section: section + '\n\n' + 'step '*60):
self.assertEqual(len(cr.recall_semantic('workflow', top_k=4)), 1)
hits = cr.recall_semantic('workflow', top_k=4, sections_per_document=2, excerpt_limit=2000)
self.assertEqual([hit.section for hit in hits], ['Intro', 'Procedure'])
self.assertGreater(len(hits[1].excerpt), 200)
self.assertIn('\n\n', hits[1].excerpt)
def test_evaluation_rejects_document_hit_with_useless_excerpt(self):
case = {'id': 'lineage', 'surface': 'delivery', 'expected_ids': ['a'],
'required_excerpt_patterns': ['source', 'version'],
'forbidden_excerpt_patterns': ['page covers']}
packet = {'records': [], 'retrieval_mode': 'fixture',
'delivery': {'status': 'ready', 'records': [record('a', .9, '1.')]}}
self.assertFalse(score_case(case, packet)['ok'])
packet['delivery']['records'][0]['summary'] = 'This page covers source and version.'
self.assertFalse(score_case(case, packet)['ok'])
packet['delivery']['records'][0]['summary'] = 'Keep version. *(self-derived · source: notes.md)*'
self.assertFalse(score_case(case, packet)['ok'])
packet['delivery']['records'][0]['summary'] = 'For every result preserve source and version.'
self.assertTrue(score_case(case, packet)['ok'])
if __name__ == '__main__':
unittest.main()