use Dict string key
This commit is contained in:
158
src/interface.jl
158
src/interface.jl
@@ -64,16 +64,16 @@ end
|
|||||||
# Example
|
# Example
|
||||||
```jldoctest
|
```jldoctest
|
||||||
julia> config = Dict(
|
julia> config = Dict(
|
||||||
:mqttServerInfo => Dict(
|
"mqttServerInfo" => Dict(
|
||||||
:description => "mqtt server info",
|
"description" => "mqtt server info",
|
||||||
:port => 1883,
|
"port" => 1883,
|
||||||
:broker => "mqtt.yiem.cc"
|
"broker" => "mqtt.yiem.cc"
|
||||||
),
|
),
|
||||||
:externalservice => Dict(
|
"externalservice" => Dict(
|
||||||
"text"2textinstruct => Dict(
|
"text2textinstruct" => Dict(
|
||||||
:mqtttopic => "/loadbalancer/requestingservice",
|
"mqtttopic" => "/loadbalancer/requestingservice",
|
||||||
:description => "text to text service with instruct LLM",
|
"description" => "text to text service with instruct LLM",
|
||||||
:llminfo => Dict(
|
"llminfo" => Dict(
|
||||||
"name" => "llama3instruct"
|
"name" => "llama3instruct"
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -81,12 +81,12 @@ 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!",
|
||||||
:action_1 => Dict{String, Any}(
|
"action_1" => Dict{String, Any}(
|
||||||
:action=>"CHATBOX",
|
"action"=>"CHATBOX",
|
||||||
:input=>"What occasion are you buying the wine for?"
|
"input"=>"What occasion are you buying the wine for?"
|
||||||
),
|
),
|
||||||
:observation_1 => ""
|
"observation_1" => ""
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
- [] update docstring
|
- [] update docstring
|
||||||
@@ -123,7 +123,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
|||||||
# end
|
# end
|
||||||
|
|
||||||
recentevents_ind = GeneralUtils.recentElementsIndex(
|
recentevents_ind = GeneralUtils.recentElementsIndex(
|
||||||
length(a.memory[:events]), recentevents; includelatest=true)
|
length(a.memory["events"]), recentevents; includelatest=true)
|
||||||
|
|
||||||
requiredKeys = ["plan", "actionname", "actioninput"]
|
requiredKeys = ["plan", "actionname", "actioninput"]
|
||||||
|
|
||||||
@@ -203,8 +203,8 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
|||||||
# 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
|
||||||
@@ -237,19 +237,19 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
|||||||
end
|
end
|
||||||
|
|
||||||
# store for later training
|
# store for later training
|
||||||
responsedict[:system] = systemmsg
|
responsedict["system"] = systemmsg
|
||||||
responsedict[:unformatPrompt] = unformatPrompt
|
responsedict["unformatPrompt"] = unformatPrompt
|
||||||
responsedict[:prompt] = prompt
|
responsedict["prompt"] = prompt
|
||||||
responsedict[:context] = context
|
responsedict["context"] = context
|
||||||
responsedict[:think] = think
|
responsedict["think"] = think
|
||||||
responsedict[:response] = response
|
responsedict["response"] = response
|
||||||
# responsedict[:QandA] = QandA
|
# responsedict["QandA"] = QandA
|
||||||
|
|
||||||
# check whether there is a file path exists before writing to it
|
# check whether there is a file path exists before writing to it
|
||||||
if !haskey(a.memory["shortmem"], :decisionlog)
|
if !haskey(a.memory["shortmem"], "decisionlog")
|
||||||
a.memory["shortmem"][:decisionlog] = [responsedict]
|
a.memory["shortmem"]["decisionlog"] = [responsedict]
|
||||||
else
|
else
|
||||||
push!(a.memory["shortmem"][:decisionlog], responsedict)
|
push!(a.memory["shortmem"]["decisionlog"], responsedict)
|
||||||
end
|
end
|
||||||
|
|
||||||
# # save to filename ./log/decisionlog.txt
|
# # 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)")
|
# println("\nYiemAgent decisionMaker() saved to disk is done. agent $(a.id)")
|
||||||
|
|
||||||
|
|
||||||
responsedict[:prompt] = prompt
|
responsedict["prompt"] = prompt
|
||||||
return responsedict
|
return responsedict
|
||||||
end
|
end
|
||||||
error("DecisionMaker failed to generate a thought ", response)
|
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)
|
addNewMessage(a, "user", userinput["text"]; maximumMsg=maximumMsg)
|
||||||
|
|
||||||
# add user activity to events memory
|
# add user activity to events memory
|
||||||
push!(a.memory[:events],
|
push!(a.memory["events"],
|
||||||
eventdict(;
|
eventdict(;
|
||||||
event_description="the user talks to the assistant.",
|
event_description="the user talks to the assistant.",
|
||||||
timestamp=Dates.now(),
|
timestamp=Dates.now(),
|
||||||
@@ -544,7 +544,7 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict;
|
|||||||
|
|
||||||
addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg)
|
addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg)
|
||||||
|
|
||||||
push!(a.memory[:events],
|
push!(a.memory["events"],
|
||||||
eventdict(;
|
eventdict(;
|
||||||
event_description="the assistant talks to the user.",
|
event_description="the assistant talks to the user.",
|
||||||
timestamp=Dates.now(),
|
timestamp=Dates.now(),
|
||||||
@@ -592,18 +592,18 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
end
|
end
|
||||||
|
|
||||||
# this section allow LLM functions above to have different return values.
|
# this section allow LLM functions above to have different return values.
|
||||||
result = haskey(response, :result) ? response[:result] : nothing
|
result = haskey(response, "result") ? response["result"] : nothing
|
||||||
rawresponse = haskey(response, :rawresponse) ? response[:rawresponse] : nothing
|
rawresponse = haskey(response, "rawresponse") ? response["rawresponse"] : nothing
|
||||||
select = haskey(response, :select) ? response[:select] : nothing
|
select = haskey(response, "select") ? response["select"] : nothing
|
||||||
reward::Integer = haskey(response, :reward) ? response[:reward] : 0
|
reward::Integer = haskey(response, "reward") ? response["reward"] : 0
|
||||||
isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false
|
isterminal::Bool = haskey(response, "isterminal") ? response["isterminal"] : false
|
||||||
errormsg::Union{AbstractString,Nothing} = haskey(response, :errormsg) ? response[:errormsg] : nothing
|
errormsg::Union{AbstractString,Nothing} = haskey(response, "errormsg") ? response["errormsg"] : nothing
|
||||||
success::Bool = haskey(response, :success) ? response[:success] : false
|
success::Bool = haskey(response, "success") ? response["success"] : false
|
||||||
|
|
||||||
# # manage memory (pass msg to generatechat)
|
# # manage memory (pass msg to generatechat)
|
||||||
# if actionname ∈ ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"]
|
# if actionname ∈ ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"]
|
||||||
# chatresponse = generatechat(a, thoughtDict)
|
# chatresponse = generatechat(a, thoughtDict)
|
||||||
# push!(a.memory[:events],
|
# push!(a.memory["events"],
|
||||||
# eventdict(;
|
# eventdict(;
|
||||||
# event_description="the assistant talks to the user.",
|
# event_description="the assistant talks to the user.",
|
||||||
# timestamp=Dates.now(),
|
# timestamp=Dates.now(),
|
||||||
@@ -615,7 +615,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
# )
|
# )
|
||||||
# result = chatresponse
|
# result = chatresponse
|
||||||
if actionname ∈ ["CHATBOX"]
|
if actionname ∈ ["CHATBOX"]
|
||||||
push!(a.memory[:events],
|
push!(a.memory["events"],
|
||||||
eventdict(;
|
eventdict(;
|
||||||
event_description="an assistant talks to the user.",
|
event_description="an assistant talks to the user.",
|
||||||
timestamp=Dates.now(),
|
timestamp=Dates.now(),
|
||||||
@@ -628,7 +628,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
result = actioninput
|
result = actioninput
|
||||||
elseif actionname ∈ ["ENDCONVERSATION"]
|
elseif actionname ∈ ["ENDCONVERSATION"]
|
||||||
chatresponse = generatechat(a, thoughtDict)
|
chatresponse = generatechat(a, thoughtDict)
|
||||||
push!(a.memory[:events],
|
push!(a.memory["events"],
|
||||||
eventdict(;
|
eventdict(;
|
||||||
event_description="an assistant talks to the user to end conversation.",
|
event_description="an assistant talks to the user to end conversation.",
|
||||||
timestamp=Dates.now(),
|
timestamp=Dates.now(),
|
||||||
@@ -641,7 +641,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
result = chatresponse
|
result = chatresponse
|
||||||
elseif actionname ∈ ["PRESENTBOX"]
|
elseif actionname ∈ ["PRESENTBOX"]
|
||||||
chatresponse = presentbox(a, thoughtDict)
|
chatresponse = presentbox(a, thoughtDict)
|
||||||
push!(a.memory[:events],
|
push!(a.memory["events"],
|
||||||
eventdict(;
|
eventdict(;
|
||||||
event_description="the assistant presents wines to the user.",
|
event_description="the assistant presents wines to the user.",
|
||||||
timestamp=Dates.now(),
|
timestamp=Dates.now(),
|
||||||
@@ -656,12 +656,12 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
elseif actionname == "CHECKWINE"
|
elseif actionname == "CHECKWINE"
|
||||||
if rawresponse !== nothing
|
if rawresponse !== nothing
|
||||||
vd = GeneralUtils.dfToVectorDict(rawresponse) # comes in dataframe format
|
vd = GeneralUtils.dfToVectorDict(rawresponse) # comes in dataframe format
|
||||||
# a.memory["shortmem"][:found_wine] = vd # used by decisionMaker() as a short note
|
# 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?
|
#[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
|
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"]["db_search_result"] = vcat(a.memory["shortmem"]["db_search_result"], vd)
|
||||||
else
|
else
|
||||||
a.memory["shortmem"][:db_search_result] = vd
|
a.memory["shortmem"]["db_search_result"] = vd
|
||||||
end
|
end
|
||||||
|
|
||||||
# # add to scratchpad
|
# # add to scratchpad
|
||||||
@@ -680,7 +680,7 @@ function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
# """
|
# """
|
||||||
end
|
end
|
||||||
|
|
||||||
push!(a.memory[:events],
|
push!(a.memory["events"],
|
||||||
eventdict(;
|
eventdict(;
|
||||||
event_description= "the assistant searched the database.",
|
event_description= "the assistant searched the database.",
|
||||||
timestamp= Dates.now(),
|
timestamp= Dates.now(),
|
||||||
@@ -803,7 +803,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
|
|||||||
end
|
end
|
||||||
|
|
||||||
# check if Context: is in dialogue
|
# 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"
|
errornote = "Your previous response contains 'Context:' which is not allowed"
|
||||||
println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
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
|
# 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, responsedict[:dialogue])
|
mentioned_winery = detectWineryName(a, responsedict["dialogue"])
|
||||||
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
|
||||||
@@ -850,7 +850,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
result = responsedict[:dialogue]
|
result = responsedict["dialogue"]
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
error("presentbox() failed to generate a response")
|
error("presentbox() failed to generate a response")
|
||||||
@@ -913,10 +913,10 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10)
|
|||||||
"""
|
"""
|
||||||
requiredKeys = [:dialogue]
|
requiredKeys = [:dialogue]
|
||||||
|
|
||||||
# a.memory["shortmem"][:available_wine] is a vector of dictionary
|
# a.memory["shortmem"]["available_wine"] is a vector of dictionary
|
||||||
# context =
|
# context =
|
||||||
# if length(a.memory["shortmem"][:available_wine]) != 0
|
# if length(a.memory["shortmem"]["available_wine"]) != 0
|
||||||
# "Wines previously found in your inventory: $(availableWineToText(a.memory["shortmem"][:available_wine]))"
|
# "Wines previously found in your inventory: $(availableWineToText(a.memory["shortmem"]["available_wine"]))"
|
||||||
# else
|
# else
|
||||||
# "N/A"
|
# "N/A"
|
||||||
# end
|
# end
|
||||||
@@ -1003,8 +1003,8 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10)
|
|||||||
# 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
|
||||||
@@ -1018,7 +1018,7 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10)
|
|||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
result = responsedict[:dialogue]
|
result = responsedict["dialogue"]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@@ -1088,15 +1088,15 @@ function generatechat(a::virtualcustomer;
|
|||||||
converPartnerName::Union{String, Nothing}=nothing, maxattempt=10, recentEventNum=10
|
converPartnerName::Union{String, Nothing}=nothing, maxattempt=10, recentEventNum=10
|
||||||
)
|
)
|
||||||
|
|
||||||
recent_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recentEventNum; includelatest=true)
|
recent_ind = GeneralUtils.recentElementsIndex(length(a.memory["events"]), recentEventNum; includelatest=true)
|
||||||
recentEventsDict = createEventsLog(a.memory[:events]; index=recent_ind)
|
recentEventsDict = createEventsLog(a.memory["events"]; index=recent_ind)
|
||||||
response = nothing # placeholder for show when error msg show up
|
response = nothing # placeholder for show when error msg show up
|
||||||
errornote = "N/A"
|
errornote = "N/A"
|
||||||
header = ["Dialogue:", "Role:"]
|
header = ["Dialogue:", "Role:"]
|
||||||
dictkey = ["dialogue", "role"]
|
dictkey = ["dialogue", "role"]
|
||||||
llmkwargs=Dict(
|
llmkwargs=Dict(
|
||||||
:num_ctx => 32768,
|
"num_ctx" => 32768,
|
||||||
:temperature => 0.5,
|
"temperature" => 0.5,
|
||||||
)
|
)
|
||||||
|
|
||||||
for attempt in 1:maxattempt
|
for attempt in 1:maxattempt
|
||||||
@@ -1141,15 +1141,15 @@ function generatechat(a::virtualcustomer;
|
|||||||
|
|
||||||
responsedict = GeneralUtils.textToDict(response, header;
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
dictKey=dictkey, symbolkey=true)
|
dictKey=dictkey, symbolkey=true)
|
||||||
if responsedict[:role] == "no"
|
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."
|
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())")
|
println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
# check if the dialogue is the same as the previous one
|
# check if the dialogue is the same as the previous one
|
||||||
if length(responsedict[:dialogue]) != 0 && responsedict[:dialogue] == a.chathistory[end]["text"]
|
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."
|
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())")
|
println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
@@ -1157,7 +1157,7 @@ function generatechat(a::virtualcustomer;
|
|||||||
# check whether LLM just repeat the previous dialogue
|
# check whether LLM just repeat the previous dialogue
|
||||||
dublicate = false
|
dublicate = false
|
||||||
for msg in a.chathistory
|
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."
|
errornote = "In your previous attempt, you repeated the earlier dialogue. Please try again."
|
||||||
println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
dublicate = true
|
dublicate = true
|
||||||
@@ -1170,7 +1170,7 @@ function generatechat(a::virtualcustomer;
|
|||||||
|
|
||||||
# println("\n$prompt", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
# println("\n$prompt", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
# println("\n $response")
|
# println("\n $response")
|
||||||
return responsedict[:dialogue]
|
return responsedict["dialogue"]
|
||||||
end
|
end
|
||||||
error("generatechat failed to generate a response")
|
error("generatechat failed to generate a response")
|
||||||
end
|
end
|
||||||
@@ -1285,12 +1285,12 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String
|
|||||||
dictkey = ["q1"]
|
dictkey = ["q1"]
|
||||||
|
|
||||||
# context =
|
# context =
|
||||||
# if length(a.memory["shortmem"][:available_wine]) != 0
|
# if length(a.memory["shortmem"]["available_wine"]) != 0
|
||||||
# "Available wines you've found in your inventory so far: $(availableWineToText(a.memory["shortmem"][:available_wine]))"
|
# "Available wines you've found in your inventory so far: $(availableWineToText(a.memory["shortmem"]["available_wine"]))"
|
||||||
# else
|
# else
|
||||||
# "N/A"
|
# "N/A"
|
||||||
# end
|
# 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)
|
# recent_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recent)
|
||||||
# recentevents = a.memory[:events][recent_ind]
|
# recentevents = a.memory[:events][recent_ind]
|
||||||
@@ -1357,8 +1357,8 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String
|
|||||||
# 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
|
||||||
@@ -1402,7 +1402,7 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String
|
|||||||
|
|
||||||
responsedict = GeneralUtils.textToDict(response, header;
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
dictKey=dictkey, symbolkey=true)
|
dictKey=dictkey, symbolkey=true)
|
||||||
response = "Q1: " * responsedict[:q1]
|
response = "Q1: " * responsedict["q1"]
|
||||||
println("\nYiemAgent generatequestion() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent generatequestion() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
try pprintln(response) catch e println(response) end
|
try pprintln(response) catch e println(response) end
|
||||||
|
|
||||||
@@ -1446,11 +1446,11 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent::
|
|||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
header = ["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])])
|
dictkey = lowercase.(["Event_$i" for i in eachindex(a.memory["events"])])
|
||||||
|
|
||||||
ind = GeneralUtils.nonRecentElementsIndex(length(a.memory[:events]), skiprecent)
|
ind = GeneralUtils.nonRecentElementsIndex(length(a.memory["events"]), skiprecent)
|
||||||
events = a.memory[:events][ind]
|
events = a.memory["events"][ind]
|
||||||
timeline = createTimeline(events)
|
timeline = createTimeline(events)
|
||||||
|
|
||||||
errornote = "N/A"
|
errornote = "N/A"
|
||||||
@@ -1570,7 +1570,7 @@ function detectWineryName(a, text)
|
|||||||
responsedict = GeneralUtils.textToDict(response, header;
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
dictKey=dictkey, symbolkey=true)
|
dictKey=dictkey, symbolkey=true)
|
||||||
|
|
||||||
result = responsedict[:winery_names]
|
result = responsedict["winery_names"]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ function virtualWineUserRecommendbox(a::T1, input
|
|||||||
)::Union{Tuple{String, Number, Number, Bool}, Tuple{String, Nothing, Number, Bool}} where {T1<:agent}
|
)::Union{Tuple{String, Number, Number, Bool}, Tuple{String, Nothing, Number, Bool}} where {T1<:agent}
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
virtualWineCustomer = a.config[:externalservice][:virtualWineCustomer_1]
|
virtualWineCustomer = a.config["externalservice"]["virtualWineCustomer_1"]
|
||||||
llminfo = virtualWineCustomer[:llminfo]
|
llminfo = virtualWineCustomer["llminfo"]
|
||||||
prompt =
|
prompt =
|
||||||
if llminfo[:name] == "llama3instruct"
|
if llminfo["name"] == "llama3instruct"
|
||||||
formatLLMtext_llama3instruct("assistant", input)
|
formatLLMtext_llama3instruct("assistant", input)
|
||||||
else
|
else
|
||||||
error("llm model name is not defied yet $(@__LINE__)")
|
error("llm model name is not defied yet $(@__LINE__)")
|
||||||
@@ -48,26 +48,26 @@ function virtualWineUserRecommendbox(a::T1, input
|
|||||||
|
|
||||||
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
msgMeta = GeneralUtils.generate_msgMeta(
|
||||||
virtualWineCustomer[:mqtttopic],
|
virtualWineCustomer["mqtttopic"],
|
||||||
senderName= "virtualWineUserRecommendbox",
|
senderName= "virtualWineUserRecommendbox",
|
||||||
senderId= a.id,
|
senderId= a.id,
|
||||||
receiverName= "virtualWineCustomer",
|
receiverName= "virtualWineCustomer",
|
||||||
mqttBroker= a.config[:mqttServerInfo][:broker],
|
mqttBroker= a.config["mqttServerInfo"]["broker"],
|
||||||
mqttBrokerPort= a.config[:mqttServerInfo][:port],
|
mqttBrokerPort= a.config["mqttServerInfo"]["port"],
|
||||||
msgId = "dummyid" #CHANGE remove after testing finished
|
msgId = "dummyid" #CHANGE remove after testing finished
|
||||||
)
|
)
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
outgoingMsg = Dict(
|
||||||
:msgMeta=> msgMeta,
|
"msgMeta"=> msgMeta,
|
||||||
:payload=> Dict(
|
"payload"=> Dict(
|
||||||
:text=> prompt,
|
"text"=> prompt,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
result = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
result = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||||
response = result[:response]
|
response = result["response"]
|
||||||
|
|
||||||
return (response[:text], response[:select], response[:reward], response[:isterminal])
|
return (response["text"], response["select"], response["reward"], response["isterminal"])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -171,26 +171,26 @@ function virtualWineUserChatbox(config::T1, input::T2, virtualCustomerChatHistor
|
|||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pushfirst!(virtualCustomerChatHistory, Dict(:name=> "system", :text=> systemmsg))
|
pushfirst!(virtualCustomerChatHistory, Dict("name"=> "system", "text"=> systemmsg))
|
||||||
|
|
||||||
# replace the :user key in chathistory to allow the virtual wine customer AI roleplay
|
# replace the :user key in chathistory to allow the virtual wine customer AI roleplay
|
||||||
chathistory::Vector{Dict{String, Any}} = Vector{Dict{String, Any}}()
|
chathistory::Vector{Dict{String, Any}} = Vector{Dict{String, Any}}()
|
||||||
for i in virtualCustomerChatHistory
|
for i in virtualCustomerChatHistory
|
||||||
newdict = Dict()
|
newdict = Dict()
|
||||||
newdict[:name] =
|
newdict["name"] =
|
||||||
if i[:name] == "user"
|
if i["name"] == "user"
|
||||||
"you"
|
"you"
|
||||||
elseif i[:name] == "assistant"
|
elseif i["name"] == "assistant"
|
||||||
"sommelier"
|
"sommelier"
|
||||||
else
|
else
|
||||||
i[:name]
|
i["name"]
|
||||||
end
|
end
|
||||||
|
|
||||||
newdict[:text] = i[:text]
|
newdict["text"] = i["text"]
|
||||||
push!(chathistory, newdict)
|
push!(chathistory, newdict)
|
||||||
end
|
end
|
||||||
|
|
||||||
push!(chathistory, Dict(:name=> "assistant", :text=> input))
|
push!(chathistory, Dict("name"=> "assistant", "text"=> input))
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = formatLLMtext(chathistory, "llama3instruct")
|
prompt = formatLLMtext(chathistory, "llama3instruct")
|
||||||
@@ -201,23 +201,23 @@ function virtualWineUserChatbox(config::T1, input::T2, virtualCustomerChatHistor
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
pprint(prompt)
|
pprint(prompt)
|
||||||
externalService = config[:externalservice][:text2textinstruct]
|
externalService = config["externalservice"]["text2textinstruct"]
|
||||||
|
|
||||||
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
msgMeta = GeneralUtils.generate_msgMeta(
|
||||||
externalService[:mqtttopic],
|
externalService["mqtttopic"],
|
||||||
senderName= "virtualWineUserChatbox",
|
senderName= "virtualWineUserChatbox",
|
||||||
senderId= string(uuid4()),
|
senderId= string(uuid4()),
|
||||||
receiverName= "text2textinstruct",
|
receiverName= "text2textinstruct",
|
||||||
mqttBroker= config[:mqttServerInfo][:broker],
|
mqttBroker= config["mqttServerInfo"]["broker"],
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
mqttBrokerPort= config["mqttServerInfo"]["port"],
|
||||||
msgId = string(uuid4()) #CHANGE remove after testing finished
|
msgId = string(uuid4()) #CHANGE remove after testing finished
|
||||||
)
|
)
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
outgoingMsg = Dict(
|
||||||
:msgMeta=> msgMeta,
|
"msgMeta"=> msgMeta,
|
||||||
:payload=> Dict(
|
"payload"=> Dict(
|
||||||
:text=> prompt,
|
"text"=> prompt,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ function virtualWineUserChatbox(config::T1, input::T2, virtualCustomerChatHistor
|
|||||||
for attempt in 1:5
|
for attempt in 1:5
|
||||||
try
|
try
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||||
_responseJsonStr = response[:response][:text]
|
_responseJsonStr = response["response"]["text"]
|
||||||
expectedJsonExample =
|
expectedJsonExample =
|
||||||
"""
|
"""
|
||||||
Here is an expected JSON format:
|
Here is an expected JSON format:
|
||||||
@@ -239,10 +239,10 @@ function virtualWineUserChatbox(config::T1, input::T2, virtualCustomerChatHistor
|
|||||||
responseJsonStr = jsoncorrection(config, _responseJsonStr, expectedJsonExample)
|
responseJsonStr = jsoncorrection(config, _responseJsonStr, expectedJsonExample)
|
||||||
responseDict = copy(JSON.parsefile(responseJsonStr))
|
responseDict = copy(JSON.parsefile(responseJsonStr))
|
||||||
|
|
||||||
text::AbstractString = responseDict[:text]
|
text::AbstractString = responseDict["text"]
|
||||||
select::Union{Nothing, Number} = responseDict[:select] == "null" ? nothing : responseDict[:select]
|
select::Union{Nothing, Number} = responseDict["select"] == "null" ? nothing : responseDict["select"]
|
||||||
reward::Number = responseDict[:reward]
|
reward::Number = responseDict["reward"]
|
||||||
isterminal::Bool = responseDict[:isterminal]
|
isterminal::Bool = responseDict["isterminal"]
|
||||||
|
|
||||||
if text != ""
|
if text != ""
|
||||||
# pass test
|
# pass test
|
||||||
@@ -455,8 +455,8 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
|||||||
|
|
||||||
unformatPrompt =
|
unformatPrompt =
|
||||||
[
|
[
|
||||||
Dict(:name=> "system", :text=> systemmsg),
|
Dict("name"=> "system", "text"=> systemmsg),
|
||||||
Dict(:name=> "user", :text=> usermsg)
|
Dict("name"=> "user", "text"=> usermsg)
|
||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
@@ -544,21 +544,20 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
|||||||
if j ∉ removekeys
|
if j ∉ removekeys
|
||||||
# in case j is wine_price it needs to be checked differently because its value is ranged
|
# in case j is wine_price it needs to be checked differently because its value is ranged
|
||||||
if j == :wine_price
|
if j == :wine_price
|
||||||
if responsedict[:wine_price] != "N/A"
|
if responsedict["wine_price"] != "N/A"
|
||||||
# check whether wine_price is in ranged number
|
if !occursin("to", responsedict["wine_price"])
|
||||||
if !occursin("to", responsedict[:wine_price])
|
errornote = "In your previous attempt, the 'wine_price' was set to $(responsedict["wine_price"]) which is not a correct format. Please adjust it accordingly."
|
||||||
errornote = "In your previous attempt, the 'wine_price' was set to $(responsedict[:wine_price]) which is not a correct format. Please adjust it accordingly."
|
|
||||||
println("\nERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
checkFlag = true
|
checkFlag = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
# # check whether max wine_price is in the input
|
# # check whether max wine_price is in the input
|
||||||
# pricerange = split(responsedict[:wine_price], '-')
|
# pricerange = split(responsedict["wine_price"], '-')
|
||||||
# minprice = pricerange[1]
|
# minprice = pricerange[1]
|
||||||
# maxprice = pricerange[end]
|
# maxprice = pricerange[end]
|
||||||
# if !occursin(maxprice, input)
|
# if !occursin(maxprice, input)
|
||||||
# responsedict[:wine_price] = "N/A"
|
# responsedict["wine_price"] = "N/A"
|
||||||
# end
|
# end
|
||||||
# # price range like 100-100 is not good
|
# # price range like 100-100 is not good
|
||||||
# if minprice == maxprice
|
# if minprice == maxprice
|
||||||
@@ -735,7 +734,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
|
|
||||||
unformatPrompt =
|
unformatPrompt =
|
||||||
[
|
[
|
||||||
Dict(:name=> "system", :text=> systemmsg),
|
Dict("name"=> "system", "text"=> systemmsg),
|
||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
@@ -883,8 +882,8 @@ function paraphrase(text2textInstructLLM::Function, text::String)
|
|||||||
|
|
||||||
_prompt =
|
_prompt =
|
||||||
[
|
[
|
||||||
Dict(:name => "system", :text => systemmsg),
|
Dict("name" => "system", "text" => systemmsg),
|
||||||
Dict(:name => "user", :text => usermsg)
|
Dict("name" => "user", "text" => usermsg)
|
||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
@@ -935,7 +934,7 @@ function paraphrase(text2textInstructLLM::Function, text::String)
|
|||||||
println("\nparaphrase() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nparaphrase() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
pprintln(Dict(responsedict))
|
pprintln(Dict(responsedict))
|
||||||
|
|
||||||
result = responsedict[:paraphrase]
|
result = responsedict["paraphrase"]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
catch e
|
catch e
|
||||||
@@ -1004,10 +1003,10 @@ function jsoncorrection(config::T1, input::T2, correctJsonExample::T3;
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# apply LLM specific instruct format
|
# apply LLM specific instruct format
|
||||||
externalService = config[:externalservice][:text2textinstruct]
|
externalService = config["externalservice"]["text2textinstruct"]
|
||||||
llminfo = externalService[:llminfo]
|
llminfo = externalService["llminfo"]
|
||||||
prompt =
|
prompt =
|
||||||
if llminfo[:name] == "llama3instruct"
|
if llminfo["name"] == "llama3instruct"
|
||||||
formatLLMtext_llama3instruct("system", _prompt)
|
formatLLMtext_llama3instruct("system", _prompt)
|
||||||
else
|
else
|
||||||
error("llm model name is not defied yet $(@__LINE__)")
|
error("llm model name is not defied yet $(@__LINE__)")
|
||||||
@@ -1015,21 +1014,21 @@ function jsoncorrection(config::T1, input::T2, correctJsonExample::T3;
|
|||||||
|
|
||||||
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
msgMeta = GeneralUtils.generate_msgMeta(
|
||||||
externalService[:mqtttopic],
|
externalService["mqtttopic"],
|
||||||
senderName= "jsoncorrection",
|
senderName= "jsoncorrection",
|
||||||
senderId= string(uuid4()),
|
senderId= string(uuid4()),
|
||||||
receiverName= "text2textinstruct",
|
receiverName= "text2textinstruct",
|
||||||
mqttBroker= config[:mqttServerInfo][:broker],
|
mqttBroker= config["mqttServerInfo"]["broker"],
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
mqttBrokerPort= config["mqttServerInfo"]["port"],
|
||||||
)
|
)
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
outgoingMsg = Dict(
|
||||||
:msgMeta=> msgMeta,
|
"msgMeta"=> msgMeta,
|
||||||
:payload=> Dict(
|
"payload"=> Dict(
|
||||||
:text=> prompt,
|
"text"=> prompt,
|
||||||
:kwargs=> Dict(
|
"kwargs"=> Dict(
|
||||||
:max_tokens=> 512,
|
"max_tokens"=> 512,
|
||||||
:stop=> ["<|eot_id|>"],
|
"stop"=> ["<|eot_id|>"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
66
src/type.jl
66
src/type.jl
@@ -38,7 +38,7 @@ function companion(
|
|||||||
name::String= "Assistant",
|
name::String= "Assistant",
|
||||||
id::String= GeneralUtils.uuid4snakecase(),
|
id::String= GeneralUtils.uuid4snakecase(),
|
||||||
maxHistoryMsg::Integer= 20,
|
maxHistoryMsg::Integer= 20,
|
||||||
chathistory::Vector{Dict{Symbol, String}} = Vector{Dict{Symbol, String}}(),
|
chathistory::Vector{Dict{String, String}} = Vector{Dict{String, String}}(),
|
||||||
llmFormatName::String= "granite3",
|
llmFormatName::String= "granite3",
|
||||||
systemmsg::String=
|
systemmsg::String=
|
||||||
"""
|
"""
|
||||||
@@ -55,7 +55,7 @@ function companion(
|
|||||||
|
|
||||||
tools = Dict( # update input format
|
tools = Dict( # update input format
|
||||||
"CHATBOX"=> Dict(
|
"CHATBOX"=> Dict(
|
||||||
:description => "- CHATBOX which you can use to talk with the user. The input is your intentions for the dialogue. Be specific.",
|
"description" => "- CHATBOX which you can use to talk with the user. The input is your intentions for the dialogue. Be specific.",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,14 +63,14 @@ function companion(
|
|||||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
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
|
NO "system" message in chathistory because I want to add it at the inference time
|
||||||
chathistory= [
|
chathistory= [
|
||||||
Dict(:name=>"user", :text=> "Wassup!", :timestamp=> Dates.now()),
|
Dict("name"=>"user", "text"=> "Wassup!", "timestamp"=> Dates.now()),
|
||||||
Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()),
|
Dict("name"=>"assistant", "text"=> "Hi I'm your assistant.", "timestamp"=> Dates.now()),
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
memory = Dict{String, Any}(
|
memory = Dict{String, Any}(
|
||||||
:events=> Vector{Dict{String, Any}}(),
|
"events"=> Vector{Dict{String, Any}}(),
|
||||||
:state=> Dict{String, Any}(), # state of the agent
|
"state"=> Dict{String, Any}(), # state of the agent
|
||||||
:recap=> OrderedDict{String, Any}(), # recap summary of the conversation
|
"recap"=> OrderedDict{String, Any}(), # recap summary of the conversation
|
||||||
)
|
)
|
||||||
|
|
||||||
newAgent = companion(
|
newAgent = companion(
|
||||||
@@ -116,7 +116,7 @@ end
|
|||||||
Retailer name associated with the sommelier. Default: `"retailer_name"`
|
Retailer name associated with the sommelier. Default: `"retailer_name"`
|
||||||
- `maxHistoryMsg::Integer`
|
- `maxHistoryMsg::Integer`
|
||||||
Maximum history messages. Default: `20`
|
Maximum history messages. Default: `20`
|
||||||
- `chathistory::Vector{Dict{Symbol, String}}`
|
- `chathistory::Vector{Dict{String, String}}`
|
||||||
Chat history. Default: empty vector.
|
Chat history. Default: empty vector.
|
||||||
- `llmFormatName::String`
|
- `llmFormatName::String`
|
||||||
LLM format name. Default: `"granite3"`
|
LLM format name. Default: `"granite3"`
|
||||||
@@ -146,20 +146,20 @@ function sommelier(
|
|||||||
id::String= string(uuid4()),
|
id::String= string(uuid4()),
|
||||||
retailername::String= "retailer_name",
|
retailername::String= "retailer_name",
|
||||||
maxHistoryMsg::Integer= 20,
|
maxHistoryMsg::Integer= 20,
|
||||||
chathistory::Vector{Dict{Symbol, String}} = Vector{Dict{Symbol, String}}(),
|
chathistory::Vector{Dict{String, String}} = Vector{Dict{String, String}}(),
|
||||||
llmFormatName::String= "granite3"
|
llmFormatName::String= "granite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
tools = Dict( # update input format
|
tools = Dict( # update input format
|
||||||
"chatbox"=> Dict(
|
"chatbox"=> Dict(
|
||||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
"description" => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
"input" => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||||
:output => "" ,
|
"output" => "" ,
|
||||||
),
|
),
|
||||||
"winestock"=> Dict(
|
"winestock"=> Dict(
|
||||||
:description => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
"description" => "<winestock tool description>A handy tool for searching wine in your inventory that match the user preferences.</winestock tool description>",
|
||||||
:input => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
"input" => """<input>Input is a JSON-formatted string that contains a detailed and precise search query.</input><input example>{\"wine type\": \"rose\", \"price\": \"max 35\", \"sweetness level\": \"sweet\", \"intensity level\": \"light bodied\", \"Tannin level\": \"low\", \"Acidity level\": \"low\"}</input example>""",
|
||||||
:output => """<output>Output are wines that match the search query in JSON format.""",
|
"output" => """<output>Output are wines that match the search query in JSON format.""",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -167,19 +167,19 @@ function sommelier(
|
|||||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
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
|
NO "system" message in chathistory because I want to add it at the inference time
|
||||||
chathistory= [
|
chathistory= [
|
||||||
Dict(:name=>"user", :text=> "Wassup!", :timestamp=> Dates.now()),
|
Dict("name"=>"user", "text"=> "Wassup!", "timestamp"=> Dates.now()),
|
||||||
Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()),
|
Dict("name"=>"assistant", "text"=> "Hi I'm your assistant.", "timestamp"=> Dates.now()),
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
memory = Dict{String, Any}(
|
memory = Dict{String, Any}(
|
||||||
:shortmem=> OrderedDict{String, Any}(
|
"shortmem"=> OrderedDict{String, Any}(
|
||||||
:db_search_result=> Any[],
|
"db_search_result"=> Any[],
|
||||||
:scratchpad=> "", #[PENDING] should be a dict e.g. Dict(:database_search_result=>Dict(:wines=> "", :search_query=> ""))
|
"scratchpad"=> "", #PENDING should be a dict e.g. Dict("database_search_result"=>Dict("wines"=> "", "search_query"=> ""))
|
||||||
),
|
),
|
||||||
:events=> Vector{Dict{String, Any}}(),
|
"events"=> Vector{Dict{String, Any}}(),
|
||||||
:state=> Dict{String, Any}(
|
"state"=> Dict{String, Any}(
|
||||||
),
|
),
|
||||||
:recap=> OrderedDict{String, Any}(),
|
"recap"=> OrderedDict{String, Any}(),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -297,7 +297,7 @@ function virtualcustomer(
|
|||||||
name::String= "Assistant",
|
name::String= "Assistant",
|
||||||
id::String= string(uuid4()),
|
id::String= string(uuid4()),
|
||||||
maxHistoryMsg::Integer= 20,
|
maxHistoryMsg::Integer= 20,
|
||||||
chathistory::Vector{Dict{Symbol, String}} = Vector{Dict{Symbol, String}}(),
|
chathistory::Vector{Dict{String, String}} = Vector{Dict{String, String}}(),
|
||||||
llmFormatName::String= "granite3",
|
llmFormatName::String= "granite3",
|
||||||
systemmsg::String=
|
systemmsg::String=
|
||||||
"""
|
"""
|
||||||
@@ -314,9 +314,9 @@ function virtualcustomer(
|
|||||||
|
|
||||||
tools = Dict( # update input format
|
tools = Dict( # update input format
|
||||||
"chatbox"=> Dict(
|
"chatbox"=> Dict(
|
||||||
:description => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
"description" => "<askbox tool description>Useful for when you need to ask the user for more context. Do not ask the user their own question.</askbox tool description>",
|
||||||
:input => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
"input" => """<input>Input is a text in JSON format.</input><input example>{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}</input example>""",
|
||||||
:output => "" ,
|
"output" => "" ,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -324,17 +324,17 @@ function virtualcustomer(
|
|||||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
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
|
NO "system" message in chathistory because I want to add it at the inference time
|
||||||
chathistory= [
|
chathistory= [
|
||||||
Dict(:name=>"user", :text=> "Wassup!", :timestamp=> Dates.now()),
|
Dict("name"=>"user", "text"=> "Wassup!", "timestamp"=> Dates.now()),
|
||||||
Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()),
|
Dict("name"=>"assistant", "text"=> "Hi I'm your assistant.", "timestamp"=> Dates.now()),
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
memory = Dict{String, Any}(
|
memory = Dict{String, Any}(
|
||||||
:shortmem=> OrderedDict{String, Any}(
|
"shortmem"=> OrderedDict{String, Any}(
|
||||||
),
|
),
|
||||||
:events=> Vector{Dict{String, Any}}(),
|
"events"=> Vector{Dict{String, Any}}(),
|
||||||
:state=> Dict{String, Any}(
|
"state"=> Dict{String, Any}(
|
||||||
),
|
),
|
||||||
:recap=> OrderedDict{String, Any}(),
|
"recap"=> OrderedDict{String, Any}(),
|
||||||
)
|
)
|
||||||
|
|
||||||
newAgent = virtualcustomer(
|
newAgent = virtualcustomer(
|
||||||
|
|||||||
97
src/util.jl
97
src/util.jl
@@ -26,14 +26,14 @@ julia> client, connection = MakeConnection("test.mosquitto.org", 1883)
|
|||||||
julia> connect(client, connection)
|
julia> connect(client, connection)
|
||||||
julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic")
|
julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic")
|
||||||
julia> agentConfig = Dict(
|
julia> agentConfig = Dict(
|
||||||
:receiveprompt=>Dict(
|
"receiveprompt"=>Dict(
|
||||||
:mqtttopic=> "testtopic/receive",
|
"mqtttopic"=> "testtopic/receive",
|
||||||
),
|
),
|
||||||
:receiveinternal=>Dict(
|
"receiveinternal"=>Dict(
|
||||||
:mqtttopic=> "testtopic/internal",
|
"mqtttopic"=> "testtopic/internal",
|
||||||
),
|
),
|
||||||
:text2text=>Dict(
|
"text2text"=>Dict(
|
||||||
:mqtttopic=> "testtopic/text2text",
|
"mqtttopic"=> "testtopic/text2text",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
julia> a = YiemAgent.sommelier(
|
julia> a = YiemAgent.sommelier(
|
||||||
@@ -52,9 +52,9 @@ julia> YiemAgent.clearhistory(a)
|
|||||||
"""
|
"""
|
||||||
function clearhistory(a::T) where {T<:agent}
|
function clearhistory(a::T) where {T<:agent}
|
||||||
empty!(a.chathistory)
|
empty!(a.chathistory)
|
||||||
empty!(a.memory[:shortmem])
|
empty!(a.memory["shortmem"])
|
||||||
empty!(a.memory[:events])
|
empty!(a.memory["events"])
|
||||||
a.memory[:chatbox] = ""
|
a.memory["chatbox"] = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ This function takes in a vector of dictionaries and outputs a single string wher
|
|||||||
|
|
||||||
julia> using Revise
|
julia> using Revise
|
||||||
julia> using GeneralUtils
|
julia> using GeneralUtils
|
||||||
julia> vecd = [Dict(:name => "John", :text => "Hello"), Dict(:name => "Jane", :text => "Goodbye")]
|
julia> vecd = [Dict("name" => "John", "text" => "Hello"), Dict("name" => "Jane", "text" => "Goodbye")]
|
||||||
julia> GeneralUtils.vectorOfDictToText(vecd, withkey=true)
|
julia> GeneralUtils.vectorOfDictToText(vecd, withkey=true)
|
||||||
"John> Hello\nJane> Goodbye\n"
|
"John> Hello\nJane> Goodbye\n"
|
||||||
```
|
```
|
||||||
@@ -233,17 +233,17 @@ function eventdict(;
|
|||||||
)
|
)
|
||||||
|
|
||||||
d = Dict{String, Any}(
|
d = Dict{String, Any}(
|
||||||
:event_description=> event_description,
|
"event_description"=> event_description,
|
||||||
:timestamp=> timestamp,
|
"timestamp"=> timestamp,
|
||||||
:subject=> subject,
|
"subject"=> subject,
|
||||||
:thought=> thought,
|
"thought"=> thought,
|
||||||
:actionname=> actionname,
|
"actionname"=> actionname,
|
||||||
:actioninput=> actioninput,
|
"actioninput"=> actioninput,
|
||||||
:location=> location,
|
"location"=> location,
|
||||||
:equipment_used=> equipment_used,
|
"equipment_used"=> equipment_used,
|
||||||
:material_used=> material_used,
|
"material_used"=> material_used,
|
||||||
:observation=> observation,
|
"observation"=> observation,
|
||||||
:note=> note,
|
"note"=> note,
|
||||||
)
|
)
|
||||||
|
|
||||||
return d
|
return d
|
||||||
@@ -268,8 +268,8 @@ end
|
|||||||
# Example
|
# Example
|
||||||
|
|
||||||
events = [
|
events = [
|
||||||
Dict(:subject => "User", :actioninput => "Hello", :observation => nothing),
|
Dict("subject" => "User", "actioninput" => "Hello", "observation" => nothing),
|
||||||
Dict(:subject => "Assistant", :actioninput => "Hi there!", :observation => "with a smile")
|
Dict("subject" => "Assistant", "actioninput" => "Hi there!", "observation" => "with a smile")
|
||||||
]
|
]
|
||||||
timeline = createTimeline(events)
|
timeline = createTimeline(events)
|
||||||
# 1) User> Hello
|
# 1) User> Hello
|
||||||
@@ -293,15 +293,14 @@ function createTimeline(events::T1; eventindex::Union{UnitRange, Nothing}=nothin
|
|||||||
for i in ind
|
for i in ind
|
||||||
event = events[i]
|
event = events[i]
|
||||||
# If no outcome exists, format without outcome
|
# If no outcome exists, format without outcome
|
||||||
# if event[:actionname] == "CHATBOX"
|
# if event["actionname"] == "CHATBOX"
|
||||||
# timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput])\n"
|
# timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"])\n"
|
||||||
# elseif event[:actionname] == "CHECKINVENTORY" && event[:observation] === nothing
|
# elseif event["actionname"] == "CHECKINVENTORY" && event["observation"] === nothing
|
||||||
# timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: Not done yet.\n"
|
# timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: Not done yet.\n"
|
||||||
# If outcome exists, include it in formatting
|
if event["actionname"] == "CHECKWINE"
|
||||||
if event[:actionname] == "CHECKWINE"
|
timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: $(event["observation"])\\n"
|
||||||
timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: $(event[:observation])\n"
|
|
||||||
else
|
else
|
||||||
timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput])\n"
|
timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"])\\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -325,11 +324,11 @@ end
|
|||||||
# for i in ind
|
# for i in ind
|
||||||
# event = events[i]
|
# event = events[i]
|
||||||
# # If no outcome exists, format without outcome
|
# # If no outcome exists, format without outcome
|
||||||
# if event[:observation] === nothing
|
# if event["observation"] === nothing
|
||||||
# timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: Not done yet.\n"
|
# timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: Not done yet.\n"
|
||||||
# # If outcome exists, include it in formatting
|
# # If outcome exists, include it in formatting
|
||||||
# else
|
# else
|
||||||
# timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: $(event[:observation])\n"
|
# timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: $(event["observation"])\\n"
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
|
|
||||||
@@ -341,7 +340,7 @@ end
|
|||||||
function createEventsLog(events::T1; index::Union{UnitRange, Nothing}=nothing
|
function createEventsLog(events::T1; index::Union{UnitRange, Nothing}=nothing
|
||||||
) where {T1<:AbstractVector}
|
) where {T1<:AbstractVector}
|
||||||
# Initialize empty log array
|
# Initialize empty log array
|
||||||
log = Dict{Symbol, String}[]
|
log = Dict{String, String}[]
|
||||||
|
|
||||||
# Determine which indices to use - either provided range or full length
|
# Determine which indices to use - either provided range or full length
|
||||||
ind =
|
ind =
|
||||||
@@ -355,20 +354,20 @@ function createEventsLog(events::T1; index::Union{UnitRange, Nothing}=nothing
|
|||||||
for i in ind
|
for i in ind
|
||||||
event = events[i]
|
event = events[i]
|
||||||
# If no outcome exists, format without outcome
|
# If no outcome exists, format without outcome
|
||||||
if event[:observation] === nothing
|
if event["observation"] === nothing
|
||||||
subject = event[:subject]
|
subject = event["subject"]
|
||||||
actionname = event[:actionname]
|
actionname = event["actionname"]
|
||||||
actioninput = event[:actioninput]
|
actioninput = event["actioninput"]
|
||||||
str = "actionname: $actionname, actioninput: $actioninput"
|
str = "actionname: $actionname, actioninput: $actioninput"
|
||||||
d = Dict{Symbol, String}(:name=>subject, :text=>str)
|
d = Dict{String, String}("name"=>subject, "text"=>str)
|
||||||
push!(log, d)
|
push!(log, d)
|
||||||
else
|
else
|
||||||
subject = event[:subject]
|
subject = event["subject"]
|
||||||
actionname = event[:actionname]
|
actionname = event["actionname"]
|
||||||
actioninput = event[:actioninput]
|
actioninput = event["actioninput"]
|
||||||
observation = event[:observation]
|
observation = event["observation"]
|
||||||
str = "actionname: $actionname, actioninput: $actioninput, observation: $observation"
|
str = "actionname: $actionname, actioninput: $actioninput, observation: $observation"
|
||||||
d = Dict{Symbol, String}(:name=>subject, :text=>str)
|
d = Dict{String, String}("name"=>subject, "text"=>str)
|
||||||
push!(log, d)
|
push!(log, d)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -380,7 +379,7 @@ end
|
|||||||
function createChatLog(chatdict::T1; index::Union{UnitRange, Nothing}=nothing
|
function createChatLog(chatdict::T1; index::Union{UnitRange, Nothing}=nothing
|
||||||
) where {T1<:AbstractVector}
|
) where {T1<:AbstractVector}
|
||||||
# Initialize empty log array
|
# Initialize empty log array
|
||||||
log = Dict{Symbol, String}[]
|
log = Dict{String, String}[]
|
||||||
|
|
||||||
# Determine which indices to use - either provided range or full length
|
# Determine which indices to use - either provided range or full length
|
||||||
ind =
|
ind =
|
||||||
@@ -393,9 +392,9 @@ function createChatLog(chatdict::T1; index::Union{UnitRange, Nothing}=nothing
|
|||||||
# Iterate through events and format each one
|
# Iterate through events and format each one
|
||||||
for i in ind
|
for i in ind
|
||||||
event = chatdict[i]
|
event = chatdict[i]
|
||||||
subject = event[:name]
|
subject = event["name"]
|
||||||
text = event[:text]
|
text = event["text"]
|
||||||
d = Dict{Symbol, String}(:name=>subject, :text=>text)
|
d = Dict{String, String}("name"=>subject, "text"=>text)
|
||||||
push!(log, d)
|
push!(log, d)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user