From bcd525a7d988d30f32051f90327044d6071183b0 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Wed, 17 Apr 2024 07:49:02 +0700 Subject: [PATCH] update --- src/interface.jl | 152 +++++++++++++++++++++++++++++++++------------ src/type.jl | 52 +--------------- src/util.jl | 158 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 271 insertions(+), 91 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index 8274af7..7f02fa4 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -1,6 +1,6 @@ module interface -export addNewMessage +export addNewMessage, conversation using JSON3, DataStructures, Dates, UUIDs, HTTP, Random using GeneralUtils @@ -33,64 +33,89 @@ using ..type, ..util, ..llmfunction # ---------------------------------------------- 100 --------------------------------------------- # - -""" Add new message to agent. +""" Chat with llm. Arguments\n ----- a::agent an agent - role::String - message sender role i.e. system, user or assistant - text::String - message text - + Return\n ----- - nothing + None Example\n ----- ```jldoctest - julia> using YiemAgent, MQTTClient, GeneralUtils - julia> client, connection = MakeConnection("test.mosquitto.org", 1883) - julia> connect(client, connection) - julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic") - julia> agentConfig = Dict( - :receiveprompt=>Dict( - :mqtttopic=> "testtopic/receive", - ), - :receiveinternal=>Dict( - :mqtttopic=> "testtopic/internal", - ), - :text2text=>Dict( - :mqtttopic=> "testtopic/text2text", - ), - ) - julia> a = YiemAgent.sommelier( - client, - msgMeta, - agentConfig, - ) - julia> YiemAgent.addNewMessage(a, "user", "hello") + julia> using JSON3, UUIDs, Dates, FileIO, MQTTClient, ChatAgent + julia> const mqttBroker = "mqtt.yiem.cc" + julia> mqttclient, connection = MakeConnection(mqttBroker, 1883) + julia> tools=Dict( # update input format + "askbox"=>Dict( + :description => "Useful for when you need to ask the user for more context. Do not ask the user their own question.", + :input => "Input is a text in JSON format.{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}", + :output => "" , + :func => nothing, + ), + ) + julia> msgMeta = Dict( + :msgPurpose=> "updateStatus", + :from=> "agent", + :to=> "llmAI", + :requestresponse=> "request", + :sendto=> "", # destination topic + :replyTo=> "agent/api/v0.1.0/txt/response", # requester ask responseer to send reply to this topic + :repondToMsgId=> "", # responseer is responseing to this msg id + :taskstatus=> "", # "complete", "fail", "waiting" or other status + :timestamp=> Dates.now(), + :msgId=> "$(uuid4())", + ) + julia> a = ChatAgent.agentReflex( + "Jene", + mqttclient, + msgMeta, + agentConfigTopic, # I need a function to send msg to config topic to get load balancer + role=:sommelier, + tools=tools + ) + julia> newAgent = ChatAgent.agentReact(agent) + julia> response = ChatAgent.conversation(newAgent, "Hi! how are you?") ``` Signature\n ----- """ -function addNewMessage(a::T1, role::String, text::T2; - maximumMsg::Integer=20) where {T1<:agent, T2<:AbstractString} - if role ∉ ["system", "user", "assistant"] # guard against typo - error("role is not in agent.availableRole $(@__LINE__)") +function conversation(a::agentReflex, usermsg::String; attemptlimit::Int=3) + a.attemptlimit = attemptlimit + workstate = nothing + response = nothing + + _ = addNewMessage(a, "user", usermsg) + isuseplan = isUsePlans(a) + # newinfo = extractinfo(a, usermsg) + # a.env = newinfo !== nothing ? updateEnvState(a, newinfo) : a.env + @show isuseplan + + if isuseplan # use plan before responding + if haskey(a.memory[:shortterm], "User:") == false #TODO should change role if user want to buy wine. + a.memory[:shortterm]["User:"] = usermsg + end + workstate, response = work(a) end - #TODO summarize the oldest 10 message - if length(a.chathistory) > maximumMsg - summarize(a.chathistory) + # if LLM using askbox, use returning msg form askbox as conversation response + if workstate == "askbox" || workstate == "formulatedUserResponse" + #TODO paraphrase msg so that it is human friendlier word. else - d = Dict(:role=> role, :text=> text, :timestamp=> Dates.now()) - push!(a.chathistory, d) + response = chat_mistral_openorca(a) + response = split(response, "\n\n")[1] + response = split(response, "\n\n")[1] end + + response = removeTrailingCharacters(response) + _ = addNewMessage(a, "assistant", response) + + return response end @@ -100,4 +125,53 @@ end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + end # module interface \ No newline at end of file diff --git a/src/type.jl b/src/type.jl index 58c4457..37ba4a7 100644 --- a/src/type.jl +++ b/src/type.jl @@ -1,6 +1,6 @@ module type -export agent, sommelier, clearhistory +export agent, sommelier using Dates, UUIDs, DataStructures, JSON3 using GeneralUtils @@ -165,56 +165,6 @@ function sommelier( return newAgent end -""" Clear agent chat history. - - Arguments\n - ----- - a::agent - an agent - - Return\n - ----- - nothing - - Example\n - ----- - ```jldoctest - julia> using YiemAgent, MQTTClient, GeneralUtils - julia> client, connection = MakeConnection("test.mosquitto.org", 1883) - julia> connect(client, connection) - julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic") - julia> agentConfig = Dict( - :receiveprompt=>Dict( - :mqtttopic=> "testtopic/receive", - ), - :receiveinternal=>Dict( - :mqtttopic=> "testtopic/internal", - ), - :text2text=>Dict( - :mqtttopic=> "testtopic/text2text", - ), - ) - julia> a = YiemAgent.sommelier( - client, - msgMeta, - agentConfig, - ) - julia> YiemAgent.addNewMessage(a, "user", "hello") - julia> YiemAgent.clearhistory(a) - ``` - - Signature\n - ----- -""" -function clearhistory(a::T) where {T<:agent} - empty!(a.chathistory) - empty!(a.mctstree) - empty!(a.plan[:activeplan]) - empty!(a.plan[:currenttrajectory]) -end - - - diff --git a/src/util.jl b/src/util.jl index 6e4581b..e04c8fe 100644 --- a/src/util.jl +++ b/src/util.jl @@ -1,12 +1,168 @@ module util -# export sendReceivePrompt +export clearhistory, addNewMessage using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3 using GeneralUtils using ..type # ---------------------------------------------- 100 --------------------------------------------- # + +""" Clear agent chat history. + + Arguments\n + ----- + a::agent + an agent + + Return\n + ----- + nothing + + Example\n + ----- + ```jldoctest + julia> using YiemAgent, MQTTClient, GeneralUtils + julia> client, connection = MakeConnection("test.mosquitto.org", 1883) + julia> connect(client, connection) + julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic") + julia> agentConfig = Dict( + :receiveprompt=>Dict( + :mqtttopic=> "testtopic/receive", + ), + :receiveinternal=>Dict( + :mqtttopic=> "testtopic/internal", + ), + :text2text=>Dict( + :mqtttopic=> "testtopic/text2text", + ), + ) + julia> a = YiemAgent.sommelier( + client, + msgMeta, + agentConfig, + ) + julia> YiemAgent.addNewMessage(a, "user", "hello") + julia> YiemAgent.clearhistory(a) + ``` + + Signature\n + ----- +""" +function clearhistory(a::T) where {T<:agent} + empty!(a.chathistory) + empty!(a.mctstree) + empty!(a.plan[:activeplan]) + empty!(a.plan[:currenttrajectory]) +end + + +""" Add new message to agent. + + Arguments\n + ----- + a::agent + an agent + role::String + message sender role i.e. system, user or assistant + text::String + message text + + Return\n + ----- + nothing + + Example\n + ----- + ```jldoctest + julia> using YiemAgent, MQTTClient, GeneralUtils + julia> client, connection = MakeConnection("test.mosquitto.org", 1883) + julia> connect(client, connection) + julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic") + julia> agentConfig = Dict( + :receiveprompt=>Dict( + :mqtttopic=> "testtopic/receive", + ), + :receiveinternal=>Dict( + :mqtttopic=> "testtopic/internal", + ), + :text2text=>Dict( + :mqtttopic=> "testtopic/text2text", + ), + ) + julia> a = YiemAgent.sommelier( + client, + msgMeta, + agentConfig, + ) + julia> YiemAgent.addNewMessage(a, "user", "hello") + ``` + + Signature\n + ----- +""" +function addNewMessage(a::T1, role::String, text::T2; + maximumMsg::Integer=20) where {T1<:agent, T2<:AbstractString} + if role ∉ ["system", "user", "assistant"] # guard against typo + error("role is not in agent.availableRole $(@__LINE__)") + end + + #TODO summarize the oldest 10 message + if length(a.chathistory) > maximumMsg + summarize(a.chathistory) + else + d = Dict(:role=> role, :text=> text, :timestamp=> Dates.now()) + push!(a.chathistory, d) + end +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +