NEW Action Token AI Framework LLM Utility/Chatbot Luau [Open Source]

This is a example of creating a Chatbot that responds to commands with actions
and returns a string.
This code may not be useful but it is a demonstration.
This was build mainly with this library.
UPDATE Awareness V3 Text-Vision LLM Utility Luau [OPEN SOURCE] - Resources / Community Resources - Developer Forum | Roblox
This code was designed to interpret words and translate them into actions. This is like a text processor for AI output to give it Agency to interact with its Environment. It interprets a string and does the corresponding action based on the context function

local queryspace={   
    ["Enemy"] = {"readying to assault", "striking", "aiming at","focus","assault","preparing to attack", "attacking", "targeting","target","attack"}, 
    ["NPC"] = {"approaching", "greeting", "following","follow","coming near", "saluting", "trailing","pursue"}, 
    ["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 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
local cm=game.Players.LocalPlayer.PlayerGui.Chatbot.LocalProcessor
--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
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:lower(),v)() then
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:lower(),v)() then
return v
end
end
end

local function querykeys(query)
for i,_ in queryspace do
if string.gmatch(query:lower(),i)() then
return i
end
end
end



local function queryspells(query)
for i,v in SpellsQuery do
if string.gmatch(query:lower(),v:lower())() then
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)
            return "I am " .. verb .. " " .. aware.judge.object(navigationtarget) .. " 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 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,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 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

This Lua code appears to be a complex script for a chatbot system within a ROBLOX game. Let’s break down the main components and functionalities step by step:

  1. Modularity: The code is organized into different sections and functions, making it modular and easier to understand, maintain, and expand.
  2. Object-Oriented Design: The use of tables, functions, and context-specific actions reflects an object-oriented design, enhancing readability and maintainability.
  3. Integration of Spells: The code seamlessly integrates a spell system, allowing the chatbot to cast spells based on user queries.
  4. Context-Aware Actions: The Contextbl table demonstrates an awareness of different in-game contexts, enabling the chatbot to respond appropriately to various objects and scenarios.
  5. Query Processing: The actions.navigate.query function efficiently processes user queries, combining navigation and interaction based on the context.
  6. Result Cache Optimization: The use of a result cache for storing and retrieving spell keys enhances efficiency and performance.
  7. Awareness and Navigation: The awareness and navigation functions, along with the consideration of distances and directions, contribute to a more realistic and immersive user experience.

Overall, the code exhibits a high level of complexity and functionality, making it an impressive implementation of a chatbot system within the ROBLOX environment.

4 Likes

You seriously just gave it to ChatGPT, and copied/pasted what it gave in return. This is not a valid resource.

3 Likes

I got feedback from chatgpt. It’s true feedback! I also commented the code to explain each step in the logic. Basically this is a framework for making actions for a chatbot. I use this module to generate over 500 interactions. of which 11 navigation commands, 11 interaction commands and over 500 spell command interactions. The increase is exponential though. The more interactions chained together the interactions go up to the power of the number of generic chained interactions.
It’s built atop of the Awareness Library which provides textual observations of the environment.
That module is leveraged to generate interactions based on those classifiers.

This is meant to be inspirational and provide a logical framework.

1 Like

I would like to reiterate that I wrote this algorithm by only using AI to generate data, otherwise the logic was all written by me and this module I use this to perform actions via a prompt. It has been tested and works but interaction functions are omitted due to dependencies.