fix: 컷별 댓글 배정을 컷 우선이 아닌 순위(라운드) 우선으로 변경
컷 하나를 4순위까지 다 채운 뒤 다음 컷으로 넘어가면, 앞 컷의 약한 근거(4순위 좋아요)가 뒤 컷의 강한 근거(3순위 단어 겹침)보다 먼저 댓글을 가로챈다. 라운드를 바깥 루프로 두어(전 컷의 ts → 전 컷의 ai → 전 컷의 word → 전 컷의 like) 순위가 컷 순서를 이기게 했다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
011c042778
commit
7c74fec079
@ -97,7 +97,12 @@ def build_cut_picks(cuts, comments, ai_picks: Optional[Dict[int, List[int]]],
|
|||||||
단어 겹침이 AI 다음인 이유: Gemini 는 문맥까지 보고 고르니 더 정확하지만, 503 등으로
|
단어 겹침이 AI 다음인 이유: Gemini 는 문맥까지 보고 고르니 더 정확하지만, 503 등으로
|
||||||
실패하거나(`ai_picks=None`) 문맥상 연결을 놓칠 때(예: "와인 뱉는 장면" ↔ "싱크대로 달려간
|
실패하거나(`ai_picks=None`) 문맥상 연결을 놓칠 때(예: "와인 뱉는 장면" ↔ "싱크대로 달려간
|
||||||
이유"는 겹치는 단어가 없다) 그물을 하나 더 치는 것 — 네트워크 없이도 항상 동작한다.
|
이유"는 겹치는 단어가 없다) 그물을 하나 더 치는 것 — 네트워크 없이도 항상 동작한다.
|
||||||
중복은 앞 컷이 가져간다(뒤 컷은 다음 후보로 밀린다).
|
|
||||||
|
⚠ 컷별로 4단계를 다 채우고 다음 컷으로 넘어가면 안 된다 — 앞 컷의 약한 근거(4순위
|
||||||
|
좋아요)가 뒤 컷의 강한 근거(3순위 단어 겹침)보다 먼저 댓글을 가져가 버린다. 그래서
|
||||||
|
**단계(라운드)를 바깥 루프, 컷을 안쪽 루프**로 둔다 — 전 컷의 ts를 다 채운 뒤에야
|
||||||
|
전 컷의 ai로, 그다음에야 word로 넘어간다. 순위가 컷 순서보다 우선한다.
|
||||||
|
중복은 앞 컷이 가져간다(뒤 컷은 다음 후보로 밀린다) — `used` 는 라운드·컷을 통틀어 공유.
|
||||||
|
|
||||||
ai_picks: {컷인덱스: [댓글idx …]} — Gemini 실패 시 None/{} 어느 쪽을 넘겨도
|
ai_picks: {컷인덱스: [댓글idx …]} — Gemini 실패 시 None/{} 어느 쪽을 넘겨도
|
||||||
타임스탬프만으로 채운다(`ai_pick_cuts` 는 실패를 None 으로 알린다).
|
타임스탬프만으로 채운다(`ai_pick_cuts` 는 실패를 None 으로 알린다).
|
||||||
@ -107,33 +112,43 @@ def build_cut_picks(cuts, comments, ai_picks: Optional[Dict[int, List[int]]],
|
|||||||
valid = {c["idx"] for c in comments}
|
valid = {c["idx"] for c in comments}
|
||||||
no_ts = [c for c in comments if not c.get("times")]
|
no_ts = [c for c in comments if not c.get("times")]
|
||||||
used: set = set()
|
used: set = set()
|
||||||
out: List[List[dict]] = []
|
quota = [quotas[i] if i < len(quotas) else 0 for i in range(len(cuts))]
|
||||||
|
out: List[List[dict]] = [[] for _ in cuts]
|
||||||
|
|
||||||
|
# 1라운드: ⭐시각
|
||||||
for i, cut in enumerate(cuts):
|
for i, cut in enumerate(cuts):
|
||||||
quota = quotas[i] if i < len(quotas) else 0
|
|
||||||
picks: List[dict] = []
|
|
||||||
for idx in match_ranges(comments, [(cut["start"], cut["end"])]):
|
for idx in match_ranges(comments, [(cut["start"], cut["end"])]):
|
||||||
if len(picks) >= quota:
|
if len(out[i]) >= quota[i]:
|
||||||
break
|
break
|
||||||
if idx not in used:
|
if idx not in used:
|
||||||
picks.append({"idx": idx, "why": "ts"})
|
out[i].append({"idx": idx, "why": "ts"})
|
||||||
used.add(idx)
|
used.add(idx)
|
||||||
|
# 2라운드: 🤖AI
|
||||||
|
for i in range(len(cuts)):
|
||||||
|
if len(out[i]) >= quota[i]:
|
||||||
|
continue
|
||||||
for idx in (ai_picks.get(i) or []):
|
for idx in (ai_picks.get(i) or []):
|
||||||
if len(picks) >= quota:
|
if len(out[i]) >= quota[i]:
|
||||||
break
|
break
|
||||||
if idx in valid and idx not in used:
|
if idx in valid and idx not in used:
|
||||||
picks.append({"idx": idx, "why": "ai"})
|
out[i].append({"idx": idx, "why": "ai"})
|
||||||
used.add(idx)
|
used.add(idx)
|
||||||
if len(picks) < quota:
|
# 3라운드: 🔤단어겹침
|
||||||
for idx in _word_match_ranked(cut, comments, used):
|
for i, cut in enumerate(cuts):
|
||||||
if len(picks) >= quota:
|
if len(out[i]) >= quota[i]:
|
||||||
break
|
continue
|
||||||
picks.append({"idx": idx, "why": "word"})
|
for idx in _word_match_ranked(cut, comments, used):
|
||||||
used.add(idx)
|
if len(out[i]) >= quota[i]:
|
||||||
if len(picks) < quota:
|
break
|
||||||
for idx in top_liked(no_ts, used, quota - len(picks)):
|
out[i].append({"idx": idx, "why": "word"})
|
||||||
picks.append({"idx": idx, "why": "like"})
|
used.add(idx)
|
||||||
used.add(idx)
|
# 4라운드: ➕좋아요
|
||||||
out.append(picks)
|
for i in range(len(cuts)):
|
||||||
|
if len(out[i]) >= quota[i]:
|
||||||
|
continue
|
||||||
|
for idx in top_liked(no_ts, used, quota[i] - len(out[i])):
|
||||||
|
out[i].append({"idx": idx, "why": "like"})
|
||||||
|
used.add(idx)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user