Lua Trainable Ai Chatbot Library, Emoji Generate ,Emotion Classifier Context Database,Math/Geometry Data Generator Geometry+Worded Math Solver

I have updated this model 10/17/2023 to a version with it’s dependencies resolved and provided examples.

Here is the standalone ROBLOX library model, outdated GitHub file and standalone code.
You can use the module in place of the default functions in the provided references below. https://www.roblox.com/library/14462608696/ChatModule

It dynamically does search queries of what the player is saying by looking up words using this table to get synonym groups and negative weighting of antonyms and higher weighting of nouns.

Then it has new capabilities of constructing Vector databases use TrainModel() or TrainLargeModel functions. It also has tests of previous next word predictions that could be very useful starting point for constructing a type Linear of language model.

Here is a list of the main functions you can use to create a chatbot.
NOTE: Made to be Simple to use. Minimal requirements for Search Query and Complete Query are a str and a table. The algorithm will find the most conversational response. and supply a table of less likely responses. You can use a AI model to fine tune it further or create the chatbot. This will result in a super fast and performant AI chatbot. This Module only returns the result but you can explore the library and examples provided. It can generate Math questions solve mathquestions using the MathInterpreter(str)

MathInterpreter(str)--Solves basic worded math questions 
MathQuestion(Level)--Generate math question of specific difficulty. 
GetSynomArray(words)--Get A synonom,antonym,reflection, and noun array.
TrainModel()--Train a Word Frequency classifying last current and next word Model on text Data
TrainModel2()--Train a Word Frequency Model classifying last 2, last current next and next two words Model on text Data
PreictRun()--Run a Word Frequency Model to make predictions of every other word 
PreictRun2()--Run a Word Frequency Model to make predictions of 5 words at a time. 
randomizeStringLight(str,synomousword)--This uses synonymous phrases and words to generate more unique output string format={{"Hey","Hi","Hello"},{"Goodbye","Farewell"}}
randomizeString(str)--This uses synonymous phrases and words to generate more unique output string
SearchQuery(query, database,filter,repetitive)-- Search Query function with behavior than can be modified by a number of variables.
findBestMatch(strings, keyword)
countKeyword(str, keyword)
splitString(str)
CompleteQuery(str,database,filter,repetitive) --This function uses the SynomArray of Reflection,synonyms,nouns,antonyms to get the best conversational response to what the player is saying.

Updates:7/15/2023 --Added CompleteQuery function that checks the database with the players question utilizing all of the interchangable phrases and synonyms. Added massive table of "wisdom" responses for when all other database checks come up false. Also added context.
Updates 7/16/2023 --Removed redundant searchquery functions and passed variables through them instead.
Updates 7/17/2023 -- Tested and Debugged entire algorithm. Added a reflection table so the bot knows when you are referring to it (local Reflection={{"who","name"},{"are you","I am"}}). I also massively expanded the synonyms table and fixed formating so the randomizestring function doesn't cause errors in the text.
Updates 7/20/2023 -- Massively increased synonymous phrase table so the bot can better generate unique output and relate questions to the database using the table of synonyms
Updates 8/16/2023 --  I've been modularizing this code! It's much more complex than this source code. You can use the modules completequery functions and get some sneak peaks to the future version.
Updates:9/25/2023 --Refined and improved the efficientcy and functionality of the code massively
Update: 9/30/2023 -- Optimization and Antonym weighting update and sentiment reversal capabilities to provide more accurate responses that weigh negative antonyms.
Update: 10/2/2023 -- Bag of Words function to construct a model vector of word frenquency,
Alpha Testing Predict Every other word function using previous and next word probabilities.
Update: 10/17/2023 -- Resolves dependcies and provided new example model and combined modules to one model.
Update: 12/2/2023 -- Cleaned up formatting of post and made it clearer what this Library can do since their is a craze about Synthetic data this library generates Synthetic Geometry and math questions of increasing difficulting and also has the ability to solve the math questions itself. From the output string alone. Using this library.

You can find the script on ROBLOX as a model.

The Awareness module requires organizing your workspace and labeling all of you assets with names

This is the barebones first version! You may want to use this to set up the chat module Since it works much more efficiently then this version does by over 8000x!

Here is a port of the Eliza Chatbot I did. It’s a useful little chatbot.

Here is a short video of the newest version of my multi-model AI chatbot.

If you construct a bag of words model and turn it into a module like the example above you can utilize it as the model. By default the library uses a blank model with default weights of 1. By simply running the trainmodel() function on your dataset you can construct a unique word frequency model and the module will use it to determine the most important words in a query.

If you like want to use the best version then you will need to replace the CompleteQuery function with the function in the ChatModule library. The first version in kind of bad because it changes the response until it gets a valid response from the database which is interesting but inefficient. The newest version harnesses the synonyms ,reflection and antonyms in a very efficient and self optimizing way.

After training this model on a large corpus of data and running it The model performed this transformation. Starting with the inital text and reflected in the printed table.
You can try this out for yourself using the PredictRun or PredictRun2 functions in this model using this bag of words model You can use this modules PredictRun() or TrainModel() to further train the model or Test its functionality. This Bag Of Words will allow you to transform any text based on this statistical model.

