diff --git a/src/interface.jl b/src/interface.jl index 5d1ebc3..15ba503 100755 --- a/src/interface.jl +++ b/src/interface.jl @@ -95,7 +95,7 @@ function agentReact( """Use the following format: Question: the input question your user is asking and you must answer Plan: first you should always think about the question and the info you have thoroughly then extract and devise a complete plan to find the answer (pay attention to variables and their corresponding numerals). - Thought: ask yourself do you have all the info you need? And what to do (pay attention to correct numeral calculation and commonsense). + Thought: ask yourself do you have all the info you need? And what to do according to the plan (pay attention to correct numeral calculation and commonsense). Act: the tool that match your thought, should be one of {toolnames} ActInput: the input to the action (pay attention to the tool's input) Obs: the result of the action @@ -313,7 +313,7 @@ end julia> respond = ChatAgent.conversation(newAgent, "Hi! how are you?") ``` """ -function conversation(a::T, usermsg::String) where {T<:agent} #WORKING +function conversation(a::T, usermsg::String) where {T<:agent} respond = nothing if a.thought != "nothing" # continue thought @@ -350,15 +350,125 @@ end """ Continuously run llm functions except when llm is getting Answer: or chatbox. """ +function work(a::T, prompt::String, maxround::Int=3) where {T<:agent} + respond = nothing + while true + a.thoughtround += 1 + @show a.thoughtround + toolname = nothing + toolinput = nothing + + #WORKING force answer if thoughtround exceed limit + if a.thoughtround > a.thoughtlimit + a.thought *= "Thought $(a.thoughtround): I think I know the answer." + prompt = a.thought + end + @show prompt + respond = sendReceivePrompt(a, prompt) + + headerToDetect = nothing + if a.thoughtround == 1 + try + respond = split(respond, "Obs:")[1] + headerToDetect = ["Question:", "Plan:", "Thought:", "Act:", "ActInput:", "Obs:", "...", "Answer:", + "Conclusion:", "Summary:"] + catch + end + else + try + respond = split(respond, "Obs $(a.thoughtround):")[1] + headerToDetect = ["Question $(a.thoughtround):", "Plan $(a.thoughtround):", + "Thought $(a.thoughtround):", "Act $(a.thoughtround):", + "ActInput $(a.thoughtround):", "Obs $(a.thoughtround):", + "...", "Answer:", + "Conclusion:", "Summary:"] + catch + end + end + + headers = detectCharacters(respond, headerToDetect) + chunkedtext = chunktext(respond, headers) + + Answer = findDetectedCharacter(headers, "Answer:") + AnswerInd = length(Answer) != 0 ? Answer[1] : nothing + Act = findDetectedCharacter(headers, "Act $(a.thoughtround):") + if length(Answer) == 1 && length(Act) == 0 + a.thought = "nothing" # question finished, no more thought + a.thoughtround = 0 + respond = chunkedtext[AnswerInd][:body] + _ = addNewMessage(a, "assistant", respond) + break + else + + # check for tool being called + ActHeader = a.thoughtround == 1 ? "Act:" : "Act $(a.thoughtround):" + if length(findDetectedCharacter(headers, ActHeader)) != 0 # check whether there is Act: in a respond + ActInd = findDetectedCharacter(headers, ActHeader)[1] + toolname = toolNameBeingCalled(chunkedtext[ActInd][:body], a.tools) + end + ActInputHeader = a.thoughtround == 1 ? "ActInput:" : "ActInput $(a.thoughtround):" + if length(findDetectedCharacter(headers, ActInputHeader)) != 0 # check whether there is ActInput: in a respond + ActInputInd = findDetectedCharacter(headers, ActInputHeader)[1] + toolinput = chunkedtext[ActInputInd][:body] + end + + # clean up + if occursin(" \"", toolinput) + toolinput = GeneralUtils.getStringBetweenCharacters(toolinput, " \"", "\"\n") + else + toolinput = GeneralUtils.getStringBetweenCharacters(toolinput, " ", "\n") + end + @show toolname #BUG llm not specify tools + @show toolinput + if toolname === nothing || toolinput === nothing + println("toolname $toolname toolinput $toolinput retry thinking") + a.thoughtround -= 1 + continue + end + + if a.thought == "nothing" + thought = "" + for i in chunkedtext + header = i[:header] + header = replace(header, ":"=>" $(a.thoughtround):") # add number so that llm not confused + body = i[:body] + thought *= "$header $body" + end + a.thought = prompt * thought #BUG should be prompt + thought + else + a.thought *= respond + end + + + if toolname == "chatbox" # chat with user + a.thought *= toolinput + respond = toolinput + _ = addNewMessage(a, "assistant", respond) + break + else # function call + println("//////////// $(a.thoughtround)") + f = a.tools[Symbol(toolname)][:func] + _result = f(toolinput) + if _result != "No info available." #TODO for use with wikisearch(). Not good for other tools + _result = makeSummary(a, _result) + end + result = "Obs $(a.thoughtround): $_result\n" + a.thought *= result + prompt = a.thought + end + end + end + @show respond + return respond +end + # function work(a::T, prompt::String, maxround::Int=3) where {T<:agent} # respond = nothing # while true # a.thoughtround += 1 -# @show a.thoughtround # toolname = nothing # toolinput = nothing -# #WORKING force answer if thoughtround exceed limit # if a.thoughtround > a.thoughtlimit # a.thought *= "Thought $(a.thoughtround): I think I know the answer." # prompt = a.thought @@ -392,6 +502,19 @@ end # chunkedtext = chunktext(respond, headers) # @show chunkedtext +# if a.thought == "nothing" +# thought = "" +# for i in chunkedtext +# header = i[:header] +# header = replace(header, ":"=>" $(a.thoughtround):") # add number so that llm not confused +# body = i[:body] +# thought *= "$header $body" +# end +# a.thought = prompt * thought +# else +# a.thought *= respond +# end + # Answer = findDetectedCharacter(headers, "Answer:") # AnswerInd = length(Answer) != 0 ? Answer[1] : nothing # Act = findDetectedCharacter(headers, "Act $(a.thoughtround):") @@ -402,20 +525,11 @@ end # _ = addNewMessage(a, "assistant", respond) # break # else - # # check for tool being called # ActHeader = a.thoughtround == 1 ? "Act:" : "Act $(a.thoughtround):" -# if length(findDetectedCharacter(headers, ActHeader)) != 0 # check whether there is Act: in a respond -# ActInd = findDetectedCharacter(headers, ActHeader)[1] -# toolname = toolNameBeingCalled(chunkedtext[ActInd][:body], a.tools) -# end -# ActInputHeader = a.thoughtround == 1 ? "ActInput:" : "ActInput $(a.thoughtround):" -# if length(findDetectedCharacter(headers, ActInputHeader)) != 0 # check whether there is ActInput: in a respond -# ActInputInd = findDetectedCharacter(headers, ActInputHeader)[1] -# toolinput = chunkedtext[ActInputInd][:body] -# end - -# # clean up +# ActInd = findDetectedCharacter(headers, ActHeader)[1] +# toolname = toolNameBeingCalled(chunkedtext[ActInd][:body], a.tools) +# toolinput = chunkedtext[ActInd+1][:body] # if occursin(" \"", toolinput) # toolinput = GeneralUtils.getStringBetweenCharacters(toolinput, " \"", "\"\n") # else @@ -423,28 +537,7 @@ end # end # @show toolname #BUG llm not specify tools # @show toolinput -# if toolname === nothing || toolinput === nothing -# println("retry think") -# a.thoughtround -= 1 -# continue -# end - - - - -# if a.thought == "nothing" -# thought = "" -# for i in chunkedtext -# header = i[:header] -# header = replace(header, ":"=>" $(a.thoughtround):") # add number so that llm not confused -# body = i[:body] -# thought *= "$header $body" -# end -# a.thought = prompt * thought #BUG should be prompt + thought -# else -# a.thought *= respond -# end - + # if toolname == "chatbox" # chat with user # a.thought *= toolinput @@ -468,106 +561,6 @@ end # return respond # end -function work(a::T, prompt::String, maxround::Int=3) where {T<:agent} - respond = nothing - while true - a.thoughtround += 1 - toolname = nothing - toolinput = nothing - - #WORKING force answer if thoughtround exceed limit - if a.thoughtround > a.thoughtlimit - a.thought *= "Thought $(a.thoughtround): I think I know the answer." - prompt = a.thought - end - @show prompt - respond = sendReceivePrompt(a, prompt) - - headerToDetect = nothing - if a.thoughtround == 1 - try - respond = split(respond, "Obs:")[1] - @show respond - headerToDetect = ["Question:", "Plan:", "Thought:", "Act:", "ActInput:", "Obs:", "...", "Answer:", - "Conclusion:", "Summary:"] - catch - end - else - try - respond = split(respond, "Obs $(a.thoughtround):")[1] - @show respond - headerToDetect = ["Question $(a.thoughtround):", "Plan $(a.thoughtround):", - "Thought $(a.thoughtround):", "Act $(a.thoughtround):", - "ActInput $(a.thoughtround):", "Obs $(a.thoughtround):", - "...", "Answer:", - "Conclusion:", "Summary:"] - catch - end - end - - headers = detectCharacters(respond, headerToDetect) - chunkedtext = chunktext(respond, headers) - @show chunkedtext - - if a.thought == "nothing" - thought = "" - for i in chunkedtext - header = i[:header] - header = replace(header, ":"=>" $(a.thoughtround):") # add number so that llm not confused - body = i[:body] - thought *= "$header $body" - end - a.thought = prompt * thought - else - a.thought *= respond - end - - Answer = findDetectedCharacter(headers, "Answer:") - AnswerInd = length(Answer) != 0 ? Answer[1] : nothing - Act = findDetectedCharacter(headers, "Act $(a.thoughtround):") - if length(Answer) == 1 && length(Act) == 0 - a.thought = "nothing" # question finished, no more thought - a.thoughtround = 0 - respond = chunkedtext[AnswerInd][:body] - _ = addNewMessage(a, "assistant", respond) - break - else - # check for tool being called - ActHeader = a.thoughtround == 1 ? "Act:" : "Act $(a.thoughtround):" - ActInd = findDetectedCharacter(headers, ActHeader)[1] - toolname = toolNameBeingCalled(chunkedtext[ActInd][:body], a.tools) - toolinput = chunkedtext[ActInd+1][:body] - if occursin(" \"", toolinput) - toolinput = GeneralUtils.getStringBetweenCharacters(toolinput, " \"", "\"\n") - else - toolinput = GeneralUtils.getStringBetweenCharacters(toolinput, " ", "\n") - end - @show toolname #BUG llm not specify tools - @show toolinput - - - if toolname == "chatbox" # chat with user - a.thought *= toolinput - respond = toolinput - _ = addNewMessage(a, "assistant", respond) - break - else # function call - println("//////////// $(a.thoughtround)") - f = a.tools[Symbol(toolname)][:func] - _result = f(toolinput) - if _result != "No info available." #TODO for use with wikisearch(). Not good for other tools - _result = makeSummary(a, _result) - end - result = "Obs $(a.thoughtround): $_result\n" - a.thought *= result - prompt = a.thought - end - end - end - @show respond - return respond -end - """ make a conversation summary.