update
This commit is contained in:
@@ -223,12 +223,18 @@ function virtualWineUserChatbox(a::T1, input::T2, virtualCustomerChatHistory
|
||||
}
|
||||
|
||||
Here are some examples:
|
||||
|
||||
sommelier: "What's your budget?
|
||||
you:
|
||||
{
|
||||
"text": "My budget is 30 USD.",
|
||||
"select": null,
|
||||
"reward": 0,
|
||||
"isterminal": false
|
||||
}
|
||||
|
||||
sommelier: "The first option is Zena Crown and the second one is Buano Red."
|
||||
you:
|
||||
{
|
||||
"text": "I like the 2nd option.",
|
||||
"select": 2,
|
||||
@@ -307,12 +313,12 @@ function virtualWineUserChatbox(a::T1, input::T2, virtualCustomerChatHistory
|
||||
responseJsonStr = jsoncorrection(a, _responseJsonStr, expectedJsonExample)
|
||||
responseDict = copy(JSON3.read(responseJsonStr))
|
||||
|
||||
text = responseDict[:text]
|
||||
select = responseDict[:select] == "null" ? nothing : responseDict[:select]
|
||||
reward = responseDict[:reward]
|
||||
isterminal = responseDict[:isterminal]
|
||||
text::AbstractString = responseDict[:text]
|
||||
select::Union{Nothing, Number} = responseDict[:select] == "null" ? nothing : responseDict[:select]
|
||||
reward::Number = responseDict[:reward]
|
||||
isterminal::Bool = responseDict[:isterminal]
|
||||
|
||||
if text != "" && select != "" && reward != "" && isterminal != ""
|
||||
if text != ""
|
||||
# pass test
|
||||
else
|
||||
error("virtual customer not answer correctly")
|
||||
@@ -332,58 +338,6 @@ function virtualWineUserChatbox(a::T1, input::T2, virtualCustomerChatHistory
|
||||
error("virtualWineUserChatbox failed to get a response")
|
||||
end
|
||||
|
||||
# function virtualWineUserChatbox(a::T1, input::T2
|
||||
# )::Union{Tuple{String, Number, Number, Bool}, Tuple{String, Nothing, Number, Bool}} where {T1<:agent, T2<:AbstractString}
|
||||
|
||||
# # put in model format
|
||||
# virtualWineCustomer = a.config[:externalservice][:virtualWineCustomer_1]
|
||||
# llminfo = virtualWineCustomer[:llminfo]
|
||||
# prompt =
|
||||
# if llminfo[:name] == "llama3instruct"
|
||||
# formatLLMtext_llama3instruct("assistant", input)
|
||||
# else
|
||||
# error("llm model name is not defied yet $(@__LINE__)")
|
||||
# end
|
||||
|
||||
# # send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
||||
# msgMeta = GeneralUtils.generate_msgMeta(
|
||||
# virtualWineCustomer[:mqtttopic],
|
||||
# senderName= "virtualWineUserChatbox",
|
||||
# senderId= a.id,
|
||||
# receiverName= "virtualWineCustomer",
|
||||
# mqttBroker= a.config[:mqttServerInfo][:broker],
|
||||
# mqttBrokerPort= a.config[:mqttServerInfo][:port],
|
||||
# msgId = "dummyid" #CHANGE remove after testing finished
|
||||
# )
|
||||
|
||||
# outgoingMsg = Dict(
|
||||
# :msgMeta=> msgMeta,
|
||||
# :payload=> Dict(
|
||||
# :text=> prompt,
|
||||
# )
|
||||
# )
|
||||
|
||||
# attempt = 0
|
||||
# for attempt in 1:5
|
||||
# try
|
||||
# result = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||
# response = result[:response]
|
||||
|
||||
# return (response[:text], response[:select], response[:reward], response[:isterminal])
|
||||
# catch e
|
||||
# io = IOBuffer()
|
||||
# showerror(io, e)
|
||||
# errorMsg = String(take!(io))
|
||||
# st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
||||
# println("")
|
||||
# @warn "Error occurred: $errorMsg\n$st"
|
||||
# println("")
|
||||
# end
|
||||
# end
|
||||
# error("virtualWineUserChatbox failed to get a response")
|
||||
# end
|
||||
|
||||
|
||||
""" Search wine in stock.
|
||||
|
||||
# Arguments
|
||||
@@ -411,6 +365,150 @@ julia> result = winestock(agent, input)
|
||||
function winestock(a::T1, input::T2
|
||||
)::Union{Tuple{String, Number, Number, Bool}, Tuple{String, Nothing, Number, Bool}} where {T1<:agent, T2<:AbstractString}
|
||||
|
||||
systemmsg =
|
||||
"""
|
||||
As an attentive sommelier, your mission is to determine the user's preferred levels of sweetness, intensity, tannin, and acidity for a wine based on their input.
|
||||
You'll achieve this by referring to the provided conversion table.
|
||||
|
||||
Conversion Table:
|
||||
Intensity level:
|
||||
Level 1: May correspond to "light-bodied" or a similar description.
|
||||
Level 2: May correspond to "med-light" or a similar description.
|
||||
Level 3: May correspond to "medium" or a similar description.
|
||||
Level 4: May correspond to "med-full" or a similar description.
|
||||
Level 5: May correspond to "full" or a similar description.
|
||||
Sweetness level:
|
||||
Level 1: May correspond to "dry", "no-sweet" or a similar description.
|
||||
Level 2: May correspond to "off-dry", "less-sweet" or a similar description.
|
||||
Level 3: May correspond to "semi-sweet" or a similar description.
|
||||
Level 4: May correspond to "sweet" or a similar description.
|
||||
Level 5: May correspond to "very sweet" or a similar description.
|
||||
Tannin level:
|
||||
Level 1: May correspond to "low tannin" or a similar description.
|
||||
Level 2: May correspond to "semi-low tannin" or a similar description.
|
||||
Level 3: May correspond to "medium tannin" or a similar description.
|
||||
Level 4: May correspond to "semi-high tannin" or a similar description.
|
||||
Level 5: May correspond to "high tannin" or a similar description.
|
||||
Acidity level:
|
||||
Level 1: May correspond to "low acidity" or a similar description.
|
||||
Level 2: May correspond to "semi-low acidity" or a similar description.
|
||||
Level 3: May correspond to "medium acidity" or a similar description.
|
||||
Level 4: May correspond to "semi-high acidity" or a similar description.
|
||||
Level 5: May correspond to "high acidity" or a similar description.
|
||||
|
||||
You should only respond in JSON format as describe below:
|
||||
{
|
||||
"sweetness": "sweetness level",
|
||||
"acidity": "acidity level",
|
||||
"tannin": "tannin level",
|
||||
"intensity": "intensity level"
|
||||
}
|
||||
|
||||
Here are some examples:
|
||||
|
||||
user: red wines, price < 50, body=full-bodied, tannins=1, off dry, acidity=medium, intensity=intense, Thai dishes
|
||||
assistant:
|
||||
{
|
||||
"wine_attributes":
|
||||
{
|
||||
"sweetness": 2,
|
||||
"acidity": 3,
|
||||
"tannin": 1,
|
||||
"intensity": 5
|
||||
}
|
||||
}
|
||||
|
||||
Let's begin!
|
||||
"""
|
||||
|
||||
usermsg =
|
||||
"""
|
||||
$input
|
||||
"""
|
||||
|
||||
chathistory =
|
||||
[
|
||||
Dict(:name=> "system", :text=> systemmsg),
|
||||
Dict(:name=> "user", :text=> usermsg)
|
||||
]
|
||||
|
||||
# put in model format
|
||||
prompt = formatLLMtext(chathistory, "llama3instruct")
|
||||
prompt *=
|
||||
"""
|
||||
<|start_header_id|>assistant<|end_header_id|>
|
||||
{
|
||||
"""
|
||||
|
||||
pprint(prompt)
|
||||
externalService = a.config[:externalservice][:text2textinstruct]
|
||||
|
||||
# send formatted input to user using GeneralUtils.sendReceiveMqttMsg
|
||||
msgMeta = GeneralUtils.generate_msgMeta(
|
||||
externalService[:mqtttopic],
|
||||
senderName= "virtualWineUserChatbox",
|
||||
senderId= a.id,
|
||||
receiverName= "text2textinstruct",
|
||||
mqttBroker= a.config[:mqttServerInfo][:broker],
|
||||
mqttBrokerPort= a.config[:mqttServerInfo][:port],
|
||||
msgId = "dummyid" #CHANGE remove after testing finished
|
||||
)
|
||||
|
||||
outgoingMsg = Dict(
|
||||
:msgMeta=> msgMeta,
|
||||
:payload=> Dict(
|
||||
:text=> prompt,
|
||||
)
|
||||
)
|
||||
|
||||
attempt = 0
|
||||
for attempt in 1:5
|
||||
try
|
||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||
_responseJsonStr = response[:response][:text]
|
||||
expectedJsonExample =
|
||||
"""
|
||||
Here is an expected JSON format:
|
||||
{
|
||||
"wine_attributes":
|
||||
{
|
||||
"...": "...",
|
||||
"...": "...",
|
||||
}
|
||||
}
|
||||
"""
|
||||
responseJsonStr = jsoncorrection(a, _responseJsonStr, expectedJsonExample)
|
||||
responseDict = copy(JSON3.read(responseJsonStr))
|
||||
|
||||
return (text, select, reward, isterminal)
|
||||
catch e
|
||||
io = IOBuffer()
|
||||
showerror(io, e)
|
||||
errorMsg = String(take!(io))
|
||||
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
||||
println("")
|
||||
@warn "Error occurred: $errorMsg\n$st"
|
||||
println("")
|
||||
end
|
||||
end
|
||||
error("virtualWineUserChatbox failed to get a response")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
winesStr =
|
||||
"""
|
||||
1: El Enemigo Cabernet Franc 2019
|
||||
@@ -425,6 +523,23 @@ function winestock(a::T1, input::T2
|
||||
"""
|
||||
return result, nothing, 0, false
|
||||
end
|
||||
# function winestock(a::T1, input::T2
|
||||
# )::Union{Tuple{String, Number, Number, Bool}, Tuple{String, Nothing, Number, Bool}} where {T1<:agent, T2<:AbstractString}
|
||||
|
||||
# winesStr =
|
||||
# """
|
||||
# 1: El Enemigo Cabernet Franc 2019
|
||||
# 2: Tantara Chardonnay 2017
|
||||
# """
|
||||
# result =
|
||||
# """
|
||||
# I found the following wines in our stock:
|
||||
# {
|
||||
# $winesStr
|
||||
# }
|
||||
# """
|
||||
# return result, nothing, 0, false
|
||||
# end
|
||||
|
||||
|
||||
""" Attemp to correct LLM response's incorrect JSON response.
|
||||
@@ -446,13 +561,14 @@ julia>
|
||||
|
||||
# Signature
|
||||
"""
|
||||
function jsoncorrection(a::T1, input::T2,
|
||||
correctJsonExample::T3) where {T1<:agent, T2<:AbstractString, T3<:AbstractString}
|
||||
function jsoncorrection(a::T1, input::T2, correctJsonExample::T3;
|
||||
maxattempt::Integer=3
|
||||
) where {T1<:agent, T2<:AbstractString, T3<:AbstractString}
|
||||
|
||||
incorrectjson = deepcopy(input)
|
||||
correctjson = nothing
|
||||
|
||||
for attempt in 1:5
|
||||
for attempt in 1:maxattempt
|
||||
try
|
||||
d = copy(JSON3.read(incorrectjson))
|
||||
correctjson = incorrectjson
|
||||
|
||||
Reference in New Issue
Block a user