Spaces:
Running
Running
Food Desert commited on
Commit ·
173ca53
1
Parent(s): 0cd97fa
Preserve user toggled provenance across Rebuild Rows
Browse files- app.py +19 -4
- scripts/smoke_ui_state.py +37 -0
app.py
CHANGED
|
@@ -555,6 +555,14 @@ def _build_toggle_rows(
|
|
| 555 |
)
|
| 556 |
)
|
| 557 |
selected_index: Dict[str, int] = {t: i for i, t in enumerate(selected_active)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 558 |
|
| 559 |
row_defs: List[Dict[str, Any]] = []
|
| 560 |
enabled_group_tag_sets: Dict[str, Set[str]] = {
|
|
@@ -605,7 +613,7 @@ def _build_toggle_rows(
|
|
| 605 |
retrieved_other_meta = {
|
| 606 |
t: {
|
| 607 |
"origin": _normalize_selection_origin(tag_selection_origins.get(t, "selection")),
|
| 608 |
-
"preselected": t
|
| 609 |
}
|
| 610 |
for t in merged_retrieved_other
|
| 611 |
}
|
|
@@ -632,7 +640,7 @@ def _build_toggle_rows(
|
|
| 632 |
selected_other_meta = {
|
| 633 |
t: {
|
| 634 |
"origin": _normalize_selection_origin(tag_selection_origins.get(t, "selection")),
|
| 635 |
-
"preselected":
|
| 636 |
}
|
| 637 |
for t in selected_other
|
| 638 |
}
|
|
@@ -668,7 +676,7 @@ def _build_toggle_rows(
|
|
| 668 |
tag_meta = {
|
| 669 |
t: {
|
| 670 |
"origin": _normalize_selection_origin(tag_selection_origins.get(t, "selection")),
|
| 671 |
-
"preselected": t
|
| 672 |
}
|
| 673 |
for t in merged
|
| 674 |
}
|
|
@@ -1010,6 +1018,7 @@ def _rebuild_rows_from_selected(
|
|
| 1010 |
if t and not _is_artist_tag(t) and not _is_excluded_recommendation_tag(t)
|
| 1011 |
)
|
| 1012 |
)
|
|
|
|
| 1013 |
|
| 1014 |
retrieved_candidate_tags: List[str] = []
|
| 1015 |
tag_selection_origins: Dict[str, str] = {}
|
|
@@ -1025,7 +1034,13 @@ def _rebuild_rows_from_selected(
|
|
| 1025 |
retrieved_candidate_tags.append(tn)
|
| 1026 |
if tn not in tag_selection_origins:
|
| 1027 |
meta = row_meta.get(t, {}) if isinstance(row_meta.get(t, {}), dict) else {}
|
| 1028 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1029 |
|
| 1030 |
for t in selected_active:
|
| 1031 |
tag_selection_origins.setdefault(t, "user")
|
|
|
|
| 555 |
)
|
| 556 |
)
|
| 557 |
selected_index: Dict[str, int] = {t: i for i, t in enumerate(selected_active)}
|
| 558 |
+
selected_set: Set[str] = set(selected_active)
|
| 559 |
+
|
| 560 |
+
def _is_pipeline_preselected(tag: str) -> bool:
|
| 561 |
+
# Tags explicitly user-toggled should keep user coloring after row rebuilds.
|
| 562 |
+
# Only non-user selected tags should render as pipeline-preselected.
|
| 563 |
+
if tag not in selected_set:
|
| 564 |
+
return False
|
| 565 |
+
return _normalize_selection_origin(tag_selection_origins.get(tag, "selection")) != "user"
|
| 566 |
|
| 567 |
row_defs: List[Dict[str, Any]] = []
|
| 568 |
enabled_group_tag_sets: Dict[str, Set[str]] = {
|
|
|
|
| 613 |
retrieved_other_meta = {
|
| 614 |
t: {
|
| 615 |
"origin": _normalize_selection_origin(tag_selection_origins.get(t, "selection")),
|
| 616 |
+
"preselected": _is_pipeline_preselected(t),
|
| 617 |
}
|
| 618 |
for t in merged_retrieved_other
|
| 619 |
}
|
|
|
|
| 640 |
selected_other_meta = {
|
| 641 |
t: {
|
| 642 |
"origin": _normalize_selection_origin(tag_selection_origins.get(t, "selection")),
|
| 643 |
+
"preselected": _is_pipeline_preselected(t),
|
| 644 |
}
|
| 645 |
for t in selected_other
|
| 646 |
}
|
|
|
|
| 676 |
tag_meta = {
|
| 677 |
t: {
|
| 678 |
"origin": _normalize_selection_origin(tag_selection_origins.get(t, "selection")),
|
| 679 |
+
"preselected": _is_pipeline_preselected(t),
|
| 680 |
}
|
| 681 |
for t in merged
|
| 682 |
}
|
|
|
|
| 1018 |
if t and not _is_artist_tag(t) and not _is_excluded_recommendation_tag(t)
|
| 1019 |
)
|
| 1020 |
)
|
| 1021 |
+
selected_active_set: Set[str] = set(selected_active)
|
| 1022 |
|
| 1023 |
retrieved_candidate_tags: List[str] = []
|
| 1024 |
tag_selection_origins: Dict[str, str] = {}
|
|
|
|
| 1034 |
retrieved_candidate_tags.append(tn)
|
| 1035 |
if tn not in tag_selection_origins:
|
| 1036 |
meta = row_meta.get(t, {}) if isinstance(row_meta.get(t, {}), dict) else {}
|
| 1037 |
+
meta_origin = _normalize_selection_origin(str(meta.get("origin", "selection")))
|
| 1038 |
+
meta_preselected = bool(meta.get("preselected", False))
|
| 1039 |
+
# Preserve explicit user toggles across rebuild:
|
| 1040 |
+
# if a currently selected tag was not pipeline-preselected, keep user provenance.
|
| 1041 |
+
if tn in selected_active_set and not meta_preselected:
|
| 1042 |
+
meta_origin = "user"
|
| 1043 |
+
tag_selection_origins[tn] = meta_origin
|
| 1044 |
|
| 1045 |
for t in selected_active:
|
| 1046 |
tag_selection_origins.setdefault(t, "user")
|
scripts/smoke_ui_state.py
CHANGED
|
@@ -189,6 +189,42 @@ def test_toggle_then_rebuild_does_not_resurrect_removed_tag() -> None:
|
|
| 189 |
_assert("cub" in prompt_after_rebuild, "other retrieved selection should remain")
|
| 190 |
|
| 191 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
def test_toggle_does_not_cross_activate_unrelated_row_tag() -> None:
|
| 193 |
row_defs = [
|
| 194 |
{"name": "organization", "label": "Organization", "tags": ["pinup", "close-up"], "tag_meta": {}},
|
|
@@ -268,6 +304,7 @@ def main() -> None:
|
|
| 268 |
test_row_deduping()
|
| 269 |
test_rebuild_ignores_stale_selected_state()
|
| 270 |
test_toggle_then_rebuild_does_not_resurrect_removed_tag()
|
|
|
|
| 271 |
test_toggle_does_not_cross_activate_unrelated_row_tag()
|
| 272 |
test_shared_tag_mirrors_without_unrelated_cross_toggle()
|
| 273 |
print("ui state smoke: ok")
|
|
|
|
| 189 |
_assert("cub" in prompt_after_rebuild, "other retrieved selection should remain")
|
| 190 |
|
| 191 |
|
| 192 |
+
def test_rebuild_preserves_user_toggled_provenance() -> None:
|
| 193 |
+
row_defs = [
|
| 194 |
+
{
|
| 195 |
+
"name": "demo_row",
|
| 196 |
+
"label": "Demo Row",
|
| 197 |
+
"tags": ["base_tag", "manual_tag"],
|
| 198 |
+
"tag_meta": {
|
| 199 |
+
"base_tag": {"origin": "selection", "preselected": True},
|
| 200 |
+
"manual_tag": {"origin": "selection", "preselected": False},
|
| 201 |
+
},
|
| 202 |
+
}
|
| 203 |
+
]
|
| 204 |
+
selected_state = ["base_tag", "manual_tag"]
|
| 205 |
+
row_values_state = [["base_tag", "manual_tag"]]
|
| 206 |
+
out = app._rebuild_rows_from_selected(
|
| 207 |
+
selected_state,
|
| 208 |
+
row_defs,
|
| 209 |
+
row_values_state,
|
| 210 |
+
app.display_top_groups_default,
|
| 211 |
+
app.display_top_tags_per_group_default,
|
| 212 |
+
app.display_rank_top_k_default,
|
| 213 |
+
)
|
| 214 |
+
rebuilt_rows = out[6]
|
| 215 |
+
manual_meta = None
|
| 216 |
+
for row in rebuilt_rows:
|
| 217 |
+
tags = row.get("tags", []) if isinstance(row, dict) else []
|
| 218 |
+
if "manual_tag" in tags:
|
| 219 |
+
row_meta = row.get("tag_meta", {}) if isinstance(row.get("tag_meta", {}), dict) else {}
|
| 220 |
+
manual_meta = row_meta.get("manual_tag")
|
| 221 |
+
if manual_meta:
|
| 222 |
+
break
|
| 223 |
+
_assert(manual_meta is not None, "manual_tag metadata missing after rebuild")
|
| 224 |
+
_assert(manual_meta.get("origin") == "user", "rebuild should preserve manual_tag origin as user")
|
| 225 |
+
_assert(manual_meta.get("preselected") is False, "rebuild should preserve manual_tag preselected=False")
|
| 226 |
+
|
| 227 |
+
|
| 228 |
def test_toggle_does_not_cross_activate_unrelated_row_tag() -> None:
|
| 229 |
row_defs = [
|
| 230 |
{"name": "organization", "label": "Organization", "tags": ["pinup", "close-up"], "tag_meta": {}},
|
|
|
|
| 304 |
test_row_deduping()
|
| 305 |
test_rebuild_ignores_stale_selected_state()
|
| 306 |
test_toggle_then_rebuild_does_not_resurrect_removed_tag()
|
| 307 |
+
test_rebuild_preserves_user_toggled_provenance()
|
| 308 |
test_toggle_does_not_cross_activate_unrelated_row_tag()
|
| 309 |
test_shared_tag_mirrors_without_unrelated_cross_toggle()
|
| 310 |
print("ui state smoke: ok")
|