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)