def incremental_filter(image_pool, space, style, mood,
color, materials, layout, lighting):
# Stage 1 — Tier 1: hard filter, keep top 50%
candidates = filter_by(image_pool, [
CLIP_MAPPINGS["space"][space],
CLIP_MAPPINGS["color"][color],
", ".join([CLIP_MAPPINGS["materials"][m] for m in materials]),
], keep_top=0.5)
# Stage 2 — Tier 2: re-rank, keep top 50% of remaining
candidates = filter_by(candidates, [
CLIP_MAPPINGS["style"][style],
CLIP_MAPPINGS["lighting"][lighting],
], keep_top=0.5)
# Stage 3 — Tier 3: final re-rank
candidates = filter_by(candidates, [
CLIP_MAPPINGS["layout"][layout],
CLIP_MAPPINGS["mood"][mood],
], keep_top=1.0) # keep all, just re-rank
return candidates
def filter_by(images, descriptions, keep_top=0.5):
scored = []
for image in images:
score = sum(clip_similarity(image, d) for d in descriptions)
scored.append((image, score))
scored.sort(key=lambda x: x[1], reverse=True)
cutoff = max(1, int(len(scored) * keep_top))
return [img for img, _ in scored[:cutoff]]# your code goes here
ZGVmIGluY3JlbWVudGFsX2ZpbHRlcihpbWFnZV9wb29sLCBzcGFjZSwgc3R5bGUsIG1vb2QsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2xvciwgbWF0ZXJpYWxzLCBsYXlvdXQsIGxpZ2h0aW5nKToKCiAgICAjIFN0YWdlIDEg4oCUIFRpZXIgMTogaGFyZCBmaWx0ZXIsIGtlZXAgdG9wIDUwJQogICAgY2FuZGlkYXRlcyA9IGZpbHRlcl9ieShpbWFnZV9wb29sLCBbCiAgICAgICAgQ0xJUF9NQVBQSU5HU1sic3BhY2UiXVtzcGFjZV0sCiAgICAgICAgQ0xJUF9NQVBQSU5HU1siY29sb3IiXVtjb2xvcl0sCiAgICAgICAgIiwgIi5qb2luKFtDTElQX01BUFBJTkdTWyJtYXRlcmlhbHMiXVttXSBmb3IgbSBpbiBtYXRlcmlhbHNdKSwKICAgIF0sIGtlZXBfdG9wPTAuNSkKCiAgICAjIFN0YWdlIDIg4oCUIFRpZXIgMjogcmUtcmFuaywga2VlcCB0b3AgNTAlIG9mIHJlbWFpbmluZwogICAgY2FuZGlkYXRlcyA9IGZpbHRlcl9ieShjYW5kaWRhdGVzLCBbCiAgICAgICAgQ0xJUF9NQVBQSU5HU1sic3R5bGUiXVtzdHlsZV0sCiAgICAgICAgQ0xJUF9NQVBQSU5HU1sibGlnaHRpbmciXVtsaWdodGluZ10sCiAgICBdLCBrZWVwX3RvcD0wLjUpCgogICAgIyBTdGFnZSAzIOKAlCBUaWVyIDM6IGZpbmFsIHJlLXJhbmsKICAgIGNhbmRpZGF0ZXMgPSBmaWx0ZXJfYnkoY2FuZGlkYXRlcywgWwogICAgICAgIENMSVBfTUFQUElOR1NbImxheW91dCJdW2xheW91dF0sCiAgICAgICAgQ0xJUF9NQVBQSU5HU1sibW9vZCJdW21vb2RdLAogICAgXSwga2VlcF90b3A9MS4wKSAgICMga2VlcCBhbGwsIGp1c3QgcmUtcmFuawoKICAgIHJldHVybiBjYW5kaWRhdGVzCgoKZGVmIGZpbHRlcl9ieShpbWFnZXMsIGRlc2NyaXB0aW9ucywga2VlcF90b3A9MC41KToKICAgIHNjb3JlZCA9IFtdCiAgICBmb3IgaW1hZ2UgaW4gaW1hZ2VzOgogICAgICAgIHNjb3JlID0gc3VtKGNsaXBfc2ltaWxhcml0eShpbWFnZSwgZCkgZm9yIGQgaW4gZGVzY3JpcHRpb25zKQogICAgICAgIHNjb3JlZC5hcHBlbmQoKGltYWdlLCBzY29yZSkpCgogICAgc2NvcmVkLnNvcnQoa2V5PWxhbWJkYSB4OiB4WzFdLCByZXZlcnNlPVRydWUpCiAgICBjdXRvZmYgPSBtYXgoMSwgaW50KGxlbihzY29yZWQpICoga2VlcF90b3ApKQogICAgcmV0dXJuIFtpbWcgZm9yIGltZywgXyBpbiBzY29yZWRbOmN1dG9mZl1dIyB5b3VyIGNvZGUgZ29lcyBoZXJl