update
This commit is contained in:
@@ -342,26 +342,24 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
||||
User's query: ...
|
||||
|
||||
You must follow the following guidelines:
|
||||
- If specific information required in the preference form is not available in the query or there isn't any, mark with "NA" to indicate this.
|
||||
- If specific information required in the preference form is not available in the query or there isn't any, mark with "N/A" to indicate this.
|
||||
Additionally, words like 'any' or 'unlimited' mean no information is available.
|
||||
- Do not generate other comments.
|
||||
|
||||
You should then respond to the user with:
|
||||
Thought: state your understanding of the current situation
|
||||
Wine_name: name of the wine
|
||||
Winery: name of the winery
|
||||
Vintage: the year of the wine
|
||||
Region: a region (NOT a country) where the wine is produced, such as Burgundy, Napa Valley, etc
|
||||
Country: a country where the wine is produced. Can be "Austria", "Australia", "France", "Germany", "Italy", "Portugal", "Spain", "United States"
|
||||
Country: a country where wine is produced. Can be "Austria", "Australia", "France", "Germany", "Italy", "Portugal", "Spain", "United States"
|
||||
Wine_type: can be one of: "red", "white", "sparkling", "rose", "dessert" or "fortified"
|
||||
Grape_varietal: the name of the primary grape used to make the wine
|
||||
Tasting_notes: a brief description of the wine's taste, such as "butter", "oak", "fruity", etc
|
||||
Wine_price: price range of wine.
|
||||
Tasting_notes: a word describe the wine's flavor, such as "butter", "oak", "fruity", "raspberry", "earthy", "floral", etc
|
||||
Wine_price_range: price range of wine. Example: For price 10-20, price range will be "10 to 20". For price 100, price range will be 0 to 100.
|
||||
Occasion: the occasion the user is having the wine for
|
||||
Food_to_be_paired_with_wine: food that the user will be served with the wine such as poultry, fish, steak, etc
|
||||
|
||||
You should only respond in format as described below:
|
||||
Thought: ...
|
||||
Wine_name: ...
|
||||
Winery: ...
|
||||
Vintage: ...
|
||||
@@ -370,41 +368,41 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
||||
Wine_type:
|
||||
Grape_varietal: ...
|
||||
Tasting_notes: ...
|
||||
Wine_price: ...
|
||||
Wine_price_range: ...
|
||||
Occasion: ...
|
||||
Food_to_be_paired_with_wine: ...
|
||||
|
||||
Here are some example:
|
||||
User's query: red, Chenin Blanc, Riesling, 20 USD
|
||||
{"reasoning": ..., "winery": "NA", "wine_name": "NA", "vintage": "NA", "region": "NA", "country": "NA", "wine_type": "red, white", "grape_varietal": "Chenin Blanc, Riesling", "tasting_notes": "NA", "wine_price": "0-20", "occasion": "NA", "food_to_be_paired_with_wine": "NA"}
|
||||
|
||||
|
||||
User's query: red, Chenin Blanc, Riesling, 20 USD from Tuscany, Italy or Napa Valley, USA
|
||||
Wine_name: N/A. Winery: N/A. Vintage: N/A. Region: Tuscany, Napa Valley. Country: Italy, United States. Wine_type: red, white. Grape_varietal: Chenin Blanc, Riesling. Tasting_notes: citrus. Wine_price_range: 0 to 20. Occasion: N/A. Food_to_be_paired_with_wine: N/A
|
||||
|
||||
User's query: Domaine du Collier Saumur Blanc 2019, France, white, Merlot
|
||||
{"reasoning": ..., "winery": "Domaine du Collier", "wine_name": "Saumur Blanc", "vintage": "2019", "region": "Saumur", "country": "France", "wine_type": "white", "grape_varietal": "Merlot", "tasting_notes": "NA", "wine_price": "NA", "occasion": "NA", "food_to_be_paired_with_wine": "NA"}
|
||||
|
||||
Winery: Domaine du Collier. Wine_name: Saumur Blanc. Vintage: 2019. Region: Saumur. Country: France. Wine_type: white. Grape_varietal: Merlot. Tasting_notes: plum. Wine_price_range: N/A. Occasion: N/A. Food_to_be_paired_with_wine: N/A.
|
||||
|
||||
Let's begin!
|
||||
"""
|
||||
|
||||
header = ["Thought:", "Wine_name:", "Winery:", "Vintage:", "Region:", "Country:", "Wine_type:", "Grape_varietal:", "Tasting_notes:", "Wine_price:", "Occasion:", "Food_to_be_paired_with_wine:"]
|
||||
dictkey = ["thought", "wine_name", "winery", "vintage", "region", "country", "wine_type", "grape_varietal", "tasting_notes", "wine_price", "occasion", "food_to_be_paired_with_wine"]
|
||||
header = ["Wine_name:", "Winery:", "Vintage:", "Region:", "Country:", "Wine_type:", "Grape_varietal:", "Tasting_notes:", "Wine_price_range:", "Occasion:", "Food_to_be_paired_with_wine:"]
|
||||
dictkey = ["wine_name", "winery", "vintage", "region", "country", "wine_type", "grape_varietal", "tasting_notes", "wine_price_range", "occasion", "food_to_be_paired_with_wine"]
|
||||
errornote = "N/A"
|
||||
|
||||
llmkwargs=Dict(
|
||||
:num_ctx => 32768,
|
||||
:temperature => 0.5,
|
||||
:temperature => 0.2,
|
||||
)
|
||||
|
||||
for attempt in 1:maxattempt
|
||||
#[PENDING] I should add generatequestion()
|
||||
|
||||
if attempt > 1
|
||||
println("\nYiemAgent extractWineAttributes_1() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
end
|
||||
|
||||
usermsg =
|
||||
"""
|
||||
User's query: $input
|
||||
P.S. $errornote
|
||||
"""
|
||||
"""
|
||||
$input
|
||||
"""
|
||||
assistantinfo =
|
||||
"""
|
||||
<information>
|
||||
P.S. $errornote
|
||||
</information>
|
||||
"""
|
||||
|
||||
_prompt =
|
||||
[
|
||||
@@ -413,23 +411,30 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
||||
]
|
||||
|
||||
# put in model format
|
||||
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||
prompt = GeneralUtils.formatLLMtext(_prompt, a.llmFormatName)
|
||||
# add info
|
||||
prompt = prompt * assistantinfo
|
||||
|
||||
response = a.func[:text2textInstructLLM](prompt;
|
||||
modelsize="medium", llmkwargs=llmkwargs, senderId=a.id)
|
||||
response = GeneralUtils.remove_french_accents(response)
|
||||
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
||||
think, response = GeneralUtils.extractthink(response)
|
||||
|
||||
# check wheter all attributes are in the response
|
||||
checkFlag = false
|
||||
for word in header
|
||||
if !occursin(word, response)
|
||||
errornote = "In your previous attempts, the $word attribute is missing. Please try again."
|
||||
println("\nYiemAgent extractWineAttributes_1() Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
checkFlag = true
|
||||
break
|
||||
end
|
||||
# check whether response has all header
|
||||
detected_kw = GeneralUtils.detect_keyword(header, response)
|
||||
kwvalue = [i for i in values(detected_kw)]
|
||||
zeroind = findall(x -> x == 0, kwvalue)
|
||||
missingkeys = [header[i] for i in zeroind]
|
||||
if 0 ∈ values(detected_kw)
|
||||
errornote = "$missingkeys are missing from your previous response"
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
elseif sum(values(detected_kw)) > length(header)
|
||||
errornote = "Your previous attempt has duplicated points"
|
||||
println("\nERROR YiemAgent decisionMaker() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
checkFlag == true ? continue : nothing
|
||||
|
||||
# check whether response has all answer's key points
|
||||
detected_kw = GeneralUtils.detect_keyword(header, response)
|
||||
@@ -440,6 +445,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
||||
elseif sum(values(detected_kw)) > length(header)
|
||||
errornote = "In your previous attempts, the response has duplicated answer's key points"
|
||||
println("\nYiemAgent extractWineAttributes_1() Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
println(response)
|
||||
continue
|
||||
end
|
||||
responsedict = GeneralUtils.textToDict(response, header;
|
||||
@@ -460,29 +466,29 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
||||
if j ∉ [:thought, :tasting_notes, :occasion, :food_to_be_paired_with_wine]
|
||||
# in case j is wine_price it needs to be checked differently because its value is ranged
|
||||
if j == :wine_price
|
||||
if responsedict[:wine_price] != "NA"
|
||||
if responsedict[:wine_price] != "N/A"
|
||||
# check whether wine_price is in ranged number
|
||||
if !occursin('-', responsedict[:wine_price])
|
||||
errornote = "In your previous attempt, the 'wine_price' was not set to a ranged number. Please adjust it accordingly."
|
||||
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."
|
||||
println("\nERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
checkFlag = true
|
||||
break
|
||||
end
|
||||
|
||||
# check whether max wine_price is in the input
|
||||
pricerange = split(responsedict[:wine_price], '-')
|
||||
minprice = pricerange[1]
|
||||
maxprice = pricerange[end]
|
||||
if !occursin(maxprice, input)
|
||||
responsedict[:wine_price] = "NA"
|
||||
end
|
||||
# price range like 100-100 is not good
|
||||
if minprice == maxprice
|
||||
errornote = "In your previous attempt, you inputted 'wine_price' with a 'minimum' value equaling the 'maximum', which is not valid."
|
||||
println("\nERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
checkFlag = true
|
||||
break
|
||||
end
|
||||
# # check whether max wine_price is in the input
|
||||
# pricerange = split(responsedict[:wine_price], '-')
|
||||
# minprice = pricerange[1]
|
||||
# maxprice = pricerange[end]
|
||||
# if !occursin(maxprice, input)
|
||||
# responsedict[:wine_price] = "N/A"
|
||||
# end
|
||||
# # price range like 100-100 is not good
|
||||
# if minprice == maxprice
|
||||
# errornote = "In your previous attempt, you inputted 'wine_price' with a 'minimum' value equaling the 'maximum', which is not valid."
|
||||
# println("\nERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
# checkFlag = true
|
||||
# break
|
||||
# end
|
||||
end
|
||||
else
|
||||
content = responsedict[j]
|
||||
@@ -517,7 +523,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
||||
result = ""
|
||||
for (k, v) in responsedict
|
||||
# some time LLM generate text with "(some comment)". this line removes it
|
||||
if !occursin("NA", v) && v != "" && !occursin("none", v) && !occursin("None", v)
|
||||
if !occursin("N/A", v) && v != "" && !occursin("none", v) && !occursin("None", v)
|
||||
result *= "$k: $v, "
|
||||
end
|
||||
end
|
||||
@@ -580,7 +586,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
||||
sweetness, acidity, tannin, intensity
|
||||
|
||||
You must follow the following guidelines:
|
||||
1) If specific information required in the preference form is not available in the query or there isn't any, mark with 'NA' to indicate this.
|
||||
1) If specific information required in the preference form is not available in the query or there isn't any, mark with 'N/A' to indicate this.
|
||||
Additionally, words like 'any' or 'unlimited' mean no information is available.
|
||||
2) Use the conversion table to convert the descriptive word level of sweetness, intensity, tannin, and acidity into a corresponding integer.
|
||||
3) Do not generate other comments.
|
||||
@@ -605,8 +611,8 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
||||
|
||||
Here are some examples:
|
||||
User's query: I want a wine with a medium-bodied, low acidity, medium tannin.
|
||||
Sweetness_keyword: NA
|
||||
Sweetness: NA
|
||||
Sweetness_keyword: N/A
|
||||
Sweetness: N/A
|
||||
Acidity_keyword: low acidity
|
||||
Acidity: 1-2
|
||||
Tannin_keyword: medium tannin
|
||||
@@ -615,20 +621,20 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
||||
Intensity: 3-4
|
||||
|
||||
User's query: German red wine, under 100, pairs with spicy food
|
||||
Sweetness_keyword: NA
|
||||
Sweetness: NA
|
||||
Acidity_keyword: NA
|
||||
Acidity: NA
|
||||
Tannin_keyword: NA
|
||||
Tannin: NA
|
||||
Intensity_keyword: NA
|
||||
Intensity: NA
|
||||
Sweetness_keyword: N/A
|
||||
Sweetness: N/A
|
||||
Acidity_keyword: N/A
|
||||
Acidity: N/A
|
||||
Tannin_keyword: N/A
|
||||
Tannin: N/A
|
||||
Intensity_keyword: N/A
|
||||
Intensity: N/A
|
||||
|
||||
Let's begin!
|
||||
"""
|
||||
header = ["Sweetness_keyword:", "Sweetness:", "Acidity_keyword:", "Acidity:", "Tannin_keyword:", "Tannin:", "Intensity_keyword:", "Intensity:"]
|
||||
dictkey = ["sweetness_keyword", "sweetness", "acidity_keyword", "acidity", "tannin_keyword", "tannin", "intensity_keyword", "intensity"]
|
||||
errornote = ""
|
||||
errornote = "N/A"
|
||||
|
||||
for attempt in 1:10
|
||||
usermsg =
|
||||
@@ -645,10 +651,11 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
||||
]
|
||||
|
||||
# put in model format
|
||||
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||
prompt = GeneralUtils.formatLLMtext(_prompt, a.llmFormatName)
|
||||
|
||||
response = a.func[:text2textInstructLLM](prompt)
|
||||
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
||||
think, response = GeneralUtils.extractthink(response)
|
||||
|
||||
# check whether response has all answer's key points
|
||||
detected_kw = GeneralUtils.detect_keyword(header, response)
|
||||
@@ -669,23 +676,23 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
||||
for i in ["sweetness", "acidity", "tannin", "intensity"]
|
||||
keyword = Symbol(i * "_keyword") # e.g. sweetness_keyword
|
||||
value = responsedict[keyword]
|
||||
if value != "NA" && !occursin(value, input)
|
||||
if value != "N/A" && !occursin(value, input)
|
||||
errornote = "In your previous attempt, keyword $keyword: $value does not appear in the input. You must use information from the input only"
|
||||
println("\nERROR YiemAgent extractWineAttributes_2() Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
end
|
||||
|
||||
# if value == "NA" then responsedict[i] = "NA"
|
||||
# e.g. if sweetness_keyword == "NA" then sweetness = "NA"
|
||||
if value == "NA"
|
||||
responsedict[Symbol(i)] = "NA"
|
||||
# if value == "N/A" then responsedict[i] = "N/A"
|
||||
# e.g. if sweetness_keyword == "N/A" then sweetness = "N/A"
|
||||
if value == "N/A"
|
||||
responsedict[Symbol(i)] = "N/A"
|
||||
end
|
||||
end
|
||||
|
||||
# some time LLM not put integer range
|
||||
for (k, v) in responsedict
|
||||
if !occursin("keyword", string(k))
|
||||
if v !== "NA" && (!occursin('-', v) || length(v) > 5)
|
||||
if v !== "N/A" && (!occursin('-', v) || length(v) > 5)
|
||||
errornote = "WARNING: The non-range value {$k: $v} is not allowed. It should be specified in a range format, i.e. min-max."
|
||||
println("\nERROR YiemAgent extractWineAttributes_2() Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||
continue
|
||||
@@ -693,10 +700,10 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
||||
end
|
||||
end
|
||||
|
||||
# some time LLM says NA-2. Need to convert NA to 1
|
||||
# some time LLM says N/A-2. Need to convert N/A to 1
|
||||
for (k, v) in responsedict
|
||||
if occursin("NA", v) && occursin("-", v)
|
||||
new_v = replace(v, "NA"=>"1")
|
||||
if occursin("N/A", v) && occursin("-", v)
|
||||
new_v = replace(v, "N/A"=>"1")
|
||||
responsedict[k] = new_v
|
||||
end
|
||||
end
|
||||
@@ -704,7 +711,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
||||
result = ""
|
||||
for (k, v) in responsedict
|
||||
# some time LLM generate text with "(some comment)". this line removes it
|
||||
if !occursin("NA", v)
|
||||
if !occursin("N/A", v)
|
||||
result *= "$k: $v, "
|
||||
end
|
||||
end
|
||||
@@ -756,7 +763,7 @@ function paraphrase(text2textInstructLLM::Function, text::String)
|
||||
header = ["Paraphrase:"]
|
||||
dictkey = ["paraphrase"]
|
||||
|
||||
errornote = ""
|
||||
errornote = "N/A"
|
||||
response = nothing # placeholder for show when error msg show up
|
||||
|
||||
|
||||
@@ -773,11 +780,12 @@ function paraphrase(text2textInstructLLM::Function, text::String)
|
||||
]
|
||||
|
||||
# put in model format
|
||||
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||
prompt = GeneralUtils.formatLLMtext(_prompt, a.llmFormatName)
|
||||
|
||||
try
|
||||
response = text2textInstructLLM(prompt)
|
||||
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
||||
think, response = GeneralUtils.extractthink(response)
|
||||
# sometime the model response like this "here's how I would respond: ..."
|
||||
if occursin("respond:", response)
|
||||
errornote = "You don't need to intro your response"
|
||||
|
||||
Reference in New Issue
Block a user