from functools import partial import gradio as gr import os import csv import pandas as pd import pickle def load_results(gen_file, grader_file, exp_name, model_name, grader): record = [] if 'llama' in model_name: version = exp_name.split('_')[2] k = exp_name.split('_')[0] if k == 'k2' and version == 'v8': return [] if k != 'k2' and version == 'v9': return [] # read csv file with open(gen_file, 'r') as file: reader = csv.reader(file) gen = list(reader) with open(grader_file, 'r') as file: reader = csv.reader(file) grade = list(reader) # print(gen_file, grader_file) # print(gen[0], grade[0]) if len(gen) != len(grade): # print("ERROR: len(gen) != len(grade)") # print(gen_file, grader_file) return [] else: # print(gen[0], grade[0]) # exit(0) #['k', 'skills', 'topic', 'system prompt', '[INST]_0', '[/INST]_0', 'model_input_0', 'text_0', '[INST]_1', '[/INST]_1', 'model_input_1', 'text_1'] # ['k', 'skills', 'topic', 'system prompt', 'user_0', 'assistant_0', 'model_input_0', 'score_0', 'score_extracted_0', 'points_0', 'num_sentences_manual_in_student_answer_0', 'true_sentence_lim_pt_0', 'num_sentences_extracted_eq_num_sentences_model_0'] for i in range(1, len(gen)): skills = [skill.strip() for skill in gen[i][1].split(',')] topic = gen[i][2] assert(skills == [skill.strip() for skill in grade[i][1].split(',')]) assert(topic == grade[i][2]) points = grade[i][9].split(',') if len(points) < len(skills): points = points + ['0.0'] * (len(skills) - len(points)) points[-1] = grade[i][11] points_no_skill_name = points.copy() answer = gen[i][-1] for skill_id, skill in enumerate(skills): simple_skill = skill.split('(')[0].strip() if simple_skill in answer: # print(skill_id, skill, simple_skill, answer, points_no_skill_name, points) points_no_skill_name[skill_id] = '0.0' record.append({ 'k': gen[i][0], 'exp_name': exp_name, 'model': model_name, 'grader': 'gpt-4' if 'gpt-4' in grader else 'llama-2-70b', 'grade_run': grader, 'skills': '\n\n'.join(skills), 'topic': topic, 'topic+skills': '+'.join([topic] + sorted(skills)), 'gen_prompt': gen[i][4].split('examples for the concepts:')[1].split('Please start the minimal natural')[0].replace('\n', '\n\n'), 'gen': gen[i][-3].replace('\n', '\n\n'), 'grade': grade[i][5].replace('\n', '\n\n'), 'points': ' '.join([(g[:-2] if g[-2:] == '.0' else g) for g in points]), 'points_no_skill_name': ' '.join([(g[:-2] if g[-2:] == '.0' else g) for g in points_no_skill_name]), # 'sent_limit_point': grade[i][11] }) return record def load_all_results(path='final'): all_results = [] for exp_name in os.listdir(path): if os.path.isfile(os.path.join(path, exp_name)): continue for model_name in os.listdir(os.path.join(path, exp_name)): gen_file = os.path.join(path, exp_name, model_name, "records.csv") if os.path.exists(gen_file) and os.path.isdir(os.path.join(path, exp_name, model_name, 'graded')): for grader in os.listdir(os.path.join(path, exp_name, model_name, 'graded')): grader_file = os.path.join(path, exp_name, model_name, 'graded', grader, "records.csv") if os.path.exists(grader_file): all_results += load_results(gen_file, grader_file, exp_name, model_name, grader) return pd.DataFrame(all_results) block_css = """ #a { color: black; background-color: #DEEBF7; font-size: 20px; } #b { color: black; background-color: #E2F0D9; font-size: 20px; } #c { color: black; background-color: #FFF2CC; font-size: 20px; } #d { color: black; background-color: #FBE5D6; font-size: 20px; } """ from Levenshtein import distance def best_match(comb, comb_list): if comb == '': return comb_list[0] dist = [distance(comb.split('+'), comb_.split('+')) for comb_ in comb_list] return comb_list[dist.index(min(dist))] class Tracker: def __init__(self, df) -> None: self.df = df self.value = {k: '' for k in ['k', 'k_list', 'comb', 'comb_list', 'model', 'model_list', 'exp_name', 'exp_name_list', 'topic', 'skills', 'gen_prompt', 'gen', 'grader', 'grader_list', 'grader_run', 'grader_run_list', 'points', 'grade']} # self.value = {k: '' for k in ['k', 'k_list', 'comb', 'comb_list', 'model', 'model_list', 'exp_name', 'exp_name_list', 'topic', 'skills', 'gen_prompt', 'gen', 'grader', 'grader_list', 'grader_run', 'grader_run_list', 'points', 'sent_limit_point', 'grade']} self.value = self.update(self.value) self.value = [self.value.copy() for _ in range(5)] self.component = [{k: '' for k in ['k', 'comb', 'model', 'exp_name', 'topic', 'skills', 'gen_prompt', 'gen', 'grader', 'grader_run', 'points', 'grade']} for _ in range(5)] # self.component = [{k: '' for k in ['k', 'comb', 'model', 'exp_name', 'topic', 'skills', 'gen_prompt', 'gen', 'grader', 'grader_run', 'points', 'sent_limit_point', 'grade']} for _ in range(5)] def update(self, value): cdf = self.df k, comb, model, exp_name, grader, grader_run = value['k'], value['comb'], value['model'], value['exp_name'], value['grader'], value['grader_run'] k_list = sorted(list(cdf.k.unique())) if k not in k_list: k = k_list[0] value['k'] = k value['k_list'] = k_list cdf = cdf[cdf.k==k] comb_list = sorted(list(cdf['topic+skills'].unique())) if comb not in comb_list: comb = best_match(comb, comb_list) value['comb'] = comb value['comb_list'] = comb_list cdf = cdf[cdf['topic+skills']==comb] model_list = sorted(list(cdf['model'].unique())) if model not in model_list: model = model_list[0] value['model'] = model value['model_list'] = model_list cdf = cdf[cdf.model==model] exp_name_list = sorted(list(cdf['exp_name'].unique())) if exp_name not in exp_name_list: exp_name = exp_name_list[0] value['exp_name'] = exp_name value['exp_name_list'] = exp_name_list cdf = cdf[cdf.exp_name==exp_name] value['topic'] = "*Topic*: " + cdf['topic'].unique()[0] value['skills'] = "*Skills*: \n\n" + cdf['skills'].unique()[0] value['gen_prompt'] = "*Skill Definition and Example*:\n\n" + cdf['gen_prompt'].unique()[0] value['gen'] = "*Model Answer*:\n\n" + cdf['gen'].unique()[0] grader_list = sorted(list(cdf['grader'].unique())) if grader not in grader_list: grader = grader_list[0] value['grader'] = grader value['grader_list'] = grader_list cdf = cdf[cdf.grader==grader] grader_run_list = sorted(list(cdf['grade_run'].unique())) if grader_run not in grader_run_list: grader_run = grader_run_list[0] value['grader_run'] = grader_run value['grader_run_list'] = grader_run_list cdf = cdf[cdf.grade_run==grader_run] value['points'] = "Points: " + cdf['points'].unique()[0] + "\n\n(After deducting points for explicitly mentioning skill names: " + cdf['points_no_skill_name'].unique()[0] + ")" # value['sent_limit_point'] = "within sentence limit? " + cdf['sent_limit_point'].unique()[0] value['grade'] = cdf['grade'].unique()[0] return value def procedure(self, c): input_list = [] output_list = [] fn_list = [] # binding = [['k', [0, 1, 3]], # ['comb', [0, 1, 3]], # ['model', [0, 1, 3]], # ['exp_name', [0, 1, 3]], # ['grader', [0, 1, 3]], # ['grader_run', [0, 1, 3]], # ] binding = [] idx = -1 for i in range(5): for k, v in self.component[i].items(): if v is c: idx = i key = k break if idx != -1: break assert(idx != -1) # print(id(c), id(self.component[idx][key]), idx, key) sync_list = [] for b in binding: if (key == b[0]) and (idx in b[1]): sync_list = [j for j in b[1] if j != idx] sync_component = [self.component[j][key] for j in sync_list] # print(c.label, key, idx, sync_list) def sync(v, sync_list=[0]): return [gr.Dropdown.update(value=v) for _ in range(len(sync_list))] if len(sync_list) > 0: input_list.append(c) output_list.append(sync_component) fn_list.append(partial(sync, sync_list=sync_list)) def update(k, comb, model, exp_name, grader, grader_run): value = { 'k': k, 'k_list': '', 'comb': comb, 'comb_list': '', 'model': model, 'model_list': '', 'exp_name': exp_name, 'exp_name_list': '', 'topic': '', 'skills': '', 'gen_prompt': '', 'gen': '', 'grader': grader, 'grader_list': '', 'grader_run': grader_run, 'grader_run_list': '', 'points': '', 'sent_limit_point': '', 'grade': '' } value = self.update(value) return [gr.Dropdown.update(value=value['k'], choices=value['k_list']), gr.Dropdown.update(value=value['comb'], choices=value['comb_list']), gr.Dropdown.update(value=value['model'], choices=value['model_list']), gr.Dropdown.update(value=value['exp_name'], choices=value['exp_name_list']), value['topic'], value['skills'], value['gen_prompt'], value['gen'], gr.Dropdown.update(value=value['grader'], choices=value['grader_list']), gr.Dropdown.update(value=value['grader_run'], choices=value['grader_run_list']), value['points'], # value['sent_limit_point'], value['grade'] ] sync_list += [idx] update_list = [] for i in range(5): for j in sync_list: if self.component[j][key] is self.component[i][key]: update_list.append(i) break for j in update_list: input_list.append([self.component[j][k] for k in ['k', 'comb', 'model', 'exp_name', 'grader', 'grader_run']]) output_list.append([self.component[j][k] for k in ['k', 'comb', 'model', 'exp_name', 'topic', 'skills', 'gen_prompt', 'gen', 'grader', 'grader_run', 'points', 'grade']]) # output_list.append([self.component[j][k] for k in ['k', 'comb', 'model', 'exp_name', 'topic', 'skills', 'gen_prompt', 'gen', 'grader', 'grader_run', 'points', 'sent_limit_point', 'grade']]) fn_list.append(update) return input_list, output_list, fn_list def build_demo(df): tracker = Tracker(df) with gr.Blocks( title="Skill-Mix: a Flexible and Expandable Family of Evaluations for AI models", theme=gr.themes.Base(text_size=gr.themes.sizes.text_lg), css=block_css, ) as demo: gr.Markdown( """ # Skill-Mix: a Flexible and Expandable Family of Evaluations for AI models By [Princeton Language and Intelligence (PLI), Princeton University](https://pli.princeton.edu/) and [Google DeepMind](https://www.deepmind.com/) ### This is a demonstration of the Skill-Mix evaluation. Paper link: [https://arxiv.org/abs/2310.17567](https://arxiv.org/abs/2310.17567) ### Samples are generated using 10% of the full set of skills and topics. Click the second tab for comparison between two generations. Coming soon: grading by LLaMA-2. """ ) with gr.Tab('Browse Single Generation'): v = tracker.value[0] with gr.Row(): k = gr.Dropdown(choices=v['k_list'], value=v['k'], label="k") tracker.component[0]['k'] = k comb = gr.Dropdown(choices=v['comb_list'], value=v['comb'], label="topic+skills") tracker.component[0]['comb'] = comb with gr.Row(): with gr.Column(): with gr.Row(): model = gr.Dropdown(choices=v['model_list'], value=v['model'], label="model") tracker.component[0]['model'] = model exp_name = gr.Dropdown(choices=v['exp_name_list'], value=v['exp_name'], label="exp_name") tracker.component[0]['exp_name'] = exp_name with gr.Row(): topic = gr.Markdown(value=v['topic'], elem_id='a') tracker.component[0]['topic'] = topic skills = gr.Markdown(value=v['skills'], elem_id='a') tracker.component[0]['skills'] = skills gen = gr.Markdown(value=v['gen'], elem_id='b') tracker.component[0]['gen'] = gen gen_prompt = gr.Markdown(value=v['gen_prompt'], elem_id='a') tracker.component[0]['gen_prompt'] = gen_prompt with gr.Column(): with gr.Row(): grader = gr.Dropdown(choices=v['grader_list'], value=v['grader'], label="grader") tracker.component[0]['grader'] = grader grader_run = gr.Dropdown(choices=v['grader_run_list'], value=v['grader_run'], label="grader_run") tracker.component[0]['grader_run'] = grader_run points = gr.Markdown(value=v['points'], elem_id='c') tracker.component[0]['points'] = points # sent_limit_point = gr.Markdown(value=v['sent_limit_point'], elem_id='c') # tracker.component[0]['sent_limit_point'] = sent_limit_point grade = gr.Markdown(value=v['grade'], elem_id='d') tracker.component[0]['grade'] = grade with gr.Tab('Compare Two Generations'): v = tracker.value[1] with gr.Row(): k = gr.Dropdown(choices=v['k_list'], value=v['k'], label="k") tracker.component[1]['k'] = tracker.component[2]['k'] = k comb = gr.Dropdown(choices=v['comb_list'], value=v['comb'], label="topic+skills") tracker.component[1]['comb'] = tracker.component[2]['comb'] = comb with gr.Row(): for col in range(1, 3): v = tracker.value[col] with gr.Column(): with gr.Row(): model = gr.Dropdown(choices=v['model_list'], value=v['model'], label="model") tracker.component[col]['model'] = model exp_name = gr.Dropdown(choices=v['exp_name_list'], value=v['exp_name'], label="exp_name") tracker.component[col]['exp_name'] = exp_name with gr.Row(): topic = gr.Markdown(value=v['topic'], elem_id='a') tracker.component[col]['topic'] = topic skills = gr.Markdown(value=v['skills'], elem_id='a') tracker.component[col]['skills'] = skills gen = gr.Markdown(value=v['gen'], elem_id='b') tracker.component[col]['gen'] = gen with gr.Row(): grader = gr.Dropdown(choices=v['grader_list'], value=v['grader'], label="grader") tracker.component[col]['grader'] = grader grader_run = gr.Dropdown(choices=v['grader_run_list'], value=v['grader_run'], label="grader_run") tracker.component[col]['grader_run'] = grader_run points = gr.Markdown(value=v['points'], elem_id='c') tracker.component[col]['points'] = points # sent_limit_point = gr.Markdown(value=v['sent_limit_point'], elem_id='c') # tracker.component[col]['sent_limit_point'] = sent_limit_point gen_prompt = gr.Markdown(value=v['gen_prompt'], elem_id='a') tracker.component[col]['gen_prompt'] = gen_prompt grade = gr.Markdown(value=v['grade'], elem_id='d') tracker.component[col]['grade'] = grade # with gr.Tab('One Generation Two Grading'): # v = tracker.value[3] # with gr.Row(): # k = gr.Dropdown(choices=v['k_list'], value=v['k'], label="k") # tracker.component[3]['k'] = tracker.component[4]['k'] = k # comb = gr.Dropdown(choices=v['comb_list'], value=v['comb'], label="topic+skills") # tracker.component[3]['comb'] = tracker.component[4]['comb'] = comb # with gr.Row(): # model = gr.Dropdown(choices=v['model_list'], value=v['model'], label="model") # tracker.component[3]['model'] = tracker.component[4]['model'] = model # exp_name = gr.Dropdown(choices=v['exp_name_list'], value=v['exp_name'], label="exp_name") # tracker.component[3]['exp_name'] = tracker.component[4]['exp_name'] = exp_name # with gr.Row(): # topic = gr.Markdown(value=v['topic'], elem_id='a') # tracker.component[3]['topic'] = tracker.component[4]['topic'] = topic # skills = gr.Markdown(value=v['skills'], elem_id='a') # tracker.component[3]['skills'] = tracker.component[4]['skills'] = skills # gen = gr.Markdown(value=v['gen'], elem_id='b') # tracker.component[3]['gen'] = tracker.component[4]['gen'] = gen # with gr.Row(): # for col in range(3, 5): # v = tracker.value[col] # with gr.Column(): # with gr.Row(): # grader = gr.Dropdown(choices=v['grader_list'], value=v['grader'], label="grader") # tracker.component[col]['grader'] = grader # grader_run = gr.Dropdown(choices=v['grader_run_list'], value=v['grader_run'], label="grader_run") # tracker.component[col]['grader_run'] = grader_run # points = gr.Markdown(value=v['points'], elem_id='c') # tracker.component[col]['points'] = points # sent_limit_point = gr.Markdown(value=v['sent_limit_point'], elem_id='c') # tracker.component[col]['sent_limit_point'] = sent_limit_point # grade = gr.Markdown(value=v['grade'], elem_id='d') # tracker.component[col]['grade'] = grade # gen_prompt = gr.Markdown(value=v['gen_prompt'], elem_id='a') # tracker.component[3]['gen_prompt'] = tracker.component[4]['gen_prompt'] = gen_prompt all_components = sum([list(tracker.component[i].values()) for i in range(5)], []) all_components = [c for c in all_components if c != ''] all_components = list(set(all_components)) # print(all_components) for c in all_components: input_list, output_list, fn_list = tracker.procedure(c) if len(fn_list) > 0: if len(fn_list) == 1: c.change(fn_list[0], input_list[0], output_list[0]) elif len(fn_list) == 2: c.change(fn_list[0], input_list[0], output_list[0]).then(fn_list[1], input_list[1], output_list[1]) elif len(fn_list) == 3: c.change(fn_list[0], input_list[0], output_list[0]).then(fn_list[1], input_list[1], output_list[1]).then(fn_list[2], input_list[2], output_list[2]) elif len(fn_list) == 4: c.change(fn_list[0], input_list[0], output_list[0]).then(fn_list[1], input_list[1], output_list[1]).then(fn_list[2], input_list[2], output_list[2]).then(fn_list[3], input_list[3], output_list[3]) elif len(fn_list) == 5: c.change(fn_list[0], input_list[0], output_list[0]).then(fn_list[1], input_list[1], output_list[1]).then(fn_list[2], input_list[2], output_list[2]).then(fn_list[3], input_list[3], output_list[3]).then(fn_list[4], input_list[4], output_list[4]) elif len(fn_list) == 6: c.change(fn_list[0], input_list[0], output_list[0]).then(fn_list[1], input_list[1], output_list[1]).then(fn_list[2], input_list[2], output_list[2]).then(fn_list[3], input_list[3], output_list[3]).then(fn_list[4], input_list[4], output_list[4]).then(fn_list[5], input_list[5], output_list[5]) else: raise NotImplementedError gr.Markdown('''### Citations ``` @article{yu2023skillmix, title={Skill-Mix: a Flexible and Expandable Family of Evaluations for AI models}, author={Yu, Dingli and Kaur, Simran and Gupta, Arushi and Brown-Cohen, Jonah and Goyal, Anirudh and Arora, Sanjeev}, journal={arXiv preprint arXiv:2310.17567}, year={2023} } ``` ``` @misc{openai2023gpt4, title={GPT-4 Technical Report}, author={OpenAI}, year={2023}, eprint={2303.08774}, archivePrefix={arXiv}, primaryClass={cs.CL} } ``` ``` @article{touvron2023llama, title={Llama 2: Open foundation and fine-tuned chat models}, author={Touvron, Hugo and Martin, Louis and Stone, Kevin and Albert, Peter and Almahairi, Amjad and Babaei, Yasmine and Bashlykov, Nikolay and Batra, Soumya and Bhargava, Prajjwal and Bhosale, Shruti and others}, journal={arXiv preprint arXiv:2307.09288}, year={2023} } ``` ``` @misc{mistral, title = {Mistral 7B}, author = {{Mistral AI Team}}, url = {https://mistral.ai/news/announcing-mistral-7b/}, year = {2023}, month = {9}, } ``` ``` @article{qwen, title={Qwen Technical Report}, author={ Bai, Jinze and Bai, Shuai and Chu, Yunfei and Cui, Zeyu and Dang, Kai and Deng, Xiaodong and Fan, Yang and Ge, Wenbin and Han, Yu and Huang, Fei and Hui, Binyuan and Ji, Luo and Li, Mei and Lin, Junyang and Lin, Runji and Liu, Dayiheng and Liu, Gao and Lu, Chengqiang and Lu, Keming and Ma, Jianxin and Men, Rui and Ren, Xingzhang and Ren, Xuancheng and Tan, Chuanqi and Tan, Sinan and Tu, Jianhong and Wang, Peng and Wang, Shijie and Wang, Wei and Wu, Shengguang and Xu, Benfeng and Xu, Jin and Yang, An and Yang, Hao and Yang, Jian and Yang, Shusheng and Yao, Yang and Yu, Bowen and Yuan, Hongyi and Yuan, Zheng and Zhang, Jianwei and Zhang, Xingxuan and Zhang, Yichang and Zhang, Zhenru and Zhou, Chang and Zhou, Jingren and Zhou, Xiaohuan and Zhu, Tianhang}, year={2023} } ``` ``` @software{xwin-lm, title = {Xwin-LM}, author = {{Xwin-LM Team}}, url = {https://github.com/Xwin-LM/Xwin-LM}, version = {pre-release}, year = {2023}, month = {9}, } ``` ``` @article{falcon, title={The Falcon Series of Language Models: Towards Open Frontier Models}, author={Almazrouei, Ebtesam and Alobeidli, Hamza and Alshamsi, Abdulaziz and Cappelli, Alessandro and Cojocaru, Ruxandra and Alhammadi, Maitha and Daniele, Mazzotta and Heslow, Daniel and Launay, Julien and Malartic, Quentin and Noune, Badreddine and Pannier, Baptiste and Penedo, Guilherme}, year={2023} } ``` ``` @misc{tigerbot, title={{TigerBot}: A cutting-edge foundation for your very own LLM.}, author={TigerResearch}, howpublished={\\url{https://github.com/TigerResearch/TigerBot}}, note={Accessed: 2023-09-30} } ``` ''') return demo if __name__ == '__main__': # df = load_all_results(path="../../on_released_topics_and_skills") # pickle.dump(df, open('on_released_topics_and_skills.pkl', 'wb')) df = pickle.load(open('on_released_topics_and_skills.pkl', 'rb')) demo = build_demo(df) # demo.launch(share=True) demo.launch()