Text Vision Awareness Judgement Description Library for LLMs in Video Games [Open Source]

Yours too! Your meshVox plugin is a godsend for developers I have gotten such amazing use out of it I’ve been hoping for support for that kind of thing for a while! I’ll be improving this resource soon with a new reformatted version soon that will focus on general usage and short form factor! I made this intentionally complicated to make sure each new object category was working properly but now I want to make it more elegant and pass variables rather the current code which has become redundant over time.

Another system I created is focused on Actions built using the Awareness Library.
Currently not completely useful as open source due to execution relying on interactions and features from a large codebase.

--[[
This Lua code is designed for use within Roblox Studio and involves complex interactions with game objects, NPCs (Non-Player Characters), and spells. It's structured to handle various actions such as navigation, interaction, and spell casting based on textual commands or queries. The code is modular, leveraging multiple tables and functions to process and execute commands within a game environment. Here's a breakdown of its functionality:

Initial Setup
queryspace: A table containing keywords associated with different game elements like enemies, NPCs, chests, etc. Each category has a list of related actions or descriptors.
RunService and isLocal: Determines if the script is running on the client-side.
actions: A table structured to hold various sub-tables for handling objects, navigation, interaction, word models, and spells.
aware, dfg, commands, actionmod: These lines import various modules required for the script to function, such as awareness algorithms, global spells, command processing, and action modules.
SpellCommands and Spells: These sections prepare the script to handle spell commands by loading them into tables for easy access.

Functions Overview
MagicSpell: A function to cast a spell, checking if the character has a tool equipped and using it as the spell's source if present.
querywordspace, keywordspace, querykeys, queryspells: Functions designed to search through the queryspace and SpellsQuery for matches based on the input query. They are used to identify actions or spells related to the query.
awareresponse: Generates a response based on navigation towards a target, including details like distance and direction.
Contextbl: A table of functions that return context-based strings for interactions with different game elements (e.g., enemies, chests, NPCs).
actions.objects, actions.navigate, actions.interact: These sub-tables within actions define functions for object handling, navigation, and interaction based on the game environment and player commands.
actions.spells.query and actions.spells.Cast: Functions for querying available spells based on the input and casting the identified spell.
actions.navigate.navinteract: Handles navigation and interaction with a target based on a query, potentially invoking spell casting if relevant.
actions.navigate.query: The main function that processes a query, identifies the relevant action (navigation, interaction, spell casting), and executes it.

Execution Flow
Initialization: Sets up the environment, loads necessary modules, and prepares spell commands.
Query Processing: When a query is received, it's processed to identify the relevant action - whether it's moving towards an object, interacting with it, or casting a spell.
Action Execution: Based on the query's context, the script executes the appropriate action. This could involve navigating the player towards a target, interacting with game objects, or casting spells.
Response Generation: After executing an action, the script can generate a descriptive response based on the action's outcome, providing feedback to the player.

Key Concepts
Modularity: The script is structured into distinct sections and functions, each handling a specific aspect of the game's interaction model.
Data-Driven: Actions and responses are driven by the queryspace and other data tables, allowing for flexible command processing.
Dynamic Interaction: The script dynamically handles interactions with the game world, allowing players to navigate, interact, and cast spells based on textual commands.
This code snippet is an example of how complex game logic can be implemented in Roblox Studio, leveraging Lua's capabilities for dynamic and interactive game development.
]]
local queryspace={   
    ["Enemy"] = {"readying to assault", "striking", "aiming at","focus","assault","preparing to attack", "attacking", "targeting","target","attack","fight"}, 
    ["NPC"] = {"approaching", "greeting", "following","follow","coming near", "saluting", "trailing","pursue","approach"}, 
    ["chest"] = {"opening", "looting", "unlocking","open","treasure","unsealing", "plundering", "unfastening","unlatch","booty"}, 
    ["crystal"] = {"examining", "admiring", "touching","inspecting", "appreciating", "feeling"}, 
    ["dungeons"] = {"exploring", "investigating", "solving","scouting", "probing", "cracking"}, 
    ["fish"] = {"catching", "fishing", "catch fish","snaring", "angling", "hook fish","fish"}, 
    ["house"] = {"entering", "searching", "leaving","penetrating", "rummaging", "departing"},
    ["loot"] = {"lifting", "gathering", "keeping","plunder","lift","picking up", "collecting", "storing","loot","pick up"}, 
    ["mapobj"] = {"interacting", "ignoring", "destroying","examine","investigate"}, 
    ["plant"] = {"reaping", "gather","pluck","snatch","cultivate","reap","amassing","harvesting", "collect","pick","pick-up","farm","harvest","collecting"}, 
    ["player"] = {"approaching", "greeting", "following"}, 
    ["rubble"] = {"mining", "clearing", "mine rock", "removing", "excavate rock"}, 
    ["tree"] = {"cutting tree", "cut tree","chop tree","woodcut","woodcutting","lumberjack","slicing tree", "fell tree","hew tree","timber","logging","woodsman"}
	
}
local RunService = game:GetService("RunService")
local isLocal = RunService:IsClient()
local actions = {}
actions.objects = {}
actions.navigate = {}
actions.interact = {}
actions.wordmodel = {}
actions.spells={}
--import libraries awareness global spells
local aware = require(game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.Awareness)
local player=game.Players.LocalPlayer
local dfg = require(game.ReplicatedStorage.GlobalSpells)
--subject,target
local commands = require(game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.Commands)
local actionmod = require(game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.ActionModule)
--local Remote=game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.APICallsLearnData.APIData.RemoteEvent
if isLocal then 
cm=game.Players.LocalPlayer.PlayerGui.Chatbot.LocalProcessor
else  
	cm=game.ReplicatedStorage.GlobalSpells.BindableFunction 
