diff --git a/src/interface.jl b/src/interface.jl index 6dbceee..573051e 100755 --- a/src/interface.jl +++ b/src/interface.jl @@ -3,7 +3,8 @@ module interface export agentReact, agentReflex, addNewMessage, clearMessage, removeLatestMsg, conversation, writeEvaluationGuideline, - grading, analyze, selfReflext, actor_mistral_openorca2, formulateUserRespond + grading, analyze, selfReflext, actor_mistral_openorca2, formulateUserRespond, + extractinfo, updateEnvState using JSON3, DataStructures, Dates, UUIDs, HTTP using CommUtils, GeneralUtils @@ -453,25 +454,24 @@ function conversation(a::agentReflex, usermsg::String; attemptlimit::Int=3) respond = nothing a.earlierConversation = conversationSummary(a) + _ = addNewMessage(a, "user", usermsg) + isusetools = isUseTools(a, usermsg) - # determine thinking mode - a.thinkingmode = chooseThinkingMode(a, usermsg) - @show a.thinkingmode - - if a.thinkingmode == :no_thinking - _ = addNewMessage(a, "user", usermsg) - prompt = chat_mistral_openorca(a, usermsg) - println("") - @show prompt - respond = sendReceivePrompt(a, prompt) - respond = split(respond, "<|im_end|>")[1] - respond = replace(respond, "\n" => "") - _ = addNewMessage(a, "assistant", respond) - println("") - @show respond - else + #WORKING + if isusetools # use tools before responding respond = work(a, usermsg) end + + #WORKING + prompt = chat_mistral_openorca(a, usermsg) + println("") + @show prompt + respond = sendReceivePrompt(a, prompt) + respond = split(respond, "<|im_end|>")[1] + respond = replace(respond, "\n" => "") + _ = addNewMessage(a, "assistant", respond) + println("") + @show respond return respond end @@ -1110,13 +1110,68 @@ function goNogo(a) end +#WORKING +""" Determine whether LLM should go to next step. + +Args: + a, one of ChatAgent's agent. + +Return: + "Yes" or "no" decision to go next step. + +# Example +```jldoctest +julia> using ChatAgent, CommUtils +julia> agent = ChatAgent.agentReflex("Jene") +julia> shorttermMemory = OrderedDict{String, Any}( + "user:" => "What's the latest AMD GPU?", + "Plan 1:" => " To answer this question, I will need to search for the latest AMD GPU using the wikisearch tool.\n", + "Act 1:" => " wikisearch\n", + "Actinput 1:" => " amd gpu latest\n", + "Obs 1:" => "No info available for your search query.", + "Act 2:" => " wikisearch\n", + "Actinput 2:" => " amd graphics card latest\n", + "Obs 2:" => "No info available for your search query.") + +julia> decision = goNogo(agent) +"Yes" +``` +""" +function extractinfo(a, msg) + + prompt = + """ + <|im_start|>system + User message: + $msg + + Your job is to extract important info from user's message into keys and values using this format: key=value ,. + p.s.1 you can extract many key-value pairs. + <|im_end|> + + """ + + respond = sendReceivePrompt(a, prompt, temperature=0.0) +end +function updateEnvState(a, currentinfo, newinfo) + prompt = + """ + <|im_start|>system + Current state: + $currentinfo + New info: + $newinfo + + Your job is to update or add information from new info into the current state which use key-value format. + <|im_end|> + Updated Current State:\n + """ - - - + respond = sendReceivePrompt(a, prompt, temperature=0.0) +end diff --git a/src/type.jl b/src/type.jl index 47bd076..f3d3be7 100644 --- a/src/type.jl +++ b/src/type.jl @@ -38,7 +38,7 @@ abstract type agent end attemptlimit::Int = 5 # thinking round limit attempt::Int = 0 # attempted number step::Int = 0 # step number - thinkingmode::Symbol = :no_thinking + env::Dict = Dict() thinkingFormat::Union{Dict, Nothing} = nothing memory::Dict = Dict( :shortterm=> OrderedDict{String, Any}(), diff --git a/src/utils.jl b/src/utils.jl index 21a926a..29686fb 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -2,7 +2,7 @@ module utils export makeSummary, sendReceivePrompt, chunktext, extractStepFromPlan, checkTotalStepInPlan, detectCharacters, findDetectedCharacter, extract_number, toolNameBeingCalled, - chooseThinkingMode, conversationSummary, checkReasonableness, replaceHeaders, + isUseTools, conversationSummary, checkReasonableness, replaceHeaders, addShortMem!, splittext, dictToString, removeHeaders, keepOnlyKeys, experience using UUIDs, Dates, DataStructures @@ -89,12 +89,14 @@ end ) ``` """ -function sendReceivePrompt(a::T, prompt::String; max_tokens=256, timeout::Int=120) where {T<:agent} +function sendReceivePrompt(a::T, prompt::String; max_tokens=256, timeout::Int=120, + temperature::AbstractFloat=0.2) where {T<:agent} a.msgMeta[:msgId] = "$(uuid4())" # new msg id for each msg msg = Dict( :msgMeta=> a.msgMeta, :txt=> prompt, - :max_tokens=>max_tokens + :max_tokens=> max_tokens, + :temperature=> temperature, ) payloadChannel = Channel(1) @@ -340,52 +342,6 @@ function toolNameBeingCalled(text::T, tools::Dict) where {T<:AbstractString} return toolNameBeingCalled end - - -function chooseThinkingMode(a::agentReflex, usermsg::String) - thinkingmode = nothing - if length(a.memory[:log]) != 0 - thinkingmode = :continue_thinking - else - prompt = - """ - <|im_start|>system - {systemMsg} - You always use tools if there is a chance to impove your respond. - You have access to the following tools: - {tools} - Your job is to determine whether you will use tools or actions to respond. - - Choose one of the following choices: - Choice 1: If the user want to get wine say, "{yes}". - Choice 2: If you don't need to use tools or actions to respond to the stimulus say, "{no}". - <|im_end|> - - <|im_start|>user - {input} - <|im_end|> - <|im_start|>assistant - - """ - toollines = "" - for (toolname, v) in a.tools - if toolname ∉ ["chatbox", "nothing"] - toolline = "$toolname: $(v[:description]) $(v[:input]) $(v[:output])\n" - toollines *= toolline - end - end - prompt = replace(prompt, "{systemMsg}" => a.roles[a.role]) - prompt = replace(prompt, "{tools}" => toollines) - prompt = replace(prompt, "{input}" => usermsg) - result = sendReceivePrompt(a, prompt) - willusetools = GeneralUtils.getStringBetweenCharacters(result, "{", "}") - thinkingmode = willusetools == "yes" ? :new_thinking : :no_thinking - end - - return thinkingmode -end - - # function chooseThinkingMode(a::agentReflex, usermsg::String) # thinkingmode = nothing # if length(a.memory[:log]) != 0 @@ -429,32 +385,26 @@ end # return thinkingmode # end -function chooseThinkingMode(a::agentReflex, usermsg::String) - thinkingmode = nothing - if length(a.memory[:log]) != 0 - thinkingmode = :continue_thinking - else - prompt = +function isUseTools(a::agentReflex, usermsg::String) + prompt = """ <|im_start|>system {systemMsg} - You always use tools if there is a chance to impove your respond. You have access to the following tools: {tools} User message: {input} - Your job is to determine the following topics: - Topic 1: Is the user message show that they would like to get some wine? {Yes/No} - Topic 2: Is the user message show that they would like to get some cloth? {Yes/No} + Your job is to answer the following questions: + Question 1: From the user's message, Do you need to any tools before responding? Answer: {Yes/No/Not sure}. What will the you do? <|im_end|> <|im_start|>assistant - + Answer: """ toollines = "" for (toolname, v) in a.tools - if toolname ∉ ["chatbox", "nothing"] + if toolname ∉ [:chatbox] toolline = "$toolname: $(v[:description]) $(v[:input]) $(v[:output])\n" toollines *= toolline end @@ -462,19 +412,17 @@ function chooseThinkingMode(a::agentReflex, usermsg::String) prompt = replace(prompt, "{systemMsg}" => a.roles[a.role]) prompt = replace(prompt, "{tools}" => toollines) prompt = replace(prompt, "{input}" => usermsg) - result = sendReceivePrompt(a, prompt) - headers = detectCharacters(lessonwithcontext, ["Topic 1:", "Topic 2:"]) - chunkedtext = chunktext(result, headers) - @show chunkedtext - error(11) - willusetools = GeneralUtils.getStringBetweenCharacters(result, "{", "}") - thinkingmode = willusetools == "Yes" ? :new_thinking : :no_thinking - end + + result = sendReceivePrompt(a, prompt, temperature=0.2) - @show result - error(11) + # headers = detectCharacters(result, ["Question 1:", "Question 2:"]) + # chunkedtext = chunktext(result, headers) - return thinkingmode + if occursin("Yes", result) + return true + else + return false + end end