This commit is contained in:
2023-11-19 23:29:02 +00:00
parent 08d8b28b99
commit 6486ab5fb5

View File

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