diff --git a/examples/interior-designer/README.md b/examples/interior-designer/README.md new file mode 100644 index 00000000..80eec542 --- /dev/null +++ b/examples/interior-designer/README.md @@ -0,0 +1,45 @@ +# Interior Designer + +It allows you to upload a picture of your room and describe how you want it redesigned. The app will first analyze the image and identify the items in it. Then, based on your description, it will suggest changes you can make to redesign your room, including the color scheme, furniture, objects you can add, etc. and search for products on the internet and share their links as well. + +## High-level overview + +- Users can upload a picture of a room and provide a description of how their room wants to be. +- The Python backend takes this input and uses GPTScript’s Python module to execute the GPTScript. +- The vision tool first analyzes the image, followed by a generation of ideas. +- The output of both is sent to the search tool, which searches the Internet for products you can purchase and add to your room. +- These are saved within a markdown file that is read and displayed on the screen. + +## Installation + +### Prerequisites + +- Python 3.8 or later +- Flask +- Python dependencies listed in `requirements.txt` respectively. + +### Steps + +1. Clone the repository: + + ``` bash + git clone https://github.com/gptscript-ai/gptscript.git + ``` + +2. Navigate to the `examples/interior-designer` directory and install the dependencies: + + Python: + + ```bash + pip install -r requirements.txt + ``` + +3. Setup `OPENAI_API_KEY` (Eg: `export OPENAI_API_KEY="yourapikey123456"`). You can get your [API key here](https://platform.openai.com/api-keys). + +4. Run the Flask application using `flask run` or `python app.py` + +## Usage + +1. Open your web browser and navigate to `http://127.0.0.1:5000/`. +2. Use the interface to provide upload an image and provide a description. +3. The application will generate ideas to redesing your room. \ No newline at end of file diff --git a/examples/interior-designer/app.py b/examples/interior-designer/app.py new file mode 100644 index 00000000..dd767c3f --- /dev/null +++ b/examples/interior-designer/app.py @@ -0,0 +1,66 @@ +from gptscript.command import stream_exec_file +from flask import Flask, render_template, request, jsonify +import os +import uuid +from werkzeug.utils import secure_filename + +app = Flask(__name__) + +# Setting the base directory +base_dir = os.path.dirname(os.path.abspath(__file__)) +app.config['PWD'] = base_dir +SCRIPT_PATH = os.path.join(base_dir, 'designer.gpt') + +# The output file name +def print_output(out, err): + # Error stream has the debug info that is useful to see + for line in err: + print(line) + for line in out: + print(line) + +@app.route('/') +def index(): + return render_template('index.html') + +def save_image(image_file, image_file_name, request_id): + # Save the uploaded image to the current directory + image_path = os.path.join(app.config['PWD'], image_file_name) + image_file.save(image_path) + + return image_path + +@app.route('/get-ideas', methods=['POST']) +def get_ideas(): + try: + # Generate a unique request ID + request_id = str(uuid.uuid4()) + + # Get the image file and prompt from the request + image_file = request.files['image'] + prompt = request.form['prompt'] + + # Generate an input image and output file name based on the request ID + image_file_name = f"{request_id}_room.jpg" + output_file_name = f"{request_id}_output.md" + output_file_path = os.path.join(app.config['PWD'], output_file_name) + + # Save the image file to the current directory + image_path = save_image(image_file, image_file_name, request_id) + + # Execute the script with the prompt, image path and outputfile name + out, err, wait = stream_exec_file(SCRIPT_PATH, "--prompt " + prompt + " --outputfile "+output_file_name + " --imagefile "+image_file_name) + print_output(out, err) + wait() + + # Read the output file + with open(output_file_path, 'r') as output_file: + summary = output_file.read() + + # Return the summary content + return summary + except Exception as e: + return jsonify({'error': str(e)}), 500 + +if __name__ == '__main__': + app.run(debug=os.environ.get('FLASK_DEBUG', True), host='0.0.0.0') \ No newline at end of file diff --git a/examples/interior-designer/designer.gpt b/examples/interior-designer/designer.gpt new file mode 100644 index 00000000..470b6ae5 --- /dev/null +++ b/examples/interior-designer/designer.gpt @@ -0,0 +1,24 @@ +tools: sys.find, sys.read, sys.write, search, github.com/gptscript-ai/gpt4-v-vision +args: prompt: Prompt from the user. +args: outputfile: Name of the output file. +args: imagefile: Name of the image file. + +You are an ace interior designer and decorater. For the image provided, analyse the image and prompt and perform the following steps in order: + +1. Call the vision tool and send a prompt to "Anaylse the image $(imagefilename) in the current directory and identify the objects in the image". +2. Based on the above analysis and the prompt provided, suggest the changes that can be done in the room in terms of paint color, theme, wallpaper, objects, furniture that can be added to the room. +3. If you feel that some of the identified objects can be resued, suggest them too. +4. Search google for new furnitures and objects suggested for the room based on the prompt. +5. Create a new md file named $(outputfile) and insert the $(imagefilename) image on the top followed by the analysis, recommendations, how to reuse some items and product links with proper headings, bullets etc. + + +--- +name: search +description: Searches the internet for content +args: query: The query to search for +tools: sys.http.html2text? + +1. Search google "https://www.google.com/search?q={$query}" for products and download content. +2. Look for the first 3 search results that have the products that relate to the room. +3. Download each search result and look for product that would best answer the query ${query}. +4. Return the link to products that one can buy. \ No newline at end of file diff --git a/examples/interior-designer/dockerfile b/examples/interior-designer/dockerfile new file mode 100644 index 00000000..afbe925e --- /dev/null +++ b/examples/interior-designer/dockerfile @@ -0,0 +1,26 @@ +# Use the official Python image as the base image +FROM python:3.9-slim + +# Set the working directory +WORKDIR /app + +# Copy the requirements file +COPY requirements.txt . + +# Install the Python dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Copy the Flask app code +COPY . . + +# Expose the port +EXPOSE 5000 + +# Set the environment variable +ENV FLASK_APP=app.py + +# Set this to True/False to enable/disable debugging. +ENV FLASK_DEBUG=False + +# Run app +CMD ["flask", "run", "--host=0.0.0.0"] \ No newline at end of file diff --git a/examples/interior-designer/requirements.txt b/examples/interior-designer/requirements.txt new file mode 100644 index 00000000..22a041a0 --- /dev/null +++ b/examples/interior-designer/requirements.txt @@ -0,0 +1,3 @@ +Flask==2.0.1 +gptscript==0.4.1 +Werkzeug==2.2.2 diff --git a/examples/interior-designer/static/css/style.css b/examples/interior-designer/static/css/style.css new file mode 100644 index 00000000..84aa1e27 --- /dev/null +++ b/examples/interior-designer/static/css/style.css @@ -0,0 +1,46 @@ +/* style.css */ +body { + background-color: #f8f2e6; + font-family: 'Merriweather', serif; + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; +} + +.container { + max-width: 500px; + width: 60%; + padding: 0 10px; +} + +.input, .button { + border-radius: 0 !important; +} + +.box { + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + border-radius: 0; + padding: 30px; +} + +.markdown-body { + box-sizing: border-box; + background-color: #f5f5f5; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + border-radius: 0; + padding: 30px; +} + +.gpt-logo { + height: 100%; + width: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.gpt-logo img { + width: 15%; + height: 15%; +} \ No newline at end of file diff --git a/examples/interior-designer/static/js/app.js b/examples/interior-designer/static/js/app.js new file mode 100644 index 00000000..03b5c239 --- /dev/null +++ b/examples/interior-designer/static/js/app.js @@ -0,0 +1,63 @@ +// app.js +new Vue({ + el: '#app', + data: { + prompt: '', + imageFile: null, + imageUrl: null, + showIdeas: false, + ideasMarkdown: '', + renderedMarkdown: '', + isLoading: false + }, + methods: { + handleImageUpload(event) { + this.imageFile = event.target.files[0]; + this.imageUrl = URL.createObjectURL(event.target.files[0]); + }, + getIdeas() { + this.isLoading = true; + const formData = new FormData(); + formData.append('image', this.imageFile); + formData.append('prompt', this.prompt); + + axios.post('/get-ideas', formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + .then(response => { + this.ideasMarkdown = response.data; + this.renderedMarkdown = marked.parse(this.ideasMarkdown); + this.showIdeas = true; + }) + .catch(error => { + if (error.response && error.response.data && error.response.data.error) { + alert('Error: ' + error.response.data.error); + } else { + alert('An unexpected error occurred. Please try again later.'); + } + }) + .finally(() => { + this.isLoading = false; + }); + } + } +}); + +// Initialize the marked library +marked.setOptions({ + renderer: new marked.Renderer(), + highlight: function(code, language) { + const hljs = require('highlight.js'); + const validLanguage = hljs.getLanguage(language) ? language : 'plaintext'; + return hljs.highlight(validLanguage, code).value; + }, + pedantic: false, + gfm: true, + breaks: false, + sanitize: false, + smartLists: true, + smartypants: false, + xhtml: false +}); \ No newline at end of file diff --git a/examples/interior-designer/static/made-with-gptscript.png b/examples/interior-designer/static/made-with-gptscript.png new file mode 100644 index 00000000..01fbff4c Binary files /dev/null and b/examples/interior-designer/static/made-with-gptscript.png differ diff --git a/examples/interior-designer/templates/index.html b/examples/interior-designer/templates/index.html new file mode 100644 index 00000000..0170f58b --- /dev/null +++ b/examples/interior-designer/templates/index.html @@ -0,0 +1,53 @@ + + + + + Interior Designer + + + + + + + + + +
+
+
+

Interior Designer

+

Are you bored of how your room looks? Want some inspiration to redesign your room? Simply click a picutre of your room, add a prompt and upload it here and see the magic unfold!

+
+
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+ Uploaded Image +
+
+ +
+ + + + + \ No newline at end of file