Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

image prompts - Entrypoint prompt - additional CLI argument #1077

Merged
merged 52 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
4abcb66
accept image prompts on cli
TheoMcCabe Mar 8, 2024
49c4008
add token usage tracking for image prompts
TheoMcCabe Mar 8, 2024
c2ad358
add token usage tests
TheoMcCabe Mar 8, 2024
833eafb
fix broken tests 1
TheoMcCabe Mar 8, 2024
43fe516
almost all tests passing. Vision model has some issues with the promp…
TheoMcCabe Mar 9, 2024
9324158
pre commit
TheoMcCabe Mar 9, 2024
bb7b3c0
import pillow
TheoMcCabe Mar 9, 2024
a5173fc
update poetry lock
TheoMcCabe Mar 9, 2024
7ac31ee
log exception
TheoMcCabe Mar 9, 2024
8b682da
remove print
TheoMcCabe Mar 9, 2024
8a20266
load env
TheoMcCabe Mar 9, 2024
ac24948
pre commit
TheoMcCabe Mar 9, 2024
db29ed3
update ai cache
TheoMcCabe Mar 9, 2024
eefbb87
revert caching ai change
TheoMcCabe Mar 9, 2024
56639eb
update poetry lock
TheoMcCabe Mar 9, 2024
6ca459a
precommit and snake case
TheoMcCabe Mar 9, 2024
a2808da
ai cache
TheoMcCabe Mar 9, 2024
847a5e4
try recreating cache from scratch
TheoMcCabe Mar 9, 2024
fcd7cfe
print missing key on build server
TheoMcCabe Mar 9, 2024
de16424
fix message collapse
TheoMcCabe Mar 9, 2024
bc14d84
pre commit
TheoMcCabe Mar 9, 2024
4d806a4
add more cache
TheoMcCabe Mar 9, 2024
7353d6f
poetry lock
TheoMcCabe Mar 17, 2024
f32a610
Fixing tests for now
ATheorell Mar 18, 2024
21cfc94
Now specifying image and prompt with dedicated arguments
ATheorell Mar 18, 2024
34acbd2
cleaning up problems from rebase
ATheorell Mar 18, 2024
06f0bed
updating cache and lock
ATheorell Mar 18, 2024
d39f766
linting with ruff
ATheorell Mar 18, 2024
9945ff1
removing falsely added prompt file
ATheorell Mar 18, 2024
d4f0aa2
self-heal mechanism using improve instead of rewriting code base
ATheorell Mar 18, 2024
d64ea18
Extended gen_entrypoint to take a prompt from the user
ATheorell Mar 18, 2024
c2dfec1
possible to pass prompt to make entrypoint
ATheorell Mar 18, 2024
f8eb4f8
small parsing adjustment
ATheorell Mar 18, 2024
ea42905
before implementing better self-heal
ATheorell Mar 18, 2024
c71f7b4
Fixing failing test caused by --entrypoint_prompt
ATheorell Mar 18, 2024
e68c246
made paths relative for load prompts flow
ATheorell Mar 18, 2024
60278a2
committing to binary search langchain error
ATheorell Mar 18, 2024
47ccb46
Fixes to self-heal printing
ATheorell Mar 18, 2024
3c2fcd3
Removed double improve
ATheorell Mar 18, 2024
376d402
fixing tests
ATheorell Mar 18, 2024
23c5e4e
Added cache option and fixed ruff errors
ATheorell Mar 19, 2024
93b8476
added more docstrings
ATheorell Mar 19, 2024
42d08b5
after rebasing
ATheorell Mar 19, 2024
b5ef722
ruff linting
ATheorell Mar 19, 2024
5263a2c
added missing use_cache argument in the minimized main callable
ATheorell Mar 19, 2024
9f0d49a
prompt file argument
TheoMcCabe Mar 20, 2024
8065a8b
remove print
TheoMcCabe Mar 20, 2024
48d991b
add vision example
TheoMcCabe Mar 20, 2024
9cd72ca
only collapse if not in vision mode
TheoMcCabe Mar 20, 2024
a7ebb48
update readme
TheoMcCabe Mar 20, 2024
eb84a28
pre commit
TheoMcCabe Mar 20, 2024
eb057ee
re insert fix to non vision ai use case
TheoMcCabe Mar 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions gpt_engineer/applications/cli/cli_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
)
from gpt_engineer.core.files_dict import FilesDict
from gpt_engineer.core.preprompts_holder import PrepromptsHolder
from gpt_engineer.core.prompt import Prompt

