This commit is contained in:
2023-12-05 05:46:51 +00:00
parent fe99b2c3dc
commit 9216f87ef8
2 changed files with 140 additions and 54 deletions

View File

@@ -402,8 +402,7 @@ function actor_mistral_openorca(a::agentReflex)
# context = replace(context, "{earlierConversation}" => "My earlier talk with the user:\n$(a.earlierConversation)")
context = replace(context, "{env state}" => "")
context = replace(context, "{longterm memory}" => "")
mark = "$(a.attempt)"
context = replace(context, "{plan}" => "My plan:\n$(a.memory[:shortterm]["Plan $mark:"])")
context = replace(context, "{plan}" => "My plan:\n$(a.memory[:shortterm]["Plan $(a.attempt):"])")
prompt = replace(prompt, "{context}" => context)
return prompt
@@ -628,8 +627,6 @@ end
function work(a::agentReflex, usermsg::String)
respond = nothing
mark_plan = "$(a.attempt)"
mark_actor = "$(a.step)"
if a.thinkingmode == :new_thinking
a.earlierConversation = conversationSummary(a)
@@ -637,13 +634,11 @@ function work(a::agentReflex, usermsg::String)
a.memory[:shortterm]["user:"] = usermsg
a.memory[:log]["user:"] = usermsg
a.newplan = true
a.attempt = 1
elseif a.thinkingmode == :continue_thinking #TODO
println("continue_thinking!!")
_ = addNewMessage(a, "user", usermsg)
a.memory[:shortterm]["Obs $mark_actor:"] = usermsg
a.step += 1
a.memory[:log]["Obs $mark_actor:"] = usermsg
a.memory[:shortterm]["Obs $(a.step):"] = usermsg
a.memory[:log]["Obs $(a.step):"] = usermsg
else
error("undefined condition thinkingmode = $thinkingmode $(@__LINE__)")
end
@@ -671,10 +666,11 @@ function work(a::agentReflex, usermsg::String)
println("")
@show plan
a.memory[:shortterm]["Plan $mark_plan:"] = plan
a.memory[:log]["Plan $mark_plan:"] = plan
a.step = 1
a.attempt += 1
a.step = 0
a.newplan = false
a.memory[:shortterm]["Plan $(a.attempt):"] = plan
a.memory[:log]["Plan $(a.attempt):"] = plan
end
# enter actor loop
@@ -688,7 +684,7 @@ function work(a::agentReflex, usermsg::String)
respond = formulateUserRespond(a)
a.memory[:shortterm]["Respond $mark_plan:"] = respond
a.memory[:shortterm]["Respond $(a.attempt):"] = respond
a.memory[:log]["Respond $mark:"] = respond
# evaluate. if score < 8/10 try again.
@@ -725,7 +721,6 @@ function work(a::agentReflex, usermsg::String)
error("attempt limit reach")
break
end
a.attempt += 1
end
# good enough answer
@@ -766,6 +761,30 @@ function actor(a::agentReflex)
totalsteps = checkTotalStepInPlan(a)
while true # Actor loop
#WORKING
if a.step == 0
a.step = 1
else
decision, reason = goNogo(a)
println("")
@show decision
@show reason
a.memory[:shortterm]["Check $(a.step):"] = reason
if decision == "Yes" # in case there is a cancel, go straight to evaluation
a.step += 1
elseif decision == "No"
# repeat the latest step
# TODO delete Thought/Act/ActInput from the latest input
error("repete step $(a.step)")
elseif decision == "formulateUserRespond"
actorState = "formulateUserRespond"
msgToUser = nothing
break
else
error("undefined condition decision = $decision $(@__LINE__)")
end
end
@show a.step
if a.step <= totalsteps
@@ -795,14 +814,12 @@ function actor(a::agentReflex)
println("")
@show respond_actor
mark_plan = "$(a.attempt)"
mark_actor = "$(a.step)"
headerToDetect = ["Plan $mark_plan:",
"Thought $mark_actor:",
"Act $mark_actor:",
"ActInput $mark_actor:",
"Obs $mark_actor:",
"Check $mark_actor:",]
headerToDetect = ["Plan $(a.attempt):",
"Thought $(a.step):",
"Act $(a.step):",
"ActInput $(a.step):",
"Obs $(a.step):",
"Check $(a.step):",]
headers = detectCharacters(respond, headerToDetect)
chunkedtext = chunktext(respond, headers)
@show chunkedtext
@@ -810,34 +827,20 @@ function actor(a::agentReflex)
# add to memory
a.memory[:shortterm] = addShortMem!(a.memory[:shortterm], chunkedtext)
toolname = toolNameBeingCalled(chunkedtext["Act $mark_actor:"], a.tools)
toolinput = chunkedtext["ActInput $mark_actor:"]
toolname = toolNameBeingCalled(chunkedtext["Act $(a.step):"], a.tools)
toolinput = chunkedtext["ActInput $(a.step):"]
@show toolname
@show toolinput
if toolname == "chatbox" # chat with user
#TODO donot use chatbox to respond to user
respond = toolinput
msgToUser = respond
msgToUser = toolinput
actorState = toolname
break
elseif toolname == "formulateUserRespond"
actorState = "formulateUserRespond"
break
else # function call
f = a.tools[Symbol(toolname)][:func]
toolresult = f(a, toolinput)
@show toolresult
a.memory[:shortterm]["Obs $mark_actor:"] = toolresult
a.step += 1
go, reason = goNogo(a)
@show go
a.memory[:shortterm]["Check $mark_actor:"] = reason
if go == "No" # in case there is a cancel, go straight to evaluation
a.step -= 1
error(113)
end
a.memory[:shortterm]["Obs $(a.step):"] = toolresult
end
else #TODO finish all steps
actorState = "all steps done"
@@ -1086,7 +1089,7 @@ julia> shorttermMemory = OrderedDict{String, Any}(
"ActInput 2:" => " amd graphics card latest\n",
"Obs 2:" => "No info available for your search query.")
julia> report = formulateRespond(agent, shorttermMemory)
julia> report = formulateUserRespond(agent, shorttermMemory)
```
"""
function formulateUserRespond(a)
@@ -1160,15 +1163,34 @@ function goNogo(a)
end
end
# prompt =
# """
# <|im_start|>system
# Symbol meaning:
# Stimulus: the input user gives to you and you must respond
# Plan: a plan
# Thought: your thought
# Act: the action you took
# ActInput: the input to the action
# Obs: the result of the action
# Stimulus:
# $stimulus
# Your work:
# $work
# From your work, you job is to decide what to do next by choosing one of the following choices:
# If you are ready to do the next step of the plan say, "{Yes}". And what is the rationale behind the decision?
# If you need to repeat the latest step say, "{No}". And what is the rationale behind the decision?
# If you are ready to formulate a final respond to user original stimulus say, {formulateUserRespond}. And what is the rationale behind the decision?
# <|im_end|>
# """
prompt =
"""
<|im_start|>system
You have access to the following tools:
chatbox: Useful for when you need to ask a customer for more context. Input should be a conversation to customer.
wikisearch: Useful for when you need to search an encyclopedia Input is keywords and not a question.
Symbol:
Symbol meaning:
Stimulus: the input user gives to you and you must respond
Plan: a plan
Thought: your thought
@@ -1182,20 +1204,84 @@ function goNogo(a)
Your work:
$work
From your work, you job is to decide whether you're ready to do the next step in the plan by choosing one of the following choices:
If you are ready say, "{Yes}". And what is the rationale behind the decision?
If you are not ready say, "{No}". And what is the rationale behind the decision?
From the latest step in your work, you job is to choose one of the following choices:
If you need to repeat the latest step say, "{No}". And what is the rationale behind the decision?
If you are ready to do the next step of the plan say, "{Yes}". And what is the rationale behind the decision?
If you are ready to formulate a final respond to user original stimulus say, {formulateUserRespond}. And what is the rationale behind the decision?
<|im_end|>
"""
respond = sendReceivePrompt(a, prompt)
decision = GeneralUtils.getStringBetweenCharacters(respond, "{", "}")
start = findfirst("}", respond)[end] +1
reason = respond[start:end]
println("")
goNogo_raw = respond
@show goNogo_raw
decision = nothing
reason = nothing
if occursin("Yes", respond)
decision = "Yes"
startInd = startInd = findfirst("Yes", respond)[end] +2
reason = respond[startInd:end]
elseif occursin("No", respond)
decision = "No"
startInd = startInd = findfirst("No", respond)[end] +2
reason = respond[startInd:end]
elseif occursin("formulateUserRespond", respond)
decision = "formulateUserRespond"
startInd = startInd = findfirst("formulateUserRespond", respond)[end] +2
reason = respond[startInd:end]
else
end
return decision, reason
end
# function goNogo(a)
# stimulus = a.memory[:shortterm]["user:"]
# work = ""
# for (k, v) in a.memory[:shortterm]
# if k ∉ ["user:"]
# work *= "$k $v"
# end
# end
# prompt =
# """
# <|im_start|>system
# You have access to the following tools:
# chatbox: Useful for when you need to ask a customer for more context. Input should be a conversation to customer.
# wikisearch: Useful for when you need to search an encyclopedia Input is keywords and not a question.
# Symbol:
# Stimulus: the input user gives to you and you must respond
# Plan: a plan
# Thought: your thought
# Act: the action you took
# ActInput: the input to the action
# Obs: the result of the action
# Stimulus:
# $stimulus
# Your work:
# $work
# From your work, you job is to decide whether you're ready to do the next step in the plan by choosing one of the following choices:
# If you are ready say, "{Yes}". And what is the rationale behind the decision?
# If you are not ready say, "{No}". And what is the rationale behind the decision?
# <|im_end|>
# """
# respond = sendReceivePrompt(a, prompt)
# decision = GeneralUtils.getStringBetweenCharacters(respond, "{", "}")
# start = findfirst("}", respond)[end] +1
# reason = respond[start:end]
# return decision, reason
# end

View File

@@ -36,8 +36,8 @@ abstract type agent end
tools::Union{Dict, Nothing} = nothing
newplan::Bool = false # if true, new plan will be generated
attemptlimit::Int = 5 # thinking round limit
attempt::Int = 1 # attempted number
step::Int = 1 # step number
attempt::Int = 0 # attempted number
step::Int = 0 # step number
thinkingmode::Symbol = :no_thinking
thinkingFormat::Union{Dict, Nothing} = nothing
memory::Dict = Dict(