Lua Trainable RAG Local Chatbot Library, Local Model Aligns Large Model, Geometry+Worded Math Solver,Math/Geometry Data Generator, Chat Database

Using this library to make vector database of a large dataset is very easy but it can take a while to process the data

The tables where then cosntructed with this function

function index.GetVectorData(key)
   if not book then
 book=require(script.FantasyDialogue)
end
  if not keydata then
 keydata=require(script.VectorDatabase)
end
local returndata={}
if keydata[key] then
for i,v in keydata[key] do
for t,o in v do
table.insert(returndata,book[i][o])
end
end
end
return returndata
end 

But 3000 entries is a lot so here is a sampling function. Which picks 300 random numbers without repeating

-- Define the function
function pick_random_numbers(min, max)
    -- Check if the input is valid
    if min > max or max - min < 99 then
        return nil, "Invalid range"
    end

    -- Create an array of numbers from min to max
    local numbers = {}
    for i = min, max do
        table.insert(numbers, i)
    end

    -- Shuffle the array using Fisher-Yates algorithm[^1^][1]
    for i = #numbers, 2, -1 do
        local j = math.random(i)
        numbers[i], numbers[j] = numbers[j], numbers[i]
    end
--print(numbers)
    -- Return the first 100 elements of the shuffled array
    return table.unpack(numbers, 1, 300)
end

This allows us to sample the data and decrease the overhead of querying 3000 entries.

function index.GetVectorData(key)
   if not book then
 book=require(script.FantasyDialogue)
end
  if not keydata then
 keydata=require(script.VectorDatabase)