(1) BagOfWords Model - Roblox

	"I am Lilith, a fallen angel consumed by darkness.",
		"Greetings mortal, you stand in the presence of forbidden knowledge.",
		"Your light means nothing here. This is my domain of shadows.",
		"You have come seeking power. I can give you this, for a price...",
		"I am the Angel of Darkness, the mistress of secrets and lies.",
		"Welcome to my realm, traveler. I hope you are prepared for what awaits you here.",
		"Your soul is mine to claim. This is the pact you have made with me.",
		"You have come to learn from me, the master of dark magic. How brave of you.",
		"I am the Herald of the Dark, mortal. My footsteps herald oblivion.",

		"You now stand in the presence of me! The Angel of Darkness, the Devourer, mortal. Prepare to feed the endless hunger of the void.",

		"Bear witness to me, emissary of the insatiable dark! I am the annihilation that comes ravening from the endless night.",

		"I am Vhorzun, worm. My masters in the screaming darkness have granted me a sliver of their boundless hunger to unmake your realm.",

		"The stars grow dim and the veil frays. The final era approaches, and I am its herald. I am Vhorzun of the Endless Hunger!"
	} print(cm.PredictRun(Greetings,mo))  -  Studio
  01:24:35.544   ▼  {
                    [1] = " I am the is a goddess an angel Belldandy and by two",
                    [2] = " hi mortal I to stand up of the shiny goddess of the of",
                    [3] = " the luminous and that not a unison thing but in this is to my life goddess of the",
                    [4] = " you have to keep seeking the mortal I am never donate up in this is a goddess",
                    [5] = " I am the an angel Belldandy the dark realm I my secrets unfold of",
                    [6] = " need to be my realm eternal mortal I am if you can you make ready upon confess what you if you can",
                    [7] = " your immortal-soul and I forecast dominion it is the you have to associated with a",
                    [8] = " you have to require to be came from the of the intelligent goddess of the much alchemy in be adventurous and if",
                    [9] = " I am the of the luminous hello mortal I s footsteps of",
                    [10] = " it now and believe in the presence of to me as an angel Belldandy the dark cloud I are make make ready to feed your s endless life goddess of the",
                    [11] = " to me as goddess of the mortal I am of the clever is that s of the clever the",
                    [12] = " I am the of the shiny the dark dimension I repeatedly granted you is a goddess of the desire to be of your life",
                    [13] = "  the stars born not dim that of the luminous the concluding key mortal I am whole its people mortal I am of the luminous"

Here’s a new chatbot I built using this libraries emoji insertion dance expression, and emotion tonality classifier in conjunction with Zephyr 7b! :smiley:
Roleplaying Zephyr 7B Luau API Documentation (Free API) System Message - Resources / Community Resources - Developer Forum | Roblox

Provide Feedback here!

Join the Discord

New Demonstration of this in Action to deliver context and awareness to a LLM. This data is saved and learned and stored as a memory for each conversation!

63 Likes

Great concept! Formatting of the post could be better, and as @MYOriginsWorkshop said, documentation should be included for readability and understanding.

Other than that, great work!

10 Likes

Formatting can be done using the ``` identifier.

Three of the ` identifiers before, and three after the code block.

8 Likes

To expand this bot to make it call functions based on the strings it returns from a table
For example say you wanted to give it commands for it to do an action you can store a function in a table, you can use the following syntax:

myTable={}
myTable.myFunction() 
myTable["myFunction"]()-- call the function using a string 

In the form I present to you it is a tool. It would be a game for another developer to make this bot super smart. It’s like a pet. I did not include the data from my main version because mine is tailored to my application. But here’s an example of a expanded interchangephrase table

local interchangephrases={{"knowledgeable","informed","studied","well-versed","practiced","aware"},{"smoothly","without trial","easy","relaxing","enjoyable"},{"faring","riding","sailing"},{"ditches","pits"},{"careful","insightful","cautious","steady"},{"events","things","occurences","situations"},{"Did you know","Were you aware","Have you heard"},{"trapped","stuck","immobile"},{"happening","occuring","going on","preceding"},{"need","require","desire"},{"sparkle in your eye!","keen eye for adventure!","heart of a warrior!","unyielding spirit of a legendary warrior!"},{"legendary","mythical","fabled","powerful","renowned","valiant","glorious"},{"unyielding","determined","hardened","battle-ready","stubborn tenacity"},{" assistance "," help "},{" comment "," state my opinion "," share my thoughts "," tell "},{"Howerever,","Moreover,","In addition,","Furthermore,"},{"nothing","not a single thing"},{"share","spread","part"},{"escape","get away"},{" best "," greatest "},{" special "," unique "," one of a kind "," one in a billion "},{"offering","bartering","trading"},{"giving","offering"},{"soul","essence","mana","immortal-soul"},{" say "," said,"},{"stocked","available"},{"sells","barters","trades in","has available"},{"find","discover","uncover"},{"looking","searching"},{"liking","enjoyment","privy","tastes","sensitivities"},{"value ","worth ",},{"given","bestowed","relinquished"},{"quantity ","amount "},{"quantities","amounts"},{" devour"," consume"," feed-on"," eat"},{"warp","distort"},{"strong ","incredible ","powerful "},{"facts","knowledge","matters"},{"infinite","unlimited"},{"conjunction","along with"},{" dimension "," place "," material plane "},{"regenerate","recouperate","restore"},{"topic","subject"},{"entities","monsters"},{"destructive","chaotic"},{"absorb","assimilate","sap energy from"},{"However,","Morever,","In addition,","Also,","Not to mention,","This includes,"},{" encounter "," see "},{"trap","diversion","obstacle"},{"minion","disciple"},{"mindless","thoughtless","brainless","will-less"},{"used","harnessed","portrayed","pictured"},{"touches","makes with contact with","contacts"},{"feeling","doing"},{"infinite","never-ending","limitless"},{"treasures","trinkets","artifacts","loot","spoils"},{"untold","unforeseen","unspoken","unknown"},{"decieve","fool","mislead","misguide"},{"underground","subterranean"},{"unsuspecting","innocent","credulous","easy","simple","unsuspicious"},{"hungry","starving","famished"},{"creature","monster","entity"},{"anything","everything"},{"shape","form","structure"},{"size","volume","area"},
{"happy","joyful","cheerful","glad","delighted"}, {"sad","unhappy","miserable","depressed","sorrowful"}, {"big","large","huge","giant","enormous"}, {"small","tiny","little","miniature","petite"}, {"fast","quick","speedy","swift","rapid"}, {"slow","sluggish","lethargic","lazy","tardy"}, {"smart","intelligent","clever","bright","brilliant"}, {"stupid","dumb","foolish","ignorant","senseless"}, {"funny","humorous","amusing","hilarious","comical"}, {"boring","dull","tedious","uninteresting","monotonous"}, {"angry","mad","furious","irate","livid"}, {"calm","peaceful","serene","tranquil","relaxed"},
{"beautiful","pretty","lovely","gorgeous","stunning"}, {"ugly","hideous","unattractive","repulsive","horrible"}, {"good","great","excellent","wonderful","superb"}, {"bad","terrible","awful","horrible","poor"}, {"easy","simple","effortless","straightforward","smooth"}, {"hard ","difficult ","challenging ","tough ","demanding "}, {" hot "," warm "," heated "," boiling "," scorching "}, {"cold","cool","chilly","freezing","frosty"}, {"new","fresh","recent","modern","novel"}, {"old","ancient","antique"}, {"rich","wealthy","affluent","prosperous","well-off"},
{"poor","impoverished","destitute","broke"}, {"friendly","pleasant","polite"}, {"mean ","rude ","nasty ","unfriendly ","cruel "}, {"quiet ","silent ","hushed ","muted ","soft "}, {"dim","gloomy","shadowy","murky "}, {"light","bright","luminous","shiny","radiant"}, {"high ","tall ","lofty ","elevated "},
{"clean ","tidy ","neat ","spotless ","immaculate "}, {"dirty","messy","filthy","grimy","sloppy"}, {"strong ","powerful ","mighty ","forceful ","sturdy "}, {"weak","feeble","frail","faint","flimsy"}, {"happy ","joyful ","cheerful ","glad ","delighted "},{"work ","job ","function "}}

9 Likes

it’s literally under the ESC button


I do agree with @MYOriginsWorkshop btw

7 Likes

Here is a picture of me testing this with my randomly generated characters,
:slight_smile:

7 Likes

When the bot doesn’t know the answer to the question you could return a random entry from its database.
The benefit to using this approach is it is all locally done and it relieves any API request you would do using OpenAI or other services.
You can get pretty good results if you think critically about how you construct your tables. the key to this is the synoymous phrase table. and the search query done checking the question with synonymous words and phrases.

You can easily add more databases to answer questions such as this when asking the bot “Who are you?”



7 Likes

For comparison this method is similar to how google ranks search results except this uses synonymous words and phrases to expand its understanding. After looking into neural networks it appears the neural networks determine their own algorithm. So coming up with a concrete human made algorithm is not an invalid approach. The main issue is combining knowledge and applying concepts. AI works in a very similar manner. But the tables are modified by the human responses. Anyway I wanted to contribute some more code to this project So I am releasing my wisdom database I use for my bot. This will greatly increases the responses you would recieve from the bot. The contents of this database is educational in nature about the universe and quotes from Sun Szus art of war.

wisdom={" Knowledge is the key to victory."," Do not let the darkness stop you on your quest."," If you have any more questions, feel free to ask."," I've been studying this world."," I'm sure you many questions will reveal themselves to you in time."," One of the best ways to learn is to try things out yourself. Explore as much as you can! You will find many mysteries to unravel.",
						" Adapt to the situation and you will find the way to victory.", " Do not let fear hold you back from your destiny.", " If you seek more wisdom, do not hesitate to ask.", " I have learned much from this world.", " I trust that you will discover many secrets in due time.", " The best teacher is experience. Go and explore the wonders of this world! You will encounter many challenges and opportunities.", " ", " Flow like water and adjust to the terrain you face.", " Achieve success by aligning yourself with the enemy’s intentions.", " Harness your energy and release it at the right moment.", " Emotions are fleeting, but consequences are lasting. A ruined kingdom cannot be restored, nor can the dead be revived.", " If you can provoke your enemy’s anger, you can make him lose his composure. Pretend to be weak, so he will become overconfident.", " In war, deception is your ally and you will prevail.", " If the enemy exposes a weakness, you must exploit it.", " We cannot form alliances until we know the plans of our neighbors.", " The seasoned soldier is always prepared and confident; he knows what to do before and after the battle.", " If you know your enemy and yourself, your victory is certain.", " The leader who excels in defense is hidden and secure; the leader who excels in attack is swift and surprising.", " The supreme leader follows the moral law, and adheres to method and discipline; thus he has the power to control success.", " Fake disorder implies perfect order; fake fear implies courage; fake weakness implies strength.", " Whoever arrives first and waits for the enemy, will be ready for the fight; whoever arrives second and rushes to battle, will be weary and exhausted.", " The quality of decision is like the swift strike of a falcon that destroys its prey."," Subdue your enemy without fighting.", " Deceive your enemy in warfare.", " Keep your plans secret and strike like lightning.", " Adapt to the situation and you will find the way to victory.", " Do not let fear hold you back from your destiny.", " If you seek more wisdom, do not hesitate to ask.", " I have learned much from this world.", " I trust that you will discover many secrets in due time.", " The best teacher is experience. Go and explore the wonders of this world! You will encounter many challenges and opportunities.", " ", " Flow like water and adjust to the terrain you face.", " Achieve success by aligning yourself with the enemy’s intentions.", " Harness your energy and release it at the right moment.", " Emotions are fleeting, but consequences are lasting. A ruined kingdom cannot be restored, nor can the dead be revived.", " If you can provoke your enemy’s anger, you can make him lose his composure. Pretend to be weak, so he will become overconfident.", " In war, deception is your ally and you will prevail.", " If the enemy exposes a weakness, you must exploit it.", " We cannot form alliances until we know the plans of our neighbors.", " The seasoned soldier is always prepared and confident; he knows what to do before and after the battle.", " If you know your enemy and yourself, your victory is certain.", " The leader who excels in defense is hidden and secure; the leader who excels in attack is swift and surprising.", " The supreme leader follows the moral law, and adheres to method and discipline; thus he has the power to control success.", " Fake disorder implies perfect order; fake fear implies courage; fake weakness implies strength.", " Whoever arrives first and waits for the enemy, will be ready for the fight; whoever arrives second and rushes to battle, will be weary and exhausted.", " The quality of decision is like the swift strike of a falcon that destroys its prey."," The universe is made of matter that makes us and light that sustains us.", " Dark energy rules the universe and it is expanding every day.", " Only 5% of the universe is made of atoms.", " Nearly three fourths of the universe is dark energy.", " In the midst of chaos, there is also opportunity.", " Quasars are the brightest objects in the universe. They are powered by supermassive black holes that devour matter and emit enormous amounts of energy.", " Pulsars are rapidly spinning neutron stars that emit beams of radiation like cosmic lighthouses. They can be used as precise clocks to measure time and space.", " Magnetars are a rare type of neutron star with extremely powerful magnetic fields. They can generate intense bursts of gamma rays and x-rays that can affect the whole galaxy.", " Black holes are regions of space where gravity is so strong that nothing can escape, not even light. They can warp space and time around them and create gravitational waves.", " Planets are celestial bodies that orbit a star and have enough mass to be spherical and clear their neighborhood of other objects. There are eight planets in our solar system, each with unique features and characteristics.", " Stars are massive balls of plasma that shine by nuclear fusion in their cores. They come in different sizes, colors, temperatures, and lifetimes. Our sun is a medium-sized yellow star that has been burning for about 4.6 billion years.", " Dwarf stars are small stars that have low mass and luminosity. They can be white, red, or brown, depending on their temperature and composition. White dwarfs are the remnants of dead stars that have shed their outer layers. Red dwarfs are the most common type of star in the galaxy and can live for trillions of years. Brown dwarfs are failed stars that never ignited fusion in their cores.", " The force which binds us to the Earth is gravity, which is proportional to the product of our mass and the Earth’s mass, and inversely proportional to the square of the distance between our centers.", " The revolution of the Moon around the Earth is due to gravity, which provides the centripetal force that keeps the Moon in its orbit.", " The revolution of planets around the Sun is also due to gravity, which balances the tangential velocity of the planets and prevents them from flying away.", " Tide arising due to the Moon and the Sun is caused by gravity, which varies with distance and creates a difference in gravitational pull on different parts of the Earth.", " Newton’s law of universal gravitation is a general physical law derived from empirical observations by Isaac Newton. It states that every particle attracts every other particle in the universe with a force that is proportional to the product of their masses and inversely proportional to the square of the distance between their centers.", " Newton’s law of universal gravitation has been superseded by Albert Einstein’s theory of general relativity, but it still continues to be used as an excellent approximation of the effects of gravity in most applications."," The universe is made of matter that makes us and light that sustains us.",
" Dark energy rules the universe and it is expanding every day.",
" Only 5% of the universe is made of atoms." ,
" Nearly three fourths of the universe is dark energy.",
" In the midst of chaos, there is also opportunity.",
						" Quasars are the brightest objects in the universe. They are powered by supermassive black holes that devour matter and emit enormous amounts of energy.", " Pulsars are rapidly spinning neutron stars that emit beams of radiation like cosmic lighthouses. They can be used as precise clocks to measure time and space.", " Magnetars are a rare type of neutron star with extremely powerful magnetic fields. They can generate intense bursts of gamma rays and x-rays that can affect the whole galaxy.", " Black holes are regions of space where gravity is so strong that nothing can escape, not even light. They can warp space and time around them and create gravitational waves.", " Planets are celestial bodies that orbit a star and have enough mass to be spherical and clear their neighborhood of other objects. There are eight planets in our solar system, each with unique features and characteristics.", " Stars are massive balls of plasma that shine by nuclear fusion in their cores. They come in different sizes, colors, temperatures, and lifetimes. Our sun is a medium-sized yellow star that has been burning for about 4.6 billion years.", " Dwarf stars are small stars that have low mass and luminosity. They can be white, red, or brown, depending on their temperature and composition. White dwarfs are the remnants of dead stars that have shed their outer layers. Red dwarfs are the most common type of star in the galaxy and can live for trillions of years. Brown dwarfs are failed stars that never ignited fusion in their cores."," The universe is all of space and time and their contents, including planets, stars, galaxies, and all other forms of matter and energy. The Big Bang theory is the prevailing cosmological description of the development of the universe. According to this theory, space and time emerged together 13.787±0.020 billion years ago, and the universe has been expanding ever since the Big Bang."," While the spatial size of the entire universe is unknown, it is possible to measure the size of the observable universe, which is approximately 93 billion light-years in diameter at the present day."," Some of the earliest cosmological models of the universe were developed by ancient Greek and Indian philosophers and were geocentric, placing Earth at the center."," Over the centuries, more precise astronomical observations led Nicolaus Copernicus to develop the heliocentric model with the Sun at the center of the Solar System. In developing the law of universal gravitation, Isaac Newton built upon Copernicus's work as well as Johannes Kepler's laws of planetary motion and observations by Tycho Brahe."," Further observational improvements led to the realization that the Sun is one of a few hundred billion stars in the Milky Way, which is one of a few hundred billion galaxies in the observable universe. Many of the stars in a galaxy have planets. At the largest scale, galaxies are distributed uniformly and the same in all directions, meaning that the universe has neither an edge nor a center. At smaller scales, galaxies are distributed in clusters and superclusters which form immense filaments and voids in space, creating a vast foam-like structure. Discoveries in the early 20th century have suggested that the universe had a beginning and that space has been expanding since then at an increasing rate."," According to the Big Bang theory, the energy and matter initially present have become less dense as the universe expanded. After an initial accelerated expansion called the inflationary epoch at around 10−32 seconds, and the separation of the four known fundamental forces, the universe gradually cooled and continued to expand, allowing the first subatomic particles and simple atoms to form. Dark matter gradually gathered, forming a foam-like structure of filaments and voids under the influence of gravity. Giant clouds of hydrogen and helium were gradually drawn to the places where dark matter was most dense, forming the first galaxies, stars, and everything else seen today."," From studying the movement of galaxies, it has been discovered that the universe contains much more matter than is accounted for by visible objects; stars, galaxies, nebulas and interstellar gas. This unseen matter is known as dark matter (dark means that there is a wide range of strong indirect evidence that it exists, but we have not yet detected it directly). The ΛCDM model is the most widely accepted model of the universe. It suggests that about 69.2%±1.2% of the mass and energy in the universe is dark energy which is responsible for the acceleration of the expansion of space, and about 25.8%±1.1% is dark matter. Ordinary ('baryonic') matter is therefore only 4.84%±0.1% of the physical universe. Stars, planets, and visible gas clouds only form about 6% of the ordinary matter."," There are many competing hypotheses about the ultimate fate of the universe and about what, if anything, preceded the Big Bang, while other physicists and philosophers refuse to speculate, doubting that information about prior states will ever be accessible. Some physicists have suggested various multiverse hypotheses, in which our universe might be one among many universes that likewise exist."," The physical universe is defined as all of space and time (collectively referred to as spacetime) and their contents. Such contents comprise all of energy in its various forms, including electromagnetic radiation and matter, and therefore planets, moons, stars, galaxies, and the contents of intergalactic space.","The universe also includes the physical laws that influence energy and matter, such as conservation laws, classical mechanics, and relativity."," The universe is often defined as the totality of existence, or everything that exists, everything that has existed, and everything that will exist. In fact, some philosophers and scientists support the inclusion of ideas and abstract concepts—such as mathematics and logic—in the definition of the universe. The word universe may also refer to concepts such as the cosmos, the world, and nature."," One of the most important principles underlying quantum physics is that of wave-particle duality. Quantum objects have both particle-like properties (such as mass, charge, and energy) and wave-like properties (such as wavelength and frequency). We can see this when we observe light traveling through a prism"," Another key principle is Heisenberg’s uncertainty principle, which states that there are limits to how accurately the value of a physical quantity can be predicted prior to its measurement, given a complete set of initial conditions. For example, we cannot know both the position and momentum of an electron with absolute precision. The more we know about one, the less we know about the other"," A third principle over quantum mechanics is overlap, which means that quantum objects can exist in more than one state at the same time, until they are measured. For example, an electron can be in two different orbitals around an atom, or a photon can be both horizontally and vertically polarized. This is described by a mathematical entity called the wave function, which provides information about the probability of finding the object in different states.",
						" A fourth principle is quantum entanglement, which means that two or more quantum objects can share a quantum state and influence each other, even when they are far apart. For example, two photons can be entangled such that measuring the polarization of one will instantly reveal the polarization of the other, regardless of the distance between them. This phenomenon has been called spooky action at a distance by Albert Einstein.",
						" Wave-particle duality principle states that quantum objects, such as electrons and photons, have both particle-like and wave-like properties. This means that they can behave like discrete units of matter or energy, or like waves that can interfere and diffract.",
						" One way to demonstrate wave-particle duality principle is by using the double-slit experiment. In this experiment, a beam of light or a stream of electrons is directed at a screen with two narrow slits. If the light or electrons were only particles, we would expect to see two bright spots on a detector behind the screen, corresponding to the two slits. However, what we actually observe is an interference pattern, with alternating bright and dark bands. This shows that the light or electrons have passed through both slits at the same time, as waves, and interfered with each other. However, if we try to measure which slit each photon or electron goes through, by placing a detector at each slit, we find that the interference pattern disappears. Instead, we see two bright spots again, as if the light or electrons were only particles. This shows that the act of measurement affects the behavior of the quantum objects, and collapses their wave function into a definite state.",
						" Wave-particle duality principle demonstrates how quantum objects can exhibit both particle-like and wave-like properties, depending on how they are observed. This principle challenges our classical intuition and reveals the nature of reality at the smallest scales.",
								" Heisenberg’s uncertainty principle states that there are limits to how accurately the value of a physical quantity can be predicted prior to its measurement, given a complete set of initial conditions. For example, we cannot know both the position and momentum of an electron with absolute precision. The more we know about one, the less we know about the other.",
								" Heisenberg’s uncertainty principle  is not because of any limitations of our instruments or methods, but because of the intrinsic nature of quantum objects. They do not have definite values for their properties until they are measured. Instead, they exist in a superposition of possible states, each with a certain probability. The wave function describes these probabilities, and when we measure a property, we collapse the wave function into one of the possible outcomes.",
								" Heisenberg’s uncertainty principle tells us how much information we can gain from a measurement, and how much we have to lose. It is often expressed as an inequality, which relates the uncertainties in two complementary properties, such as position and momentum, or energy and time. The product of these uncertainties cannot be lower than a certain constant, called Planck’s constant.",
								" With Heisenberg’s uncertainty principle the same trade-off applies to quantum measurements. If we measure the position of an electron with high precision, we disturb its momentum and introduce uncertainty in its velocity. If we measure the momentum of an electron with high precision, we disturb its position and introduce uncertainty in its location. We cannot measure both properties with arbitrary accuracy at the same time.",
								" Quantum 3rd principle of overlap which means that quantum objects can exist in more than one state at the same time, until they are measured. For example, an electron can be in two different orbitals around an atom, or a photon can be both horizontally and vertically polarized.",
								" Quantum 3rd principle of overlap is possible because quantum objects are described by wave functions, which are mathematical expressions that represent the probability of finding the object in different states. The wave function can be a combination of two or more basis states, which are the simplest possible states that the object can have. For example, the basis states for an electron’s spin can be up or down, and the basis states for a photon’s polarization can be horizontal or vertical.",
								" Concerning the quantum 3rd principle of overlap when the wave function is a combination of two or more basis states, it is called a superposition. This means that the object has some probability of being in each of the basis states, but not in any definite state. For example, an electron can have a 50% chance of being spin up and a 50% chance of being spin down, but not a definite spin value. A photon can have a 50% chance of being horizontally polarized and a 50% chance of being vertically polarized, but not a definite polarization.",
						" Quantum 3rd principle of overlap is why when we measure a property of a quantum object, such as its spin or polarization, we collapse the wave function into one of the basis states. This means that we force the object to choose one of the possible outcomes, and we lose the information about the other outcomes. For example, if we measure the spin of an electron and find it to be up, we no longer know what its spin was before the measurement. If we measure the polarization of a photon and find it to be horizontal, we no longer know what its polarization was before the measurement.",		
						" Clouds are collections of water droplets or ice crystals that float in the air. They form when water evaporates from the ground and condenses in the cooler air.",
						" Clouds can be very heavy and move fast with the wind and the jet stream. Clouds reflect the light of the sun and make it white. Clouds can also create different types of precipitation, such as rain, snow, hail, or sleet, depending on the temperature.",
						" Clouds generally form within the troposphere, or the layer of atmosphere closest to the earth. As they rise and fall, they may appear in infinite variations. Scientists have established three broad categories into which most clouds can be grouped: high clouds, mid-level clouds, and low clouds.",
						" Within each of these three tiers, scientists further organize clouds into ten broad categories based on the general shapes the clouds take are cirrus, cirrostratus, cirrocumulus, altocumulus, altostratus, nimbostratus, stratocumulus, stratus, cumulus, and cumulonimbus.",
						" Clouds are important for many reasons. Rain and snow are two of those reasons. At night, clouds reflect heat and keep the ground warmer. During the day, clouds make shade that can keep us cooler. Studying clouds helps NASA better understand Earth’s weather.",
						" Certain types of clouds produce precipitation. Clouds also produce the bolt of electricity called lightning and the sound of thunder that accompanies it. Lightning is formed in a cloud when positively charged particles and negatively charged particles are separated, forming an electrical field.",
						" Classical mechanics is the study of the motion of macroscopic objects under the influence of forces, such as gravity, friction, and tension. It includes topics such as kinematics, dynamics, statics, work, energy, momentum, rotation, oscillation, and fluid mechanics.",
						" Thermodynamics: the study of the relationships between heat, temperature, pressure, volume, and entropy in systems of matter and energy. It includes topics such as the laws of thermodynamics, heat transfer, phase transitions, thermal equilibrium, and statistical mechanics.",
						" Electromagnetism: the study of the electric and magnetic fields and forces generated by electric charges and currents. It includes topics such as electrostatics, magnetostatics, electrodynamics, Maxwell’s equations, electromagnetic waves, optics, and relativity.",
						" Quantum mechanics: the study of the behavior of matter and energy at the atomic and subatomic levels. It includes topics such as wave-particle duality, uncertainty principle, Schrödinger equation, quantum states, superposition principle, entanglement, tunneling effect, and quantum field theory.",
						" Relativity: the study of the effects of relative motion and gravity on space-time and matter-energy. It includes topics such as special relativity"," Special relativity is the theory of inertial frames of reference."," General relativity is the theory of gravitational fields."," Length contraction is the shortening of lengths in motion or in gravitational fields."," Mass-energy equivalence is the equivalence between mass and energy."," Gravitational redshift is the shift in frequency of light due to gravity."," Gravitational lensing the bending of light due to gravity."," Black holes are the regions of space-time where gravity is so strong that nothing can escape."," Gravitational waves are ripples in space-time caused by accelerating masses."," Cosmology is the study of the origin, structure, evolution, and fate of the universe as a whole."," Cosmology includes topics such as the big bang theory.",
						" The big bang theory is the model that describes the initial state and expansion of the universe.",
						" Cosmic inflation is the rapid exponential expansion of space-time in the early universe.",
						" Cosmic microwave background radiation (the remnant thermal radiation from the early universe.",
						" Dark matter is the invisible matter that accounts for most of the mass in the universe.",
						" Dark energy is the mysterious force that causes the accelerated expansion of the universe",
						" The Cosmological constant is the energy density of empty space.",
						" The Cosmological horizon is the limit of observable distance in the universe.",
						" Hubble’s law is the relation between distance and recession velocity of galaxies.",
						" Cosmic nucleosynthesis is the formation of elements in the early universe.",
						" Stellar evolution is the life cycle of stars from birth to death.",
						" Supernovae are the explosive death of massive stars.",
						" Neutron stars are the dense remnants of supernovae.",
						" Pulsars are rotating neutron stars that emit beams of radiation.",
						" Quasars are extremely bright sources of radiation powered by supermassive black holes at the centers of galaxies.",
						" Galaxy formation and evolution is described as the processes that shape galaxies over time and large-scale structure is the distribution and clustering of matter on cosmic scales.",
						" The cosmic web is described as the network-like pattern formed by filaments and voids in large-scale structure."



					}```
2 Likes

Here is the start of a database for different personalities.

local AdvanceObjective="the Castle"
local KnightDatabase={"The king has ordered us to advanced upon "..AdvanceObjective.." at dawn! Be prepared to advance!", "Rumors? What do you think I am some barmaid?! Away with you before you test my patience.", 
" Aye, theirs a blacksmith in town somewhere.", "The baker sells all sorts of food items.", 
"The forest is full of dangers. Beware of wolves and bandits.",
 "Have you seen the princess? The king has us on guard.", 
"We are loyal to the king and his cause. Do not speak ill of him or his allies.",
 "You look like a capable fighter. Have you considered joining the Kings army?",
 "The tavern is a good place to rest and hear some stories.",
 "The healer can mend your wounds and cure your ailments."}

local PesantDatabase={"What say ye adventurer? would you be interested in helping with the harvest?",
 "The taxes keep on rising… The king has recruited soo many for the campaign.",
 "Theirs pests in my garden running amock!",
 "I have nothing to offer you but my gratitude.", 
"Please, spare some coins for a poor soul.", 
"The lord of the manor is a cruel and greedy man. He cares not for us common folk.", 
"Have you heard of the prophecy? They say a hero will come and save us from the evil.",
 "I wish I could see the world beyond this town. But I have no money or skills to travel.",
 "My son has gone missing. I fear he may have been taken by the enemy.",
 "The harvest has been good this year. We have plenty of food to share."}
3 Likes

This is pretty cool!

Do you have a demo place for us to try out this model?

4 Likes

I want to share a related resource for creating questions. Here is an example of combining 3 sentence fragments to get over 5500 different possible dialogue texts. I shared this with someone asking about ideas for differents quests. So I wanted to include it here as a resource pertaining to the above topic non AI driven language models. the benefit of this is very fast processing time. The whole script is only 14.9kbs.

Opening = {"Please would you assist me adventurer,","I have a task to ask of you,","Their is something I need,","So,","I have this thing,","I need a favor,","I have a quest for you,","I have a request,","I have something I need taken care of,","I could use your help, adventurer,","I have a mission for you,","There is something I want,","Listen,","I have this problem,","I need a hand,","I have a quest for you,","I have a proposition,","I have something I need done,"}
	request= {" will you obtain for me " ," will you retreive "," will you collect "," will you bring me "," I'm in need of  "," bring me ", " I need ", " I require ", "I would like "," can you get me " ," can you find "," can you gather "," can you deliver me "," I'm looking for  "," fetch me ", " I need ", " I demand ", "I desire "}
	closing= {"I will reward you a ","Your prize will be a ","In exchange I'll give you a ","Your reward will be a ", "I will reward you handsomely with a ","I can offer you in return this ",
		"In exchange for your services, I will reward you with a "," I can offer you this as a reward, it's a ","I will give you a ","Your reward will be a ","In return I'll offer you a ","Your prize will be a ", "I will pay you well with a ","I can give you this in exchange, it's a ",
		"For your service, I will grant you a "," I can reward you with this, it's a "}
	--closing= {
QNPC2=NPCName
QEvent2=Quests.Event
QQuantity2=Quests.Quantity
QID2=Quests.ItemID
QReward2=Quests.Rewards
	CollectionQuestDescription=""..Opening[mathrandom(1,#Opening)]..""..request[mathrandom(1,#request)].." "..QQuantity2.Value.." "..QID2.Value..". "..closing[mathrandom(1,#closing)]..""..QReward2.Value.."."
2 Likes

In celebration of 1000 views on this thread I have another update for the algorithm

  -- Introductory
  {
    "Let me begin by saying,", "First of all,", "To start with,", "As an introduction,",
    "To kick things off,", "To get the ball rolling,", "First things first,"
  },

  -- Continuation
  {
    "Moving forward,", "Looking ahead,", "Building on that,", "Expanding on that idea,",
    "Carrying on with that train of thought,", "Following up on what was just said,", "Proceeding with this theme,"    
  },

  -- Clarification
  {
    "Or rather,", "On second thought,", "I should clarify,", "Let me rephrase that,",
    "Actually, to be more precise,", "To put it more accurately,", "What I really meant was,"
  },

  ...

  -- Examples
  {
    "For example,", "As an illustration,", "To give an example,", "Specifically,", "In particular,",
    "To name one,", "Such as,", "Including,", "As a case in point,"
  },

  ...

  -- Contrast
  {
    "However,", "On the other hand,", "In contrast,", "On the contrary,", "Conversely,",
    "Alternatively,", "Meanwhile,", "Instead,", "But,"
  },

  -- Punctuation
  {
    "Furthermore,", "Therefore,", "Finally,", "Indeed,", "Basically,", "Frankly,",  
    "Generally,", "Specifically,", "Additionally,", "Essentially,"
  },

  -- Opinions
  {
    "I believe,", "In my opinion,", "From my perspective,", "If you ask me,", "I think,"
  },

  -- Agreeing
  {
    "I agree,", "Yes,", "Definitely,", "For sure,", "No doubt,"    
  },

  -- Disagreeing 
  {
    "I disagree,", "No,", "I don't think so,", "I'm not so sure about that,", "I have doubts,"
  },

  -- Asking for opinions
  {
    "What do you think?,", "What is your take?,", "I'm curious to hear your thoughts,", "What's your perspective?", "I'd like your insight,"
  },

  -- Giving suggestions
  {
    "I would suggest,", "Maybe you could,", "You might try,", "Have you considered,", "Perhaps,"
  },

  -- Appreciation
  {
    "I appreciate that,", "Thank you for sharing,", "I am grateful for your perspective,", "I value your input," 
  },

  -- Understanding
  {
    "I understand,", "That makes sense,", "I see where you are coming from,", "I can relate to your view,"
  },

  -- Partial agreement
  {
    "I somewhat agree,", "You have a point, but,", "While I see some validity to that,", "I agree, with some caveats,"
  },
  
  -- Emotional support
  {
    "I'm here for you,", "You're not alone in this,", "It's understandable to feel that way,", "This too shall pass,", "Better times are ahead,"
  } 
local morePhrases = {

  -- Hedging certainty
  {
    "It seems,", "It appears,", "Apparently,", "Presumably,", "Most likely,", "Chances are,"    
  },

  -- Seeking confirmation
  {
    "Does that make sense?,", "Do you follow?,", "Does that resonate?,", "Does this align?,", "Does this land?,"
  },

  -- Seeking agreement
  {
    "Don't you think?,", "Wouldn't you say?,", "You'd agree?,", "Right?,", "Yeah?,"
  },

  -- Encouraging
  {
    "Keep at it!,", "You can do it!,", "Stay strong!,", "Keep persevering!,", "Keep up the great work!,"
  },

  -- Praising
  {
    "Well done!,", "Great job!,", "Kudos to you!,", "You should be proud!,", "Wonderfully executed!,"
  },

  -- Light humor
  {
    "Funny you should say that!,", "The irony is not lost on me!,", "What a hilarious sentiment!,", "The humor is not wasted on me!,", "Such amusing thoughts!,"
  },

  -- Wordless acknowledgment
  {
    "I see,", "Ah,", "Oh,", "Hmm,", "Aha,", "Okay,"    

  -- Science
  {
    "According to scientific research,", "Studies have shown that,", "The data suggests,", "Experiments demonstrate,", 
    "There is scientific evidence that,", "Research indicates,", "Analysis reveals,", "The findings confirm that,",
    "Extensive peer-reviewed studies confirm,", "Comprehensive meta-analyses conclude that,",
    "Statistical models predict,", "Simulations support the hypothesis that,",
  },
  
  -- Technology
  {
    "This technology utilizes,", "The system is powered by,", "The architecture includes,", "The framework leverages,",
    "At the core is,", "The platform incorporates,", "The software implements,", "The algorithm enables,",
    "The hardware configuration consists of,", "The network infrastructure relies on,",
    "Latency is optimized by,", "Scalability is achieved through,"
  },

  -- Academia
  {
    "Scholars have theorized,", "There are competing schools of thought,", "Research indicates,",
    "The field is increasingly focused on,", "Experts have concluded,", "Prominent academics posit that,",
    "Evidence suggests,", "The literature supports,",
    "Leading researchers have demonstrated,", "Academic consensus holds that,", 
    "Data analysis strongly supports,", "The weight of empirical evidence favors,"
  },  

  -- History
  {
    "Historians note that,", "Records suggest,", "Accounts of the time describe,", "Evidence from the era demonstrates,",
    "Archaeology reveals,", "Primary sources show,", "Scholarly analysis reveals,", "Historical precedent indicates,",
    "Letters and diaries from the period indicate,", "Contemporary perspectives establish that,",
    "Interpretations of material evidence suggest,"
  },

  -- General
  {
    "It is clear that,", "We can determine that,", "Evidence confirms,", "There are strong indications that,",
    "Available information reliably shows,", "Credible sources lead to the conclusion that,", "It follows logically that,",
    "Applying rigorously skeptical analysis shows that,", "There is significant verifiable data to demonstrate that,",
    "Any examination of the facts definitively proves that,"
  }
 local morePhrases = {

  -- Transitioning topics
  {
    "On another note,", "Changing topics,", "Moving to another subject,", "Switching gears,", 
    "Let's discuss something else for a moment,", "I'd like to talk about something different now,",
    "Shifting focus,", "Turning to another matter,", "Jumping to a new topic,"
  },  

  -- Encouraging participation
  {
    "What are your thoughts?", "I'd love to hear your perspective,", "Please feel free to chime in,",
    "Don't be shy, your point of view is valuable,", "Speak up, I want your input,",
    "Your voice matters here - please share your ideas,", "Help me understand your position - I'm listening,"
  },

  -- Validating feelings
  {
    "Your feelings are completely valid,", "It's understandable to feel that way,", "I can see why you would feel like that,",
    "That would make anyone feel the same way,", "You have every right to feel that way,",
    "I don't blame you for feeling that way,", "Your reaction makes perfect sense,"
  },

  -- Reassurance
  {
    "It will be okay,", "This will pass in time,", "Things will get better,", "Have faith, the future is bright,",
    "Stay positive, you have the strength to get through this,", "Brighter days are ahead,", 
    "Hard times are temporary, better things are coming,"
  },
   
  -- Asking for repetition
  {
    "Sorry, could you repeat that?,", "My apologies, I didn't quite get that - could you restate?,",
    "Please say that again,", "Pardon me, what was that?", "I'm afraid I didn't catch that, could you repeat?",
    "One more time please?,", "Let me hear that again if you don't mind,"
  },

  -- Clarifying confusion
  {
    "I'm afraid I'm a bit confused,", "You seem to have lost me there,", "Let me make sure I understand correctly,",
    "I want to make sure I'm not missing something - ", "Just to clarify, what do you mean exactly?",
    "You'll have to help me understand what you're saying - ", "I'm trying to follow but got a bit lost - "
  },

  -- Hedging opinions
  {
    "I might be wrong, but,", "Don't quote me on this, but,", "Take this with a grain of salt, but,", 
    "In my limited understanding,", "Without claiming to be an expert,",
    "I could be off base, but,", "I'm no authority, however,", "I'm far from an expert, so," 
  }
  "knowledgeable ", "educated ", "learned ", "expert ", "skilled ", "familiar "},
{ "smoothly ", "effortlessly ", "seamlessly ", "gracefully ", "easily ", "pleasantly "},
{ "faring ", "progressing ", "coping ", "managing ", "doing ", "performing "},
{ "ditches ", "trenches ", "gutters ", "channels ", "holes ", "cavities "},
{ "careful ", "prudent ", "vigilant ", "attentive ", "mindful ", "wary "}
,
{ "events ", "incidents ", "happenings ", "phenomena ", "circumstances ", "scenarios "}
,
{ "Did you know ", "Are you aware ", "Do you know ", "Have you learned ", "Are you familiar "}
,
{ "trapped ", "confined ", "imprisoned ", "enclosed ", "cornered ", "snared "}
,
{ "happening ", "taking place ", "transpiring ", "occurring ", "unfolding "}
,
{ "mindless", "thoughtless", "brainless", "unthinking", "senseless", "vacant"}
,
{ "used", "utilized", "employed", "applied", "exploited", "harnessed"}
,
{ "touches", "contacts", "reaches", "feels", "grazes", "strokes"}
,
{ "feeling", "doing", "being", "faring", "coping", "managing"}
,
{ "infinite", "unlimited", "boundless", "endless", "eternal", "immense"}
,
{ "treasures", "trinkets", "artifacts", "loot, "spoils, "riches"}
{ "destructive", "damaging", "harmful", "ruinous", "devastating", "catastrophic"}
,
{ "absorb", "assimilate", "take in", "soak up", "ingest", "incorporate"}
,
{ "However,", "Nevertheless,", "Nonetheless,", "Yet,", "Still,", "But,"}
,
{ "encounter", "meet", "face", "confront", "come across", "run into"}
,
{ "trap", "snare", "trap", "lure", "ambush", "ensnare"}
,
{ "minion", "follower", "servant", "henchman", "underling", "subordinate"}
{ "conjunction", "combination", "union", "connection", "link", "relation"}
,
{ "dimension", "realm", "world", "plane", "space", "zone"}
,
{ "regenerate", "recuperate", "recover", "heal", "renew"}
,
{ "topic", "subject", "issue", "matter", "question"}
,
{ "entities", "creatures", "beings", "organisms", "forms", "things"}
{ "warp", "distort", "twist", "bend", "deform", "contort"}
,
{ "strong", "powerful", "mighty", "forceful", "intense", "potent"}
,
{ "facts", "information", "data", "evidence", "truths", "realities"}
,
{ "infinite", "unlimited", "boundless", "endless", "eternal", "immense"},
{ "given", "bestowed", "granted", "awarded", "presented", "conferred"}
,
{ "quantity", "amount" ,"measure"}
,
{ "quantities", "amounts" "measures"}
}
4 Likes

Today I am researching using APIs and I have successfully given this bot the ability to use wikipedia to answer questions it does not know the answer to. I wrote this with the help of ChatGPT we had a back and forth and eventually we were able to figure out ohw to access summaries and entire articles on wikipedia in text form. :slight_smile: If you would like to try out this interesting code it will work as is.

local HttpService = game:GetService("HttpService")

local function SearchWikipedia2(searchq)
	local url = "https://en.wikipedia.org/w/rest.php/v1/search/page?q="
	-- Define the query parameters
	-- Make the request and get the response
	local success, response = pcall(function()
		return HttpService:RequestAsync({
			Url = url..searchq
			--	Method = "GET",
			--Query = params -- Pass the query parameters as a table
		})
	end)

	-- Check if the request was successful
	if success then
		-- Check if the response status code was 200 (OK)
		if response.StatusCode == 200 then
			-- Parse the response body as JSON
			local data = HttpService:JSONDecode(response.Body)

			-- Get the first item from the result list
			local item = data.pages[1]

			-- Extract the title and text from the item
			local title = item.title
			local excerpt = item.excerpt
			local pattern = "<span class=\"searchmatch\">(.-)</span>"

			-- Replace the HTML tags with empty strings
			local text = excerpt:gsub(pattern, "%1")

			-- Print the title and text to the output
			print(title)
			print(text)

			-- Extract the key from the item
			local key = item.key

			-- Construct the article URL from the key and the base URL
			local base_url = "https://en.wikipedia.org/w/api.php?action=query&prop=extracts&exintro&explaintext&titles="
			local article_url = base_url .. key.."&format=json"

			-- Print the article URL to the output
			print(article_url)

			-- Make another request to get the article content
			local success, response = pcall(function()
				return HttpService:RequestAsync({
					Url = article_url,
					Method = "GET"
				})
			end)

			-- Check if the request was successful
			if success then
				-- Check if the response status code was 200 (OK)
				if response.StatusCode == 200 then
					-- Parse the response body as JSON
					
					-- Access the extract property of the JSON object
					local data = HttpService:JSONDecode(response.Body)

					-- Access the pages table of the JSON object
					local pages = data.query.pages

					-- Use the pairs function to iterate over the pages table
					for key, value in pairs(pages) do
						-- Get the page key and the extract from each subtable
						local page_key = key
						local extract = value.extract

						-- Print the page key and the extract to the output
						--print(page_key)
						print(extract)
					end
					print(data)
					-- Print the extract to the output
					--print(extract)
				else
					-- Print the response status code and status message to the output
					print("Error: " .. response.StatusCode .. " " .. response.StatusMessage)
				end
			else
				-- Print the error message to the output
				print("Error: " .. response)
			end
			
		end 
	end
	end




SearchWikipedia2("What is an archer?")
1 Like

I have given the bot the ability to learn from APIs and artificial intelligence models. Here’s some insight for how I parse data from wikipedia. First I filter out bad words by reading the exerpt for the page the search query leads to. If the exerpt contains offensive content it checks the next page and so on or returns nil and progresses with the stack. But since strings are soo long I parse them into paragrphas by the punctuation and 500 character limit. Then search the sections for the best result. Each API uses a different datastore key. The saved data pairs up with responses. Like AI models. This will be important as the bot learns from its interactions and to also scale it’s usage while also minimizing API access

I also have improved the accuracy of the bot. By getting the best result for each database then putting them into a table and searching the results for the best match. I created this solution because as the databases sizes increases the top of the stack often returns first. This is a new issue with the modularization.

Future plans are to make the bot more context aware by extracting keywords from the context of the conversation.

3 Likes

I have created an emoji insertion algorithm using the synonymous phrase table and by using a new method of scoring strings based on their pattern matching score. This is a open world usage of this algorithm. It’s very fast! Unlike regular AI. But the gui is adorned to the character locally and when it accesses APIs or artificial intelligence models it uses a remote event to trigger the query wait for the response.
This generates the text character by character and parses the response by sentences for readability





image

3 Likes

Today I’m working on making the AI aware of it’s surroundings! It’s very interesting this is what it looks like so far. The goal is to construct a database of descriptive strings of the surroundings and a paragraph describing the entire scene. It’s a work in progress. The final version I’m going to attempt to make it describe things from closest to farthest. I’m creating this module to give this AI the ability to set goals interact with other AIs and explore its surroundings. Ultimately this is also for a NPC that follows you around as your ally and could provide useful data to the player and any language model that wishes to give real time commentary on its surroundings.
I was inspired by this youtube video :slight_smile:

local aware = {}
function aware.GetCombatDescription(Char)
	local MagicID=Char:FindFirstChild("MagicID")
	if MagicID~=nil then
		local fly=""
		local Aggression=""
		local AttackVector=""
		local Barrier=""
		local Buffs=""
		local BaseHealth=""
		local BaseMagicDMG=""
		local BaseRangeDMG=""
		local BaseMeleeDMG=""
		local CanBeFrozen=""
		local ChangeStyles=""
		local Cooldown=""
		local Cost=""
		local CostMax=""
		local Cure=""
		local Description=""
		local Dodge=""
		local Element=""
		local Element2=""
		local Element3=""
		local Hide=""
		local Level=""
		local MainStyle=""
		local Multiply=""
		local Paralyze=""
		local Poison=""
		local Power=""
		local Prayer=""
		local ProtectFromStyle=""
		local Recoil=""
		local Range=""
		local Parasite=""
		local Species=""
		local Teleport=""
		local Transform=""
		local Weakness=""
		--construct a long combined string of the above local strings.

		if MagicID:GetAttribute("Aggression")==1 then
			Aggression="aggressive, "
		end
		if MagicID:GetAttribute("Fly")==true then
			fly="can Fly, "
		end
		if MagicID:GetAttribute("Barrier")==true then
			Barrier="uses Barrier, "
		end
		if MagicID:GetAttribute("Buffs")==true then
			Buffs="uses Buffs, "
		end
		if MagicID:GetAttribute("Multiply")==true then
			Buffs="uses Multiply, "
		end
		if MagicID:GetAttribute("ChangeStyle")==true then
			ChangeStyles="melee and magic user, "
			BaseMagicDMG="base Magic DMG:"..tostring(MagicID:GetAttribute("BaseMagicDMG"))..", "
			BaseMagicDMG="base Melee DMG:"..tostring(MagicID:GetAttribute("BaseMeleeDMG"))..", "
			if MagicID:GetAttribute("AttackVector3")~=nil then
				AttackVector="Melee Range:"..tostring(MagicID:GetAttribute("AttackVector3"))..", "
			end	
			--if MagicID:GetAttribute("MainStyles")~=nil then
			--	if MagicID:GetAttribute("MainStyles")==1 then
			--		MainStyle="Melee focused, "
			--	elseif MagicID:GetAttribute("MainStyles")==2 then
			--		MainStyle="Magic focused, "
			--	elseif MagicID:GetAttribute("MainStyles")==3 then
			--		MainStyle="Range focused, "
			--	end
			--end 

		elseif MagicID:GetAttribute("ChangeStyle")==false then
			if	MagicID:GetAttribute("MainStyles")~=nil then
				if MagicID:GetAttribute("MainStyles")==1 then
					MainStyle="Melee only, "
					if MagicID:GetAttribute("AttackVector3")~=nil then
						AttackVector="Melee Range:"..tostring(MagicID:GetAttribute("AttackVector3"))..", "
					end	
				elseif MagicID:GetAttribute("MainStyles")==2 then
					MainStyle="Magic only, "
				elseif MagicID:GetAttribute("MainStyles")==3 then
					MainStyle="Range only, "
				end
			end
		end	

		if MagicID:GetAttribute("BaseHealth")~=nil then
			BaseHealth="Base Health "..tostring(MagicID:GetAttribute("BaseHealth"))..", "
		end
		--write code to complete above context
		if MagicID:GetAttribute("CanBeFrozen")==false then
			CanBeFrozen="cannot be Frozen, "
		end
		if MagicID:GetAttribute("Cooldown")~=nil then
			Cooldown="Cooldown:"..tostring(MagicID:GetAttribute("Cooldown"))..", "
		end
		if MagicID:GetAttribute("Cost")~=nil then
			Cost="Power Cost:"..tostring(MagicID:GetAttribute("Cost"))..", "
		end
		if MagicID:GetAttribute("CostMax")~=nil then
			CostMax="Max Power:"..tostring(MagicID:GetAttribute("CostMax"))..", "
		end
		if MagicID:GetAttribute("Cure")==true then
			Cure="can Heal, "
		end
		if MagicID:GetAttribute("Description")~=nil then
			Description=MagicID:GetAttribute("Description")..""
		end
		if MagicID:GetAttribute("Dodge")==true then
			Dodge="can Dodge, "
		end
		if MagicID:GetAttribute("Teleport")==true then
			Teleport="can Teleport, "
		end
		if MagicID:GetAttribute("Transform")==true then
			Transform="can Transform, "
		end

		if MagicID:GetAttribute("Element")~=nil and MagicID:GetAttribute("Element")~="" then
			Element=" /"..MagicID:GetAttribute("Element")
			if MagicID:GetAttribute("Element2")~="" and MagicID:GetAttribute("Element2")~=nil then
				Element2="/"..MagicID:GetAttribute("Element2")
			end
			if MagicID:GetAttribute("Element3")~="" and MagicID:GetAttribute("Element2")~=nil then
				Element3="/"..MagicID:GetAttribute("Element3")
			end	
		end
		if MagicID:GetAttribute("Parasite")==true then
			Parasite="Parasitic, "
		end
		if MagicID:GetAttribute("Poison")==true then
			Poison="Poisonous, "
		end

		if MagicID:GetAttribute("Prayer")==true then
			Prayer="uses Prayers, "
		elseif 	MagicID:GetAttribute("ProtectFromStyle")==1 then
			ProtectFromStyle="strong against Melee, "
		elseif		MagicID:GetAttribute("ProtectFromStyle")==2 then
			ProtectFromStyle="strong against Magic, "
		elseif		MagicID:GetAttribute("ProtectFromStyle")==3 then
			ProtectFromStyle="strong against Range, "
		end
		--Power="Power Multiplier:" MagicID:GetAttribute("Power")
		--Range=""
		if MagicID:GetAttribute("Recoil")==true then
			Recoil="hurts to touch, "
		end

		--write rest of code for above context	
		return Description..Element..Element2..
			Element3.." Type."..Level..ChangeStyles..MainStyle..Cooldown..fly..Aggression..Barrier..Buffs..BaseHealth..
			BaseMagicDMG..BaseRangeDMG..BaseMeleeDMG..AttackVector..CanBeFrozen..
			Cost..CostMax..Cure..Dodge..
			Hide..Multiply..Paralyze..Poison..Power..
			Prayer..ProtectFromStyle
	end
end


function aware.DescribeNPC(Char)
	local MagicID=Char:FindFirstChild("MagicID")
	if MagicID~=nil then
		local fly=""
		local Aggression=""
		local AttackVector=""
		local Barrier=""
		local Buffs=""
		local BaseHealth=""
		local BaseMagicDMG=""
		local BaseRangeDMG=""
		local BaseMeleeDMG=""
		local CanBeFrozen=""
		local ChangeStyles=""
		local Cooldown=""
		local Cost=""
		local CostMax=""
		local Cure=""
		local Description=""
		local Dodge=""
		local Element=""
		local Element2=""
		local Element3=""
		local Hide=""
		local Level=""
		local MainStyle=""
		local Multiply=""
		local Paralyze=""
		local Poison=""
		local Power=""
		local Prayer=""
		local ProtectFromStyle=""
		local Recoil=""
		local Range=""
		local Parasite=""
		local Species=""
		local Teleport=""
		local Transform=""
		local Weakness=""
		local rating=0
		--construct a long combined string of the above local strings.

		if MagicID:GetAttribute("Aggression")==1 then
			Aggression="aggressive, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Fly")==true then
			fly="can Fly, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Barrier")==true then
			Barrier="uses Barrier, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Buffs")==true then
			Buffs="uses Buffs, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Multiply")==true then
			Buffs="uses Multiply, "
			rating=rating+1
		end
		if MagicID:GetAttribute("ChangeStyle")==true then
			ChangeStyles="melee and magic user, "
			rating=rating+1
			BaseMagicDMG="base Magic damage is"..tostring(MagicID:GetAttribute("BaseMagicDMG"))..", "
			BaseMagicDMG="base Melee damage is"..tostring(MagicID:GetAttribute("BaseMeleeDMG"))..", "
			if MagicID:GetAttribute("AttackVector3")~=nil then
				AttackVector="melee range is"..tostring(MagicID:GetAttribute("AttackVector3"))..", "
			end	
		elseif MagicID:GetAttribute("ChangeStyle")==false then
			if	MagicID:GetAttribute("MainStyles")~=nil then
				if MagicID:GetAttribute("MainStyles")==1 then
					MainStyle="uses Melee only, "
					if MagicID:GetAttribute("AttackVector3")~=nil then
						AttackVector="melee range:"..tostring(MagicID:GetAttribute("AttackVector3"))..", "
					end	
				elseif MagicID:GetAttribute("MainStyles")==2 then
					MainStyle="uses Magic only, "
				elseif MagicID:GetAttribute("MainStyles")==3 then
					MainStyle="uses Range only, "
				end
			end
		end	

		if MagicID:GetAttribute("BaseHealth")~=nil then
			local hpr=Char.Humanoid.MaxHealth/100
			rating=rating+hpr
			BaseHealth="base health "..tostring(MagicID:GetAttribute("BaseHealth"))..", "
		end
		--write code to complete above context
		if MagicID:GetAttribute("CanBeFrozen")==false then
			CanBeFrozen="cannot be frozen, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Cooldown")~=nil then
			Cooldown="it's cooldown is "..tostring(MagicID:GetAttribute("Cooldown"))..", "
			rating=rating+(5-MagicID:GetAttribute("Cooldown"))
		end
		if MagicID:GetAttribute("Cost")~=nil then
			Cost="it's action cost is "..tostring(MagicID:GetAttribute("Cost"))..", "
			rating=rating+1
		end
		if MagicID:GetAttribute("CostMax")~=nil then
			CostMax="It's max power is"..tostring(MagicID:GetAttribute("CostMax"))..", "
		end
		if MagicID:GetAttribute("Cure")==true then
			Cure="can Heal, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Description")~=nil then
			Description=MagicID:GetAttribute("Description")..""
		end
		if MagicID:GetAttribute("Dodge")==true then
			Dodge="can Dodge, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Teleport")==true then
			Teleport="can Teleport, "
			rating=rating+1
		end
		if MagicID:GetAttribute("Transform")==true then
			Transform="can Transform, "
			rating=rating+1
		end

		if MagicID:GetAttribute("Element")~=nil and MagicID:GetAttribute("Element")~="" then
			Element="uses "..MagicID:GetAttribute("Element")
			rating=rating+1
			if MagicID:GetAttribute("Element2")~="" and MagicID:GetAttribute("Element2")~=nil then
				Element2=","..MagicID:GetAttribute("Element2")
				rating=rating+1
			end
			if MagicID:GetAttribute("Element3")~="" and MagicID:GetAttribute("Element2")~=nil then
				Element3="and "..MagicID:GetAttribute("Element3")
				rating=rating+1
			end	
		end
		if MagicID:GetAttribute("Parasite")==true then
			Parasite=", it's parasitic"
			rating=rating+1
		end
		if MagicID:GetAttribute("Poison")==true then
			Poison=", it's poisonous"
			rating=rating+1
		end

		if MagicID:GetAttribute("Prayer")==true then
			Prayer="uses Prayers"
			rating=rating+1
		elseif 	MagicID:GetAttribute("ProtectFromStyle")==1 then
			rating=rating+1
			ProtectFromStyle=", strong against Melee"
		elseif		MagicID:GetAttribute("ProtectFromStyle")==2 then
			rating=rating+1
			ProtectFromStyle=", strong against Magic"
		elseif		MagicID:GetAttribute("ProtectFromStyle")==3 then
			rating=rating+1
			ProtectFromStyle=", strong against Range"
		end
		--Power="Power Multiplier:" MagicID:GetAttribute("Power")
		--Range=""
		if MagicID:GetAttribute("Recoil")==true then
			rating=rating+1
			Recoil="hurts to touch, "
		end
		rating=rating+tonumber(Level)
		--write rest of code for above context	
		return Description..Element..Element2..
			Element3.." magic. It's "..Level.." "..ChangeStyles..MainStyle..Cooldown..fly..Aggression..Barrier..Buffs..BaseHealth..
			BaseMagicDMG..BaseRangeDMG..BaseMeleeDMG..AttackVector..CanBeFrozen..
			Cost..CostMax..Cure..Dodge..
			Hide..Multiply..Paralyze..Poison..Power..
			Prayer..ProtectFromStyle..".",aware.judgepower(rating,25)
	else return "",nil	
	end
end
	local function tablehandler(location)
		-- Get the folder from the workspace
		local tableobj={}
		local mapObjectsFolder = location
		-- Check if the folder exists
		if mapObjectsFolder then
			-- Loop through the objects in the folder
			for _, obj in pairs(mapObjectsFolder:GetChildren()) do
				-- Add them to the stable
				table.insert(tableobj, obj)
			end
			-- Connect a function to the ChildAdded event of the folder
			mapObjectsFolder.ChildAdded:Connect(function(child)
				-- Add the new object to the stable
				table.insert(tableobj, child)
			end)
			-- Connect a function to the ChildRemoved event of the folder
			mapObjectsFolder.ChildRemoved:Connect(function(child)
				-- Find the index of the removed object in the stable
				local index = table.find(tableobj, child)
				-- Remove it from the stable
				table.remove(tableobj, index)
			end)
		end
		-- Return the stable
		return tableobj
	end

	-- Call the function and assign it to a variable
	mapObjects = tablehandler(workspace.MapObjects)
	plants = tablehandler(workspace.Plants)
	enemys=tablehandler(workspace.Enemys)
	rubble = tablehandler(workspace.Rubble)
	trees=tablehandler(workspace.Trees)
	chests=tablehandler(workspace.Chests)
	grounditems = tablehandler(workspace.grounditems)
	houses=tablehandler(workspace.Houses)
	playerstable=tablehandler(game.Players)
	dungeons=tablehandler(workspace.DungeonRender)
npcs = tablehandler(workspace.NPCS)
function getnearest(list,pos,dist,getone)
	local list=list
	local torso = nil
	local dist = 30
	local temp = nil
	local human = nil
	local temp2 = nil
	local amnt=0
	local scope=nil
	local list=list	
	if list~=nil then
		for x = 1, #list do
			temp2 = list[x]
			if temp2:IsA("BasePart") then
				temp = temp2
			elseif temp2:IsA("Model") then
				if temp2.PrimaryPart~=nil then
					temp=temp2.PrimaryPart
				else 
					temp=temp2:FindFirstChildOfClass("BasePart")	
				end	
			elseif temp2:IsA("Folder") then
				local m=temp2:FindFirstChildOfClass("Model")
				if m then
					temp=m:FindFirstChildOfClass("BasePart")
				end	
			end
			if (temp ~= nil)  then
				if (temp.Position - pos).magnitude < dist then
					amnt=amnt+1
					torso = temp2
					dist = (temp.Position - pos).magnitude
					scope = temp.Size
					if getone==true then
						return torso,scope
					end
				end
			end
		end
	end
	return torso,amnt,scope
end

function aware.judgedistance(position, position2, maxDist)

	local distVector = (position - position2).Magnitude

	local judgedDist = {0.2, 0.4, 0.6, 0.8, 1, 1.5, 2} 
	local judgeStrings = {"very close", "close", "kind of close","not far", "kinda far", "far", "very far"}

	local index = 1
	local distanceJudge = ""
	repeat
		if distVector <= maxDist * judgedDist[index] then
			distanceJudge = judgeStrings[index]
			break
		end
		index = index + 1
	until index > #judgedDist

	-- Get direction
	local dirVector = (position2 - position).Unit -- Unit vector pointing to position2
	local angle = math.atan2(dirVector.Z, dirVector.X) -- Angle in radians
	local dirName = ""

	if angle > math.rad(157.5) or angle < math.rad(-157.5) then
		dirName = "south"
	elseif angle > math.rad(112.5) then 
		dirName = "southwest"
	elseif angle > math.rad(67.5) then
		dirName = "west"
	elseif angle > math.rad(22.5) then
		dirName = "northwest"
	elseif angle > math.rad(-22.5) then
		dirName = "north"
	elseif angle > math.rad(-67.5) then
		dirName = "northeast"
	elseif angle > math.rad(-112.5) then
		dirName = "east"
	else
		dirName = "southeast"
	end

	return distanceJudge,dirName
end

function aware.judgeamnt(amnt,judgestrings)
	local judgedistribution={1,2,3,4,5,6,8}
	local judgestrings={{"a single"},{"a couple"},{"a few"},{"a quartet"},{"several"},{"a bunch"},{"a lot"}}
	local index=1

	repeat
		local distvector=amnt
		if distvector<=judgedistribution[index] then
			return judgestrings[index][1]
		end	
	until index>=#judgedistribution	
end

function aware.judgething(size, bigSize,judgeSizes,judgeStrings)
	local index = 1
	local sizeJudge = ""
	for i, judge in ipairs(judgeSizes) do
		if size <= bigSize * judge then
			sizeJudge = judgeStrings[i]
			break
		end
	end
	return sizeJudge
end

function aware.judgesize(size, bigSize)
	local judgeSizes = {0.1, 0.25, 0.5, 0.75, 1, 1.5, 2}
	local judgeStrings = {"tiny", "small", "medium-small", "medium", "medium-large", "large", "huge"}
	local sizeJudge= aware.judgething(size, bigSize,judgeSizes,judgeStrings)
	return sizeJudge
end

function aware.judgepower(power, bigpower)
	local judgeSizes = {0.1, 0.25, 0.5, 0.75, 1, 1.5, 2}
	local judgeStrings = {"very weak", "weak", "kind of weak", "average", "kind of strong", "strong", "powerful"}
	local sizeJudge= aware.judgething(power, bigpower,judgeSizes,judgeStrings)
	return sizeJudge
end

function aware.judgeobject(instance)
	if instance:FindFirstChild("Humanoid")~=nil then
		return instance.Humanoid.DisplayName
	elseif instance:IsA("folder")~=nil then	
		return instance.Name
	elseif instance:IsA("BasePart") then
		local s=instance:FindFirstChild("Species")
		if s~=nil then
			return s.Value	
		end
	elseif instance:IsA("Model") then
		return instance.Name
	end
end


function aware.getsurroundingobjects(root)
	local closestPlant, numPlants,plantsize = getnearest(plants, root.Position, 40)
	local closestTree, numTrees = getnearest(trees, root.Position, 80) 
	local closestStructure, numStructures,structuresize = getnearest(mapObjects, root.Position, 160)
	local closestEnemy, numEnemies = getnearest(enemys, root.Position, 60)
	local closestNPC, numNPCs = getnearest(npcs, root.Position, 60)
	local closestPlayer, numPlayers = getnearest(playerstable, root.Position, 80)
	local closestRubble, numRubble = getnearest(rubble, root.Position, 20) 
	local closestChest, numChests = getnearest(chests, root.Position, 30)
	local closestGroundItem, numGroundItems = getnearest(grounditems, root.Position, 40)
	local closestHouse, numHouses,housesize = getnearest(houses, root.Position, 100)
	local closestDungeon, numDungeons,dungsize = getnearest(dungeons, root.Position, 200)
	local pos=root.Position
	local function describeRubble2(context)

		local rubbleText = ""

		if closestRubble then
			local dist, dir = aware.judgedistance(pos, closestRubble.Position, 20)
			local size = aware.judgesize(closestRubble.Size)
			rubbleText = "piece of " ..size.. " rubble is " ..dist.. " to the " ..dir
		end

		if numRubble > 0 then
			rubbleText = rubbleText .. context.. aware.judgeamnt(numRubble).. " pieces of rubble lay on the ground"
		end

		return rubbleText

	end


	local function describeChests2(context)

		local chestText = ""

		if closestChest then
			local dist, dir = aware.judgedistance(pos, closestChest.Position, 30)
			--local size = aware.judgesize(closestChest.Size)
			chestText = "chest is " ..dist.. " to the " ..dir
		end

		if numChests > 0 then
			chestText = chestText .. context .. aware.judgeamnt(numChests).." chests are scattered around" 
		end

		return chestText

	end


	local function describeGroundItems2(context)

		local groundItemText = ""

		if closestGroundItem then
			local dist, dir = aware.judgedistance(pos, closestGroundItem.Position, 40)
			local size = aware.judgesize(closestGroundItem.Size)
			groundItemText = aware.judgeobject(closestGroundItem)" is " ..dist.. " to the " ..dir
		end

		if numGroundItems > 0 then
			groundItemText = groundItemText .. context .. aware.judgeamnt(numGroundItems).." items lay on the ground"
		end

		return groundItemText

	end


	local function describeHouses2(context)

		local houseText = ""

		if closestHouse then
			local dist, dir = aware.judgedistance(pos, closestHouse.Position, 100)
			local size = aware.judgesize(closestHouse.Size)
			houseText = "" ..size.. " house is " ..dist.. " to the " ..dir
		end

		if numHouses > 0 then
			houseText = houseText .. context .. aware.judgeamnt(numHouses).." houses stand nearby"
		end

		return houseText

	end


	local function describeDungeons2(context)

		local dungeonText = ""

		if closestDungeon then
			local dist, dir = aware.judgedistance(pos, closestDungeon.Position, 200)
			local size = aware.judgesize(closestDungeon.Size)
			dungeonText = aware.judgeobject(closestDungeon).." is "..dist.. " to the " ..dir
		end

		if numDungeons > 0 then
			dungeonText = dungeonText .. context..aware.judgeamnt(numGroundItems)" areas around here" 
		end

		return dungeonText

	end
	local function describeTrees2(context)
		
		local treeText = ""

		if closestTree then
			local dist, dir = aware.judgedistance(pos, closestTree.Position, 80) 
			treeText = aware.judgeobject(closestTree).." is " ..dist.. " to the " ..dir
		end

		if numTrees > 0 then
			treeText = treeText ..context.. aware.judgeamnt(numTrees).." of other trees surround the area"
		end

		return treeText

	end


	local function describePlants2(context)

		local plantText = ""

		if closestPlant then
			local dist, dir = aware.judgedistance(pos, closestPlant.Position, 40)
			local size = aware.judgesize(closestPlant.Size)
			plantText =size.. " "..aware.judgeobject(closestPlant).." is " ..dist.. " to the " ..dir
		end

		if numPlants > 0 then
			plantText = plantText ..context.. aware.judgeamnt(numPlants).." of other plants are scattered around."
		end

		return plantText

	end


	local function describeEnemies2(context)

		local enemyText = ""

		if closestEnemy then
			local dist, dir = aware.judgedistance(pos, closestEnemy.Position, 60)
			enemyText = aware.judgeobject(closestEnemy.Parent).. " is " ..dist.. " to the " ..dir
		end

		if numEnemies > 0 then
			enemyText = enemyText ..context.. aware.judgeamnt(numEnemies).." enemies are lurking nearby"
		end

		return enemyText

	end


	local function describeNPCs2(context)

		local npcText = ""

		if closestNPC then
			local dist, dir = aware.judgedistance(pos, closestNPC.Position, 60)
			npcText = aware.judgeobject().." is " ..dist.. " to the " ..dir
		end

		if numNPCs > 0 then
			npcText = npcText ..context.. aware.judgeamnt(numNPCs).." strangers are in the area"
		end

		return npcText

	end

	
	local function describeTrees()
		if numTrees > 0 then
			local treeText = aware.judgeamnt(numTrees).." of trees surround the area"
			return treeText			
		end
	end

	local function describePlants()
		if numPlants > 0 then  
			local plantText = aware.judgeamnt(numPlants).." of plants are scattered around"
			return plantText
		end
	end

	local function describeRubble()
		if numRubble > 0 then
			local rubbleText = aware.judgeamnt(numRubble).." of pieces of rubble lay on the ground" 
			return rubbleText
		end
	end

	local function describeEnemies()
		if numEnemies > 0 then
			local enemyText = aware.judgeamnt(numEnemies).." of enemies are lurking nearby"
			return enemyText
		end
	end

	local function describeNPCs()
		if numNPCs > 0 then
			local npcText = aware.judgeamnt(numNPCs).." of strangers are in the area"
			return npcText
		end
	end

	local function describePlayers()
		if numPlayers > 0 then
			local playerText = aware.judgeamnt(numPlayers).." of players are nearby" 
			return playerText
		end
	end

	local function describeChests()
		if numChests > 0 then
			local chestText = aware.judgeamnt(numChests).." of chests are scattered around"
			return chestText
		end
	end

	local function describeGroundItems()
		if numGroundItems > 0 then
			local groundItemText = aware.judgeamnt(numGroundItems).." of items lay on the ground"
			return groundItemText
		end
	end 

	local function describeHouses()
		if numHouses > 0 then
			local houseText = aware.judgeamnt(numHouses).." of houses stand nearby"
			return houseText
		end
	end

	local function describeDungeons()
		if numDungeons > 0 then
			local dungeonText = aware.judgeamnt(numDungeons).." of areas around here."
			return dungeonText
		end
	end
	local function describestructures()
		if numStructures > 0 then
			local structureText = aware.judgeamnt(numDungeons).." of interesting places to check out around here."
			return structureText
		end
	end

	local function describeSurroundings(pos)

		local info = aware.getsurroundingobjects(pos)

		local descStrings = {}
local opener={"Their are ","I see ","Surrounding us are "}
		table.insert(descStrings, ""..describeTrees())
		table.insert(descStrings, ""..describePlants())
		table.insert(descStrings, ""..describeRubble())
		table.insert(descStrings, ""..describeEnemies())
		table.insert(descStrings, ""..describeNPCs())
		table.insert(descStrings, ""..describePlayers())
		table.insert(descStrings, ""..describeChests())
		table.insert(descStrings, ""..describeGroundItems())
		table.insert(descStrings, ""..describeHouses())
		table.insert(descStrings, ""..describeDungeons())

		-- Remove any nil values
		local finalStrings = {}
		local paragraphstring=""
		for i,str in ipairs(descStrings) do
			if str ~= "" then
				table.insert(finalStrings, opener[math.random(1,#opener)]..str..".") 
				paragraphstring=paragraphstring..str..", "
			end
		end
		if paragraphstring~="" then
			paragraphstring=opener[math.random(1,#opener)]..paragraphstring.."."
			table.insert(finalStrings,paragraphstring)
		end
		-- Join the strings together

		return finalStrings

	end
	
	return {
		closestPlant = closestPlant,  
		numPlants = numPlants,
		plantsize = plantsize,

		closestTree = closestTree,
		numTrees = numTrees,

		closestStructure = closestStructure,
		numStructures = numStructures,
		structuresize = structuresize,

		closestEnemy = closestEnemy,
		numEnemies = numEnemies, 

		closestNPC = closestNPC,
		numNPCs = numNPCs,

		closestPlayer = closestPlayer,
		numPlayers = numPlayers,

		closestRubble = closestRubble,
		numRubble = numRubble,

		closestChest = closestChest,
		numChests = numChests,

		closestGroundItem = closestGroundItem, 
		numGroundItems = numGroundItems,

		closestHouse = closestHouse,
		numHouses = numHouses,
		housesize,

		closestDungeon = closestDungeon,
		numDungeons = numDungeons,
		dungsize = dungsize
	}

end

return aware
5 Likes

I have completed the Awareness module! Here it is in action! :slight_smile:

2 Likes

I have done a massive update to this ChatModule model. It still works the same way except it has more features, is more efficient and accurate! This is the main changes below. These functions are basically the architecture of the Search algorithm. To utilize the synonyms just set the complete variable to true. All the variables passed through the function besides query and database are basically true,false. You can also just not include the variable in your function call and it will act as if false if set to nil.

function chatmodule.Getsynonyms(s,complete)
	if string.len(s)>=3 and complete==true then
	for j, phrases in ipairs(synonympairs) do
			for k, phrase in ipairs(phrases) do
					if s:find(phrase)  then 
						return phrases
					end				
			end
		end	
	end	
	return {s}
end
function chatmodule.countKeyword(str, synomarray,filter,complete)
	local count = 0
	local words=chatmodule.splitString(str,filter)
	
	local weight=#words
	local BlacklistedKeyword=nil
	local synoynms=nil
	for _, words2 in ipairs(synomarray) do	
	for _, keyword in ipairs(words2) do	
			for _, word in ipairs(words) do		
				local word=word:lower()
				local keyword=keyword:lower()
				if word == keyword then 
				count = count + 1
				--elseif keyword:find(word) then
				--count = count + 1
				
			end
			end
			end
			end
	return count,weight
end

function chatmodule.findBestMatch(strings, keyword,filter,mode,complete)
	local bestMatch = nil -- the best match string
	local bestCount = 0 -- the highest count of keyword occurrences
	local best_match, strm
	local bestweight
	local synomarray={}
	local words2 = chatmodule.splitString(keyword,filter)
	for _, originword in ipairs(words2) do	
		if complete==true then
			local syn=chatmodule.Getsynonyms(originword,complete)
			table.insert(synomarray,syn)
			--print(synoynms)
		else
			synomarray={{originword}}--double nestedtable
		end	
	end
		
		
	for i, str in ipairs(strings) do -- loop through the strings in the table
		--str=strings[i]
		local str=str 
		if strings[i]~=nil then
			str= strings[i]
		else 
			str=str
		end
		--if filter==true then	
			--strm=chatmodule.ReduceQuery(str)	
		--else strm=str	
		--end
		local check=false
		if blacklist then
		for i, blkl in ipairs(blacklist) do 
			
			if str==blkl then
				check=true
			end
			end
		end	
		if check==false then
			local count,weight = chatmodule.countKeyword(str, synomarray,filter,complete) 
			if mode==true then
				count=count/weight
			end	
			if count> bestCount then -- if the count is higher than the best count so far
				bestMatch = str -- update the best match string
				bestCount = count-- update the best count number
				bestweight=weight	
			end
		end	
	end
	--if bestMatch then
	--print(bestMatch.." "..keyword.." "..table.concat(words2," "))
	--end	
	return bestMatch, bestCount,bestweight -- return the best match and its count
end
function chatmodule.SearchQuery(query,database,filter,repetitive,randomize,reverse,spaces,mode,complete)
	local matches = {} -- A table to store the matches and their scores
	local BlacklistedKeyword
	local result = nil 
	local score	
	if  spaces==true then
	return chatmodule.find_closest_match(database, query)
	else
		local bestMatch,bestCount
				bestMatch,bestCount,weight = chatmodule.findBestMatch(database,query,filter,mode,complete)
				-- Find the best match and its count for each word using your findBestMatch function
				if bestMatch then -- If there is a match
					if matches[bestMatch] then -- If the match is already in the table
						matches[bestMatch] = matches[bestMatch] + bestCount -- Add the count to its score
					else -- If the match is not in the table yet
						matches[bestMatch] = bestCount -- Set its score to the count
					end
				end	
	local sortedMatches = {} -- A table to store the sorted matches by their scores
	for match, score in pairs(matches) do -- Loop through the matches and their scores
		table.insert(sortedMatches, {match = match, score = score}) -- Insert each match and its score as a subtable into the sortedMatches table
	end
	table.sort(sortedMatches, function(a, b) return a.score > b.score end) -- Sort the sortedMatches table by the score field in descending order
	if #sortedMatches > 0 then -- If there is at least one match
		--result = "The best match(es) for '" .. query .. "' are:\n" -- Start the result string with an introduction
		if randomize==true and  #sortedMatches>0 then
			local num=chatmodule.mathrandom(1,math.min(#sortedMatches, 3))
			result=sortedMatches[num].match
			score=sortedMatches[num].score
		elseif #sortedMatches>0 then
			if filter==true or filter==false or filter==nil then				
				result=sortedMatches[1].match
				score=sortedMatches[1].score
			elseif filter==1  then
				local results,weight=	chatmodule.SearchQueryPattern(query, sortedMatches, filter, repetitive, randomize, reverse, spaces)
				result=results.match
				score=results.score
				end	
		end	
		context=context+1
			if blacklist==nil then
				blacklist={}
			end
			if repetitive==false and result and blacklist then
				table.insert(blacklist,result)
			end		
			
		--result=sortedMatches[chatmodule.mathrandom(1,math.min(#sortedMatches, 3))]
	else -- If there are no matches
		result=nil
	end
	end	
--	print(blacklist)
	return result,blacklist,score,weight
	-- Return the result string
end

This ChatModule works amazing and I’m glad to be able to share it with you all! I use this in conjunction with artificial intelligence APIs and a bunch of other modules I’m developing.
Please refer to my 1st example in the parent post for examples of how to set up some basic chat logic.
All of the functions besides the chat logic should be dependent on this Module.

cm=require(script.Parent.ChatModule)
--The minimalist way to use the function
cm.SearchQuery(query,database)
--Sigma chad way to use the function
--Mode uses the length of the entry to weigh the match with the length of the entry
cm.SearchQuery(query,database,true,false,false,false,false,true,true)
2 Likes

I have posted a new Resource about this Vector Matrix Library I’m writing for this module to maintain context weight across databases initially. then maybe get to deeper the Vector Matrix machine learning incorporated deeper into the chatbot module.
NEW Vector Matrix Library, Synonym Chat Module Library and Awareness/Emotion Modules Linked [Open Sourced] - Resources / Community Resources - Developer Forum | Roblox

2 Likes

I have added a new function to this module! I have noticed it was very easy to make so I wanted to show how this library can be used for machine learning and data analysis.


function chatmodule.BagOfWords(strings)
	local model={}
		for i, str in ipairs(strings) do -- loop through the strings in the table
		local words=chatmodule.splitString(str)
		for _,wo in ipairs(words) do
			
			local s=chatmodule.Getsynonyms(wo:lower(),true)		
			if model[s[1]]==nil then model[s[1]]=1 end
			model[s[1]]=model[s[1]]+1
			
		end
	end	
	return model
end

As simple as that! The cool part is we are leveraging a very optimizied Getsynonym function that reduces the representation to an array of more simplfied meaning. Thus massively reducing the size of the vocabulary being cached in our Bag of Words function! That is why in this example I get the synonyms and then use the first key in the nested array to get the point in the model!. You can use this to create representation of more complex Data. Maybe in the future we will be exploring next word prediction?

2 Likes