This commit is contained in:
narawat lamaiin
2024-05-17 10:44:28 +07:00
parent e9c91fdb4d
commit f820fe1143
4 changed files with 315 additions and 79 deletions

View File

@@ -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

226
src/type copy.jl Normal file
View File

@@ -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

View File

@@ -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