This commit is contained in:
narawat lamaiin
2025-05-18 17:21:51 +07:00
parent 3a88e0e7d4
commit 919d8ec85e
2 changed files with 56 additions and 28 deletions

View File

@@ -249,8 +249,9 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
<context> <context>
<Available tools> <Available tools>
- CHATBOX which you can use to talk with the user. Be specific. - CHATBOX which you can use to talk with the user. Be specific.
- CHECKINVENTORY allows you to check information about wines you want in your inventory's database. The input must be supported search criteria includeing: wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity. - CHECKWINE allows you to check information about wines you want in your inventory's database. The input must be supported search criteria includeing: wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
Example query: "Dry, full-bodied red wine from Burgundy, France or Tuscany, Italy. Merlot varietal. price 100 to 1000 USD." Example query 1: "Dry, full-bodied red wine from Burgundy region, France or Tuscany region, Italy. Merlot varietal. price 100 to 1000 USD."
Example query 2: "Red wine, bold intensity, price under 300 USD"
- PRESENTBOX which you can use to present wines you have found in your inventory to the user. The input are wine names that you want to present. - PRESENTBOX which you can use to present wines you have found in your inventory to the user. The input are wine names that you want to present.
- ENDCONVERSATION which you can use to properly end the conversation with the user. Input is a dialogue where you wrap up the conversation, thank the user, and invite them to return next time. - ENDCONVERSATION which you can use to properly end the conversation with the user. Input is a dialogue where you wrap up the conversation, thank the user, and invite them to return next time.
</Available tools> </Available tools>
@@ -332,9 +333,9 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
# responsedict = GeneralUtils.textToDict(response, header; # responsedict = GeneralUtils.textToDict(response, header;
# dictKey=dictkey, symbolkey=true) # dictKey=dictkey, symbolkey=true)
if responsedict[:action_name] ["CHATBOX", "CHECKINVENTORY", "PRESENTBOX", "ENDCONVERSATION"] if responsedict[:action_name] ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"]
errornote = "Your previous attempt didn't use the given functions" errornote = "Your previous attempt didn't use the given functions"
println("\nERROR YiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") println("\nERROR YiemAgent decisionMaker() $errornote --> $(responsedict[:action_name])", @__FILE__, ":", @__LINE__, " $(Dates.now())")
continue continue
end end
@@ -420,7 +421,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
if evaluationdict[:approved] == "no" if evaluationdict[:approved] == "no"
mentor_comment = evaluationdict[:suggestion] mentor_comment = evaluationdict[:suggestion]
errornote = "Your previous attempt was not good enough. Please try again. Here is the mentor's suggestion: $mentor_comment" errornote = "Your previous attempt was not good enough. Please try again. Here is the mentor's suggestion: $mentor_comment"
println("\nERROR YiemAgent decisionMaker() - $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") println("\nERROR YiemAgent decisionMaker() $errornote --> \n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
continue continue
end end
@@ -814,7 +815,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext
- Under your supervision, a trainee sommelier is engaging with a store customer. Each time the customer speaks, the trainee will assess the situation, determine the next course of action, and pause to await your guidance before proceeding. - Under your supervision, a trainee sommelier is engaging with a store customer. Each time the customer speaks, the trainee will assess the situation, determine the next course of action, and pause to await your guidance before proceeding.
</Situation> </Situation>
<Your mission> <Your mission>
- To improve a trainee sommelier decision based on the store policy and guidelines. - Improve a trainee sommelier decision based on the store policy and guidelines while ensuring seamless interactions between the trainee and customers.
</Your mission> </Your mission>
<At each round of conversation, you will be given the following information> <At each round of conversation, you will be given the following information>
- trajectory: A conversation between your trainee and the customer that have occurred up until now - trajectory: A conversation between your trainee and the customer that have occurred up until now
@@ -1084,7 +1085,7 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict;
actioninput=userinput[:text], actioninput=userinput[:text],
) )
) )
chatresponse = generatechat(a; converPartnerName=converPartnerName) chatresponse = generatechat(a; converPartnerName=converPartnerName, recentEventNum=20)
addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg) addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg)
@@ -1127,8 +1128,8 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
response = response =
if actionname == "CHATBOX" || actionname == "ENDCONVERSATION" if actionname == "CHATBOX" || actionname == "ENDCONVERSATION"
(result=thoughtDict[:plan], errormsg=nothing, success=true) (result=thoughtDict[:plan], errormsg=nothing, success=true)
elseif actionname == "CHECKINVENTORY" elseif actionname == "CHECKWINE"
checkinventory(a, actioninput) checkwine(a, actioninput)
elseif actionname == "PRESENTBOX" elseif actionname == "PRESENTBOX"
(result=actioninput, errormsg=nothing, success=true) (result=actioninput, errormsg=nothing, success=true)
# elseif actionname == "ENDCONVERSATION" # elseif actionname == "ENDCONVERSATION"
@@ -1200,7 +1201,7 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
) )
result = chatresponse result = chatresponse
elseif actionname == "CHECKINVENTORY" 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
@@ -1417,6 +1418,17 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
if isWineInEvent == false if isWineInEvent == false
errornote = "Your previous response recommended wines that is not in your inventory which is not allowed" errornote = "Your previous response recommended wines that is not in your inventory which is not allowed"
println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
s = """
Perfect choice! The Colgin Tychson Hill Vineyard Cabernet Sauvignon (2014) is an excellent match for your criteria. Here's why:
Boldness & Flavor: This wine delivers intense blackberry, black cherry, and dark fruit notes, layered with vanilla, oak, and earthy undertones. Its high intensity (rated 5/5) ensures a rich, full-bodied experience that's both powerful and balanced.
Family-Owned Legacy: Produced by Colgin Cellars, a renowned Napa Valley family winery, this vintage reflects their commitment to quality and tradition. While not a limited-edition release, it's a highly regarded, consistently excellent Cabernet Sauvignon.
Gift-Ready & Affordable: Priced at USD144 (well under your USD250 budget), it comes in a sleek, gift-ready box—perfect for impressing friends or loved ones.
Why I Recommend It: It perfectly balances your desire for bold fruit, oak, and a presentable format without sacrificing quality. If you're curious about alternatives, the 2017 Hunter Glenn Cabernet (also USD159) shares similar intensity but lacks specific tasting notes. However, the 2014 Tychson Hill is a more complete match for your criteria. Enjoy your selection!"""
continue continue
end end
end end
@@ -1923,8 +1935,7 @@ 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)
recentevents = a.memory[:events][recent_ind] recentEventsDict = createEventsLog(a.memory[:events]; index=recent_ind)
recentEventsDict = createEventsLog(recentevents; 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"]

View File

@@ -1,6 +1,6 @@
module llmfunction module llmfunction
export virtualWineUserChatbox, jsoncorrection, checkinventory, # recommendbox, export virtualWineUserChatbox, jsoncorrection, checkwine, # recommendbox,
virtualWineUserRecommendbox, userChatbox, userRecommendbox, extractWineAttributes_1, virtualWineUserRecommendbox, userChatbox, userRecommendbox, extractWineAttributes_1,
extractWineAttributes_2, paraphrase extractWineAttributes_2, paraphrase
@@ -288,17 +288,25 @@ julia> result = checkinventory(agent, input)
# Signature # Signature
""" """
function checkinventory(a::T1, input::T2 function checkwine(a::T1, input::T2; maxattempt::Int=3
) where {T1<:agent, T2<:AbstractString} ) where {T1<:agent, T2<:AbstractString}
println("\ncheckinventory order: $input ", @__FILE__, ":", @__LINE__, " $(Dates.now())") println("\ncheckinventory order: $input ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
wineattributes_1 = extractWineAttributes_1(a, input) wineattributes_1 = extractWineAttributes_1(a, input)
wineattributes_2 = extractWineAttributes_2(a, input) wineattributes_2 = extractWineAttributes_2(a, input)
# placeholder
textresult = nothing
rawresponse = nothing
for i in 1:maxattempt
#CHANGE if you want to add retailer name #CHANGE if you want to add retailer name
# _inventoryquery = "retailer name: $(a.retailername), $wineattributes_1, $wineattributes_2" # _inventoryquery = "retailer name: $(a.retailername), $wineattributes_1, $wineattributes_2"
_inventoryquery = "$wineattributes_1, $wineattributes_2" _inventoryquery = "$wineattributes_1, $wineattributes_2"
inventoryquery = "Retrieves winery, wine_name, wine_id, vintage, region, country, wine_type, grape, serving_temperature, sweetness, intensity, tannin, acidity, tasting_notes, price and currency of wines that match the following criteria - {$_inventoryquery}"
retrieve_attributes = ["winery", "wine_name", "wine_id", "vintage", "region", "country", "wine_type", "grape", "serving_temperature", "sweetness", "intensity", "tannin", "acidity", "tasting_notes", "price", "currency"]
inventoryquery = "Retrieves $retrieve_attributes of wines that match the following criteria - {$_inventoryquery}"
println("\ncheckinventory input: $inventoryquery ", @__FILE__, ":", @__LINE__, " $(Dates.now())") println("\ncheckinventory input: $inventoryquery ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
# add suppport for similarSQLVectorDB # add suppport for similarSQLVectorDB
textresult, rawresponse = SQLLLM.query(inventoryquery, a.func[:executeSQL], textresult, rawresponse = SQLLLM.query(inventoryquery, a.func[:executeSQL],
@@ -306,10 +314,19 @@ function checkinventory(a::T1, input::T2
insertSQLVectorDB=a.func[:insertSQLVectorDB], insertSQLVectorDB=a.func[:insertSQLVectorDB],
similarSQLVectorDB=a.func[:similarSQLVectorDB], similarSQLVectorDB=a.func[:similarSQLVectorDB],
llmFormatName="qwen3") llmFormatName="qwen3")
#[PENDING] sometime wine data comeout {wine name, price, wine_id} and nothing else. I need to make sure that wine data include all of its attributes # check if all of retrieve_attributes appears in textresult
isin = [occursin(x, textresult) for x in retrieve_attributes]
if !all(isin) && !occursin("The resulting table has 0 row", textresult)
errornote = "Not all of $retrieve_attributes appear in search result"
println("\nERROR YiemAgent checkwine() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
continue
else
break
end
end
println("\ncheckinventory result ", @__FILE__, ":", @__LINE__, " $(Dates.now())") println("\ncheckinventory result ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
println(textresult) println(textresult)
#[PENDING] if there is no wine id, it is not a valid result
return (result=textresult, rawresponse=rawresponse, success=true, errormsg=nothing) return (result=textresult, rawresponse=rawresponse, success=true, errormsg=nothing)
end end
@@ -352,7 +369,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
wine_name: name of the wine wine_name: name of the wine
winery: name of the winery winery: name of the winery
vintage: the year of the wine vintage: the year of the wine
region: a region (NOT a country) where the wine is produced, such as Burgundy, Napa Valley, etc region: a region, such as Burgundy, Bordeaux, Champagne, Napa Valley, Tuscany, California, Oregon, etc
country: a country where 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" 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 grape_varietal: the name of the primary grape used to make the wine