end	
	--dfg.FindPath(Subject,Targ)
local Controller = dfg.LocalController()
local SpellCommands=game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.SpellCommands:GetChildren()
local Spells={}--spells require a humanoid?
local SpellRemote=game.ReplicatedStorage.GlobalSpells:WaitForChild("RemoteEvent")
for i,v in SpellCommands do
Spells[v.Name]=v
end
local SpellsQuery={}
for i,v in SpellCommands do
SpellsQuery[i]=v.Name--:lower()
end

function actions.MagicSpell(Character,player,Type,Target)
if Character:FindFirstChildOfClass("Tool")==nil  then
		Controller.MagicSpell(Character.RightHand,Type,Target,nil,1,player)
	else	
		Controller.MagicSpell(Character:FindFirstChildOfClass("Tool").Handle,Type,Target,nil,1,player)
end	
end

--for i,v in commands do
--Controller[i]=v
--end
--for i,v in commands do
--local i=i
--Controller[i]=function(args) Remote:FireServer(args,i) end
--end

local near = aware.near
local navigation = {""}

local worldmodel = {}

local path = Controller.FindPath
local pathingdebounce = {}
--action.ConductAlchemy(Character,root,Herb)
--action.PickUpObject(Character,Object)
local function querywordspace(query)--query entire word space
for i,c in queryspace do
for t,v in c do
if string.gmatch(query,v)() then
print("Found pattern "..v.." inside "..query)
return v
end
end
end
end

local function keywordspace(query,key)--query key word space
for i,v in queryspace[key] do
if string.gmatch(query,v)() then
print("Found pattern "..v.." inside "..query)
return v
end
end
end


local function querykeys(query)--there are not many of these so i lower is fine.
for i,_ in queryspace do
if string.gmatch(query,i:lower())() then
print("Found pattern "..i.." inside "..query)
return i
end
end
end



local function queryspells(query)
for i,v in SpellsQuery do
if string.gmatch(query,v:lower())() then
print("Found Spell pattern "..v.." inside "..query)
return v
end
end
end

function actions.wordmodel.awareresponse(root, navigationtarget, magnitude, navroot, verb)
    local res = ""
    if navigationtarget then
        local pos = root.CFrame.Position
        if navigationtarget then
            local magn = magnitude
            local dist, dir = aware.judge.distance(root, magn, pos, navroot.Position, 80)
            --local size = aware.judge.size(closestChest.Size)
            if dir ==nil then dir="around here" end  if dist==nil then dist="somewhere" end
            local objstr=aware.judge.object(navigationtarget)
            print(objstr)
            if objstr==nil then objstr=navigationtarget.Name end 
           if verb==nil then verb="walking towards the" end
          print(verb)
        print(objstr)
        print(dist)
        print(dir)
              return "I am " .. verb .. 
                                " " .. objstr .. 
                                            " that is " .. dist ..
                                                                     "" .. dir
        end
    end
