paper2code-cli / codes /3.1_coding_sh.py
Leon4gr45's picture
Upload folder using huggingface_hub (part 8)
a72140d verified
Raw
History Blame Contribute Delete
5.87 kB
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)