CodeGenType = TypeVar("CodeGenType", bound=Callable[[AI, str, BaseMemory], FilesDict])
CodeProcessor = TypeVar(
Expand Down Expand Up @@ -147,7 +148,7 @@ def with_default_config(
preprompts_holder=preprompts_holder or PrepromptsHolder(PREPROMPTS_PATH),
)

def init(self, prompt: str) -> FilesDict:
def init(self, prompt: Prompt) -> FilesDict:
"""
Generates a new piece of code using the AI and step bundle based on the provided prompt.

Expand All @@ -166,7 +167,7 @@ def init(self, prompt: str) -> FilesDict:
self.ai, prompt, self.memory, self.preprompts_holder
)
entrypoint = gen_entrypoint(
self.ai, files_dict, self.memory, self.preprompts_holder
self.ai, prompt, files_dict, self.memory, self.preprompts_holder
)
combined_dict = {**files_dict, **entrypoint}
files_dict = FilesDict(combined_dict)
Expand All @@ -175,13 +176,15 @@ def init(self, prompt: str) -> FilesDict:
self.execution_env,
files_dict,
preprompts_holder=self.preprompts_holder,
prompt=prompt,
memory=self.memory,
)
return files_dict

def improve(
self,
files_dict: FilesDict,
prompt: str,
prompt: Prompt,
execution_command: Optional[str] = None,
) -> FilesDict:
"""
Expand All @@ -205,19 +208,18 @@ def improve(
files_dict = self.improve_fn(
self.ai, prompt, files_dict, self.memory, self.preprompts_holder
)

# No need to run entrypoint for improve right?
# if not execution_command and ENTRYPOINT_FILE not in files_dict:
# entrypoint = gen_entrypoint(
# self.ai, files_dict, self.memory, self.preprompts_holder
# )
# combined_dict = {**files_dict, **entrypoint}
# files_dict = FilesDict(combined_dict)

# entrypoint = gen_entrypoint(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we sure we want commented code here? its always in the git history if we want to bring it back later - or are we expecting this to be commented in and out regularly

# self.ai, prompt, files_dict, self.memory, self.preprompts_holder
# )
# combined_dict = {**files_dict, **entrypoint}
# files_dict = FilesDict(combined_dict)
# files_dict = self.process_code_fn(
# self.ai,
# self.execution_env,
# files_dict,
# preprompts_holder=self.preprompts_holder,
# prompt=prompt,
# memory=self.memory,
# )

return files_dict
5 changes: 3 additions & 2 deletions gpt_engineer/applications/cli/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
human_review_input,
)
from gpt_engineer.core.default.disk_memory import DiskMemory
from gpt_engineer.core.prompt import Prompt


def send_learning(learning: Learning):
Expand Down Expand Up @@ -62,7 +63,7 @@ def send_learning(learning: Learning):


def collect_learnings(
prompt: str,
prompt: Prompt,
model: str,
temperature: float,
config: any,
Expand Down Expand Up @@ -138,7 +139,7 @@ def collect_learnings(


def collect_and_send_human_review(
prompt: str,
prompt: Prompt,
model: str,
temperature: float,
config: Tuple[str, ...],
Expand Down
7 changes: 4 additions & 3 deletions gpt_engineer/applications/cli/learning.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
Checks if the user has previously given consent to store their data and, if not, asks for it.
ask_collection_consent() -> bool
Prompts the user for consent to store their data for the purpose of improving GPT Engineer.
extract_learning(prompt: str, model: str, temperature: float, config: Tuple[str, ...], memory: DiskMemory, review: Review) -> Learning
extract_learning(prompt: Prompt, model: str, temperature: float, config: Tuple[str, ...], memory: DiskMemory, review: Review) -> Learning
Extracts feedback and session details to create a Learning instance based on the provided parameters.
get_session() -> str
Retrieves a unique identifier for the current user session, creating one if it does not exist.
Expand All @@ -40,6 +40,7 @@
from termcolor import colored

from gpt_engineer.core.default.disk_memory import DiskMemory
from gpt_engineer.core.prompt import Prompt


@dataclass_json
Expand Down Expand Up @@ -97,7 +98,7 @@ class Learning:
The version of the learning data schema.
"""

prompt: str
prompt: Prompt
model: str
temperature: float
config: str
Expand Down Expand Up @@ -236,7 +237,7 @@ def ask_collection_consent() -> bool:


def extract_learning(
prompt: str,
prompt: Prompt,
model: str,
temperature: float,
config: Tuple[str, ...],
Expand Down
112 changes: 102 additions & 10 deletions gpt_engineer/applications/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import typer

from dotenv import load_dotenv
from langchain.cache import SQLiteCache
from langchain.globals import set_llm_cache

from gpt_engineer.applications.cli.cli_agent import CliAgent
from gpt_engineer.applications.cli.collect import collect_and_send_human_review
Expand All @@ -52,6 +54,7 @@
stage_files,
)
from gpt_engineer.core.preprompts_holder import PrepromptsHolder
from gpt_engineer.core.prompt import Prompt
from gpt_engineer.tools.custom_steps import clarified_gen, lite_gen, self_heal

app = typer.Typer() # creates a CLI app
Expand All @@ -73,7 +76,25 @@
openai.api_key = os.getenv("OPENAI_API_KEY")


def load_prompt(input_repo: DiskMemory, improve_mode):
def concatenate_paths(base_path, sub_path):
# Compute the relative path from base_path to sub_path
relative_path = os.path.relpath(sub_path, base_path)

# If the relative path is not in the parent directory, use the original sub_path
if not relative_path.startswith(".."):
return sub_path

Check warning on line 85 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L85

Added line #L85 was not covered by tests

# Otherwise, concatenate base_path and sub_path
return os.path.normpath(os.path.join(base_path, sub_path))


def load_prompt(
input_repo: DiskMemory,
improve_mode: bool,
prompt_file: str,
image_directory: str,
entrypoint_prompt_file: str = "",
) -> Prompt:
"""
Load or request a prompt from the user based on the mode.

Expand All @@ -89,16 +110,47 @@
str
The loaded or inputted prompt.
"""
if input_repo.get("prompt"):
return input_repo.get("prompt")

if not improve_mode:
input_repo["prompt"] = input(
"\nWhat application do you want gpt-engineer to generate?\n"
if os.path.isdir(prompt_file):
raise ValueError(
f"The path to the prompt, {prompt_file}, already exists as a directory. No prompt can be read from it. Please specify a prompt file using --prompt"
)
prompt_str = input_repo.get(prompt_file)
if not prompt_str:
if not improve_mode:
prompt_str = input(
"\nWhat application do you want gpt-engineer to generate?\n"
)
else:
prompt_str = input("\nHow do you want to improve the application?\n")

Check warning on line 125 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L125

Added line #L125 was not covered by tests

if entrypoint_prompt_file == "":
entrypoint_prompt = ""
else:
full_entrypoint_prompt_file = concatenate_paths(

Check warning on line 130 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L130

Added line #L130 was not covered by tests
input_repo.path, entrypoint_prompt_file
)
if os.path.isfile(full_entrypoint_prompt_file):
entrypoint_prompt = input_repo.get(full_entrypoint_prompt_file)

Check warning on line 134 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L133-L134

Added lines #L133 - L134 were not covered by tests

else:
raise ValueError("The provided file at --entrypoint-prompt does not exist")

Check warning on line 137 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L137

Added line #L137 was not covered by tests

if image_directory == "":
return Prompt(prompt_str, entrypoint_prompt=entrypoint_prompt)

full_image_directory = concatenate_paths(input_repo.path, image_directory)
if os.path.isdir(full_image_directory):
if len(os.listdir(full_image_directory)) == 0:
raise ValueError("The provided --image_directory is empty.")

Check warning on line 145 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L145

Added line #L145 was not covered by tests
image_repo = DiskMemory(full_image_directory)
return Prompt(
prompt_str,
image_repo.get(".").to_dict(),
entrypoint_prompt=entrypoint_prompt,
)
else:
input_repo["prompt"] = input("\nHow do you want to improve the application?\n")
return input_repo.get("prompt")
raise ValueError("The provided --image_directory is not a directory.")

Check warning on line 153 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L153

Added line #L153 was not covered by tests


def get_preprompts_path(use_custom_preprompts: bool, input_path: Path) -> Path:
Expand Down Expand Up @@ -140,7 +192,7 @@
@app.command()
def main(
project_path: str = typer.Argument("projects/example", help="path"),
model: str = typer.Argument("gpt-4-1106-preview", help="model id string"),
model: str = typer.Argument("gpt-4-0125-preview", help="model id string"),
temperature: float = 0.1,
improve_mode: bool = typer.Option(
False,
Expand Down Expand Up @@ -184,6 +236,26 @@
"--llm-via-clipboard",
help="Use the clipboard to communicate with the AI.",
),
prompt_file: str = typer.Option(
"prompt",
"--prompt_file",
help="Relative path to a text file containing a prompt.",
),
entrypoint_prompt_file: str = typer.Option(
"",
"--entrypoint_prompt",
help="Relative path to a text file containing a file that specifies requirements for you entrypoint.",
),
image_directory: str = typer.Option(
"",
"--image_directory",
help="Relative path to a folder containing images.",
),
use_cache: bool = typer.Option(
False,
"--use_cache",
help="Speeds up computations and saves tokens when running the same prompt multiple times by caching the LLM response.",
),
verbose: bool = typer.Option(False, "--verbose", "-v"),
):
"""
Expand Down Expand Up @@ -213,6 +285,14 @@
The endpoint for Azure OpenAI services.
use_custom_preprompts : bool
Flag indicating whether to use custom preprompts.
prompt_file : str
Relative path to a text file containing a prompt.
entrypoint_prompt_file: str
Relative path to a text file containing a file that specifies requirements for you entrypoint.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great

image_directory: str
Relative path to a folder containing images.
use_cache: bool
Speeds up computations and saves tokens when running the same prompt multiple times by caching the LLM response.
verbose : bool
Flag indicating whether to enable verbose logging.

Expand All @@ -223,6 +303,8 @@

logging.basicConfig(level=logging.DEBUG if verbose else logging.INFO)

if use_cache:
set_llm_cache(SQLiteCache(database_path=".langchain.db"))

Check warning on line 307 in gpt_engineer/applications/cli/main.py

View check run for this annotation

Codecov / codecov/patch

gpt_engineer/applications/cli/main.py#L307

Added line #L307 was not covered by tests
if improve_mode:
assert not (
clarify_mode or lite_mode
Expand All @@ -248,7 +330,17 @@
print("Initializing an empty git repository")
init_git_repo(path)

prompt = load_prompt(DiskMemory(path), improve_mode)
prompt = load_prompt(
DiskMemory(path),
improve_mode,
prompt_file,
image_directory,
entrypoint_prompt_file,
)

# todo: if ai.vision is false and not llm_via_clipboard - ask if they would like to use gpt-4-vision-preview instead? If so recreate AI
if not ai.vision:
prompt.image_urls = None

# configure generation function
if clarify_mode:
Expand Down
3 changes: 2 additions & 1 deletion gpt_engineer/benchmark/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from gpt_engineer.core.base_execution_env import BaseExecutionEnv
from gpt_engineer.core.files_dict import FilesDict
from gpt_engineer.core.prompt import Prompt


@dataclass
Expand Down Expand Up @@ -56,7 +57,7 @@ class Task:
name: str
initial_code: Optional[FilesDict]
command: Optional[str]
prompt: str
prompt: Prompt
assertions: Optional[Dict[str, Assertion]]


Expand Down
Loading
Loading