Spaces:
Sleeping
Sleeping
| from openai import OpenAI | |
| import json | |
| import os | |
| from tqdm import tqdm | |
| import sys | |
| import copy | |
| from utils import extract_planning, content_to_json, extract_code_from_content, print_response, print_log_cost, load_accumulated_cost, save_accumulated_cost, read_python_files | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('--paper_name',type=str) | |
| parser.add_argument('--gpt_version',type=str, default="o3-mini") | |
| parser.add_argument('--paper_format',type=str, default="JSON", choices=["JSON", "LaTeX"]) | |
| parser.add_argument('--pdf_json_path', type=str) # json format | |
| parser.add_argument('--pdf_latex_path', type=str) # latex format | |
| parser.add_argument('--output_dir',type=str, default="") | |
| parser.add_argument('--output_repo_dir',type=str, default="") | |
| args = parser.parse_args() | |
| client = OpenAI(api_key = os.environ["OPENAI_API_KEY"]) | |
| paper_name = args.paper_name | |
| gpt_version = args.gpt_version | |
| paper_format = args.paper_format | |
| pdf_json_path = args.pdf_json_path | |
| pdf_latex_path = args.pdf_latex_path | |
| output_dir = args.output_dir | |
| output_repo_dir = args.output_repo_dir | |
| if paper_format == "JSON": | |
| with open(f'{pdf_json_path}') as f: | |
| paper_content = json.load(f) | |
| elif paper_format == "LaTeX": | |
| with open(f'{pdf_latex_path}') as f: | |
| paper_content = f.read() | |
| else: | |
| print(f"[ERROR] Invalid paper format. Please select either 'JSON' or 'LaTeX.") | |
| sys.exit(0) | |
| with open(f'{output_dir}/planning_config.yaml') as f: | |
| config_yaml = f.read() | |
| context_lst = extract_planning(f'{output_dir}/planning_trajectories.json') | |
| # 0: overview, 1: detailed, 2: PRD | |
| # file_list = content_to_json(context_lst[1]) | |
| task_list = content_to_json(context_lst[2]) | |
| todo_file_lst = task_list['Task list'] | |
| done_file_lst = ['config.yaml'] | |
| done_file_dict = {} | |
| code_msg = [ | |
| {"role": "system", "content": f"""You are an expert researcher and software engineer with a deep understanding of experimental design and reproducibility in scientific research. | |
| You will receive configuration file named "config.yaml", and implmented code repository. | |
| Your task is to write a Bash script that can run the given repository from scratch. The script should create and activate the required environment, install all dependencies, and include the commands needed to execute the main file or entry point. Make sure the script is self-contained and can be executed without any manual setup. | |
| Write code with triple quoto."""}] | |
| def get_write_msg(todo_file_name, done_file_lst): | |
| code_files = "" | |
| for done_file in done_file_lst: | |
| if done_file.endswith(".yaml"): continue | |
| code_files += f""" | |
| ```python | |
| {done_file_dict[done_file]} | |
| ``` | |
| """ | |
| write_msg=[ | |
| {'role': 'user', "content": f"""# Context | |
| ## Configuration file | |
| ```yaml | |
| {config_yaml} | |
| ``` | |
| ----- | |
| ## Code Files | |
| {code_files} | |
| ----- | |
| # Format example | |
| ## Code: {todo_file_name} | |
| ```python | |
| ## {todo_file_name} | |
| ... | |
| ``` | |
| ----- | |
| # Instruction | |
| Based on the code files, follow "Format example", write the code. | |
| We have {done_file_lst}. | |
| Next, you must write only the "{todo_file_name}". | |
| ## Code: {todo_file_name}"""}] | |
| return write_msg | |
| def api_call(msg): | |
| if "o3-mini" in gpt_version or "o4-mini" in gpt_version: | |
| completion = client.chat.completions.create( | |
| model=gpt_version, | |
| reasoning_effort="high", | |
| messages=msg | |
| ) | |
| else: | |
| completion = client.chat.completions.create( | |
| model=gpt_version, | |
| messages=msg | |
| ) | |
| return completion | |
| artifact_output_dir=f'{output_dir}/coding_artifacts' | |
| os.makedirs(artifact_output_dir, exist_ok=True) | |
| python_dict = read_python_files(output_repo_dir) | |
| for todo_idx, todo_file_name in enumerate(tqdm(todo_file_lst)): | |
| if todo_file_name == "config.yaml": | |
| continue | |
| done_file_dict[todo_file_name] = python_dict[todo_file_name] | |
| done_file_lst.append(todo_file_name) | |
| total_accumulated_cost = load_accumulated_cost(f"{output_dir}/accumulated_cost.json") | |
| for todo_idx, todo_file_name in enumerate(["reproduce.sh"]): | |
| responses = [] | |
| trajectories = copy.deepcopy(code_msg) | |
| current_stage = f"[CODING] {todo_file_name}" | |
| print(current_stage) | |
| if todo_file_name == "config.yaml": | |
| continue | |
| instruction_msg = get_write_msg(todo_file_name, done_file_lst) | |
| trajectories.extend(instruction_msg) | |
| completion = api_call(trajectories) | |
| # print(completion.choices[0].message) | |
| # response | |
| completion_json = json.loads(completion.model_dump_json()) | |
| responses.append(completion_json) | |
| # trajectories | |
| message = completion.choices[0].message | |
| trajectories.append({'role': message.role, 'content': message.content}) | |
| done_file_lst.append(todo_file_name) | |
| # save | |
| # save_dir_name = f"{paper_name}_repo" | |
| os.makedirs(f'{output_repo_dir}', exist_ok=True) | |
| save_todo_file_name = todo_file_name.replace("/", "_") | |
| # print and logging | |
| print_response(completion_json) | |
| temp_total_accumulated_cost = print_log_cost(completion_json, gpt_version, current_stage, output_dir, total_accumulated_cost) | |
| total_accumulated_cost = temp_total_accumulated_cost | |
| # save artifacts | |
| with open(f'{artifact_output_dir}/{save_todo_file_name}_coding.txt', 'w') as f: | |
| f.write(completion_json['choices'][0]['message']['content']) | |
| # extract code save | |
| code = extract_code_from_content(message.content) | |
| if len(code) == 0: | |
| code = message.content | |
| done_file_dict[todo_file_name] = code | |
| if save_todo_file_name != todo_file_name: | |
| todo_file_dir = '/'.join(todo_file_name.split("/")[:-1]) | |
| os.makedirs(f"{output_repo_dir}/{todo_file_dir}", exist_ok=True) | |
| with open(f"{output_repo_dir}/{todo_file_name}", 'w') as f: | |
| f.write(code) | |
| save_accumulated_cost(f"{output_dir}/accumulated_cost.json", total_accumulated_cost) | |