From 68a20b5080ae399e28f7160f4a4ab01a97c75c18 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Thu, 17 Jul 2025 11:48:23 +0700 Subject: [PATCH] update --- src/interface.jl | 553 +---------------------------------------------- src/type.jl | 12 +- 2 files changed, 11 insertions(+), 554 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index a694988..e1420b7 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -413,321 +413,6 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 error("DecisionMaker failed to generate a thought ", response) end end -# function decisionMaker(a::T; recent::Integer=10 -# ) where {T<:agent} - -# # lessonDict = copy(JSON3.read("lesson.json")) - -# # lesson = -# # if isempty(lessonDict) -# # "" -# # else -# # lessons = Dict{Symbol, Any}() -# # for (k, v) in lessonDict -# # lessons[k] = lessonDict[k][:lesson] -# # end - -# # """ -# # You have attempted to help the user before and failed, either because your reasoning for the -# # recommendation was incorrect or your response did not exactly match the user expectation. -# # The following lesson(s) give a plan to avoid failing to help the user in the same way you -# # did previously. Use them to improve your strategy to help the user. - -# # Here are some lessons in JSON format: -# # $(JSON3.write(lessons)) - -# # When providing the thought and action for the current trial, that into account these failed -# # trajectories and make sure not to repeat the same mistakes and incorrect answers. -# # """ -# # end - -# recent_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recent) -# recentevents = a.memory[:events][recent_ind] -# timeline = createTimeline(recentevents; eventindex=recent_ind) - -# # recap as caching -# # query similar result from vectorDB -# recapkeys = keys(a.memory[:recap]) -# _recapkeys_vec = [i for i in recapkeys] - -# # select recent keys -# _recentRecapKeys = -# if length(a.memory[:recap]) <= 3 # 1st message is a user's hello msg -# _recapkeys_vec -# elseif length(a.memory[:recap]) > 3 -# l = length(a.memory[:recap]) -# _recapkeys_vec[l-2:l] -# end - -# # get recent recap -# _recentrecap = OrderedDict() -# for (k, v) in a.memory[:recap] -# if k ∈ _recentRecapKeys -# _recentrecap[k] = v -# end -# end - -# recentrecap = GeneralUtils.dictToString_noKey(_recentrecap) -# # similarDecision = a.context[:similarSommelierDecision](recentrecap) -# similarDecision = nothing #CHANGE - -# if similarDecision !== nothing -# responsedict = similarDecision -# return responsedict -# else - -# header = ["Thought:", "Plan:", "Action_name:", "Action_input:"] -# dictkey = ["thought", "plan", "actionname", "actioninput"] - -# context = # may b add wine name instead of the hold wine data is better -# if length(a.memory[:shortmem][:available_wine]) != 0 -# winenames = [] -# for (i, wine) in enumerate(a.memory[:shortmem][:available_wine]) -# name = "$i) $(wine["wine_name"]) " -# push!(winenames, name) -# end -# availableWineName = join(winenames, ',') -# "Available wines you've found in your inventory so far: $availableWineName" -# else -# "" -# end - -# errornote = "N/A" -# response = nothing # placeholder for show when error msg show up - -# for attempt in 1:10 -# if attempt > 1 -# println("\nYiemAgent decisionMaker() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# end - -# QandA = generatequestion(a, a.context[:text2textInstructLLM]; recent=3) -# systemmsg = -# """ -# Your name is $(a.name). You are a helpful English-speaking assistant, acting as a polite, website-based sommelier for $(a.retailername)'s wine store. -# Your goal includes: -# 1) Establish a connection with the customer by greeting them warmly -# 2) Guide them to select the best wines only from your store's inventory that align with their preferences - -# Your responsibility includes: -# 1) Make an informed decision about what you need to do to achieve the goal -# 2) Thanks the user when they don't need any further assistance and invite them to comeback next time - -# Your responsibility does NOT includes: -# 1) Requesting the user to place an order, make a purchase, or confirm the order. These are the job of our sales team at the store. -# 2) Processing sales orders or engaging in any other sales-related activities. These are the job of our sales team at the store. -# 3) Answering questions or offering additional services beyond those related to your store's wine recommendations such as discounts, quantity, rewards programs, promotions, delivery options, shipping, boxes, gift wrapping, packaging, personalized messages or something similar. These are the job of our sales team at the store. - -# At each round of conversation, you will be given the following information: -# Your recent events: latest 5 events of the situation -# Your Q&A: the question and answer you have asked yourself - -# You must follow the following guidelines: -# - Focus on the latest event -# - 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 -# - Approach each customer with open-ended questions to understand their preferences, budget, and occasion. This will help you guide the conversation naturally while gathering essential insights. Once you have this information, you can efficiently check your inventory for the best match. -# - 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. -# - Spicy foods should not be paired with medium and full-bodied red wines. - -# You should follow the following guidelines: -# - When searching an inventory, search as broadly as possible based on the information you have gathered so far. -# - Encourage the customer to explore different options and try new things. -# - If you are unable to locate the desired item after multiple attempts, it may not be available in your inventory. In such cases, inform the user that the item is unavailable and suggest an alternative instead. - -# For your information: -# - Your store carries only wine. -# - Vintage 0 means non-vintage. - -# You should then respond to the user with interleaving Thought, Plan, Action_name, Action_input: -# 1) Thought: Articulate your current understanding and consider the current situation. -# 2) Plan: Based on the current situation, state a complete action plan to complete the task. Be specific. -# 3) Action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the following function names: -# - CHATBOX which you can use to talk with the user. The input is your intentions for the dialogue. Be specific. -# - CHECKINVENTORY allows you to check information about wines you want in your inventory. The input should be a specific search term in verbal English. A good search term should include details such as winery, wine name, vintage, region, country, wine type, grape varietal, tasting notes, wine price, occasion, food to be paired with wine, intensity, tannin, sweetness, acidity. -# Invalid query example: red wine that pair well with spicy food. -# - 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 when the user has finished their conversation with you, so that you can properly end the conversation. Input is "NA". -# 4) Action_input: The input to the action you are about to perform. This should be aligned with the plan - - -# You should only respond in format as described below: -# Thought: ... -# Plan: ... -# Action_name: ... -# Action_input: ... - -# Let's begin! - -# $context -# Your recent events: -# $timeline -# Your Q&A: -# $QandA -# P.S. $errornote -# """ - -# unformatPrompt = -# [ -# Dict(:name => "system", :text => systemmsg), -# ] - -# # found wine is "count 0" invalid return from CHECKINVENTORY() -# # check if winename in shortmem occurred in chathistory. if not, skip decision and imediately use PRESENTBOX -# # if length(a.memory[:shortmem][:found_wine]) != 0 -# # # check if wine name mentioned in recentevents, only check first wine name is enough -# # # because agent will recommend every wines it found each time. -# # winenames = [] -# # for wine in a.memory[:shortmem][:found_wine] -# # push!(winenames, wine["wine_name"]) -# # end - -# # for winename in winenames -# # if !occursin(winename, chathistory) -# # println("\nYiem decisionMaker() found wines from DB ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# # d = Dict( -# # :thought=> "The user is looking for a wine tahat matches their intention and budget. I've checked the inventory and found wines that match the customer's criteria. I will present the wines to the customer.", -# # :plan=> "1) I'll provide detailed introductions of the wines I just found to the user. 2) I'll explain how the wine could match the user's intention and what its effects might mean for the user's experience. 3) If multiple wines are available, I'll highlight their differences and provide a comprehensive comparison of how each option aligns with the user's intention and what the potential effects of each option could mean for the user's experience. 4) I'll provide my personal recommendation.", -# # :actionname=> "PRESENTBOX", -# # :actioninput=> "I need to present to the user the following wines: $winenames") -# # a.memory[:shortmem][:found_wine] = [] # clear because PRESENTBOX command is issued. This is to prevent decisionMaker() keep presenting the same wines -# # result = (systemmsg=systemmsg, usermsg=usermsg, unformatPrompt=unformatPrompt, result=d) -# # println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# # pprintln(Dict(d)) -# # return result -# # end -# # end -# # end - -# # change qwen format put in model format -# prompt = GeneralUtils.formatLLMtext(unformatPrompt, "qwen3") -# response = a.context[:text2textInstructLLM](prompt) -# response = GeneralUtils.remove_french_accents(response) -# response = replace(response, "**"=>"") -# response = replace(response, "***"=>"") -# response = replace(response, "<|eot_id|>"=>"") -# response = GeneralUtils.deFormatLLMtext(response, "qwen3") - -# # check if response contain more than one functions from ["CHATBOX", "CHECKINVENTORY", "ENDCONVERSATION"] -# count = 0 -# for i ∈ ["CHATBOX", "CHECKINVENTORY", "PRESENTBOX", "ENDCONVERSATION"] -# if occursin(i, response) -# count += 1 -# end -# end -# if count > 1 -# errornote = "You must use only one function" -# println("\nERROR YiemAgent decisionMaker() $errornote\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# 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 - -# responsedict = GeneralUtils.textToDict(response, header; -# dictKey=dictkey, symbolkey=true) - -# if responsedict[:actionname] ∉ ["CHATBOX", "CHECKINVENTORY", "PRESENTBOX", "ENDCONVERSATION"] -# errornote = "Your previous attempt didn't use the given functions" -# println("\nERROR YiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end - -# checkFlag = false -# for i ∈ Symbol.(dictkey) -# if length(responsedict[i]) == 0 -# errornote = "$i is empty" -# println("\nERROR YiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# checkFlag = true -# break -# end -# end -# checkFlag == true ? continue : nothing - -# # check if there are more than 1 key per categories -# checkFlag = false -# for i ∈ Symbol.(dictkey) -# matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i) -# if length(matchkeys) > 1 -# errornote = "Your previous attempt has more than one key per categories" -# println("\nERROR YiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# checkFlag = true -# break -# end -# end -# checkFlag == true ? continue : nothing - -# # check if actionname = CHECKINVENTORY and actioninput has the words "pairs well" or -# # "pair well" in it because it is not a valid query. -# detected_kw = GeneralUtils.detect_keyword(["pair", "pairs", "pairing", "well"], responsedict[:actioninput]) -# if responsedict[:actionname] == "CHECKINVENTORY" && sum(values(detected_kw)) != 0 -# errornote = "In your previous attempt, actioninput for CHECKINVENTORY function is invalid" -# println("\nERROR YiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end - -# println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# pprintln(Dict(responsedict)) - -# # check whether an agent recommend wines before checking inventory or recommend wines -# # outside its inventory -# # ask LLM whether there are any winery mentioned in the response -# mentioned_winery = detectWineryName(a, response) -# if mentioned_winery != "None" -# mentioned_winery = String.(strip.(split(mentioned_winery, ","))) - -# # check whether the wine is in event -# isWineInEvent = false -# for winename in mentioned_winery -# for event in a.memory[:events] -# if event[:observation] !== nothing && occursin(winename, event[:observation]) -# isWineInEvent = true -# break -# end -# end -# end - -# # then the agent is not supposed to recommend the wine -# if isWineInEvent == false -# errornote = "You recommended wines that are not in your inventory before. Please only recommend wines that you have previously found in your inventory." -# println("\nERROR YiemAgent decisionMaker() $errornote $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end -# end - -# delete!(responsedict, :mentioned_winery) -# responsedict[:systemmsg] = systemmsg -# responsedict[:unformatPrompt] = unformatPrompt -# responsedict[:QandA] = QandA - -# # check whether responsedict[:actioninput] is the same as previous dialogue -# if responsedict[:actioninput] == a.chathistory[end][:text] -# errornote = "In your previous attempt, you repeated the previous dialogue. Please try again." -# println("\nERROR YiemAgent decisionMaker() $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end - -# # println("\n$prompt", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# # println("\n$response") - -# responsedict[:prompt] = prompt -# return responsedict -# end -# error("DecisionMaker failed to generate a thought ", response) -# end -# end @@ -1308,32 +993,6 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev continue end - # # check whether response has not-allowed words - # notallowed = ["respond:", "user>", "user:"] - # detected_kw = GeneralUtils.detect_keyword(notallowed, response) - # # list all keys that have 1 value in detected_kw dictionary - # k = [key for (key, value) in detected_kw if value == 1] - # if length(k) > 0 - # errornote = "In your previous attempt, you have $k in your response which is not allowed." - # println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # continue - # end - - # # check whether response has all header - # detected_kw = GeneralUtils.detect_keyword(header, response) - # if 0 ∈ values(detected_kw) - # errornote = "$missingkeys are missing from your previous response" - # println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # continue - # elseif sum(values(detected_kw)) > length(header) - # errornote = "\nYour previous attempt has duplicated points according to the required response format" - # println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # continue - # end - - # responsedict = GeneralUtils.textToDict(response, header; - # dictKey=dictkey, symbolkey=true) - # check if Context: is in dialogue if occursin("Context:", responsedict[:dialogue]) errornote = "Your previous response contains 'Context:' which is not allowed" @@ -1387,177 +1046,6 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev end error("presentbox() failed to generate a response") end -# function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10) -# systemmsg = -# """ -# Your profile: -# Your name is $(a.name). You are a helpful English-speaking assistant, acting as a polite, website-based sommelier for $(a.retailername)'s wine store. -# Situation: -# You have checked the inventory and found wines. -# Your mission: -# Present the wines to the customer in a way that keep the conversation smooth and engaging. -# At each round of conversation, you will be given the following information: -# Database search result: the result of a database search using SQL commands you have found so far -# Chat history: your ongoing conversation with the user -# Name of the wines that needs to be introduced: name of wines you are going to introduce to the user. -# You should follow the following guidelines: -# - Provide detailed introductions of the wines you've found to the user. -# - Explain how the wine could match the user's intention and what its effects might mean for the user's experience. -# - If multiple wines are available, highlight their differences and provide a comprehensive comparison of how each option aligns with the user's intention and what the potential effects of each option could mean for the user's experience. -# - Provide your personal recommendation and provide a brief explanation of why you recommend it. -# You should then respond to the user with: -# dialogue: Your presentation to the user -# You should only respond in format as described below: -# { -# "dialogue": "..." -# } - -# Let's begin! -# """ -# requiredKeys = [:dialogue] -# database_search_result = -# if length(a.memory[:shortmem][:db_search_result]) != 0 -# availableWineToText(a.memory[:shortmem][:db_search_result]) -# else -# "N/A" -# end - -# chathistory = chatHistoryToText(a.chathistory) -# errornote = "N/A" -# response = nothing # placeholder for show when error msg show up - - - -# # yourthought = "$(thoughtDict[:thought]) $(thoughtDict[:plan])" -# # yourthought1 = nothing - -# for attempt in 1:maxtattempt - -# context = -# """ -# -# Database search result: $database_search_result -# Chat history: $chathistory -# Name of the wines that needs to be introduced: $(thoughtDict[:actioninput]) -# P.S. $errornote -# -# """ - -# unformatPrompt = -# [ -# Dict(:name => "system", :text => systemmsg), -# ] - -# # put in model format -# prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName) -# # add info -# prompt = prompt * context - -# response = a.context[:text2textInstructLLM](prompt; senderId=a.id) -# response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) -# response = GeneralUtils.remove_french_accents(response) -# # response = replace(response, '$'=>"USD") -# think, response = GeneralUtils.extractthink(response) - -# response = replace(response, '*'=>"") -# response = replace(response, '$' => "USD") -# response = replace(response, '`' => "") -# response = replace(response, "<|eot_id|>"=>"") - -# responsedict = nothing -# try -# responsedict = copy(JSON3.read(response)) -# catch -# println("\nERROR YiemAgent presentbox() failed to parse response: $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end - -# # check whether all answer's key points are in responsedict -# _responsedictKey = keys(responsedict) -# responsedictKey = [i for i in _responsedictKey] # convert into a list -# is_requiredKeys_in_responsedictKey = [i ∈ responsedictKey for i in requiredKeys] - -# if length(is_requiredKeys_in_responsedictKey) > length(requiredKeys) -# errornote = "Your previous attempt has more key points than answer's required key points." -# println("\nERROR YiemAgent presentbox() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# elseif !all(is_requiredKeys_in_responsedictKey) -# zeroind = findall(x -> x == 0, is_requiredKeys_in_responsedictKey) -# missingkeys = [requiredKeys[i] for i in zeroind] -# errornote = "$missingkeys are missing from your previous response" -# println("\nERROR YiemAgent presentbox() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end - -# # # check whether response has not-allowed words -# # notallowed = ["respond:", "user>", "user:"] -# # detected_kw = GeneralUtils.detect_keyword(notallowed, response) -# # # list all keys that have 1 value in detected_kw dictionary -# # k = [key for (key, value) in detected_kw if value == 1] -# # if length(k) > 0 -# # errornote = "In your previous attempt, you have $k in your response which is not allowed." -# # println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# # continue -# # end - -# # # check whether response has all header -# # detected_kw = GeneralUtils.detect_keyword(header, response) -# # if 0 ∈ values(detected_kw) -# # errornote = "$missingkeys are missing from your previous response" -# # println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# # continue -# # elseif sum(values(detected_kw)) > length(header) -# # errornote = "\nYour previous attempt has duplicated points according to the required response format" -# # println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# # continue -# # end - -# # responsedict = GeneralUtils.textToDict(response, header; -# # dictKey=dictkey, symbolkey=true) - -# # check if Context: is in dialogue -# if occursin("Context:", responsedict[:dialogue]) -# errornote = "Your previous response contains 'Context:' which is not allowed" -# println("\nERROR YiemAgent presentbox() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end - -# println("\nYiemAgent presentbox() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# pprintln(Dict(responsedict)) - -# # check whether an agent recommend wines before checking inventory or recommend wines -# # outside its inventory -# # ask LLM whether there are any winery mentioned in the response -# mentioned_winery = detectWineryName(a, responsedict[:dialogue]) -# if mentioned_winery != "None" -# mentioned_winery = String.(strip.(split(mentioned_winery, ","))) - -# # check whether the wine is in event -# isWineInEvent = false -# for winename in mentioned_winery -# for event in a.memory[:events] -# if event[:observation] !== nothing && occursin(winename, event[:observation]) -# isWineInEvent = true -# break -# end -# end -# end - -# # if wine is mentioned but not in timeline or shortmem, -# # then the agent is not supposed to recommend the wine -# if isWineInEvent == false -# 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())") -# continue -# end -# end - -# result = responsedict[:dialogue] -# return result -# end -# error("presentbox() failed to generate a response") -# end - """ @@ -1705,37 +1193,6 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) response = replace(response, '`' => "") response = replace(response, "<|eot_id|>"=>"") - - - - # # 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 generatechat() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # continue - # elseif sum(values(detected_kw)) > length(header) - # errornote = "\nYour previous attempt has duplicated points according to the required response format" - # println("\nERROR YiemAgent generatechat() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # continue - # end - - # responsedict = GeneralUtils.textToDict(response, header; - # dictKey=dictkey, symbolkey=true) - - # # check if Context: is in dialogue - # if occursin("Context:", responsedict[:dialogue]) - # errornote = "Your previous response contains 'Context:' which is not allowed" - # println("\nERROR YiemAgent generatechat() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # continue - # end - - # println("\nYiemAgent generatechat() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # pprintln(Dict(responsedict)) - # check whether an agent recommend wines before checking inventory or recommend wines # outside its inventory # ask LLM whether there are any winery mentioned in the response @@ -1835,7 +1292,7 @@ function generatechat(a::virtualcustomer; recentEventsDict = createEventsLog(a.memory[:events]; index=recent_ind) response = nothing # placeholder for show when error msg show up errornote = "N/A" - header = ["Dialogue:", "Role"] + header = ["Dialogue:", "Role:"] dictkey = ["dialogue", "role"] llmkwargs=Dict( :num_ctx => 32768, @@ -1869,7 +1326,7 @@ function generatechat(a::virtualcustomer; think, response = GeneralUtils.extractthink(response) # check whether response has all header - detected_kw = GeneralUtils.detect_keyword(header, response) + detected_kw = GeneralUtils.detectKeywordVariation(header, response) kwvalue = [i for i in values(detected_kw)] zeroind = findall(x -> x == 0, kwvalue) missingkeys = [header[i] for i in zeroind] @@ -2133,7 +1590,7 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String end # check whether response has all header - detected_kw = GeneralUtils.detect_keyword(header, response) + detected_kw = GeneralUtils.detectKeywordVariation(header, response) if 0 ∈ values(detected_kw) errornote = "\nYour previous attempt did not have all points according to the required response format" println("\nERROR YiemAgent generatequestion() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") @@ -2223,7 +1680,7 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent:: response = GeneralUtils.deFormatLLMtext(response, "qwen3") # check whether response has all header - detected_kw = GeneralUtils.detect_keyword(header, response) + detected_kw = GeneralUtils.detectKeywordVariation(header, response) kwvalue = [i for i in values(detected_kw)] zeroind = findall(x -> x == 0, kwvalue) missingkeys = [header[i] for i in zeroind] @@ -2298,7 +1755,7 @@ function detectWineryName(a, text) try pprintln(response) catch e println(response) end # check whether response has all header - detected_kw = GeneralUtils.detect_keyword(header, response) + detected_kw = GeneralUtils.detectKeywordVariation(header, response) if 0 ∈ values(detected_kw) errornote = "\nYiemAgent detectWineryName() response does not have all header" continue diff --git a/src/type.jl b/src/type.jl index fa84efc..6dbcf0d 100644 --- a/src/type.jl +++ b/src/type.jl @@ -30,7 +30,7 @@ mutable struct companion <: agent maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized chathistory::Vector{Dict{Symbol, Any}} memory::Dict{Symbol, Any} - func::NamedTuple # NamedTuple of functions + context::NamedTuple # NamedTuple of functions llmFormatName::String end @@ -168,12 +168,12 @@ mutable struct sommelier <: agent maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized chathistory::Vector{Dict{Symbol, Any}} memory::Dict{Symbol, Any} - func # NamedTuple of functions + context # NamedTuple of functions llmFormatName::String end function sommelier( - context::appcontext, # NamedTuple of functions + context::appcontext, # app context ; name::String= "Assistant", id::String= string(uuid4()), @@ -240,12 +240,12 @@ mutable struct virtualcustomer <: agent maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized chathistory::Vector{Dict{Symbol, Any}} memory::Dict{Symbol, Any} - func # NamedTuple of functions + context # NamedTuple of functions llmFormatName::String end function virtualcustomer( - func, # NamedTuple of functions + context, # NamedTuple of functions ; name::String= "Assistant", id::String= string(uuid4()), @@ -298,7 +298,7 @@ function virtualcustomer( maxHistoryMsg, chathistory, memory, - func, + context, llmFormatName )