end

local Contextbl = {
    --target attack the enemy
    ["Enemy"] = function(root, obj, key)
        return "preparing to attack", aware.get.NPCDescription(obj.Parent)
    end, --walk towards the npc
    ["NPC"] = function(root, obj, key)
        return nil, ""
    end,
     --do nothing just navigate to
    --walk towards and open the chest
    ["chest"] = function(root, obj, key)
        return "walking towards the lock of the", ""
    end, --navigate to the animpoint inside the chest
    --walk towards and examine the crystal
    ["crystal"] = function(root, obj, key)
        return "checking out this", ""
    end,
    ["dungeons"] = function(root, obj, key)
        return "trying to find the center of this", ""
    end,
    ["fish"] = function(root, obj, key)
          if obj then Controller.PickUpObject({root.Parent, obj}) end
        return "swimming towards the", ""
    end,
    ["house"] = function(root, obj, key)
        return "walking towards the door of the", ""
    end,
    ["loot"] = function(root, obj, key)
       if obj then Controller.PickUpObject({root.Parent, obj}) end
        return "attempting to loot the", actionmod.PickUpObject(root.Parent, obj) 
    end,
    ["mapobj"] = function(root, obj, key)
        return nil, ""
    end,
    ["plant"] = function(root, obj, key)
         if obj then Controller.PickUpObject({root.Parent, obj}) end
        return nil, ""
    end,
    ["player"] = function(root, obj, key)
        return nil, ""
    end,
    ["rubble"] = function(root, obj, key, Player)
        local key = "mine rock"
        commands[key](Player, root.Parent)
        return nil, commands.commandresponse(key)
    end,
    ["tree"] = function(root, obj, key, Player)
        commands["cut tree"](Player, root.Parent)
        return nil, commands.commandresponse("cut tree")
    end
}


local keytable= {
   [1] = "crystal",
   [2] = "plant",
   [3] = "tree",
   [4] = "mapobj",
   [5] = "rubble",
   [6] = "chest",
   [7] = "player",
   [8] = "loot",
   [9] = "fish",
   [10] = "NPC",
   [11] = "Enemy",
   [12] = "house",
   [13] = "dungeons"
}

for key, v in near do
    worldmodel[key] = {}
    --get the object with a query
    actions.objects[key] = function(root, player, var, query) --get closest object and query the surroundings
        local closestObject, NumObjects, ObjectSize, ObjectDistance = aware.get.objectsdata(root, key, query)
         --query the array with a string
       -- print(closestObject)
      --  print(query)
        if closestObject~=nil then
        worldmodel[key] = {Close = closestObject, Amount = NumObjects, Size = ObjectSize, Magnitude = ObjectDistance}
        else 
        worldmodel[key] = {Close = nil, Amount = NumObjects, Size = ObjectSize, Magnitude = ObjectDistance}       
        end
         --rebuild the observation
        if var then
            return worldmodel[key][var]
        end
        return worldmodel[key] --return the variable or the table
    end

    actions.navigate[key] = function(root, player, query, verb,navigation) --navigate to the request place/object and return string
        if pathingdebounce[root.Parent.Humanoid.DisplayName] == nil then
            pathingdebounce[root.Parent.Humanoid.DisplayName] = false
        end
        if pathingdebounce[root.Parent.Humanoid.DisplayName] == false then
            if query~=nil then query={Query=query} end
          if navigation==nil then navigation = actions.objects[key](root, player, nil, query) end
             --query the object array with a string with no var to recieve full array of data

            if navigation.Close~=nil then -- if there is a navigate close target return the target and do pathing
                print("Successful Environment Navigation Search") -- The object has beenn found
                print(navigation)
                Controller.WalkTween({root, root.Parent.Humanoid, navigation.Magnitude, 4})
                 --Calculate acceleration based on distance

                local navroot = aware.get.root2(navigation.Close)
                 --get the navigation root

                pathingdebounce[root.Parent.Humanoid.DisplayName] = true
                path({root.Parent, navroot}) --navigate to object

                task.delay(
                    3,
                    function()
                        pathingdebounce[root.Parent.Humanoid.DisplayName] = false
                    end
                )
                 --delay and trigger debounce
               local resultant
                  if verb == nil then
                     verb, resultant = Contextbl[key](root, nil, key, player)   
                    if verb==nil then verb = "walking towards the" end
                end
                return actions.wordmodel.awareresponse(root, navigation.Close, navigation.Magnitude, navroot, verb), navigation,verb,resultant
             --return a string describing the object and its position
            end
        end
        return nil --no result found
    end
    --always returns a string
    actions.interact[key] = function(root, player, query,navigation,destination,verb,resultant) -- navigate and interact with the object
      if verb or resultant==nil then verb, resultant = Contextbl[key](root, nil, key, player) end
      if navigation or destination==nil then destination, navigation = actions.navigate[key](root, player, query, verb) end
        if destination ~= nil then
            Contextbl[key](root, navigation.Close, key, player)
            Controller[key](root, navigation.Close)
            return destination .. " " .. resultant
        end
    return destination
    end

