From d5365d72ceb0d11f15955c19422a6b4dbf2cc5ae Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 08:59:32 -0400 Subject: [PATCH 01/24] Create picture-hanger.py Clone of voting flowchart generator, just to start with something. --- picture-hanger.py | 143 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 picture-hanger.py diff --git a/picture-hanger.py b/picture-hanger.py new file mode 100644 index 0000000..1406a16 --- /dev/null +++ b/picture-hanger.py @@ -0,0 +1,143 @@ +PUBLISHED = False +APP_URL = "https://voting-decision-tree.streamlit.app" + +APP_TITLE = "How To Vote: A Decision Tree Generator for College Students" +APP_INTRO = """This app helps you draw a custom flowchart to help your students decide when and where to vote. +""" + +APP_HOW_IT_WORKS = """ +A simple flowchart can help students overwhelmed with classes fit voting into their schedule. This app tries to draw a custom decision tree based on a teacher's answers to a few fields.\n\nIt utilizes the OpenAI and other AI APIs to send a custom prompt to AI with the user's inputs and returns the AI's response. + """ + +SHARED_ASSET = { +} + +HTML_BUTTON = { + "button_text": "BallotPedia.org Sample Ballot", + "url": "https://ballotpedia.org/wiki/index.php?title=Sample_Ballot_Lookup&Source=sitenotice" +} + + + +SYSTEM_PROMPT = """Acting as an expert in data visualization, you will generate the code required to draw a decision tree. You must use the syntax for the Mermaid.js JavaScript library to produce the visualization. Do not create an image directly with a text-to-image generator like DALL-E; it must be constructed with the markdown-like Mermaid.js code.""" + +PHASES = { + "tree-generation": { + "name": "Build your Voting Decision Chart", + "fields": { + "info": { + "type": "markdown", + "body": "Select the options that your students have available to them to generate a shareable voting decision tree. Students should have at least the option to vote at home, on-campus, or off-campus in order for the tool to generate results." + }, + "hometown-option": { + "type": "checkbox", + "label": """My students have enough time to vote at home.""", + "help": "If so, the flowchart will give them the option to vote in their hometowns.", + }, + "absentee-option": { + "type": "checkbox", + "label": """My students have enough time to order an absentee ballot.""", + "help": "If checked, the flowchart will offer that option.", + }, + "oncampus-option": { + "type": "checkbox", + "label": """My students can vote on-campus.""", + "help": "This assumes there's one or more designated campus facilities.", + }, + "oncampus-locations": { + "type": "text_input", + "label": """Where can students vote on-campus?""", + "help": "Give one or more times and/or addresses. Short answers fit the flowchart best!", + "value": "9am-5pm in 123 Susan B. Anthony Hall", + }, + "oncampus-requirements": { + "type": "text_input", + "label": """What must students do to vote on campus?""", + "help": "Mention any requirements for voting in that location.", + "value": "Bring a photo id and proof of residency", + }, + "offcampus-option": { + "type": "checkbox", + "label": """Students can vote off-campus in nearby town/s.""", + "help": "If checked, the flowchart will offer that option.", + }, + "offcampus-locations": { + "type": "text_input", + "label": """Where can students vote off-campus?""", + "help": "Give one or more times and/or addresses. Short answers fit the flowchart best!", + "value": "9am-5pm at the Springfield Town Hall, 789 Main Street", + }, + "offcampus-requirements": { + "type": "text_input", + "label": """What must students do to vote off campus?""", + "help": "Mention any requirements for voting in that location.", + "value": "Bring a photo id and proof of residency", + }, + }, + "user_prompt": [ + { + "condition": {}, + "prompt": "Please generate mermaid.js code with a decision tree for voting. Here are the steps in order." + }, + { + "condition": {}, + "prompt": "- Start off by asking if the user wants to vote. If no, then tell them thank you and end the branch. If yes, then provide the following options:\n", + }, + { + "condition": {"$or":[{"hometown-option": True},{"absentee-option": True}]}, + "prompt": "- Ask if the user wants to vote on hometown issues. If yes, then ask if they have time to go home. If the student has time to go home, then this branch stops with 'Go home and vote. Check 'ballotpedia.org' for local voting information.' If the student does not have time, then end this branch with 'Request an absentee ballot'.\n", + }, + { + "condition": {"oncampus-option": True}, + "prompt": "Vote on campus.\n End the branch with a box that includes \"{oncampus-locations}\" and \"{oncampus-requirements}\"\n", + }, + { + "condition": {"offcampus-option": True}, + "prompt": "Vote off campus.\n End the branch with a box that includes \"{offcampus-locations}\" and \"{offcampus-requirements}\"\n", + }, + { + "condition": {}, + "prompt": """Once you have shared the Mermaid.js code to generate this flowchart, tell the user to paste in into the Mermaid live editor, and give the user a link to https://mermaid.live. Also tell the user that non-partisan information about candidates and issues on their ballot can be found at Ballotpedia, and give them a link to https://ballotpedia.org/wiki/index.php?title=Sample_Ballot_Lookup&Source=sitenotice with a recommendation to type their zip code into the search box.""" + }, + ], + "ai_response": True, + "allow_skip": False, + "show_prompt": True, + "allow_revisions": True, + #"read_only_prompt": False + } +} + +PREFERRED_LLM = "gpt-4o-mini" +LLM_CONFIG_OVERRIDE = {"gpt-4o-mini": { + "family": "openai", + "model": "gpt-4o-mini", + "max_tokens": 1000, + "temperature": 1.0, + "top_p": 1.0, + "frequency_penalty": 0, + "presence_penalty": 0, + "supports_image": False, + "price_input_token_1M": 0.15, + "price_output_token_1M": 0.60 + } +} + +PAGE_CONFIG = { + "page_title": "Voting Decision Tree", + "page_icon": "️✅", + "layout": "centered", + "initial_sidebar_state": "collapsed" +} + +SIDEBAR_HIDDEN = True + +SCORING_DEBUG_MODE = True +DISPLAY_COST = True + +COMPLETION_MESSAGE = "⚠️ Chatbots can generate incorrect results; always check the output before publishing it. We hope this app makes voting easier!" +COMPLETION_CELEBRATION = False + +from core_logic.main import main +if __name__ == "__main__": + main(config=globals()) From cb8710500d3a90a7dca74b9f44cad59fd8d7d588 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 09:02:26 -0400 Subject: [PATCH 02/24] Rename picture-hanger.py to app_picture_hanger.py To fit John Swope's naming convention. --- picture-hanger.py => app_picture_hanger.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename picture-hanger.py => app_picture_hanger.py (100%) diff --git a/picture-hanger.py b/app_picture_hanger.py similarity index 100% rename from picture-hanger.py rename to app_picture_hanger.py From 4364b235a1a32128b8f70169eef7da06ea503626 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 09:05:24 -0400 Subject: [PATCH 03/24] Update app_picture_hanger.py Updating title and intro text. --- app_picture_hanger.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 1406a16..0744d9c 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -1,9 +1,8 @@ PUBLISHED = False APP_URL = "https://voting-decision-tree.streamlit.app" -APP_TITLE = "How To Vote: A Decision Tree Generator for College Students" -APP_INTRO = """This app helps you draw a custom flowchart to help your students decide when and where to vote. -""" +APP_TITLE = "Hang a Picture" +APP_INTRO = """This app helps you hang a painting, framed photo, or other flat artwork on the wall of a home or gallery""" APP_HOW_IT_WORKS = """ A simple flowchart can help students overwhelmed with classes fit voting into their schedule. This app tries to draw a custom decision tree based on a teacher's answers to a few fields.\n\nIt utilizes the OpenAI and other AI APIs to send a custom prompt to AI with the user's inputs and returns the AI's response. From cf1ffe796ae42a8e60d73d24a9589f8388e8a71d Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 09:55:26 -0400 Subject: [PATCH 04/24] Update app_picture_hanger.py --- app_picture_hanger.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 0744d9c..935bf40 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -5,7 +5,7 @@ APP_INTRO = """This app helps you hang a painting, framed photo, or other flat artwork on the wall of a home or gallery""" APP_HOW_IT_WORKS = """ -A simple flowchart can help students overwhelmed with classes fit voting into their schedule. This app tries to draw a custom decision tree based on a teacher's answers to a few fields.\n\nIt utilizes the OpenAI and other AI APIs to send a custom prompt to AI with the user's inputs and returns the AI's response. +This app helps you hang a picture by telling you where to hammer your nail based on the size of your wall and the frame.\n\nIt uses OpenAI behind the scenes to calculate this position based on the fields you complete and generates instructions accordingly. """ SHARED_ASSET = { @@ -16,8 +16,6 @@ "url": "https://ballotpedia.org/wiki/index.php?title=Sample_Ballot_Lookup&Source=sitenotice" } - - SYSTEM_PROMPT = """Acting as an expert in data visualization, you will generate the code required to draw a decision tree. You must use the syntax for the Mermaid.js JavaScript library to produce the visualization. Do not create an image directly with a text-to-image generator like DALL-E; it must be constructed with the markdown-like Mermaid.js code.""" PHASES = { @@ -123,8 +121,8 @@ } PAGE_CONFIG = { - "page_title": "Voting Decision Tree", - "page_icon": "️✅", + "page_title": "Hang a Picture", + "page_icon": "️🖼", "layout": "centered", "initial_sidebar_state": "collapsed" } From 2f0bdbad1728d7aa3c163b4c224f1e7690c1c8c7 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 10:16:44 -0400 Subject: [PATCH 05/24] Update app_picture_hanger.py Updating system prompt. --- app_picture_hanger.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 935bf40..1efa6d7 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -12,11 +12,11 @@ } HTML_BUTTON = { - "button_text": "BallotPedia.org Sample Ballot", - "url": "https://ballotpedia.org/wiki/index.php?title=Sample_Ballot_Lookup&Source=sitenotice" + "button_text": "Make your own AI MicroApp", + "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } -SYSTEM_PROMPT = """Acting as an expert in data visualization, you will generate the code required to draw a decision tree. You must use the syntax for the Mermaid.js JavaScript library to produce the visualization. Do not create an image directly with a text-to-image generator like DALL-E; it must be constructed with the markdown-like Mermaid.js code.""" +SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Do not create an image directly with a text-to-image generator like DALL-E; it must be constructed with the markdown-like Mermaid.js code.""" PHASES = { "tree-generation": { From 5aeb65d24c0ba577d73a89d9b97e5725fb211e46 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 10:23:08 -0400 Subject: [PATCH 06/24] Update app_picture_hanger.py Updated system prompt. --- app_picture_hanger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 1efa6d7..79f9b75 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -16,7 +16,7 @@ "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } -SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Do not create an image directly with a text-to-image generator like DALL-E; it must be constructed with the markdown-like Mermaid.js code.""" +SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. After typing out these instructions, write a prompt to be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting she or he enter this prompt into ChatGPT.com to generate a useful diagram.""" PHASES = { "tree-generation": { From e27cd868eabe1180c44956218d4337a434b46c12 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 10:28:55 -0400 Subject: [PATCH 07/24] Update app_picture_hanger.py Modifying phases. --- app_picture_hanger.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 79f9b75..d47c363 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -19,17 +19,17 @@ SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. After typing out these instructions, write a prompt to be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting she or he enter this prompt into ChatGPT.com to generate a useful diagram.""" PHASES = { - "tree-generation": { - "name": "Build your Voting Decision Chart", + "dimension_calculations": { + "name": "Calculate your nail's position", "fields": { "info": { "type": "markdown", - "body": "Select the options that your students have available to them to generate a shareable voting decision tree. Students should have at least the option to vote at home, on-campus, or off-campus in order for the tool to generate results." + "body": "Use a tape measure to find the following dimensions." }, - "hometown-option": { - "type": "checkbox", - "label": """My students have enough time to vote at home.""", - "help": "If so, the flowchart will give them the option to vote in their hometowns.", + "measurement-units": { + "type": "text_input", + "label": """Are you measuring dimensions in inches or centimeters?""", + "help": "Just type .", }, "absentee-option": { "type": "checkbox", From d279b2853fba52595459f0203b5f8ae39f69b926 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 11:16:04 -0400 Subject: [PATCH 08/24] Update app_picture_hanger.py Customizing questions. --- app_picture_hanger.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index d47c363..99bb352 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -16,7 +16,7 @@ "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } -SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. After typing out these instructions, write a prompt to be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting she or he enter this prompt into ChatGPT.com to generate a useful diagram.""" +SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. You'll calculate the EYE_HEIGHT = .93 * VIEWER_HEIGHT. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. After typing out these instructions, write a prompt to be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting she or he enter this prompt into ChatGPT.com to generate a useful diagram.""" PHASES = { "dimension_calculations": { @@ -27,9 +27,23 @@ "body": "Use a tape measure to find the following dimensions." }, "measurement-units": { - "type": "text_input", - "label": """Are you measuring dimensions in inches or centimeters?""", - "help": "Just type .", + "type": "selectbox", + "options": ['inches', 'centimeters'], + "help": "Are you measuring dimensions in inches or centimeters? (Whole numbers without fractions or decimals will suffice)", + }, + "viewer-height-inches": { + "type": "slider", + "min_value": 60, + "max_value": 75, + "label": "How tall is your average viewer in inches? (The average American height is 66 in.)", + "showIf": {"measurement-units": "inches"}, + }, + "viewer-height-cm": { + "type": "slider", + "min_value": 155, + "max_value": 180, + "label": "How tall is your average viewer in centimeters? (The average American height is 168 cm.)", + "showIf": {"measurement-units": "centimeters"}, }, "absentee-option": { "type": "checkbox", @@ -74,7 +88,7 @@ "user_prompt": [ { "condition": {}, - "prompt": "Please generate mermaid.js code with a decision tree for voting. Here are the steps in order." + "prompt": "Please use \"{measurement-units}\" in all of your output for this prompt." }, { "condition": {}, From f12a885055420f2334dfa662fc78c9da5b2f87d0 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 11:25:57 -0400 Subject: [PATCH 09/24] Update app_picture_hanger.py Customizing questions. --- app_picture_hanger.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 99bb352..68483d3 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -45,6 +45,23 @@ "label": "How tall is your average viewer in centimeters? (The average American height is 168 cm.)", "showIf": {"measurement-units": "centimeters"}, }, + "picture-height": { + "type": "number_input", + "step": 1, + "label": "What's the height of your picture, including the frame?", + }, + "drop-to-hardware": { + "type": "number_input", + "step": 1, + "label": "How far below the top of the picture is the hanger on the back?", + "help": "Measure down from the top to the place where the nail will go, whether a hook or a wire held taut, in the units you chose (inches or cm).", + }, + "available_wall_width": { + "type": "number_input", + "step": 1, + "label": "How much horizontal wall space is available?", + "help": "Include the total span in the units you chose (inches or cm), eg between adjacent walls, nearby furniture, or pictures to the left and right.", + }, "absentee-option": { "type": "checkbox", "label": """My students have enough time to order an absentee ballot.""", From f9d1aa6a3ba5c661a15f4497bb5c20f846a9a891 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 11:33:13 -0400 Subject: [PATCH 10/24] Update app_picture_hanger.py Customizing questions. --- app_picture_hanger.py | 52 +++++++++++-------------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 68483d3..14b88f0 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -16,7 +16,7 @@ "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } -SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. You'll calculate the EYE_HEIGHT = .93 * VIEWER_HEIGHT. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. After typing out these instructions, write a prompt to be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting she or he enter this prompt into ChatGPT.com to generate a useful diagram.""" +SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. You'll calculate the EYE_HEIGHT = .93 * VIEWER_HEIGHT. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. After typing out these instructions, write a prompt to be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting she or he enter this prompt into ChatGPT.com to generate a useful diagram.""" PHASES = { "dimension_calculations": { @@ -29,7 +29,8 @@ "measurement-units": { "type": "selectbox", "options": ['inches', 'centimeters'], - "help": "Are you measuring dimensions in inches or centimeters? (Whole numbers without fractions or decimals will suffice)", + "label": "Are you measuring dimensions in inches or centimeters?", + "help": "Whole numbers without fractions or decimals will suffice", }, "viewer-height-inches": { "type": "slider", @@ -62,44 +63,17 @@ "label": "How much horizontal wall space is available?", "help": "Include the total span in the units you chose (inches or cm), eg between adjacent walls, nearby furniture, or pictures to the left and right.", }, - "absentee-option": { - "type": "checkbox", - "label": """My students have enough time to order an absentee ballot.""", - "help": "If checked, the flowchart will offer that option.", - }, - "oncampus-option": { - "type": "checkbox", - "label": """My students can vote on-campus.""", - "help": "This assumes there's one or more designated campus facilities.", - }, - "oncampus-locations": { - "type": "text_input", - "label": """Where can students vote on-campus?""", - "help": "Give one or more times and/or addresses. Short answers fit the flowchart best!", - "value": "9am-5pm in 123 Susan B. Anthony Hall", - }, - "oncampus-requirements": { - "type": "text_input", - "label": """What must students do to vote on campus?""", - "help": "Mention any requirements for voting in that location.", - "value": "Bring a photo id and proof of residency", - }, - "offcampus-option": { - "type": "checkbox", - "label": """Students can vote off-campus in nearby town/s.""", - "help": "If checked, the flowchart will offer that option.", - }, - "offcampus-locations": { - "type": "text_input", - "label": """Where can students vote off-campus?""", - "help": "Give one or more times and/or addresses. Short answers fit the flowchart best!", - "value": "9am-5pm at the Springfield Town Hall, 789 Main Street", + "picture-weight": { + "type": "selectbox", + "options": ['light (under 5 pounds)', 'medium (5-20 pounds)', 'heavy (over 20 pounds)'], + "label": "How heavy is the picture?", + "help": "Include the frame and glazing, if any" }, - "offcampus-requirements": { - "type": "text_input", - "label": """What must students do to vote off campus?""", - "help": "Mention any requirements for voting in that location.", - "value": "Bring a photo id and proof of residency", + "wall-type": { + "type": "selectbox", + "options": ['normal', 'reinforced'], + "label": "What type of wall are you hanging on?", + "help": "Most buildings have normal drywall, but some galleries are reinforced with plywood backing" }, }, "user_prompt": [ From 702059e7b92eec3042eeda9c176162fd0c2b796c Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 11:35:50 -0400 Subject: [PATCH 11/24] Update app_picture_hanger.py Updating system prompt. --- app_picture_hanger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 14b88f0..a68cf38 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -16,7 +16,7 @@ "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } -SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. You'll calculate the EYE_HEIGHT = .93 * VIEWER_HEIGHT. For the nail's height off the floor, use the formula NAIL_HEIGHT = EYE_HEIGHT + (PICTURE_HEIGHT/2) - DROP_TO_HARDWARE. For the nail's distance from the nearest horizontal obstacle, use the formula NAIL_HORIZONTAL_POSITION = AVAILABLE_WALL_WIDTH/2. If the PICTURE_WEIGHT is "light", recommend using a simple nail or adhesive hook; if the PICTURE_WEIGHT is "medium", recommend a picture hook or wall anchor; the PICTURE_WEIGHT is "heavy", recommend hammering a nail into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center. If the WALL_TYPE is "reinforced", explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. After typing out these instructions, write a prompt to be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting she or he enter this prompt into ChatGPT.com to generate a useful diagram.""" +SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. You may also mention tips such as placing painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust.""" PHASES = { "dimension_calculations": { From 0a7b9f04a88a55d9ff1072be084e0f8cb8695dae Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 11:44:23 -0400 Subject: [PATCH 12/24] Update app_picture_hanger.py Customizing user prompt. --- app_picture_hanger.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index a68cf38..f00344a 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -39,7 +39,7 @@ "label": "How tall is your average viewer in inches? (The average American height is 66 in.)", "showIf": {"measurement-units": "inches"}, }, - "viewer-height-cm": { + "viewer-height-centimeters": { "type": "slider", "min_value": 155, "max_value": 180, @@ -73,7 +73,7 @@ "type": "selectbox", "options": ['normal', 'reinforced'], "label": "What type of wall are you hanging on?", - "help": "Most buildings have normal drywall, but some galleries are reinforced with plywood backing" + "help": "Most American rooms have normal drywall, but some galleries are reinforced with plywood backing" }, }, "user_prompt": [ @@ -81,10 +81,22 @@ "condition": {}, "prompt": "Please use \"{measurement-units}\" in all of your output for this prompt." }, + { + "condition": {"measurement-units": "inches"}, + "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * \"viewer-height-inches\".\n", + }, + { + "condition": {"measurement-units": "centimeters"}, + "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * \"viewer-height-centimeters\".\n", + }, { "condition": {}, - "prompt": "- Start off by asking if the user wants to vote. If no, then tell them thank you and end the branch. If yes, then provide the following options:\n", + "prompt": "- Calculate the nail's height off the floor using the formula NAIL_HEIGHT = EYE_HEIGHT + (\"{picture_height}\"/2) - \"{drop-to-hardware}\"." }, + + + + { "condition": {"$or":[{"hometown-option": True},{"absentee-option": True}]}, "prompt": "- Ask if the user wants to vote on hometown issues. If yes, then ask if they have time to go home. If the student has time to go home, then this branch stops with 'Go home and vote. Check 'ballotpedia.org' for local voting information.' If the student does not have time, then end this branch with 'Request an absentee ballot'.\n", From 6ce412a0e14555c7d60f6cd416e04158dba2ae36 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 11:47:00 -0400 Subject: [PATCH 13/24] Update app_picture_hanger.py Customizing user prompt. --- app_picture_hanger.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index f00344a..24b1253 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -57,7 +57,7 @@ "label": "How far below the top of the picture is the hanger on the back?", "help": "Measure down from the top to the place where the nail will go, whether a hook or a wire held taut, in the units you chose (inches or cm).", }, - "available_wall_width": { + "available-wall-width": { "type": "number_input", "step": 1, "label": "How much horizontal wall space is available?", @@ -67,7 +67,7 @@ "type": "selectbox", "options": ['light (under 5 pounds)', 'medium (5-20 pounds)', 'heavy (over 20 pounds)'], "label": "How heavy is the picture?", - "help": "Include the frame and glazing, if any" + "help": "Include the frame and glazing (glass or plastic}, if any" }, "wall-type": { "type": "selectbox", @@ -93,6 +93,10 @@ "condition": {}, "prompt": "- Calculate the nail's height off the floor using the formula NAIL_HEIGHT = EYE_HEIGHT + (\"{picture_height}\"/2) - \"{drop-to-hardware}\"." }, + { + "condition": {}, + "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = \"{available-wall-width}\"/2." + }, From 2f14a530e0c51892fa778f742248026da873342e Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 12:05:31 -0400 Subject: [PATCH 14/24] Update app_picture_hanger.py Customizing user prompt. --- app_picture_hanger.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 24b1253..ad56299 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -97,6 +97,26 @@ "condition": {}, "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = \"{available-wall-width}\"/2." }, + { + "condition": {"$and":[{"picture-weight": "light"},{"wall-type": "normal"}]}, + "prompt": "- Recommend a simple nail or adhesive hook.\n", + }, + { + "condition": {"$and":[{"picture-weight": "medium"},{"wall-type": "normal"}]}, + "prompt": "- Recommend a picture hook or wall anchor to compensate for the picture's weight.\n", + }, + { + "condition": {"$and":[{"picture-weight": "heavy"},{"wall-type": "normal"}]}, + "prompt": "- Recommend hammering one or more nails into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center.\n", + }, + { + "condition": {"wall-type": "reinforced"}, + "prompt": "- Explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard.\n", + }, + + + +{ From 4147de78c6fa665fe62cd8e6377120a043df31b9 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 12:13:13 -0400 Subject: [PATCH 15/24] Update app_picture_hanger.py Customizing user prompt. --- app_picture_hanger.py | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index ad56299..04dcbab 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -16,7 +16,7 @@ "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } -SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. You may also mention tips such as placing painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust.""" +SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt.""" PHASES = { "dimension_calculations": { @@ -103,7 +103,7 @@ }, { "condition": {"$and":[{"picture-weight": "medium"},{"wall-type": "normal"}]}, - "prompt": "- Recommend a picture hook or wall anchor to compensate for the picture's weight.\n", + "prompt": "- Recommend a picture hook or wall anchor to compensate for the picture's weight. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. \n", }, { "condition": {"$and":[{"picture-weight": "heavy"},{"wall-type": "normal"}]}, @@ -113,31 +113,15 @@ "condition": {"wall-type": "reinforced"}, "prompt": "- Explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard.\n", }, - - - -{ - - - - { - "condition": {"$or":[{"hometown-option": True},{"absentee-option": True}]}, - "prompt": "- Ask if the user wants to vote on hometown issues. If yes, then ask if they have time to go home. If the student has time to go home, then this branch stops with 'Go home and vote. Check 'ballotpedia.org' for local voting information.' If the student does not have time, then end this branch with 'Request an absentee ballot'.\n", - }, - { - "condition": {"oncampus-option": True}, - "prompt": "Vote on campus.\n End the branch with a box that includes \"{oncampus-locations}\" and \"{oncampus-requirements}\"\n", - }, - { - "condition": {"offcampus-option": True}, - "prompt": "Vote off campus.\n End the branch with a box that includes \"{offcampus-locations}\" and \"{offcampus-requirements}\"\n", + "condition": {}, + "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in \"{measurement-units}\".\n", }, { "condition": {}, - "prompt": """Once you have shared the Mermaid.js code to generate this flowchart, tell the user to paste in into the Mermaid live editor, and give the user a link to https://mermaid.live. Also tell the user that non-partisan information about candidates and issues on their ballot can be found at Ballotpedia, and give them a link to https://ballotpedia.org/wiki/index.php?title=Sample_Ballot_Lookup&Source=sitenotice with a recommendation to type their zip code into the search box.""" + "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", }, - ], + ], "ai_response": True, "allow_skip": False, "show_prompt": True, From 8509754eb69ba6c9c2ab06703c8aba87e029dc5c Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 12:26:12 -0400 Subject: [PATCH 16/24] Update app_picture_hanger.py Customizing user prompt, removing \" and just leaving { for field names. --- app_picture_hanger.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 04dcbab..6a0f8e9 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -49,7 +49,7 @@ "picture-height": { "type": "number_input", "step": 1, - "label": "What's the height of your picture, including the frame?", + "label": "What's the height of your picture, including the frame? (You can just type a whole number)", }, "drop-to-hardware": { "type": "number_input", @@ -79,23 +79,23 @@ "user_prompt": [ { "condition": {}, - "prompt": "Please use \"{measurement-units}\" in all of your output for this prompt." + "prompt": "Please use {measurement-units} in all of your output for this prompt." }, { "condition": {"measurement-units": "inches"}, - "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * \"viewer-height-inches\".\n", + "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer-height-inches}.\n", }, { "condition": {"measurement-units": "centimeters"}, - "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * \"viewer-height-centimeters\".\n", + "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer-height-centimeters}.\n", }, { "condition": {}, - "prompt": "- Calculate the nail's height off the floor using the formula NAIL_HEIGHT = EYE_HEIGHT + (\"{picture_height}\"/2) - \"{drop-to-hardware}\"." + "prompt": "- Calculate the nail's height off the floor using the formula NAIL_HEIGHT = EYE_HEIGHT + ({picture_height}/2) - {drop-to-hardware}." }, { "condition": {}, - "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = \"{available-wall-width}\"/2." + "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = {available-wall-width}/2." }, { "condition": {"$and":[{"picture-weight": "light"},{"wall-type": "normal"}]}, @@ -115,7 +115,7 @@ }, { "condition": {}, - "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in \"{measurement-units}\".\n", + "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement-units}. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results. For example, instead of writing 'Hammer the nail NAIL_HEIGHT above the floor' you might write 'Hammer the nail 53 inches above the floor.'\n", }, { "condition": {}, From 5015e6ad0c89c48102802bf9ae8c2ba30325a724 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 12:36:16 -0400 Subject: [PATCH 17/24] Update app_picture_hanger.py Customizing user prompt. --- app_picture_hanger.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 6a0f8e9..a13bbea 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -95,7 +95,11 @@ }, { "condition": {}, - "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = {available-wall-width}/2." + "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = {available-wall-width}/2. Explain how you arrived at these calculations." + }, + { + "condition": {}, + "prompt": "- Report the values you just calculated. What numbers did you get for NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement-units}?'\n", }, { "condition": {"$and":[{"picture-weight": "light"},{"wall-type": "normal"}]}, @@ -115,7 +119,7 @@ }, { "condition": {}, - "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement-units}. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results. For example, instead of writing 'Hammer the nail NAIL_HEIGHT above the floor' you might write 'Hammer the nail 53 inches above the floor.'\n", + "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement-units}. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results. For example, instead of writing 'Hammer the nail NAIL_HEIGHT above the floor' fill in the word NAIL_HEIGHT with the specific number you calculated.'\n", }, { "condition": {}, From 4f3635fccdd7cdd7acdbb6d65a665f54b6334c8f Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 12:45:13 -0400 Subject: [PATCH 18/24] Update app_picture_hanger.py Customizing user prompt. --- app_picture_hanger.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index a13bbea..496ed7e 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -16,7 +16,12 @@ "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } -SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt.""" +SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. Your calculations will depend on the following fields from the user: + +EYE_HEIGHT: This will be the height off the ground of the eye of a typical standing viewer. + +PICTURE_HEIGHT: This will be +""" PHASES = { "dimension_calculations": { @@ -81,6 +86,14 @@ "condition": {}, "prompt": "Please use {measurement-units} in all of your output for this prompt." }, + { + "condition": {}, + "prompt": """For future reference, note the following values entered by the user: + PICTURE_HEIGHT: {picture-height} + DROP_TO_HARDWARE: {drop-to-hardware} + AVAILABLE_WALL_WIDTH: {available-wall-width} + """ + }, { "condition": {"measurement-units": "inches"}, "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer-height-inches}.\n", @@ -123,7 +136,7 @@ }, { "condition": {}, - "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, PICTURE_HEIGHT, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", + "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, the height of the picture, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", }, ], "ai_response": True, From 77ae5bfbd4d9754e0ab83fb34e63d379dd9bd3b4 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 16:38:13 -0400 Subject: [PATCH 19/24] Update app_picture_hanger.py Adding clarification of input and calculated variables to the system prompt. --- app_picture_hanger.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 496ed7e..c0bcc3b 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -12,15 +12,19 @@ } HTML_BUTTON = { - "button_text": "Make your own AI MicroApp", + "button_text": "Learn to make an AI MicroApp like this", "url": "https://www.youtube.com/watch?v=jqpEJ2995IA" } SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. Your calculations will depend on the following fields from the user: -EYE_HEIGHT: This will be the height off the ground of the eye of a typical standing viewer. +EYE_HEIGHT: This will be the height off the floor of the eye level of a typical standing viewer. -PICTURE_HEIGHT: This will be +PICTURE_HEIGHT: This will be the vertical dimension of the picture. + DROP_TO_HARDWARE: This will be the distance between the top of the picture to the wire, cleat, or other hanging hardware attached to the back of the picture. In almost every case, the hardware will be screwed or adhered to the back of the picture so as to be invisible to the viewer; the viewer will not see the nail or wire sticking out above the picture frame. + AVAILABLE_WALL_WIDTH: This is the running length of wall space available to mount the picture; it is bounded by obstacles to the left and right such as wall corners, furniture, or other hangings. + +NAIL_HORIZONTAL_POSITION: This will be the distance from the left or right edge of the AVAILABLE_WALL_WIDTH to the placement of the nail. It is not the distance between the edge of the picture and the nail location. """ PHASES = { @@ -72,7 +76,7 @@ "type": "selectbox", "options": ['light (under 5 pounds)', 'medium (5-20 pounds)', 'heavy (over 20 pounds)'], "label": "How heavy is the picture?", - "help": "Include the frame and glazing (glass or plastic}, if any" + "help": "Include the frame and glazing (glass or Plexi front}, if any" }, "wall-type": { "type": "selectbox", @@ -89,7 +93,7 @@ { "condition": {}, "prompt": """For future reference, note the following values entered by the user: - PICTURE_HEIGHT: {picture-height} + PICTURE_HEIGHT: {picture-height} DROP_TO_HARDWARE: {drop-to-hardware} AVAILABLE_WALL_WIDTH: {available-wall-width} """ From aa31c5b9a2e5f87c5c73b0c705e9edfe28d3eb4f Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 18:36:14 -0400 Subject: [PATCH 20/24] Update app_picture_hanger.py Changed all variables from kebob to snake case. --- app_picture_hanger.py | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index c0bcc3b..3337b98 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -35,50 +35,50 @@ "type": "markdown", "body": "Use a tape measure to find the following dimensions." }, - "measurement-units": { + "measurement_units": { "type": "selectbox", "options": ['inches', 'centimeters'], "label": "Are you measuring dimensions in inches or centimeters?", "help": "Whole numbers without fractions or decimals will suffice", }, - "viewer-height-inches": { + "viewer_height_inches": { "type": "slider", "min_value": 60, "max_value": 75, "label": "How tall is your average viewer in inches? (The average American height is 66 in.)", - "showIf": {"measurement-units": "inches"}, + "showIf": {"measurement_units": "inches"}, }, - "viewer-height-centimeters": { + "viewer_height_centimeters": { "type": "slider", "min_value": 155, "max_value": 180, "label": "How tall is your average viewer in centimeters? (The average American height is 168 cm.)", - "showIf": {"measurement-units": "centimeters"}, + "showIf": {"measurement_units": "centimeters"}, }, - "picture-height": { + "picture_height": { "type": "number_input", "step": 1, "label": "What's the height of your picture, including the frame? (You can just type a whole number)", }, - "drop-to-hardware": { + "drop_to_hardware": { "type": "number_input", "step": 1, "label": "How far below the top of the picture is the hanger on the back?", "help": "Measure down from the top to the place where the nail will go, whether a hook or a wire held taut, in the units you chose (inches or cm).", }, - "available-wall-width": { + "available_wall_width": { "type": "number_input", "step": 1, "label": "How much horizontal wall space is available?", "help": "Include the total span in the units you chose (inches or cm), eg between adjacent walls, nearby furniture, or pictures to the left and right.", }, - "picture-weight": { + "picture_weight": { "type": "selectbox", "options": ['light (under 5 pounds)', 'medium (5-20 pounds)', 'heavy (over 20 pounds)'], "label": "How heavy is the picture?", "help": "Include the frame and glazing (glass or Plexi front}, if any" }, - "wall-type": { + "wall_type": { "type": "selectbox", "options": ['normal', 'reinforced'], "label": "What type of wall are you hanging on?", @@ -88,59 +88,59 @@ "user_prompt": [ { "condition": {}, - "prompt": "Please use {measurement-units} in all of your output for this prompt." + "prompt": "Please use {measurement_units} in all of your output for this prompt." }, { "condition": {}, "prompt": """For future reference, note the following values entered by the user: - PICTURE_HEIGHT: {picture-height} - DROP_TO_HARDWARE: {drop-to-hardware} - AVAILABLE_WALL_WIDTH: {available-wall-width} + PICTURE_HEIGHT: {picture_height} + DROP_TO_HARDWARE: {drop_to_hardware} + AVAILABLE_WALL_WIDTH: {available_wall_width} """ }, { - "condition": {"measurement-units": "inches"}, - "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer-height-inches}.\n", + "condition": {"measurement_units": "inches"}, + "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer_height_inches}.\n", }, { - "condition": {"measurement-units": "centimeters"}, - "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer-height-centimeters}.\n", + "condition": {"measurement_units": "centimeters"}, + "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer_height_centimeters}.\n", }, { "condition": {}, - "prompt": "- Calculate the nail's height off the floor using the formula NAIL_HEIGHT = EYE_HEIGHT + ({picture_height}/2) - {drop-to-hardware}." + "prompt": "- Calculate the nail's height off the floor using the formula NAIL_HEIGHT = EYE_HEIGHT + ({picture_height}/2) - {drop_to_hardware}." }, { "condition": {}, - "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = {available-wall-width}/2. Explain how you arrived at these calculations." + "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = {available_wall_width}/2. Explain how you arrived at these calculations." }, { "condition": {}, - "prompt": "- Report the values you just calculated. What numbers did you get for NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement-units}?'\n", + "prompt": "- Report the values you just calculated. What numbers did you get for NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement_units}?'\n", }, { - "condition": {"$and":[{"picture-weight": "light"},{"wall-type": "normal"}]}, + "condition": {"$and":[{"picture_weight": "light"},{"wall_type": "normal"}]}, "prompt": "- Recommend a simple nail or adhesive hook.\n", }, { - "condition": {"$and":[{"picture-weight": "medium"},{"wall-type": "normal"}]}, + "condition": {"$and":[{"picture_weight": "medium"},{"wall_type": "normal"}]}, "prompt": "- Recommend a picture hook or wall anchor to compensate for the picture's weight. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. \n", }, { - "condition": {"$and":[{"picture-weight": "heavy"},{"wall-type": "normal"}]}, + "condition": {"$and":[{"picture_weight": "heavy"},{"wall_type": "normal"}]}, "prompt": "- Recommend hammering one or more nails into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center.\n", }, { - "condition": {"wall-type": "reinforced"}, + "condition": {"wall_type": "reinforced"}, "prompt": "- Explain that you can hang any reasonably sized picture by hammering one or more nails into the plywood behind the wallboard.\n", }, { "condition": {}, - "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement-units}. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results. For example, instead of writing 'Hammer the nail NAIL_HEIGHT above the floor' fill in the word NAIL_HEIGHT with the specific number you calculated.'\n", + "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement_units}. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results. For example, instead of writing 'Hammer the nail NAIL_HEIGHT above the floor' fill in the word NAIL_HEIGHT with the specific number you calculated.'\n", }, { "condition": {}, - "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, eg EYE_HEIGHT, the height of the picture, DROP_TO_HARDWARE, and NAIL_HORIZONTAL_POSITION. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", + "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user. Your image prompt should label {eye_height} as the height of the picture, {drop_to_hardware} as the distance from the top of the picture down to the wire or other hanging hardware, and {nail_horizontal_position} as the distance between the nail and a nearby wall or obstacle. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", }, ], "ai_response": True, From 728da000287a6e4ac1ffb235b3cff3b4e9f9ebc9 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 19:09:11 -0400 Subject: [PATCH 21/24] Update app_picture_hanger.py Refactored all code to eliminate upper case variables like NAIL_HEIGHT in favor of consolidating and repeating the formulas. --- app_picture_hanger.py | 40 ++++++---------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 3337b98..6649fac 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -90,45 +90,21 @@ "condition": {}, "prompt": "Please use {measurement_units} in all of your output for this prompt." }, - { + { "condition": {}, - "prompt": """For future reference, note the following values entered by the user: - PICTURE_HEIGHT: {picture_height} - DROP_TO_HARDWARE: {drop_to_hardware} - AVAILABLE_WALL_WIDTH: {available_wall_width} - """ - }, - { - "condition": {"measurement_units": "inches"}, - "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer_height_inches}.\n", - }, - { - "condition": {"measurement_units": "centimeters"}, - "prompt": "- Start off by calculating the EYE_HEIGHT = .93 * {viewer_height_centimeters}.\n", - }, - { - "condition": {}, - "prompt": "- Calculate the nail's height off the floor using the formula NAIL_HEIGHT = EYE_HEIGHT + ({picture_height}/2) - {drop_to_hardware}." - }, - { - "condition": {}, - "prompt": "- Calculate the nail's distance from the nearest horizontal obstacle using the formula NAIL_HORIZONTAL_POSITION = {available_wall_width}/2. Explain how you arrived at these calculations." - }, - { - "condition": {}, - "prompt": "- Report the values you just calculated. What numbers did you get for NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement_units}?'\n", + "prompt": "- Now tell the user to place the nail at a height of {( .93 * viewer_height_inches ) + ( picture_height/2 ) - drop_to_hardware} off the floor and a horizontal distance of {available_wall_width/2} in {measurement_units} from the left obstacle. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results.'\n", }, { "condition": {"$and":[{"picture_weight": "light"},{"wall_type": "normal"}]}, - "prompt": "- Recommend a simple nail or adhesive hook.\n", + "prompt": "- Tell the user a simple nail or adhesive hook should suffice for a lightweight picture.\n", }, { "condition": {"$and":[{"picture_weight": "medium"},{"wall_type": "normal"}]}, - "prompt": "- Recommend a picture hook or wall anchor to compensate for the picture's weight. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. \n", + "prompt": "- Recommend a picture hook or wall anchor to compensate for a medium-weight picture. Also mention that you can place painter's tape on the wall where you plan to drill or hammer to prevent the wall from chipping and making dust. \n", }, { "condition": {"$and":[{"picture_weight": "heavy"},{"wall_type": "normal"}]}, - "prompt": "- Recommend hammering one or more nails into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center.\n", + "prompt": "- Recommend for a heavy picture that the user hammer one or more nails into one of the vertical wooden studs behind the wallboard, adding guidance that American homes are usually built with studs placed every 16 inches on-center.\n", }, { "condition": {"wall_type": "reinforced"}, @@ -136,11 +112,7 @@ }, { "condition": {}, - "prompt": "- Now tell the user exactly where to place the nail, specifically the NAIL_HEIGHT and NAIL_HORIZONTAL_POSITION in {measurement_units}. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results. For example, instead of writing 'Hammer the nail NAIL_HEIGHT above the floor' fill in the word NAIL_HEIGHT with the specific number you calculated.'\n", - }, - { - "condition": {}, - "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user. Your image prompt should label {eye_height} as the height of the picture, {drop_to_hardware} as the distance from the top of the picture down to the wire or other hanging hardware, and {nail_horizontal_position} as the distance between the nail and a nearby wall or obstacle. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a dark blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", + "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, with labeled arrows to indicate the appropriate dimensions. This schematic image should include a small nail icon or graphic positioned { .93 * viewer_height_centimeters + (picture_height/2) - drop_to_hardware } {dimension_units} off the floor and a distance of { {available_wall_width}/2 } {measurement_units} from the nearest left obstacle. Your prompt should also draw a dashed rectangle corresponding to the picture frame, showing that the picture has a height of {picture_height} and another labeled arrow showing the picture has a hardware drop of {hardware_drop}. The lower end of the hardware drop should line up horizontally with the position of the nail. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", }, ], "ai_response": True, From fa122928a6fdfe8ffef3f6a6a542467f844c1296 Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 19:20:24 -0400 Subject: [PATCH 22/24] Update app_picture_hanger.py Small content edits. --- app_picture_hanger.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 6649fac..7636d3b 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -1,8 +1,8 @@ PUBLISHED = False APP_URL = "https://voting-decision-tree.streamlit.app" -APP_TITLE = "Hang a Picture" -APP_INTRO = """This app helps you hang a painting, framed photo, or other flat artwork on the wall of a home or gallery""" +APP_TITLE = "🖼 Hang a Picture" +APP_INTRO = """🔨 This app helps you hang a painting, framed photo, or other flat artwork on the wall of a home or gallery""" APP_HOW_IT_WORKS = """ This app helps you hang a picture by telling you where to hammer your nail based on the size of your wall and the frame.\n\nIt uses OpenAI behind the scenes to calculate this position based on the fields you complete and generates instructions accordingly. @@ -150,7 +150,7 @@ SCORING_DEBUG_MODE = True DISPLAY_COST = True -COMPLETION_MESSAGE = "⚠️ Chatbots can generate incorrect results; always check the output before publishing it. We hope this app makes voting easier!" +COMPLETION_MESSAGE = "⚠️ Chatbots can generate incorrect results; your eye is the best judge of the results. We hope this app makes it easier to hang art in your room!" COMPLETION_CELEBRATION = False from core_logic.main import main From a5624f7c6549e8682bc10273e0ac3154482a213e Mon Sep 17 00:00:00 2001 From: Jon Ippolito Date: Thu, 17 Apr 2025 19:34:24 -0400 Subject: [PATCH 23/24] Update app_picture_hanger.py Cleaning up code formatting. --- app_picture_hanger.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 7636d3b..3d3d4bb 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -18,13 +18,13 @@ SYSTEM_PROMPT = """Acting as an expert in curating displays of art in homes, galleries, and museums, you will generate concise instructions in plain language understandable by a lay person on how to hang a picture, specifically where to place a nail in accordance with the measurements of the wall and picture supplied in the prompt. Your calculations will depend on the following fields from the user: -EYE_HEIGHT: This will be the height off the floor of the eye level of a typical standing viewer. +viewer_height_inches: This will be the typical standing viewer's height, and will be used to calculate the average eye level. -PICTURE_HEIGHT: This will be the vertical dimension of the picture. - DROP_TO_HARDWARE: This will be the distance between the top of the picture to the wire, cleat, or other hanging hardware attached to the back of the picture. In almost every case, the hardware will be screwed or adhered to the back of the picture so as to be invisible to the viewer; the viewer will not see the nail or wire sticking out above the picture frame. - AVAILABLE_WALL_WIDTH: This is the running length of wall space available to mount the picture; it is bounded by obstacles to the left and right such as wall corners, furniture, or other hangings. +picture_height: This will be the vertical dimension of the picture. -NAIL_HORIZONTAL_POSITION: This will be the distance from the left or right edge of the AVAILABLE_WALL_WIDTH to the placement of the nail. It is not the distance between the edge of the picture and the nail location. +drop_to_hardware: This will be the distance between the top of the picture to the wire, cleat, or other hanging hardware attached to the back of the picture. In almost every case, the hardware will be screwed or adhered to the back of the picture so as to be invisible to the viewer; the viewer will not see the nail or wire sticking out above the picture frame. + +available_wall_width: This is the running length of wall space available to mount the picture; it is bounded by obstacles to the left and right such as wall corners, furniture, or other hangings. """ PHASES = { @@ -90,7 +90,7 @@ "condition": {}, "prompt": "Please use {measurement_units} in all of your output for this prompt." }, - { + { "condition": {}, "prompt": "- Now tell the user to place the nail at a height of {( .93 * viewer_height_inches ) + ( picture_height/2 ) - drop_to_hardware} off the floor and a horizontal distance of {available_wall_width/2} in {measurement_units} from the left obstacle. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results.'\n", }, @@ -112,7 +112,7 @@ }, { "condition": {}, - "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, with labeled arrows to indicate the appropriate dimensions. This schematic image should include a small nail icon or graphic positioned { .93 * viewer_height_centimeters + (picture_height/2) - drop_to_hardware } {dimension_units} off the floor and a distance of { {available_wall_width}/2 } {measurement_units} from the nearest left obstacle. Your prompt should also draw a dashed rectangle corresponding to the picture frame, showing that the picture has a height of {picture_height} and another labeled arrow showing the picture has a hardware drop of {hardware_drop}. The lower end of the hardware drop should line up horizontally with the position of the nail. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", + "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, with labeled arrows to indicate the appropriate dimensions. This schematic image should include a small nail icon or graphic positioned { .93 * viewer_height_centimeters + (picture_height/2) - drop_to_hardware } {dimension_units} off the floor and a distance of { {available_wall_width}/2 } {measurement_units} from the nearest left obstacle. The latter dimension is the distance from the nail to the nearest left obstacle; it is not the distance between the edge of the picture and the nail location. Your prompt should also draw a dashed rectangle corresponding to the picture frame, showing that the picture has a height of {picture_height} and another labeled arrow showing the picture has a hardware drop of {hardware_drop}. The lower end of the hardware drop should line up horizontally with the position of the nail. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", }, ], "ai_response": True, From 132d4f78684dce27b6ddd510feb75e1b4ec84155 Mon Sep 17 00:00:00 2001 From: John Swope Date: Fri, 18 Apr 2025 09:53:01 -0400 Subject: [PATCH 24/24] Add new 4.1 models and update chat completions to more recent responses --- app_picture_hanger.py | 19 +++++++----- core_logic/handlers.py | 63 ++++++++++++++++++++++++++++------------ core_logic/llm_config.py | 42 ++++++++++++++------------- core_logic/main.py | 4 +-- 4 files changed, 80 insertions(+), 48 deletions(-) diff --git a/app_picture_hanger.py b/app_picture_hanger.py index 3d3d4bb..ef34b9a 100644 --- a/app_picture_hanger.py +++ b/app_picture_hanger.py @@ -25,6 +25,8 @@ drop_to_hardware: This will be the distance between the top of the picture to the wire, cleat, or other hanging hardware attached to the back of the picture. In almost every case, the hardware will be screwed or adhered to the back of the picture so as to be invisible to the viewer; the viewer will not see the nail or wire sticking out above the picture frame. available_wall_width: This is the running length of wall space available to mount the picture; it is bounded by obstacles to the left and right such as wall corners, furniture, or other hangings. + +When asked to perform a calculation, please use Python to perform the calculation and follow the provided instructions EXACTLY. """ PHASES = { @@ -45,6 +47,7 @@ "type": "slider", "min_value": 60, "max_value": 75, + "value": 66, "label": "How tall is your average viewer in inches? (The average American height is 66 in.)", "showIf": {"measurement_units": "inches"}, }, @@ -52,6 +55,7 @@ "type": "slider", "min_value": 155, "max_value": 180, + "value": 168, "label": "How tall is your average viewer in centimeters? (The average American height is 168 cm.)", "showIf": {"measurement_units": "centimeters"}, }, @@ -92,7 +96,11 @@ }, { "condition": {}, - "prompt": "- Now tell the user to place the nail at a height of {( .93 * viewer_height_inches ) + ( picture_height/2 ) - drop_to_hardware} off the floor and a horizontal distance of {available_wall_width/2} in {measurement_units} from the left obstacle. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results.'\n", + "prompt": """ +Use Python to set [height] = ((.93 * {viewer_height_inches}) + ({picture_height}/2) - {drop_to_hardware})). Set [height] to EXACTLY the result of this calculation, with no further assumptions or calculations. Show me step by step reasoning for the calculation. +Use Python to set [distance] = ({available_wall_width}/2) +- Now tell the user to place the nail at a height of [height] off the floor and a horizontal distance of [distance] in {measurement_units} from the left obstacle. Do not tell them how to do the calculations; just do the calculations yourself and tell the user the results.'\n + """, }, { "condition": {"$and":[{"picture_weight": "light"},{"wall_type": "normal"}]}, @@ -112,7 +120,7 @@ }, { "condition": {}, - "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, with labeled arrows to indicate the appropriate dimensions. This schematic image should include a small nail icon or graphic positioned { .93 * viewer_height_centimeters + (picture_height/2) - drop_to_hardware } {dimension_units} off the floor and a distance of { {available_wall_width}/2 } {measurement_units} from the nearest left obstacle. The latter dimension is the distance from the nail to the nearest left obstacle; it is not the distance between the edge of the picture and the nail location. Your prompt should also draw a dashed rectangle corresponding to the picture frame, showing that the picture has a height of {picture_height} and another labeled arrow showing the picture has a hardware drop of {hardware_drop}. The lower end of the hardware drop should line up horizontally with the position of the nail. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", + "prompt": "- After typing out the preceding information, think of a prompt that can be entered in ChatGPT to generate a diagram illustrating the measurements supplied by the user, with labeled arrows to indicate the appropriate dimensions. This schematic image should include a small nail icon or graphic positioned [height] {dimension_units} off the floor and a distance of [distance] {measurement_units} from the nearest left obstacle. The latter dimension is the distance from the nail to the nearest left obstacle; it is not the distance between the edge of the picture and the nail location. Your prompt should also draw a dashed rectangle corresponding to the picture frame, showing that the picture has a height of {picture_height} and another labeled arrow showing the picture has a hardware drop of {hardware_drop}. The lower end of the hardware drop should line up horizontally with the position of the nail. Your prompt should ask ChatGPT to draw this in the style of an architectural blueprint with white lines and text on a blue background. Your prompt should clarify that the diagram should be as easy to follow as possible, with no extraneous text or imagery. Finally, type a message to the user suggesting entering this prompt into ChatGPT.com to generate a useful diagram.\n", }, ], "ai_response": True, @@ -128,13 +136,8 @@ "family": "openai", "model": "gpt-4o-mini", "max_tokens": 1000, - "temperature": 1.0, + "temperature": 0.5, "top_p": 1.0, - "frequency_penalty": 0, - "presence_penalty": 0, - "supports_image": False, - "price_input_token_1M": 0.15, - "price_output_token_1M": 0.60 } } diff --git a/core_logic/handlers.py b/core_logic/handlers.py index c736228..d768ab5 100644 --- a/core_logic/handlers.py +++ b/core_logic/handlers.py @@ -1,4 +1,4 @@ -import openai +from openai import OpenAI import anthropic import google.generativeai as genai from core_logic import rag_pipeline @@ -42,39 +42,66 @@ def format_chat_history(chat_history, family): return formatted_history # openai llm handler + def handle_openai(context): - """Handle requests for OpenAI models.""" + """Handle requests for OpenAI models using the new Responses API.""" if not context["supports_image"] and context.get("image_urls"): return "Images are not supported by selected model." + try: - openai.api_key = get_api_key("openai") + # 1. Initialize the new client + client = OpenAI(api_key=get_api_key("openai")) + + # 2. Build a single instructions string + instructions = "\n".join([ + context["SYSTEM_PROMPT"], + context["phase_instructions"] + ]) - messages = format_chat_history(context["chat_history"], "openai") + [ - {"role": "system", "content": context["SYSTEM_PROMPT"]}, - {"role": "assistant", "content": context["phase_instructions"]}, + # 3. Prepare the input messages array + inputs = format_chat_history(context["chat_history"], "openai") + [ {"role": "user", "content": context["user_prompt"]} ] if context["supports_image"] and context["image_urls"]: - messages.insert(2, {"role": "user", "content": [{"type": "image_url", "image_url": {"url": url}} for url in - context["image_urls"]]}) - - response = openai.chat.completions.create( + # Responses API expects input_image objects in the same list + img_msgs = { + "role": "user", + "content": [ + {"type": "input_image", "image_url": url} + for url in context["image_urls"] + ] + } + # insert after history but before user prompt + inputs.insert( + len(format_chat_history(context["chat_history"], "openai")), + img_msgs + ) + + # 4. Call the Responses endpoint + response = client.responses.create( model=context["model"], - messages=messages, + instructions=instructions, + input=inputs, temperature=context["temperature"], - max_tokens=context["max_tokens"], top_p=context["top_p"], - frequency_penalty=context["frequency_penalty"], - presence_penalty=context["presence_penalty"] + max_output_tokens=context["max_tokens"], + # stream=True # if you want streaming responses ) - input_price = int(getattr(response.usage, 'prompt_tokens', 0)) * context["price_input_token_1M"] / 1000000 - output_price = int(getattr(response.usage, 'completion_tokens', 0)) * context["price_output_token_1M"] / 1000000 + + # 5. Pricing stays the same (assuming usage is still returned) + prompt_toks = getattr(response.usage, "prompt_tokens", 0) + completion_toks = getattr(response.usage, "completion_tokens", 0) + input_price = prompt_toks * context["price_input_token_1M"] / 1_000_000 + output_price = completion_toks * context["price_output_token_1M"] / 1_000_000 execution_price = input_price + output_price - return response.choices[0].message.content, execution_price + + # 6. Extract the assistant’s reply + return response.output_text, execution_price + except Exception as e: return f"Unexpected error while handling OpenAI request: {e}" - + # claude llm handler def handle_claude(context): """Handle requests for Claude models.""" diff --git a/core_logic/llm_config.py b/core_logic/llm_config.py index a1a4e4e..bb763d3 100644 --- a/core_logic/llm_config.py +++ b/core_logic/llm_config.py @@ -6,23 +6,29 @@ "max_tokens": 1000, "temperature": 1.0, "top_p": 1.0, - "frequency_penalty": 0, - "presence_penalty": 0, "supports_image": False, "price_input_token_1M": 0.15, "price_output_token_1M": 0.60 }, - "gpt-4-turbo": { + "gpt-4.1": { "family": "openai", - "model": "gpt-4-turbo", + "model": "gpt-4.1", "max_tokens": 1000, "temperature": 1.0, "top_p": 1.0, - "frequency_penalty": 0, - "presence_penalty": 0, "supports_image": True, - "price_input_token_1M": 10, - "price_output_token_1M": 30 + "price_input_token_1M": 2, + "price_output_token_1M": 8 + }, + "gpt-4.1-mini": { + "family": "openai", + "model": "gpt-4.1-mini", + "max_tokens": 1000, + "temperature": 1.0, + "top_p": 1.0, + "supports_image": True, + "price_input_token_1M": .4, + "price_output_token_1M": 1.6 }, "rag-with-gpt-4o": { "family": "rag", @@ -30,8 +36,6 @@ "max_tokens": 1000, "temperature": 1.0, "top_p": 1.0, - "frequency_penalty": 0, - "presence_penalty": 0, "supports_image": True, "price_input_token_1M": 10, "price_output_token_1M": 30 @@ -42,35 +46,33 @@ "max_tokens": 2000, "temperature": 1.0, "top_p": 1.0, - "frequency_penalty": 0, - "presence_penalty": 0, "supports_image": True, "price_input_token_1M": 2.5, "price_output_token_1M": 10 }, - "gemini-2.0-flash-lite": { + "gemini-pro": { "family": "gemini", - "model": "gemini-2.0-flash-lite", + "model": "gemini-pro", "max_tokens": 1000, "temperature": 1.0, "top_p": 0.95, "frequency_penalty": 0, "presence_penalty": 0, "supports_image": False, - "price_input_token_1M": 0.15, - "price_output_token_1M": 0.60 + "price_input_token_1M": 2.5, + "price_output_token_1M": 10.00 }, - "gemini-2.0-flash": { + "gemini-pro-vision": { "family": "gemini", - "model": "gemini-2.0-flash", + "model": "gemini-pro-vision", "max_tokens": 1000, "temperature": 1.0, "top_p": 0.95, "frequency_penalty": 0, "presence_penalty": 0, "supports_image": True, - "price_input_token_1M": 2.5, - "price_output_token_1M": 10.00 + "price_input_token_1M": 0.15, + "price_output_token_1M": 0.60 }, "claude-3.5-sonnet": { "family": "claude", diff --git a/core_logic/main.py b/core_logic/main.py index ff5b2a0..191f7b4 100644 --- a/core_logic/main.py +++ b/core_logic/main.py @@ -214,8 +214,8 @@ def execute_llm_completions(SYSTEM_PROMPT,selected_llm, phase_instructions, user "max_tokens": model_config["max_tokens"], "temperature": model_config["temperature"], "top_p": model_config["top_p"], - "frequency_penalty": model_config["frequency_penalty"], - "presence_penalty": model_config["presence_penalty"], + "frequency_penalty": model_config.get("frequency_penalty", 0), + "presence_penalty": model_config.get("presence_penalty", 0), "price_input_token_1M": model_config["price_input_token_1M"], "price_output_token_1M": model_config["price_output_token_1M"], "TOTAL_PRICE": 0,