This commit is contained in:
2023-12-07 03:27:36 +00:00
parent 5fa16dc1fe
commit 7765d0c4cf
3 changed files with 84 additions and 41 deletions

View File

@@ -503,7 +503,7 @@ function work(a::T, prompt::String, maxround::Int=3) where {T<:agent}
if a.thinkinground == 1
try
respond = split(respond, "Obs:")[1]
headerToDetect = ["Question:", "Plan:", "Thought:", "Act:", "ActInput:", "Obs:", "...", "Answer:",
headerToDetect = ["Question:", "Plan:", "Thought:", "Act:", "Actinput:", "Obs:", "...", "Answer:",
"Conclusion:", "Summary:"]
catch
end
@@ -512,7 +512,7 @@ function work(a::T, prompt::String, maxround::Int=3) where {T<:agent}
respond = split(respond, "Obs $(a.thinkinground):")[1]
headerToDetect = ["Question $(a.thinkinground):", "Plan $(a.thinkinground):",
"Thought $(a.thinkinground):", "Act $(a.thinkinground):",
"ActInput $(a.thinkinground):", "Obs $(a.thinkinground):",
"Actinput $(a.thinkinground):", "Obs $(a.thinkinground):",
"...", "Answer:",
"Conclusion:", "Summary:"]
catch
@@ -541,10 +541,10 @@ function work(a::T, prompt::String, maxround::Int=3) where {T<:agent}
ActInd = findDetectedCharacter(headers, ActHeader)[1]
toolname = toolNameBeingCalled(chunkedtext[ActInd][:body], a.tools)
end
ActInputHeader = a.thinkinground == 1 ? "ActInput:" : "ActInput $(a.thinkinground):"
if length(findDetectedCharacter(headers, ActInputHeader)) != 0 # check whether there is ActInput: in a respond
ActInputInd = findDetectedCharacter(headers, ActInputHeader)[1]
toolinput = chunkedtext[ActInputInd][:body]
ActinputHeader = a.thinkinground == 1 ? "Actinput:" : "Actinput $(a.thinkinground):"
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
@@ -688,7 +688,7 @@ function work(a::agentReflex, usermsg::String)
@show formulatedRespond
a.memory[:shortterm]["Respond $(a.attempt):"] = respond
a.memory[:log]["Respond $mark:"] = respond
a.memory[:log]["Respond $(a.attempt):"] = respond
# evaluate. if score < 8/10 try again.
guideline = writeEvaluationGuideline(a, a.memory[:shortterm]["user:"])
@@ -705,7 +705,11 @@ function work(a::agentReflex, usermsg::String)
@show analysis
lessonwithcontext = selfReflext(a, analysis)
@show lessonwithcontext
a.memory[:shortterm] = OrderedDict{String, Any}()
newdict = OrderedDict()
a.memory[:shortterm] = keepOnlyKeys(a.memory[:shortterm], ["user:"])
#TODO add lesson and context into longterm memory
headerToDetect = ["Lesson:", "Context:", ]
headers = detectCharacters(lessonwithcontext, headerToDetect)
@@ -775,6 +779,7 @@ function actor(a::agentReflex)
elseif decision == "No"
# repeat the latest step
a.memory[:shortterm] = removeHeaders(a.memory[:shortterm], a.step, ["Plan"])
a.memory[:log] = removeHeaders(a.memory[:log], a.step, ["Plan"])
println("repeating step $(a.step)")
elseif decision == "formulateUserRespond"
actorState = "formulateUserRespond"
@@ -802,7 +807,7 @@ function actor(a::agentReflex)
end
headerToDetect = ["Question:", "Plan:", "Thought:",
"Act:", "ActInput:", "Obs:", "...",
"Act:", "Actinput:", "Obs:", "...",
"Answer:", "Conclusion:", "Summary:"]
# replace headers with headers with correct attempt and step number
@@ -817,7 +822,7 @@ function actor(a::agentReflex)
headerToDetect = ["Plan $(a.attempt):",
"Thought $(a.step):",
"Act $(a.step):",
"ActInput $(a.step):",
"Actinput $(a.step):",
"Obs $(a.step):",
"Check $(a.step):",]
headers = detectCharacters(respond, headerToDetect)
@@ -826,9 +831,10 @@ function actor(a::agentReflex)
# add to memory
a.memory[:shortterm] = addShortMem!(a.memory[:shortterm], chunkedtext)
a.memory[:log] = addShortMem!(a.memory[:log], chunkedtext)
toolname = toolNameBeingCalled(chunkedtext["Act $(a.step):"], a.tools)
toolinput = chunkedtext["ActInput $(a.step):"]
toolinput = chunkedtext["Actinput $(a.step):"]
@show toolname
@show toolinput
@@ -845,6 +851,7 @@ function actor(a::agentReflex)
toolresult = f(a, toolinput)
@show toolresult
a.memory[:shortterm]["Obs $(a.step):"] = toolresult
a.memory[:log]["Obs $(a.step):"] = toolresult
end
else #TODO finish all steps
actorState = "all steps done"
@@ -919,10 +926,10 @@ 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",
"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",
"Actinput 2:" => " amd graphics card latest\n",
"Obs 2:" => "No info available for your search query.")
julia> guideline = "\nEvaluation Guideline:\n1. Check if the user's question has been understood correctly.\n2. Evaluate the steps taken to provide the information requested by the user.\n3. Assess whether the correct tools were used for the task.\n4. Determine if the user's request was successfully fulfilled.\n5. Identify any potential improvements or alternative approaches that could be used in the future.\n\nThe respond should include:\n1. A clear understanding of the user's question.\n2. The steps taken to provide the information requested by the user.\n3. An evaluation of whether the correct tools were used for the task.\n4. A confirmation or explanation if the user's request was successfully fulfilled.\n5. Any potential improvements or alternative approaches that could be used in the future."
julia> score = grading(agent, guideline, shorttermMemory)
@@ -984,10 +991,10 @@ 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",
"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",
"Actinput 2:" => " amd graphics card latest\n",
"Obs 2:" => "No info available for your search query.")
julia> report = analyze(agent, shorttermMemory)
```
@@ -1004,21 +1011,23 @@ function analyze(a)
Your work:
$shorttermMemory
Do each of the following steps in detail to analize your work.
You job is to do each of the following steps in detail to analize your work.
1. What happened?
2. List all relationships, each with cause and effect .
2. List all relationships, each with cause and effect.
3. Look at each relationship, figure out why it behaved that way.
4. What could you do to improve the respond?
<|im_end|>
<|im_start|>assistant
"""
respond = sendReceivePrompt(a, prompt, max_tokens=2048)
respond = sendReceivePrompt(a, prompt, max_tokens=1024, timeout=180)
println("")
analyze_prompt = prompt
@show analyze_prompt
println("")
println(">>>")
analyze_respond = respond
@show analyze_respond
@@ -1096,10 +1105,10 @@ 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",
"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",
"Actinput 2:" => " amd graphics card latest\n",
"Obs 2:" => "No info available for your search query.")
julia> report = formulateUserRespond(agent, shorttermMemory)
@@ -1118,7 +1127,7 @@ function formulateUserRespond(a)
Plan: a plan
Thought: your thought
Act: the action you took
ActInput: the input to the action
Actinput: the input to the action
Obs: the result of the action
Stimulus:
@@ -1153,10 +1162,10 @@ 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",
"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",
"Actinput 2:" => " amd graphics card latest\n",
"Obs 2:" => "No info available for your search query.")
julia> decision = goNogo(agent)
@@ -1175,7 +1184,7 @@ function goNogo(a)
# Plan: a plan
# Thought: your thought
# Act: the action you took
# ActInput: the input to the action
# Actinput: the input to the action
# Obs: the result of the action
# Stimulus:
@@ -1199,7 +1208,7 @@ function goNogo(a)
Plan: a plan
Thought: your thought
Act: the action you took
ActInput: the input to the action
Actinput: the input to the action
Obs: the result of the action
Stimulus:

View File

@@ -92,9 +92,9 @@ function agentReflex(
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 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)
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 can repeat N times until you know the answer.)
... (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
@@ -111,7 +111,7 @@ function agentReflex(
Use the following format:
Thought: you should always think about what to do according to step {step} of the plan and the info you have (pay attention to correct numeral calculation and commonsense).
Act: the action to take that match your thought, should be one of [{toolnames}]
ActInput: the input to the action (pay attention to the tool's input)
Actinput: the input to the action (pay attention to the tool's input)
Obs: the result of the action
""",
),
@@ -241,9 +241,9 @@ function agentReact(
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 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)
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 can repeat N times until you know the answer.)
... (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

View File

@@ -3,7 +3,7 @@ module utils
export makeSummary, sendReceivePrompt, chunktext, extractStepFromPlan, checkTotalStepInPlan,
detectCharacters, findDetectedCharacter, extract_number, toolNameBeingCalled,
chooseThinkingMode, conversationSummary, checkReasonableness, replaceHeaders,
addShortMem!, splittext, shortMemoryToString, removeHeaders
addShortMem!, splittext, shortMemoryToString, removeHeaders, keepOnlyKeys
using UUIDs, Dates, DataStructures
using CommUtils, GeneralUtils
@@ -181,7 +181,7 @@ end
julia> chunkedtext = ChatAgent.chunktext(text, headers)
OrderedDict{String, String} with 3 entries:
"Act 1:" => " wikisearch"
"ActInput 1:" => " latest AMD GPU"
"Actinput 1:" => " latest AMD GPU"
"Thought 1:" => " I should always think about..."
```
"""
@@ -515,13 +515,13 @@ Return: no return
julia> chunkedtext = OrderedDict{String, String}(
"Thought 1:" => " I should always think about...",
"Act 1:" => " wikisearch",
"ActInput 1:" => " latest AMD GPU",)
"Actinput 1:" => " latest AMD GPU",)
julia> shortMem = OrderedDict{String, Any}()
julia> addShortMem!(shortMem, chunkedtext)
OrderedDict{String, Any} with 3 entries:
"Thought 1:" => " I should always think about..."
"Act 1:" => " wikisearch"
"ActInput 1:" => " latest AMD GPU"
"Actinput 1:" => " latest AMD GPU"
```
"""
function addShortMem!(shortMem::OrderedDict{String, Any}, chunkedtext::T) where {T<:AbstractDict}
@@ -634,12 +634,12 @@ julia> shortMemory = OrderedDict(
"user:" => "Umm",
"Thought 1:" => "I like it.",
"Act 1:" => "chatbox",
"ActInput 1:" => "I get this one.",
"Actinput 1:" => "I get this one.",
)
julia> headers = ["user:"]
julia> shortMemoryToString(shortMemory, headers)
"Thought 1: I like it.\nAct 1: chatbox\nActInput 1: I get this one.\n"
"Thought 1: I like it.\nAct 1: chatbox\nActinput 1: I get this one.\n"
```
"""
function shortMemoryToString(shortMemory::OrderedDict,
@@ -677,11 +677,11 @@ julia> shortMemory = OrderedDict(
"Plan 1:" => "testing a small portion of icecream",
"Thought 1:" => "I like it.",
"Act 1:" => "chatbox",
"ActInput 1:" => "I get this one.",
"Actinput 1:" => "I get this one.",
"Plan 2:" => "I'm meeting my wife this afternoon",
"Thought 2:" => "I also want it for my wife",
"Act 2:" => "chatbox",
"ActInput 2:" => "I would like to get 2 more",
"Actinput 2:" => "I would like to get 2 more",
)
julia> skipHeaders = ["Plan"]
julia> step = 2
@@ -691,7 +691,7 @@ OrderedDict(
"Plan 1:" => "testing a small portion of icecream",
"Thought 1:" => "I like it.",
"Act 1:" => "chatbox",
"ActInput 1:" => "I get this one.",
"Actinput 1:" => "I get this one.",
"Plan 2:" => "I'm meeting my wife this afternoon",
)
```
@@ -725,10 +725,44 @@ end
""" Keep only specified keys in a dictionary. All non-specified keys will be removed.
Args:
dict = a dictionary
keys = keys you want to keep in a dict
Return:
a dict with all non-specified keys removed
# Example
```jldoctest
julia> dict = OrderedDict(
"user:" => "May I try this one?",
"Plan 1:" => "testing a small portion of icecream",
"Thought 1:" => "I like it.",
"Act 1:" => "chatbox",
"Actinput 1:" => "I get this one.",
"Plan 2:" => "I'm meeting my wife this afternoon",
"Thought 2:" => "I also want it for my wife",
"Act 2:" => "chatbox",
"Actinput 2:" => "I would like to get 2 more",
)
julia> keys = ["user:"]
julia> keepOnlyKeys(dict, keys)
OrderedDict(
"user:" => "May I try this one?",
)
```
"""
function keepOnlyKeys(dict::T1, keys::T2) where {T1<:AbstractDict, T2<:AbstractVector}
newdict = similar(dict)
for (k, v) in dict
if k keys
newdict[k] = v
end
end
return newdict
end