end
local resultcache={}
function actions.spells.query(root,player,query)
local spellkey
--if resultcache[query]==nil then resultcache[query]=queryspells(query) end
--if resultcache[query]~=nil then spellkey=resultcache[query] else 
spellkey= queryspells(query) --end
if spellkey then
--if resultcache[query]==nil then resultcache[query]=spellkey end
local spell=require(Spells[spellkey])
return spell[math.random(1,#spell)],spellkey
end
return nil
end
function actions.spells.Cast(root,player,Target,query)
local spell,Type= actions.spells.query(root,player,query)
if spell then
actions.MagicSpell(root.Parent,player,Type,Target)
return 'I am casting '..Type..". "..spell,Type
end
return nil
end



function actions.navigate.navinteract(root,player,query,key,query2)
        local navigation=actions.objects[key](root, player, nil, query)   --query the namespace and return the navigation result   
  
        if navigation.Close ~= nil then --if close entry is not nil then we got a direct result
        local Result= querywordspace(query) -- if we get a result confirm with different context words which would imply navigation
         if Result then
         local destination,navigation,verb,resultant = actions.navigate[key](root, player, query2,nil,navigation) --navigate and return a string destination, navigation table, the verb and the resultant string
        print("Navigating to target")
        if destination then--if destination string is not nil then we are 
        local actiontoken=  keywordspace(query,key)--search the key word space to determine if interaction
             print("Got Interaction Result")  
        local spellcontext,SpellKey,interaction=nil,nil,nil       
            if actiontoken==nil then --if no action token found in the keyword space search the spells 
            spellcontext,SpellKey=actions.spells.Cast(root,player,navigation.Close,query)                    
            interaction=destination
         
         elseif actiontoken~=nil then --if we have a action token then we should interact with the object
 --  repeat task.wait(.15) until root.Parent.PathingTag:GetAttribute("Complete")==true   --wait for pathing to complete
 interaction=actions.interact[key](root, player, query,navigation,destination,verb,resultant) end
            --return the results as a string 
            if spellcontext==nil and interaction~="" then --no spell casted and interaction was successful
             return interaction,key
           elseif spellcontext~=nil then --spell was cast describe the spell and the navigation string.
         return spellcontext..interaction,SpellKey
         end 
        end
        return destination --return  just the navigation string if nothing else passed.
        end
        end
return nil
end
--this funcion generates 78 commands
function actions.navigate.query(root, player, query)--this function takes a query and executes a action command based on the 
local query=query:lower()
 local result=nil
 for key, v in near do
   local res=actions.navigate.navinteract(root,player,query,key,query)
    if res then return res end
  end
local explicitkey=  querykeys(query)
if explicitkey~=nil then
result=actions.navigate.navinteract(root,player,query,explicitkey,nil)
end
if result==nil then result=actions.spells.Cast(root,player,navigation.Close,query)  end      
resultcache=nil 
   return result
end
--local actions=require(game.ReplicatedStorage.GlobalSpells.ActionModule2)
--actions.navigate.query(root, player, query)
return actions