add context
This commit is contained in:
283
src/interface.jl
283
src/interface.jl
@@ -78,7 +78,7 @@ julia> config = Dict(
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
julia> output_thoughtDict = Dict(
|
julia> output_thoughtDict = Dict(
|
||||||
"thought_1" => "The customer wants to buy a bottle of wine. This is a good start!",
|
"thought_1" => "The customer wants to buy a bottle of wine. This is a good start!",
|
||||||
@@ -93,7 +93,7 @@ julia> output_thoughtDict = Dict(
|
|||||||
- [] use customerinfo
|
- [] use customerinfo
|
||||||
- [] user storeinfo
|
- [] user storeinfo
|
||||||
|
|
||||||
""" #WORKING
|
"""
|
||||||
function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||||
) where {T<:agent}
|
) where {T<:agent}
|
||||||
println("\nExecuting YiemAgent decisionMaker()")
|
println("\nExecuting YiemAgent decisionMaker()")
|
||||||
@@ -127,159 +127,172 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
|||||||
|
|
||||||
requiredKeys = ["plan", "actionname", "actioninput"]
|
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"
|
errornote = "N/A"
|
||||||
response = nothing # placeholder for show when error msg show up
|
response = nothing # placeholder for show when error msg show up
|
||||||
|
|
||||||
|
|
||||||
for attempt in 1:maxattempt
|
for attempt in 1:maxattempt
|
||||||
if attempt > 1
|
if attempt > 1
|
||||||
println("\nYiemAgent decisionMaker() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent decisionMaker() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
end
|
end
|
||||||
|
|
||||||
unformatPrompt =
|
unformatPrompt =
|
||||||
[
|
[
|
||||||
Dict("name" => "system", "text" => systemmsg),
|
Dict("name" => "system", "text" => systemmsg),
|
||||||
]
|
]
|
||||||
|
|
||||||
unformatPrompt = vcat(unformatPrompt, recentEvents)
|
unformatPrompt = vcat(unformatPrompt, recentEvents)
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName)
|
prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName)
|
||||||
# add info
|
# add info
|
||||||
prompt = prompt * context
|
prompt = prompt * context
|
||||||
|
|
||||||
response = a.context.text2textInstructLLM(prompt; senderId=a.id)
|
response = a.context.text2textInstructLLM(prompt; senderId=a.id)
|
||||||
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
||||||
response = GeneralUtils.remove_french_accents(response)
|
response = GeneralUtils.remove_french_accents(response)
|
||||||
think, response = GeneralUtils.extractthink(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 = String(split(response, ", observation")[1]) # in case LLM generate observation key which it isn't supposed to
|
||||||
response = strip(response)
|
response = strip(response)
|
||||||
responsedict = nothing
|
responsedict = nothing
|
||||||
try
|
try
|
||||||
responsedict = copy(JSON.parsefile(response))
|
responsedict = copy(JSON.parsefile(response))
|
||||||
catch
|
catch
|
||||||
println("\nERROR YiemAgent decisionMaker() failed to parse response: $response", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nERROR YiemAgent decisionMaker() failed to parse response: $response", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
# check whether all answer's key points are in responsedict
|
# check whether all answer's key points are in responsedict
|
||||||
ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys)
|
ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys)
|
||||||
if !ispass
|
if !ispass
|
||||||
errornote = errormsg
|
errornote = errormsg
|
||||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
|
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
# _responsedictKey = keys(responsedict)
|
# _responsedictKey = keys(responsedict)
|
||||||
# responsedictKey = [i for i in _responsedictKey] # convert into a list
|
# responsedictKey = [i for i in _responsedictKey] # convert into a list
|
||||||
# is_requiredKeys_in_responsedictKey = [i ∈ responsedictKey for i in requiredKeys]
|
# is_requiredKeys_in_responsedictKey = [i ∈ responsedictKey for i in requiredKeys]
|
||||||
|
|
||||||
# if length(is_requiredKeys_in_responsedictKey) > length(requiredKeys)
|
# if length(is_requiredKeys_in_responsedictKey) > length(requiredKeys)
|
||||||
# errornote = "Your previous attempt has more key points than answer's required key points."
|
# 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())")
|
# println("\nERROR YiemAgent decisionMaker() $errornote ----(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
# continue
|
# continue
|
||||||
# elseif !all(is_requiredKeys_in_responsedictKey)
|
# elseif !all(is_requiredKeys_in_responsedictKey)
|
||||||
# zeroind = findall(x -> x == 0, is_requiredKeys_in_responsedictKey)
|
# zeroind = findall(x -> x == 0, is_requiredKeys_in_responsedictKey)
|
||||||
# missingkeys = [requiredKeys[i] for i in zeroind]
|
# missingkeys = [requiredKeys[i] for i in zeroind]
|
||||||
# errornote = "$missingkeys are missing from your previous response"
|
# errornote = "$missingkeys are missing from your previous response"
|
||||||
# println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
# println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
# continue
|
# continue
|
||||||
# end
|
# end
|
||||||
|
|
||||||
if responsedict["actionname"] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"]
|
if responsedict["actionname"] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"]
|
||||||
errornote = "Your previous attempt didn't use the given functions"
|
errornote = "Your previous attempt didn't use the given functions"
|
||||||
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict["actionname"])", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict["actionname"])", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
pprintln(Dict(responsedict))
|
pprintln(Dict(responsedict))
|
||||||
|
|
||||||
# check whether an agent recommend wines before checking inventory or recommend wines
|
# check whether an agent recommend wines before checking inventory or recommend wines
|
||||||
# outside its inventory
|
# outside its inventory
|
||||||
# ask LLM whether there are any winery mentioned in the response
|
# ask LLM whether there are any winery mentioned in the response
|
||||||
mentioned_winery = detectWineryName(a, response)
|
mentioned_winery = detectWineryName(a, response)
|
||||||
if mentioned_winery != "None"
|
if mentioned_winery != "None"
|
||||||
mentioned_winery = String.(strip.(split(mentioned_winery, ",")))
|
mentioned_winery = String.(strip.(split(mentioned_winery, ",")))
|
||||||
|
|
||||||
# check whether the wine is in event
|
# check whether the wine is in event
|
||||||
isWineInEvent = false
|
isWineInEvent = false
|
||||||
for winename in mentioned_winery
|
for winename in mentioned_winery
|
||||||
for event in a.memory["events"]
|
for event in a.memory["events"]
|
||||||
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
||||||
isWineInEvent = true
|
isWineInEvent = true
|
||||||
break
|
break
|
||||||
end
|
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
delete!(responsedict, :mentioned_winery)
|
# then the agent is not supposed to recommend the wine
|
||||||
|
if isWineInEvent == false
|
||||||
# check whether responsedict["actioninput"] is the same as previous dialogue
|
errornote = "You recommended wines that are not in your inventory before. Please only recommend wines that you have previously found in your inventory."
|
||||||
if !isempty(a.chathistory) && responsedict["actioninput"] == a.chathistory[end]["text"]
|
println("\nERROR YiemAgent decisionMaker() $errornote $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
errornote = "In your previous attempt, you repeated the previous dialogue. Please try again."
|
|
||||||
println("\nERROR YiemAgent decisionMaker() $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
|
||||||
continue
|
continue
|
||||||
end
|
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
|
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
|
end
|
||||||
|
error("DecisionMaker failed to generate a thought ", response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
24
src/type.jl
24
src/type.jl
@@ -321,16 +321,30 @@ function virtualcustomer(
|
|||||||
)
|
)
|
||||||
|
|
||||||
""" Memory
|
""" Memory
|
||||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
Ref: Chat prompt format is openai
|
||||||
NO "system" message in chathistory because I want to add it at the inference time
|
chathistory = [
|
||||||
chathistory= [
|
Dict(
|
||||||
Dict("name"=>"user", "text"=> "Wassup!", "timestamp"=> Dates.now()),
|
"role" => "system",
|
||||||
Dict("name"=>"assistant", "text"=> "Hi I'm your assistant.", "timestamp"=> Dates.now()),
|
"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}(
|
memory = Dict{String, Any}(
|
||||||
"shortmem"=> OrderedDict{String, Any}(
|
"shortmem"=> OrderedDict{String, Any}(
|
||||||
),
|
),
|
||||||
|
"scratchpad"=> "",
|
||||||
"events"=> Vector{Dict{String, Any}}(),
|
"events"=> Vector{Dict{String, Any}}(),
|
||||||
"state"=> Dict{String, Any}(
|
"state"=> Dict{String, Any}(
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user