use Dict string key
This commit is contained in:
+85
-85
@@ -64,29 +64,29 @@ end
|
||||
# Example
|
||||
```jldoctest
|
||||
julia> config = Dict(
|
||||
:mqttServerInfo => Dict(
|
||||
:description => "mqtt server info",
|
||||
:port => 1883,
|
||||
:broker => "mqtt.yiem.cc"
|
||||
),
|
||||
:externalservice => Dict(
|
||||
"text"2textinstruct => Dict(
|
||||
:mqtttopic => "/loadbalancer/requestingservice",
|
||||
:description => "text to text service with instruct LLM",
|
||||
:llminfo => Dict(
|
||||
"name" => "llama3instruct"
|
||||
)
|
||||
),
|
||||
)
|
||||
)
|
||||
"mqttServerInfo" => Dict(
|
||||
"description" => "mqtt server info",
|
||||
"port" => 1883,
|
||||
"broker" => "mqtt.yiem.cc"
|
||||
),
|
||||
"externalservice" => Dict(
|
||||
"text2textinstruct" => Dict(
|
||||
"mqtttopic" => "/loadbalancer/requestingservice",
|
||||
"description" => "text to text service with instruct LLM",
|
||||
"llminfo" => Dict(
|
||||
"name" => "llama3instruct"
|
||||
)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
julia> output_thoughtDict = Dict(
|
||||
:thought_1 => "The customer wants to buy a bottle of wine. This is a good start!",
|
||||
:action_1 => Dict{String, Any}(
|
||||
:action=>"CHATBOX",
|
||||
:input=>"What occasion are you buying the wine for?"
|
||||
"thought_1" => "The customer wants to buy a bottle of wine. This is a good start!",
|
||||
"action_1" => Dict{String, Any}(
|
||||
"action"=>"CHATBOX",
|
||||
"input"=>"What occasion are you buying the wine for?"
|
||||
),
|
||||
:observation_1 => ""
|
||||
"observation_1" => ""
|
||||
)
|
||||
```
|
||||
- [] update docstring
|
||||
@@ -123,7 +123,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||
# end
|
||||
|
||||
recentevents_ind = GeneralUtils.recentElementsIndex(
|
||||
length(a.memory[:events]), recentevents; includelatest=true)
|
||||
length(a.memory["events"]), recentevents; includelatest=true)
|
||||
|
||||
requiredKeys = ["plan", "actionname", "actioninput"]
|
||||
|
||||
@@ -203,8 +203,8 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||
# 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])
|
||||
for event in a.memory["events"]
|
||||
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
||||
isWineInEvent = true
|
||||
break
|
||||
end
|
||||
@@ -237,19 +237,19 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||
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
|
||||
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]
|
||||
if !haskey(a.memory["shortmem"], "decisionlog")
|
||||
a.memory["shortmem"]["decisionlog"] = [responsedict]
|
||||
else
|
||||
push!(a.memory["shortmem"][:decisionlog], responsedict)
|
||||
push!(a.memory["shortmem"]["decisionlog"], responsedict)
|
||||
end
|
||||
|
||||
# # save to filename ./log/decisionlog.txt
|
||||
@@ -275,7 +275,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||
# println("\nYiemAgent decisionMaker() saved to disk is done. agent $(a.id)")
|
||||
|
||||
|
||||
responsedict[:prompt] = prompt
|
||||
responsedict["prompt"] = prompt
|
||||
return responsedict
|
||||
end
|
||||
error("DecisionMaker failed to generate a thought ", response)
|
||||
@@ -531,7 +531,7 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict;
|
||||
addNewMessage(a, "user", userinput["text"]; maximumMsg=maximumMsg)
|
||||
|
||||
# add user activity to events memory
|
||||
push!(a.memory[:events],
|
||||
push!(a.memory["events"],
|
||||
eventdict(;
|
||||
event_description="the user talks to the assistant.",
|
||||
timestamp=Dates.now(),
|
||||
@@ -544,7 +544,7 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict;
|
||||
|
||||
addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg)
|
||||
|
||||
push!(a.memory[:events],
|
||||
push!(a.memory["events"],
|
||||
eventdict(;
|
||||
event_description="the assistant talks to the user.",
|
||||
timestamp=Dates.now(),
|
||||
@@ -592,18 +592,18 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
||||
end
|
||||
|
||||
# this section allow LLM functions above to have different return values.
|
||||
result = haskey(response, :result) ? response[:result] : nothing
|
||||
rawresponse = haskey(response, :rawresponse) ? response[:rawresponse] : nothing
|
||||
select = haskey(response, :select) ? response[:select] : nothing
|
||||
reward::Integer = haskey(response, :reward) ? response[:reward] : 0
|
||||
isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false
|
||||
errormsg::Union{AbstractString,Nothing} = haskey(response, :errormsg) ? response[:errormsg] : nothing
|
||||
success::Bool = haskey(response, :success) ? response[:success] : false
|
||||
result = haskey(response, "result") ? response["result"] : nothing
|
||||
rawresponse = haskey(response, "rawresponse") ? response["rawresponse"] : nothing
|
||||
select = haskey(response, "select") ? response["select"] : nothing
|
||||
reward::Integer = haskey(response, "reward") ? response["reward"] : 0
|
||||
isterminal::Bool = haskey(response, "isterminal") ? response["isterminal"] : false
|
||||
errormsg::Union{AbstractString,Nothing} = haskey(response, "errormsg") ? response["errormsg"] : nothing
|
||||
success::Bool = haskey(response, "success") ? response["success"] : false
|
||||
|
||||
# # manage memory (pass msg to generatechat)
|
||||
# if actionname ∈ ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"]
|
||||
# chatresponse = generatechat(a, thoughtDict)
|
||||
# push!(a.memory[:events],
|
||||
# push!(a.memory["events"],
|
||||
# eventdict(;
|
||||
# event_description="the assistant talks to the user.",
|
||||
# timestamp=Dates.now(),
|
||||
@@ -615,7 +615,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
||||
# )
|
||||
# result = chatresponse
|
||||
if actionname ∈ ["CHATBOX"]
|
||||
push!(a.memory[:events],
|
||||
push!(a.memory["events"],
|
||||
eventdict(;
|
||||
event_description="an assistant talks to the user.",
|
||||
timestamp=Dates.now(),
|
||||
@@ -628,7 +628,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
||||
result = actioninput
|
||||
elseif actionname ∈ ["ENDCONVERSATION"]
|
||||
chatresponse = generatechat(a, thoughtDict)
|
||||
push!(a.memory[:events],
|
||||
push!(a.memory["events"],
|
||||
eventdict(;
|
||||
event_description="an assistant talks to the user to end conversation.",
|
||||
timestamp=Dates.now(),
|
||||
@@ -641,7 +641,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
||||
result = chatresponse
|
||||
elseif actionname ∈ ["PRESENTBOX"]
|
||||
chatresponse = presentbox(a, thoughtDict)
|
||||
push!(a.memory[:events],
|
||||
push!(a.memory["events"],
|
||||
eventdict(;
|
||||
event_description="the assistant presents wines to the user.",
|
||||
timestamp=Dates.now(),
|
||||
@@ -656,12 +656,12 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
||||
elseif actionname == "CHECKWINE"
|
||||
if rawresponse !== nothing
|
||||
vd = GeneralUtils.dfToVectorDict(rawresponse) # comes in dataframe format
|
||||
# a.memory["shortmem"][:found_wine] = vd # used by decisionMaker() as a short note
|
||||
#[PENDING] a.memory["shortmem"][:available_wine] should be OrderedDict instead of vector dict so that no duplicate item are listed?
|
||||
if length(a.memory["shortmem"][:db_search_result]) != 0
|
||||
a.memory["shortmem"][:db_search_result] = vcat(a.memory["shortmem"][:db_search_result], vd)
|
||||
# a.memory["shortmem"]["found_wine"] = vd # used by decisionMaker() as a short note
|
||||
#[PENDING] a.memory["shortmem"]["available_wine"] should be OrderedDict instead of vector dict so that no duplicate item are listed?
|
||||
if length(a.memory["shortmem"]["db_search_result"]) != 0
|
||||
a.memory["shortmem"]["db_search_result"] = vcat(a.memory["shortmem"]["db_search_result"], vd)
|
||||
else
|
||||
a.memory["shortmem"][:db_search_result] = vd
|
||||
a.memory["shortmem"]["db_search_result"] = vd
|
||||
end
|
||||
|
||||
# # add to scratchpad
|
||||
@@ -680,7 +680,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
||||
# """
|
||||
end
|
||||
|
||||
push!(a.memory[:events],
|
||||
push!(a.memory["events"],
|
||||
eventdict(;
|
||||
event_description= "the assistant searched the database.",
|
||||
timestamp= Dates.now(),
|
||||
@@ -803,7 +803,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
|
||||
end
|
||||
|
||||
# check if Context: is in dialogue
|
||||
if occursin("Context:", responsedict[:dialogue])
|
||||
if occursin("Context:", responsedict["dialogue"])
|
||||
errornote = "Your previous response contains 'Context:' which is not allowed"
|
||||
println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
@@ -815,15 +815,15 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
|
||||
# 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, responsedict[:dialogue])
|
||||
mentioned_winery = detectWineryName(a, responsedict["dialogue"])
|
||||
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])
|
||||
for event in a.memory["events"]
|
||||
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
||||
isWineInEvent = true
|
||||
break
|
||||
end
|
||||
@@ -850,7 +850,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
|
||||
end
|
||||
end
|
||||
|
||||
result = responsedict[:dialogue]
|
||||
result = responsedict["dialogue"]
|
||||
return result
|
||||
end
|
||||
error("presentbox() failed to generate a response")
|
||||
@@ -913,10 +913,10 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10)
|
||||
"""
|
||||
requiredKeys = [:dialogue]
|
||||
|
||||
# a.memory["shortmem"][:available_wine] is a vector of dictionary
|
||||
# a.memory["shortmem"]["available_wine"] is a vector of dictionary
|
||||
# context =
|
||||
# if length(a.memory["shortmem"][:available_wine]) != 0
|
||||
# "Wines previously found in your inventory: $(availableWineToText(a.memory["shortmem"][:available_wine]))"
|
||||
# if length(a.memory["shortmem"]["available_wine"]) != 0
|
||||
# "Wines previously found in your inventory: $(availableWineToText(a.memory["shortmem"]["available_wine"]))"
|
||||
# else
|
||||
# "N/A"
|
||||
# end
|
||||
@@ -1003,8 +1003,8 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10)
|
||||
# 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])
|
||||
for event in a.memory["events"]
|
||||
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
||||
isWineInEvent = true
|
||||
break
|
||||
end
|
||||
@@ -1018,7 +1018,7 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10)
|
||||
continue
|
||||
end
|
||||
end
|
||||
result = responsedict[:dialogue]
|
||||
result = responsedict["dialogue"]
|
||||
|
||||
return result
|
||||
end
|
||||
@@ -1088,15 +1088,15 @@ function generatechat(a::virtualcustomer;
|
||||
converPartnerName::Union{String, Nothing}=nothing, maxattempt=10, recentEventNum=10
|
||||
)
|
||||
|
||||
recent_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recentEventNum; includelatest=true)
|
||||
recentEventsDict = createEventsLog(a.memory[:events]; index=recent_ind)
|
||||
recent_ind = GeneralUtils.recentElementsIndex(length(a.memory["events"]), recentEventNum; includelatest=true)
|
||||
recentEventsDict = createEventsLog(a.memory["events"]; index=recent_ind)
|
||||
response = nothing # placeholder for show when error msg show up
|
||||
errornote = "N/A"
|
||||
header = ["Dialogue:", "Role:"]
|
||||
dictkey = ["dialogue", "role"]
|
||||
llmkwargs=Dict(
|
||||
:num_ctx => 32768,
|
||||
:temperature => 0.5,
|
||||
"num_ctx" => 32768,
|
||||
"temperature" => 0.5,
|
||||
)
|
||||
|
||||
for attempt in 1:maxattempt
|
||||
@@ -1141,15 +1141,15 @@ function generatechat(a::virtualcustomer;
|
||||
|
||||
responsedict = GeneralUtils.textToDict(response, header;
|
||||
dictKey=dictkey, symbolkey=true)
|
||||
if responsedict[:role] == "no"
|
||||
errornote = "In your previous attempt you said $(responsedict[:dialogue]) which you, as a customer of a wine store, are not supposed to speak."
|
||||
if responsedict["role"] == "no"
|
||||
errornote = "In your previous attempt you said $(responsedict["dialogue"]) which you, as a customer of a wine store, are not supposed to speak."
|
||||
println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
# check if the dialogue is the same as the previous one
|
||||
if length(responsedict[:dialogue]) != 0 && responsedict[:dialogue] == a.chathistory[end]["text"]
|
||||
errornote = "In your previous attempt you said $(responsedict[:dialogue]) which was the same as the previous one."
|
||||
if length(responsedict["dialogue"]) != 0 && responsedict["dialogue"] == a.chathistory[end]["text"]
|
||||
errornote = "In your previous attempt you said $(responsedict["dialogue"]) which was the same as the previous one."
|
||||
println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
@@ -1157,7 +1157,7 @@ function generatechat(a::virtualcustomer;
|
||||
# check whether LLM just repeat the previous dialogue
|
||||
dublicate = false
|
||||
for msg in a.chathistory
|
||||
if msg["text"] == responsedict[:dialogue]
|
||||
if msg["text"] == responsedict["dialogue"]
|
||||
errornote = "In your previous attempt, you repeated the earlier dialogue. Please try again."
|
||||
println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
dublicate = true
|
||||
@@ -1170,7 +1170,7 @@ function generatechat(a::virtualcustomer;
|
||||
|
||||
# println("\n$prompt", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# println("\n $response")
|
||||
return responsedict[:dialogue]
|
||||
return responsedict["dialogue"]
|
||||
end
|
||||
error("generatechat failed to generate a response")
|
||||
end
|
||||
@@ -1285,12 +1285,12 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String
|
||||
dictkey = ["q1"]
|
||||
|
||||
# context =
|
||||
# if length(a.memory["shortmem"][:available_wine]) != 0
|
||||
# "Available wines you've found in your inventory so far: $(availableWineToText(a.memory["shortmem"][:available_wine]))"
|
||||
# if length(a.memory["shortmem"]["available_wine"]) != 0
|
||||
# "Available wines you've found in your inventory so far: $(availableWineToText(a.memory["shortmem"]["available_wine"]))"
|
||||
# else
|
||||
# "N/A"
|
||||
# end
|
||||
database_search_result = a.memory["shortmem"][:db_search_result]
|
||||
database_search_result = a.memory["shortmem"]["db_search_result"]
|
||||
|
||||
# recent_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recent)
|
||||
# recentevents = a.memory[:events][recent_ind]
|
||||
@@ -1357,8 +1357,8 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String
|
||||
# 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])
|
||||
for event in a.memory["events"]
|
||||
if event["observation"] !== nothing && occursin(winename, event["observation"])
|
||||
isWineInEvent = true
|
||||
break
|
||||
end
|
||||
@@ -1402,7 +1402,7 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String
|
||||
|
||||
responsedict = GeneralUtils.textToDict(response, header;
|
||||
dictKey=dictkey, symbolkey=true)
|
||||
response = "Q1: " * responsedict[:q1]
|
||||
response = "Q1: " * responsedict["q1"]
|
||||
println("\nYiemAgent generatequestion() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
try pprintln(response) catch e println(response) end
|
||||
|
||||
@@ -1446,11 +1446,11 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent::
|
||||
Let's begin!
|
||||
"""
|
||||
|
||||
header = ["Event_$i:" for i in eachindex(a.memory[:events])]
|
||||
dictkey = lowercase.(["Event_$i" for i in eachindex(a.memory[:events])])
|
||||
header = ["Event_$i:" for i in eachindex(a.memory["events"])]
|
||||
dictkey = lowercase.(["Event_$i" for i in eachindex(a.memory["events"])])
|
||||
|
||||
ind = GeneralUtils.nonRecentElementsIndex(length(a.memory[:events]), skiprecent)
|
||||
events = a.memory[:events][ind]
|
||||
ind = GeneralUtils.nonRecentElementsIndex(length(a.memory["events"]), skiprecent)
|
||||
events = a.memory["events"][ind]
|
||||
timeline = createTimeline(events)
|
||||
|
||||
errornote = "N/A"
|
||||
@@ -1570,7 +1570,7 @@ function detectWineryName(a, text)
|
||||
responsedict = GeneralUtils.textToDict(response, header;
|
||||
dictKey=dictkey, symbolkey=true)
|
||||
|
||||
result = responsedict[:winery_names]
|
||||
result = responsedict["winery_names"]
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user