This commit is contained in:
narawat lamaiin
2024-04-17 06:49:41 +07:00
parent 08220bb282
commit 366266fb57

View File

@@ -9,34 +9,41 @@ using GeneralUtils
abstract type agent end abstract type agent end
""" A sommelier agent. """ A sommelier agent.
Arguments\n
-----
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\n
-----
name::String
Agent's name
id::String
Agent's ID
tools::Dict{Symbol, Any}
Agent's tools
maxHistoryMsg::Integer
max history message
Return\n
-----
nothing
Example: Example:
```jldoctest ```jldoctest
julia> using ChatAgent julia> using YiemAgent, MQTTClient, GeneralUtils
julia> mqttClientSpec = ( julia> msgMeta = GeneralUtils.generate_msgMeta(
clientName= "someclient", # name of this client "N/A",
clientID= "$(uuid4())", replyTopic = "/testtopic/prompt"
broker= "mqtt.yiem.ai", )
pubtopic= (imgAI="img/api/v0.0.1/gpu/request", julia> tools= Dict(
txtAI="txt/api/v0.1.0/gpu/request"), # this is where LLM server located
subtopic= (imgAI="agent/api/v0.1.0/img/respond",
txtAI="agent/api/v0.1.0/txt/respond"), # this is where this agent located
keepalive= 30,
)
julia> msgMeta = Dict(
:msgPurpose=> "updateStatus",
:from=> "agent",
:to=> "llmAI",
:requestrespond=> "request",
:sendto=> "", # destination topic
:replyTo=> "agent/api/v0.1.0/txt/respond", # requester ask responder to send reply to this topic
:repondToMsgId=> "", # responder is responding to this msg id
:taskstatus=> "", # "complete", "fail", "waiting" or other status
:timestamp=> Dates.now(),
:msgId=> "$(uuid4())",
)
julia> tools=Dict(
:chatbox=>Dict( :chatbox=>Dict(
:name => "chatbox", :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.", :description => "Useful only for when you need to ask the user for more info or context. Do not ask the user their own question.",
@@ -44,51 +51,53 @@ abstract type agent end
:output => "" , :output => "" ,
:func => nothing, :func => nothing,
), ),
:wikisearch=>Dict( )
:name => "wikisearch", julia> agentConfig = Dict(
:description => "Useful for when you need to search an encyclopedia.", :receiveprompt=>Dict(
:input => "Input is keywords and not a question.", :mqtttopic=> "/testtopic/prompt", # topic to receive prompt i.e. frontend send msg to this topic
:output => "",
:func => ChatAgent.wikisearch, # put function here
), ),
:winestock=>Dict( :receiveinternal=>Dict(
:name => "wineStock", :mqtttopic=> "/testtopic/internal", # receive topic for model's internal
:description => "useful for when you need to search your wine stock by wine description, price, name or ID.", ),
:input => "Input is a search query.", :text2text=>Dict(
:output => "Output are Wine name, description, price and ID" , :mqtttopic=> "/text2text/receive",
:func => ChatAgent.winestock,
), ),
) )
julia> agent = ChatAgent.agentReflex( julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
"Jene", julia> agent = YiemAgent.bsommelier(
role=:assistant, client,
mqttClientSpec=mqttClientSpec, msgMeta,
msgMeta=msgMeta, agentConfig,
tools=tools name= "assistant",
id= "555", # agent instance id
tools=tools,
) )
``` ```
Signature\n
-----
""" #TODO update document """ #TODO update document
@kwdef mutable struct sommelier <: agent @kwdef mutable struct sommelier <: agent
name::String name::String
id::String id::String
config::Dict config::Dict
tools::Union{Dict, Nothing} = nothing tools::Dict
attemptlimit::Int # thinking round limit thinkinglimit::Integer # thinking round limit
attemptcount::Int # used to count attempted round of a task thinkingcount::Integer # used to count attempted round of a task
# memory # memory
# Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3 # Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
# messages= [Dict(:role=>"system", :content=> "", :timestamp=> Dates.now()),] # messages= [Dict(:role=>"system", :content=> "", :timestamp=> Dates.now()),]
chathistory = Vector{Dict{Symbol, Any}}() # store messages history in the format :name=>"message" chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}() # store messages history in the format :name=>"message"
maxHistoryMsg::Int = 20 # 31th and earlier messages will get summarized maxHistoryMsg::Integer # 31th and earlier messages will get summarized
keywordinfo = Dict{Symbol, Any}( keywordinfo::Dict{Symbol, Any} = Dict{Symbol, Any}(
:userinfo => Dict{Symbol, Any}(), :userinfo => Dict{Symbol, Any}(),
:retailerinfo => Dict{Symbol, Any}(), :retailerinfo => Dict{Symbol, Any}(),
) )
mctstree = Dict{Symbol, Any}() mctstree::Dict{Symbol, Any} = Dict{Symbol, Any}()
# 1-history point compose of: # 1-history point compose of:
# state_t, statevalue_t, thought_t, action_t, observation_t, state_tplus1, statevalue_tplus1 # state_t, statevalue_t, thought_t, action_t, observation_t, state_tplus1, statevalue_tplus1
plan = 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 # store 3 to 5 best plan AI frequently used to avoid having to search MCTS all the time
:existingplan => Dict{Symbol, Any}(), :existingplan => Dict{Symbol, Any}(),
@@ -98,33 +107,33 @@ abstract type agent end
) )
# communication # communication
mqttClient::Any=nothing # store mqtt client for use in various internal functions mqttClient::Any= nothing # store mqtt client for use in various internal functions
msgMeta::Dict # a template for msgMeta msgMeta::Dict{Symbol, Any} # a template for msgMeta
# put incoming message here. waiting for further processing # put incoming message here. waiting for further processing
userMsg::Channel{Dict} = Channel{Dict}(32) # for user communication userMsg::Channel{Dict} = Channel{Dict}(8) # for user communication
internalMsg::Channel{Dict} = Channel{Dict}(32) # for internal communication internalMsg::Channel{Dict} = Channel{Dict}(8) # for internal communication
end end
function sommelier( function sommelier(
mqttClient, mqttClient,
msgMeta::Dict= GeneralUtils.generate_msgMeta("N/A"), msgMeta::Dict= GeneralUtils.generate_msgMeta("N/A"),
config::Dict = Dict( config::Dict = Dict(
:frontend=>Dict( :frontend=> Dict(
:mqtttopic=> nothing :mqtttopic=> nothing
), ),
:internal=>Dict( :internal=> Dict(
:mqtttopic=> nothing :mqtttopic=> nothing
), ),
:text2text=>Dict( :text2text=> Dict(
:mqtttopic=> "txt2text/api/v1/prompt/gpu", :mqtttopic=> "txt2text/api/v1/prompt/gpu",
), ),
) )
; ;
name::String="Assistant", name::String= "Assistant",
id::String=string(uuid4()), id::String= string(uuid4()),
tools::Dict=Dict( tools::Dict= Dict(
:chatbox=>Dict( :chatbox=> Dict(
:name => "chatbox", :name => "chatbox",
:description => "Useful for when you need to communicate with the user.", :description => "Useful for when you need to communicate with the user.",
:input => "Input should be a conversation to the user.", :input => "Input should be a conversation to the user.",
@@ -132,7 +141,9 @@ function sommelier(
:func => nothing, :func => nothing,
), ),
), ),
maxHistoryMsg::Int=20, maxHistoryMsg::Integer= 20,
thinkinglimit::Integer= 5,
thinkingcount::Integer= 0,
) )
#NEXTVERSION publish to a.config[:configtopic] to get a config. #NEXTVERSION publish to a.config[:configtopic] to get a config.
@@ -147,8 +158,8 @@ function sommelier(
msgMeta = msgMeta, msgMeta = msgMeta,
maxHistoryMsg = maxHistoryMsg, maxHistoryMsg = maxHistoryMsg,
tools = tools, tools = tools,
attemptlimit = 5, thinkinglimit = thinkinglimit,
attemptcount = 0, thinkingcount = thinkingcount,
) )
return newAgent return newAgent