add context
This commit is contained in:
279
src/interface.jl
279
src/interface.jl
@@ -93,7 +93,7 @@ julia> output_thoughtDict = Dict(
|
||||
- [] use customerinfo
|
||||
- [] user storeinfo
|
||||
|
||||
""" #WORKING
|
||||
"""
|
||||
function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||
) where {T<:agent}
|
||||
println("\nExecuting YiemAgent decisionMaker()")
|
||||
@@ -127,159 +127,172 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||
|
||||
requiredKeys = ["plan", "actionname", "actioninput"]
|
||||
|
||||
context =
|
||||
"""
|
||||
<internal_context_for_LLM>
|
||||
$(a.memory["scratchpad"])
|
||||
</internal_context_for_LLM>
|
||||
"""
|
||||
|
||||
#WORKING add context to the latest message (in the front)
|
||||
for d in enumerate(a.chathistory[end]["content"])
|
||||
if d["type"] == "text"
|
||||
d["text"] = context * d["text"]
|
||||
break
|
||||
end
|
||||
end
|
||||
errornote = "N/A"
|
||||
response = nothing # placeholder for show when error msg show up
|
||||
|
||||
|
||||
for attempt in 1:maxattempt
|
||||
if attempt > 1
|
||||
println("\nYiemAgent decisionMaker() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
end
|
||||
for attempt in 1:maxattempt
|
||||
if attempt > 1
|
||||
println("\nYiemAgent decisionMaker() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
end
|
||||
|
||||
unformatPrompt =
|
||||
[
|
||||
Dict("name" => "system", "text" => systemmsg),
|
||||
]
|
||||
unformatPrompt =
|
||||
[
|
||||
Dict("name" => "system", "text" => systemmsg),
|
||||
]
|
||||
|
||||
unformatPrompt = vcat(unformatPrompt, recentEvents)
|
||||
# put in model format
|
||||
prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName)
|
||||
# add info
|
||||
prompt = prompt * context
|
||||
unformatPrompt = vcat(unformatPrompt, recentEvents)
|
||||
# put in model format
|
||||
prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName)
|
||||
# add info
|
||||
prompt = prompt * context
|
||||
|
||||
response = a.context.text2textInstructLLM(prompt; senderId=a.id)
|
||||
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
||||
response = GeneralUtils.remove_french_accents(response)
|
||||
think, response = GeneralUtils.extractthink(response)
|
||||
response = String(split(response, ", observation")[1]) # in case LLM generate observation key which it isn't supposed to
|
||||
response = strip(response)
|
||||
responsedict = nothing
|
||||
try
|
||||
responsedict = copy(JSON.parsefile(response))
|
||||
catch
|
||||
println("\nERROR YiemAgent decisionMaker() failed to parse response: $response", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
response = a.context.text2textInstructLLM(prompt; senderId=a.id)
|
||||
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
||||
response = GeneralUtils.remove_french_accents(response)
|
||||
think, response = GeneralUtils.extractthink(response)
|
||||
response = String(split(response, ", observation")[1]) # in case LLM generate observation key which it isn't supposed to
|
||||
response = strip(response)
|
||||
responsedict = nothing
|
||||
try
|
||||
responsedict = copy(JSON.parsefile(response))
|
||||
catch
|
||||
println("\nERROR YiemAgent decisionMaker() failed to parse response: $response", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
# check whether all answer's key points are in responsedict
|
||||
ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys)
|
||||
if !ispass
|
||||
errornote = errormsg
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
|
||||
continue
|
||||
end
|
||||
# _responsedictKey = keys(responsedict)
|
||||
# responsedictKey = [i for i in _responsedictKey] # convert into a list
|
||||
# is_requiredKeys_in_responsedictKey = [i ∈ responsedictKey for i in requiredKeys]
|
||||
# check whether all answer's key points are in responsedict
|
||||
ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys)
|
||||
if !ispass
|
||||
errornote = errormsg
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
|
||||
continue
|
||||
end
|
||||
# _responsedictKey = keys(responsedict)
|
||||
# responsedictKey = [i for i in _responsedictKey] # convert into a list
|
||||
# is_requiredKeys_in_responsedictKey = [i ∈ responsedictKey for i in requiredKeys]
|
||||
|
||||
# if length(is_requiredKeys_in_responsedictKey) > length(requiredKeys)
|
||||
# errornote = "Your previous attempt has more key points than answer's required key points."
|
||||
# println("\nERROR YiemAgent decisionMaker() $errornote ----(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# continue
|
||||
# elseif !all(is_requiredKeys_in_responsedictKey)
|
||||
# zeroind = findall(x -> x == 0, is_requiredKeys_in_responsedictKey)
|
||||
# missingkeys = [requiredKeys[i] for i in zeroind]
|
||||
# errornote = "$missingkeys are missing from your previous response"
|
||||
# println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# continue
|
||||
# end
|
||||
# if length(is_requiredKeys_in_responsedictKey) > length(requiredKeys)
|
||||
# errornote = "Your previous attempt has more key points than answer's required key points."
|
||||
# println("\nERROR YiemAgent decisionMaker() $errornote ----(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# continue
|
||||
# elseif !all(is_requiredKeys_in_responsedictKey)
|
||||
# zeroind = findall(x -> x == 0, is_requiredKeys_in_responsedictKey)
|
||||
# missingkeys = [requiredKeys[i] for i in zeroind]
|
||||
# errornote = "$missingkeys are missing from your previous response"
|
||||
# println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# continue
|
||||
# end
|
||||
|
||||
if responsedict["actionname"] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"]
|
||||
errornote = "Your previous attempt didn't use the given functions"
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict["actionname"])", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
if responsedict["actionname"] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"]
|
||||
errornote = "Your previous attempt didn't use the given functions"
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict["actionname"])", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
pprintln(Dict(responsedict))
|
||||
println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
pprintln(Dict(responsedict))
|
||||
|
||||
# check whether an agent recommend wines before checking inventory or recommend wines
|
||||
# outside its inventory
|
||||
# ask LLM whether there are any winery mentioned in the response
|
||||
mentioned_winery = detectWineryName(a, response)
|
||||
if mentioned_winery != "None"
|
||||
mentioned_winery = String.(strip.(split(mentioned_winery, ",")))
|
||||
# check whether an agent recommend wines before checking inventory or recommend wines
|
||||
# outside its inventory
|
||||
# ask LLM whether there are any winery mentioned in the response
|
||||
mentioned_winery = detectWineryName(a, response)
|
||||
if mentioned_winery != "None"
|
||||
mentioned_winery = String.(strip.(split(mentioned_winery, ",")))
|
||||
|
||||
# check whether the wine is in event
|
||||
isWineInEvent = false
|
||||
for winename in mentioned_winery
|
||||
for event in a.memory["events"]
|
||||
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
||||
isWineInEvent = true
|
||||
break
|
||||
end
|
||||
# check whether the wine is in event
|
||||
isWineInEvent = false
|
||||
for winename in mentioned_winery
|
||||
for event in a.memory["events"]
|
||||
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
||||
isWineInEvent = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# then the agent is not supposed to recommend the wine
|
||||
if isWineInEvent == false
|
||||
errornote = "You recommended wines that are not in your inventory before. Please only recommend wines that you have previously found in your inventory."
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
end
|
||||
|
||||
delete!(responsedict, :mentioned_winery)
|
||||
|
||||
# check whether responsedict["actioninput"] is the same as previous dialogue
|
||||
if !isempty(a.chathistory) && responsedict["actioninput"] == a.chathistory[end]["text"]
|
||||
errornote = "In your previous attempt, you repeated the previous dialogue. Please try again."
|
||||
println("\nERROR YiemAgent decisionMaker() $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# then the agent is not supposed to recommend the wine
|
||||
if isWineInEvent == false
|
||||
errornote = "You recommended wines that are not in your inventory before. Please only recommend wines that you have previously found in your inventory."
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
evaluationdict = evaluator(a, timeline, responsedict, context)
|
||||
if evaluationdict[:approval] == "no"
|
||||
mentor_comment = evaluationdict[:suggestion]
|
||||
errornote = "Your previous attempt was not good enough. Please try again. Here is the mentor's suggestion: $mentor_comment"
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> \n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
# store for later training
|
||||
responsedict["system"] = systemmsg
|
||||
responsedict["unformatPrompt"] = unformatPrompt
|
||||
responsedict["prompt"] = prompt
|
||||
responsedict["context"] = context
|
||||
responsedict["think"] = think
|
||||
responsedict["response"] = response
|
||||
# responsedict["QandA"] = QandA
|
||||
|
||||
# check whether there is a file path exists before writing to it
|
||||
if !haskey(a.memory["shortmem"], "decisionlog")
|
||||
a.memory["shortmem"]["decisionlog"] = [responsedict]
|
||||
else
|
||||
push!(a.memory["shortmem"]["decisionlog"], responsedict)
|
||||
end
|
||||
|
||||
# # save to filename ./log/decisionlog.txt
|
||||
# println("\nsaving YiemAgent decisionMaker() to disk ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# filename = "agent_decision_log_$(a.id).json"
|
||||
# filepath = "/appfolder/app/log/$filename"
|
||||
# # check whether there is a file path exists before writing to it
|
||||
# if !isfile(filepath)
|
||||
# decisionlist = [responsedict]
|
||||
# println("Creating file $filepath")
|
||||
# open(filepath, "w") do io
|
||||
# JSON.pretty(io, decisionlist)
|
||||
# end
|
||||
# else
|
||||
# # read the file and append new data
|
||||
# decisionlist = copy(JSON.parsefile(filepath))
|
||||
# push!(decisionlist, responsedict)
|
||||
# println("Appending new data to file $filepath")
|
||||
# open(filepath, "w") do io
|
||||
# JSON.pretty(io, decisionlist)
|
||||
# end
|
||||
# end
|
||||
# println("\nYiemAgent decisionMaker() saved to disk is done. agent $(a.id)")
|
||||
|
||||
|
||||
responsedict["prompt"] = prompt
|
||||
return responsedict
|
||||
end
|
||||
error("DecisionMaker failed to generate a thought ", response)
|
||||
|
||||
delete!(responsedict, :mentioned_winery)
|
||||
|
||||
# check whether responsedict["actioninput"] is the same as previous dialogue
|
||||
if !isempty(a.chathistory) && responsedict["actioninput"] == a.chathistory[end]["text"]
|
||||
errornote = "In your previous attempt, you repeated the previous dialogue. Please try again."
|
||||
println("\nERROR YiemAgent decisionMaker() $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
evaluationdict = evaluator(a, timeline, responsedict, context)
|
||||
if evaluationdict[:approval] == "no"
|
||||
mentor_comment = evaluationdict[:suggestion]
|
||||
errornote = "Your previous attempt was not good enough. Please try again. Here is the mentor's suggestion: $mentor_comment"
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> \n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
# store for later training
|
||||
responsedict["system"] = systemmsg
|
||||
responsedict["unformatPrompt"] = unformatPrompt
|
||||
responsedict["prompt"] = prompt
|
||||
responsedict["context"] = context
|
||||
responsedict["think"] = think
|
||||
responsedict["response"] = response
|
||||
# responsedict["QandA"] = QandA
|
||||
|
||||
# check whether there is a file path exists before writing to it
|
||||
if !haskey(a.memory["shortmem"], "decisionlog")
|
||||
a.memory["shortmem"]["decisionlog"] = [responsedict]
|
||||
else
|
||||
push!(a.memory["shortmem"]["decisionlog"], responsedict)
|
||||
end
|
||||
|
||||
# # save to filename ./log/decisionlog.txt
|
||||
# println("\nsaving YiemAgent decisionMaker() to disk ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# filename = "agent_decision_log_$(a.id).json"
|
||||
# filepath = "/appfolder/app/log/$filename"
|
||||
# # check whether there is a file path exists before writing to it
|
||||
# if !isfile(filepath)
|
||||
# decisionlist = [responsedict]
|
||||
# println("Creating file $filepath")
|
||||
# open(filepath, "w") do io
|
||||
# JSON.pretty(io, decisionlist)
|
||||
# end
|
||||
# else
|
||||
# # read the file and append new data
|
||||
# decisionlist = copy(JSON.parsefile(filepath))
|
||||
# push!(decisionlist, responsedict)
|
||||
# println("Appending new data to file $filepath")
|
||||
# open(filepath, "w") do io
|
||||
# JSON.pretty(io, decisionlist)
|
||||
# end
|
||||
# end
|
||||
# println("\nYiemAgent decisionMaker() saved to disk is done. agent $(a.id)")
|
||||
|
||||
|
||||
responsedict["prompt"] = prompt
|
||||
return responsedict
|
||||
end
|
||||
error("DecisionMaker failed to generate a thought ", response)
|
||||
end
|
||||
|
||||
|
||||
|
||||
24
src/type.jl
24
src/type.jl
@@ -321,16 +321,30 @@ function virtualcustomer(
|
||||
)
|
||||
|
||||
""" Memory
|
||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
||||
NO "system" message in chathistory because I want to add it at the inference time
|
||||
chathistory= [
|
||||
Dict("name"=>"user", "text"=> "Wassup!", "timestamp"=> Dates.now()),
|
||||
Dict("name"=>"assistant", "text"=> "Hi I'm your assistant.", "timestamp"=> Dates.now()),
|
||||
Ref: Chat prompt format is openai
|
||||
chathistory = [
|
||||
Dict(
|
||||
"role" => "system",
|
||||
"content" => [
|
||||
Dict("type" => "text", "text" => system_msg),
|
||||
]
|
||||
),
|
||||
Dict(
|
||||
"role" => "user",
|
||||
"content" => [
|
||||
Dict("type" => "text", "text" => "Do you know this wine? Just give me brief intro."),
|
||||
Dict(
|
||||
"type" => "image_url",
|
||||
"image_url" => Dict("url" => data1_uri)
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
"""
|
||||
memory = Dict{String, Any}(
|
||||
"shortmem"=> OrderedDict{String, Any}(
|
||||
),
|
||||
"scratchpad"=> "",
|
||||
"events"=> Vector{Dict{String, Any}}(),
|
||||
"state"=> Dict{String, Any}(
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user