Skip to content

Commit

Permalink
Remove delete_existing option; Introduce archive (AntonOsika#409)
Browse files Browse the repository at this point in the history
* Remove `delete_existing` option; Introduce archive

* Update gpt_engineer/db.py

* Update gpt_engineer/main.py

* Update gpt_engineer/main.py

* Update gpt_engineer/steps.py

* Update gpt_engineer/steps.py

---------

Co-authored-by: Anton Osika <[email protected]>
  • Loading branch information
azrv and AntonOsika authored Jul 2, 2023
1 parent 14ae0e7 commit 60e0a7e
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 18 deletions.
2 changes: 2 additions & 0 deletions gpt_engineer/db.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from dataclasses import dataclass
from pathlib import Path
from typing import Optional


# This class represents a simple database that stores its data as files in a directory.
Expand Down Expand Up @@ -47,3 +48,4 @@ class DBs:
preprompts: DB
input: DB
workspace: DB
archive: DB
20 changes: 8 additions & 12 deletions gpt_engineer/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import logging
import shutil
import os

from pathlib import Path

Expand All @@ -18,7 +18,6 @@
@app.command()
def main(
project_path: str = typer.Argument("example", help="path"),
delete_existing: bool = typer.Argument(False, help="delete existing files"),
model: str = typer.Argument("gpt-4", help="model id string"),
temperature: float = 0.1,
steps_config: steps.Config = typer.Option(
Expand All @@ -35,28 +34,25 @@ def main(
):
logging.basicConfig(level=logging.DEBUG if verbose else logging.INFO)

input_path = Path(project_path).absolute()
memory_path = input_path / f"{run_prefix}memory"
workspace_path = input_path / f"{run_prefix}workspace"

if delete_existing:
# Delete files and subdirectories in paths
shutil.rmtree(memory_path, ignore_errors=True)
shutil.rmtree(workspace_path, ignore_errors=True)

model = fallback_model(model)

ai = AI(
model=model,
temperature=temperature,
)

input_path = Path(project_path).absolute()
memory_path = input_path / f"{run_prefix}memory"
workspace_path = input_path / f"{run_prefix}workspace"
archive_path = input_path / f"{run_prefix}archive"

initial_run = not os.path.exists(memory_path) and not os.path.exists(workspace_path)
dbs = DBs(
memory=DB(memory_path),
logs=DB(memory_path / "logs"),
input=DB(input_path),
workspace=DB(workspace_path),
preprompts=DB(Path(__file__).parent / "preprompts"),
archive=None if initial_run else DB(archive_path),
)

steps = STEPS[steps_config]
Expand Down
22 changes: 20 additions & 2 deletions gpt_engineer/steps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import datetime
import json
import os
import re
import shutil
import subprocess

from enum import Enum
Expand Down Expand Up @@ -258,6 +261,16 @@ def fix_code(ai: AI, dbs: DBs):
return messages


def archive(ai: AI, dbs: DBs):
os.makedirs(dbs.archive.path, exist_ok=True)
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
shutil.move(dbs.memory.path, dbs.archive.path / timestamp / dbs.memory.path.name)
shutil.move(
dbs.workspace.path, dbs.archive.path / timestamp / dbs.workspace.path.name
)
return []


def human_review(ai: AI, dbs: DBs):
review = human_input()
dbs.memory["review"] = review.to_json() # type: ignore
Expand All @@ -280,15 +293,17 @@ class Config(str, Enum):
# Different configs of what steps to run
STEPS = {
Config.DEFAULT: [
archive,
clarify,
gen_clarified_code,
gen_entrypoint,
execute_entrypoint,
human_review,
],
Config.BENCHMARK: [simple_gen, gen_entrypoint],
Config.SIMPLE: [simple_gen, gen_entrypoint, execute_entrypoint],
Config.BENCHMARK: [archive, simple_gen, gen_entrypoint],
Config.SIMPLE: [archive, simple_gen, gen_entrypoint, execute_entrypoint],
Config.TDD: [
archive,
gen_spec,
gen_unit_tests,
gen_code,
Expand All @@ -297,6 +312,7 @@ class Config(str, Enum):
human_review,
],
Config.TDD_PLUS: [
archive,
gen_spec,
gen_unit_tests,
gen_code,
Expand All @@ -306,13 +322,15 @@ class Config(str, Enum):
human_review,
],
Config.CLARIFY: [
archive,
clarify,
gen_clarified_code,
gen_entrypoint,
execute_entrypoint,
human_review,
],
Config.RESPEC: [
archive,
gen_spec,
respec,
gen_unit_tests,
Expand Down
Empty file added tests/steps/__init__.py
Empty file.
44 changes: 44 additions & 0 deletions tests/steps/test_archive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import datetime
import os

from unittest.mock import MagicMock

from gpt_engineer.db import DB, DBs
from gpt_engineer.steps import archive


def freeze_at(monkeypatch, time):
datetime_mock = MagicMock(wraps=datetime.datetime)
datetime_mock.now.return_value = time
monkeypatch.setattr(datetime, "datetime", datetime_mock)


def setup_dbs(tmp_path, dir_names):
directories = [tmp_path / name for name in dir_names]

# Create DB objects
dbs = [DB(dir) for dir in directories]

# Create DBs instance
return DBs(*dbs)


def test_archive(tmp_path, monkeypatch):
dbs = setup_dbs(
tmp_path, ["memory", "logs", "preprompts", "input", "workspace", "archive"]
)
freeze_at(monkeypatch, datetime.datetime(2020, 12, 25, 17, 5, 55))
archive(None, dbs)
assert not os.path.exists(tmp_path / "memory")
assert not os.path.exists(tmp_path / "workspace")
assert os.path.isdir(tmp_path / "archive" / "20201225_170555")

dbs = setup_dbs(
tmp_path, ["memory", "logs", "preprompts", "input", "workspace", "archive"]
)
freeze_at(monkeypatch, datetime.datetime(2022, 8, 14, 8, 5, 12))
archive(None, dbs)
assert not os.path.exists(tmp_path / "memory")
assert not os.path.exists(tmp_path / "workspace")
assert os.path.isdir(tmp_path / "archive" / "20201225_170555")
assert os.path.isdir(tmp_path / "archive" / "20220814_080512")
2 changes: 1 addition & 1 deletion tests/test_collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_collect_learnings(monkeypatch):
model = "test_model"
temperature = 0.5
steps = [gen_code]
dbs = DBs(DB("/tmp"), DB("/tmp"), DB("/tmp"), DB("/tmp"), DB("/tmp"))
dbs = DBs(DB("/tmp"), DB("/tmp"), DB("/tmp"), DB("/tmp"), DB("/tmp"), DB("/tmp"))
dbs.input = {
"prompt": "test prompt\n with newlines",
"feedback": "test feedback",
Expand Down
7 changes: 4 additions & 3 deletions tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_DB_operations(tmp_path):


def test_DBs_initialization(tmp_path):
dir_names = ["memory", "logs", "preprompts", "input", "workspace"]
dir_names = ["memory", "logs", "preprompts", "input", "workspace", "archive"]
directories = [tmp_path / name for name in dir_names]

# Create DB objects
Expand All @@ -41,6 +41,7 @@ def test_DBs_initialization(tmp_path):
assert isinstance(dbs_instance.preprompts, DB)
assert isinstance(dbs_instance.input, DB)
assert isinstance(dbs_instance.workspace, DB)
assert isinstance(dbs_instance.archive, DB)


def test_invalid_path():
Expand Down Expand Up @@ -106,11 +107,11 @@ def test_DBs_instantiation_with_wrong_number_of_arguments(tmp_path):
DBs(db, db, db)

with pytest.raises(TypeError):
DBs(db, db, db, db, db, db)
DBs(db, db, db, db, db, db, db)


def test_DBs_dataclass_attributes(tmp_path):
dir_names = ["memory", "logs", "preprompts", "input", "workspace"]
dir_names = ["memory", "logs", "preprompts", "input", "workspace", "archive"]
directories = [tmp_path / name for name in dir_names]

# Create DB objects
Expand Down

0 comments on commit 60e0a7e

Please sign in to comment.