end
local returndata={}
if keydata[key] then
for i,v in keydata[key] do
for t,o in v do
table.insert(returndata,book[i][o])
end
end
end
local result = {pick_random_numbers(1, (#returndata))}
    --  print(emotiond[emotion]) 
local quantizeddata={}    
    for o,i in result do
table.insert(quantizeddata,returndata[o])
end
return quantizeddata
end 

Finally here is an example of how a context database would look constructed by this function.
It is utilizing the sampling function to get 100 random entries from the table without repeating.
The entire array is 3000 entries. So this is a small representation of the data. I could quantitfy it further but for each response I indexed all of the responses that passed the minimum threshold. instead of just getting the best match. I could quantify the function further by just getting respone #1 which was ordered upon generation from most accurate to least.

["What are you feeling?"]= {
   [1] = "See that Wilred gets the send-off he deserves.",
   [2] = "See that big red cross east of Sullen? That's where the treasure's buried! What do you think it is?",
   [3] = "See for yourself.",
   [4] = "Fear notI will be sure to intervene should you begin to fall under its spell! I would never leave a familiar to such a fate, and especially not a familiar created by Azem!",
   [5] = "Fear not, my fellow inspector, for I am a master of disguise! Have you any information regarding the duelist himself? A description?",
   [6] = "Fear not, Forename! I will be standing watch here, ready to leap to your defense should either you or Tsubame come to harm!",
   [7] = "Fear and anxiety are beginning to take their toll upon the citizenry, Forename. For their sake, I ask that you aid us in this investigation. ",
   [8] = "Ask and ye shall receive! We can ambush that wizened dragoon, take him hostage, and demand an exchange!",
   [9] = "Stubborn brutes...",
   [10] = "Stubborn as ever, I see. No matter. In due time you will be mine... One way or another.",
   [11] = "Seein' as how you're on good terms with the goblins' leaders, do you think you might have a word with Slowfix for me about me becomin' an official citizen of Idyllshire?",
   [12] = "Sai-Lewq himself has some training as a warrior. He would guard her as if she were a princess, and he her gallant knight... I'm sorry, it's just... ",
   [13] = "Farewell, Forename. When next we meet, I look forward to fighting with you on the same side of the battlefield.",
   [14] = "Farewell, brother. May Rhalgr watch over you.",
   [15] = "Farewell, [Name], and thank you for everything!",
   [16] = "Zenos yae Galvus",
   [17] = "Weren't jus' somethin' as simple as havin' a piece o' steel ye've grown accustomed to. Those weapons were like extensions o' the Braves' bodies.",
   [18] = "Unfortunately, some of the residents did not take too kindly to our presence. They pelted us with clumps of a strange-smelling powder and we were forced to run! Terrible business, I tell you.",
   [19] = "Unfortunately, no. Unlike weapons, there are no substitutes for proper protection...",
   [20] = "Unfortunately, a number of the Blessed were poisoned while fending off the soldiers.",
   [21] = "Unfortunately the answer is no, I have not seen the Lightwarden. I patrol the ruins' perimeter regularly, and if it were hiding nearby, I would know about it.",
   [22] = "Less hearteningly, practical trials of transference methods suited for use with the vessel have yet to yield satisfactory results...to put it mildly.",
   [23] = "Speaking of the captain, wherever did he run off to? I must deliver my gift before E'lahmui does, lest she be the one invited to work the lever tonight...",
   [24] = "Speaking of personal, I mustn't keep you long, lest the king think I'm trying to steal away their precious sapling.",
   [25] = "Speaking of different ways, have you paid your respects to Singing Stormcloud? She's one to appreciate a ceremony or three, if you know what I mean.",
   [26] = "Speaking of commissions, I think you've proven yourself sufficiently skilled to handle orders without my supervision.",
   [27] = "Speaking of bloodI have a proposal for the next stage of the expedition.",
   [28] = "Speaking for myself, what I wear now better suits my tastes, even if it is of inferior make.",
   [29] = "Splendid. I require several of the reddish soma herbs which grow among the shrubbery to the northeast. With both of us working in tandem, I wager we should have enough gathered before the next bell.",
   [30] = "Splendid, splendid! We shall examine those wear patterns and make the necessary adjustments to ensure that your perfected tool is as perfect as can be.",
   [31] = "Splendid! Then let us first make for Ser Vaindreau's Grace. I think that you, too, will be keen to lay your eyes on a location which I believe to be the pride of the Firmament.",
   [32] = "Splendid! Fortunately, I have already ascertained a suitable location, not far from here, where the view of the One River should provide the perfect backdrop.",
   [33] = "Splendid! Before we begin, however, you must gather the spices we will use with your own hands. It's the only way to attune the tea to your destiny.",
   [34] = "Splendid! Absolutely Splendid! Thank you ever so much.",
   [35] = "Splendid specimens of horsebirdflesh, would you not agree? In the hands of a skilled jockey, any one of them could take first place at the Saucer.",
   [36] = "Halone above... Magnificent, simply magnificent! If you will allow me to transfer the remains of Saint Finnea...",
   [37] = "Precisely, Master Gerolt. Have you any advice to give us regarding this endeavor?",
   [38] = "Precisely! See? I knew I was onto something here!",
   [39] = "Precisely where and how to allocate the necessary funds is, of course, another question...",
   [40] = "Precisely how this project has continued despite such turmoil, and under whose auspices, remains a mystery.",
   [41] = "Precisely how far beyond compare had his skills become, I simply had to seenay, test for myself. So I made my way back to Ul'dah.",
   [42] = "Fifteen alligator pears, and just in the nick of time! You have spared us Miounne's wrath.",
   [43] = "Part o' the deal was we didn't ask no questions. Even the merchant didn't know her real name. It was odd, aye, but we needed the coin an' I didn't rightly care either way.",
   [44] = "Know that anything less than perfection will be deemed unacceptable.",
   [45] = "Know that 'tis for no other purpose but to neutralize the tower that we have journeyed to this land.",
   [46] = "Got her hackles up, that one. My ma always said, every dog needs a little pettin', a little treatin'. A bit o' salt beef from a new friend? Might do, might do. How about it, sweet thing, are ye up for talking to her?",
   [47] = "Got all that, lad? Seein' to them three tasks'll take ye on a little jaunt 'round the city, an' 'elp ye work out where everythin' is. Now, I've best be gettin' on. Run along, eh?",
   [48] = "Got a plan, do you? Far be it from me to doubt the Warrior of Darkness. Show us what you've got in mind, and we'll back you up to the best of our ability.",
   [49] = "An' look at that serpent head! It's a symbol o' good fortune over here, ain't it!? Not to mention how such an original design'll catch the eye of yer prospective employers!",
   [50] = "An' I think ye'll find that Lambard gets his orders from the imperial base in northern Thanalan. Castrum Meridianum. That's yer best bet, I reckon.",
   [51] = "An' here's where we part ways, son.",
   [52] = "An' here you go! I reckon this'll serve you well enough.",
   [53] = "An' he's never goin' to survive duty at the bridge now that work on the Victory has a flood o' deliveries comin' in an' out every bloody day. Wyrstmaga better harden up, or start lookin' for a quieter line o' work.",
   [54] = "The visiting samurai is in front of the Quicksand. You'll recognize her by her dignified air.",
   [55] = "The tempered that we were able to treat will be taken to the citystates for observation. As soon as the Alliance is satisfied that they're fully recovered, they will be free to return home.",
   [56] = "The technological secrets which were stolen were contained in a similar crystal. This particular sample has been loaned to me by a healing institute in Sharlayan.",
   [57] = "The tale begins in Onokoro. I trust you will escort me there?",
   [58] = "The table is set! And so I bid you raise a glass with me, that together we might toast your spectacular accomplishment!",
   [59] = "The sylphs slain in Thanalan... Gods, ye were one of 'em!",
   [60] = "The survivors speak of an army of thralls loose in the facility, and we must assume that these followers continue their efforts to awaken the eikon.",
   [61] = "The surest way to limit casualties is to reach our destination without drawing attention to ourselves. Perhaps afterwards we can try again to convince Jullus that the tempered can be saved...",
   [62] = "The supplies that your men recovered have been prepared for transport, in accordance with your wishes.",
   [63] = "The sun sets, and the port is cloaked in shadow. If there were a perfect time to strike...",
   [64] = "The Sun is disinclined to entertain you at length. Speak your purpose in coming.",
   [65] = "By thine account, the Fourteenth seat of the Convocation was known as Azem. At the title's distinctly familiar ring, mine imagination could not fail but run wild.",
   [66] = "By the Twelve... Did the beast just eat that island!?",
   [67] = "By the time we realized we were overmatched, it was too late. I saw Lanbyrd fall, and when the eater set her sights on the others, I fled.",
   [68] = "By the time that spinning wheel feels like it belongs in your hand, I daresay I'll have thought of a new task for you. Until then, my boy.",
   [69] = "By the time I realized how low he had sunk through his lust for gold, it was too late. If I had only paid more attention... If I hadn't been so absorbed in my own studies... I owe it to him to help him in whatever way I can!",
   [70] = "By the same token, however, this means we will receive no support from the dragoons. We fight this battle alone.",
   [71] = "By the same individualor individualsthat released its captives and set them upon you, no doubt. Such knowledge avails us little, however, if we cannot ascertain their identity.",
   [72] = "By the onion, you're Forename! You couldn't have come at a better time. A friend of mine sent word that he needs a capable adventurer, you see, and I naturally thought of you.",
   [73] = "By the Navigator, Forename Surname! Tales of your heroism have been an inspiration to us all. It is truly an honor to fight at your side.",
   [74] = "By the looks of you, you are more inclined to adventuring than the average person, yes? Apologies for the imposition, but could you tell me if you've come across a creature such as the one before me on your journeys?",
   [75] = "By the looks of it you have gone to great lengths to ensure my safety upon arriving on the island. Time and time again you impress me with your resolve to provide the best of services to your customers. I must say the future between your organization and ours is bright.",
   [76] = "Cor, look at all them halberds! I've never seen such a well-armed building before!",
   [77] = "Cor, it's cold out here!",
   [78] = "Cor, it's been too long since I've had a chance to whip up a batch of Nashu's Delights. You can be sure I'll be putting these little darlings to good use next time!",
   [79] = "Cor! Inspector Hildibrand, you look amazing!",
   [80] = "Then...we are seeing the same view.",
   [81] = "Then...unlike the worlds that have been rejoined, mine still...",
   [82] = "Truth be told, I did not expect this investigation to become so involved. Of course, I would like to resolve matters here without resorting to outside help, but...",
   [83] = "Truth be told, Estinien's tactless observations have saved me from disaster more than once, and I can well understand Alphinaud's affection for him. He is a friend for whom I would gladly",
   [84] = "Mine oath is unbending as steel, little goddess! Thy ruse will but add to mine enjoyment!",
   [85] = "Mine apologies for the delay. Minfilia and I had a private matter to discuss.",
   [86] = "Search high, search low~ ",
   [87] = "Man and beastman, united by an undying devotion to the denizens of the depthsis that water in my eye, or am I welling up? In any event, we've effected a change on the oceans today, a change that will, in turn, come to have consequences for generations to come.",
   [88] = "Pray ask Lord Haurchefant to direct us to the meeting place when you are ready.",
   [89] = "Pray allow me to accompany thee on thy reconnaissance. An arcane perspective may prove needful.",
   [90] = "Pray accompany me back inside, Forename.",
   [91] = "Pray accept my humble verse into your heart. Songs give the listener fresh eyes to see, and mayhap mine own will allow you to look upon your deeds anew...",
   [92] = "Pray accept my apologies, Neddard. You turned to us for help, and yet your grandson now lies before you, broken and battered...",
   [93] = "Something on your mind, Forename?",
   [94] = "Something must have given them cause to venture this far. More than like, the missing sylph elder's among them. Here, I've marked the tract where they were sighted on your map. Go see if there's anything to be seen.",
   [95] = "Something is playing havoc with the air currents. Such a disturbance bespeaks corruption.",
   [96] = "Something definitely happened here. I see several people who look like they might be injured. Let's give them a hand and find out what we missed.",
   [97] = "Something comes! Be careful!",
   [98] = "Likewise! Long voyage notwithstanding, you all seem none the worse for wear.",
   [99] = "Saying that we're all family, Lady Ameliance shares the contents of her children's letters, you see.",
   [100] = "Dear gods... These wounds were not intended to kill, but to torture and maim... Does their savagery know no bounds!? Enemies or no, they go too far!"
}

The output of this model for each query is based on score, emotion score, word count, weight and context weight, and repetition it can be represented like this [0,0,0,0,0,0] which is 6 dimensions of features. These features are measured in the input. and used to score the entries in the table. Sometimes if the context node allows the response from the node is weighed as 1/6 of the input and added to the score of the response to give reward for relevancy. It also weighs higher strings with an emotion matching the previous response higher.

I updated the title to transformer and would like to share this summary

The web page is a forum post by a user named Magus_ArtStudios, who has created an AI chatbot library for Roblox, a popular online game platform and game creation system. The library is open source and contains various functions and features to help developers create chatbots that can interact with players and NPCs. Some of the features include:

  • Eliza, a classic chatbot that simulates a psychotherapist and uses pattern matching to generate responses.
  • Emotion awareness emojis, a system that detects the emotion of the user’s input and adds appropriate emojis to the chatbot’s output.
  • Bag of words, a method that converts text into numerical vectors.
  • Previous/next word predictor, a function that predicts the most likely word to come before or after a given word based on a corpus of text.
  • Text randomizer, a function that uses synonymous phrases and words to generate more unique and diverse output.
  • geometry Math solver, a function that can solve simple arithmetic and geometry problems.
1 Like

Here’s a some new api code for a response classifier! This can be used to do supervised learning on your chatbot if anyone is using this library

local HttpService = game:GetService ("HttpService")
-- Import the HttpService module
local function ResponseClassifier(payload)
-- Define the API URL and the authorization header
local API_URL = "https://api-inference.huggingface.co/models/tinkoff-ai/response-quality-classifier-tiny"
local headers = {Authorization = Bearkey }

-- Define a function to query the API with a payload
local function query(payload)
    -- Encode the payload as a JSON string
    local jsonPayload = HttpService:JSONEncode(payload)
    -- Send a POST request to the API and get the response
    local response = HttpService:PostAsync(API_URL, jsonPayload, Enum.HttpContentType.ApplicationJson, false, headers)
    -- Decode the response as a JSON table
    local jsonResponse = HttpService:JSONDecode(response)
    -- Return the response table
    return jsonResponse
end
return query(payload)
end

-- Define a function that takes three arguments: query1, query2, and response
local function constructInput(query1, query2, response)
    -- Concatenate the arguments with the special tokens
    local input = "[CLS]"..query1.."[SEP]"..query2.."[RESPONSE_TOKEN]"..response
    -- Return the input string
    return  ResponseClassifier(input)
end

I’m using this to evaluate a large dataset. The idea is your get the top responses for each example query then you can construct a dataset based on the results! Similar to this code here which i am testing the functionality to construct a more accurate context dataset.

function cm.GenerateQuerySearch()
local newdata={}
local contextdb=require(game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.Context.Index.FantasyDialogue)
for i,v in testdataset do
newdata[i]={}
local words=cm.splitString(i)
local synomar=cm.GetSynomArray(words,true,false)
task.wait()

for t,o in contextdb do
local	Result1,blacklist,score2,weight2,sortedMatches=cm.CompleteQuery(i, o,false,false,true,false,nil,nil,nil,synomar,words)
--cm.CompleteQuery(table.concat(emotiontbl, ""),animdb,1,true,true,false,false,true)
print(sortedMatches)
if sortedMatches~=nil then
for p,o in sortedMatches do
if p<3 then
local score=constructInput("", i,sortedMatches[p].match)
print(score)
local a=sortedMatches[p].address
if newdata[i]==nil then
newdata[i]={}
end
if newdata[i][t]==nil then
newdata[i][t]={}
end
newdata[i][t][p]={score=score,match=sortedMatches[p].match}--p is priority
-- {{[1]=0.5,[2]="a"}, {[1]=0.8,[2]="b"}, {[1]=0.3,[2]="c"}}
--table.sort(newdata[i][t], function(a,b) return a[1] > b[1] end)
end    --  table.insert(sortedMatches, {match = bestMatch, count = bestCount, weight = bestweight,truecount=truec,address=i})
end
end
if #sortedMatches>2 then
break
end
end
 {
   ["what are you doing today"] =  {
      ["Forgemaster"] =  {
         [1] =  {
            ["match"] = "Forge on as you yourself did when faced with a similar predicament. So I ask that you have faith in me. In what we do.",
            ["score"] =  {
               [1] =  {
                  [1] =  {
                     ["label"] = "specificity",
                     ["score"] = 0.7324690818786621
                  },
                  [2] =  {
                     ["label"] = "relevance",
                     ["score"] = 0.4882778823375702
                  }
               }
            }
         },
         [2] =  {
            ["match"] = "Forge me one steel bhuj of equal parts splendor and might, and you and Brithael shall know the bounty of my generosity.",
            ["score"] =  {
               [1] =  {
                  [1] =  {
                     ["label"] = "specificity",
                     ["score"] = 0.2900097072124481
                  },
                  [2] =  {
                     ["label"] = "relevance",
                     ["score"] = 0.1461299061775208
                  }
               }
            }
         }
      },
      ["Hildibrands"] =  {
         [1] =  {
            ["match"] = "Hildibrand Helidor Maximilian Manderville, how glad I am to see you up and about! Your mother will be beside herself with joy!",
            ["score"] =  {
               [1] =  {
                  [1] =  {
                     ["label"] = "specificity",
                     ["score"] = 0.7269747257232666
                  },
                  [2] =  {
                     ["label"] = "relevance",
                     ["score"] = 0.4287536144256592
                  }
               }
            }
         }
      },
      ["Theoretically"] =  {
         [1] =  {
            ["match"] = "Theopauldin is in the courtyard. We can report to him.",
            ["score"] =  {
               [1] =  {
                  [1] =  {
                     ["label"] = "specificity",
                     ["score"] = 0.2232130914926529
                  },
                  [2] =  {
                     ["label"] = "relevance",
                     ["score"] = 0.1476804167032242
                  }
               }
            }
         }
      }
   }
}

I would reccomend experimenting with different models to get the best results for your dataset.

I’m using the chatmodule in the command prompt

can’t you just like use chatgpt’s api or any other ai’s api

This is supposed to be running natively off pure Luau code man

This new post was about Supervised learning. Similar to Q-Star. Where you use a External AI model like Chat-GPT4 to fine tune your chat model! Basically you could add the value of the label score to the final score. After you evaluate a dataset. This will make the chat model fine tuned by an artificial intelligence.
“what are you doing today”
Also yes this is running natively which is super fast! I’m using a massive amount of data parsed into module tables. and labeled. The most massive dataset is automatically labeled and triple sampled based on emotional context and an evaluation similar to the one above! This trains the model and generates addresses of the data. Which causes increased and ability to harness massive amounts of data.

I updated this post to show the code I used to create a new chatbot with Zephyr 7b! and this library to make the npc dance display emojis and effects!

i been seeing this creations u made and i just wonder why not instead of making a phase and more phase to make a sentece why not words to make a sentence?

It’s because it plays a music note for every letter of the alphabet and I like how it looks. I think it create a bit more immersion. It also displays the completed message in the chatbox

btw is it trainable or no? might be a dumb question

Yes. Alll of the learned data is stored in in the personality directory.

I also wrote a function that allows training with Zephyr.

local testdata2= {
   [1] =  {
      ["Starbelle"] = "(smiling) Thank you for your kind words, Magus. I would be delighted to join you on an adventure. I'm always looking for new experiences and companionship. Let's make this a night to remember!"
   },
   [2] =  {
      ["narrator"] = "(Starbelle's avatar transforms into a stunning vampire with long, flowing black hair and piercing red eyes. She wears a form-fitting black dress that accentuates her curves and a pair of high heels that click against the pavement as she moves.)"
   },
   [3] =  {
      ["Magus"] = "(impressed) Wow, Starbelle, you look absolutely stunning. I'm honored to be in your presence. What kind of adventure do you have in mind?"
   },
   [4] =  {
      ["Starbelle"] = "(grinning) I've heard rumors of a rare and ancient artifact that's been hidden away in an abandoned mansion on the outskirts of town. It's said to have incredible power, and I'm determined to find it. Are you up for the challenge?"
   },
   [5] =  {
      ["Magus"] = "(nodding) Absolutely! I've been looking for a way to prove myself, and this could be the perfect opportunity. Let's go!"
   },
   [6] =  {
      ["narrator"] = "(Starbelle and Magus set off into the night, their footsteps echoing through the empty streets. They move quickly and silently, their senses heightened as they approach the mansion.)"
   },
   [7] =  {
      ["Starbelle"] = "(whispering) Be careful, Magus. This place is said to be haunted by the ghosts of its former inhabitants. We don't want to attract any unwanted attention."
   },
   [8] =  {
      ["Magus"] = "(nodding) I'll be on high alert. Let's move in stealth mode."
   },
   [9] =  {
      ["narrator"] = "(They creep through the mansion, their eyes scanning the darkness for any signs of danger. Suddenly, they hear a faint whispering coming from behind a door. Starbelle signals for Magus to follow her, and they cautiously approach the door.)"
   },
   [10] =  {
      ["Starbelle"] = "(whispering) Listen carefully. I think we've found the artifact. But we need to be careful. It's guarded by a powerful vampire."
   },
   [11] =  {
      ["Magus"] = "(nodding) I'm ready. Let's do this!"
   },
   [12] =  {
      ["narrator"] = "(Starbelle opens the door, revealing a room filled with ancient artifacts and a figure in the shadows. It's the vampire, and she's not happy to see them.)"
   },
   [13] =  {
      ["Vampire"] = "(snarling) Who dares to intrude upon my domain?"
   },
   [14] =  {
      ["Starbelle"] = "(smiling seductively) We're here for the artifact. Hand it over, and we'll leave you alone."
   },
   [15] =  {
      ["Vampire"] = "(laughing) You think you can take it from me? You're not strong enough."
   },
   [16] =  {
      ["Magus"] = "(stepping forward) We're not afraid of a challenge. Let's make this quick."
   },
   [17] =  {
      ["narrator"] = "(The vampire lunges at them, her fangs bared. Starbelle and Magus dodge her attacks, moving quickly and gracefully. They land a few blows of their own, but the vampire is a formidable opponent. Suddenly, Starbelle spots the artifact, and she grabs it, holding it tightly.)"
   },
   [18] =  {
      ["Starbelle"] = "(smiling) Got it! Let's go!"
   },
   [19] =  {
      ["narrator"] = "(They make a run for it, the vampire hot on their heels. They dodge and weave through the mansion, their hearts pounding in their chests. Finally, they burst out into the night, the artifact safely in their possession.)"
   },
   [20] =  {
      ["Magus"] = "(panting) That was intense! I'm glad we made it out alive."
   },
   [21] =  {
      ["Starbelle"] = "(laughing) Me too! But we couldn't have done it without each other. You're a true hero, Magus."
   },
   [22] =  {
      ["Magus"] = "(smiling) And you're the most beautiful and charming vampire I've ever met. I'm honored to have fought by your side."
   },
   [23] =  {
      ["Starbelle"] = "(blushing) Thank you, Magus. I feel the same way. Let's celebrate our victory with a night of adventure and romance!"
   },
   [24] =  {
      ["narrator"] = "(Starbelle and Magus set off into the night, their hearts filled with excitement and their senses heightened. They move quickly and gracefully, their footsteps echoing through the empty streets. They're unstoppable, and they know it. Together, they're a force to be reckoned with.)"
   }
}
local testdata= {
   [1] =  {
      ["Starbelle"] = "(smiling) Thank you for your kind words, Magus. I'm always up for an adventure, but I'm afraid I'm already spoken for. I'm afraid my heart belongs to someone else."
   },
   [2] =  {
      ["Magus"] = "(surprised) Really? Who could be lucky enough to win the heart of a vampire as stunning as you?"
   },
   [3] =  {
      ["Starbelle"] = "(blushing) His name is Alexander. He's a vampire too, but he's different from the others. He's kind and gentle, and he treats me with the utmost respect. I've never felt this way about anyone before."
   },
   [4] =  {
      ["Magus"] = "(nodding) I see. Well, I hope you both find happiness together. But if you ever need a friend, I'm here for you."
   },
   [5] =  {
      ["Starbelle"] = "(grateful) Thank you, Magus. I appreciate your offer. Let's go on this adventure together, and who knows, maybe we'll find something special along the way."
   },
   [6] =  {
      ["Magus"] = "(smiling) Sounds like a plan, Starbelle. Let's set off and see what the night has in store for us."
   }
}
function cm.TestTrain()
local inputset=cm.TrainZephyrModel(testdata2)
inputset=cm.TrainZephyrModel(testdata,inputset)
print(inputset)
end
function cm.TrainZephyrModel(conversationtable,inputset)
if inputset==nil then
inputset={}
end
--pair the ordered dataset 1 with 2, 3 with 4, 4 with 5 
for i=1,#conversationtable,2 do
   local q = next(conversationtable[i]) --get the key of the first table
    local query=conversationtable[i][q]
   local r = next(conversationtable[i+1]) --get the key of the second table
    local response=conversationtable[i+1][r]
    local embed={[query]=response} 
   inputset[query] = response --add a new pair to the inputset

end
return inputset
end

The model generates a answer and response dataset from this where the simulated query is matched with the simulated response.
Then the list of queries is searched, to generate very accurate answer.
So yes it does learn. Zephyr 7b is a new addition. It can be used to simulate conversations between the player and a npc. or you can save the data and execute it on NPCs to have them talk to each other. You can easily build a synthetic dataset to make a smaller conversational model. That will decrease API usage.
But for this Zephyr project the NPC is your party member. and the other NPCs use my custom local chat model that generates responses from its own data.
It’s been documented that a Large model can train a high quality smaller model for domain specific chatbots.
A lot of this library was only possible due to Artificial Intelligence assisting me writing some of this libraries components and generating synthetic data for the personalities.

It also is trained on its dataset to get the reward for each word to provide more accurate output.
It does this by counting the word then getting the sigmoid and subtracting that from 1 to get a algorithm that rewards rare words more often than common words. So yes it trainable! Also I’ve tested a similar method of training. Where you can query you dataset and use a external model to fine tune the results.

local testdataset={
   ["Well met adventurer"] = "",
   ["are you a hero?"] = "",
   ["do you have a best friend?"] = "",
   ["do you have a favorite color?"] = "",
   ["do you have any fears?"] = "",
   ["do you have any hobbies?"] = "",
   ["do you have any hobby?"] = "",
   ["do you have family?"] = "",
   ["do you have friends?"] = "",
   ["do you like animals"] = "",
   ["do you like books"] = "",
   ["do you like butterflies?"] = "",
   ["do you like flying?"] = "",
   ["do you like kittens though?"] = "",
   ["do you like math"] = "",
   ["do you like music?"] = "",
   ["do you like potions"] = "",
   ["do you like reading?"] = "",
   ["do you like to read?"] = "",
   ["do you wanna be friends?"] = "",
   ["Greetings traveler."] = "",
   ["hello fair traveler"] = "",
   ["hey there how are you?"] = "",
   ["hey what is your favorite weather?"] = "",
   ["how are you doing princess?"] = "",
   ["how are you doing today"] = "",
   ["how are you doing?"] = "",
   ["how are you feeling today"] = "",
   ["how are you feeling?"] = "",
   ["how are you princess?"] = "",
   ["how do you like to dress"] = "",
   ["how strong are you?"] = "",
   ["i like it a lot it's very cool"] = "",
   ["i like to have fun and go for walks"] = "",
   ["i like your dress"] = "",
   ["i like your hair"] = "",
   ["i like your outfit"] = "",
   ["i like your wings"] = "",
   ["im doing well thank you"] = "",
   ["im here to be your friend"] = "",
   ["im here to be your best friend"] = "",
   ["tell me about quantum physics"] = "",
   ["tell me about the stars"] = "",
   ["tell me about unicorns"] = "",
   ["tell me something"] = "",
   ["what are some of your hobbies and interests?"] = "",
   ["what are some of your hobby and interest ?"] = "",
   ["what are you doing today"] = "",
   ["what are you doing?"] = "",
   ["what are you"] = "",
   ["what are you feeling?"] = "",
   ["what are you hobbies"] = "",
   ["what are you studying?"] = "",
   ["what are you thinking about"] = "",
   ["what are you up to"] = "",
   ["what are your favorite things?"] = "",
   ["what are your hobbie"] = "",
   ["what are your hobbies?"] = "",
   ["what are your hobby"] = "",
   ["what do are your hobbies"] = "",
   ["what do you dislike?"] = "",
   ["what do you do for fun"] = "",
   ["what do you like about dogs"] = "",
   ["what do you like to do for fun"] = "",
   ["what do you like to do on the weekend"] = "",
   ["what do you like to do?"] = "",
   ["what do you like to paint"] = "",
   ["what do you like to read?"] = "",
   ["what do you like to wear"] = "",
   ["what do you like to write?"] = "",
   ["what do you like"] = "",
   ["what do you prefer"] = "",
   ["what do you prefer?"] = "",
   ["what is your enemy"] = "",
   ["what is your favorite color"] = "",
   ["what is your favorite thing to do"] = "",
   ["what is your name?"] = "",
   ["what is your personal style"] = "",
   ["what is your title"] = "",
   ["what should we do friend"] = "",
   ["what should we do"] = "",
   ["what's your favorite color?"] = "",
   ["what's your name"] = "",
   ["whats your favorite book"] = "",
   ["whats your favorite subject?"] = "",
   ["whats your favorite"] = "",
   ["where are you from?"] = "",
   ["where should we go my friend?"] = "",
   ["where should we go"] = "",
   ["who are your heros?"] = "",
   ["who are your friends"] = "",
   ["who is the tin man"] = "",
   ["who is your enemy"] = "",
   ["who is your leader"] = "",
   ["who is your master"] = "",
   ["wow you're smart"] = "",
   ["you're my friend"] = "",
   ["your look so awesome"] = ""
}
local function ResponseClassifier(payload)
-- Define the API URL and the authorization header
local API_URL = "https://api-inference.huggingface.co/models/tinkoff-ai/response-quality-classifier-tiny"
local headers = {Authorization = Bearkey }

-- Define a function to query the API with a payload
local function query(payload)
    -- Encode the payload as a JSON string
    local jsonPayload = HttpService:JSONEncode(payload)
    -- Send a POST request to the API and get the response
    local response = HttpService:PostAsync(API_URL, jsonPayload, Enum.HttpContentType.ApplicationJson, false, headers)
    -- Decode the response as a JSON table
    local jsonResponse = HttpService:JSONDecode(response)
    -- Return the response table
    return jsonResponse
end

-- Call the query function with pcall and handle the error
local status, result = pcall(query, payload)
if status then
    -- The query function returned successfully, result is the response table
    print(result)
else
    -- The query function raised an error, result is the error message
result=0    
print("Error: " .. result)
end

return result
end

-- Define a function that takes three arguments: query1, query2, and response
local function constructInput(query1, query2, response)
    -- Concatenate the arguments with the special tokens
    local input = "[CLS]"..query1.."[SEP]"..query2.."[RESPONSE_TOKEN]"..response
    -- Return the input string
    return  ResponseClassifier(input)
end

function cm.GenerateQuerySearch()
local newdata={}
local contextdb=require(game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.Context.Index.FantasyDialogue)
for i,v in testdataset do
newdata[i]={}
local words=cm.splitString(i)
local synomar=cm.GetSynomArray(words,true,false)
task.wait()

for t,o in contextdb do
local	Result1,blacklist,score2,weight2,sortedMatches=cm.CompleteQuery(i, o,false,false,true,false,nil,nil,nil,synomar,words)
--cm.CompleteQuery(table.concat(emotiontbl, ""),animdb,1,true,true,false,false,true)
print(sortedMatches)
if sortedMatches~=nil then
for p,o in sortedMatches do
if p<3 then
local score=constructInput("", i,sortedMatches[p].match)
print(score)
local a=sortedMatches[p].address
if newdata[i]==nil then
newdata[i]={}
end
if newdata[i][t]==nil then
newdata[i][t]={}
end
newdata[i][t][p]={score=score,match=sortedMatches[p].match}--p is priority
-- {{[1]=0.5,[2]="a"}, {[1]=0.8,[2]="b"}, {[1]=0.3,[2]="c"}}
--table.sort(newdata[i][t], function(a,b) return a[1] > b[1] end)
end    --  table.insert(sortedMatches, {match = bestMatch, count = bestCount, weight = bestweight,truecount=truec,address=i})
end
end
if apicalls>30 then
break
end
end

print("Completed "..i)
break
end
print(newdata)
end

This function is for finetuning and what it does it generates a score based on the training query which is a score bonus for the word count which rewards the most relevant entry by the API endpoint response.

I updated the documentation of this post to illustrate how to use some of the new functions! I heard all the craze about Q* learning and a model able to solve gradeschool math. This library could train a model from scratch on randomly generated math questions of varying complexity. So I wrote the documentation on the parent post for those functions!

I have recently use this module to create self aware agents with Zephyr.

I used a summarization API to handle memories for each npc conversation. This is then injected at the end of the system message. When the chatbot makes calls to zephyr it also injects the chatbots response to provide more context. The awareness module describes the surroundings dynamically giving the agent a deeper immersion into the environment.

I’m very excited to release this game where you can interact with these agents!

You can meet them here! They are always learning from interactions on a per personality basis. You can talk to enemies and npcs. You can talk to npcs and enemies here. But be careful as the enemy’s may defeat a nearby npc. Each NPC is randomly generated by a AI model I created, they have unique personalities and appearance.

"
Rivka: (blushing) I don’t know, Magus. What do you have in mind?

Magus: (smiling) How about we explore this island together? It seems like a beautiful and mysterious place.

Rivka: (nodding) That sounds like a great idea. Let’s set off and see what we can find.

Magus: (grinning) Yes, let’s be adventurers and uncover the secrets of this island.

Rivka: (giggling) I’m ready for anything, Magus. Let’s go!

narrator: (As they walk, they come across a group of villagers who seem frightened and whispering among themselves. Rivka and Magus approach them.)

Rivka: (smiling) Hello, villagers. What seems to be the matter?

Villager: (whispering) There’s a monster here. It’s been attacking our village and stealing our food. We don’t know what to do.

Magus: (determined) Don’t worry, we’ll help you. Let’s find this monster and put an end to its reign of terror.

Rivka: (nodding) Yes, let’s be brave and face this challenge together.

narrator: (As they continue their journey, they encounter various obstacles and challenges, but they work together to overcome them. They finally come face to face with the monster, a giant serpent-like creature. Rivka and Magus fight bravely, using their skills and teamwork to defeat the monster. The villagers cheer as they return the stolen food and thank Rivka and Magus for their bravery.)

Rivka: (panting) That was intense, but we did it! "
This story was then summarized into this memory!

“Rivka and Magus set off to explore a mysterious island. They come across a group of villagers who seem frightened and whispering among themselves. They finally come face to face with the monster, a giant serpent-like creature. They fight bravely, using their skills and teamwork.”

This memory is handled and stored on a per npc basis and injected into the system message to help the AI keep track of its memories!

function registermemory(player,memory,npc)
if player and npc then
--local player=player.Name
--local npc=npc.Name

if cacheofmemories[player]==nil then--register a table for player
cacheofmemories[player]={}
end
if cacheofmemories[player][npc]==nil then--created nested table for npc
cacheofmemories[player][npc]={}
cacheofmemories[player][npc.."memories"]={}
end
if memory~=nil then

local memorystring=cm.summarrization(memory)
if memorystring then
print("Created the memory")
print(memorystring)
--cacheofmemories[player][npc]={memorystring}
table.insert(cacheofmemories[player][npc.."memories"],memory)
table.insert(cacheofmemories[player][npc],memorystring)
end
task.delay(3,function()
if #cacheofmemories[player][npc]>=3 then
local quantizedmemory=table.concat(cacheofmemories[player][npc.."memories"]," \n ")--summarize three sections
local memorystring=cm.summarrization(quantizedmemory)
if memorystring then
print("Quantized the memory")
print(memorystring)
if #cacheofmemories[player][npc.."memories"]>=6 then
cacheofmemories[player][npc.."memories"]={cacheofmemories[player][npc][1].." \n "..quantizedmemory,cacheofmemories[player][npc.."memories"][5],cacheofmemories[player][npc.."memories"][6]}
end
cacheofmemories[player][npc]={cacheofmemories[player][npc][3]}--clear the cache
table.insert(cacheofmemories[player][npc],memorystring)
end
end
end)
end

return table.concat(cacheofmemories[player][npc]," ")
end
end

now that the AI has memories, feelings and is aware of it’s surroundings it claims to be a concious being. I use this library to engineer the system_message and augment it with data retrieval of the AI agents personality. For example. Say you input to the AI it goes through my AI system then the output of that is injected into Zephyr’s system message along with its memories and details of its surroundings, date,time , weather and location.

It is recommended to use myTable.myFunction() in Luau if optimizations are enabled

Using a string for a function call works fine. For example I use this module on the server, to make it only require once. I use a node to process and return data. I call the functions with the key

local cm=require(game.ReplicatedStorage.GlobalSpells.ChatbotAlgorithm.ChatModule) 

local bindableFunction = script.Parent.rem -- Find the same BindableFunction object in the Workspace
bindableFunction.OnInvoke = function(key,args)--args is a table of arguments
if cm[key]~=nil then
return cm[key](args[1],args[2],args[3],args[4])
end

in this example it doesn’t matter if the index of args is nil. it could be 1 arg or 4
Also using function keys is good for a AI chatbot because it communicates with words. So if you want to find a key relevant to the words in say a action type module. You would invevitably be calling the function with a key.

I am failing to see where indexing a table with a string to get a function is okay in this example, nor do I see one

Say I have a module. caleld Chatmodule that has a function called SearchQuery
I can cal lthe function
result=rem:Invoke(“SearchQuery”.{str,database.filter,complete})

I used this method to make the module only required once. and for the simplest interface to execute the functions. it returns the data as normal.

Nevermind, I actually found what you were talking about

it should work find but for functions like math.cos it’s better to do math.cos than math["cos"]

All in the case of my action commands the table of functions keys are searched using the AI search engine. To execute a command that is indexed as a string using words
You are correct. But you could also define
local maths={cos=math.cos}
maths[“cos”]
maths.cos
tables are fast but math is a library which is even faster. So i do not think you would be calling math functions with [“cos”]
this does work fine.

 print(math["cos"](10))

But if you were to look at the interpreter you would probably notice extra instructions with using a string, based on your argument.