From 2b277ad51d9bc1ecd68a3a9b74bbe96376ddaba6 Mon Sep 17 00:00:00 2001 From: Senko Rasic Date: Sun, 28 Jan 2024 13:36:32 -0800 Subject: [PATCH] Avoid frontend frameworks and docker if possible, and warn about them. --- pilot/helpers/Project.py | 6 ++--- pilot/helpers/agents/Architect.py | 26 ++++++++++++++++++- pilot/helpers/agents/Developer.py | 9 +++---- pilot/helpers/agents/TechLead.py | 5 +++- .../prompts/architecture/technologies.prompt | 11 ++------ .../prompts/components/project_details.prompt | 20 ++++++-------- .../development/env_setup/specs.prompt | 5 +--- pilot/prompts/development/iteration.prompt | 8 +++--- .../task/break_down_code_changes.prompt | 7 ++--- .../prompts/development/task/breakdown.prompt | 5 ++-- pilot/utils/files.py | 2 -- 11 files changed, 56 insertions(+), 48 deletions(-) diff --git a/pilot/helpers/Project.py b/pilot/helpers/Project.py index 0277c62b..f0f42194 100644 --- a/pilot/helpers/Project.py +++ b/pilot/helpers/Project.py @@ -82,9 +82,9 @@ class Project: self.clarifications = None self.user_stories = None self.user_tasks = None - self.architecture = None - self.system_dependencies = None - self.package_dependencies = None + self.architecture = "" + self.system_dependencies = [] + self.package_dependencies = [] self.development_plan = None self.dot_pilot_gpt = DotGptPilot(log_chat_completions=True) diff --git a/pilot/helpers/agents/Architect.py b/pilot/helpers/agents/Architect.py index 4128c6a7..d512a290 100644 --- a/pilot/helpers/agents/Architect.py +++ b/pilot/helpers/agents/Architect.py @@ -1,7 +1,7 @@ from utils.utils import step_already_finished from helpers.Agent import Agent import json -from utils.style import color_green_bold +from utils.style import color_green_bold, color_yellow_bold from const.function_calls import ARCHITECTURE import platform @@ -9,8 +9,12 @@ from utils.utils import should_execute_step, generate_app_data from database.database import save_progress, get_progress_steps from logger.logger import logger from helpers.AgentConvo import AgentConvo +from prompts.prompts import ask_user ARCHITECTURE_STEP = 'architecture' +WARN_SYSTEM_DEPS = ["docker", "kubernetes", "microservices"] +WARN_FRAMEWORKS = ["react", "react.js", "next.js", "vue", "vue.js", "svelte", "angular"] +WARN_FRAMEWORKS_URL = "https://github.com/Pythagora-io/gpt-pilot/wiki/Using-GPT-Pilot-with-frontend-frameworks" class Architect(Agent): @@ -68,6 +72,26 @@ class Architect(Agent): self.project.system_dependencies = llm_response["system_dependencies"] self.project.package_dependencies = llm_response["package_dependencies"] + warn_system_deps = [dep["name"] for dep in self.project.system_dependencies if dep["name"].lower() in WARN_SYSTEM_DEPS] + warn_package_deps = [dep["name"] for dep in self.project.package_dependencies if dep["name"].lower() in WARN_FRAMEWORKS] + + if warn_system_deps: + print(color_yellow_bold( + f"Warning: GPT Pilot doesn't officially support {', '.join(warn_system_deps)}. " + f"You can try to use {'it' if len(warn_system_deps) == 1 else 'them'}, but you may run into problems." + )) + print('continue', type='buttons-only') + ask_user(self.project, "Press ENTER if you still want to proceed. If you'd like to modify the project description, close the app and start a new one.", require_some_input=False) + + if warn_package_deps: + print(color_yellow_bold( + f"Warning: GPT Pilot works best with vanilla JavaScript. " + f"You can try try to use {', '.join(warn_package_deps)}, but you may run into problems. " + f"Visit {WARN_FRAMEWORKS_URL} for more information." + )) + print('continue', type='buttons-only') + ask_user(self.project, "Press ENTER if you still want to proceed. If you'd like to modify the project description, close the app and start a new one.", require_some_input=False) + # TODO: Project.args should be a defined class so that all of the possible args are more obvious if self.project.args.get('advanced', False): llm_response = self.convo_architecture.get_additional_info_from_user(ARCHITECTURE) diff --git a/pilot/helpers/agents/Developer.py b/pilot/helpers/agents/Developer.py index df496eb9..08191b3b 100644 --- a/pilot/helpers/agents/Developer.py +++ b/pilot/helpers/agents/Developer.py @@ -107,6 +107,8 @@ class Developer(Agent): "current_task_index": i, "development_tasks": self.project.development_plan, "files": self.project.get_all_coded_files(), + "architecture": self.project.architecture, + "technologies": self.project.system_dependencies + self.project.package_dependencies, "task_type": 'feature' if self.project.finished else 'app' }) @@ -491,10 +493,6 @@ class Developer(Agent): if user_feedback is not None: iteration_convo = AgentConvo(self) - technologies = ( - [dep["name"] for dep in self.project.system_dependencies] + - [dep["name"] for dep in self.project.package_dependencies] - ) iteration_description = iteration_convo.send_message('development/iteration.prompt', { "name": self.project.args['name'], "app_type": self.project.args['app_type'], @@ -502,7 +500,8 @@ class Developer(Agent): "clarifications": self.project.clarifications, "user_stories": self.project.user_stories, "user_tasks": self.project.user_tasks, - "technologies": technologies, + "architecture": self.project.architecture, + "technologies": self.project.system_dependencies + self.project.package_dependencies, "array_of_objects_to_string": array_of_objects_to_string, # TODO check why is this here "directory_tree": self.project.get_directory_tree(True), "current_task": development_task, diff --git a/pilot/helpers/agents/TechLead.py b/pilot/helpers/agents/TechLead.py index faa7a24f..19a9d0de 100644 --- a/pilot/helpers/agents/TechLead.py +++ b/pilot/helpers/agents/TechLead.py @@ -40,6 +40,8 @@ class TechLead(Agent): "clarifications": self.project.clarifications, "user_stories": self.project.user_stories, "user_tasks": self.project.user_tasks, + "architecture": self.project.architecture, + "technologies": self.project.system_dependencies + self.project.package_dependencies, "task_type": 'app', }, DEVELOPMENT_PLAN) self.project.development_plan = llm_response['plan'] @@ -65,7 +67,8 @@ class TechLead(Agent): "clarifications": self.project.clarifications, "user_stories": self.project.user_stories, "user_tasks": self.project.user_tasks, - "technologies": self.project.architecture, + "architecture": self.project.architecture, + "technologies": self.project.system_dependencies + self.project.package_dependencies, "directory_tree": self.project.get_directory_tree(True), "development_tasks": self.project.development_plan, "files": self.project.get_all_coded_files(), diff --git a/pilot/prompts/architecture/technologies.prompt b/pilot/prompts/architecture/technologies.prompt index 2a842783..1e87a607 100644 --- a/pilot/prompts/architecture/technologies.prompt +++ b/pilot/prompts/architecture/technologies.prompt @@ -17,14 +17,13 @@ Based on these details, think step by step to design the architecture for the pr * You must only list *system* dependencies, ie. the ones that need to be installed (typically as admin) to set up the programming language, database, etc. Any packages that will need to be installed via language/platform-specific package managers are *not* system dependencies. * If there are several popular options (such as Nginx or Apache for web server), pick one that would be more suitable for the app in question. -* DO NOT include text editors, IDEs, shells, OpenSSL, CLI tools such as AWS, or Stripe clients, or other utilities in your list. only direct dependencies required to build and run the project. +* DO NOT include text editors, IDEs, shells, OpenSSL, CLI tools such as git, AWS, or Stripe clients, or other utilities in your list. only direct dependencies required to build and run the project. * If a dependency (such as database) has a cloud alternative or can be installed on another computer (ie. isn't required on this computer), you must mark it as `required_locally: false` Output only your response in JSON format like in this example, without other commentary: ``` { - "architecture": "Detailed description of the arch -itecture of the application", + "architecture": "Detailed description of the architecture of the application", "system_dependencies": [ { "name": "Node.js", @@ -32,12 +31,6 @@ itecture of the application", "test": "node --version", "required_locally": true }, - { - "name": "git", - "description": "A popular version control system. Required to be able to store your code in version control.", - "test": "git --version", - "required_locally": true - }, { "name": "MongoDB", "description": "NoSQL database. If you don't want to install MongoDB locally, you can use a cloud version such as MongoDB Atlas.", diff --git a/pilot/prompts/components/project_details.prompt b/pilot/prompts/components/project_details.prompt index f4f37976..c40a07db 100644 --- a/pilot/prompts/components/project_details.prompt +++ b/pilot/prompts/components/project_details.prompt @@ -3,8 +3,7 @@ Here is a high level description of "{{ name }}": {{ app_summary }} ``` -{% if clarifications %} -Here are some additional questions and answers to clarify the apps description: +{% if clarifications %}Here are some additional questions and answers to clarify the apps description: ``` {% for clarification in clarifications %} Q: {{ clarification.question }} @@ -12,28 +11,25 @@ A: {{ clarification.answer }} {% endfor %} ``` -{% endif %}{% if user_stories %} -Here are user stories that specify how users use "{{ name }}": +{% endif %}{% if architecture %}Here is a short description of the project architecture: +{{ architecture }} + +{% endif %}{% if user_stories %}Here are user stories that specify how users use "{{ name }}": ``` {% for story in user_stories %} - {{ story }} {% endfor %} ``` -{% endif %}{% if user_tasks %} -Here are user tasks that specify what users need to do to interact with "{{ name }}": +{% endif %}{% if user_tasks %}Here are user tasks that specify what users need to do to interact with "{{ name }}": ``` {% for task in user_tasks %} - {{ task }} {% endfor %} ``` -{% endif %}{% if technologies %} -Here are the technologies that {% if task_type == 'feature' %}that were used{% else %}you need to use{% endif %} for this project: -``` +{% endif %}{% if technologies %}Here are the technologies that {% if task_type == 'feature' %}that were used{% else %}you need to use{% endif %} for this project: {% for tech in technologies %} -- {{ tech }} -{% endfor %} -``` +* {{ tech["name"] }} - {{ tech["description"] }}{% endfor %} {% endif %} \ No newline at end of file diff --git a/pilot/prompts/development/env_setup/specs.prompt b/pilot/prompts/development/env_setup/specs.prompt index a6c978d6..b0d96b92 100644 --- a/pilot/prompts/development/env_setup/specs.prompt +++ b/pilot/prompts/development/env_setup/specs.prompt @@ -1,11 +1,8 @@ You are working in a software development agency and a project manager and software architect approach you telling you that you're assigned to work on a new project. You are working on a {{ app_type }} called "{{ name }}" and your first job is to set up the environment on a computer. Here are the technologies that you need to use for this project: -``` {% for tech in technologies %} -- {{ tech }} -{% endfor %} -``` +* {{ tech["name"] }} - {{ tech["description"] }}{% endfor %} Let's set up the environment on my machine. Here are the details about my machine: ``` diff --git a/pilot/prompts/development/iteration.prompt b/pilot/prompts/development/iteration.prompt index e2438808..4e9457ee 100644 --- a/pilot/prompts/development/iteration.prompt +++ b/pilot/prompts/development/iteration.prompt @@ -5,10 +5,12 @@ Here is a high level description of "{{ name }}": {{ app_summary }} ``` +Project architecture: +{{ architecture }} + Here are the technologies that you need to use for this project: -```{% for tech in technologies %} -- {{ tech }}{% endfor %} -``` +{% for tech in technologies %} +* {{ tech["name"] }} - {{ tech["description"] }}{% endfor %} {% if development_tasks and current_task %} Development process of this app was split into smaller tasks. Here is the list of all tasks: diff --git a/pilot/prompts/development/task/break_down_code_changes.prompt b/pilot/prompts/development/task/break_down_code_changes.prompt index fbda8dc9..9fa20729 100644 --- a/pilot/prompts/development/task/break_down_code_changes.prompt +++ b/pilot/prompts/development/task/break_down_code_changes.prompt @@ -9,11 +9,8 @@ Here is the current folder tree: ``` Here are technologies that you can use: -``` -{% for technology in technologies %} -- {{ technology }} -{% endfor %} -``` +{% for tech in technologies %} +* {{ tech["name"] }} - {{ tech["description"] }}{% endfor %} First, you need to break down these instructions into actionable steps that can be made. There are 2 types of steps. If a step requires a change in a file content, that step is of a type `code_change` and if a change requires a command to be run (eg. to create a file or a folder), that step is of a type `run_command`. For a step to be actionable, it cannot have a vague description but a clear explanation of what needs to be done to finish that step. Here are a couple of examples of good and bad steps: diff --git a/pilot/prompts/development/task/breakdown.prompt b/pilot/prompts/development/task/breakdown.prompt index 593f9428..5a57856d 100644 --- a/pilot/prompts/development/task/breakdown.prompt +++ b/pilot/prompts/development/task/breakdown.prompt @@ -2,8 +2,7 @@ You are working on a {{ app_type }} called "{{ name }}" and you need to write co {{ project_details }} -{% if current_task_index != 0 or task_type == 'feature' %} -So far, this code has been implemented: +{% if current_task_index != 0 or task_type == 'feature' %}So far, this code has been implemented: {% for file in files %} **{{ file.path }}/{{ file.name }}**: ```{# file.language #} @@ -11,8 +10,8 @@ So far, this code has been implemented: ``` {% endfor %} -{% endif %} +{% endif %} We've broken the development of this {{ task_type }} down to these tasks: ```{% for task in development_tasks %} {{ loop.index }}. {{ task['description'] }} diff --git a/pilot/utils/files.py b/pilot/utils/files.py index 97bf0288..3063f1b9 100644 --- a/pilot/utils/files.py +++ b/pilot/utils/files.py @@ -15,7 +15,6 @@ def get_parent_folder(folder_name): def setup_workspace(args) -> str: """ Creates & returns the path to the project workspace. - Also creates a 'tests' folder inside the workspace. :param args: may contain 'root' key """ workspace = args.get('workspace') @@ -26,7 +25,6 @@ def setup_workspace(args) -> str: name = args.get('name', 'default_project_name') project_path = create_directory(os.path.join(root, 'workspace'), name) - create_directory(project_path, 'tests') try: save_user_app(args.get('user_id'), args.get('app_id'), project_path) except Exception as e: