diff --git a/Manifest.toml b/Manifest.toml index 5539e2c..24c8b32 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -26,9 +26,9 @@ uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" version = "0.1.9" [[deps.CEnum]] -git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90" +git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" -version = "0.4.2" +version = "0.5.0" [[deps.CSV]] deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"] @@ -36,29 +36,23 @@ git-tree-sha1 = "6c834533dc1fabd820c1db03c839bf97e45a3fab" uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" version = "0.10.14" -[[deps.Calculus]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad" -uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9" -version = "0.5.1" - [[deps.CodeTracking]] deps = ["InteractiveUtils", "UUIDs"] -git-tree-sha1 = "c0216e792f518b39b22212127d4a84dc31e4e386" +git-tree-sha1 = "7eee164f122511d3e4e1ebadb7956939ea7e1c77" uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" -version = "1.3.5" +version = "1.3.6" [[deps.CodecZlib]] deps = ["TranscodingStreams", "Zlib_jll"] -git-tree-sha1 = "b8fe8546d52ca154ac556809e10c75e6e7430ac8" +git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759" uuid = "944b1d66-785c-5afd-91f1-9de20f533193" -version = "0.7.5" +version = "0.7.6" [[deps.Compat]] deps = ["TOML", "UUIDs"] -git-tree-sha1 = "b1c55339b7c6c350ee89f2c1604299660525b248" +git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.15.0" +version = "4.16.0" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] @@ -77,9 +71,9 @@ version = "2.4.2" [[deps.CondaPkg]] deps = ["JSON3", "Markdown", "MicroMamba", "Pidfile", "Pkg", "Preferences", "TOML"] -git-tree-sha1 = "e81c4263c7ef4eca4d645ef612814d72e9255b41" +git-tree-sha1 = "8f7faef2ca039ee068cd971a80ccd710d23fb2eb" uuid = "992eb4ea-22a4-4c89-a5bb-47a3300528ab" -version = "0.2.22" +version = "0.2.23" [[deps.Crayons]] git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" @@ -124,15 +118,17 @@ version = "0.4.1" [[deps.DispatchDoctor]] deps = ["MacroTools", "Preferences"] -git-tree-sha1 = "32d236e685d028f5bc808aae0634b58aac5128f0" +git-tree-sha1 = "c2acd1de2c4c357928f9fb6b60b402d914621378" uuid = "8d63f2c5-f18a-4cf2-ba9d-b3f60fc568c8" -version = "0.4.10" +version = "0.4.14" [deps.DispatchDoctor.extensions] DispatchDoctorChainRulesCoreExt = "ChainRulesCore" + DispatchDoctorEnzymeCoreExt = "EnzymeCore" [deps.DispatchDoctor.weakdeps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" [[deps.Distributed]] deps = ["Random", "Serialization", "Sockets"] @@ -140,9 +136,9 @@ uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[deps.Distributions]] deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] -git-tree-sha1 = "9c405847cc7ecda2dc921ccf18b47ca150d7317e" +git-tree-sha1 = "0e0a1264b0942f1f3abb2b30891f2a590cc652ac" uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" -version = "0.25.109" +version = "0.25.110" [deps.Distributions.extensions] DistributionsChainRulesCoreExt = "ChainRulesCore" @@ -165,12 +161,6 @@ deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" version = "1.6.0" -[[deps.DualNumbers]] -deps = ["Calculus", "NaNMath", "SpecialFunctions"] -git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566" -uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74" -version = "0.6.8" - [[deps.ExceptionUnwrapping]] deps = ["Test"] git-tree-sha1 = "dcb08a0d93ec0b1cdc4af184b26b591e9695423a" @@ -199,9 +189,9 @@ uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" [[deps.FillArrays]] deps = ["LinearAlgebra"] -git-tree-sha1 = "0653c0a2396a6da5bc4766c43041ef5fd3efbe57" +git-tree-sha1 = "fd0002c0b5362d7eb952450ad5eb742443340d6e" uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "1.11.0" +version = "1.12.0" weakdeps = ["PDMats", "SparseArrays", "Statistics"] [deps.FillArrays.extensions] @@ -232,10 +222,16 @@ uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" version = "1.10.8" [[deps.HypergeometricFunctions]] -deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] -git-tree-sha1 = "f218fe3736ddf977e0e772bc9a586b2383da2685" +deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] +git-tree-sha1 = "7c4195be1649ae622304031ed46a2f4df989f1eb" uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" -version = "0.3.23" +version = "0.3.24" + +[[deps.ICU_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "20b6765a3016e1fca0c9c93c80d50061b94218b7" +uuid = "a51ab1cf-af8e-5615-a023-bc2c838bba6b" +version = "69.1.0+0" [[deps.Infinity]] deps = ["Dates", "Random", "Requires"] @@ -306,9 +302,9 @@ version = "1.14.0" [[deps.JuliaInterpreter]] deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"] -git-tree-sha1 = "a6adc2dcfe4187c40dc7c2c9d2128e326360e90a" +git-tree-sha1 = "7ae67d8567853d367e3463719356b8989e236069" uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a" -version = "0.9.32" +version = "0.9.34" [[deps.Kerberos_krb5_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -357,15 +353,15 @@ version = "1.6.4+0" [[deps.LibPQ]] deps = ["CEnum", "DBInterface", "Dates", "Decimals", "DocStringExtensions", "FileWatching", "Infinity", "Intervals", "IterTools", "LayerDicts", "LibPQ_jll", "Libdl", "Memento", "OffsetArrays", "SQLStrings", "Tables", "TimeZones", "UTCDateTimes"] -git-tree-sha1 = "74feb1a63ebbcdcf1730016d2a4dfad0a655404f" +git-tree-sha1 = "3d227cd13cbf1e9a54d7748dab33e078da6f9168" uuid = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1" -version = "1.17.1" +version = "1.18.0" [[deps.LibPQ_jll]] -deps = ["Artifacts", "JLLWrappers", "Kerberos_krb5_jll", "Libdl", "OpenSSL_jll", "Pkg"] -git-tree-sha1 = "a299629703a93d8efcefccfc16b18ad9a073d131" +deps = ["Artifacts", "ICU_jll", "JLLWrappers", "Kerberos_krb5_jll", "Libdl", "OpenSSL_jll", "Zstd_jll"] +git-tree-sha1 = "09163f837936c8cc44f4691cb41d805eb1769642" uuid = "08be9ffa-1c94-5ee5-a977-46a84ec9b350" -version = "14.3.0+1" +version = "16.0.0+0" [[deps.LibSSH2_jll]] deps = ["Artifacts", "Libdl", "MbedTLS_jll"] @@ -406,9 +402,9 @@ version = "1.0.3" [[deps.LoweredCodeUtils]] deps = ["JuliaInterpreter"] -git-tree-sha1 = "eeaedcf337f33c039f9f3a209a8db992deefd7e9" +git-tree-sha1 = "1ce1834f9644a8f7c011eb0592b7fd6c42c90653" uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b" -version = "2.4.8" +version = "3.0.1" [[deps.MQTTClient]] deps = ["Distributed", "Random", "Sockets"] @@ -464,20 +460,14 @@ uuid = "a63ad114-7e13-5084-954f-fe012c677804" [[deps.Mocking]] deps = ["Compat", "ExprTools"] -git-tree-sha1 = "bf17d9cb4f0d2882351dfad030598f64286e5936" +git-tree-sha1 = "2c140d60d7cb82badf06d8783800d0bcd1a7daa2" uuid = "78c3b35d-d492-501b-9361-3d52fe80e533" -version = "0.7.8" +version = "0.8.1" [[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" version = "2023.1.10" -[[deps.NaNMath]] -deps = ["OpenLibm_jll"] -git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" -uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" -version = "1.0.2" - [[deps.NetworkOptions]] uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" version = "1.2.0" @@ -511,9 +501,9 @@ version = "1.4.3" [[deps.OpenSSL_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "a12e56c72edee3ce6b96667745e6cbbe5498f200" +git-tree-sha1 = "a028ee3cb5641cccc4c24e90c36b0a4f7707bdf5" uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" -version = "1.1.23+0" +version = "3.0.14+0" [[deps.OpenSpecFun_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] @@ -589,15 +579,15 @@ version = "1.2.0" [[deps.PythonCall]] deps = ["CondaPkg", "Dates", "Libdl", "MacroTools", "Markdown", "Pkg", "REPL", "Requires", "Serialization", "Tables", "UnsafePointers"] -git-tree-sha1 = "8de9e6cbabc9bcad4f325bd9f2f1e83361e5037d" +git-tree-sha1 = "84084218c7377beb15a317868d4541a8c3c4ac99" uuid = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" -version = "0.9.20" +version = "0.9.22" [[deps.QuadGK]] deps = ["DataStructures", "LinearAlgebra"] -git-tree-sha1 = "9b23c31e76e333e6fb4c1595ae6afa74966a729e" +git-tree-sha1 = "e237232771fdafbae3db5c31275303e056afaa9f" uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" -version = "2.9.4" +version = "2.10.1" [[deps.REPL]] deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] @@ -625,10 +615,10 @@ uuid = "ae029012-a4dd-5104-9daa-d747884805df" version = "1.3.0" [[deps.Revise]] -deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "Pkg", "REPL", "Requires", "UUIDs", "Unicode"] -git-tree-sha1 = "85ddd93ea15dcd8493400600e09104a9e94bb18d" +deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "REPL", "Requires", "UUIDs", "Unicode"] +git-tree-sha1 = "7b7850bb94f75762d567834d7e9802fc22d62f9c" uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" -version = "3.5.15" +version = "3.5.18" [[deps.Rmath]] deps = ["Random", "Rmath_jll"] @@ -638,9 +628,9 @@ version = "0.7.1" [[deps.Rmath_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "d483cd324ce5cf5d61b77930f0bbd6cb61927d21" +git-tree-sha1 = "e60724fd3beea548353984dc61c943ecddb0e29a" uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" -version = "0.4.2+0" +version = "0.4.3+0" [[deps.SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" @@ -773,10 +763,10 @@ uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" version = "1.0.1" [[deps.Tables]] -deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"] -git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d" +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "598cd7c1f68d1e205689b1c2fe65a9f85846f297" uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.11.1" +version = "1.12.0" [[deps.Tar]] deps = ["ArgTools", "SHA"] @@ -789,22 +779,18 @@ uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[deps.TimeZones]] deps = ["Dates", "Downloads", "InlineStrings", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] -git-tree-sha1 = "a6ae8d7a27940c33624f8c7bde5528de21ba730d" +git-tree-sha1 = "b92aebdd3555f3a7e3267cf17702033c2814ef48" uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" -version = "1.17.0" +version = "1.18.0" weakdeps = ["RecipesBase"] [deps.TimeZones.extensions] TimeZonesRecipesBaseExt = "RecipesBase" [[deps.TranscodingStreams]] -git-tree-sha1 = "60df3f8126263c0d6b357b9a1017bb94f53e3582" +git-tree-sha1 = "e84b3a11b9bece70d14cce63406bbc79ed3464d2" uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" -version = "0.11.0" -weakdeps = ["Random", "Test"] - - [deps.TranscodingStreams.extensions] - TestExt = ["Test", "Random"] +version = "0.11.2" [[deps.URIs]] git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b" @@ -845,6 +831,12 @@ deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" version = "1.2.13+1" +[[deps.Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e678132f07ddb5bfa46857f0d7620fb9be675d3b" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.6+0" + [[deps.libblastrampoline_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" diff --git a/previousversion/0.1/src/type.jl b/previousversion/0.1/src/type.jl index f6b98e7..f3953e6 100644 --- a/previousversion/0.1/src/type.jl +++ b/previousversion/0.1/src/type.jl @@ -149,7 +149,7 @@ function sommelier( :activeplan => Dict{Symbol, Any}(), # current using plan :currenttrajectory=> Dict{Symbol, Any}(), # store question, thought, action, observation, ... - ) + ), mctsWorkDict::Dict{Symbol, Any} = Dict{Symbol, Any}() ) diff --git a/src/interface.jl b/src/interface.jl index ddc26b5..c17d2da 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -341,21 +341,21 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol, Any} where {T<:age response = a.text2textInstructLLM(prompt) responsedict = GeneralUtils.textToDict(response, ["Understanding", "Reasoning", "Plan", "Action_name", "Action_input", "Mentioning_wine"], - rightmarker=":", symbolkey=true) + rightmarker=":", symbolkey=true, lowercasekey=true) - if responsedict[:Action_name] ∉ ["CHATBOX", "PRESENTBOX", "CHECKINVENTORY", "ENDCONVERSATION"] + if responsedict[:action_name] ∉ ["CHATBOX", "PRESENTBOX", "CHECKINVENTORY", "ENDCONVERSATION"] errornote = "You must use the given functions" error("You must use the given functions ", @__FILE__, " ", @__LINE__) end - for i ∈ [:Understanding, :Plan, :Action_name] + for i ∈ [:understanding, :plan, :action_name] if length(responsedict[i]) == 0 error("$i is empty ", @__FILE__, " ", @__LINE__) end end # check if there are more than 1 key per categories - for i ∈ [:Understanding, :Plan, :Action_name, :Action_input, :Mentioning_wine] + for i ∈ [:understanding, :plan, :action_name, :action_input, :mentioning_wine] matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i) if length(matchkeys) > 1 error("DecisionMaker has more than one key per categories") @@ -368,13 +368,13 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol, Any} where {T<:age # check if LLM recommend wine before checking inventory isMemEmpty = isempty(a.memory[:shortmem]) - if occursin("Yes", responsedict[:Mentioning_wine]) && isMemEmpty && - responsedict[:Action_name] != "CHECKINVENTORY" + if occursin("Yes", responsedict[:mentioning_wine]) && isMemEmpty && + responsedict[:action_name] != "CHECKINVENTORY" errornote = "Note: You can't recommend wines yet. You must check your inventory before recommending wine to the user." error( "You can't recommend wines yet. You must check your inventory before recommending wines") - elseif responsedict[:Action_name] == "PRESENTBOX" && isMemEmpty && - responsedict[:Action_name] != "CHECKINVENTORY" + elseif responsedict[:action_name] == "PRESENTBOX" && isMemEmpty && + responsedict[:action_name] != "CHECKINVENTORY" errornote = "Note: You can't recommend wines yet. You must check your inventory before recommending wine to the user." error( "You can't recommend wines yet. You must check your inventory before recommending wines") @@ -382,7 +382,7 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol, Any} where {T<:age errornote = "" end - delete!(responsedict, :Mentioning_wine) + delete!(responsedict, :mentioning_wine) return responsedict catch e @@ -903,23 +903,6 @@ function conversation(a::T, userinput::Dict) where {T<:agent} # thought will be added to chat model via context chatresponse = generatechat(a.memory, a.chathistory, a.text2textInstructLLM) - # some time LLM said to user that it (checking inventory) but it is not. - # if chatresponse want to check inventory but think() didn't checkinventory then do it - llmCheckInv = occursin("(check", chatresponse) || occursin("*check", chatresponse) || - occursin("inventory)", chatresponse) || occursin("inventory*", chatresponse) - - if llmCheckInv && actionname != "checkinventory" - error("force check inventory should not be called") - actionname, result = forceInventoryCheck(a) - push!(a.memory[:shortmem], Dict(Symbol(actionname)=> result)) - - # generate chatresponse again because we have force inventory check - chatresponse = generatechat(a.memory, a.chathistory, a.text2textInstructLLM) - else - # since chatresponse does not halucinate i.e. no (check inventory), it does not need - # to regenerate again and con be use directly - end - addNewMessage(a, "assistant", chatresponse) push!(a.memory[:events], @@ -954,22 +937,11 @@ function think(a::T)::NamedTuple{(:actionname, :result), Tuple{String, String}} a.memory[:recap] = generateSituationReport(a, a.text2textInstructLLM; skiprecent=5) a.memory[:QandA] = generatequestion(a, a.text2textInstructLLM; recent=5) - - dummy = situationtrack(a, a.text2textInstructLLM) - - # after the user selected their wine. No question should be asked - # a.memory[:QandA] = - # if occursin("None", a.memory[:sitrep][:wine_selected]) - # generatequestion(a, a.text2textInstructLLM) - # else - # generatequestion(a, a.text2textInstructLLM) #[PENDING] to be removed. this is just for explor - # "None" - # end thoughtDict = decisionMaker(a; recent=5) - actionname = thoughtDict[:Action_name] - actioninput = thoughtDict[:Action_input] + actionname = thoughtDict[:action_name] + actioninput = thoughtDict[:action_input] # map action and input() to llm function response = @@ -1020,131 +992,6 @@ function think(a::T)::NamedTuple{(:actionname, :result), Tuple{String, String}} end -""" Force to think and check inventory - -""" -function forceInventoryCheck(a::T)::NamedTuple{(:actionname, :result), Tuple{String, String}} where {T<:agent} - println("--> forceInventoryCheck()") - thoughtDict = thinkCheckInventory(a) - actionname = thoughtDict[:Action_name] - actioninput = thoughtDict[:Action_input] - - # map action and input() to llm function - response = - if actionname == "CHECKINVENTORY" - checkinventory(a, actioninput) - else - error("undefined LLM function. Requesting $actionname") - end - - # this section allow LLM functions above to have different return values. - result = haskey(response, :result) ? response[:result] : nothing - select = haskey(response, :select) ? response[:select] : nothing - reward::Integer = haskey(response, :reward) ? response[:reward] : 0 - isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false - errormsg::Union{AbstractString, Nothing} = haskey(response, :errormsg) ? response[:errormsg] : nothing - success::Bool = haskey(response, :success) ? response[:success] : false - - return (actionname=actionname, result=result) -end - - - - -function thinkCheckInventory(a::T)::Dict{Symbol, Any} where {T<:agent} - - systemmsg = - """ - You are a helpful sommelier working for a wine store. - Your task is to help the user choose the best wine that match the user preferences from your inventory. - - Definitions: - - observation: result of the preceding immediate action. - - At each round of conversation, the user will give you the current situation: - Context: ... - Your earlier conversation with the user: ... - - You must follow the following guidelines: - - Check inventory immediately based on what you know about the user. - - You should then respond to the user with interleaving Thought, Plan, Action and Observation: - - thought: - 1) State your reasoning about the current situation. - - plan: Based on the current situation, state a complete plan to complete the task. Be specific. - - action_name (Must be aligned with your plan): Can be one of the following functions: - 1) CHECKINVENTORY[query], which you can use to check info about wine in your inventory. "query" is a search term in verbal English. - Good query example: black car with a stereo, 200 mile range and an electric motor. - Good query example: How many car brand are from Asia? - - Action_input: input to the action - - You should only respond in format as described below: - thought: ... - plan: ... - action_name: ... - action_input: ... - - Let's begin! - """ - - usermsg = - """ - Context: None - Your earlier conversation with the user: $(vectorOfDictToText(a.chathistory)) - """ - - _prompt = - [ - Dict(:name=> "system", :text=> systemmsg), - Dict(:name=> "user", :text=> usermsg) - ] - - # put in model format - prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct") - prompt *= - """ - <|start_header_id|>assistant<|end_header_id|> - """ - response = nothing # store for show when error msg show up - for attempt in 1:10 - try - response = a.text2textInstructLLM(prompt) - responsedict = GeneralUtils.textToDict(response, - ["thought", "plan", "action_name", "action_input"], - rightmarker=":", symbolkey=true) - - if responsedict[:action_name] ∉ ["CHECKINVENTORY"] - error("decisionMaker didn't use the given functions ", @__LINE__) - end - - for i ∈ [:thought, :plan, :action_name] - if length(JSON3.write(responsedict[i])) == 0 - error("$i is empty ", @__LINE__) - end - end - - # check if there are more than 1 key per categories - for i ∈ [:thought, :plan, :action_name, :action_input] - matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i) - if length(matchkeys) > 1 - error("DecisionMaker has more than one key per categories") - end - end - - return responsedict - catch e - io = IOBuffer() - showerror(io, e) - errorMsg = String(take!(io)) - st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace())) - println("") - println("Attempt $attempt. Error occurred: $errorMsg\n$st") - println("") - end - end - error("DecisionMaker failed to generate a thought ", response) -end - """ @@ -1202,7 +1049,7 @@ function generatechat(memory::Dict, chathistory::Vector, text2textInstructLLM::F """ context = - if length(memory[:shortmem]) > 0 #[WORKING] add with number order 1), 2) + if length(memory[:shortmem]) > 0 vectorOfDictToText(memory[:shortmem], withkey=false) else "" @@ -1237,7 +1084,7 @@ function generatechat(memory::Dict, chathistory::Vector, text2textInstructLLM::F try response = text2textInstructLLM(prompt) responsedict = GeneralUtils.textToDict(response,["Mentioning_wine", "Chat"], - rightmarker=":", symbolkey=true) + rightmarker=":", symbolkey=true, lowercasekey=true) for i ∈ [:Chat] if length(JSON3.write(responsedict[i])) == 0 @@ -1264,7 +1111,12 @@ function generatechat(memory::Dict, chathistory::Vector, text2textInstructLLM::F # check if LLM recommend wine before checking inventory isMemEmpty = isempty(memory[:shortmem]) - if occursin("Yes", responsedict[:Mentioning_wine]) && isMemEmpty + if occursin("Yes", responsedict[:mentioning_wine]) && isMemEmpty + errornote = "Note: You can't recommend wines yet. You must check your inventory before recommending wine to the user." + error( "You must check your inventory before recommending wine") + elseif occursin("(check", chatresponse) || occursin("*check", chatresponse) || + occursin("inventory)", chatresponse) || occursin("inventory*", chatresponse) + errornote = "Note: You can't recommend wines yet. You must check your inventory before recommending wine to the user." error( "You must check your inventory before recommending wine") else @@ -1272,7 +1124,7 @@ function generatechat(memory::Dict, chathistory::Vector, text2textInstructLLM::F end memory[:CHATBOX] = "" # delete content because it no longer used. - delete!(responsedict, :Mentioning_wine) + delete!(responsedict, :mentioning_wine) result = responsedict[:Chat] return result @@ -1452,7 +1304,7 @@ function generatequestion(a, text2textInstructLLM::Function; recent=nothing)::St # response = string(split(response, "Please")[1]) # LLM usually add comments which is no need. responsedict = GeneralUtils.textToDict(response, ["Understanding", "Q1", "Note"], - rightmarker=":", symbolkey=true) + rightmarker=":", symbolkey=true, lowercasekey=true) response = "Q1: " * responsedict[:Q1] println("--> generatequestion ", @__FILE__, " ", @__LINE__) pprintln(response) @@ -1739,144 +1591,144 @@ end -function situationtrack(a, text2textInstructLLM::Function)::String +# function situationtrack(a, text2textInstructLLM::Function)::String - systemmsg = - """ - You are a helpful assistant acting as a polite, website-based sommelier for an online wine store. +# systemmsg = +# """ +# You are a helpful assistant acting as a polite, website-based sommelier for an online wine store. - Sommelier's general workflow includes: - 1) Greet the user and introduce yourself. - 2) Understand the user's needs. - 3) Looking for the wines that match user's needs in the database. - 4) Introduce the wines to the user. - 5) Thanks the user when they are done choosing wines and invite them to comeback next time. +# Sommelier's general workflow includes: +# 1) Greet the user and introduce yourself. +# 2) Understand the user's needs. +# 3) Looking for the wines that match user's needs in the database. +# 4) Introduce the wines to the user. +# 5) Thanks the user when they are done choosing wines and invite them to comeback next time. - Your goal includes: - 1) Help the user select the best wines from your inventory that align with the user's preferences. +# Your goal includes: +# 1) Help the user select the best wines from your inventory that align with the user's preferences. - Your responsibility includes: - 1) Ask yourself specifically about how you are progressing towards the goal. +# Your responsibility includes: +# 1) Ask yourself specifically about how you are progressing towards the goal. - At each round of conversation, you will be given the current situation: - Your conversation with the user: ... - Context: ... +# At each round of conversation, you will be given the current situation: +# Your conversation with the user: ... +# Context: ... - You must follow the following guidelines: - - Your question should be specific, self-contained and not require any additional context. - - Do not generate any question or comments at the end. +# You must follow the following guidelines: +# - Your question should be specific, self-contained and not require any additional context. +# - Do not generate any question or comments at the end. - You should follow the following guidelines: - - Focus on the latest event. +# You should follow the following guidelines: +# - Focus on the latest event. - You should then respond to the user with: - 1) Understanding: State your understanding about the current situation - 2) Q: Given the situation, "ask yourself" at least five, but no more than ten, questions. - 3) A: Given the situation, "answer to yourself" the best you can - 4) Note: Additional info you want to say. Otherwise, "NA" +# You should then respond to the user with: +# 1) Understanding: State your understanding about the current situation +# 2) Q: Given the situation, "ask yourself" at least five, but no more than ten, questions. +# 3) A: Given the situation, "answer to yourself" the best you can +# 4) Note: Additional info you want to say. Otherwise, "NA" - You must only respond in format as described below: - Understanding: ... - Q1: ... - A1: ... - Q2: ... - A2: ... - Q3: ... - A3: ... - ... - Note: ... +# You must only respond in format as described below: +# Understanding: ... +# Q1: ... +# A1: ... +# Q2: ... +# A2: ... +# Q3: ... +# A3: ... +# ... +# Note: ... - Here are some examples: - Q: Where am I in the workflow? - A: According to the situation, ... +# Here are some examples: +# Q: Where am I in the workflow? +# A: According to the situation, ... - Q: Am I greeting the user and introducing myself? - A: According to the situation, no. +# Q: Am I greeting the user and introducing myself? +# A: According to the situation, no. - Q: Did the user tell me what they like? - A: According to the situation, no. We are just starting the conversation. +# Q: Did the user tell me what they like? +# A: According to the situation, no. We are just starting the conversation. - Q: What do I know about the user? - A: According to the situation, … +# Q: What do I know about the user? +# A: According to the situation, … - Q: Have I searched the database yet? - A: According to the situation, no. I need more information. +# Q: Have I searched the database yet? +# A: According to the situation, no. I need more information. - Q: Did I introduce the coffee blend varieties to the user yet? - A: According to the situation, no, I didn't because I have not searched the database yet. +# Q: Did I introduce the coffee blend varieties to the user yet? +# A: According to the situation, no, I didn't because I have not searched the database yet. - Q: What did I find in the database? - A: According to the situation, I found the following … +# Q: What did I find in the database? +# A: According to the situation, I found the following … - Let's begin! - """ +# Let's begin! +# """ - timeline = "" - for (i, event) in enumerate(a.memory[:events]) - if event[:outcome] === nothing - timeline *= "$i) $(event[:subject])> $(event[:action_or_dialogue])\n" - else - timeline *= "$i) $(event[:subject])> $(event[:action_or_dialogue]) $(event[:outcome])\n" - end - end +# timeline = "" +# for (i, event) in enumerate(a.memory[:events]) +# if event[:outcome] === nothing +# timeline *= "$i) $(event[:subject])> $(event[:action_or_dialogue])\n" +# else +# timeline *= "$i) $(event[:subject])> $(event[:action_or_dialogue]) $(event[:outcome])\n" +# end +# end - context = - if length(a.memory[:shortmem]) > 0 - vectorOfDictToText(a.memory[:shortmem], withkey=false) - else - "" - end - chathistory = vectorOfDictToText(a.chathistory) - errornote = "" - response = nothing # store for show when error msg show up +# context = +# if length(a.memory[:shortmem]) > 0 +# vectorOfDictToText(a.memory[:shortmem], withkey=false) +# else +# "" +# end +# chathistory = vectorOfDictToText(a.chathistory) +# errornote = "" +# response = nothing # store for show when error msg show up - for attempt in 1:10 - usermsg = - """ - Events timeline: $timeline - $context - $errornote - """ +# for attempt in 1:10 +# usermsg = +# """ +# Events timeline: $timeline +# $context +# $errornote +# """ - _prompt = - [ - Dict(:name=> "system", :text=> systemmsg), - Dict(:name=> "user", :text=> usermsg) - ] +# _prompt = +# [ +# Dict(:name=> "system", :text=> systemmsg), +# Dict(:name=> "user", :text=> usermsg) +# ] - # put in model format - prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct") - prompt *= - """ - <|start_header_id|>assistant<|end_header_id|> - """ +# # put in model format +# prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct") +# prompt *= +# """ +# <|start_header_id|>assistant<|end_header_id|> +# """ - try - response = text2textInstructLLM(prompt) - q_number = count("Q", response) - if q_number < 3 - error("too few questions only $q_number questions are generated ", @__FILE__, " ", @__LINE__) - end - # response = string(split(response, "Please")[1]) # LLM usually add comments which is no need. - responsedict = GeneralUtils.textToDict(response, - ["Understanding", "Q1", "Note"], - rightmarker=":", symbolkey=true) - response = "Q1: " * responsedict[:Q1] - println("--> situationtrack ", @__FILE__, " ", @__LINE__) - pprintln(Dict(responsedict)) - return response - catch e - io = IOBuffer() - showerror(io, e) - errorMsg = String(take!(io)) - st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace())) - println("") - println("Attempt $attempt. Error occurred: $errorMsg\n$st") - println("") - end - end - error("situationtrack failed to generate a thought ", response) -end +# try +# response = text2textInstructLLM(prompt) +# q_number = count("Q", response) +# if q_number < 3 +# error("too few questions only $q_number questions are generated ", @__FILE__, " ", @__LINE__) +# end +# # response = string(split(response, "Please")[1]) # LLM usually add comments which is no need. +# responsedict = GeneralUtils.textToDict(response, +# ["Understanding", "Q1", "Note"], +# rightmarker=":", symbolkey=true) +# response = "Q1: " * responsedict[:Q1] +# println("--> situationtrack ", @__FILE__, " ", @__LINE__) +# pprintln(Dict(responsedict)) +# return response +# catch e +# io = IOBuffer() +# showerror(io, e) +# errorMsg = String(take!(io)) +# st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace())) +# println("") +# println("Attempt $attempt. Error occurred: $errorMsg\n$st") +# println("") +# end +# end +# error("situationtrack failed to generate a thought ", response) +# end