Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Faster, resource efficient agents via getCraftingPlan tool #391

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Ayushmaniar
Copy link

@Ayushmaniar Ayushmaniar commented Dec 31, 2024

Commit: Provide agents with a tool called "getCraftingPlan(targetItem, count)" to make them resource efficient, fast and more grounded in the world of minecraft

Problem statement

Have you ever tried to ask andy to craft a stone pickaxe and andy starts collecting 6 cobblestones and 10 oak_logs ? This happens with me more often than not and if you actually think about it, you just need 3 cobblestones and 2 sticks which come from 2 oak_planks which inturn come from 1 oak_log to craft a stone pickaxe. There is no need to waste a lot of extra time (and sometimes even tokens (aka money)) to collect all the unnecessary items.

Well, this would be no more of an issue since the agent call now call a query called !getCraftingPlan(targetItem, count = 1) which would tell it what items and how much of those items the bot is missing, along with giving a detailed plan about how to craft the item sequentially working up from the "base items" to the final product (aka targetItem).

Here is the output the bot would get when it calls !getCraftingPlan("stone_pickaxe",1)

You are missing the following items: 
- 3 cobblestone
- 1 oak_log

Once you have these items, Here's your crafting plan: 

1x time 1 oak_log -> 4 oak_planks
1x time 2 oak_planks -> 4 stick
1x time 3 cobblestone + 2 stick -> 1 stone_pickaxe

Suppose if andy has all the items required, the function would tell that "You have all the items required to craft this item. Here's your crafting plan: ....".
Thus the function getCraftingPlan() also takes the agents current inventory into account.

This function recursively calls getItemCraftingRecipes function to find out what items are missing to craft a targetItem. The recursion doesn't stop untill a "base item" (like oak_log) is found which has no "parents" (aka no crafting recipes), the base items are supposed to be found organically in the world via exploration.

Note : We also handle some edge case errors when we can run into infinite crafting loops. For example the crafting recipe for diamond sword is 2 diamonds + 1 sticks, the recursion called on 1 stick would terminate at 1 oak_log, but the recursion called on diamonds would run into an infinite loop where ("diamonds" -> "diamond_block" -> "diamonds" -> "diamond_block" -> "diamond" .....). In such cases we treat "diamond" as a "looping item" and stop the recursion at diamond.
There are approximately 81 such looping items out of 1312 minecraft items (as of version 1.20.4)
Additional Note : If you want to understand the recursion of reaching to base items, then I have created a project which helps in visualizing recipes of any items in minecraft via a streamlit app. Here is a youtube video describing the work if anyone is interested (github repo available as well) Visualizing minecraft recipes with recursion to base items

Changes explained in Detail

1. Conversation Examples for !getCraftingPlan(targetItem,count) (_default.json)

  • Added some conversation examples in default.json to teach andy how and when to use this new function

Examples:

    [
        {"role": "user", "content": "terrance: (FROM OTHER BOT)Lets make a wooden pickaxe together"},
        {"role": "assistant", "content": "Sure, let me check how to make a wooden pickaxe !getCraftingPlan(\"wooden_pickaxe\",1)"},
        {"role": "system", "content": "You are missing the following items:\n - 2 oak_log\n\n Once you have these items, Here's your crafting plan:\n\n 2x times 1 oak_log -> 4 oak_planks\n1x time 2 oak_planks -> 4 stick\n1x time 3 oak_planks + 2 stick -> 1 wooden_pickaxe"},
        {"role": "assistant", "content": "I need 2 oak logs to make a wooden pickaxe. Do you have any?"}
    ]

2. Return craftedCount along with the recipe (mcdata.js)

  • getItemCraftingRecipes function now return a list of two elements for each recipe where first item of the list is the recipe dictionary, and the section item of the list is {"craftedCount" : units"}

For a concrete example the first recipe of getItemCraftingRecipes("stick") would now be [ {"oak_planks":2}, {"craftedCount":4} ] instead of the previous output of {"oak_planks":2}.

The knowledge about crafting Count is important to find the minimum amount of ingredients required to craft some item since crafting 4 sticks also requires 2 oak_planks and crafting 1 stick also requires 2 oak_planks

3. getDetailedCraftingPlan(currentInventory, targetItem, count = 1) function (main/major change) (mcdata.js)

The generateCraftingSteps function is the core of the algorithm.

It does the following:

  • Checks Inventory: Ensures the required item is already in the inventory before attempting to craft, and updates the inventory by deducting the used amount if sufficient.
  • Handles Missing Recipes: If no recipe is found for an item, it's added to the missingItems.
  • Processes Crafting Recipes: If a recipe exists, it calculates how many batches are needed to meet the required count, adds the recipe as a crafting step, and recursively determines how to obtain the recipe's ingredients.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant