From f820fe1143d02d8ef841e1ca398f9e0eab635b5d Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Fri, 17 May 2024 10:44:28 +0700 Subject: [PATCH] update --- Manifest.toml | 49 ++++++---- src/interface.jl | 2 +- src/type copy.jl | 226 +++++++++++++++++++++++++++++++++++++++++++++++ src/type.jl | 117 ++++++++++++------------ 4 files changed, 315 insertions(+), 79 deletions(-) create mode 100644 src/type copy.jl diff --git a/Manifest.toml b/Manifest.toml index 767e318..ee06871 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -4,6 +4,12 @@ julia_version = "1.10.3" manifest_format = "2.0" project_hash = "c6233f8bf690740dd830d1f0927bd3afed93b8d2" +[[deps.AliasTables]] +deps = ["PtrArrays", "Random"] +git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff" +uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8" +version = "1.1.3" + [[deps.ArgTools]] uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" version = "1.1.1" @@ -39,9 +45,9 @@ version = "0.7.4" [[deps.Compat]] deps = ["TOML", "UUIDs"] -git-tree-sha1 = "c955881e3c981181362ae4088b35995446298b80" +git-tree-sha1 = "b1c55339b7c6c350ee89f2c1604299660525b248" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.14.0" +version = "4.15.0" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] @@ -71,9 +77,9 @@ version = "1.16.0" [[deps.DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "97d79461925cdb635ee32116978fc735b9463a39" +git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.19" +version = "0.18.20" [[deps.DataValueInterfaces]] git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" @@ -89,10 +95,10 @@ deps = ["Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[deps.Distributions]] -deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] -git-tree-sha1 = "7c302d7a5fec5214eb8a5a4c466dcf7a51fcf169" +deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "22c595ca4146c07b16bcf9c8bea86f731f7109d2" uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" -version = "0.25.107" +version = "0.25.108" [deps.Distributions.extensions] DistributionsChainRulesCoreExt = "ChainRulesCore" @@ -132,9 +138,9 @@ uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" [[deps.FillArrays]] deps = ["LinearAlgebra"] -git-tree-sha1 = "bfe82a708416cf00b73a3198db0859c82f741558" +git-tree-sha1 = "0653c0a2396a6da5bc4766c43041ef5fd3efbe57" uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "1.10.0" +version = "1.11.0" weakdeps = ["PDMats", "SparseArrays", "Statistics"] [deps.FillArrays.extensions] @@ -150,9 +156,9 @@ version = "0.1.0" [[deps.HTTP]] deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] -git-tree-sha1 = "8e59b47b9dc525b70550ca082ce85bcd7f5477cd" +git-tree-sha1 = "d1d712be3164d61d1fb98e7ce9bcbc6cc06b45ed" uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" -version = "1.10.5" +version = "1.10.8" [[deps.HypergeometricFunctions]] deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] @@ -336,9 +342,9 @@ version = "0.8.1+2" [[deps.OpenSSL]] deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] -git-tree-sha1 = "af81a32750ebc831ee28bdaaba6e1067decef51e" +git-tree-sha1 = "38cb508d080d21dc1128f7fb04f20387ed4c0af4" uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" -version = "1.4.2" +version = "1.4.3" [[deps.OpenSSL_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] @@ -401,11 +407,16 @@ version = "0.4.2" deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +[[deps.PtrArrays]] +git-tree-sha1 = "077664975d750757f30e739c870fbbdc01db7913" +uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" +version = "1.1.0" + [[deps.PythonCall]] deps = ["CondaPkg", "Dates", "Libdl", "MacroTools", "Markdown", "Pkg", "REPL", "Requires", "Serialization", "Tables", "UnsafePointers"] -git-tree-sha1 = "0fe6664f742903eab8929586af78e10a51b33577" +git-tree-sha1 = "8de9e6cbabc9bcad4f325bd9f2f1e83361e5037d" uuid = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" -version = "0.9.19" +version = "0.9.20" [[deps.QuadGK]] deps = ["DataStructures", "LinearAlgebra"] @@ -484,9 +495,9 @@ version = "1.10.0" [[deps.SpecialFunctions]] deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] -git-tree-sha1 = "e2cfc4012a19088254b3950b85c3c1d8882d864d" +git-tree-sha1 = "2f5d4697f21388cbe1ff299430dd169ef97d7e14" uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "2.3.1" +version = "2.4.0" [deps.SpecialFunctions.extensions] SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" @@ -567,9 +578,9 @@ deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[deps.TranscodingStreams]] -git-tree-sha1 = "71509f04d045ec714c4748c785a59045c3736349" +git-tree-sha1 = "5d54d076465da49d6746c647022f3b3674e64156" uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" -version = "0.10.7" +version = "0.10.8" weakdeps = ["Random", "Test"] [deps.TranscodingStreams.extensions] diff --git a/src/interface.jl b/src/interface.jl index 08f44b5..c742a60 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -798,7 +798,7 @@ function conversation(a::T, userinput::Dict) where {T<:agent} addNewMessage(a, "assistant", actioninput) return actioninput else - _, a.plan[:currenttrajectory] = transition(a, a.plan[:activeplan]) + _, a.plan[:currenttrajectory] = transition(a, a.plan[:currenttrajectory], a.plan[:activeplan]) end end end diff --git a/src/type copy.jl b/src/type copy.jl new file mode 100644 index 0000000..faf5b52 --- /dev/null +++ b/src/type copy.jl @@ -0,0 +1,226 @@ +module type + +export agent, sommelier + +using Dates, UUIDs, DataStructures, JSON3 +using GeneralUtils + +# ---------------------------------------------- 100 --------------------------------------------- # + +abstract type agent end + + +""" A sommelier agent. + +# Arguments + - `mqttClient::Client` + MQTTClient's client + - `msgMeta::Dict{Symbol, Any}` + A dict contain info about a message. + - `config::Dict{Symbol, Any}` + Config info for an agent. Contain mqtt topic for internal use and other info. + +# Keyword Arguments + - `name::String` + Agent's name + - `id::String` + Agent's ID + - `tools::Dict{Symbol, Any}` + Agent's tools + - `maxHistoryMsg::Integer` + max history message + +# Return + - `nothing` + +# Example +```jldoctest +julia> using YiemAgent, MQTTClient, GeneralUtils +julia> msgMeta = GeneralUtils.generate_msgMeta( + "N/A", + replyTopic = "/testtopic/prompt" + ) +julia> tools= Dict( + :chatbox=>Dict( + :name => "chatbox", + :description => "Useful only for when you need to ask the user for more info or context. Do not ask the user their own question.", + :input => "Input should be a text.", + :output => "" , + :func => nothing, + ), + ) +julia> agentConfig = Dict( + :receiveprompt=>Dict( + :mqtttopic=> "/testtopic/prompt", # topic to receive prompt i.e. frontend send msg to this topic + ), + :receiveinternal=>Dict( + :mqtttopic=> "/testtopic/internal", # receive topic for model's internal + ), + :text2text=>Dict( + :mqtttopic=> "/text2text/receive", + ), + ) +julia> client, connection = MakeConnection("test.mosquitto.org", 1883) +julia> agent = YiemAgent.bsommelier( + client, + msgMeta, + agentConfig, + name= "assistant", + id= "555", # agent instance id + tools=tools, + ) +``` + +# TODO +- [] update docstring +- [x] implement the function + +# Signature +""" +@kwdef mutable struct sommelier <: agent + name::String # agent name + id::String # agent id + config::Dict # agent config + tools::Dict + thinkinglimit::Integer # thinking round limit + thinkingcount::Integer # used to count attempted round of a task + + """ Memory + Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3 + NO "system" message in chathistory because I want to add it at the inference time + chathistory= [ + Dict(:name=>"user", :text=> "Wassup!", :timestamp=> Dates.now()), + Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()), + ] + + """ + chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}() + + maxHistoryMsg::Integer # 21th and earlier messages will get summarized + keywordinfo::Dict{Symbol, Any} = Dict{Symbol, Any}( + :customerinfo => Dict{Symbol, Any}(), + :storeinfo => Dict{Symbol, Any}(), + ) + mctstree::Dict{Symbol, Any} = Dict{Symbol, Any}() + + # 1-historyPoint is in Dict{Symbol, Any} and compose of: + # state, statevalue, thought, action, observation + plan::Dict{Symbol, Any} = Dict{Symbol, Any}( + + # store 3 to 5 best plan AI frequently used to avoid having to search MCTS all the time + # each plan is in [historyPoint_1, historyPoint_2, ...] format + :existingplan => Vector(), + + :activeplan => Dict{Symbol, Any}(), # current using plan + :currenttrajectory=> Dict{Symbol, Any}(), # store question, thought, action, observation, ... + ) + +end + +function sommelier( + config::Dict = Dict( + :mqttServerInfo=> Dict( + :broker=> nothing, + :port=> nothing, + ), + :receivemsg=> Dict( + :prompt=> nothing, # topic to receive prompt i.e. frontend send msg to this topic + :internal=> nothing, + ), + :thirdPartyService=> Dict( + :text2textinstruct=> nothing, + :text2textchat=> nothing, + ), + ) + ; + name::String= "Assistant", + id::String= string(uuid4()), + tools::Dict= Dict( + :chatbox=> Dict( + :name => "chatbox", + :description => "Useful for when you need to communicate with the user.", + :input => "Input should be a conversation to the user.", + :output => "" , + :func => nothing, + ), + ), + maxHistoryMsg::Integer= 20, + thinkinglimit::Integer= 5, + thinkingcount::Integer= 0, + ) + + #[NEXTVERSION] publish to a.config[:configtopic] to get a config. + #[NEXTVERSION] get a config message in a.mqttMsg_internal + #[NEXTVERSION] set agent according to config + + newAgent = sommelier( + name= name, + id= id, + config= config, + maxHistoryMsg= maxHistoryMsg, + tools= tools, + thinkinglimit= thinkinglimit, + thinkingcount= thinkingcount, + ) + + return newAgent +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +end # module type \ No newline at end of file diff --git a/src/type.jl b/src/type.jl index c70253a..f55ad1a 100644 --- a/src/type.jl +++ b/src/type.jl @@ -77,13 +77,15 @@ julia> agent = YiemAgent.bsommelier( # Signature """ -@kwdef mutable struct sommelier <: agent +mutable struct sommelier <: agent name::String # agent name id::String # agent id config::Dict # agent config tools::Dict - thinkinglimit::Integer # thinking round limit - thinkingcount::Integer # used to count attempted round of a task + maxiterations::Integer # how many thinking round + totalsample::Integer # how many sample in each thinking round + maxDepth::Integer # how many step ahead to be simulated start from current state into the future + maxHistoryMsg::Integer # 21th and earlier messages will get summarized """ Memory Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3 @@ -94,17 +96,50 @@ julia> agent = YiemAgent.bsommelier( ] """ - chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}() - - maxHistoryMsg::Integer # 21th and earlier messages will get summarized - keywordinfo::Dict{Symbol, Any} = Dict{Symbol, Any}( - :customerinfo => Dict{Symbol, Any}(), - :storeinfo => Dict{Symbol, Any}(), - ) - mctstree::Dict{Symbol, Any} = Dict{Symbol, Any}() + chathistory::Vector{Dict{Symbol, Any}} + keywordinfo::Dict{Symbol, Any} # 1-historyPoint is in Dict{Symbol, Any} and compose of: # state, statevalue, thought, action, observation + plan::Dict{Symbol, Any} +end + +function sommelier( + config::Dict = Dict( + :mqttServerInfo=> Dict( + :broker=> nothing, + :port=> nothing, + ), + :receivemsg=> Dict( + :prompt=> nothing, # topic to receive prompt i.e. frontend send msg to this topic + :internal=> nothing, + ), + :thirdPartyService=> Dict( + :text2textinstruct=> nothing, + :text2textchat=> nothing, + ), + ) + ; + name::String= "Assistant", + id::String= string(uuid4()), + tools::Dict= Dict( + :chatbox=> Dict( + :name => "chatbox", + :description => "Useful for when you need to communicate with the user.", + :input => "Input should be a conversation to the user.", + :output => "" , + :func => nothing, + ), + ), + maxiterations::Integer= 3, + totalsample::Integer= 3, + maxDepth::Integer= 3, + maxHistoryMsg::Integer= 20, + chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}(), + keywordinfo::Dict{Symbol, Any} = Dict{Symbol, Any}( + :customerinfo => Dict{Symbol, Any}(), + :storeinfo => Dict{Symbol, Any}(), + ), plan::Dict{Symbol, Any} = Dict{Symbol, Any}( # store 3 to 5 best plan AI frequently used to avoid having to search MCTS all the time @@ -113,45 +148,7 @@ julia> agent = YiemAgent.bsommelier( :activeplan => Dict{Symbol, Any}(), # current using plan :currenttrajectory=> Dict{Symbol, Any}(), # store question, thought, action, observation, ... - ) - - # put incoming message here. waiting for further processing - receiveUserMsgChannel::Channel{Dict} = Channel{Dict}(8) # for incoming user communication - receiveInternalMsgChannel::Channel{Dict} = Channel{Dict}(8) # for internal communication -end - -function sommelier( - receiveUserMsgChannel::Channel, - receiveInternalMsgChannel::Channel, - config::Dict = Dict( - :mqttServerInfo=> Dict( - :broker=> nothing, - :port=> nothing, - ), - :receivemsg=> Dict( - :prompt=> nothing, # topic to receive prompt i.e. frontend send msg to this topic - :internal=> nothing, - ), - :thirdPartyService=> Dict( - :text2textinstruct=> nothing, - :text2textchat=> nothing, - ), ) - ; - name::String= "Assistant", - id::String= string(uuid4()), - tools::Dict= Dict( - :chatbox=> Dict( - :name => "chatbox", - :description => "Useful for when you need to communicate with the user.", - :input => "Input should be a conversation to the user.", - :output => "" , - :func => nothing, - ), - ), - maxHistoryMsg::Integer= 20, - thinkinglimit::Integer= 5, - thinkingcount::Integer= 0, ) #[NEXTVERSION] publish to a.config[:configtopic] to get a config. @@ -159,16 +156,18 @@ function sommelier( #[NEXTVERSION] set agent according to config newAgent = sommelier( - receiveUserMsgChannel= receiveUserMsgChannel, - receiveInternalMsgChannel= receiveInternalMsgChannel, - name= name, - id= id, - config= config, - maxHistoryMsg= maxHistoryMsg, - tools= tools, - thinkinglimit= thinkinglimit, - thinkingcount= thinkingcount, - ) + name, + id, + config, + tools, + maxiterations, + totalsample, + maxDepth, + maxHistoryMsg, + chathistory, + keywordinfo, + plan, + ) return newAgent end