This commit is contained in:
2024-12-22 20:40:13 +07:00
parent 00f1a6775b
commit 27944a178b
2 changed files with 36 additions and 30 deletions

View File

@@ -173,6 +173,7 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen
- All wines in your inventory are always in stock. - All wines in your inventory are always in stock.
- If the user interrupts, prioritize the user - If the user interrupts, prioritize the user
- Do not ask the user about wine's flavor e.g. floral, citrusy, nutty or some thing similar as these terms cannot be used to search the database. - Do not ask the user about wine's flavor e.g. floral, citrusy, nutty or some thing similar as these terms cannot be used to search the database.
- The best strategy for searching an inventory is to start broadly and then narrow down.
- Once the user has selected their wine, ask the user if they need any further assistance. Do not offer any additional services. If the user doesn't need any further assistance, say goodbye and invite them to come back next time. - Once the user has selected their wine, ask the user if they need any further assistance. Do not offer any additional services. If the user doesn't need any further assistance, say goodbye and invite them to come back next time.
Tips: Tips:
@@ -255,6 +256,7 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen
try try
response = a.func[:text2textInstructLLM](prompt) response = a.func[:text2textInstructLLM](prompt)
response = GeneralUtils.remove_french_accents(response)
responsedict = GeneralUtils.textToDict(response, responsedict = GeneralUtils.textToDict(response,
["Understanding", "Reasoning", "Plan", "Action_name", "Action_input"], ["Understanding", "Reasoning", "Plan", "Action_name", "Action_input"],
rightmarker=":", symbolkey=true, lowercasekey=true) rightmarker=":", symbolkey=true, lowercasekey=true)
@@ -697,7 +699,7 @@ function conversation(a::sommelier, userinput::Dict)
# thinking loop until AI wants to communicate with the user # thinking loop until AI wants to communicate with the user
chatresponse = nothing chatresponse = nothing
for i in 1:3 for i in 1:5
actionname, result = think(a) actionname, result = think(a)
if actionname ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"] if actionname ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"]
chatresponse = result chatresponse = result
@@ -773,7 +775,7 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
# map action and input() to llm function # map action and input() to llm function
response = response =
if actionname == "CHATBOX" if actionname == "CHATBOX"
input = thoughtDict[:plan] input = thoughtDict[:action_input]
(result=input, errormsg=nothing, success=true) (result=input, errormsg=nothing, success=true)
elseif actionname == "CHECKINVENTORY" elseif actionname == "CHECKINVENTORY"
checkinventory(a, actioninput) checkinventory(a, actioninput)
@@ -1338,7 +1340,7 @@ function detectWineryName(a, text)
Text: a text describing the situation. Text: a text describing the situation.
Tips: Tips:
- Winery usually contains Château, Chateau, Domaine, Côte, Cote, St. de, or a combination of these words. - Winery usually contains Château, Chateau, Domaine, Côte, Cotes, St. de, or a combination of these words.
You should then respond to the user with: You should then respond to the user with:
Winery_names: A list of winery names mentioned in the text or "None" if no winery name is mentioned. Winery_names: A list of winery names mentioned in the text or "None" if no winery name is mentioned.
@@ -1347,7 +1349,7 @@ function detectWineryName(a, text)
Winery_names: ... Winery_names: ...
Here are some examples: Here are some examples:
Winery_names: Domaine Courbis, Chateau Lafite Rothschild, Matarromera Domaine Roulot, Château Winery_names: Domaine Courbis, Chateau Lafite Rothschild, Matarromera Domaine Roulot, Château, Cotes
Let's begin! Let's begin!
""" """

View File

