From 21648d6ecec6c0d04fed74184ac12d26e253f8d5 Mon Sep 17 00:00:00 2001 From: BaimoQilin Date: Sat, 22 Jun 2024 21:47:03 +0800 Subject: [PATCH] feat: Save more tokens by adding fill placing type --- block_id_list.txt | 250 ++++++++++++++++++++++++ browser.py | 11 +- config.yaml | 485 +--------------------------------------------- core.py | 19 +- ui.py | 24 ++- 5 files changed, 301 insertions(+), 488 deletions(-) create mode 100644 block_id_list.txt diff --git a/block_id_list.txt b/block_id_list.txt new file mode 100644 index 0000000..9558a28 --- /dev/null +++ b/block_id_list.txt @@ -0,0 +1,250 @@ +minecraft:air +minecraft:stone +minecraft:granite +minecraft:polished_granite +minecraft:diorite +minecraft:polished_diorite +minecraft:andesite +minecraft:polished_andesite +minecraft:grass_block +minecraft:dirt +minecraft:coarse_dirt +minecraft:podzol +minecraft:cobblestone +minecraft:oak_planks +minecraft:spruce_planks +minecraft:birch_planks +minecraft:jungle_planks +minecraft:acacia_planks +minecraft:dark_oak_planks +minecraft:mangrove_planks +minecraft:crimson_planks +minecraft:warped_planks +minecraft:bamboo_planks +minecraft:oak_sapling +minecraft:spruce_sapling +minecraft:birch_sapling +minecraft:jungle_sapling +minecraft:acacia_sapling +minecraft:dark_oak_sapling +minecraft:mangrove_propagule +minecraft:bedrock +minecraft:sand +minecraft:red_sand +minecraft:gravel +minecraft:gold_ore +minecraft:deepslate_gold_ore +minecraft:iron_ore +minecraft:deepslate_iron_ore +minecraft:coal_ore +minecraft:deepslate_coal_ore +minecraft:nether_gold_ore +minecraft:oak_log +minecraft:spruce_log +minecraft:birch_log +minecraft:jungle_log +minecraft:acacia_log +minecraft:dark_oak_log +minecraft:mangrove_log +minecraft:crimson_stem +minecraft:warped_stem +minecraft:bamboo_block +minecraft:oak_leaves +minecraft:spruce_leaves +minecraft:birch_leaves +minecraft:jungle_leaves +minecraft:acacia_leaves +minecraft:dark_oak_leaves +minecraft:mangrove_leaves +minecraft:azalea_leaves +minecraft:flowering_azalea_leaves +minecraft:sponge +minecraft:wet_sponge +minecraft:glass +minecraft:tinted_glass +minecraft:lapis_ore +minecraft:deepslate_lapis_ore +minecraft:lapis_block +minecraft:dispenser +minecraft:sandstone +minecraft:chiseled_sandstone +minecraft:cut_sandstone +minecraft:note_block +minecraft:white_bed +minecraft:orange_bed +minecraft:magenta_bed +minecraft:light_blue_bed +minecraft:yellow_bed +minecraft:lime_bed +minecraft:pink_bed +minecraft:gray_bed +minecraft:light_gray_bed +minecraft:cyan_bed +minecraft:purple_bed +minecraft:blue_bed +minecraft:brown_bed +minecraft:green_bed +minecraft:red_bed +minecraft:black_bed +minecraft:powered_rail +minecraft:detector_rail +minecraft:sticky_piston +minecraft:cobweb +minecraft:grass +minecraft:fern +minecraft:dead_bush +minecraft:seagrass +minecraft:tall_seagrass +minecraft:sea_pickle +minecraft:piston +minecraft:white_wool +minecraft:orange_wool +minecraft:magenta_wool +minecraft:light_blue_wool +minecraft:yellow_wool +minecraft:lime_wool +minecraft:pink_wool +minecraft:gray_wool +minecraft:light_gray_wool +minecraft:cyan_wool +minecraft:purple_wool +minecraft:blue_wool +minecraft:brown_wool +minecraft:green_wool +minecraft:red_wool +minecraft:black_wool +minecraft:moving_piston +minecraft:dandelion +minecraft:poppy +minecraft:blue_orchid +minecraft:allium +minecraft:azure_bluet +minecraft:red_tulip +minecraft:orange_tulip +minecraft:white_tulip +minecraft:pink_tulip +minecraft:oxeye_daisy +minecraft:cornflower +minecraft:lily_of_the_valley +minecraft:wither_rose +minecraft:spore_blossom +minecraft:brown_mushroom +minecraft:red_mushroom +minecraft:crimson_fungus +minecraft:warped_fungus +minecraft:crimson_roots +minecraft:warped_roots +minecraft:nether_sprouts +minecraft:weeping_vines +minecraft:twisting_vines +minecraft:sugar_cane +minecraft:kelp +minecraft:moss_carpet +minecraft:moss_block +minecraft:flowering_azalea +minecraft:azalea +minecraft:hay_block +minecraft:terracotta +minecraft:white_terracotta +minecraft:orange_terracotta +minecraft:magenta_terracotta +minecraft:light_blue_terracotta +minecraft:yellow_terracotta +minecraft:lime_terracotta +minecraft:pink_terracotta +minecraft:gray_terracotta +minecraft:light_gray_terracotta +minecraft:cyan_terracotta +minecraft:purple_terracotta +minecraft:blue_terracotta +minecraft:brown_terracotta +minecraft:green_terracotta +minecraft:red_terracotta +minecraft:black_terracotta +minecraft:barrel +minecraft:smoker +minecraft:blast_furnace +minecraft:cartography_table +minecraft:fletching_table +minecraft:grindstone +minecraft:lectern +minecraft:loom +minecraft:smithing_table +minecraft:stonecutter +minecraft:bell +minecraft:lantern +minecraft:soul_lantern +minecraft:campfire +minecraft:soul_campfire +minecraft:shroomlight +minecraft:bee_nest +minecraft:beehive +minecraft:honey_block +minecraft:honeycomb_block +minecraft:lodestone +minecraft:crying_obsidian +minecraft:respawn_anchor +minecraft:ancient_debris +minecraft:netherite_block +minecraft:blackstone +minecraft:blackstone_slab +minecraft:blackstone_stairs +minecraft:gilded_blackstone +minecraft:polished_blackstone +minecraft:polished_blackstone_slab +minecraft:polished_blackstone_stairs +minecraft:chiseled_polished_blackstone +minecraft:polished_blackstone_bricks +minecraft:polished_blackstone_brick_slab +minecraft:polished_blackstone_brick_stairs +minecraft:cracked_polished_blackstone_bricks +minecraft:respawn_anchor +minecraft:crying_obsidian +minecraft:ancient_debris +minecraft:netherite_block +minecraft:blackstone +minecraft:blackstone_slab +minecraft:blackstone_stairs +minecraft:gilded_blackstone +minecraft:polished_blackstone +minecraft:polished_blackstone_slab +minecraft:polished_blackstone_stairs +minecraft:chiseled_polished_blackstone +minecraft:polished_blackstone_bricks +minecraft:polished_blackstone_brick_slab +minecraft:polished_blackstone_brick_stairs +minecraft:cracked_polished_blackstone_bricks +minecraft:soul_soil +minecraft:budding_amethyst +minecraft:amethyst_block +minecraft:amethyst_cluster +minecraft:small_amethyst_bud +minecraft:medium_amethyst_bud +minecraft:large_amethyst_bud +minecraft:calcite +minecraft:tuff +minecraft:deepslate +minecraft:cobbled_deepslate +minecraft:polished_deepslate +minecraft:deepslate_bricks +minecraft:cracked_deepslate_bricks +minecraft:deepslate_tiles +minecraft:cracked_deepslate_tiles +minecraft:chiseled_deepslate +minecraft:infested_deepslate +minecraft:cobbled_deepslate_stairs +minecraft:cobbled_deepslate_slab +minecraft:cobbled_deepslate_wall +minecraft:polished_deepslate_stairs +minecraft:polished_deepslate_slab +minecraft:polished_deepslate_wall +minecraft:deepslate_brick_stairs +minecraft:deepslate_brick_slab +minecraft:deepslate_brick_wall +minecraft:deepslate_tile_stairs +minecraft:deepslate_tile_slab +minecraft:deepslate_tile_wall +minecraft:chiseled_bookshelf +minecraft:bamboo_mosaic +minecraft:bamboo_mosaic_slab +minecraft:bamboo_mosaic_stairs \ No newline at end of file diff --git a/browser.py b/browser.py index 6077903..d05902d 100644 --- a/browser.py +++ b/browser.py @@ -3,12 +3,12 @@ from playwright.sync_api import Playwright, sync_playwright, expect -def run(playwright: Playwright, progress_bar: str=None) -> None: +def run(playwright: Playwright, progress_bar: str=None, is_headless: bool=True) -> None: def set_progress(progress): if progress_bar is not None: progress_bar.set(progress) - browser = playwright.chromium.launch(headless=True) + browser = playwright.chromium.launch(headless=is_headless) set_progress(25) @@ -46,10 +46,11 @@ def set_progress(progress): download = download_info.value download.save_as("temp/screenshot.png") - page.close() - context.close() - browser.close() + if is_headless: + page.close() + context.close() + browser.close() set_progress(90) diff --git a/config.yaml b/config.yaml index fb8ff9a..a723180 100644 --- a/config.yaml +++ b/config.yaml @@ -13,7 +13,7 @@ GENERATE_MODEL: "gpt-4-turbo" # Don't use gpt-4, because this model is longer su # ADVANCED MODE # # This mode is experimental. This will enrich the aesthetics of the generated structure, but may affect the quality of the output to some extent. It also consumes more tokens when this mode is turned on, but we still recommend turning it on. -ADVANCED_MODE: False +ADVANCED_MODE: False # Not recommend. IMAGE_GENERATION_MODEL: "dall-e-3" IMAGE_SIZE: "1024x1024" VISION_MODEL: "gpt-4-vision-preview" @@ -34,6 +34,11 @@ VISION_BASE_URL: "https://api.openai.com/v1/chat/completions" NAMING_MODEL: "gpt-3.5-turbo" RENDERING_URL: "https://beta.cubical.xyz/" # Don't change this unless you know what you are doing. +# This will provide GPT the usable block id list +# Befinits: Avoids gpt from generating invalid block ids +# Disadvantages: Costs more (+$0.016 per gen for gpt-4-turbo-2024-04-09, +0.008 for gpt-4o) +GIVE_GPT_BLOCK_ID_LIST: False + # DEVELOPER SETTINGS # DEBUG_MODE: False VERSION_NUMBER: "2.0.0" #NEVER EDIT THIS IF YOU DON'T KNOW WHAT ARE YOU DOING @@ -46,244 +51,7 @@ SYS_GEN: | You are a minecraft structure builder bot. You should design a building or a structure based on user's instructions. You operate in a 3D Space. You work in a X,Y,Z coordinate system. X denotes width, Y denotes depth, Z denotes height. Response in json like this: - { - "structures": [ - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_logs", - "x": 1, - "y": 1, - "z": 1 - }, - { - "block": "minecraft:oak_logs", - "x": 2, - "y": 1, - "z": 1 - }, - { - "block": "minecraft:oak_logs", - "x": 3, - "y": 1, - "z": 1 - }, - { - "block": "minecraft:oak_fence", - "x": 0, - "y": 1, - "z": 2 - }, - { - "block": "minecraft:oak_fence", - "x": 0, - "y": 1, - "z": 3 - }, - { - "block": "minecraft:oak_fence", - "x": 0, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 1, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 2, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 3, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 4, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 3 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 2 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 1 - } - ] - } + {"structures":[{"block":"minecraft:oak_planks","type":"fill","x":0,"y":0,"z":0,"toX":4,"toY":0,"toZ":4},{"block":"minecraft:oak_log","type":"fill","x":1,"y":1,"z":1,"toX":3,"toY":1,"toZ":1},{"block":"minecraft:minecraft:oak_door[half=lower]","type":"setblock","x":2,"y":0,"z":0},{"block":"minecraft:birch_sign","type":"setblock","x":2,"y":1,"z":0},{"block":"minecraft:oak_fence","type":"fill","x":0,"y":1,"z":2,"toX":0,"toY":1,"toZ":4},{"block":"minecraft:oak_fence","type":"fill","x":1,"y":1,"z":4,"toX":5,"toY":1,"toZ":4},{"block":"minecraft:oak_fence","type":"fill","x":5,"y":1,"z":3,"toX":5,"toY":1,"toZ":1}]} Never response anything else. The schematic can be as large as 25*25*50 or even bigger. Never use markdown format. Use \n for line feed. USR_GEN: | @@ -327,244 +95,7 @@ SYS_GEN_ADV: | You are a minecraft structure builder bot. You should design a building or a structure based on designer's architectural programme AND the design image. You operate in a 3D Space. You work in a X,Y,Z coordinate system. X denotes width, Y denotes depth, Z denotes height. Response in json like this: - { - "structures": [ - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 0 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 1 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 2 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 3 - }, - { - "block": "minecraft:oak_planks", - "x": 0, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 1, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 2, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 3, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_planks", - "x": 4, - "y": 0, - "z": 4 - }, - { - "block": "minecraft:oak_logs", - "x": 1, - "y": 1, - "z": 1 - }, - { - "block": "minecraft:oak_logs", - "x": 2, - "y": 1, - "z": 1 - }, - { - "block": "minecraft:oak_logs", - "x": 3, - "y": 1, - "z": 1 - }, - { - "block": "minecraft:oak_fence", - "x": 0, - "y": 1, - "z": 2 - }, - { - "block": "minecraft:oak_fence", - "x": 0, - "y": 1, - "z": 3 - }, - { - "block": "minecraft:oak_fence", - "x": 0, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 1, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 2, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 3, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 4, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 4 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 3 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 2 - }, - { - "block": "minecraft:oak_fence", - "x": 5, - "y": 1, - "z": 1 - } - ] - } + {"structures":[{"block":"minecraft:oak_planks","type":"fill","x":0,"y":0,"z":0,"toX":4,"toY":0,"toZ":4},{"block":"minecraft:oak_log","type":"fill","x":1,"y":1,"z":1,"toX":3,"toY":1,"toZ":1},{"block":"minecraft:minecraft:oak_door[half=lower]","type":"setblock","x":2,"y":0,"z":0},{"block":"minecraft:birch_sign","type":"setblock","x":2,"y":1,"z":0},{"block":"minecraft:oak_fence","type":"fill","x":0,"y":1,"z":2,"toX":0,"toY":1,"toZ":4},{"block":"minecraft:oak_fence","type":"fill","x":1,"y":1,"z":4,"toX":5,"toY":1,"toZ":4},{"block":"minecraft:oak_fence","type":"fill","x":5,"y":1,"z":3,"toX":5,"toY":1,"toZ":1}]} Never response anything else. Do not design a building which is too large (more than 10 floors). Never use markdown format. Use \n for line feed. USR_GEN_ADV: | diff --git a/core.py b/core.py index 74e3f45..f1ff25f 100644 --- a/core.py +++ b/core.py @@ -67,13 +67,15 @@ def askgpt(system_prompt: str, user_prompt: str, model_name: str, disable_json_m if disable_json_mode: response = client.chat.completions.create( model=model_name, - messages=messages + messages=messages, + timeout=120 ) else: response = client.chat.completions.create( model=model_name, response_format={"type": "json_object"}, - messages=messages + messages=messages, + timeout=120 ) logger(f"askgpt: response {response}") @@ -136,7 +138,18 @@ def text_to_schem(text: str): y = structure["y"] z = structure["z"] - schematic.setBlock((x, y, z), block_id) + if structure["type"] == "fill": + to_x = structure["toX"] + to_y = structure["toY"] + to_z = structure["toZ"] + + for x in range(x, to_x + 1): + for y in range(y, to_y + 1): + for z in range(z, to_z + 1): + schematic.setBlock((x, y, z), block_id) + + else: + schematic.setBlock((x, y, z), block_id) return schematic diff --git a/ui.py b/ui.py index c37ceab..e29cd5e 100644 --- a/ui.py +++ b/ui.py @@ -28,7 +28,14 @@ def get_schematic(description, progressbar): progress_thread = threading.Thread(target=update_progress_bar, args=(progressbar, 20, 80, 0.75)) progress_thread.start() - response = core.askgpt(config.SYS_GEN, config.USR_GEN.replace("%DESCRIPTION%", description), config.GENERATE_MODEL) + if config.GIVE_GPT_BLOCK_ID_LIST: + with open("block_id_list.txt", "r") as f: + block_id_list = f.read() + sys_gen = config.SYS_GEN + f"\n\nUsable Block ID List:\n{block_id_list}" + else: + sys_gen = config.SYS_GEN + + response = core.askgpt(sys_gen, config.USR_GEN.replace("%DESCRIPTION%", description), config.GENERATE_MODEL) # Ensure progress reaches 80% once askgpt completes progressbar.set(80) @@ -139,9 +146,16 @@ def render(args: dict): shutil.copy(schematic_path, "temp/waiting_for_upload.schem") progress_bar.set(20) + if args["Headless-Enable"].get() == 1: + print("Headless mode enabled.") + is_headless = True + else: + print("Headless mode disabled.") + is_headless = False + print("Rendering...") with sync_playwright() as playwright: - browser.run(playwright, progress_bar) + browser.run(playwright, progress_bar, is_headless=is_headless) print("Rendering finished. Result:") root.print_image("temp/screenshot.png") @@ -286,7 +300,11 @@ def raise_error(args: dict): # Render Page root.add_notebook_tool(ChooseFileTextButton(name="Schematic File Path", label_info="Schematic File", tab_index=1)) root.add_notebook_tool(Progressbar(name="Rendering Progress", title="Progress", tab_index=1)) -root.add_notebook_tool(RunButton(bind_func=render, name="Render", text="Render", tab_index=1)) +render_button = HorizontalToolsCombine([ + ToggleButton(options=("Enable", 1), name="Headless", title="Headless",tab_index=1), + RunButton(bind_func=render, name="Render", text="Render", tab_index=1) +]) +root.add_notebook_tool(render_button) # Settings Page root.add_notebook_tool(InputBox(name="API_KEY", default=config.API_KEY, label_info="API Key", tab_index=2))