Update app.py
Browse files
app.py
CHANGED
|
@@ -6,9 +6,22 @@ import threading
|
|
| 6 |
import gradio as gr
|
| 7 |
from sentence_transformers import SentenceTransformer, util
|
| 8 |
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
MAX_CONCURRENT_JOBS = 7
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
print("Loading embedding model...")
|
| 13 |
embedder = SentenceTransformer(EMBED_MODEL_ID)
|
| 14 |
print("β
Ready")
|
|
@@ -73,15 +86,19 @@ def _clean_tags(tags: str) -> str:
|
|
| 73 |
return ", ".join(kept) if kept else tags # never return empty
|
| 74 |
|
| 75 |
|
| 76 |
-
def _select_best_position(script: str, videos: list)
|
| 77 |
if not videos:
|
| 78 |
-
return None
|
| 79 |
tag_strings = [_clean_tags(v.get("tags", "")) for v in videos]
|
| 80 |
|
| 81 |
-
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
sims = util.cos_sim(
|
| 85 |
best_idx = int(sims.argmax())
|
| 86 |
return videos[best_idx].get("position"), float(sims[best_idx])
|
| 87 |
|
|
@@ -116,6 +133,7 @@ def _select_best_videos(scenes_data: dict) -> list:
|
|
| 116 |
"scene": scene_num,
|
| 117 |
"script": script,
|
| 118 |
"status": "ok",
|
|
|
|
| 119 |
"video": {
|
| 120 |
"position": chosen.get("position"),
|
| 121 |
"id": chosen.get("id"),
|
|
@@ -151,8 +169,9 @@ def gradio_select_best(json_text):
|
|
| 151 |
lines.append(f"| {r['scene']} | {r['script']} | β | β | *no candidates* | β |")
|
| 152 |
else:
|
| 153 |
v = r["video"]
|
|
|
|
| 154 |
lines.append(
|
| 155 |
-
f"| {r['scene']} | {r['script']} | {v['id']} | {v['similarity']} | {v['tags']} | {v['pageURL']} |"
|
| 156 |
)
|
| 157 |
return "\n".join(lines)
|
| 158 |
except Exception as e:
|
|
|
|
| 6 |
import gradio as gr
|
| 7 |
from sentence_transformers import SentenceTransformer, util
|
| 8 |
|
| 9 |
+
# e5-small-v2 is trained specifically for asymmetric query->passage retrieval
|
| 10 |
+
# (short query vs. longer descriptive text) using "query: "/"passage: "
|
| 11 |
+
# prefixes. This handles short, title-style script lines ("Short Script on
|
| 12 |
+
# AI.") far more reliably than a generic sentence-similarity model, which
|
| 13 |
+
# has almost nothing to embed against in a 4-word input and falls back to
|
| 14 |
+
# near-arbitrary rankings.
|
| 15 |
+
EMBED_MODEL_ID = "intfloat/e5-small-v2"
|
| 16 |
MAX_CONCURRENT_JOBS = 7
|
| 17 |
|
| 18 |
+
# Below this cosine similarity, treat the pick as unreliable rather than
|
| 19 |
+
# silently returning a low-confidence guess. e5 cosine scores for genuinely
|
| 20 |
+
# relevant pairs typically sit higher than raw MiniLM scores did, but this
|
| 21 |
+
# is a starting point β tune it against your own data if it flags too many
|
| 22 |
+
# or too few scenes.
|
| 23 |
+
LOW_CONFIDENCE_THRESHOLD = 0.78
|
| 24 |
+
|
| 25 |
print("Loading embedding model...")
|
| 26 |
embedder = SentenceTransformer(EMBED_MODEL_ID)
|
| 27 |
print("β
Ready")
|
|
|
|
| 86 |
return ", ".join(kept) if kept else tags # never return empty
|
| 87 |
|
| 88 |
|
| 89 |
+
def _select_best_position(script: str, videos: list):
|
| 90 |
if not videos:
|
| 91 |
+
return None, None
|
| 92 |
tag_strings = [_clean_tags(v.get("tags", "")) for v in videos]
|
| 93 |
|
| 94 |
+
# e5 convention: "query: " for the search text, "passage: " for the
|
| 95 |
+
# candidate documents being ranked against it.
|
| 96 |
+
query_emb = embedder.encode(f"query: {script}", convert_to_tensor=True)
|
| 97 |
+
passage_embs = embedder.encode(
|
| 98 |
+
[f"passage: {t}" for t in tag_strings], convert_to_tensor=True
|
| 99 |
+
)
|
| 100 |
|
| 101 |
+
sims = util.cos_sim(query_emb, passage_embs)[0] # shape: (num_candidates,)
|
| 102 |
best_idx = int(sims.argmax())
|
| 103 |
return videos[best_idx].get("position"), float(sims[best_idx])
|
| 104 |
|
|
|
|
| 133 |
"scene": scene_num,
|
| 134 |
"script": script,
|
| 135 |
"status": "ok",
|
| 136 |
+
"low_confidence": score < LOW_CONFIDENCE_THRESHOLD,
|
| 137 |
"video": {
|
| 138 |
"position": chosen.get("position"),
|
| 139 |
"id": chosen.get("id"),
|
|
|
|
| 169 |
lines.append(f"| {r['scene']} | {r['script']} | β | β | *no candidates* | β |")
|
| 170 |
else:
|
| 171 |
v = r["video"]
|
| 172 |
+
flag = " β οΈ" if r.get("low_confidence") else ""
|
| 173 |
lines.append(
|
| 174 |
+
f"| {r['scene']} | {r['script']} | {v['id']} | {v['similarity']}{flag} | {v['tags']} | {v['pageURL']} |"
|
| 175 |
)
|
| 176 |
return "\n".join(lines)
|
| 177 |
except Exception as e:
|