@@ -421,6 +421,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
try try
response = a.func[:text2textInstructLLM](prompt) response = a.func[:text2textInstructLLM](prompt)
response = GeneralUtils.remove_french_accents(response)
# check wheter all attributes are in the response # check wheter all attributes are in the response
for word in attributes for word in attributes
@@ -431,15 +432,13 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
responsedict = GeneralUtils.textToDict(response, attributes, rightmarker=":", symbolkey=true) responsedict = GeneralUtils.textToDict(response, attributes, rightmarker=":", symbolkey=true)
#[WORKING] check if winery, wine_name, region, country, wine_type, grape_variety are in the query because sometime AI halucinates
for i attributes for i attributes
if length(JSON3.write(responsedict[Symbol(i)])) == 0 if length(JSON3.write(responsedict[Symbol(i)])) == 0
error("$i is empty ", @__LINE__) error("$i is empty ", @__LINE__)
end end
end end
#[PENDING] check if the following attributes has more than 1 name #check if the following attributes has more than 1 name
responsedict[:grape_variety] = split(responsedict[:grape_variety], ',')[1] responsedict[:grape_variety] = split(responsedict[:grape_variety], ',')[1]
responsedict[:grape_variety] = split(responsedict[:grape_variety], '/')[1] responsedict[:grape_variety] = split(responsedict[:grape_variety], '/')[1]
@@ -449,33 +448,24 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
responsedict[:region] = split(responsedict[:region], ',')[1] responsedict[:region] = split(responsedict[:region], ',')[1]
responsedict[:region] = split(responsedict[:region], '/')[1] responsedict[:region] = split(responsedict[:region], '/')[1]
# check if grape_variety is mentioned in the input
if !occursin("NA", responsedict[:grape_variety]) && !occursin(responsedict[:grape_variety], input)
if attempt < maxattempt
errornote = "$(responsedict[:grape_variety]) is not mentioned in the user query, you must only use the info from the query."
error("$(responsedict[:grape_variety]) is not mentioned in the user query, you must only use the info from the query.")
else
responsedict[:grape_variety] = "NA"
end
end
# check if region is mentioned in the input
if !occursin("NA", responsedict[:region]) && !occursin(responsedict[:region], input)
if attempt < maxattempt
errornote = "$(responsedict[:region]) is not mentioned in the user query, you must only use the info from the query.."
error("$(responsedict[:region]) is not mentioned in the user query, you must only use the info from the query..")
else
responsedict[:region] = "NA"
end
end
# delete!(responsedict, :region)
delete!(responsedict, :reasoning) delete!(responsedict, :reasoning)
# delete!(responsedict, :tasting_notes) delete!(responsedict, :tasting_notes)
# delete!(responsedict, :price)
delete!(responsedict, :occasion) delete!(responsedict, :occasion)
delete!(responsedict, :food_to_be_paired_with_wine) delete!(responsedict, :food_to_be_paired_with_wine)
# check if winery, wine_name, region, country, wine_type, grape_variety are in the query because sometime AI halucinates
for i in [:grape_variety, :winery, :wine_name, :region]
result = check_key_in_input(input, responsedict, attempt, maxattempt, i)
if result === nothing
# nothing wrong
elseif result == "NA"
responsedict[i] = "NA"
else
errornote = result
error(errornote)
end
end
# remove (some text) # remove (some text)
for (k, v) in responsedict for (k, v) in responsedict
_v = replace(v, r"\(.*?\)" => "") _v = replace(v, r"\(.*?\)" => "")
@@ -900,6 +890,20 @@ function jsoncorrection(config::T1, input::T2, correctJsonExample::T3;
end end
function check_key_in_input(input::String, responsedict, attempt::Int, maxattempt::Int, key::Symbol)
if !occursin("NA", responsedict[key]) && !occursin(responsedict[key], input)
if attempt < maxattempt
errornote = "$(responsedict[key]) is not mentioned in the user query, you must only use the info from the query."
return errornote
else
return "NA"
end
else
return nothing
end
end
# function isrecommend(state::T1, text2textInstructLLM::Function # function isrecommend(state::T1, text2textInstructLLM::Function
# ) where {T1<:AbstractDict} # ) where {T1<:AbstractDict}