ping98k commited on
Commit
c0bf2b8
·
1 Parent(s): c29b692

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +27 -45
main.py CHANGED
@@ -18,37 +18,35 @@ def generate_players(instruction, n):
18
  )
19
  return [c.message.content.strip() for c in response.choices]
20
 
21
- def run_tournament(instruction_input, criteria_input, n_gen,
22
- num_top_picks, pool_size, max_workers):
23
  instruction = instruction_input.strip()
24
- criteria_list = [c.strip() for c in criteria_input.split(",") if c.strip()] or [
25
- "Factuality", "Instruction Following", "Precision"
26
- ]
27
  n_gen = int(n_gen)
28
  num_top_picks = int(num_top_picks)
29
  pool_size = int(pool_size)
30
  max_workers = int(max_workers)
31
-
 
 
 
 
 
 
32
  def criteria_block():
33
  return "\n".join(f"{i + 1}) {c}" for i, c in enumerate(criteria_list))
34
-
35
  def prompt_score(player):
36
  prompt = f"""Evaluate the output below on the following criteria:
37
  {criteria_block()}
38
 
39
- Return JSON exactly like: {{"score": [{', '.join(['1-10'] * len(criteria_list))}]}}.
40
 
41
  Instruction:
42
  {instruction}
43
 
44
  Output:
45
  {player}"""
46
- response = completion(
47
- model="gpt-4o-mini",
48
- messages=[{"role": "system", "content": prompt}]
49
- )
50
  return response.choices[0].message.content.strip()
51
-
52
  def score(player):
53
  try:
54
  data = json.loads(prompt_score(player))
@@ -56,12 +54,16 @@ Output:
56
  data = eval(prompt_score(player))
57
  lst = data.get("score", data.get("scores", []))
58
  return sum(lst) / len(lst) if lst else 0.0
59
-
 
 
 
 
60
  def prompt_play(a, b):
61
  prompt = f"""Compare the two players below using:
62
  {criteria_block()}
63
 
64
- Return ONLY JSON {{"winner": "A"}} or {{"winner": "B"}}.
65
 
66
  Instruction:
67
  {instruction}
@@ -69,26 +71,14 @@ Instruction:
69
  Players:
70
  <A>{a}</A>
71
  <B>{b}</B>"""
72
- response = completion(
73
- model="gpt-4o-mini",
74
- messages=[{"role": "system", "content": prompt}]
75
- )
76
  return response.choices[0].message.content.strip()
77
-
78
  def play(a, b):
79
  try:
80
  winner_label = json.loads(prompt_play(a, b))["winner"]
81
  except json.JSONDecodeError:
82
  winner_label = eval(prompt_play(a, b)).get("winner", "A")
83
  return a if winner_label == "A" else b
84
-
85
- def precompute_scores(players, executor):
86
- futures = {executor.submit(score, p): p for p in players}
87
- scores = {}
88
- for fut in tqdm(as_completed(futures), total=len(futures)):
89
- scores[futures[fut]] = fut.result()
90
- return scores
91
-
92
  def tournament_round(pairs, executor):
93
  futures = {executor.submit(play, a, b): (a, b) for a, b in pairs}
94
  results = []
@@ -98,7 +88,6 @@ Players:
98
  loser = b if winner == a else a
99
  results.append((winner, loser))
100
  return results
101
-
102
  def tournament(players, executor):
103
  lost_to = {}
104
  current = players[:]
@@ -110,36 +99,26 @@ Players:
110
  if len(players) % 2 == 1:
111
  current.append(players[-1])
112
  return current[0], lost_to
113
-
114
  def get_candidates(champion, lost_to):
115
  return [p for p, o in lost_to.items() if o == champion] + [champion]
116
-
117
  def playoff(candidates, executor):
118
  wins = {p: 0 for p in candidates}
119
- pairs = [(candidates[i], candidates[j])
120
- for i in range(len(candidates))
121
- for j in range(i + 1, len(candidates))]
122
  futures = {executor.submit(play, a, b): (a, b) for a, b in pairs}
123
  for fut in tqdm(as_completed(futures), total=len(futures)):
124
  wins[fut.result()] += 1
125
  return sorted(candidates, key=lambda p: wins[p], reverse=True)
126
-
127
  def get_top(players, executor):
128
  champion, lost_to = tournament(players, executor)
129
  runner_up = lost_to.get(champion)
130
  finalists = [champion] + ([runner_up] if runner_up else [])
131
- semifinalists = [p for p, o in lost_to.items()
132
- if o in finalists and p not in finalists]
133
- candidates = set(finalists + semifinalists +
134
- get_candidates(champion, lost_to))
135
  return playoff(list(candidates), executor)[:num_top_picks]
136
-
137
- all_players = generate_players(instruction, n_gen)
138
  with ThreadPoolExecutor(max_workers=max_workers) as ex:
139
- scores = precompute_scores(all_players, ex)
140
- top_players = sorted(all_players, key=scores.get, reverse=True)[:pool_size]
141
  top_k = get_top(top_players, ex)
142
- return ", ".join(top_k)
143
 
144
  demo = gr.Interface(
145
  fn=run_tournament,
@@ -151,7 +130,10 @@ demo = gr.Interface(
151
  gr.Number(value=POOL_SIZE_DEFAULT, label="Filter Size"),
152
  gr.Number(value=MAX_WORKERS_DEFAULT, label="Max Workers")
153
  ],
154
- outputs=gr.Textbox(label="Top picks")
 
 
 
155
  )
