update
This commit is contained in:
212
src/interface.jl
212
src/interface.jl
@@ -60,7 +60,8 @@ abstract type agent end
|
||||
context::String = "nothing" # internal thinking area
|
||||
tools::Union{Dict, Nothing} = nothing
|
||||
thought::String = "nothing" # contain unfinished thoughts for ReAct agent only
|
||||
thoughtround::Int = 0
|
||||
thoughtround::Int = 0 # no. of thinking round
|
||||
thoughtlimit::Int = 5 # thinking round limit
|
||||
thinkingMode::Union{Dict, Nothing} = nothing
|
||||
end
|
||||
|
||||
@@ -98,10 +99,9 @@ function agentReact(
|
||||
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
|
||||
... (this Plan/Thought/Act/ActInput/Obs loop can repeat N times until you know the answer.)
|
||||
Answer: Answer of the original question.
|
||||
|
||||
When you get "No info available." 3 times in a row, just answer the question.
|
||||
... (this Plan/Thought/Act/ActInput/Obs can repeat N times until you know the answer.)
|
||||
Thought: I think I know the answer
|
||||
Answer: Answer of the original question
|
||||
|
||||
Begin!""",
|
||||
),
|
||||
@@ -109,7 +109,7 @@ function agentReact(
|
||||
:wikisearch=>Dict(
|
||||
:name => "wikisearch",
|
||||
:description => "Useful for when you need to search the Internet",
|
||||
:input => "Input should be a keyword not a question.",
|
||||
:input => "Input should be keywords not a question.",
|
||||
:output => "",
|
||||
:func => wikisearch, # put function here
|
||||
),
|
||||
@@ -350,21 +350,27 @@ end
|
||||
"""
|
||||
Continuously run llm functions except when llm is getting Answer: or chatbox.
|
||||
"""
|
||||
function work(a::T, prompt::String) where {T<:agent}
|
||||
function work(a::T, prompt::String, maxround::Int=3) where {T<:agent}
|
||||
respond = nothing
|
||||
while true
|
||||
a.thoughtround += 1
|
||||
@show prompt
|
||||
@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)
|
||||
@show respond
|
||||
|
||||
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
|
||||
@@ -372,6 +378,7 @@ function work(a::T, prompt::String) where {T<:agent}
|
||||
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):",
|
||||
@@ -382,23 +389,9 @@ function work(a::T, prompt::String) where {T<:agent}
|
||||
end
|
||||
|
||||
headers = detectCharacters(respond, headerToDetect)
|
||||
@show headers
|
||||
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 = thought
|
||||
else
|
||||
a.thought *= respond
|
||||
end
|
||||
|
||||
Answer = findDetectedCharacter(headers, "Answer:")
|
||||
AnswerInd = length(Answer) != 0 ? Answer[1] : nothing
|
||||
Act = findDetectedCharacter(headers, "Act $(a.thoughtround):")
|
||||
@@ -409,18 +402,49 @@ function work(a::T, prompt::String) where {T<:agent}
|
||||
_ = 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 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
|
||||
@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 = thought #BUG should be prompt + thought
|
||||
else
|
||||
a.thought *= respond
|
||||
end
|
||||
|
||||
|
||||
if toolname == "chatbox" # chat with user
|
||||
a.thought *= toolinput
|
||||
@@ -435,7 +459,6 @@ function work(a::T, prompt::String) where {T<:agent}
|
||||
_result = makeSummary(a, _result)
|
||||
end
|
||||
result = "Obs $(a.thoughtround): $_result\n"
|
||||
@show result
|
||||
a.thought *= result
|
||||
prompt = a.thought
|
||||
end
|
||||
@@ -445,6 +468,107 @@ function work(a::T, prompt::String) where {T<:agent}
|
||||
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 = 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.
|
||||
```jldoctest
|
||||
@@ -715,7 +839,22 @@ function toolNameBeingCalled(text::T, tools::Dict) where {T<:AbstractString}
|
||||
end
|
||||
|
||||
|
||||
function answerNow(a::T) where {T<:agent}
|
||||
prompt =
|
||||
"""
|
||||
<|im_start|>system
|
||||
{systemMsg}
|
||||
Your need to determine now whether you will use tools or actions to answer the question.
|
||||
|
||||
You have the following choices:
|
||||
If you don't need tools or actions to answer the question say, "{no}".
|
||||
If you need tools or actions to answer the question say, "{yes}".
|
||||
<|im_end|>
|
||||
"""
|
||||
prompt = replace(prompt, "{systemMsg}" => a.thought)
|
||||
|
||||
error("answerNow done")
|
||||
end
|
||||
|
||||
|
||||
#TODO
|
||||
@@ -761,23 +900,6 @@ function checkReasonableness(userMsg::String, context::String, tools)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function react_plan(text::String, firstlast="first")
|
||||
"Plan" * GeneralUtils.getStringBetweenCharacters(text, "Plan", "Thought", firstlast=firstlast)
|
||||
end
|
||||
|
||||
function react_thought(text::String, firstlast="first")
|
||||
"Thought" * GeneralUtils.getStringBetweenCharacters(text, "Thought", "Act", firstlast=firstlast)
|
||||
end
|
||||
|
||||
function react_act(text::String, firstlast="first")
|
||||
"Act" * GeneralUtils.getStringBetweenCharacters(text, "Act", "ActInput", firstlast=firstlast)
|
||||
end
|
||||
|
||||
function react_actinput(text::String, firstlast="first")
|
||||
"ActInput" * GeneralUtils.getStringBetweenCharacters(text, "ActInput", "Obs", firstlast=firstlast)
|
||||
end
|
||||
|
||||
"""
|
||||
Detect given characters. Output is a list of named tuple of detected char.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user