This commit is contained in:
narawat lamaiin
2025-01-11 16:57:57 +07:00
parent 944d9eaf2b
commit a29e8049a7
3 changed files with 41 additions and 34 deletions

View File

@@ -218,7 +218,7 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen
winenames = df[:, :wine_name]
for winename in winenames
if !occursin(winename, chathistory)
println("\n~~~ Yiem decisionMaker() found wines from DB ", @__FILE__, " ", @__LINE__)
println("\n~~~ Yiem decisionMaker() found wines from DB ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
d = Dict(
:understanding=> "I understand that the customer is looking for a wine that matches their intention and budget.",
:reasoning=> "I checked the inventory and found wines that match the customer's criteria. I will present the wines to the customer.",
@@ -271,7 +271,7 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen
end
if count > 1
errornote = "You must use only one function"
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
continue
end
@@ -281,16 +281,16 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen
if responsedict[:action_name] ["CHATBOX", "CHECKINVENTORY", "ENDCONVERSATION"]
errornote = "You must use the given functions"
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
continue
end
checkFlag = false
for i [:understanding, :plan, :action_name]
if length(responsedict[i]) == 0
error("$i is empty ", @__FILE__, " ", @__LINE__)
error("$i is empty ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
errornote = "$i is empty"
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
checkFlag = true
break
end
@@ -303,14 +303,14 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen
matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i)
if length(matchkeys) > 1
errornote = "DecisionMaker has more than one key per categories"
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
checkFlag = true
break
end
end
checkFlag == true ? continue : nothing
println("\n~~~ Yiem decisionMaker() ", @__FILE__, " ", @__LINE__)
println("\n~~~ Yiem decisionMaker() ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
pprintln(Dict(responsedict))
# check whether an agent recommend wines before checking inventory or recommend wines
@@ -337,7 +337,7 @@ function decisionMaker(a::T; recent::Integer=5)::Dict{Symbol,Any} where {T<:agen
isWineInEvent == false
errornote = "Note: Before recommending a wine, ensure it's in your inventory. Check your stock first."
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
continue
end
end
@@ -503,7 +503,7 @@ function evaluator(config::T1, state::T2
showerror(io, e)
errorMsg = String(take!(io))
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", @__FILE__, " ", @__LINE__)
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
end
error("evaluator failed to generate an evaluation")
@@ -633,7 +633,7 @@ function reflector(config::T1, state::T2)::String where {T1<:AbstractDict,T2<:Ab
showerror(io, e)
errorMsg = String(take!(io))
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", @__FILE__, " ", @__LINE__)
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
end
error("reflector failed to generate a thought")
@@ -733,7 +733,7 @@ function conversation(a::sommelier, userinput::Dict)
end
end
function conversation(a::companion, userinput::Dict)
function conversation(a::companion, userinput::Dict; maximumMsg=30)
chatresponse = nothing
if userinput[:text] == "newtopic"
@@ -754,7 +754,7 @@ function conversation(a::companion, userinput::Dict)
)
chatresponse = generatechat(a)
addNewMessage(a, "assistant", chatresponse)
addNewMessage(a, "assistant", chatresponse; maximumMsg=30)
push!(a.memory[:events],
eventdict(;
@@ -871,7 +871,7 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
)
)
else
error("condition is not defined ", @__FILE__, " ", @__LINE__)
error("condition is not defined ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
@@ -928,6 +928,7 @@ function generatechat(a::sommelier, thoughtDict)
- If the user interrupts, prioritize the user
- Medium and full-bodied red wines should not be paired with spicy foods.
You should then respond to the user with:
1) Chat: Given the situation, How would you respond to the user to express your thoughts honestly and keep the conversation going smoothly?
@@ -977,7 +978,7 @@ function generatechat(a::sommelier, thoughtDict)
# 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"
error("generatechat() response contain : ", @__FILE__, " ", @__LINE__)
error("generatechat() response contain : ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
response = GeneralUtils.remove_french_accents(response)
response = replace(response, '*'=>"")
@@ -989,7 +990,7 @@ function generatechat(a::sommelier, thoughtDict)
for i [:chat]
if length(JSON3.write(responsedict[i])) == 0
error("$i is empty ", @__FILE__, " ", @__LINE__)
error("$i is empty ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
end
@@ -1006,7 +1007,7 @@ function generatechat(a::sommelier, thoughtDict)
error("Context: is in text. This is not allowed")
end
println("\n~~~ generatechat() ", @__FILE__, " ", @__LINE__)
println("\n~~~ generatechat() ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
pprintln(Dict(responsedict))
# check whether an agent recommend wines before checking inventory or recommend wines
@@ -1044,7 +1045,7 @@ function generatechat(a::sommelier, thoughtDict)
showerror(io, e)
errorMsg = String(take!(io))
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", @__FILE__, " ", @__LINE__)
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
end
error("generatechat failed to generate a response")
@@ -1137,6 +1138,12 @@ function generatequestion(a, text2textInstructLLM::Function; recent=nothing)::St
- If you don't already know, find out the characteristics of wine the user is looking for, such as tannin, sweetness, intensity, acidity
- If you don't already know, find out what food will be served with wine
- If you haven't already, introduce the wines you found in the database to the user first
- Generally speaking, your inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know exactly until you check your inventory.
- All wines in your inventory are always in stock.
- Engage in conversation to indirectly investigate the customer's intention, budget and preferences before checking your inventory.
- 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.
- 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.
- Medium and full-bodied red wines should not be paired with spicy foods.
You should then respond to the user with:
1) Understanding:
@@ -1251,17 +1258,17 @@ function generatequestion(a, text2textInstructLLM::Function; recent=nothing)::St
# check for valid response
q_atleast = length(a.memory[:events]) <= 2 ? 1 : 3
if q_number < q_atleast
error("too few questions only $q_number questions are generated ", @__FILE__, " ", @__LINE__)
error("too few questions only $q_number questions are generated ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
# check whether "A1" is in the response, if not error.
elseif !occursin("A1:", response)
error("no answer found in the response ", @__FILE__, " ", @__LINE__)
error("no answer found in the response ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
responsedict = GeneralUtils.textToDict(response,
["Understanding", "Q1"],
rightmarker=":", symbolkey=true, lowercasekey=true)
response = "Q1: " * responsedict[:q1]
println("\n~~~ generatequestion ", @__FILE__, " ", @__LINE__)
println("\n~~~ generatequestion ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
pprintln(response)
return response
catch e
@@ -1269,7 +1276,7 @@ function generatequestion(a, text2textInstructLLM::Function; recent=nothing)::St
showerror(io, e)
errorMsg = String(take!(io))
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", @__FILE__, " ", @__LINE__)
println("\nAttempt $attempt. Error occurred: $errorMsg\n$st ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
end
error("generatequestion failed to generate a response ", response)
@@ -1345,7 +1352,7 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent::
# responsedict = GeneralUtils.textToDict(response,
# ["summary", "presented", "selected"],
# rightmarker=":", symbolkey=true)
println("\n~~~ generateSituationReport() ", @__FILE__, " ", @__LINE__)
println("\n~~~ generateSituationReport() ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
pprintln(response)
return Dict(:recap => response)
@@ -1401,7 +1408,7 @@ function detectWineryName(a, text)
try
response = a.func[:text2textInstructLLM](prompt)
println("\n~~~ detectWineryName() ", @__FILE__, " ", @__LINE__)
println("\n~~~ detectWineryName() ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
pprintln(response)
responsedict = GeneralUtils.textToDict(response, ["winery_names"],
@@ -1415,7 +1422,7 @@ function detectWineryName(a, text)
showerror(io, e)
errorMsg = String(take!(io))
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
println("\n Attempt $attempt. Error occurred: $errorMsg\n$st ", @__FILE__, " ", @__LINE__)
println("\n Attempt $attempt. Error occurred: $errorMsg\n$st ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
end
end
error("detectWineryName failed to generate a response")

View File

@@ -291,20 +291,20 @@ julia> result = checkinventory(agent, input)
function checkinventory(a::T1, input::T2
) where {T1<:agent, T2<:AbstractString}
println("\n~~~ checkinventory order: $input ", @__FILE__, " ", @__LINE__)
println("\n~~~ checkinventory order: $input ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
wineattributes_1 = extractWineAttributes_1(a, input)
wineattributes_2 = extractWineAttributes_2(a, input)
_inventoryquery = "retailer name: $(a.retailername), $wineattributes_1, $wineattributes_2"
inventoryquery = "Retrieves winery, wine_name, 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}"
println("~~~ checkinventory input: $inventoryquery ", @__FILE__, " ", @__LINE__)
println("~~~ checkinventory input: $inventoryquery ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
# add suppport for similarSQLVectorDB
textresult, rawresponse = SQLLLM.query(inventoryquery, a.func[:executeSQL],
a.func[:text2textInstructLLM],
insertSQLVectorDB=a.func[:insertSQLVectorDB],
similarSQLVectorDB=a.func[:similarSQLVectorDB])
println("\n~~~ checkinventory result ", @__FILE__, " ", @__LINE__)
println("\n~~~ checkinventory result ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
println(textresult)
return (result=textresult, rawresponse=rawresponse, success=true, errormsg=nothing)
@@ -403,7 +403,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
for word in attributes
if !occursin(word, response)
errornote = "$word attribute is missing in previous attempts"
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
checkFlag = true
break
end
@@ -431,7 +431,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
# check whether wine_price is in ranged number
if !occursin('-', responsedict[:wine_price])
errornote = "wine_price must be a range number"
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
checkFlag = true
break
end
@@ -454,7 +454,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
for x in content #BUG why x is "0-1500"
if !occursin("NA", responsedict[j]) && !occursin(x, input)
errornote = "$x is not mentioned in the user query, you must only use the info from the query."
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
checkFlag == true
break
end
@@ -624,7 +624,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
value = responsedict[keyword]
if value != "NA" && !occursin(value, input)
errornote = "WARNING. Keyword $keyword: $value does not appear in the input. You must use information from the input only"
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
continue
end
@@ -640,7 +640,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
if !occursin("keyword", string(k))
if v !== "NA" && (!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("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
println("Attempt $attempt $errornote ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
continue
end
end
@@ -859,7 +859,7 @@ end
# state[:isterminal] = true
# state[:reward] = 1
# end
# println("--> 5 Evaluator ", @__FILE__, " ", @__LINE__)
# println("--> 5 Evaluator ", Dates.now(), " ", @__FILE__, " ", @__LINE__)
# pprintln(Dict(responsedict))
# return responsedict[:score]
# catch e

View File

@@ -106,7 +106,7 @@ function addNewMessage(a::T1, name::String, text::T2;
error("name is not in agent.availableRole $(@__LINE__)")
end
#[] summarize the oldest 10 message
#[WORKING] summarize the oldest 10 message
if length(a.chathistory) > maximumMsg
summarize(a.chathistory)
else