156
 
157
  if __name__ == "__main__":
 
18
  )
19
  return [c.message.content.strip() for c in response.choices]
20
 
21
+ def run_tournament(instruction_input, criteria_input, n_gen, num_top_picks, pool_size, max_workers):
 
22
  instruction = instruction_input.strip()
23
+ criteria_list = [c.strip() for c in criteria_input.split(",") if c.strip()] or ["Factuality", "Instruction Following", "Precision"]
 
 
24
  n_gen = int(n_gen)
25
  num_top_picks = int(num_top_picks)
26
  pool_size = int(pool_size)
27
  max_workers = int(max_workers)
28
+ process_log = []
29
+ def log(msg):
30
+ process_log.append(msg)
31
+ yield "\n".join(process_log), ""
32
+ yield from log("Generating players …")
33
+ all_players = generate_players(instruction, n_gen)
34
+ yield from log(f"{len(all_players)} players generated")
35
  def criteria_block():
36
  return "\n".join(f"{i + 1}) {c}" for i, c in enumerate(criteria_list))
 
37
  def prompt_score(player):
38
  prompt = f"""Evaluate the output below on the following criteria:
39
  {criteria_block()}
40
 
41
+ Return JSON exactly like: {{\"score\": [{', '.join(['1-10'] * len(criteria_list))}]}}.
42
 
43
  Instruction:
44
  {instruction}
45
 
46
  Output:
47
  {player}"""
48
+ response = completion(model="gpt-4o-mini", messages=[{"role": "system", "content": prompt}])
 
 
 
49
  return response.choices[0].message.content.strip()
 
50
  def score(player):
51
  try:
52
  data = json.loads(prompt_score(player))
 
54
  data = eval(prompt_score(player))
55
  lst = data.get("score", data.get("scores", []))
56
  return sum(lst) / len(lst) if lst else 0.0
57
+ yield from log("Scoring players …")
58
+ with ThreadPoolExecutor(max_workers=max_workers) as ex:
59
+ scores = {p: s for p, s in zip(all_players, list(tqdm(ex.map(score, all_players), total=len(all_players))))}
60
+ top_players = sorted(all_players, key=scores.get, reverse=True)[:pool_size]
61
+ yield from log(f"Filtered to {len(top_players)} players with best scores")
62
  def prompt_play(a, b):
63
  prompt = f"""Compare the two players below using:
64
  {criteria_block()}
65
 
66
+ Return ONLY JSON {{\"winner\": \"A\"}} or {{\"winner\": \"B\"}}.
67
 
68
  Instruction:
69
  {instruction}
 
71
  Players:
72
  <A>{a}</A>
73
  <B>{b}</B>"""
74
+ response = completion(model="gpt-4o-mini", messages=[{"role": "system", "content": prompt}])
 
 
 
75
  return response.choices[0].message.content.strip()
 
76
  def play(a, b):
77
  try:
78
  winner_label = json.loads(prompt_play(a, b))["winner"]
79
  except json.JSONDecodeError:
80
  winner_label = eval(prompt_play(a, b)).get("winner", "A")
81
  return a if winner_label == "A" else b
 
 
 
 
 
 
 
 
82
  def tournament_round(pairs, executor):
83
  futures = {executor.submit(play, a, b): (a, b) for a, b in pairs}
84
  results = []
 
88
  loser = b if winner == a else a
89
  results.append((winner, loser))
90
  return results
 
91
  def tournament(players, executor):
92
  lost_to = {}
93
  current = players[:]
 
99
  if len(players) % 2 == 1:
100
  current.append(players[-1])
101
  return current[0], lost_to
 
102
  def get_candidates(champion, lost_to):
103
  return [p for p, o in lost_to.items() if o == champion] + [champion]
 
104
  def playoff(candidates, executor):
105
  wins = {p: 0 for p in candidates}
106
+ pairs = [(candidates[i], candidates[j]) for i in range(len(candidates)) for j in range(i + 1, len(candidates))]
 
 
107
  futures = {executor.submit(play, a, b): (a, b) for a, b in pairs}
108
  for fut in tqdm(as_completed(futures), total=len(futures)):
109
  wins[fut.result()] += 1
110
  return sorted(candidates, key=lambda p: wins[p], reverse=True)
 
111
  def get_top(players, executor):
112
  champion, lost_to = tournament(players, executor)
113
  runner_up = lost_to.get(champion)
114
  finalists = [champion] + ([runner_up] if runner_up else [])
115
+ semifinalists = [p for p, o in lost_to.items() if o in finalists and p not in finalists]
116
+ candidates = set(finalists + semifinalists + get_candidates(champion, lost_to))
 
 
117
  return playoff(list(candidates), executor)[:num_top_picks]
118
+ yield from log("Running tournament …")
 
119
  with ThreadPoolExecutor(max_workers=max_workers) as ex:
 
 
120
  top_k = get_top(top_players, ex)
121
+ yield "\n".join(process_log + ["Done"]), ", ".join(top_k)
122
 
123
  demo = gr.Interface(
124
  fn=run_tournament,
 
130
  gr.Number(value=POOL_SIZE_DEFAULT, label="Filter Size"),
131
  gr.Number(value=MAX_WORKERS_DEFAULT, label="Max Workers")
132
  ],
133
+ outputs=[
134
+ gr.Textbox(lines=10, label="Process"),
135
+ gr.Textbox(label="Top picks")
136
+ ]
137
  )
138
 
139
  if __name__ == "__main__":