diff --git a/src/interface.jl b/src/interface.jl index 8d82451..dbcf246 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -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. - 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. + - 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. Tips: @@ -255,6 +256,7 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen try response = a.func[:text2textInstructLLM](prompt) + response = GeneralUtils.remove_french_accents(response) responsedict = GeneralUtils.textToDict(response, ["Understanding", "Reasoning", "Plan", "Action_name", "Action_input"], 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 chatresponse = nothing - for i in 1:3 + for i in 1:5 actionname, result = think(a) if actionname ∈ ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"] chatresponse = result @@ -773,7 +775,7 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh # map action and input() to llm function response = if actionname == "CHATBOX" - input = thoughtDict[:plan] + input = thoughtDict[:action_input] (result=input, errormsg=nothing, success=true) elseif actionname == "CHECKINVENTORY" checkinventory(a, actioninput) @@ -1338,7 +1340,7 @@ function detectWineryName(a, text) Text: a text describing the situation. 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: 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: ... 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! """ diff --git a/src/llmfunction.jl b/src/llmfunction.jl index 16e8d04..be43805 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -421,6 +421,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2< try response = a.func[:text2textInstructLLM](prompt) + response = GeneralUtils.remove_french_accents(response) # check wheter all attributes are in the response 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) - #[WORKING] check if winery, wine_name, region, country, wine_type, grape_variety are in the query because sometime AI halucinates - for i ∈ attributes if length(JSON3.write(responsedict[Symbol(i)])) == 0 error("$i is empty ", @__LINE__) 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] @@ -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] - # 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, :tasting_notes) - # delete!(responsedict, :price) + delete!(responsedict, :tasting_notes) delete!(responsedict, :occasion) 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) for (k, v) in responsedict _v = replace(v, r"\(.*?\)" => "") @@ -900,6 +890,20 @@ function jsoncorrection(config::T1, input::T2, correctJsonExample::T3; 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 # ) where {T1<:AbstractDict}