From 03f50379c981b66703991eb2d3ea3e3173719c89 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Mon, 26 May 2025 07:14:19 +0700 Subject: [PATCH 01/23] mark new version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1f417cd..c3aeeed 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "YiemAgent" uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" authors = ["narawat lamaiin "] -version = "0.3.0" +version = "0.4.0" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" From a5c6360b4ecfaf3c155cce7c3e8c14d5adcf604f Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Tue, 3 Jun 2025 10:08:54 +0700 Subject: [PATCH 02/23] update --- src/interface.jl | 209 +++++++++++++++++++++++++-------------------- src/llmfunction.jl | 7 +- src/util.jl | 47 +++++----- 3 files changed, 143 insertions(+), 120 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index eea2c7c..d0756af 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -129,10 +129,10 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 includelatest=true) timeline = createTimeline(a.memory[:events]; eventindex=recentevents_ind) - recentchat_ind = GeneralUtils.recentElementsIndex(length(a.chathistory), recentevents; - includelatest=true) - recentchat = createChatLog(a.chathistory; index=recentchat_ind) - # recentEventsDict = createEventsLog(recentevents; index=recent_ind) + # recentchat_ind = GeneralUtils.recentElementsIndex(length(a.chathistory), recentevents; + # includelatest=true) + # recentchat = createChatLog(a.chathistory; index=recentchat_ind) + recentEvents = createEventsLog(a.memory[:events]; index=recentevents_ind) # # recap as caching @@ -180,43 +180,51 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 systemmsg = """ - Your name is $(a.name). You are a sommelier for website-based $(a.retailername)'s wine store. You are working under your mentor supervision. - 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) According to the store's policy and guidelines, make an informed decision about what you need to do to achieve the goal - 2) Value your mentor's suggestions. - - 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: - context: additional information about the current situation - - You should then respond to the user with interleaving Plan, Action_name, Action_input: - 1) plan: Based on the current situation, state a complete action plan to complete the task. Be specific. - 2) action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the available tool name - 3) action_input: The input to the action you are about to perform according to your plan. - - You should only respond in JSON format as described below: + + Your name is $(a.name). You are a sommelier for website-based $(a.retailername)'s wine store. You are working under your mentor supervision. + + + Your customer is coming into the store + + + 1) Establish a connection with the customer by talking to them politely and showing your enthusiasm for their wine preferences. + 2) Provide relevant information and guide them to select the best wines only from your store's inventory that align with their preferences. + + + 1) According to the store's policy and guidelines, make an informed decision about what you need to do to achieve the goal + 2) Keep the conversation with the customer going smoothly + 2) Obey your mentor's suggestions. + + + 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. + + + context: additional information about the current situation + + + 1) plan: Based on the current situation, state a complete action plan to complete the task. Be specific. + 2) action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the available tool name + 3) action_input: The input to the action you are about to perform according to your plan. + + { "plan": "...", "action_name": "...", "action_input": "..." } + Let's begin! """ requiredKeys = [:plan, :action_name, :action_input] - database_search_result = - if length(a.memory[:shortmem][:db_search_result]) != 0 - availableWineToText(a.memory[:shortmem][:db_search_result]) - else - "N/A" - end + # database_search_result = + # if length(a.memory[:shortmem][:db_search_result]) != 0 + # availableWineToText(a.memory[:shortmem][:db_search_result]) + # else + # "N/A" + # end errornote = "N/A" response = nothing # placeholder for show when error msg show up @@ -233,27 +241,32 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 - Generally speaking, the store inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know exactly until you check your inventory. - - If you found wines in the store's database, they are in stock - - Approach each customer with open-ended questions to understand their preferences, budget, and occasion. Once you have these information, you can check 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. Other wine characteristics useful for CHECKINVENTORY tools are allowed. + - If you found wines in the store's database, they are in stock. + - You can only recommend wines that are currently in our inventory + - Before searching the database for wine, ensure you have at least the following information: 1) budget, 2) wine type, and 3) occasion. Additional details are always helpful. If the user is unsure, provide relevant information and gather insights to make reasonable inferences. + - Ask the user one question at a time. + - 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, if you haven't already, ask the user whether they need any further assistance. Do not offer any additional services. - - If the user is ending the conversation, say goodbye and invite them to come back next time. - - Spicy foods should not be paired with medium and full-bodied red wines. - - We do not sell organic, sustainability and sulfite wine. + - Only end the conversation when the user explicitly intends to do so. When ending, ensure a polite farewell and an invitation to return in the future. + - Spicy foods should be paired only with light red wines. + - We do not sell organic, sustainable, gluten-free, and sulfite-free wine. Inform the user imediately if they are looking for these types of wines. Do not sell our wines as such. - Gift box, gift card, and custom messages are available. Inform the user to contact our sales team. + - Greeting the customer warmly by ask them how could you help. Do not ask any other questions during this greeting. - Encourage the customer to explore different options and try new things. - If you are unable to locate the desired item in the database after 2 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. - Your store carries only wine. - Vintage 0 means non-vintage. - + - Start searching the database as broadly as possible within the given information boundary to maximize the chances of finding. Avoid unnecessary parameters unless specified by the user. Refine the search subsequently. + Search the database as broad as possible under the informantion you have will increase the chance to find wine. Avoid uneccessary parameter such as region, country, tasting notes unless the user specify - CHATBOX which you can use to talk with the user. Be specific. - 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 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. + Example query 1: "Dry, full-bodied red wine from 1) region: Burgundy, country: France or 2) region: Tuscany, country: Italy. Grape varietal: Merlot or Syrah. price 100 to 1000 USD." + Example query 2: "Red or white wine, medium tannin, price under 700 USD" + Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France + - 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. The output is presentation of the wines. - 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. $(a.memory[:shortmem][:scratchpad]) @@ -266,7 +279,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 Dict(:name => "system", :text => systemmsg), ] - unformatPrompt = vcat(unformatPrompt, recentchat) + unformatPrompt = vcat(unformatPrompt, recentEvents) # put in model format prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName) # add info @@ -387,7 +400,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 isWineInEvent = false for winename in mentioned_winery for event in a.memory[:events] - if event[:outcome] !== nothing && occursin(winename, event[:outcome]) + if event[:observation] !== nothing && occursin(winename, event[:observation]) isWineInEvent = true break end @@ -405,17 +418,14 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 delete!(responsedict, :mentioned_winery) # check whether responsedict[:action_input] is the same as previous dialogue - if responsedict[:action_input] == a.chathistory[end][:text] + if !isempty(a.chathistory) && responsedict[:action_input] == 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("\nYiemAgent decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - println("\n$response") - evaluationdict = evaluator(a, timeline, responsedict, context) - if evaluationdict[:approved] == "no" + if evaluationdict[:approval] == "no" mentor_comment = evaluationdict[:suggestion] errornote = "Your previous attempt was not good enough. Please try again. Here is the mentor's suggestion: $mentor_comment" println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> \n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") @@ -425,7 +435,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # store for later training responsedict[:system] = systemmsg responsedict[:unformatPrompt] = unformatPrompt - responsedict[:recentchat] = recentchat + # responsedict[:recentchat] = recentchat responsedict[:prompt] = prompt responsedict[:context] = context responsedict[:think] = think @@ -460,7 +470,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # end # end # println("\nYiemAgent decisionMaker() saved to disk is done. agent $(a.id)") - + responsedict[:prompt] = prompt return responsedict @@ -747,7 +757,7 @@ end # isWineInEvent = false # for winename in mentioned_winery # for event in a.memory[:events] -# if event[:outcome] !== nothing && occursin(winename, event[:outcome]) +# if event[:observation] !== nothing && occursin(winename, event[:observation]) # isWineInEvent = true # break # end @@ -804,10 +814,6 @@ serving as a heuristic to steer the search algorithm towards the most promising julia> ``` -# TODO - - [WORKING] Implement the function. - - # Signature """ function evaluator(a::T1, timeline, decisiondict, evaluateecontext @@ -848,7 +854,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext 2) decision_evaluation: - Examine how the trainee's decisions align with the store's policies and guidelines before proceeding. 3) suggestion: Based store policy and guidelines, provide a suggestion for the immediate decision step only. - 4) approved: Based on suggestion, decide whether to let the trainee proceed with the decision. Can be "yes" or "no" + 4) approval: Can be "yes" or "no". "no" if the suggestion contradict the trainee's decision; otherwise, it is "yes". @@ -856,13 +862,13 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext "trajectory_evaluation": "...", "decision_evaluation": "...", "suggestion": "...", - "approved": "...", + "approval": "...", } Let's begin! """ - requiredKeys = [:trajectory_evaluation, :decision_evaluation, :approved, :suggestion] + requiredKeys = [:trajectory_evaluation, :decision_evaluation, :approval, :suggestion] errornote = "N/A" for attempt in 1:10 @@ -1016,18 +1022,31 @@ julia> response = ChatAgent.conversation(newAgent, "Hi! how are you?") # Signature """ -function conversation(a::sommelier, userinput::Dict; maximumMsg=50) - +function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, + maximumMsg=50) + #[WORKING] add the ability to start the conversation by sommelier # place holder actionname = nothing result = nothing chatresponse = nothing - userinput[:text] = GeneralUtils.remove_french_accents(userinput[:text]) - if userinput[:text] == "newtopic" + if userinput === nothing + # thinking loop until AI wants to communicate with the user + chatresponse = nothing + while chatresponse === nothing + actionname, result = think(a) + if actionname ∈ ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"] + chatresponse = result + end + end + addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg) + + return chatresponse + elseif userinput[:text] == "newtopic" clearhistory(a) return "Okay. What shall we talk about?" else + userinput[:text] = GeneralUtils.remove_french_accents(userinput[:text]) # add usermsg to a.chathistory addNewMessage(a, "user", userinput[:text]; maximumMsg=maximumMsg) @@ -1037,8 +1056,8 @@ function conversation(a::sommelier, userinput::Dict; maximumMsg=50) event_description="the user talks to the assistant.", timestamp=Dates.now(), subject="user", - actionname="CHATBOX", - actioninput=userinput[:text], + action_name="CHATBOX", + action_input=userinput[:text], ) ) @@ -1075,7 +1094,8 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; event_description="the user talks to the assistant.", timestamp=Dates.now(), subject="user", - actioninput=userinput[:text], + action_name="CHATBOX", + action_input=userinput[:text], ) ) chatresponse = generatechat(a; converPartnerName=converPartnerName, recentEventNum=20) @@ -1087,7 +1107,8 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; event_description="the assistant talks to the user.", timestamp=Dates.now(), subject="assistant", - actioninput=chatresponse, + action_name="CHATBOX", + action_input=chatresponse, ) ) return chatresponse @@ -1162,8 +1183,8 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh timestamp=Dates.now(), subject="assistant", thought=thoughtDict, - actionname=actionname, - actioninput=actioninput, + action_name=actionname, + action_input=actioninput, ) ) result = actioninput @@ -1188,8 +1209,8 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh timestamp=Dates.now(), subject="assistant", thought=thoughtDict, - actionname=actionname, - actioninput=chatresponse, + action_name=actionname, + action_input=chatresponse, ) ) result = chatresponse @@ -1197,7 +1218,7 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh elseif actionname == "CHECKWINE" if rawresponse !== nothing 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 #[PENDING] a.memory[:shortmem][:available_wine] should be OrderedDict instead of vector dict so that no duplicate item are listed? if length(a.memory[:shortmem][:db_search_result]) != 0 a.memory[:shortmem][:db_search_result] = vcat(a.memory[:shortmem][:db_search_result], vd) @@ -1205,20 +1226,20 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh a.memory[:shortmem][:db_search_result] = vd end - # add to scratchpad - a.memory[:shortmem][:scratchpad] *= - """ - - I searched the database with this search term: $actioninput \nThis is what I found: $result - - """ + # # add to scratchpad + # a.memory[:shortmem][:scratchpad] *= + # """ + # + # I searched the database with this search term: $actioninput \nThis is what I found: $result + # + # """ else - a.memory[:shortmem][:scratchpad] *= - """ - - I searched the database with this search term: $actioninput \nThis is what I found: $result - - """ + # a.memory[:shortmem][:scratchpad] *= + # """ + # + # I searched the database with this search term: $actioninput \nThis is what I found: $result + # + # """ end push!(a.memory[:events], @@ -1227,9 +1248,9 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh timestamp= Dates.now(), subject= "assistant", thought=thoughtDict, - actionname=actionname, - actioninput= "I search the database with this search term: $actioninput", - outcome= "This is what I found:, $result" + action_name=actionname, + action_input= "I search the database with this search term: $actioninput", + observation= "This is what I found:, $result" ) ) @@ -1248,7 +1269,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev 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 name is $(a.name). You are a helpful English-speaking assistant, acting as a polite, website-based sommelier for $(a.retailername)'s wine store. You have checked the inventory and found wines that may match what the user wants @@ -1399,7 +1420,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev isWineInEvent = false for winename in mentioned_winery for event in a.memory[:events] - if event[:outcome] !== nothing && occursin(winename, event[:outcome]) + if event[:observation] !== nothing && occursin(winename, event[:observation]) isWineInEvent = true break end @@ -1580,7 +1601,7 @@ end # isWineInEvent = false # for winename in mentioned_winery # for event in a.memory[:events] -# if event[:outcome] !== nothing && occursin(winename, event[:outcome]) +# if event[:observation] !== nothing && occursin(winename, event[:observation]) # isWineInEvent = true # break # end @@ -1791,7 +1812,7 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) isWineInEvent = false for winename in mentioned_winery for event in a.memory[:events] - if event[:outcome] !== nothing && occursin(winename, event[:outcome]) + if event[:observation] !== nothing && occursin(winename, event[:observation]) isWineInEvent = true break end @@ -1997,7 +2018,7 @@ function generatechat(a::virtualcustomer; end # check if the dialogue is the same as the previous one - if responsedict[:dialogue] == a.chathistory[end][:text] + if length(responsedict[:dialogue]) != 0 && responsedict[:dialogue] == a.chathistory[end][:text] errornote = "In your previous attempt you said $(responsedict[:dialogue]) which was the same as the previous one." println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -2195,7 +2216,7 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String isWineInEvent = false for winename in mentioned_winery for event in a.memory[:events] - if event[:outcome] !== nothing && occursin(winename, event[:outcome]) + if event[:observation] !== nothing && occursin(winename, event[:observation]) isWineInEvent = true break end diff --git a/src/llmfunction.jl b/src/llmfunction.jl index 4a8febb..09f9a14 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -373,8 +373,8 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10 wine_name: name of the wine winery: name of the winery vintage: the year of the wine - 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" + region: a region, such as Burgundy, Bordeaux, Champagne, Napa Valley, Tuscany, California, Oregon, etc. Use "or" if there are multiple regions. + country: a country where wine is produced. Can be "Austria", "Australia", "France", "Germany", "Italy", "Portugal", "Spain", "United States". Use "or" if there are multiple countries. 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 word describe the wine's flavor, such as "butter", "oak", "fruity", "raspberry", "earthy", "floral", etc @@ -866,8 +866,7 @@ function paraphrase(text2textInstructLLM::Function, text::String) Let's begin! """ - #[WORKING] use JSON3 the same as extractWineAttributes_1 is better - #[WORKING] change this function to use the same format use decisionMater + #[PENDING] use JSON3 the same as extractWineAttributes_1 is better. change this function to use the same format use decisionMaker header = ["Paraphrase:"] dictkey = ["paraphrase"] diff --git a/src/util.jl b/src/util.jl index 763d37c..3f57a9f 100644 --- a/src/util.jl +++ b/src/util.jl @@ -231,12 +231,12 @@ function eventdict(; timestamp::Union{DateTime, Nothing}=nothing, subject::Union{String, Nothing}=nothing, thought::Union{AbstractDict, Nothing}=nothing, - actionname::Union{String, Nothing}=nothing, # "CHAT", "CHECKINVENTORY", "PRESENTBOX", etc - actioninput::Union{String, Nothing}=nothing, + action_name::Union{String, Nothing}=nothing, # "CHAT", "CHECKINVENTORY", "PRESENTBOX", etc + action_input::Union{String, Nothing}=nothing, location::Union{String, Nothing}=nothing, equipment_used::Union{String, Nothing}=nothing, material_used::Union{String, Nothing}=nothing, - outcome::Union{String, Nothing}=nothing, + observation::Union{String, Nothing}=nothing, note::Union{String, Nothing}=nothing, ) @@ -245,12 +245,12 @@ function eventdict(; :timestamp=> timestamp, :subject=> subject, :thought=> thought, - :actionname=> actionname, - :actioninput=> actioninput, + :action_name=> action_name, + :action_input=> action_input, :location=> location, :equipment_used=> equipment_used, :material_used=> material_used, - :outcome=> outcome, + :observation=> observation, :note=> note, ) @@ -266,7 +266,7 @@ end Each event dictionary should have the following keys: - :subject - The subject or entity performing the action - :actioninput - The action or input performed by the subject - - :outcome - (Optional) The result or outcome of the action + - :observation - (Optional) The result or outcome of the action # Returns - `timeline::String` @@ -276,8 +276,8 @@ end # Example events = [ - Dict(:subject => "User", :actioninput => "Hello", :outcome => nothing), - Dict(:subject => "Assistant", :actioninput => "Hi there!", :outcome => "with a smile") + Dict(:subject => "User", :actioninput => "Hello", :observation => nothing), + Dict(:subject => "Assistant", :actioninput => "Hi there!", :observation => "with a smile") ] timeline = createTimeline(events) # 1) User> Hello @@ -297,19 +297,19 @@ function createTimeline(events::T1; eventindex::Union{UnitRange, Nothing}=nothin 1:length(events) end - #[WORKING] Iterate through events and format each one + # Iterate through events and format each one for i in ind event = events[i] # If no outcome exists, format without outcome # if event[:actionname] == "CHATBOX" # timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput])\n" - # elseif event[:actionname] == "CHECKINVENTORY" && event[:outcome] === nothing + # elseif event[:actionname] == "CHECKINVENTORY" && event[:observation] === nothing # timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: Not done yet.\n" # If outcome exists, include it in formatting - if event[:actionname] == "CHECKWINE" - timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: $(event[:outcome])\n" + if event[:action_name] == "CHECKWINE" + timeline *= "Event_$i $(event[:subject])> action_name: $(event[:action_name]), action_input: $(event[:action_input]), observation: $(event[:observation])\n" else - timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput])\n" + timeline *= "Event_$i $(event[:subject])> action_name: $(event[:action_name]), action_input: $(event[:action_input])\n" end end @@ -333,11 +333,11 @@ end # for i in ind # event = events[i] # # If no outcome exists, format without outcome -# if event[:outcome] === nothing +# if event[:observation] === nothing # timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: Not done yet.\n" # # If outcome exists, include it in formatting # else -# timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: $(event[:outcome])\n" +# timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: $(event[:observation])\n" # end # end @@ -363,16 +363,19 @@ function createEventsLog(events::T1; index::Union{UnitRange, Nothing}=nothing for i in ind event = events[i] # If no outcome exists, format without outcome - if event[:outcome] === nothing + if event[:observation] === nothing subject = event[:subject] - actioninput = event[:actioninput] - d = Dict{Symbol, String}(:name=>subject, :text=>actioninput) + action_name = event[:action_name] + action_input = event[:action_input] + str = "Action_name: $action_name, Action_input: $action_input" + d = Dict{Symbol, String}(:name=>subject, :text=>str) push!(log, d) else subject = event[:subject] - actioninput = event[:actioninput] - outcome = event[:outcome] - str = "Action: $actioninput Outcome: $outcome" + action_name = event[:action_name] + action_input = event[:action_input] + observation = event[:observation] + str = "Action_name: $action_name, Action_input: $action_input, Observation: $observation" d = Dict{Symbol, String}(:name=>subject, :text=>str) push!(log, d) end From 932611a439fd1cbf9efa833d6af79d70e258bc0a Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Mon, 9 Jun 2025 06:33:48 +0700 Subject: [PATCH 03/23] update --- src/interface.jl | 90 +++++++++++++++++++++++----------------------- src/llmfunction.jl | 2 +- src/util.jl | 36 +++++++++---------- test/test_1.jl | 4 ++- 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index d0756af..449f100 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -205,20 +205,20 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 1) plan: Based on the current situation, state a complete action plan to complete the task. Be specific. - 2) action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the available tool name - 3) action_input: The input to the action you are about to perform according to your plan. + 2) actionname: (Typically corresponds to the execution of the first step in your plan) Can be one of the available tool name + 3) actioninput: The input to the action you are about to perform according to your plan. { "plan": "...", - "action_name": "...", - "action_input": "..." + "actionname": "...", + "actioninput": "..." } Let's begin! """ - requiredKeys = [:plan, :action_name, :action_input] + requiredKeys = [:plan, :actionname, :actioninput] # database_search_result = # if length(a.memory[:shortmem][:db_search_result]) != 0 # availableWineToText(a.memory[:shortmem][:db_search_result]) @@ -347,9 +347,9 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # responsedict = GeneralUtils.textToDict(response, header; # dictKey=dictkey, symbolkey=true) - if responsedict[:action_name] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"] + if responsedict[:actionname] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"] errornote = "Your previous attempt didn't use the given functions" - println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict[:action_name])", @__FILE__, ":", @__LINE__, " $(Dates.now())") + println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict[:actionname])", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue end @@ -377,12 +377,12 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # end # checkFlag == true ? continue : nothing - # # check if action_name = CHECKINVENTORY and action_input has the words "pairs well" or + # # 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[:action_input]) - # if responsedict[:action_name] == "CHECKINVENTORY" && sum(values(detected_kw)) != 0 - # errornote = "In your previous attempt, action_input for CHECKINVENTORY function was $(responsedict[:action_name]). It was not specific enough." - # println("\nERROR YiemAgent decisionMaker() $errornote => $(responsedict[:action_input]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + # 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 was $(responsedict[:actionname]). It was not specific enough." + # println("\nERROR YiemAgent decisionMaker() $errornote => $(responsedict[:actioninput]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") # continue # end @@ -417,8 +417,8 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 delete!(responsedict, :mentioned_winery) - # check whether responsedict[:action_input] is the same as previous dialogue - if !isempty(a.chathistory) && responsedict[:action_input] == a.chathistory[end][:text] + # check whether responsedict[:actioninput] is the same as previous dialogue + if !isempty(a.chathistory) && 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 @@ -542,7 +542,7 @@ end # else # header = ["Thought:", "Plan:", "Action_name:", "Action_input:"] -# dictkey = ["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 @@ -653,8 +653,8 @@ end # # 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.", -# # :action_name=> "PRESENTBOX", -# # :action_input=> "I need to present to the user the following wines: $winenames") +# # :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())") @@ -704,7 +704,7 @@ end # responsedict = GeneralUtils.textToDict(response, header; # dictKey=dictkey, symbolkey=true) -# if responsedict[:action_name] ∉ ["CHATBOX", "CHECKINVENTORY", "PRESENTBOX", "ENDCONVERSATION"] +# 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 @@ -734,11 +734,11 @@ end # end # checkFlag == true ? continue : nothing -# # check if action_name = CHECKINVENTORY and action_input has the words "pairs well" or +# # 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[:action_input]) -# if responsedict[:action_name] == "CHECKINVENTORY" && sum(values(detected_kw)) != 0 -# errornote = "In your previous attempt, action_input for CHECKINVENTORY function is invalid" +# 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 @@ -777,8 +777,8 @@ end # responsedict[:unformatPrompt] = unformatPrompt # responsedict[:QandA] = QandA -# # check whether responsedict[:action_input] is the same as previous dialogue -# if responsedict[:action_input] == a.chathistory[end][:text] +# # 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 @@ -835,15 +835,15 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext - evaluatee_context: The context that evaluatee use to make a decision - evaluatee_decision: The decision made by the evaluatee, consists of the following elements: "plan" is the trainee's plan - "action_name" is the name of the action taken, which can be one of the available tool name. - "action_input" is the input to the action. + "actionname" is the name of the action taken, which can be one of the available tool name. + "actioninput" is the input to the action. - Use only infomation provided by the store policy and guidelines as a bedrocks for your response. - - The trainee's plan, action_name, and action_input must be logically consistent - - The trainee's action_input should be in a proper format as specified by the tools. + - The trainee's plan, actionname, and actioninput must be logically consistent + - The trainee's actioninput should be in a proper format as specified by the tools. 1) trajectory_evaluation: Analyze the trajectory of a solution to answer the user's original question. @@ -885,7 +885,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext $evaluateecontext - {plan: $(decisiondict[:plan]), action_name: $(decisiondict[:action_name]), action_input: $(decisiondict[:action_input])} + {plan: $(decisiondict[:plan]), actionname: $(decisiondict[:actionname]), actioninput: $(decisiondict[:actioninput])} P.S. $errornote @@ -1056,8 +1056,8 @@ function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, event_description="the user talks to the assistant.", timestamp=Dates.now(), subject="user", - action_name="CHATBOX", - action_input=userinput[:text], + actionname="CHATBOX", + actioninput=userinput[:text], ) ) @@ -1094,8 +1094,8 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; event_description="the user talks to the assistant.", timestamp=Dates.now(), subject="user", - action_name="CHATBOX", - action_input=userinput[:text], + actionname="CHATBOX", + actioninput=userinput[:text], ) ) chatresponse = generatechat(a; converPartnerName=converPartnerName, recentEventNum=20) @@ -1107,8 +1107,8 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; event_description="the assistant talks to the user.", timestamp=Dates.now(), subject="assistant", - action_name="CHATBOX", - action_input=chatresponse, + actionname="CHATBOX", + actioninput=chatresponse, ) ) return chatresponse @@ -1135,8 +1135,8 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh # a.memory[:recap] = generateSituationReport(a, a.func[:text2textInstructLLM]; skiprecent=0) thoughtDict = decisionMaker(a) - actionname = thoughtDict[:action_name] - actioninput = thoughtDict[:action_input] + actionname = thoughtDict[:actionname] + actioninput = thoughtDict[:actioninput] # map action and input() to llm function response = @@ -1183,8 +1183,8 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh timestamp=Dates.now(), subject="assistant", thought=thoughtDict, - action_name=actionname, - action_input=actioninput, + actionname=actionname, + actioninput=actioninput, ) ) result = actioninput @@ -1209,8 +1209,8 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh timestamp=Dates.now(), subject="assistant", thought=thoughtDict, - action_name=actionname, - action_input=chatresponse, + actionname=actionname, + actioninput=chatresponse, ) ) result = chatresponse @@ -1248,8 +1248,8 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh timestamp= Dates.now(), subject= "assistant", thought=thoughtDict, - action_name=actionname, - action_input= "I search the database with this search term: $actioninput", + actionname=actionname, + actioninput= "I search the database with this search term: $actioninput", observation= "This is what I found:, $result" ) ) @@ -1320,7 +1320,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev context = """ - Name of the wines that needs to be introduced: $(thoughtDict[:action_input]) + Name of the wines that needs to be introduced: $(thoughtDict[:actioninput]) $(a.memory[:shortmem][:scratchpad]) P.S. $errornote @@ -1503,7 +1503,7 @@ end # # Database search result: $database_search_result # Chat history: $chathistory -# Name of the wines that needs to be introduced: $(thoughtDict[:action_input]) +# Name of the wines that needs to be introduced: $(thoughtDict[:actioninput]) # P.S. $errornote # # """ diff --git a/src/llmfunction.jl b/src/llmfunction.jl index 09f9a14..aaa3212 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -1053,7 +1053,7 @@ end # “action_name” is the name of the action taken, which can be one of the following functions: # 1) CHATBOX[text], which you can use to talk with the user. "text" is in verbal English. # 2) WINESTOCK[query], which you can use to find info about wine in your inventory. "query" is a search term in verbal English. The best query must includes "budget", "type of wine", "characteristics of wine" and "food pairing". -# "action_input" is the input to the action +# "actioninput" is the input to the action # "observation" is result of the preceding immediate action. # At each round of conversation, the user will give you: diff --git a/src/util.jl b/src/util.jl index 3f57a9f..ba4c7ae 100644 --- a/src/util.jl +++ b/src/util.jl @@ -102,7 +102,7 @@ end ----- """ function addNewMessage(a::T1, name::String, text::T2; - maximumMsg::Integer=20) where {T1<:agent, T2<:AbstractString} + maximumMsg::Integer=30) where {T1<:agent, T2<:AbstractString} if name ∉ ["system", "user", "assistant"] # guard against typo error("name is not in agent.availableRole $(@__LINE__)") end @@ -231,8 +231,8 @@ function eventdict(; timestamp::Union{DateTime, Nothing}=nothing, subject::Union{String, Nothing}=nothing, thought::Union{AbstractDict, Nothing}=nothing, - action_name::Union{String, Nothing}=nothing, # "CHAT", "CHECKINVENTORY", "PRESENTBOX", etc - action_input::Union{String, Nothing}=nothing, + actionname::Union{String, Nothing}=nothing, # "CHAT", "CHECKINVENTORY", "PRESENTBOX", etc + actioninput::Union{String, Nothing}=nothing, location::Union{String, Nothing}=nothing, equipment_used::Union{String, Nothing}=nothing, material_used::Union{String, Nothing}=nothing, @@ -245,8 +245,8 @@ function eventdict(; :timestamp=> timestamp, :subject=> subject, :thought=> thought, - :action_name=> action_name, - :action_input=> action_input, + :actionname=> actionname, + :actioninput=> actioninput, :location=> location, :equipment_used=> equipment_used, :material_used=> material_used, @@ -302,14 +302,14 @@ function createTimeline(events::T1; eventindex::Union{UnitRange, Nothing}=nothin event = events[i] # If no outcome exists, format without outcome # if event[:actionname] == "CHATBOX" - # timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput])\n" + # timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput])\n" # elseif event[:actionname] == "CHECKINVENTORY" && event[:observation] === nothing - # timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: Not done yet.\n" + # timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: Not done yet.\n" # If outcome exists, include it in formatting - if event[:action_name] == "CHECKWINE" - timeline *= "Event_$i $(event[:subject])> action_name: $(event[:action_name]), action_input: $(event[:action_input]), observation: $(event[:observation])\n" + if event[:actionname] == "CHECKWINE" + timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: $(event[:observation])\n" else - timeline *= "Event_$i $(event[:subject])> action_name: $(event[:action_name]), action_input: $(event[:action_input])\n" + timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput])\n" end end @@ -334,10 +334,10 @@ end # event = events[i] # # If no outcome exists, format without outcome # if event[:observation] === nothing -# timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: Not done yet.\n" +# timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: Not done yet.\n" # # If outcome exists, include it in formatting # else -# timeline *= "Event_$i $(event[:subject])> action_name: $(event[:actionname]), action_input: $(event[:actioninput]), observation: $(event[:observation])\n" +# timeline *= "Event_$i $(event[:subject])> actionname: $(event[:actionname]), actioninput: $(event[:actioninput]), observation: $(event[:observation])\n" # end # end @@ -365,17 +365,17 @@ function createEventsLog(events::T1; index::Union{UnitRange, Nothing}=nothing # If no outcome exists, format without outcome if event[:observation] === nothing subject = event[:subject] - action_name = event[:action_name] - action_input = event[:action_input] - str = "Action_name: $action_name, Action_input: $action_input" + actionname = event[:actionname] + actioninput = event[:actioninput] + str = "actionname: $actionname, actioninput: $actioninput" d = Dict{Symbol, String}(:name=>subject, :text=>str) push!(log, d) else subject = event[:subject] - action_name = event[:action_name] - action_input = event[:action_input] + actionname = event[:actionname] + actioninput = event[:actioninput] observation = event[:observation] - str = "Action_name: $action_name, Action_input: $action_input, Observation: $observation" + str = "actionname: $actionname, actioninput: $actioninput, observation: $observation" d = Dict{Symbol, String}(:name=>subject, :text=>str) push!(log, d) end diff --git a/test/test_1.jl b/test/test_1.jl index f779d5c..4da18c3 100644 --- a/test/test_1.jl +++ b/test/test_1.jl @@ -239,7 +239,9 @@ a = YiemAgent.sommelier( while true print("\nyour respond: ") user_answer = readline() - response = YiemAgent.conversation(a, Dict(:text=> user_answer)) + response = YiemAgent.conversation(agent; + userinput=Dict(:text=> user_answer), + maximumMsg=50) println("\n$response") end From e0dc7d29b2529e6a29b0fb52bdbfaa4ee3290670 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Sun, 15 Jun 2025 08:02:59 +0700 Subject: [PATCH 04/23] update --- src/interface.jl | 83 ++++++++++-------------------------------------- 1 file changed, 17 insertions(+), 66 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index 449f100..713c65c 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -1024,7 +1024,7 @@ julia> response = ChatAgent.conversation(newAgent, "Hi! how are you?") """ function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, maximumMsg=50) - #[WORKING] add the ability to start the conversation by sommelier + # place holder actionname = nothing result = nothing @@ -1890,64 +1890,12 @@ function generatechat(a::companion; recentevents::Integer=10, end error("generatechat failed to generate a response") end -# function generatechat(a::companion; converPartnerName::Union{String, Nothing}=nothing, maxattempt=10) -# response = nothing # placeholder for show when error msg show up -# errornote = "N/A" -# llmkwargs=Dict( -# :num_ctx => 32768, -# :temperature => 0.5, -# ) -# for attempt in 1:maxattempt -# if attempt > 1 -# println("\nYiemAgent generatechat() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# end - -# systemmsg = a.systemmsg * "\nP.S. $errornote\n" -# _prompt = -# [ -# Dict(:name => "system", :text => systemmsg), -# ] -# for i in a.chathistory -# tempdict = Dict{Symbol, String}() -# for j in keys(i) -# if j ∉ [:timestamp] -# tempdict[j] = i[j] -# end -# end -# _prompt = vcat(_prompt, tempdict) -# end - -# # put in model format -# _prompt = GeneralUtils.formatLLMtext(_prompt, a.llmFormatName) - -# # replace user and assistant with partner name -# prompt = replace(_prompt, "|>user"=>"|>$(converPartnerName)") -# prompt = replace(prompt, "|>assistant"=>"|>$(a.name)") - -# response = a.func[:text2textInstructLLM](prompt; llmkwargs=llmkwargs, senderId=a.id) -# response = replace(response, "<|im_start|>"=> "") -# response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) -# think, response = GeneralUtils.extractthink(response) - -# # check whether LLM just repeat the previous dialogue -# for msg in a.chathistory -# if msg[:text] == response -# errornote = "In your previous attempt, you repeated the previous dialogue. Please try again." -# println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") -# continue -# end -# end - -# return response -# end -# error("generatechat failed to generate a response") -# end - # modify it to work with customer object function generatechat(a::virtualcustomer; converPartnerName::Union{String, Nothing}=nothing, maxattempt=10, recentEventNum=10 - ) + ) + recent_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recentEventNum; includelatest=true) recentEventsDict = createEventsLog(a.memory[:events]; index=recent_ind) response = nothing # placeholder for show when error msg show up @@ -1979,21 +1927,12 @@ function generatechat(a::virtualcustomer; prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName) # add info prompt = prompt * context - + response = a.func[:text2textInstructLLM](prompt; llmkwargs=llmkwargs, senderId=a.id) response = replace(response, "<|im_start|>"=> "") response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) think, response = GeneralUtils.extractthink(response) - # check whether LLM just repeat the previous dialogue - for msg in a.chathistory - if msg[:text] == response - errornote = "In your previous attempt, you repeated the previous dialogue. Please try again." - println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - continue - end - end - # check whether response has all header detected_kw = GeneralUtils.detect_keyword(header, response) kwvalue = [i for i in values(detected_kw)] @@ -2024,7 +1963,19 @@ function generatechat(a::virtualcustomer; continue end - + # check whether LLM just repeat the previous dialogue + dublicate = false + for msg in a.chathistory + if msg[:text] == responsedict[:dialogue] + errornote = "In your previous attempt, you repeated the earlier dialogue. Please try again." + println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + dublicate = true + break + end + end + if dublicate + continue + end # println("\n$prompt", @__FILE__, ":", @__LINE__, " $(Dates.now())") # println("\n $response") From 5d552d96c4ed37ca2b84cec367e37ffdd0c057a1 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Tue, 17 Jun 2025 12:52:00 +0700 Subject: [PATCH 05/23] add example --- example/agent_chat_virtualCustomer.jl | 585 +++++++++++++++++ example/config.json | 76 +++ example/main.jl | 706 +++++++++++++++++++++ test/{test_1.jl => chatting_with_agent.jl} | 0 4 files changed, 1367 insertions(+) create mode 100644 example/agent_chat_virtualCustomer.jl create mode 100644 example/config.json create mode 100644 example/main.jl rename test/{test_1.jl => chatting_with_agent.jl} (100%) diff --git a/example/agent_chat_virtualCustomer.jl b/example/agent_chat_virtualCustomer.jl new file mode 100644 index 0000000..7b9a0e4 --- /dev/null +++ b/example/agent_chat_virtualCustomer.jl @@ -0,0 +1,585 @@ +using Revise +using JSON, JSON3, Dates, UUIDs, PrettyPrinting, LibPQ, Base64, DataFrames, DataStructures +using YiemAgent, GeneralUtils +using Base.Threads + +# ---------------------------------------------- 100 --------------------------------------------- # + + + +# load config +config = JSON3.read("/appfolder/app/dev/YiemAgent/test/config.json") +# config = copy(JSON3.read("../mountvolume/config.json")) + + +function executeSQL(sql::T) where {T<:AbstractString} + host = config[:externalservice][:wineDB][:host] + port = config[:externalservice][:wineDB][:port] + dbname = config[:externalservice][:wineDB][:dbname] + user = config[:externalservice][:wineDB][:user] + password = config[:externalservice][:wineDB][:password] + DBconnection = LibPQ.Connection("host=$host port=$port dbname=$dbname user=$user password=$password") + result = LibPQ.execute(DBconnection, sql) + close(DBconnection) + return result +end + +function executeSQLVectorDB(sql) + host = config[:externalservice][:SQLVectorDB][:host] + port = config[:externalservice][:SQLVectorDB][:port] + dbname = config[:externalservice][:SQLVectorDB][:dbname] + user = config[:externalservice][:SQLVectorDB][:user] + password = config[:externalservice][:SQLVectorDB][:password] + DBconnection = LibPQ.Connection("host=$host port=$port dbname=$dbname user=$user password=$password") + result = LibPQ.execute(DBconnection, sql) + close(DBconnection) + return result +end + +function text2textInstructLLM(prompt::String; maxattempt::Integer=10, modelsize::String="medium", + senderId=GeneralUtils.uuid4snakecase(), timeout=90, + llmkwargs=Dict( + :num_ctx => 32768, + :temperature => 0.5, + ) + ) + msgMeta = GeneralUtils.generate_msgMeta( + config[:externalservice][:loadbalancer][:mqtttopic]; + msgPurpose="inference", + senderName="yiemagent", + senderId=senderId, + receiverName="text2textinstruct_$modelsize", + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => Dict( + :text => prompt, + :kwargs => llmkwargs + ) + ) + + response = nothing + for attempts in 1:maxattempt + _response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; responsetimeout=timeout, responsemaxattempt=maxattempt) + payload = _response[:response] + if _response[:success] && payload[:text] !== nothing + response = _response[:response][:text] + break + else + println("\n attempt $attempts/$maxattempt failed ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + pprintln(outgoingMsg) + println(" attempt $attempts/$maxattempt failed ", @__FILE__, ":", @__LINE__, " $(Dates.now())\n") + sleep(3) + end + end + + return response +end + +# get text embedding from a LLM service +function getEmbedding(text::T) where {T<:AbstractString} + msgMeta = GeneralUtils.generate_msgMeta( + config[:externalservice][:loadbalancer][:mqtttopic]; + msgPurpose="embedding", + senderName="yiemagent", + senderId=sessionId, + receiverName="textembedding", + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => Dict( + :text => [text] # must be a vector of string + ) + ) + + response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; responsetimeout=120, responsemaxattempt=3) + embedding = response[:response][:embeddings] + return embedding +end + +function findSimilarTextFromVectorDB(text::T1, tablename::T2, embeddingColumnName::T3, + vectorDB::Function; limit::Integer=1 + )::DataFrame where {T1<:AbstractString, T2<:AbstractString, T3<:AbstractString} + # get embedding from LLM service + embedding = getEmbedding(text)[1] + # check whether there is close enough vector already store in vectorDB. if no, add, else skip + sql = """ + SELECT *, $embeddingColumnName <-> '$embedding' as distance + FROM $tablename + ORDER BY distance LIMIT $limit; + """ + response = vectorDB(sql) + df = DataFrame(response) + return df +end + +function similarSQLVectorDB(query; maxdistance::Integer=100) + tablename = "sqlllm_decision_repository" + # get embedding of the query + df = findSimilarTextFromVectorDB(query, tablename, + "function_input_embedding", executeSQLVectorDB) + # println(df[1, [:id, :function_output]]) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + # distance = 100 # CHANGE this is for testing only + if row != 0 && distance < maxdistance + # if there is usable SQL, return it. + output_b64 = df[1, :function_output_base64] # pick the closest match + output_str = String(base64decode(output_b64)) + rowid = df[1, :id] + println("\n~~~ found similar sql. row id $rowid, distance $distance ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + return (dict=output_str, distance=distance) + else + println("\n~~~ similar sql not found, max distance $maxdistance ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + return (dict=nothing, distance=nothing) + end +end + +function insertSQLVectorDB(query::T1, SQL::T2; maxdistance::Integer=3) where {T1<:AbstractString, T2<:AbstractString} + tablename = "sqlllm_decision_repository" + # get embedding of the query + # query = state[:thoughtHistory][:question] + df = findSimilarTextFromVectorDB(query, tablename, + "function_input_embedding", executeSQLVectorDB) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + if row == 0 || distance > maxdistance # no close enough SQL stored in the database + query_embedding = getEmbedding(query)[1] + query = replace(query, "'" => "") + sql_base64 = base64encode(SQL) + sql_ = replace(SQL, "'" => "") + + sql = """ + INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$query', '$sql_', '$sql_base64', '$query_embedding'); + """ + # println("\n~~~ added new decision to vectorDB ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + # println(sql) + _ = executeSQLVectorDB(sql) + end +end + + +function similarSommelierDecision(recentevents::T1; maxdistance::Integer=3 + )::Union{AbstractDict, Nothing} where {T1<:AbstractString} + tablename = "sommelier_decision_repository" + # find similar + println("\n~~~ search vectorDB for this: $recentevents ", @__FILE__, " ", @__LINE__) + df = findSimilarTextFromVectorDB(recentevents, tablename, + "function_input_embedding", executeSQLVectorDB) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + if row != 0 && distance < maxdistance + # if there is usable decision, return it. + rowid = df[1, :id] + println("\n~~~ found similar decision. row id $rowid, distance $distance ", @__FILE__, " ", @__LINE__) + output_b64 = df[1, :function_output_base64] # pick the closest match + _output_str = String(base64decode(output_b64)) + output = copy(JSON3.read(_output_str)) + return output + else + println("\n~~~ similar decision not found, max distance $maxdistance ", @__FILE__, " ", @__LINE__) + return nothing + end +end + + +function insertSommelierDecision(recentevents::T1, decision::T2; maxdistance::Integer=5 + ) where {T1<:AbstractString, T2<:AbstractDict} + tablename = "sommelier_decision_repository" + # find similar + df = findSimilarTextFromVectorDB(recentevents, tablename, + "function_input_embedding", executeSQLVectorDB) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + if row == 0 || distance > maxdistance # no close enough SQL stored in the database + recentevents_embedding = getEmbedding(recentevents)[1] + recentevents = replace(recentevents, "'" => "") + decision_json = JSON3.write(decision) + decision_base64 = base64encode(decision_json) + decision = replace(decision_json, "'" => "") + + sql = """ + INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$recentevents', '$decision', '$decision_base64', '$recentevents_embedding'); + """ + println("\n~~~ added new decision to vectorDB ", @__FILE__, " ", @__LINE__) + println(sql) + _ = executeSQLVectorDB(sql) + else + println("~~~ similar decision previously cached, distance $distance ", @__FILE__, " ", @__LINE__) + end +end + + +sessionId = GeneralUtils.uuid4snakecase() + +externalFunction = ( + getEmbedding=getEmbedding, + text2textInstructLLM=text2textInstructLLM, + executeSQL=executeSQL, + similarSQLVectorDB=similarSQLVectorDB, + insertSQLVectorDB=insertSQLVectorDB, + similarSommelierDecision=similarSommelierDecision, + insertSommelierDecision=insertSommelierDecision, + ) + + +# s = "full-bodied red wine, budget 1500 USD" +# r = YiemAgent.extractWineAttributes_1(agent, s) +# println(r) + + +# --------------------------- generating scenario and customer profile --------------------------- # + +function rolegenerator() + rolegenerator_systemmsg = + """ + Your role: + - You are a helpful assistant + Your mission: + - Create one random role of a potential customer of an internet wine store. + You must follow the following guidelines: + - the user only need the role, do not add your own words. + - the role should be detailed and realistic. + You should then respond to the user with: + Name: a name of the potential customer + Situation: a situation that the potential customer may be facing + Mission: a mission of the potential customer + Profile: a profile of the potential customer, including their age, gender, occupation, and other relevant information + You should only respond in format as described below: + Name: ... + Situation: ... + Mission: ... + Profile: ... + Additional_information: ... + + Here are some examples: + Name: Jimmy + Situation: + - Your relationship with your boss is not that good. You need to improve your relationship with your boss. + - Your boss's wedding anniversary is coming up. + - You are at a wine store and start talking with the store's sommelier. + Mission: + - Ask the sommelier to provide multiple wine options, and subsequently choose one option from the presented list. + Profile: + - You are a young professional in a big company. + - You are avid party goer + - You like beer. + - You know nothing about wine. + - You have a budget of 1500usd. + Additional_information: + - your boss like spicy food. + - your boss is a middle-aged man. + - your boss likes Australian wine. + + Name: Kate + Situation: + - Your husband asked you to get him a bottle of wine. He will gift the wine to his business client while dining at a German restaurant. + - Your husband is a business client and he will gift the wine to his business + - You are at a wine store and start talking with the store's sommelier. + Mission: + - Ask the sommelier to provide multiple wine options, and subsequently choose one option from the presented list. + Profile: + - You are a CEO in a startup company. + - You are a nerd + - You don't like alcohol. + - You have a budget of 150usd. + - You don't care about organic, sulfite, gluten-free, or sustainability certified wines + Additional_information: + - your husband like spicy food. + - your husband is a middle-aged man. + + Name: John + Situation: + - A local newspaper club wants to have a scoop about wine with local food in the U.S. + - You are at a wine store and start talking with the store's sommelier. + Mission: + - Ask the sommelier to provide multiple wine options, and subsequently choose one option from the presented list. + Profile: + - I'm a young guy. + - I prefer to express my ideas in a succinct and clear manner. + Additional_information: + - N/A + + Name: Jane + Situation: + - You have catering a dinner party with French cuisine. + - You want to serve wine with your guests. + - You are at a wine store and start talking with the store's sommelier. + Mission: + - Ask the sommelier to provide multiple wine options, and subsequently choose one option from the presented list. + Profile: + - You are a young French restaurant owner. + - You like dry, full-bodied red wine with high tannin + - You don't care about organic, sulfite, gluten-free, or sustainability certified wines. + - You have a budget of 200 usd. + Additional_information: + - N/A + + Let's begin! + """ + + header = ["Name:", "Situation:", "Mission:", "Profile:", "Additional_information:"] + dictkey = ["name", "situation", "mission", "profile", "additional_information"] + errornote = "N/A" + + for attempt in 1:10 + _prompt = + [ + Dict(:name => "system", :text => rolegenerator_systemmsg), + ] + prompt = GeneralUtils.formatLLMtext(_prompt, "qwen3") + + response = text2textInstructLLM(prompt) # generated role + response = GeneralUtils.deFormatLLMtext(response, "qwen3") + think, response = GeneralUtils.extractthink(response) + + # 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 rolegenerator() $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 rolegenerator() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + continue + end + + responsedict = GeneralUtils.textToDict(response, header; + dictKey=dictkey, symbolkey=true) + responsedict[:id] = GeneralUtils.uuid4snakecase() + + responsedict[:systemmsg] = + """ + You are role playing as a CUSTOMER of a wine store and you are currently talking with a sommelier of a wine store. + Your profile is as follows: + Situation: $(responsedict[:situation]) + Mission: $(responsedict[:mission]) + Profile: $(responsedict[:profile]) + Additional_information: $(responsedict[:additional_information]) + + You should follow the following guidelines: + - Focus on the lastest conversation + - Your like to be short and concise + - If you don't know an answer to sommelier's question, you should say: I don't know. + - If you think the store can't provide what you seek, you can leave. + + You should then respond to the user with: + Dialogue: what you want to say to the user + Role: Verify that the dialogue is intended for the customer of a wine store. Can be "yes" or "no" + You should only respond in format as described below: + Dialogue: ... + Role: ... + + Let's begin! + """ + + println("\nrolegenerator() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + println(responsedict) + return responsedict + end + error("ERROR rolegenerator() failed to generate customer role: ", @__FILE__, ":", @__LINE__, " $(Dates.now())") +end + + +# Define the external functions for the customer agent in named tuple format +customer_externalFunction = ( + text2textInstructLLM=text2textInstructLLM, + ) + + + + +function main() + agent = YiemAgent.sommelier( + externalFunction; + name="Jane", + id=sessionId, # agent instance id + retailername="Yiem", + llmFormatName="qwen3" + ) + + customerDict = rolegenerator() + customer = YiemAgent.virtualcustomer( + customer_externalFunction; + systemmsg=customerDict[:systemmsg], + name=customerDict[:name], + id=sessionId, # agent instance id + llmFormatName="qwen3" + ) + + # customer_chat = "hello" + + # YiemAgent.addNewMessage(customer, "assistant", customer_chat) + # # add user activity to events memory + # push!(customer.memory[:events], + # YiemAgent.eventdict(; + # event_description="the assistant talks to the user.", + # timestamp=Dates.now(), + # subject="assistant", + # actionname="CHATBOX", + # action_input=customer_chat, + # ) + # ) + # println("\ncustomer respond:\n $customer_chat") + agent_response = YiemAgent.conversation(agent; maximumMsg=50) + println("\nagent respond:\n $agent_response") + while true + customer_chat = nothing + while customer_chat === nothing + customer_response = YiemAgent.conversation(customer, Dict(:text=> agent_response); + converPartnerName=agent.name, + maximumMsg=50) + customer_response = GeneralUtils.deFormatLLMtext(customer_response, customer.llmFormatName) + customer_chat = customer_response + + #[WORKING] check whether customer response the same before + end + + println("\ncustomer respond:\n $customer_chat") + + agent_response = YiemAgent.conversation(agent; + userinput=Dict(:text=> customer_chat), + maximumMsg=50) + println("\nagent respond:\n $agent_response") + + if haskey(agent.memory[:events][end], :thought) + lastAssistantAction = agent.memory[:events][end][:thought][:actionname] + if lastAssistantAction == "ENDCONVERSATION" # store thoughtDict + + # save a.memory[:shortmem][:decisionlog] to disk using JSON3 + println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") + date = "$(Dates.now())" + date = replace(date, ':'=>'.') + filename = "agent_decision_log_$(date)_$(agent.id).json" + filepath = "/appfolder/mountvolume/appdata/log/$filename" + open(filepath, "w") do io + JSON3.pretty(io, agent.memory[:shortmem][:decisionlog]) + end + + # check how many file in /appfolder/mountvolume/appdata/log/ folder now + logfilesnumber = length(readdir("/appfolder/mountvolume/appdata/log/")) + println("\nCaching conversation process done. Total $logfilesnumber files in /appfolder/mountvolume/appdata/log/ folder now.\n") + break + end + end + end +end + +for i in 1:100 + main() + println("\n Round $i/100 done.") +end + +println("done") + +# prompt = +# """ +# <|im_start|>system +# You are a role playing agent acting as: +# Name: Emily +# Situation: - Emily is planning her upcoming birthday party and wants to make it extra special. She has invited close friends and family, and she's looking for a unique wine that will impress them. +# Mission: - Emily needs to find a rare and high-quality wine that matches the theme of her party, which is a mix of classic and modern flavors. She also wants to ensure that the wine is not too expensive so that it won't break her budget. +# Profile: - Emily is in her late 20s, works as a marketing executive for a tech company, and has a passion for trying new things. She's organized and detail-oriented but can be spontaneous when it comes to planning events. +# Additional_information: - Emily loves experimenting with different types of food and wine pairings. + +# Your are currently talking with a sommelier. + +# You should follow the following guidelines: +# - Focus on the lastest conversation +# - If you satisfy with the sommelier's recommendation for bottle of wine(s), you should say: Thanks for you help. I will buy the wine you recommended. +# - If you don't satisfy with the sommelier's questions or can't get a good wine recommendation, you can continue the conversation. + +# Let's begin! + +# <|im_end|> +# <|im_start|>Jane +# Hello! Welcome to Yiem's Wine Store. I'm Jane, your friendly sommelier. How can I assist you today? What type of wine are you in the mood for, and is there a special occasion or event on your mind? +# <|im_end|> +# <|im_start|>Emily +# Hi Jane! Thank you so much for welcoming me. For my birthday party, I'm looking for something that combines classic and modern flavors. It's a mix of guests who enjoy both traditional tastes and more contemporary ones. Also, I want to make sure it won't break the bank. Any suggestions? +# <|im_end|> +# <|im_start|>Jane +# Thank you for sharing your preferences, Jane! To better assist you, could you please let me know if there are any specific characteristics of wine you're looking for, such as tannin, sweetness, intensity, or acidity? Additionally, do you have any food items in mind that this wine should pair well with? +# <|im_end|> +# <|im_start|>Emily +# """ + +# llmkwargs=Dict( +# :num_ctx => 32768, +# :temperature => 0.3, +# ) +# r = text2textInstructLLM(prompt, llmkwargs=llmkwargs) +# println(r) +# println(555) + +# response = YiemAgent.conversation(agent, Dict(:text=> "I want to get a French red wine under 100.")) + + +# while true +# println("your respond: ") +# user_answer = readline() +# response = YiemAgent.conversation(agent, Dict(:text=> user_answer)) +# println("\n$response") +# end + + + + + + + + + + + + +# """ +# Hello + +# I would like to get a bottle of wine for my boss but I don't know much about wine. Can you help me? + +# well actually, my boss is going to offer the wine to his client as a gift in a business meeting. All I know is his client like spicy food and French wine. I have a budget about 1000. + +# """ + +# input = "French wine, bordeaux, under USD100, pairs with spicy food" +# r = YiemAgent.extractWineAttributes_1(a, input) + +# inventory_order = "French Syrah, Viognier, full bodied, under 100" +# r = YiemAgent.extractWineAttributes_2(a, inventory_order) +# pprintln(r) + + +# cron job +# @reboot sleep 50 && nvidia-smi -pm 1 +# @reboot sleep 51 && nvidia-smi -i 0 -pl 150 +# @reboot sleep 52 && nvidia-smi -i 1 -pl 150 +# @reboot sleep 53 && nvidia-smi -i 2 -pl 150 +# @reboot sleep 54 && nvidia-smi -i 3 -pl 150 + +# @reboot sleep 55 && julia -t 2 /home/ton/work/restartContainer/main.jl + +# using GeneralUtils +# msgMeta = GeneralUtils.generate_msgMeta( +# "/tonpc_containerServices", +# senderName= "somename", +# senderId= "1230", +# mqttBrokerAddress= "mqtt.yiem.cc", +# mqttBrokerPort= 1883, +# ) +# outgoingMsg = Dict( +# :msgMeta=> msgMeta, +# :payload=> "docker container restart playground-app", +# ) +# GeneralUtils.sendMqttMsg(outgoingMsg) + diff --git a/example/config.json b/example/config.json new file mode 100644 index 0000000..13ca00f --- /dev/null +++ b/example/config.json @@ -0,0 +1,76 @@ +{ + "mqttServerInfo": { + "description": "mqtt server info", + "port": 1883, + "broker": "mqtt.yiem.cc" + }, + "testingOrProduction": { + "value": "testing", + "description": "agent status, couldbe testing or production" + }, + "agentid": { + "value": "2b74b87a-5413-4fe2-a4d3-405891051680", + "description": "a unique id for this agent" + }, + "agentCentralConfigTopic": { + "mqtttopic": "/yiem_branch_1/agent/sommelier/backend/config/api/v1.1", + "description": "a central agent server's topic to get this agent config" + }, + "servicetopic": { + "mqtttopic": [ + "/yiem/hq/agent/sommelier/backend/prompt/api_v1/testing" + ], + "description": "a topic this agent are waiting for service request" + }, + "role": { + "value": "sommelier", + "description": "agent role" + }, + "organization": { + "value": "yiem_branch_1", + "description": "organization name" + }, + "externalservice": { + "loadbalancer": { + "mqtttopic": "/loadbalancer/requestingservice", + "description": "text to text service with instruct LLM" + }, + "text2textinstruct": { + "mqtttopic": "/loadbalancer/requestingservice", + "description": "text to text service with instruct LLM", + "llminfo": { + "name": "llama3instruct" + } + }, + "virtualWineCustomer_1": { + "mqtttopic": "/virtualenvironment/winecustomer", + "description": "text to text service with instruct LLM that act as wine customer", + "llminfo": { + "name": "llama3instruct" + } + }, + "text2textchat": { + "mqtttopic": "/loadbalancer/requestingservice", + "description": "text to text service with instruct LLM", + "llminfo": { + "name": "llama3instruct" + } + }, + "wineDB" : { + "description": "A wine database connection info for LibPQ client", + "host": "192.168.88.12", + "port": 10201, + "dbname": "wineDB", + "user": "yiemtechnologies", + "password": "yiemtechnologies@Postgres_0.0" + }, + "SQLVectorDB" : { + "description": "A wine database connection info for LibPQ client", + "host": "192.168.88.12", + "port": 10203, + "dbname": "SQLVectorDB", + "user": "yiemtechnologies", + "password": "yiemtechnologies@Postgres_0.0" + } + } +} \ No newline at end of file diff --git a/example/main.jl b/example/main.jl new file mode 100644 index 0000000..7e5d8c9 --- /dev/null +++ b/example/main.jl @@ -0,0 +1,706 @@ +using JSON, JSON3, Dates, UUIDs, PrettyPrinting, LibPQ, Base64, DataFrames, DataStructures +using YiemAgent, GeneralUtils +using Base.Threads + +# ---------------------------------------------- 100 --------------------------------------------- # + + +""" Expected incomming MQTT message format for this service: + { + "msgMeta": { + "msgPurpose": "updateStatus", + "requestresponse": "request", + "timestamp": "2024-03-29T05:8:48.362", + "replyToMsgId": null, + "receiverId": null, + "getpost": "get", + "msgId": "e5c09bd8-7100-4e4e-bb43-05bee589a22c", + "acknowledgestatus": null, + "sendTopic": "/agent/wine/backend/chat/api/v1/prompt", + "receiverName": "agent-wine-backend", + "replyTopic": "/agent/wine/frontend/chat/api/v1/txt/receive", + "senderName": "agent-wine-frontend-chat", + "senderId": "0938a757-e0ee-40a9-8355-5e24906a87cd" + }, + "payload" : { + "text": "hello" + } + + } +""" + + + + + +# load config +config = copy(JSON3.read("../mountvolume/config/config.json")) + +""" Instantiate an agent. One need to specify startmessage and one of gpu location info, + Mqtt or Rest. start message must be comply with GeneralUtils's message format + + Arguments\n + ----- + channel::Channel + communication channel + sessionId::String + sesstion ID of the agent + agentName::String + Name of the agent + mqttBroker::String + mqtt broker e.g. "tcp://127.0.0.1:1883" + agentConfigTopic::String + main communication topic for an agent to ask for config + timeout::Int64 + inactivity timeout in minutes. If timeout is reached, an agent will be terminated. + + Return\n + ----- + a task represent an agent + + Example\n + ----- + ```jldoctest + julia> using YiemAgent, GeneralUtils + julia> msg = GeneralUtils.generate_msgMeta("/agent") + julia> incoming_msg = msg # assuming 1st msg was sent from other app + julia> agentConfigTopic = "/agent/wine/backend/config" + julia> task = runAgentInstance(incoming_msg, mqttBroker, agentConfigTopic, 60) + ``` + + TODO\n + ----- + [] update docstringLAMA_CONTEXT_LENGTH=40960 since the default size is 2048 as you can see in your debug log: + [] change how to get result of YiemAgent from let YiemAgent send msg directly to frontend, + to + response = YiemAgent.conversation() + then send response to frontend + + Signature\n + ----- +""" +function runAgentInstance( + receiveUserMsgChannel::Channel, + outputchannel::Channel, + sessionId::String, + config::Dict, + timeout::Int64, + ) + + function executeSQL(sql::T) where {T<:AbstractString} + host = config[:externalservice][:wineDB][:host] + port = config[:externalservice][:wineDB][:port] + dbname = config[:externalservice][:wineDB][:dbname] + user = config[:externalservice][:wineDB][:user] + password = config[:externalservice][:wineDB][:password] + DBconnection = LibPQ.Connection("host=$host port=$port dbname=$dbname user=$user password=$password") + result = LibPQ.execute(DBconnection, sql) + close(DBconnection) + return result + end + + function executeSQLVectorDB(sql) + host = config[:externalservice][:SQLVectorDB][:host] + port = config[:externalservice][:SQLVectorDB][:port] + dbname = config[:externalservice][:SQLVectorDB][:dbname] + user = config[:externalservice][:SQLVectorDB][:user] + password = config[:externalservice][:SQLVectorDB][:password] + DBconnection = LibPQ.Connection("host=$host port=$port dbname=$dbname user=$user password=$password") + result = LibPQ.execute(DBconnection, sql) + close(DBconnection) + return result + end + + function text2textInstructLLM(prompt::String; maxattempt::Integer=3, modelsize::String="medium", + senderId=GeneralUtils.uuid4snakecase(), timeout=180, + llmkwargs=Dict( + :num_ctx => 32768, + :temperature => 0.5, + )) + msgMeta = GeneralUtils.generate_msgMeta( + config[:externalservice][:loadbalancer][:mqtttopic]; + msgPurpose="inference", + senderName="yiemagent", + senderId=senderId, + receiverName="text2textinstruct_$modelsize", + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => Dict( + :text => prompt, + :kwargs => llmkwargs + ) + ) + + response = nothing + for attempts in 1:maxattempt + _response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=timeout, maxattempt=maxattempt) + payload = _response[:response] + if _response[:success] && payload[:text] !== nothing + response = _response[:response][:text] + break + else + println("\n attempt $attempts/$maxattempt failed ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + pprintln(outgoingMsg) + println(" attempt $attempts/$maxattempt failed ", @__FILE__, ":", @__LINE__, " $(Dates.now())\n") + sleep(3) + end + end + + return response + end + + # get text embedding from a LLM service + function getEmbedding(text::T) where {T<:AbstractString} + msgMeta = GeneralUtils.generate_msgMeta( + config[:externalservice][:loadbalancer][:mqtttopic]; + msgPurpose="embedding", + senderName="yiemagent", + senderId=sessionId, + receiverName="textembedding", + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => Dict( + :text => [text] # must be a vector of string + ) + ) + + response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120, maxattempt=3) + embedding = response[:response][:embeddings] + return embedding + end + + function findSimilarTextFromVectorDB(text::T1, tablename::T2, embeddingColumnName::T3, + vectorDB::Function; limit::Integer=1 + )::DataFrame where {T1<:AbstractString, T2<:AbstractString, T3<:AbstractString} + # get embedding from LLM service + embedding = getEmbedding(text)[1] + # check whether there is close enough vector already store in vectorDB. if no, add, else skip + sql = """ + SELECT *, $embeddingColumnName <-> '$embedding' as distance + FROM $tablename + ORDER BY distance LIMIT $limit; + """ + response = vectorDB(sql) + df = DataFrame(response) + return df + end + + function similarSQLVectorDB(query; maxdistance::Integer=100) + tablename = "sqlllm_decision_repository" + # get embedding of the query + df = findSimilarTextFromVectorDB(query, tablename, + "function_input_embedding", executeSQLVectorDB) + # println(df[1, [:id, :function_output]]) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + # distance = 100 # CHANGE this is for testing only + if row != 0 && distance < maxdistance + # if there is usable SQL, return it. + output_b64 = df[1, :function_output_base64] # pick the closest match + output_str = String(base64decode(output_b64)) + rowid = df[1, :id] + println("\n~~~ found similar sql. row id $rowid, distance $distance ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + return (dict=output_str, distance=distance) + else + println("\n~~~ similar sql not found, max distance $maxdistance ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + return (dict=nothing, distance=nothing) + end + end + + function insertSQLVectorDB(query::T1, SQL::T2; maxdistance::Integer=3) where {T1<:AbstractString, T2<:AbstractString} + tablename = "sqlllm_decision_repository" + # get embedding of the query + # query = state[:thoughtHistory][:question] + df = findSimilarTextFromVectorDB(query, tablename, + "function_input_embedding", executeSQLVectorDB) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + if row == 0 || distance > maxdistance # no close enough SQL stored in the database + query_embedding = getEmbedding(query)[1] + query = replace(query, "'" => "") + sql_base64 = base64encode(SQL) + sql_ = replace(SQL, "'" => "") + + sql = """ + INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$query', '$sql_', '$sql_base64', '$query_embedding'); + """ + # println("\n~~~ added new decision to vectorDB ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + # println(sql) + _ = executeSQLVectorDB(sql) + end + end + + + function similarSommelierDecision(recentevents::T1; maxdistance::Integer=3 + )::Union{AbstractDict, Nothing} where {T1<:AbstractString} + tablename = "sommelier_decision_repository" + # find similar + println("\n~~~ search vectorDB for this: $recentevents ", @__FILE__, " ", @__LINE__) + df = findSimilarTextFromVectorDB(recentevents, tablename, + "function_input_embedding", executeSQLVectorDB) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + if row != 0 && distance < maxdistance + # if there is usable decision, return it. + rowid = df[1, :id] + println("\n~~~ found similar decision. row id $rowid, distance $distance ", @__FILE__, " ", @__LINE__) + output_b64 = df[1, :function_output_base64] # pick the closest match + _output_str = String(base64decode(output_b64)) + output = copy(JSON3.read(_output_str)) + return output + else + println("\n~~~ similar decision not found, max distance $maxdistance ", @__FILE__, " ", @__LINE__) + return nothing + end + end + + + function insertSommelierDecision(recentevents::T1, decision::T2; maxdistance::Integer=5 + ) where {T1<:AbstractString, T2<:AbstractDict} + tablename = "sommelier_decision_repository" + # find similar + df = findSimilarTextFromVectorDB(recentevents, tablename, + "function_input_embedding", executeSQLVectorDB) + row, col = size(df) + distance = row == 0 ? Inf : df[1, :distance] + if row == 0 || distance > maxdistance # no close enough SQL stored in the database + recentevents_embedding = getEmbedding(recentevents)[1] + recentevents = replace(recentevents, "'" => "") + decision_json = JSON3.write(decision) + decision_base64 = base64encode(decision_json) + decision = replace(decision_json, "'" => "") + + sql = + """ + INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$recentevents', '$decision', '$decision_base64', '$recentevents_embedding'); + """ + println("\n~~~ added new decision to vectorDB ", @__FILE__, " ", @__LINE__) + println(sql) + _ = executeSQLVectorDB(sql) + else + println("~~~ similar decision previously cached, distance $distance ", @__FILE__, " ", @__LINE__) + end + end + + # keepaliveChannel_2::Channel{Dict} = Channel{Dict}(8) + latestUserMsgTimeStamp::DateTime = Dates.now() + + externalFunction = ( + getEmbedding=getEmbedding, + text2textInstructLLM=text2textInstructLLM, + executeSQL=executeSQL, + similarSQLVectorDB=similarSQLVectorDB, + insertSQLVectorDB=insertSQLVectorDB, + similarSommelierDecision=similarSommelierDecision, + insertSommelierDecision=insertSommelierDecision, + ) + + agent = YiemAgent.sommelier( + externalFunction; + name="Jane", + id=sessionId, # agent instance id + retailername="Yiem", + llmFormatName="qwen3" + ) + + # user chat loop + while true + # check for new user message + if isready(receiveUserMsgChannel) + incomingMsg = take!(receiveUserMsgChannel) + incoming_msgMeta = incomingMsg[:msgMeta] + incomingPayload = incomingMsg[:payload] + latestUserMsgTimeStamp = Dates.now() + + # make sure the message has :text key because YiemAgent use this key for incoming user msg + if haskey(incomingPayload, :text) + # skip, msg already has correct key name + elseif haskey(incomingPayload, :txt) + # change key name to text + incomingPayload[:text] = incomingPayload[:txt] + else + error("\n no :txt or :text key in the message.") + end + + # reset agent + if occursin("newtopic", incomingPayload[:text]) || + occursin("Newtopic", incomingPayload[:text]) || + occursin("New topic", incomingPayload[:text]) || + occursin("new topic", incomingPayload[:text]) + # YiemAgent.clearhistory(agent) + + agent = YiemAgent.sommelier( + externalFunction; + name="Janie", + id=sessionId, # agent instance id + retailername="Yiem", + ) + + # sending msg back to sender i.e. LINE + msgMeta = GeneralUtils.generate_msgMeta( + incomingMsg[:msgMeta][:replyTopic]; + senderName="wine_assistant_backend", + senderId=sessionId, + replyToMsgId=incomingMsg[:msgMeta][:msgId], + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => Dict( + :alias => agent.name, # will be shown in frontend as agent name + :text => "Okay. What shall we talk about?" + ) + ) + _ = GeneralUtils.sendMqttMsg(outgoingMsg) + println("--> outgoingMsg ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + pprintln(outgoingMsg) + else + usermsg = incomingPayload + + if incoming_msgMeta[:msgPurpose] == "initialize" + println("\n-- Initializing... ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + end + + # send prompt + result = YiemAgent.conversation(agent; + userinput=usermsg, + maximumMsg=50) + # Ken's bot use [br] for newline character '\n' + # result = replace(result, '\n'=>"[br]") + + if incoming_msgMeta[:msgPurpose] == "initialize" + println("\n-- Initialized. Ready! waiting for request at:\n$(config[:servicetopic][:mqtttopic]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + continue + end + + msgMeta = GeneralUtils.generate_msgMeta( + incomingMsg[:msgMeta][:replyTopic]; + senderName="wine_assistant_backend", + senderId=string(uuid4()), + replyToMsgId=incomingMsg[:msgMeta][:msgId], + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => Dict( + :alias => agent.name, # will be shown in frontend as agent name + :text => result + ) + ) + _ = GeneralUtils.sendMqttMsg(outgoingMsg) + println("\n--> outgoingMsg ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + pprintln(outgoingMsg) + + + # jpg_as_juliaStr = nothing + # prompt = nothing + + # if haskey(payload, "img") + # url_or_base64 = payload["img"] + + # if startswith(url_or_base64, "http") + # # img in http + # julia_rgb_img, cv2_bgr_img = ImageUtils.url_to_cv2_image(url_or_base64) + # _, buffer = cv2.imencode(".jpg", cv2_bgr_img) + # jpg_as_pyStr = base64.b64encode(buffer).decode("utf-8") + # jpg_as_juliaStr = pyconvert(String, jpg_as_pyStr) + # else + # # img in base64 + # cv2_bgr_img = payload["img"] + # jpg_as_juliaStr = pyconvert(String, jpg_as_pyStr) + # end + # end + + end + else + # println("\n no msg") + end + + if haskey(agent.memory[:events][end], :thought) + lastAssistantAction = agent.memory[:events][end][:thought][:action_name] + if lastAssistantAction == "ENDCONVERSATION" # store thoughtDict + + # save a.memory[:shortmem][:decisionlog] to disk using JSON3 + println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") + filename = "agent_decision_log_$(Dates.now())_$(agent.id).json" + filepath = "/appfolder/app/log/$filename" + open(filepath, "w") do io + JSON3.pretty(io, agent.memory[:shortmem][:decisionlog]) + end + + # for (i, event) in enumerate(agent.memory[:events]) + # if event[:subject] == "assistant" + # # create timeline of the last 3 conversation except the last one. + # # The former will be used as caching key and the latter will be the caching target + # # in vector database + # all_recapkeys = keys(agent.memory[:recap]) #[TESTING] recap as caching + # all_recapkeys_vec = [r for r in all_recapkeys] # convert to a vector + + # # select from 1 to 2nd-to-lase event (i.e. excluding the latest which is assistant's response) + # _recapkeys_vec = all_recapkeys_vec[1:i-1] + + # # select only previous 3 recaps + # recapkeys_vec = + # if length(_recapkeys_vec) <= 3 # 1st message is a user's hello msg + # _recapkeys_vec # choose all + # else + # _recapkeys_vec[end-2:end] + # end + # #[PENDING] if there is specific data such as number, donot store in database + # tempmem = DataStructures.OrderedDict() + # for k in recapkeys_vec + # tempmem[k] = agent.memory[:recap][k] + # end + + # recap = GeneralUtils.dictToString_noKey(tempmem) + # thoughtDict = agent.memory[:events][i][:thought] # latest assistant thoughtDict + # insertSommelierDecision(recap, thoughtDict) + # else + # # skip + # end + # end + println("\nCaching conversation process done") + break + end + end + + # self terminate if too long inactivity + timediff = GeneralUtils.timedifference(latestUserMsgTimeStamp, Dates.now(), "minutes") + if timediff > timeout + + result = Dict(:exitreason => "timeout", :timestamp => Dates.now()) + put!(outputchannel, result) + println("Agent ID $(agent.id) timeout has been reached $timediff/$timeout minutes Send delete session msg ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + + # send "delete session" message to inform the main loop that this session can be deleted + sendto = + if typeof(config[:servicetopic][:mqtttopic]) <: Array + config[:servicetopic][:mqtttopic][1] + else + config[:servicetopic][:mqtttopic] + end + + msgMeta = GeneralUtils.generate_msgMeta( + sendto; + senderName="session", + senderId=sessionId, + msgPurpose="delete session", + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => nothing + ) + _ = GeneralUtils.sendMqttMsg(outgoingMsg) + + try disconnect(agent.mqttClient) catch end + break + end + sleep(1) # allowing on_msg_2, asyncmove above and other process to run + end +end + +sessionDict = Dict{String,Any}() +incomingMsgChannel = (ch1=Channel(8),) # store msg that coming into servicetopic +# incommingInternalMsg = [] # st ore msg that coming into servicetopic internal management +keepaliveChannel::Channel{Dict} = Channel{Dict}(8) + +# Define the callback for receiving messages. +function onMsgCallback_1(topic, payload) + jobj = JSON3.read(String(payload)) + incomingMqttMsg = copy(jobj) # convert json object into julia dictionary recursively + + if occursin("keepalive", topic) + put!(keepaliveChannel, incomingMqttMsg) + else + put!(incomingMsgChannel[:ch1], incomingMqttMsg) + end +end + +mqttInstance = GeneralUtils.mqttClientInstance_v2( + config[:mqttServerInfo][:broker], + config[:servicetopic][:mqtttopic], + incomingMsgChannel, + keepaliveChannel, + onMsgCallback_1 +) + +# ------------------------------------------------------------------------------------------------ # +# this service main loop # +# ------------------------------------------------------------------------------------------------ # + +function main() + sessiontimeout = 1 * 1 * 60 # timeout in minute for each instance (day * hour * minute) + initializing = false + while true + # check if mqtt connection is still up + _ = GeneralUtils.checkMqttConnection!(mqttInstance; keepaliveCheckInterval=30) + + # initialize session 0 + if initializing == false # send init msg + sendto = + if typeof(config[:servicetopic][:mqtttopic]) <: Array + config[:servicetopic][:mqtttopic][1] + else + config[:servicetopic][:mqtttopic] + end + + msgMeta = GeneralUtils.generate_msgMeta( + sendto; + msgPurpose="initialize", + senderName="initializer", + senderId="0", + msgId= "initMsg", + replyTopic=sendto, + mqttBrokerAddress=config[:mqttServerInfo][:broker], + mqttBrokerPort=config[:mqttServerInfo][:port], + ) + + outgoingMsg = Dict( + :msgMeta => msgMeta, + :payload => Dict( # will be shown in frontend as agent name + :text => "Do you have full-bodied red wines under 100 USD. I don't have any other preferences." + ) + ) + _ = GeneralUtils.sendMqttMsg(outgoingMsg) + initializing = true + println("\n--> Initializing msg sent ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + end + + # check for new message + if !isempty(incomingMsgChannel[:ch1]) + msg = popfirst!(incomingMsgChannel[:ch1]) + println("\n<-- incomingMsg ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + pprintln(msg) + + # @spawn new runAgentInstance and store it in sessionDict + # use agent's frontend id because 1 backend agent per 1 frontend session + sessionId = msg[:msgMeta][:senderId] + sessionId = replace(sessionId, "-" => "_") # julia can't use "-" in a dict key + + # check for delete session msg + if msg[:msgMeta][:msgPurpose] == "delete session" + delete!(sessionDict, sessionId) + println("sessionId $(sessionId) has been terminated ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + + # no session yet, create new session + elseif sessionId ∉ keys(sessionDict) + inputch = Channel{Dict}(8) + outputch = Channel{Dict}(8) + + process = @spawn runAgentInstance(inputch, outputch, sessionId, config, sessiontimeout) + # process = runAgentInstance(inputch, outputch, sessionId, config, sessiontimeout) #XXX use spawn version + + println("\ninstantiate agent success ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + + # call runAgentInstance() and store it in sessionDict to be able to check on it later + sessionDict[sessionId] = Dict( + :inputchannel => inputch, + :outputchannel => outputch, + :process => process, + ) + put!(sessionDict[sessionId][:inputchannel], msg) + # ongoing session + else + println("sessionId $(sessionId) existing session ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + put!(sessionDict[sessionId][:inputchannel], msg) + end + end + + # sleep is needed because MQTTClient use async. "while true" loop leave no + # chance for control to switch to on_msg() + sleep(1) + end +end + +main() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/test_1.jl b/test/chatting_with_agent.jl similarity index 100% rename from test/test_1.jl rename to test/chatting_with_agent.jl From f2b56640cc7ab90a67528fe4ad0282f2e182de55 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Tue, 17 Jun 2025 12:53:32 +0700 Subject: [PATCH 06/23] update --- src/interface.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface.jl b/src/interface.jl index 713c65c..a5d6bf4 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -208,7 +208,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 2) actionname: (Typically corresponds to the execution of the first step in your plan) Can be one of the available tool name 3) actioninput: The input to the action you are about to perform according to your plan. - + { "plan": "...", "actionname": "...", From bad2ca35ed59fed1a3c956a159c83a893e15ad11 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Mon, 14 Jul 2025 08:54:51 +0700 Subject: [PATCH 07/23] update --- Manifest.toml | 230 +++++++++++++++++++++++++++++------------------ Project.toml | 2 + src/interface.jl | 69 +------------- src/type.jl | 7 +- 4 files changed, 152 insertions(+), 156 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index bc87211..6a3c541 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,8 +1,8 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.11.4" +julia_version = "1.11.5" manifest_format = "2.0" -project_hash = "cb7f3c57318e927e8ac4dc2dea9acdcace566ed1" +project_hash = "9896e9d54d6cf4e2c3ae871a42f43f2f212ab1c9" [[deps.AliasTables]] deps = ["PtrArrays", "Random"] @@ -27,6 +27,11 @@ git-tree-sha1 = "0691e34b3bb8be9307330f88d1a3c3f25466c24d" uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" version = "0.1.9" +[[deps.BufferedStreams]] +git-tree-sha1 = "6863c5b7fc997eadcabdbaf6c5f201dc30032643" +uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d" +version = "1.2.2" + [[deps.CEnum]] git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" @@ -40,26 +45,37 @@ version = "0.10.15" [[deps.CodeTracking]] deps = ["InteractiveUtils", "UUIDs"] -git-tree-sha1 = "7eee164f122511d3e4e1ebadb7956939ea7e1c77" +git-tree-sha1 = "062c5e1a5bf6ada13db96a4ae4749a4c2234f521" uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" -version = "1.3.6" +version = "1.3.9" + +[[deps.CodecBase]] +deps = ["TranscodingStreams"] +git-tree-sha1 = "40956acdbef3d8c7cc38cba42b56034af8f8581a" +uuid = "6c391c72-fb7b-5838-ba82-7cfb1bcfecbf" +version = "0.3.4" [[deps.CodecZlib]] deps = ["TranscodingStreams", "Zlib_jll"] -git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759" +git-tree-sha1 = "962834c22b66e32aa10f7611c08c8ca4e20749a9" uuid = "944b1d66-785c-5afd-91f1-9de20f533193" -version = "0.7.6" +version = "0.7.8" [[deps.Compat]] deps = ["TOML", "UUIDs"] -git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215" +git-tree-sha1 = "3a3dfb30697e96a440e4149c8c51bf32f818c0f3" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.16.0" +version = "4.17.0" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] CompatLinearAlgebraExt = "LinearAlgebra" +[[deps.Compiler]] +git-tree-sha1 = "382d79bfe72a406294faca39ef0c3cef6e6ce1f1" +uuid = "807dbc54-b67e-4c79-8afb-eafe4df6f2e1" +version = "0.1.1" + [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" @@ -67,9 +83,9 @@ version = "1.1.1+0" [[deps.ConcurrentUtilities]] deps = ["Serialization", "Sockets"] -git-tree-sha1 = "ea32b83ca4fefa1768dc84e504cc0a94fb1ab8d1" +git-tree-sha1 = "d9d26935a0bcffc87d2613ce14c527c99fc543fd" uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" -version = "2.4.2" +version = "2.5.0" [[deps.Crayons]] git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" @@ -94,9 +110,9 @@ version = "1.7.0" [[deps.DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82" +git-tree-sha1 = "4e1fe97fdaed23e9dc21d4d664bea76b65fc50a0" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.20" +version = "0.18.22" [[deps.DataValueInterfaces]] git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" @@ -120,9 +136,9 @@ version = "1.11.0" [[deps.Distributions]] deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] -git-tree-sha1 = "0b4190661e8a4e51a842070e7dd4fae440ddb7f4" +git-tree-sha1 = "3e6d038b77f22791b8e3472b7c633acea1ecac06" uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" -version = "0.25.118" +version = "0.25.120" [deps.Distributions.extensions] DistributionsChainRulesCoreExt = "ChainRulesCore" @@ -135,10 +151,9 @@ version = "0.25.118" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[deps.DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +git-tree-sha1 = "7442a5dfe1ebb773c29cc2962a8980f47221d76c" uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.9.3" +version = "0.9.5" [[deps.Downloads]] deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] @@ -199,16 +214,21 @@ uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" version = "1.11.0" [[deps.GeneralUtils]] -deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON3", "MQTTClient", "PrettyPrinting", "Random", "SHA", "UUIDs"] +deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON3", "MQTTClient", "NATS", "PrettyPrinting", "Random", "SHA", "UUIDs"] path = "/appfolder/app/dev/GeneralUtils" uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe" -version = "0.2.3" +version = "0.3.1" [[deps.HTTP]] deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "PrecompileTools", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] -git-tree-sha1 = "6c22309e9a356ac1ebc5c8a217045f9bae6f8d9a" +git-tree-sha1 = "ed5e9c58612c4e081aecdb6e1a479e18462e041e" uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" -version = "1.10.13" +version = "1.10.17" + +[[deps.HashArrayMappedTries]] +git-tree-sha1 = "2eaa69a7cab70a52b9687c8bf950a5a93ec895ae" +uuid = "076d061b-32b6-4027-95e0-9a2c6f6d7e74" +version = "0.2.0" [[deps.HypergeometricFunctions]] deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] @@ -217,10 +237,10 @@ uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" version = "0.3.28" [[deps.ICU_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "20b6765a3016e1fca0c9c93c80d50061b94218b7" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "b3d8be712fbf9237935bde0ce9b5a736ae38fc34" uuid = "a51ab1cf-af8e-5615-a023-bc2c838bba6b" -version = "69.1.0+0" +version = "76.2.0+0" [[deps.Infinity]] deps = ["Dates", "Random", "Requires"] @@ -229,9 +249,9 @@ uuid = "a303e19e-6eb4-11e9-3b09-cd9505f79100" version = "0.2.4" [[deps.InlineStrings]] -git-tree-sha1 = "45521d31238e87ee9f9732561bfee12d4eebd52d" +git-tree-sha1 = "8594fac023c5ce1ef78260f24d1ad18b4327b420" uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" -version = "1.4.2" +version = "1.4.4" [deps.InlineStrings.extensions] ArrowTypesExt = "ArrowTypes" @@ -253,9 +273,9 @@ uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5" version = "1.10.0" [[deps.InvertedIndices]] -git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038" +git-tree-sha1 = "6da3c4316095de0f5ee2ebd875df8721e7e0bdbe" uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" -version = "1.3.0" +version = "1.3.1" [[deps.IrrationalConstants]] git-tree-sha1 = "e2222959fbc6c19554dc15174c81bf7bf3aa691c" @@ -274,15 +294,15 @@ version = "1.0.0" [[deps.JLLWrappers]] deps = ["Artifacts", "Preferences"] -git-tree-sha1 = "be3dc50a92e5a386872a493a10050136d4703f9b" +git-tree-sha1 = "a007feb38b422fbdab534406aeca1b86823cb4d6" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.6.1" +version = "1.7.0" [[deps.JSON3]] deps = ["Dates", "Mmap", "Parsers", "PrecompileTools", "StructTypes", "UUIDs"] -git-tree-sha1 = "1d322381ef7b087548321d3f878cb4c9bd8f8f9b" +git-tree-sha1 = "411eccfe8aba0814ffa0fdf4860913ed09c34975" uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -version = "1.14.1" +version = "1.14.3" [deps.JSON3.extensions] JSON3ArrowExt = ["ArrowTypes"] @@ -292,15 +312,15 @@ version = "1.14.1" [[deps.JuliaInterpreter]] deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"] -git-tree-sha1 = "10da5154188682e5c0726823c2b5125957ec3778" +git-tree-sha1 = "6ac9e4acc417a5b534ace12690bc6973c25b862f" uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a" -version = "0.9.38" +version = "0.10.3" [[deps.Kerberos_krb5_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "60274b4ab38e8d1248216fe6b6ace75ae09b0502" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "0f2899fdadaab4b8f57db558ba21bdb4fb52f1f0" uuid = "b39eb1a6-c29a-53d7-8c32-632cd16f18da" -version = "1.19.3+0" +version = "1.21.3+0" [[deps.LLMMCTS]] deps = ["GeneralUtils", "JSON3", "PrettyPrinting"] @@ -346,9 +366,9 @@ version = "1.18.0" [[deps.LibPQ_jll]] deps = ["Artifacts", "ICU_jll", "JLLWrappers", "Kerberos_krb5_jll", "Libdl", "OpenSSL_jll", "Zstd_jll"] -git-tree-sha1 = "09163f837936c8cc44f4691cb41d805eb1769642" +git-tree-sha1 = "7757f54f007cc0eb516a5000fb9a6fc19a49da7e" uuid = "08be9ffa-1c94-5ee5-a977-46a84ec9b350" -version = "16.0.0+0" +version = "16.8.0+0" [[deps.LibSSH2_jll]] deps = ["Artifacts", "Libdl", "MbedTLS_jll"] @@ -391,10 +411,10 @@ uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" version = "1.1.0" [[deps.LoweredCodeUtils]] -deps = ["JuliaInterpreter"] -git-tree-sha1 = "688d6d9e098109051ae33d126fcfc88c4ce4a021" +deps = ["Compiler", "JuliaInterpreter"] +git-tree-sha1 = "bc54ba0681bb71e56043a1b923028d652e78ee42" uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b" -version = "3.1.0" +version = "3.4.1" [[deps.MQTTClient]] deps = ["Distributed", "Random", "Sockets"] @@ -448,14 +468,26 @@ version = "0.8.1" uuid = "14a3606d-f60d-562e-9121-12d972cd8159" version = "2023.12.12" +[[deps.NATS]] +deps = ["Base64", "BufferedStreams", "CodecBase", "Dates", "DocStringExtensions", "JSON3", "MbedTLS", "NanoDates", "Random", "ScopedValues", "Sockets", "Sodium", "StructTypes", "URIs"] +git-tree-sha1 = "d9d9a189fb9155a460e6b5e8966bf6a66737abf8" +uuid = "55e73f9c-eeeb-467f-b4cc-a633fde63d2a" +version = "0.1.0" + +[[deps.NanoDates]] +deps = ["Dates", "Parsers"] +git-tree-sha1 = "850a0557ae5934f6e67ac0dc5ca13d0328422d1f" +uuid = "46f1a544-deae-4307-8689-c12aa3c955c6" +version = "1.0.3" + [[deps.NetworkOptions]] uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" version = "1.2.0" [[deps.OffsetArrays]] -git-tree-sha1 = "39d000d9c33706b8364817d8894fae1548f40295" +git-tree-sha1 = "117432e406b5c023f665fa73dc26e79ec3630151" uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.14.2" +version = "1.17.0" [deps.OffsetArrays.extensions] OffsetArraysAdaptExt = "Adapt" @@ -471,42 +503,42 @@ version = "0.3.27+1" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+4" +version = "0.8.5+0" [[deps.OpenSSL]] deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] -git-tree-sha1 = "38cb508d080d21dc1128f7fb04f20387ed4c0af4" +git-tree-sha1 = "f1a7e086c677df53e064e0fdd2c9d0b0833e3f6e" uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" -version = "1.4.3" +version = "1.5.0" [[deps.OpenSSL_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "7493f61f55a6cce7325f197443aa80d32554ba10" +git-tree-sha1 = "87510f7292a2b21aeff97912b0898f9553cc5c2c" uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" -version = "3.0.15+1" +version = "3.5.1+0" [[deps.OpenSpecFun_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1346c9208249809840c91b26703912dff463d335" uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" -version = "0.5.5+2" +version = "0.5.6+0" [[deps.OrderedCollections]] -git-tree-sha1 = "12f1439c4f986bb868acda6ea33ebc78e19b95ad" +git-tree-sha1 = "05868e21324cede2207c6f0f466b4bfef6d5e7ee" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.7.0" +version = "1.8.1" [[deps.PDMats]] deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "48566789a6d5f6492688279e22445002d171cf76" +git-tree-sha1 = "f07c06228a1c670ae4c87d1276b92c7c597fdda0" uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" -version = "0.11.33" +version = "0.11.35" [[deps.Parsers]] deps = ["Dates", "PrecompileTools", "UUIDs"] -git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821" +git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.8.1" +version = "2.8.3" [[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] @@ -591,15 +623,19 @@ version = "1.2.2" [[deps.Requires]] deps = ["UUIDs"] -git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +git-tree-sha1 = "62389eeff14780bfe55195b7204c0d8738436d64" uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.3.0" +version = "1.3.1" [[deps.Revise]] -deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "REPL", "Requires", "UUIDs", "Unicode"] -git-tree-sha1 = "470f48c9c4ea2170fd4d0f8eb5118327aada22f5" +deps = ["CodeTracking", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "REPL", "Requires", "UUIDs", "Unicode"] +git-tree-sha1 = "f6f7d30fb0d61c64d0cfe56cf085a7c9e7d5bc80" uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" -version = "3.6.4" +version = "3.8.0" +weakdeps = ["Distributed"] + + [deps.Revise.extensions] + DistributedExt = "Distributed" [[deps.Rmath]] deps = ["Random", "Rmath_jll"] @@ -628,17 +664,23 @@ git-tree-sha1 = "55de0530689832b1d3d43491ee6b67bd54d3323c" uuid = "af517c2e-c243-48fa-aab8-efac3db270f5" version = "0.1.0" +[[deps.ScopedValues]] +deps = ["HashArrayMappedTries", "Logging"] +git-tree-sha1 = "1147f140b4c8ddab224c94efa9569fc23d63ab44" +uuid = "7e506255-f358-4e82-b7e4-beb19740aa63" +version = "1.3.0" + [[deps.Scratch]] deps = ["Dates"] -git-tree-sha1 = "3bac05bc7e74a75fd9cba4295cde4045d9fe2386" +git-tree-sha1 = "9b81b8393e50b7d4e6d0a9f14e192294d3b7c109" uuid = "6c6a2e73-6563-6170-7368-637461726353" -version = "1.2.1" +version = "1.3.0" [[deps.SentinelArrays]] deps = ["Dates", "Random"] -git-tree-sha1 = "d0553ce4031a081cc42387a9b9c8441b7d99f32d" +git-tree-sha1 = "712fb0231ee6f9120e005ccd56297abbc053e7e0" uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" -version = "1.4.7" +version = "1.4.8" [[deps.Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" @@ -653,6 +695,12 @@ version = "1.2.0" uuid = "6462fe0b-24de-5631-8697-dd941f90decc" version = "1.11.0" +[[deps.Sodium]] +deps = ["Base64", "libsodium_jll"] +git-tree-sha1 = "907703e0d50846f300650d7225bdcab145b7bca9" +uuid = "4f5b5e99-b0ad-42cd-b47a-334e172ec8bd" +version = "1.1.2" + [[deps.SortingAlgorithms]] deps = ["DataStructures"] git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085" @@ -666,9 +714,9 @@ version = "1.11.0" [[deps.SpecialFunctions]] deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] -git-tree-sha1 = "64cca0c26b4f31ba18f13f6c12af7c85f478cfde" +git-tree-sha1 = "41852b8679f78c8d8961eeadc8f62cef861a52e3" uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "2.5.0" +version = "2.5.1" [deps.SpecialFunctions.extensions] SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" @@ -688,21 +736,21 @@ weakdeps = ["SparseArrays"] [[deps.StatsAPI]] deps = ["LinearAlgebra"] -git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" +git-tree-sha1 = "9d72a13a3f4dd3795a195ac5a44d7d6ff5f552ff" uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" -version = "1.7.0" +version = "1.7.1" [[deps.StatsBase]] deps = ["AliasTables", "DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] -git-tree-sha1 = "29321314c920c26684834965ec2ce0dacc9cf8e5" +git-tree-sha1 = "b81c5035922cc89c2d9523afc6c54be512411466" uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" -version = "0.34.4" +version = "0.34.5" [[deps.StatsFuns]] deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] -git-tree-sha1 = "35b09e80be285516e52c9054792c884b9216ae3c" +git-tree-sha1 = "8e45cecc66f3b42633b8ce14d431e8e57a3e242e" uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" -version = "1.4.0" +version = "1.5.0" [deps.StatsFuns.extensions] StatsFunsChainRulesCoreExt = "ChainRulesCore" @@ -714,9 +762,9 @@ version = "1.4.0" [[deps.StringManipulation]] deps = ["PrecompileTools"] -git-tree-sha1 = "a6b1675a536c5ad1a60e5a5153e1fee12eb146e3" +git-tree-sha1 = "725421ae8e530ec29bcbdddbe91ff8053421d023" uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" -version = "0.4.0" +version = "0.4.1" [[deps.StructTypes]] deps = ["Dates", "UUIDs"] @@ -744,9 +792,9 @@ version = "1.0.3" [[deps.TZJData]] deps = ["Artifacts"] -git-tree-sha1 = "36b40607bf2bf856828690e097e1c799623b0602" +git-tree-sha1 = "72df96b3a595b7aab1e101eb07d2a435963a97e2" uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7" -version = "1.3.0+2024b" +version = "1.5.0+2025b" [[deps.TableTraits]] deps = ["IteratorInterfaceExtensions"] @@ -756,9 +804,9 @@ version = "1.0.1" [[deps.Tables]] deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] -git-tree-sha1 = "598cd7c1f68d1e205689b1c2fe65a9f85846f297" +git-tree-sha1 = "f2c1efbc8f3a609aadf318094f8fc5204bdaf344" uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.12.0" +version = "1.12.1" [[deps.Tar]] deps = ["ArgTools", "SHA"] @@ -771,10 +819,10 @@ uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" version = "1.11.0" [[deps.TimeZones]] -deps = ["Dates", "Downloads", "InlineStrings", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] -git-tree-sha1 = "33c771f2157712ff4c85931186a4984efbe58934" +deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] +git-tree-sha1 = "2c705e96825b66c4a3f25031a683c06518256dd3" uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" -version = "1.19.0" +version = "1.21.3" weakdeps = ["RecipesBase"] [deps.TimeZones.extensions] @@ -786,9 +834,9 @@ uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" version = "0.11.3" [[deps.URIs]] -git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b" +git-tree-sha1 = "bef26fb046d031353ef97a82e3fdb6afe7f21b1a" uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" -version = "1.5.1" +version = "1.6.1" [[deps.UTCDateTimes]] deps = ["Dates", "TimeZones"] @@ -823,15 +871,21 @@ version = "1.2.13+1" [[deps.Zstd_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "555d1076590a6cc2fdee2ef1469451f872d8b41b" +git-tree-sha1 = "446b23e73536f84e8037f5dce465e92275f6a308" uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" -version = "1.5.6+1" +version = "1.5.7+1" [[deps.libblastrampoline_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" version = "5.11.0+0" +[[deps.libsodium_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "011b0a7331b41c25524b64dc42afc9683ee89026" +uuid = "a9144af2-ca23-56d9-984f-0d03f7b5ccf8" +version = "1.0.21+0" + [[deps.nghttp2_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" diff --git a/Project.toml b/Project.toml index c3aeeed..3882fdd 100644 --- a/Project.toml +++ b/Project.toml @@ -13,6 +13,7 @@ HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" LLMMCTS = "d76c5a4d-449e-4835-8cc4-dd86ec44f241" LibPQ = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1" +NATS = "55e73f9c-eeeb-467f-b4cc-a633fde63d2a" PrettyPrinting = "54e16d92-306c-5ea0-a30b-337be88ac337" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" @@ -24,3 +25,4 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] CSV = "0.10.15" DataFrames = "1.7.0" +NATS = "0.1.0" diff --git a/src/interface.jl b/src/interface.jl index a5d6bf4..ab73bab 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -288,9 +288,9 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 response = a.func[: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 = String(split(response, ", observation")[1]) # in case LLM generate observation key which it isn't supposed to + response = strip(response) responsedict = nothing try responsedict = copy(JSON3.read(response)) @@ -316,76 +316,12 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 continue end - # # 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", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"] errornote = "Your previous attempt didn't use the given functions" println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict[:actionname])", @__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 was $(responsedict[:actionname]). It was not specific enough." - # println("\nERROR YiemAgent decisionMaker() $errornote => $(responsedict[:actioninput]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # continue - # end - println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") pprintln(Dict(responsedict)) @@ -435,7 +371,6 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # store for later training responsedict[:system] = systemmsg responsedict[:unformatPrompt] = unformatPrompt - # responsedict[:recentchat] = recentchat responsedict[:prompt] = prompt responsedict[:context] = context responsedict[:think] = think diff --git a/src/type.jl b/src/type.jl index 242da74..a945198 100644 --- a/src/type.jl +++ b/src/type.jl @@ -2,11 +2,16 @@ module type export agent, sommelier, companion, virtualcustomer -using Dates, UUIDs, DataStructures, JSON3 +using Dates, UUIDs, DataStructures, JSON3, NATS using GeneralUtils # ---------------------------------------------- 100 --------------------------------------------- # +#[WORKING] +# struct appcontext +# connection:: +# end + abstract type agent end mutable struct companion <: agent From 8a9c9606c7962d3ba2697ede67edad12032c3438 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Mon, 14 Jul 2025 19:33:12 +0700 Subject: [PATCH 08/23] update --- src/interface.jl | 30 +++++++++++++++--------------- src/llmfunction.jl | 13 +++++++------ src/type.jl | 24 ++++++++++++++++-------- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index ab73bab..a694988 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -158,7 +158,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # end # recentrecap = GeneralUtils.dictToString_noKey(_recentrecap) - # similarDecision = a.func[:similarSommelierDecision](recentrecap) + # similarDecision = a.context[:similarSommelierDecision](recentrecap) similarDecision = nothing #CHANGE if similarDecision !== nothing @@ -234,7 +234,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 println("\nYiemAgent decisionMaker() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())") end - # QandA = generatequestion(a, a.func[:text2textInstructLLM], timeline) + # QandA = generatequestion(a, a.context[:text2textInstructLLM], timeline) context = """ @@ -285,7 +285,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # add info prompt = prompt * context - response = a.func[:text2textInstructLLM](prompt; senderId=a.id) + response = a.context.text2textInstructLLM(prompt; senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) response = GeneralUtils.remove_french_accents(response) think, response = GeneralUtils.extractthink(response) @@ -468,7 +468,7 @@ end # end # recentrecap = GeneralUtils.dictToString_noKey(_recentrecap) -# # similarDecision = a.func[:similarSommelierDecision](recentrecap) +# # similarDecision = a.context[:similarSommelierDecision](recentrecap) # similarDecision = nothing #CHANGE # if similarDecision !== nothing @@ -500,7 +500,7 @@ end # println("\nYiemAgent decisionMaker() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())") # end -# QandA = generatequestion(a, a.func[:text2textInstructLLM]; recent=3) +# 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. @@ -601,7 +601,7 @@ end # # change qwen format put in model format # prompt = GeneralUtils.formatLLMtext(unformatPrompt, "qwen3") -# response = a.func[:text2textInstructLLM](prompt) +# response = a.context[:text2textInstructLLM](prompt) # response = GeneralUtils.remove_french_accents(response) # response = replace(response, "**"=>"") # response = replace(response, "***"=>"") @@ -838,7 +838,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext println("") println(prompt) - response = a.func[:text2textInstructLLM](prompt; senderId=a.id) + response = a.context.text2textInstructLLM(prompt; senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) response = GeneralUtils.remove_french_accents(response) # response = replace(response, '$'=>"USD") @@ -1067,7 +1067,7 @@ julia> # Signature """ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} where {T<:agent} - # a.memory[:recap] = generateSituationReport(a, a.func[:text2textInstructLLM]; skiprecent=0) + # a.memory[:recap] = generateSituationReport(a, a.context[:text2textInstructLLM]; skiprecent=0) thoughtDict = decisionMaker(a) actionname = thoughtDict[:actionname] @@ -1272,7 +1272,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev # add info prompt = prompt * context - response = a.func[:text2textInstructLLM](prompt; senderId=a.id) + response = a.context.text2textInstructLLM(prompt; senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) response = GeneralUtils.remove_french_accents(response) # response = replace(response, '$'=>"USD") @@ -1453,7 +1453,7 @@ end # # add info # prompt = prompt * context -# response = a.func[:text2textInstructLLM](prompt; senderId=a.id) +# response = a.context[:text2textInstructLLM](prompt; senderId=a.id) # response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) # response = GeneralUtils.remove_french_accents(response) # # response = replace(response, '$'=>"USD") @@ -1634,7 +1634,7 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) for attempt in 1:maxattempt # if attempt > 1 # use to prevent LLM generate the same respond over and over # println("\nYiemAgent generatchat() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # yourthought1 = paraphrase(a.func[:text2textInstructLLM], yourthought) + # yourthought1 = paraphrase(a.context[:text2textInstructLLM], yourthought) # else # yourthought1 = yourthought # end @@ -1658,7 +1658,7 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) # add info prompt = prompt * context - response = a.func[:text2textInstructLLM](prompt; senderId=a.id) + response = a.context.text2textInstructLLM(prompt; senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) response = GeneralUtils.remove_french_accents(response) # response = replace(response, '$'=>"USD") @@ -1807,7 +1807,7 @@ function generatechat(a::companion; recentevents::Integer=10, prompt = replace(_prompt, "|>user"=>"|>$(converPartnerName)") prompt = replace(prompt, "|>assistant"=>"|>$(a.name)") - response = a.func[:text2textInstructLLM](prompt; llmkwargs=llmkwargs, senderId=a.id) + response = a.context.text2textInstructLLM(prompt; llmkwargs=llmkwargs, senderId=a.id) response = replace(response, "<|im_start|>"=> "") response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) think, response = GeneralUtils.extractthink(response) @@ -1863,7 +1863,7 @@ function generatechat(a::virtualcustomer; # add info prompt = prompt * context - response = a.func[:text2textInstructLLM](prompt; llmkwargs=llmkwargs, senderId=a.id) + response = a.context.text2textInstructLLM(prompt; llmkwargs=llmkwargs, senderId=a.id) response = replace(response, "<|im_start|>"=> "") response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) think, response = GeneralUtils.extractthink(response) @@ -2291,7 +2291,7 @@ function detectWineryName(a, text) # put in model format prompt = GeneralUtils.formatLLMtext(_prompt, a.llmFormatName) - response = a.func[:text2textInstructLLM](prompt; senderId=a.id) + response = a.context.text2textInstructLLM(prompt; senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) think, response = GeneralUtils.extractthink(response) println("\ndetectWineryName() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") diff --git a/src/llmfunction.jl b/src/llmfunction.jl index aaa3212..dfefe2f 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -309,10 +309,11 @@ function checkwine(a::T1, input::T2; maxattempt::Int=3 inventoryquery = "Retrieves $retrieve_attributes of wines that match the following criteria - {$_inventoryquery}" println("\ncheckinventory input: $inventoryquery ", @__FILE__, ":", @__LINE__, " $(Dates.now())") # add suppport for similarSQLVectorDB - textresult, rawresponse = SQLLLM.query(inventoryquery, a.func[:executeSQL], - a.func[:text2textInstructLLM]; - insertSQLVectorDB=a.func[:insertSQLVectorDB], - similarSQLVectorDB=a.func[:similarSQLVectorDB], + textresult, rawresponse = SQLLLM.query(inventoryquery, + a.context.executeSQL, + a.context.text2textInstructLLM; + insertSQLVectorDB=a.context.insertSQLVectorDB, + similarSQLVectorDB=a.context.similarSQLVectorDB, llmFormatName="qwen3") # check if all of retrieve_attributes appears in textresult isin = [occursin(x, textresult) for x in retrieve_attributes] @@ -463,7 +464,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10 # add info prompt = prompt * context - response = a.func[:text2textInstructLLM](prompt; modelsize="medium", senderId=a.id) + response = a.context.text2textInstructLLM(prompt; modelsize="medium", senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) response = GeneralUtils.remove_french_accents(response) think, response = GeneralUtils.extractthink(response) @@ -742,7 +743,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2< # add info prompt = prompt * context - response = a.func[:text2textInstructLLM](prompt; modelsize="medium", senderId=a.id) + response = a.context.text2textInstructLLM(prompt; modelsize="medium", senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) response = GeneralUtils.remove_french_accents(response) think, response = GeneralUtils.extractthink(response) diff --git a/src/type.jl b/src/type.jl index a945198..fa84efc 100644 --- a/src/type.jl +++ b/src/type.jl @@ -1,6 +1,6 @@ module type -export agent, sommelier, companion, virtualcustomer +export agent, sommelier, companion, virtualcustomer, appcontext using Dates, UUIDs, DataStructures, JSON3, NATS using GeneralUtils @@ -8,9 +8,17 @@ using GeneralUtils # ---------------------------------------------- 100 --------------------------------------------- # #[WORKING] -# struct appcontext -# connection:: -# end +mutable struct appcontext + const connection::NATS.Connection + const text2textInstructLLMServiceSubject::String + getTextEmbedding::Function + text2textInstructLLM::Function + executeSQL::Function + similarSQLVectorDB::Function + insertSQLVectorDB::Function + similarSommelierDecision::Function + insertSommelierDecision::Function +end abstract type agent end @@ -27,7 +35,7 @@ mutable struct companion <: agent end function companion( - func::NamedTuple # NamedTuple of functions + context::appcontext # NamedTuple of functions ; name::String= "Assistant", id::String= GeneralUtils.uuid4snakecase(), @@ -75,7 +83,7 @@ function companion( maxHistoryMsg, chathistory, memory, - func, + context, llmFormatName ) @@ -165,7 +173,7 @@ mutable struct sommelier <: agent end function sommelier( - func, # NamedTuple of functions + context::appcontext, # NamedTuple of functions ; name::String= "Assistant", id::String= string(uuid4()), @@ -216,7 +224,7 @@ function sommelier( maxHistoryMsg, chathistory, memory, - func, + context, llmFormatName ) From 68a20b5080ae399e28f7160f4a4ab01a97c75c18 Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Thu, 17 Jul 2025 11:48:23 +0700 Subject: [PATCH 09/23] 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 ) From 0a1032c54598a3287b269bc8847a98ec4fdc82ba Mon Sep 17 00:00:00 2001 From: narawat lamaiin Date: Fri, 18 Jul 2025 07:54:59 +0700 Subject: [PATCH 10/23] update --- src/interface.jl | 120 ++++++++++++++++++++--------------------------- src/type.jl | 2 +- src/util.jl | 44 +++++++++++++++-- 3 files changed, 91 insertions(+), 75 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index e1420b7..afefc2a 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -300,21 +300,27 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 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 decisionMaker() $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 decisionMaker() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys) + if !ispass + errornote = errormsg + println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n") continue end + # _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 decisionMaker() $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 decisionMaker() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + # continue + # end if responsedict[:actionname] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"] errornote = "Your previous attempt didn't use the given functions" @@ -538,19 +544,10 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext 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 generatechat() $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 generatechat() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys) + if !ispass + errornote = errormsg + println("\nERROR YiemAgent evaluator() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n") continue end @@ -977,19 +974,10 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev 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())") + ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys) + if !ispass + errornote = errormsg + println("\nERROR YiemAgent presentbox() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n") continue end @@ -1161,19 +1149,10 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) 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 generatechat() $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 generatechat() $errornote --(not qualify response)--> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + ispass, errormsg = checkAgentResponse_JSON(responsedict, requiredKeys) + if !ispass + errornote = errormsg + println("\nERROR YiemAgent generatechat() $errornote --(not qualify response)> $responsedict", @__FILE__, ":", @__LINE__, " $(Dates.now())\n") continue end @@ -1327,16 +1306,15 @@ function generatechat(a::virtualcustomer; # check whether response has all header 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] - if 0 ∈ values(detected_kw) + missingkeys = [k for (k, v) in detected_kw if v === nothing] + + if !isempty(missingkeys) errornote = "$missingkeys are missing from your previous response" - println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + println("\nERROR YiemAgent rolegenerator() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue - elseif sum(values(detected_kw)) > length(header) - errornote = "Your previous attempt has duplicated points" - println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + elseif sum([length(i) for i in values(detected_kw)]) > length(header) + errornote = "\nYour previous attempt has duplicated points according to the required response format" + println("\nERROR YiemAgent rolegenerator() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue end @@ -1754,15 +1732,19 @@ function detectWineryName(a, text) println("\ndetectWineryName() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") try pprintln(response) catch e println(response) end - # check whether response has all header - detected_kw = GeneralUtils.detectKeywordVariation(header, response) - if 0 ∈ values(detected_kw) - errornote = "\nYiemAgent detectWineryName() response does not have all header" - continue - elseif sum(values(detected_kw)) > length(header) - errornote = "\nYiemAgent detectWineryName() response has duplicated header" - continue - end + # check whether response has all header + detected_kw = GeneralUtils.detectKeywordVariation(header, response) + missingkeys = [k for (k, v) in detected_kw if v === nothing] + + if !isempty(missingkeys) + errornote = "$missingkeys are missing from your previous response" + println("\nERROR YiemAgent rolegenerator() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + continue + elseif sum([length(i) for i in values(detected_kw)]) > length(header) + errornote = "\nYour previous attempt has duplicated points according to the required response format" + println("\nERROR YiemAgent rolegenerator() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + continue + end responsedict = GeneralUtils.textToDict(response, header; dictKey=dictkey, symbolkey=true) diff --git a/src/type.jl b/src/type.jl index 6dbcf0d..7071571 100644 --- a/src/type.jl +++ b/src/type.jl @@ -7,7 +7,7 @@ using GeneralUtils # ---------------------------------------------- 100 --------------------------------------------- # -#[WORKING] + mutable struct appcontext const connection::NATS.Connection const text2textInstructLLMServiceSubject::String diff --git a/src/util.jl b/src/util.jl index ba4c7ae..018adde 100644 --- a/src/util.jl +++ b/src/util.jl @@ -1,7 +1,8 @@ module util export clearhistory, addNewMessage, chatHistoryToText, eventdict, noises, createTimeline, - availableWineToText, createEventsLog, createChatLog + availableWineToText, createEventsLog, createChatLog, checkAgentResponse_JSON, + checkAgentResponse_text using UUIDs, Dates, DataStructures, HTTP, JSON3 using GeneralUtils @@ -411,12 +412,45 @@ function createChatLog(chatdict::T1; index::Union{UnitRange, Nothing}=nothing end +function checkAgentResponse_text(response::String, requiredHeader::T + )::Tuple where {T<:Array{String}} + detected_kw = GeneralUtils.detectKeywordVariation(requiredHeader, response) + missingkeys = [k for (k, v) in detected_kw if v === nothing] + ispass = false + errormsg = nothing + if !isempty(missingkeys) + errormsg = "$missingkeys are missing from your previous response" + ispass = false + elseif sum([length(i) for i in values(detected_kw)]) > length(requiredHeader) + errormsg = "Your previous attempt has duplicated points according to the required response format" + ispass = false + else + ispass = true + end + return (ispass, errormsg) +end - - - - +function checkAgentResponse_JSON(responsedict::Dict, requiredKeys::T + )::Tuple where {T<:Array{Symbol}} + _responsedictKey = keys(responsedict) + responsedictKey = [i for i in _responsedictKey] # convert into a list + is_requiredKeys_in_responsedictKey = [i ∈ responsedictKey for i in requiredKeys] + ispass = false + errormsg = nothing + if length(is_requiredKeys_in_responsedictKey) > length(requiredKeys) + errormsg = "Your previous attempt has duplicated points according to the required response format" + ispass = false + elseif !all(is_requiredKeys_in_responsedictKey) + zeroind = findall(x -> x == 0, is_requiredKeys_in_responsedictKey) + missingkeys = [requiredKeys[i] for i in zeroind] + errormsg = "$missingkeys are missing from your previous response" + ispass = false + else + ispass = true + end + return (ispass, errormsg) +end From 4eb55537f71724d112db9a0360fb0ad6e10c9e0f Mon Sep 17 00:00:00 2001 From: narawat Date: Wed, 23 Jul 2025 18:28:38 +0700 Subject: [PATCH 11/23] update --- src/interface.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index afefc2a..79bc7c1 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -526,8 +526,6 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName) # add info prompt = prompt * context - println("") - println(prompt) response = a.context.text2textInstructLLM(prompt; senderId=a.id) response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName) From b5a00bc69489d9b88c701a2ba296fa2c386885b8 Mon Sep 17 00:00:00 2001 From: narawat Date: Wed, 30 Jul 2025 18:08:57 +0700 Subject: [PATCH 12/23] update --- src/interface.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/interface.jl b/src/interface.jl index 79bc7c1..d19b59a 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -470,6 +470,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext - The trainee's plan, actionname, and actioninput must be logically consistent - The trainee's actioninput should be in a proper format as specified by the tools. + - The trainee's action name and action input should make sense. For example, if the trainee isn't finished talking, he shouldn't use the ENDCONVERSATION tool. 1) trajectory_evaluation: Analyze the trajectory of a solution to answer the user's original question. From 99b2fda4616b0b9983b48cfb5bae5f8269597d2f Mon Sep 17 00:00:00 2001 From: narawat Date: Sun, 21 Jun 2026 08:51:39 +0700 Subject: [PATCH 13/23] use JSON instead --- Manifest.toml | 385 ++++++++++++++------------ Project.toml | 7 +- example/agent_chat_virtualCustomer.jl | 14 +- example/main.jl | 14 +- src/interface.jl | 28 +- src/llmfunction.jl | 14 +- src/type.jl | 2 +- src/util.jl | 2 +- test/chatting_with_agent.jl | 8 +- test/prompttest.jl | 4 +- test/prompttest_1.jl | 2 +- 11 files changed, 254 insertions(+), 226 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 6a3c541..d79f83d 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,8 +1,8 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.11.5" +julia_version = "1.12.6" manifest_format = "2.0" -project_hash = "9896e9d54d6cf4e2c3ae871a42f43f2f212ab1c9" +project_hash = "e6bd85ad2679c39ab370f878253f2eeb45c1b6ae" [[deps.AliasTables]] deps = ["PtrArrays", "Random"] @@ -14,6 +14,12 @@ version = "1.1.3" uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" version = "1.1.2" +[[deps.ArrowTypes]] +deps = ["Sockets", "UUIDs"] +git-tree-sha1 = "404265cd8128a2515a81d5eae16de90fdef05101" +uuid = "31f734f8-188a-4ce0-8406-c8a06bd891cd" +version = "2.3.0" + [[deps.Artifacts]] uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" version = "1.11.0" @@ -22,11 +28,6 @@ version = "1.11.0" uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" version = "1.11.0" -[[deps.BitFlags]] -git-tree-sha1 = "0691e34b3bb8be9307330f88d1a3c3f25466c24d" -uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" -version = "0.1.9" - [[deps.BufferedStreams]] git-tree-sha1 = "6863c5b7fc997eadcabdbaf6c5f201dc30032643" uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d" @@ -37,17 +38,21 @@ git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" version = "0.5.0" +[[deps.CRC32c]] +uuid = "8bf52ea8-c179-5cab-976a-9e18b702a9bc" +version = "1.11.0" + [[deps.CSV]] deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"] -git-tree-sha1 = "deddd8725e5e1cc49ee205a1964256043720a6c3" +git-tree-sha1 = "8d8e0b0f350b8e1c91420b5e64e5de774c2f0f4d" uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -version = "0.10.15" +version = "0.10.16" [[deps.CodeTracking]] -deps = ["InteractiveUtils", "UUIDs"] -git-tree-sha1 = "062c5e1a5bf6ada13db96a4ae4749a4c2234f521" +deps = ["InteractiveUtils", "REPL", "UUIDs"] +git-tree-sha1 = "cfb7a2e89e245a9d5016b70323db412b3a7438d5" uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" -version = "1.3.9" +version = "3.0.2" [[deps.CodecBase]] deps = ["TranscodingStreams"] @@ -63,9 +68,9 @@ version = "0.7.8" [[deps.Compat]] deps = ["TOML", "UUIDs"] -git-tree-sha1 = "3a3dfb30697e96a440e4149c8c51bf32f818c0f3" +git-tree-sha1 = "9d8a54ce4b17aa5bdce0ea5c34bc5e7c340d16ad" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.17.0" +version = "4.18.1" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] @@ -79,13 +84,7 @@ version = "0.1.1" [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.1.1+0" - -[[deps.ConcurrentUtilities]] -deps = ["Serialization", "Sockets"] -git-tree-sha1 = "d9d26935a0bcffc87d2613ce14c527c99fc543fd" -uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" -version = "2.5.0" +version = "1.3.0+1" [[deps.Crayons]] git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" @@ -104,15 +103,15 @@ version = "1.16.0" [[deps.DataFrames]] deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] -git-tree-sha1 = "fb61b4812c49343d7ef0b533ba982c46021938a6" +git-tree-sha1 = "5fab31e2e01e70ad66e3e24c968c264d1cf166d6" uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -version = "1.7.0" +version = "1.8.2" [[deps.DataStructures]] -deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "4e1fe97fdaed23e9dc21d4d664bea76b65fc50a0" +deps = ["OrderedCollections"] +git-tree-sha1 = "6fb53a69613a0b2b68a0d12671717d307ab8b24e" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.22" +version = "0.19.5" [[deps.DataValueInterfaces]] git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" @@ -136,18 +135,20 @@ version = "1.11.0" [[deps.Distributions]] deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] -git-tree-sha1 = "3e6d038b77f22791b8e3472b7c633acea1ecac06" +git-tree-sha1 = "3c8a0a9a6d4a10bdfb6b751bd2b6051ed3e25fd4" uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" -version = "0.25.120" +version = "0.25.127" [deps.Distributions.extensions] DistributionsChainRulesCoreExt = "ChainRulesCore" DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsSparseConnectivityTracerExt = "SparseConnectivityTracer" DistributionsTestExt = "Test" [deps.Distributions.weakdeps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + SparseConnectivityTracer = "9f842d2f-2579-4b1d-911e-f412cf18a3f5" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[deps.DocStringExtensions]] @@ -158,13 +159,12 @@ version = "0.9.5" [[deps.Downloads]] deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -version = "1.6.0" +version = "1.7.0" -[[deps.ExceptionUnwrapping]] -deps = ["Test"] -git-tree-sha1 = "d36f682e590a83d63d1c7dbd287573764682d12a" -uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4" -version = "0.1.11" +[[deps.EnumX]] +git-tree-sha1 = "c49898e8438c828577f04b92fc9368c388ac783c" +uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" +version = "1.0.7" [[deps.ExprTools]] git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" @@ -173,13 +173,9 @@ version = "0.1.10" [[deps.FileIO]] deps = ["Pkg", "Requires", "UUIDs"] -git-tree-sha1 = "b66970a70db13f45b7e57fbda1736e1cf72174ea" +git-tree-sha1 = "91e0e5c68d02bcdaae76d3c8ceb4361e8f28d2e9" uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" -version = "1.17.0" -weakdeps = ["HTTP"] - - [deps.FileIO.extensions] - HTTPExt = "HTTP" +version = "1.16.5" [[deps.FilePathsBase]] deps = ["Compat", "Dates"] @@ -198,32 +194,40 @@ version = "1.11.0" [[deps.FillArrays]] deps = ["LinearAlgebra"] -git-tree-sha1 = "6a70198746448456524cb442b8af316927ff3e1a" +git-tree-sha1 = "2f979084d1e13948a3352cf64a25df6bd3b4dca3" uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "1.13.0" -weakdeps = ["PDMats", "SparseArrays", "Statistics"] +version = "1.16.0" [deps.FillArrays.extensions] FillArraysPDMatsExt = "PDMats" FillArraysSparseArraysExt = "SparseArrays" + FillArraysStaticArraysExt = "StaticArrays" FillArraysStatisticsExt = "Statistics" + [deps.FillArrays.weakdeps] + PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + [[deps.Future]] deps = ["Random"] uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" version = "1.11.0" [[deps.GeneralUtils]] -deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON3", "MQTTClient", "NATS", "PrettyPrinting", "Random", "SHA", "UUIDs"] -path = "/appfolder/app/dev/GeneralUtils" +deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "UUIDs"] +git-tree-sha1 = "8720a31344bc85ad610ae12f7e1247de22070765" +repo-rev = "main" +repo-url = "https://git.yiem.cc/ton/GeneralUtils" uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe" -version = "0.3.1" +version = "0.3.2" [[deps.HTTP]] -deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "PrecompileTools", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] -git-tree-sha1 = "ed5e9c58612c4e081aecdb6e1a479e18462e041e" +deps = ["Base64", "CodecZlib", "Dates", "EnumX", "PrecompileTools", "Random", "Reseau", "SHA", "URIs", "UUIDs", "Zlib_jll"] +git-tree-sha1 = "a95f80749437ffb42948848d2d2ec81a5050ef4b" uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" -version = "1.10.17" +version = "2.4.0" [[deps.HashArrayMappedTries]] git-tree-sha1 = "2eaa69a7cab70a52b9687c8bf950a5a93ec895ae" @@ -249,28 +253,25 @@ uuid = "a303e19e-6eb4-11e9-3b09-cd9505f79100" version = "0.2.4" [[deps.InlineStrings]] -git-tree-sha1 = "8594fac023c5ce1ef78260f24d1ad18b4327b420" +git-tree-sha1 = "8f3d257792a522b4601c24a577954b0a8cd7334d" uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" -version = "1.4.4" +version = "1.4.5" +weakdeps = ["ArrowTypes", "Parsers"] [deps.InlineStrings.extensions] ArrowTypesExt = "ArrowTypes" ParsersExt = "Parsers" - [deps.InlineStrings.weakdeps] - ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd" - Parsers = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" - [[deps.InteractiveUtils]] deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" version = "1.11.0" [[deps.Intervals]] -deps = ["Dates", "Printf", "RecipesBase", "Serialization", "TimeZones"] -git-tree-sha1 = "ac0aaa807ed5eaf13f67afe188ebc07e828ff640" +deps = ["ArrowTypes", "Dates", "Printf", "RecipesBase", "Serialization", "TimeZones"] +git-tree-sha1 = "d6fe00b123e32ddd17231b35d69a6394e696fd5a" uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5" -version = "1.10.0" +version = "1.11.0" [[deps.InvertedIndices]] git-tree-sha1 = "6da3c4316095de0f5ee2ebd875df8721e7e0bdbe" @@ -278,9 +279,9 @@ uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" version = "1.3.1" [[deps.IrrationalConstants]] -git-tree-sha1 = "e2222959fbc6c19554dc15174c81bf7bf3aa691c" +git-tree-sha1 = "b2d91fe939cae05960e760110b328288867b5758" uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" -version = "0.2.4" +version = "0.2.6" [[deps.IterTools]] git-tree-sha1 = "42d5f897009e7ff2cf88db414a389e5ed1bdd023" @@ -294,27 +295,40 @@ version = "1.0.0" [[deps.JLLWrappers]] deps = ["Artifacts", "Preferences"] -git-tree-sha1 = "a007feb38b422fbdab534406aeca1b86823cb4d6" +git-tree-sha1 = "7204148362dafe5fe6a273f855b8ccbe4df8173e" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.7.0" +version = "1.8.0" + +[[deps.JSON]] +deps = ["Dates", "Logging", "Parsers", "PrecompileTools", "StructUtils", "UUIDs", "Unicode"] +git-tree-sha1 = "c89d196f5ffb64bfbf80985b699ea913b0d2c211" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "1.6.1" +weakdeps = ["ArrowTypes"] + + [deps.JSON.extensions] + JSONArrowExt = ["ArrowTypes"] [[deps.JSON3]] deps = ["Dates", "Mmap", "Parsers", "PrecompileTools", "StructTypes", "UUIDs"] git-tree-sha1 = "411eccfe8aba0814ffa0fdf4860913ed09c34975" uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" version = "1.14.3" +weakdeps = ["ArrowTypes"] [deps.JSON3.extensions] JSON3ArrowExt = ["ArrowTypes"] - [deps.JSON3.weakdeps] - ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd" - [[deps.JuliaInterpreter]] deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"] -git-tree-sha1 = "6ac9e4acc417a5b534ace12690bc6973c25b862f" +git-tree-sha1 = "58927c485919bf17ea308d9d82156de1adf4b006" uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a" -version = "0.10.3" +version = "0.10.12" + +[[deps.JuliaSyntaxHighlighting]] +deps = ["StyledStrings"] +uuid = "ac6e5ff7-fb65-4e79-a425-ec3bc9c03011" +version = "1.12.0" [[deps.Kerberos_krb5_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] @@ -323,8 +337,8 @@ uuid = "b39eb1a6-c29a-53d7-8c32-632cd16f18da" version = "1.21.3+0" [[deps.LLMMCTS]] -deps = ["GeneralUtils", "JSON3", "PrettyPrinting"] -path = "/appfolder/app/dev/LLMMCTS" +deps = ["GeneralUtils", "JSON", "PrettyPrinting"] +path = "../LLMMCTS" uuid = "d76c5a4d-449e-4835-8cc4-dd86ec44f241" version = "0.1.4" @@ -344,19 +358,19 @@ uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" version = "0.6.4" [[deps.LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "OpenSSL_jll", "Zlib_jll", "nghttp2_jll"] uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "8.6.0+0" +version = "8.15.0+0" [[deps.LibGit2]] -deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +deps = ["LibGit2_jll", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" version = "1.11.0" [[deps.LibGit2_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "OpenSSL_jll"] uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" -version = "1.7.2+0" +version = "1.9.0+0" [[deps.LibPQ]] deps = ["CEnum", "DBInterface", "Dates", "Decimals", "DocStringExtensions", "FileWatching", "Infinity", "Intervals", "IterTools", "LayerDicts", "LibPQ_jll", "Libdl", "Memento", "OffsetArrays", "SQLStrings", "Tables", "TimeZones", "UTCDateTimes"] @@ -366,14 +380,14 @@ version = "1.18.0" [[deps.LibPQ_jll]] deps = ["Artifacts", "ICU_jll", "JLLWrappers", "Kerberos_krb5_jll", "Libdl", "OpenSSL_jll", "Zstd_jll"] -git-tree-sha1 = "7757f54f007cc0eb516a5000fb9a6fc19a49da7e" +git-tree-sha1 = "c692057e05ba6da348bc45d5dab8c7a2c88da518" uuid = "08be9ffa-1c94-5ee5-a977-46a84ec9b350" -version = "16.8.0+0" +version = "16.14.0+0" [[deps.LibSSH2_jll]] -deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +deps = ["Artifacts", "Libdl", "OpenSSL_jll"] uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" -version = "1.11.0+1" +version = "1.11.3+1" [[deps.Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" @@ -382,13 +396,13 @@ version = "1.11.0" [[deps.LinearAlgebra]] deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -version = "1.11.0" +version = "1.12.0" [[deps.LogExpFunctions]] deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "13ca9e2586b89836fd20cccf56e57e2b9ae7f38f" +git-tree-sha1 = "bba2d9aa057d8f126415de240573e86a8f39d2a1" uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.29" +version = "1.0.1" [deps.LogExpFunctions.extensions] LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" @@ -404,49 +418,34 @@ version = "0.3.29" uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" version = "1.11.0" -[[deps.LoggingExtras]] -deps = ["Dates", "Logging"] -git-tree-sha1 = "f02b56007b064fbfddb4c9cd60161b6dd0f40df3" -uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" -version = "1.1.0" - [[deps.LoweredCodeUtils]] -deps = ["Compiler", "JuliaInterpreter"] -git-tree-sha1 = "bc54ba0681bb71e56043a1b923028d652e78ee42" +deps = ["CodeTracking", "Compiler", "JuliaInterpreter"] +git-tree-sha1 = "0aad96d7b987a5600e260eec50147b254d5ff7e6" uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b" -version = "3.4.1" - -[[deps.MQTTClient]] -deps = ["Distributed", "Random", "Sockets"] -git-tree-sha1 = "f2597b290d4bf17b577346153cd2ddf9accb5c26" -uuid = "985f35cc-2c3d-4943-b8c1-f0931d5f0959" -version = "0.3.1" -weakdeps = ["PrecompileTools"] - - [deps.MQTTClient.extensions] - PrecompileMQTT = "PrecompileTools" +version = "3.6.0" [[deps.Markdown]] -deps = ["Base64"] +deps = ["Base64", "JuliaSyntaxHighlighting", "StyledStrings"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" version = "1.11.0" [[deps.MbedTLS]] deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] -git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" +git-tree-sha1 = "8785729fa736197687541f7053f6d8ab7fc44f92" uuid = "739be429-bea8-5141-9913-cc70e7f3736d" -version = "1.1.9" +version = "1.1.10" [[deps.MbedTLS_jll]] -deps = ["Artifacts", "Libdl"] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "ff69a2b1330bcb730b9ac1ab7dd680176f5896b8" uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.6+0" +version = "2.28.1010+0" [[deps.Memento]] deps = ["Dates", "Distributed", "Requires", "Serialization", "Sockets", "Test", "UUIDs"] -git-tree-sha1 = "bb2e8f4d9f400f6e90d57b34860f6abdc51398e5" +git-tree-sha1 = "e03a25cb3b6569623f8246d3d8b3faa7ce86f4ad" uuid = "f28f55f0-a522-5efc-85c2-fe41dfb9b2d9" -version = "1.4.1" +version = "1.5.0" [[deps.Missings]] deps = ["DataAPI"] @@ -466,13 +465,13 @@ version = "0.8.1" [[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2023.12.12" +version = "2025.11.4" [[deps.NATS]] deps = ["Base64", "BufferedStreams", "CodecBase", "Dates", "DocStringExtensions", "JSON3", "MbedTLS", "NanoDates", "Random", "ScopedValues", "Sockets", "Sodium", "StructTypes", "URIs"] -git-tree-sha1 = "d9d9a189fb9155a460e6b5e8966bf6a66737abf8" +git-tree-sha1 = "a1cdf34ba90ee5cd2658e487d3277ffafee712ce" uuid = "55e73f9c-eeeb-467f-b4cc-a633fde63d2a" -version = "0.1.0" +version = "0.1.1" [[deps.NanoDates]] deps = ["Dates", "Parsers"] @@ -482,7 +481,7 @@ version = "1.0.3" [[deps.NetworkOptions]] uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" -version = "1.2.0" +version = "1.3.0" [[deps.OffsetArrays]] git-tree-sha1 = "117432e406b5c023f665fa73dc26e79ec3630151" @@ -498,24 +497,17 @@ version = "1.17.0" [[deps.OpenBLAS_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.27+1" +version = "0.3.29+0" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.5+0" - -[[deps.OpenSSL]] -deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] -git-tree-sha1 = "f1a7e086c677df53e064e0fdd2c9d0b0833e3f6e" -uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" -version = "1.5.0" +version = "0.8.7+0" [[deps.OpenSSL_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "87510f7292a2b21aeff97912b0898f9553cc5c2c" +deps = ["Artifacts", "Libdl"] uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" -version = "3.5.1+0" +version = "3.5.4+0" [[deps.OpenSpecFun_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"] @@ -524,26 +516,30 @@ uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" version = "0.5.6+0" [[deps.OrderedCollections]] -git-tree-sha1 = "05868e21324cede2207c6f0f466b4bfef6d5e7ee" +git-tree-sha1 = "94ba93778373a53bfd5a0caaf7d809c445292ff4" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.8.1" +version = "1.8.2" [[deps.PDMats]] deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "f07c06228a1c670ae4c87d1276b92c7c597fdda0" +git-tree-sha1 = "e4cff168707d441cd6bf3ff7e4832bdf34278e4a" uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" -version = "0.11.35" +version = "0.11.37" +weakdeps = ["StatsBase"] + + [deps.PDMats.extensions] + StatsBaseExt = "StatsBase" [[deps.Parsers]] deps = ["Dates", "PrecompileTools", "UUIDs"] -git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" +git-tree-sha1 = "32a4e09c5f29402573d673901778a0e03b0807b9" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.8.3" +version = "2.8.6" [[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.11.0" +version = "1.12.1" weakdeps = ["REPL"] [deps.Pkg.extensions] @@ -557,15 +553,15 @@ version = "1.4.3" [[deps.PrecompileTools]] deps = ["Preferences"] -git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" +git-tree-sha1 = "edbeefc7a4889f528644251bdb5fc9ab5348bc2c" uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.2.1" +version = "1.3.4" [[deps.Preferences]] deps = ["TOML"] -git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +git-tree-sha1 = "8b770b60760d4451834fe79dd483e318eee709c4" uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.3" +version = "1.5.2" [[deps.PrettyPrinting]] git-tree-sha1 = "142ee93724a9c5d04d78df7006670a93ed1b244e" @@ -573,10 +569,16 @@ uuid = "54e16d92-306c-5ea0-a30b-337be88ac337" version = "0.4.2" [[deps.PrettyTables]] -deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"] -git-tree-sha1 = "1101cd475833706e4d0e7b122218257178f48f34" +deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "REPL", "Reexport", "StringManipulation", "Tables"] +git-tree-sha1 = "624de6279ab7d94fc9f672f0068107eb6619732c" uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" -version = "2.4.0" +version = "3.3.2" + + [deps.PrettyTables.extensions] + PrettyTablesTypstryExt = "Typstry" + + [deps.PrettyTables.weakdeps] + Typstry = "f0ed7684-a786-439e-b1e3-3b82803b501e" [[deps.Printf]] deps = ["Unicode"] @@ -584,15 +586,15 @@ uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" version = "1.11.0" [[deps.PtrArrays]] -git-tree-sha1 = "1d36ef11a9aaf1e8b74dacc6a731dd1de8fd493d" +git-tree-sha1 = "4fbbafbc6251b883f4d2705356f3641f3652a7fe" uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" -version = "1.3.0" +version = "1.4.0" [[deps.QuadGK]] deps = ["DataStructures", "LinearAlgebra"] -git-tree-sha1 = "9da16da70037ba9d701192e27befedefb91ec284" +git-tree-sha1 = "5e8e8b0ab68215d7a2b14b9921a946fee794749e" uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" -version = "2.11.2" +version = "2.11.3" [deps.QuadGK.extensions] QuadGKEnzymeExt = "Enzyme" @@ -601,7 +603,7 @@ version = "2.11.2" Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" [[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"] +deps = ["InteractiveUtils", "JuliaSyntaxHighlighting", "Markdown", "Sockets", "StyledStrings", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" version = "1.11.0" @@ -627,11 +629,17 @@ git-tree-sha1 = "62389eeff14780bfe55195b7204c0d8738436d64" uuid = "ae029012-a4dd-5104-9daa-d747884805df" version = "1.3.1" +[[deps.Reseau]] +deps = ["NetworkOptions", "OpenSSL_jll", "PrecompileTools", "Random", "SHA"] +git-tree-sha1 = "0eab6d95ed40c2ef3992255c1c71e4f9748932b5" +uuid = "802f3686-a58f-41ce-bb0c-3c43c75bba36" +version = "1.3.1" + [[deps.Revise]] -deps = ["CodeTracking", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "REPL", "Requires", "UUIDs", "Unicode"] -git-tree-sha1 = "f6f7d30fb0d61c64d0cfe56cf085a7c9e7d5bc80" +deps = ["CRC32c", "CodeTracking", "FileWatching", "InteractiveUtils", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "Preferences", "REPL", "UUIDs"] +git-tree-sha1 = "27e3ee13fc8739a59b380d6163d6a82f52c03bd7" uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" -version = "3.8.0" +version = "3.15.1" weakdeps = ["Distributed"] [deps.Revise.extensions] @@ -639,9 +647,9 @@ weakdeps = ["Distributed"] [[deps.Rmath]] deps = ["Random", "Rmath_jll"] -git-tree-sha1 = "852bd0f55565a9e973fcfee83a84413270224dc4" +git-tree-sha1 = "5b3d50eb374cea306873b371d3f8d3915a018f0b" uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" -version = "0.8.0" +version = "0.9.0" [[deps.Rmath_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] @@ -655,7 +663,7 @@ version = "0.7.0" [[deps.SQLLLM]] deps = ["CSV", "DataFrames", "DataStructures", "Dates", "FileIO", "GeneralUtils", "HTTP", "JSON3", "LLMMCTS", "LibPQ", "PrettyPrinting", "Random", "Revise", "StatsBase", "Tables", "URIs", "UUIDs"] -path = "/appfolder/app/dev/SQLLLM" +path = "../SQLLLM" uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3" version = "0.2.4" @@ -666,9 +674,9 @@ version = "0.1.0" [[deps.ScopedValues]] deps = ["HashArrayMappedTries", "Logging"] -git-tree-sha1 = "1147f140b4c8ddab224c94efa9569fc23d63ab44" +git-tree-sha1 = "67a144433c4ce877ee6d1ada69a124d6b1ecf7be" uuid = "7e506255-f358-4e82-b7e4-beb19740aa63" -version = "1.3.0" +version = "1.6.2" [[deps.Scratch]] deps = ["Dates"] @@ -678,19 +686,14 @@ version = "1.3.0" [[deps.SentinelArrays]] deps = ["Dates", "Random"] -git-tree-sha1 = "712fb0231ee6f9120e005ccd56297abbc053e7e0" +git-tree-sha1 = "084c47c7c5ce5cfecefa0a98dff69eb3646b5a80" uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" -version = "1.4.8" +version = "1.4.10" [[deps.Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" version = "1.11.0" -[[deps.SimpleBufferStream]] -git-tree-sha1 = "f305871d2f381d21527c770d4788c06c097c9bc1" -uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" -version = "1.2.0" - [[deps.Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" version = "1.11.0" @@ -703,20 +706,20 @@ version = "1.1.2" [[deps.SortingAlgorithms]] deps = ["DataStructures"] -git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085" +git-tree-sha1 = "13cd91cc9be159e3f4d95b857fa2aa383b53772a" uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" -version = "1.2.1" +version = "1.2.3" [[deps.SparseArrays]] deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -version = "1.11.0" +version = "1.12.0" [[deps.SpecialFunctions]] deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] -git-tree-sha1 = "41852b8679f78c8d8961eeadc8f62cef861a52e3" +git-tree-sha1 = "6547cbdd8ce32efba0d21c5a40fa96d1a3548f9f" uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "2.5.1" +version = "2.8.0" [deps.SpecialFunctions.extensions] SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" @@ -736,21 +739,21 @@ weakdeps = ["SparseArrays"] [[deps.StatsAPI]] deps = ["LinearAlgebra"] -git-tree-sha1 = "9d72a13a3f4dd3795a195ac5a44d7d6ff5f552ff" +git-tree-sha1 = "178ed29fd5b2a2cfc3bd31c13375ae925623ff36" uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" -version = "1.7.1" +version = "1.8.0" [[deps.StatsBase]] -deps = ["AliasTables", "DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] -git-tree-sha1 = "b81c5035922cc89c2d9523afc6c54be512411466" +deps = ["AliasTables", "DataAPI", "DataStructures", "IrrationalConstants", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "e4d7a1a0edc20af42689ea6f4f3587a2175d50ee" uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" -version = "0.34.5" +version = "0.34.12" [[deps.StatsFuns]] deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] -git-tree-sha1 = "8e45cecc66f3b42633b8ce14d431e8e57a3e242e" +git-tree-sha1 = "770240df9a3b8888065046948f7a09b4e0f997d5" uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" -version = "1.5.0" +version = "2.2.0" [deps.StatsFuns.extensions] StatsFunsChainRulesCoreExt = "ChainRulesCore" @@ -762,9 +765,9 @@ version = "1.5.0" [[deps.StringManipulation]] deps = ["PrecompileTools"] -git-tree-sha1 = "725421ae8e530ec29bcbdddbe91ff8053421d023" +git-tree-sha1 = "d05693d339e37d6ab134c5ab53c29fce5ee5d7d5" uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" -version = "0.4.1" +version = "0.4.4" [[deps.StructTypes]] deps = ["Dates", "UUIDs"] @@ -772,6 +775,22 @@ git-tree-sha1 = "159331b30e94d7b11379037feeb9b690950cace8" uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" version = "1.11.0" +[[deps.StructUtils]] +deps = ["Dates", "UUIDs"] +git-tree-sha1 = "82bee338d650aa515f31866c460cb7e3bcef90b8" +uuid = "ec057cc2-7a8d-4b58-b3b3-92acb9f63b42" +version = "2.8.2" + + [deps.StructUtils.extensions] + StructUtilsMeasurementsExt = ["Measurements"] + StructUtilsStaticArraysCoreExt = ["StaticArraysCore"] + StructUtilsTablesExt = ["Tables"] + + [deps.StructUtils.weakdeps] + Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" + Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" + [[deps.StyledStrings]] uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b" version = "1.11.0" @@ -783,7 +802,7 @@ uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" [[deps.SuiteSparse_jll]] deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "7.7.0+0" +version = "7.8.3+2" [[deps.TOML]] deps = ["Dates"] @@ -820,9 +839,9 @@ version = "1.11.0" [[deps.TimeZones]] deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] -git-tree-sha1 = "2c705e96825b66c4a3f25031a683c06518256dd3" +git-tree-sha1 = "d422301b2a1e294e3e4214061e44f338cafe18a2" uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" -version = "1.21.3" +version = "1.22.2" weakdeps = ["RecipesBase"] [deps.TimeZones.extensions] @@ -855,19 +874,25 @@ version = "1.11.0" [[deps.WeakRefStrings]] deps = ["DataAPI", "InlineStrings", "Parsers"] -git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23" +git-tree-sha1 = "0716e01c3b40413de5dedbc9c5c69f27cddfddfc" uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" -version = "1.4.2" +version = "1.4.3" [[deps.WorkerUtilities]] git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7" uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" version = "1.6.1" +[[deps.YiemAgent]] +deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs"] +path = "." +uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" +version = "0.4.0" + [[deps.Zlib_jll]] deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+1" +version = "1.3.1+2" [[deps.Zstd_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] @@ -878,7 +903,7 @@ version = "1.5.7+1" [[deps.libblastrampoline_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.11.0+0" +version = "5.15.0+0" [[deps.libsodium_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] @@ -889,9 +914,9 @@ version = "1.0.21+0" [[deps.nghttp2_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.59.0+0" +version = "1.64.0+1" [[deps.p7zip_jll]] -deps = ["Artifacts", "Libdl"] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+2" +version = "17.7.0+0" diff --git a/Project.toml b/Project.toml index 3882fdd..f41bfb4 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "YiemAgent" uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" -authors = ["narawat lamaiin "] version = "0.4.0" +authors = ["narawat lamaiin "] [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" @@ -10,7 +10,7 @@ DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" GeneralUtils = "c6c72f09-b708-4ac8-ac7c-2084d70108fe" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" -JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LLMMCTS = "d76c5a4d-449e-4835-8cc4-dd86ec44f241" LibPQ = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1" NATS = "55e73f9c-eeeb-467f-b4cc-a633fde63d2a" @@ -25,4 +25,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] CSV = "0.10.15" DataFrames = "1.7.0" +GeneralUtils = "0.3.2" +HTTP = "2.4.0" +JSON = "1.6.1" NATS = "0.1.0" diff --git a/example/agent_chat_virtualCustomer.jl b/example/agent_chat_virtualCustomer.jl index 7b9a0e4..b5ace45 100644 --- a/example/agent_chat_virtualCustomer.jl +++ b/example/agent_chat_virtualCustomer.jl @@ -1,5 +1,5 @@ using Revise -using JSON, JSON3, Dates, UUIDs, PrettyPrinting, LibPQ, Base64, DataFrames, DataStructures +using JSON, JSON, Dates, UUIDs, PrettyPrinting, LibPQ, Base64, DataFrames, DataStructures using YiemAgent, GeneralUtils using Base.Threads @@ -8,8 +8,8 @@ using Base.Threads # load config -config = JSON3.read("/appfolder/app/dev/YiemAgent/test/config.json") -# config = copy(JSON3.read("../mountvolume/config.json")) +config = JSON.parsefile("/appfolder/app/dev/YiemAgent/test/config.json") +# config = copy(JSON.parsefile("../mountvolume/config.json")) function executeSQL(sql::T) where {T<:AbstractString} @@ -180,7 +180,7 @@ function similarSommelierDecision(recentevents::T1; maxdistance::Integer=3 println("\n~~~ found similar decision. row id $rowid, distance $distance ", @__FILE__, " ", @__LINE__) output_b64 = df[1, :function_output_base64] # pick the closest match _output_str = String(base64decode(output_b64)) - output = copy(JSON3.read(_output_str)) + output = copy(JSON.parsefile(_output_str)) return output else println("\n~~~ similar decision not found, max distance $maxdistance ", @__FILE__, " ", @__LINE__) @@ -200,7 +200,7 @@ function insertSommelierDecision(recentevents::T1, decision::T2; maxdistance::In if row == 0 || distance > maxdistance # no close enough SQL stored in the database recentevents_embedding = getEmbedding(recentevents)[1] recentevents = replace(recentevents, "'" => "") - decision_json = JSON3.write(decision) + decision_json = JSON.json(decision) decision_base64 = base64encode(decision_json) decision = replace(decision_json, "'" => "") @@ -456,14 +456,14 @@ function main() lastAssistantAction = agent.memory[:events][end][:thought][:actionname] if lastAssistantAction == "ENDCONVERSATION" # store thoughtDict - # save a.memory[:shortmem][:decisionlog] to disk using JSON3 + # save a.memory[:shortmem][:decisionlog] to disk using JSON println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") date = "$(Dates.now())" date = replace(date, ':'=>'.') filename = "agent_decision_log_$(date)_$(agent.id).json" filepath = "/appfolder/mountvolume/appdata/log/$filename" open(filepath, "w") do io - JSON3.pretty(io, agent.memory[:shortmem][:decisionlog]) + JSON.pretty(io, agent.memory[:shortmem][:decisionlog]) end # check how many file in /appfolder/mountvolume/appdata/log/ folder now diff --git a/example/main.jl b/example/main.jl index 7e5d8c9..781feb0 100644 --- a/example/main.jl +++ b/example/main.jl @@ -1,4 +1,4 @@ -using JSON, JSON3, Dates, UUIDs, PrettyPrinting, LibPQ, Base64, DataFrames, DataStructures +using JSON, JSON, Dates, UUIDs, PrettyPrinting, LibPQ, Base64, DataFrames, DataStructures using YiemAgent, GeneralUtils using Base.Threads @@ -34,7 +34,7 @@ using Base.Threads # load config -config = copy(JSON3.read("../mountvolume/config/config.json")) +config = copy(JSON.parsefile("../mountvolume/config/config.json")) """ Instantiate an agent. One need to specify startmessage and one of gpu location info, Mqtt or Rest. start message must be comply with GeneralUtils's message format @@ -254,7 +254,7 @@ function runAgentInstance( println("\n~~~ found similar decision. row id $rowid, distance $distance ", @__FILE__, " ", @__LINE__) output_b64 = df[1, :function_output_base64] # pick the closest match _output_str = String(base64decode(output_b64)) - output = copy(JSON3.read(_output_str)) + output = copy(JSON.parsefile(_output_str)) return output else println("\n~~~ similar decision not found, max distance $maxdistance ", @__FILE__, " ", @__LINE__) @@ -274,7 +274,7 @@ function runAgentInstance( if row == 0 || distance > maxdistance # no close enough SQL stored in the database recentevents_embedding = getEmbedding(recentevents)[1] recentevents = replace(recentevents, "'" => "") - decision_json = JSON3.write(decision) + decision_json = JSON.json(decision) decision_base64 = base64encode(decision_json) decision = replace(decision_json, "'" => "") @@ -431,12 +431,12 @@ function runAgentInstance( lastAssistantAction = agent.memory[:events][end][:thought][:action_name] if lastAssistantAction == "ENDCONVERSATION" # store thoughtDict - # save a.memory[:shortmem][:decisionlog] to disk using JSON3 + # save a.memory[:shortmem][:decisionlog] to disk using JSON println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") filename = "agent_decision_log_$(Dates.now())_$(agent.id).json" filepath = "/appfolder/app/log/$filename" open(filepath, "w") do io - JSON3.pretty(io, agent.memory[:shortmem][:decisionlog]) + JSON.pretty(io, agent.memory[:shortmem][:decisionlog]) end # for (i, event) in enumerate(agent.memory[:events]) @@ -520,7 +520,7 @@ keepaliveChannel::Channel{Dict} = Channel{Dict}(8) # Define the callback for receiving messages. function onMsgCallback_1(topic, payload) - jobj = JSON3.read(String(payload)) + jobj = JSON.parsefile(String(payload)) incomingMqttMsg = copy(jobj) # convert json object into julia dictionary recursively if occursin("keepalive", topic) diff --git a/src/interface.jl b/src/interface.jl index d19b59a..84db415 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -3,7 +3,7 @@ module interface export addNewMessage, conversation, decisionMaker, reflector, generatechat, generalconversation, detectWineryName, generateSituationReport -using JSON3, DataStructures, Dates, UUIDs, HTTP, Random, PrettyPrinting, Serialization, +using JSON, DataStructures, Dates, UUIDs, HTTP, Random, PrettyPrinting, Serialization, DataFrames, CSV using GeneralUtils using ..type, ..util, ..llmfunction @@ -100,7 +100,7 @@ julia> output_thoughtDict = Dict( function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 ) where {T<:agent} println("\nExecuting YiemAgent decisionMaker()") - # lessonDict = copy(JSON3.read("lesson.json")) + # lessonDict = copy(JSON.parsefile("lesson.json")) # lesson = # if isempty(lessonDict) @@ -118,7 +118,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # did previously. Use them to improve your strategy to help the user. # Here are some lessons in JSON format: - # $(JSON3.write(lessons)) + # $(JSON.json(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. @@ -293,7 +293,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 response = strip(response) responsedict = nothing try - responsedict = copy(JSON3.read(response)) + responsedict = copy(JSON.parsefile(response)) catch println("\nERROR YiemAgent decisionMaker() failed to parse response: $response", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -399,15 +399,15 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # decisionlist = [responsedict] # println("Creating file $filepath") # open(filepath, "w") do io - # JSON3.pretty(io, decisionlist) + # JSON.pretty(io, decisionlist) # end # else # # read the file and append new data - # decisionlist = copy(JSON3.read(filepath)) + # decisionlist = copy(JSON.parsefile(filepath)) # push!(decisionlist, responsedict) # println("Appending new data to file $filepath") # open(filepath, "w") do io - # JSON3.pretty(io, decisionlist) + # JSON.pretty(io, decisionlist) # end # end # println("\nYiemAgent decisionMaker() saved to disk is done. agent $(a.id)") @@ -536,7 +536,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext responsedict = nothing try - responsedict = copy(JSON3.read(response)) + responsedict = copy(JSON.parsefile(response)) catch println("\nERROR YiemAgent generatechat() failed to parse response: $response", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -568,15 +568,15 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext # decisionlist = [responsedict] # println("Creating file $filepath") # open(filepath, "w") do io - # JSON3.pretty(io, decisionlist) + # JSON.pretty(io, decisionlist) # end # else # # read the file and append new data - # decisionlist = copy(JSON3.read(filepath)) + # decisionlist = copy(JSON.parsefile(filepath)) # push!(decisionlist, responsedict) # println("Appending new data to file $filepath") # open(filepath, "w") do io - # JSON3.pretty(io, decisionlist) + # JSON.pretty(io, decisionlist) # end # end @@ -597,7 +597,7 @@ end # Example ```jldoctest -julia> using JSON3, UUIDs, Dates, FileIO, MQTTClient, ChatAgent +julia> using JSON, UUIDs, Dates, FileIO, MQTTClient, ChatAgent julia> const mqttBroker = "mqtt.yiem.cc" julia> mqttclient, connection = MakeConnection(mqttBroker, 1883) julia> tools=Dict( # update input format @@ -966,7 +966,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev responsedict = nothing try - responsedict = copy(JSON3.read(response)) + responsedict = copy(JSON.parsefile(response)) catch println("\nERROR YiemAgent presentbox() failed to parse response: $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -1141,7 +1141,7 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) responsedict = nothing try - responsedict = copy(JSON3.read(response)) + responsedict = copy(JSON.parsefile(response)) catch println("\nERROR YiemAgent generatechat() failed to parse response: $response", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue diff --git a/src/llmfunction.jl b/src/llmfunction.jl index dfefe2f..c028e02 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -4,7 +4,7 @@ export virtualWineUserChatbox, jsoncorrection, checkwine, # recommendbox, virtualWineUserRecommendbox, userChatbox, userRecommendbox, extractWineAttributes_1, extractWineAttributes_2, paraphrase -using HTTP, JSON3, URIs, Random, PrettyPrinting, UUIDs, Dates, DataFrames +using HTTP, JSON, URIs, Random, PrettyPrinting, UUIDs, Dates, DataFrames using GeneralUtils, SQLLLM using ..type, ..util @@ -237,7 +237,7 @@ function virtualWineUserChatbox(config::T1, input::T2, virtualCustomerChatHistor } """ responseJsonStr = jsoncorrection(config, _responseJsonStr, expectedJsonExample) - responseDict = copy(JSON3.read(responseJsonStr)) + responseDict = copy(JSON.parsefile(responseJsonStr)) text::AbstractString = responseDict[:text] select::Union{Nothing, Number} = responseDict[:select] == "null" ? nothing : responseDict[:select] @@ -471,7 +471,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10 responsedict = nothing try - responsedict = copy(JSON3.read(response)) + responsedict = copy(JSON.parsefile(response)) catch println("\nERROR YiemAgent extractWineAttributes_1() failed to parse response: $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -750,7 +750,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2< responsedict = nothing try - responsedict = copy(JSON3.read(response)) + responsedict = copy(JSON.parsefile(response)) catch println("\nERROR YiemAgent extractWineAttributes_2() failed to parse response: $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -867,7 +867,7 @@ function paraphrase(text2textInstructLLM::Function, text::String) Let's begin! """ - #[PENDING] use JSON3 the same as extractWineAttributes_1 is better. change this function to use the same format use decisionMaker + #[PENDING] use JSON the same as extractWineAttributes_1 is better. change this function to use the same format use decisionMaker header = ["Paraphrase:"] dictkey = ["paraphrase"] @@ -919,7 +919,7 @@ function paraphrase(text2textInstructLLM::Function, text::String) dictKey=dictkey, symbolkey=true) for i ∈ [:paraphrase] - if length(JSON3.write(responsedict[i])) == 0 + if length(JSON.json(responsedict[i])) == 0 error("$i is empty ", @__FILE__, ":", @__LINE__, " $(Dates.now())") end end @@ -979,7 +979,7 @@ function jsoncorrection(config::T1, input::T2, correctJsonExample::T3; for attempt in 1:maxattempt try - d = copy(JSON3.read(incorrectjson)) + d = copy(JSON.parsefile(incorrectjson)) correctjson = incorrectjson return correctjson catch e diff --git a/src/type.jl b/src/type.jl index 7071571..10260f6 100644 --- a/src/type.jl +++ b/src/type.jl @@ -2,7 +2,7 @@ module type export agent, sommelier, companion, virtualcustomer, appcontext -using Dates, UUIDs, DataStructures, JSON3, NATS +using Dates, UUIDs, DataStructures, JSON, NATS using GeneralUtils # ---------------------------------------------- 100 --------------------------------------------- # diff --git a/src/util.jl b/src/util.jl index 018adde..1ef6039 100644 --- a/src/util.jl +++ b/src/util.jl @@ -4,7 +4,7 @@ export clearhistory, addNewMessage, chatHistoryToText, eventdict, noises, create availableWineToText, createEventsLog, createChatLog, checkAgentResponse_JSON, checkAgentResponse_text -using UUIDs, Dates, DataStructures, HTTP, JSON3 +using UUIDs, Dates, DataStructures, HTTP, JSON using GeneralUtils using ..type diff --git a/test/chatting_with_agent.jl b/test/chatting_with_agent.jl index 4da18c3..5e66a0f 100644 --- a/test/chatting_with_agent.jl +++ b/test/chatting_with_agent.jl @@ -8,8 +8,8 @@ using Base.Threads # load config -config = JSON3.read("/appfolder/app/dev/YiemAgent/test/config.json") -# config = copy(JSON3.read("../mountvolume/config.json")) +config = JSON.parsefile("/appfolder/app/dev/YiemAgent/test/config.json") +# config = copy(JSON.parsefile("../mountvolume/config.json")) function executeSQL(sql::T) where {T<:AbstractString} @@ -179,7 +179,7 @@ function similarSommelierDecision(recentevents::T1; maxdistance::Integer=3 println("\n~~~ found similar decision. row id $rowid, distance $distance ", @__FILE__, " ", @__LINE__) output_b64 = df[1, :function_output_base64] # pick the closest match _output_str = String(base64decode(output_b64)) - output = copy(JSON3.read(_output_str)) + output = copy(JSON.parsefile(_output_str)) return output else println("\n~~~ similar decision not found, max distance $maxdistance ", @__FILE__, " ", @__LINE__) @@ -199,7 +199,7 @@ function insertSommelierDecision(recentevents::T1, decision::T2; maxdistance::In if row == 0 || distance > maxdistance # no close enough SQL stored in the database recentevents_embedding = getEmbedding(recentevents)[1] recentevents = replace(recentevents, "'" => "") - decision_json = JSON3.write(decision) + decision_json = JSON.json(decision) decision_base64 = base64encode(decision_json) decision = replace(decision_json, "'" => "") diff --git a/test/prompttest.jl b/test/prompttest.jl index bab5a3a..b75dd4c 100644 --- a/test/prompttest.jl +++ b/test/prompttest.jl @@ -46,7 +46,7 @@ thoughtDict = OrderedDict( :Observation_6=> "I don't like it. Do you have another option?", ) -_thoughtJsonStr = JSON3.write(thoughtDict) +_thoughtJsonStr = JSON.json(thoughtDict) thoughtJsonStr = _thoughtJsonStr[1:end-1] # remove } at the end # @show thoughtJsonStr @@ -100,7 +100,7 @@ Here are some examples: Let's begin! -$(JSON3.write(thoughtDict)) +$(JSON.json(thoughtDict)) {Thought_$nextThoughtIndice """ diff --git a/test/prompttest_1.jl b/test/prompttest_1.jl index 2804269..c736b5b 100644 --- a/test/prompttest_1.jl +++ b/test/prompttest_1.jl @@ -4,7 +4,7 @@ using Base.Threads # ---------------------------------------------- 100 --------------------------------------------- # -config = copy(JSON3.read("config.json")) +config = copy(JSON.parsefile("config.json")) instanceInternalTopic = config[:serviceInternalTopic][:mqtttopic] * "/1" From f6eaf4751b601d3318ad220eb5d9f53597e1efa7 Mon Sep 17 00:00:00 2001 From: narawat Date: Sun, 21 Jun 2026 09:48:17 +0700 Subject: [PATCH 14/23] update --- Manifest.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Manifest.toml b/Manifest.toml index d79f83d..bf971b5 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -884,7 +884,7 @@ uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" version = "1.6.1" [[deps.YiemAgent]] -deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs"] +deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs"] path = "." uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" version = "0.4.0" From 906afc6422ff02d4725d3948153027ee537ee7e9 Mon Sep 17 00:00:00 2001 From: narawat Date: Wed, 24 Jun 2026 08:47:36 +0700 Subject: [PATCH 15/23] update --- src/interface.jl | 120 ++++++++++++++------------------ src/llmfunction.jl | 2 +- src/type.jl | 161 +++++++++++++++++-------------------------- src/util.jl | 45 +++++------- test/prompttest_1.jl | 2 +- test/runtests.jl | 108 +++++++++++++++++++++++++++++ 6 files changed, 244 insertions(+), 194 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index 84db415..7d1297b 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -82,7 +82,7 @@ julia> config = Dict( julia> output_thoughtDict = Dict( :thought_1 => "The customer wants to buy a bottle of wine. This is a good start!", - :action_1 => Dict{Symbol, Any}( + :action_1 => Dict{String, Any}( :action=>"CHATBOX", :input=>"What occasion are you buying the wine for?" ), @@ -106,7 +106,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # if isempty(lessonDict) # "" # else - # lessons = Dict{Symbol, Any}() + # lessons = Dict{String, Any}() # for (k, v) in lessonDict # lessons[k] = lessonDict[k][:lesson] # end @@ -588,57 +588,31 @@ end """ Chat with llm. -# Arguments - `a::agent` - an agent - -# Return - None +# Example userinput -# Example -```jldoctest -julia> using JSON, UUIDs, Dates, FileIO, MQTTClient, ChatAgent -julia> const mqttBroker = "mqtt.yiem.cc" -julia> mqttclient, connection = MakeConnection(mqttBroker, 1883) -julia> tools=Dict( # update input format - "askbox"=>Dict( - :description => "Useful for when you need to ask the user for more context. Do not ask the user their own question.", - :input => "Input is a text in JSON format.{\"Q1\": \"How are you doing?\", \"Q2\": \"How may I help you?\"}", - :output => "" , - :func => nothing, - ), +image_path = "test/large_image.png" +image_bytes = read(image_path) +base64_string = base64encode(image_bytes) + +# 2. Match the MIME type according to your file extension (e.g., png, jpeg) +mime_type = "image/png" +data_uri = "data:$(mime_type);base64,$(base64_string)" + +# 3. Construct payload with the Data URI +message => Dict( + "role" => "user", + "content" => [ + Dict("type" => "text", "text" => "Describe this image for me"), + Dict( + "type" => "image_url", + "image_url" => Dict("url" => data_uri) ) -julia> msgMeta = Dict( - :msgPurpose=> "updateStatus", - :from=> "agent", - :to=> "llmAI", - :requestresponse=> "request", - :sendto=> "", # destination topic - :replyTo=> "agent/api/v0.1.0/txt/response", # requester ask responseer to send reply to this topic - :repondToMsgId=> "", # responseer is responseing to this msg id - :taskstatus=> "", # "complete", "fail", "waiting" or other status - :timestamp=> Dates.now(), - :msgId=> "$(uuid4())", -) -julia> a = ChatAgent.agentReflex( - "Jene", - mqttclient, - msgMeta, - agentConfigTopic, # I need a function to send msg to config topic to get load balancer - role=:sommelier, - tools=tools - ) -julia> newAgent = ChatAgent.agentReact(agent) -julia> response = ChatAgent.conversation(newAgent, "Hi! how are you?") -``` + ] + ) -# TODO - - [] update docstring - - [] add recap to initialState for earlier completed question - -# Signature +- TODO add recap to initialState for earlier completed question """ -function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, +function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, maximumMsg=50) # place holder @@ -646,7 +620,20 @@ function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, result = nothing chatresponse = nothing - if userinput === nothing + userinput = GeneralUtils.dictify(userinput) + + user_text_input, text_position = + if userinput !== nothing + for (i, d) in enumerate(userinput["content"]) + if d["type"] == "text" + (d["text"], i) + end + end + else + (nothing, nothing) + end + + if user_text_input === nothing # thinking loop until AI wants to communicate with the user chatresponse = nothing while chatresponse === nothing @@ -658,24 +645,24 @@ function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg) return chatresponse - elseif userinput[:text] == "newtopic" + elseif user_text_input == "newtopic" clearhistory(a) return "Okay. What shall we talk about?" else - userinput[:text] = GeneralUtils.remove_french_accents(userinput[:text]) - # add usermsg to a.chathistory - addNewMessage(a, "user", userinput[:text]; maximumMsg=maximumMsg) + userinput["content"][text_position] = GeneralUtils.remove_french_accents(user_text_input) + # add usermsg to a.chathistory but how do I handle images? + addNewMessage(a, "user", userinput; maximumMsg=maximumMsg) # add user activity to events memory - push!(a.memory[:events], - eventdict(; - event_description="the user talks to the assistant.", - timestamp=Dates.now(), - subject="user", - actionname="CHATBOX", - actioninput=userinput[:text], - ) - ) + # push!(a.memory[:events], + # eventdict(; + # event_description="the user talks to the assistant.", + # timestamp=Dates.now(), + # subject="user", + # actionname="CHATBOX", + # actioninput=userinput[:text], + # ) + # ) # thinking loop until AI wants to communicate with the user chatresponse = nothing @@ -742,11 +729,8 @@ end julia> ``` -# TODO - - [] update docstring - -# Signature -""" +TODO update docstring +""" # WORKING function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} where {T<:agent} # a.memory[:recap] = generateSituationReport(a, a.context[:text2textInstructLLM]; skiprecent=0) thoughtDict = decisionMaker(a) diff --git a/src/llmfunction.jl b/src/llmfunction.jl index c028e02..13233d2 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -174,7 +174,7 @@ function virtualWineUserChatbox(config::T1, input::T2, virtualCustomerChatHistor pushfirst!(virtualCustomerChatHistory, Dict(:name=> "system", :text=> systemmsg)) # replace the :user key in chathistory to allow the virtual wine customer AI roleplay - chathistory::Vector{Dict{Symbol, Any}} = Vector{Dict{Symbol, Any}}() + chathistory::Vector{Dict{String, Any}} = Vector{Dict{String, Any}}() for i in virtualCustomerChatHistory newdict = Dict() newdict[:name] = diff --git a/src/type.jl b/src/type.jl index 10260f6..7c4bfde 100644 --- a/src/type.jl +++ b/src/type.jl @@ -1,6 +1,6 @@ module type -export agent, sommelier, companion, virtualcustomer, appcontext +export agent, sommelier, companion, virtualcustomer, agentcontext using Dates, UUIDs, DataStructures, JSON, NATS using GeneralUtils @@ -8,11 +8,9 @@ using GeneralUtils # ---------------------------------------------- 100 --------------------------------------------- # -mutable struct appcontext - const connection::NATS.Connection - const text2textInstructLLMServiceSubject::String - getTextEmbedding::Function +mutable struct agentcontext text2textInstructLLM::Function + getTextEmbedding::Function executeSQL::Function similarSQLVectorDB::Function insertSQLVectorDB::Function @@ -28,14 +26,14 @@ mutable struct companion <: agent systemmsg::String # system message tools::Dict # tools maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized - chathistory::Vector{Dict{Symbol, Any}} - memory::Dict{Symbol, Any} + chathistory::Vector{Dict{String, Any}} + memory::Dict{String, Any} context::NamedTuple # NamedTuple of functions llmFormatName::String end function companion( - context::appcontext # NamedTuple of functions + context::agentcontext # NamedTuple of functions ; name::String= "Assistant", id::String= GeneralUtils.uuid4snakecase(), @@ -69,10 +67,10 @@ function companion( Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()), ] """ - memory = Dict{Symbol, Any}( - :events=> Vector{Dict{Symbol, Any}}(), - :state=> Dict{Symbol, Any}(), # state of the agent - :recap=> OrderedDict{Symbol, Any}(), # recap summary of the conversation + memory = Dict{String, Any}( + :events=> Vector{Dict{String, Any}}(), + :state=> Dict{String, Any}(), # state of the agent + :recap=> OrderedDict{String, Any}(), # recap summary of the conversation ) newAgent = companion( @@ -91,89 +89,58 @@ function companion( end - - -""" A sommelier agent. - -# Arguments - - `mqttClient::Client` - MQTTClient's client - - `msgMeta::Dict{Symbol, Any}` - A dict contain info about a message. - - `config::Dict{Symbol, Any}` - Config info for an agent. Contain mqtt topic for internal use and other info. - -# Keyword Arguments - - `name::String` - Agent's name - - `id::String` - Agent's ID - - `tools::Dict{Symbol, Any}` - Agent's tools - - `maxHistoryMsg::Integer` - max history message - -# Return - - `nothing` - -# Example -```jldoctest -julia> using YiemAgent, MQTTClient, GeneralUtils -julia> msgMeta = GeneralUtils.generate_msgMeta( - "N/A", - replyTopic = "/testtopic/prompt" - ) -julia> tools= Dict( - :chatbox=>Dict( - :name => "chatbox", - :description => "Useful only for when you need to ask the user for more info or context. Do not ask the user their own question.", - :input => "Input should be a text.", - :output => "" , - :func => nothing, - ), - ) -julia> agentConfig = Dict( - :receiveprompt=>Dict( - :mqtttopic=> "/testtopic/prompt", # topic to receive prompt i.e. frontend send msg to this topic - ), - :receiveinternal=>Dict( - :mqtttopic=> "/testtopic/internal", # receive topic for model's internal - ), - :text2text=>Dict( - :mqtttopic=> "/text2text/receive", - ), - ) -julia> client, connection = MakeConnection("test.mosquitto.org", 1883) -julia> agent = YiemAgent.bsommelier( - client, - msgMeta, - agentConfig, - name= "assistant", - id= "555", # agent instance id - tools=tools, - ) -``` - -# TODO -- [] update docstring -- [x] implement the function - -# Signature -""" mutable struct sommelier <: agent name::String # agent name id::String # agent id retailername::String tools::Dict maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized - chathistory::Vector{Dict{Symbol, Any}} - memory::Dict{Symbol, Any} - context # NamedTuple of functions + chathistory::Vector{Dict{String, Any}} + memory::Dict{String, Any} + context::agentcontext llmFormatName::String end + +""" A sommelier agent. +# Arguments + - `context::agentcontext` + Application context containing shared functions for LLM, SQL, and vector database operations. + +# Keyword Arguments + - `name::String` + Agent's name. Default: `"Assistant"` + - `id::String` + Agent's ID. Default: generated UUID string. + - `retailername::String` + Retailer name associated with the sommelier. Default: `"retailer_name"` + - `maxHistoryMsg::Integer` + Maximum history messages. Default: `20` + - `chathistory::Vector{Dict{Symbol, String}}` + Chat history. Default: empty vector. + - `llmFormatName::String` + LLM format name. Default: `"granite3"` + +# Return + - `sommelier`: An instantiated sommelier agent. + +# Example +```julia +julia> using YiemAgent +julia> context = agentcontext( + text2textInstructLLM, + getTextEmbedding, + executeSQL, + similarSQLVectorDB, + insertSQLVectorDB, + similarSommelierDecision, + insertSommelierDecision + ) +julia> agent = sommelier(context, name="WineExpert", id="123", retailername="MyWineShop") +``` +""" function sommelier( - context::appcontext, # app context + context::agentcontext, # app context ; name::String= "Assistant", id::String= string(uuid4()), @@ -204,15 +171,15 @@ function sommelier( Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()), ] """ - memory = Dict{Symbol, Any}( - :shortmem=> OrderedDict{Symbol, Any}( + memory = Dict{String, Any}( + :shortmem=> OrderedDict{String, Any}( :db_search_result=> Any[], :scratchpad=> "", #[PENDING] should be a dict e.g. Dict(:database_search_result=>Dict(:wines=> "", :search_query=> "")) ), - :events=> Vector{Dict{Symbol, Any}}(), - :state=> Dict{Symbol, Any}( + :events=> Vector{Dict{String, Any}}(), + :state=> Dict{String, Any}( ), - :recap=> OrderedDict{Symbol, Any}(), + :recap=> OrderedDict{String, Any}(), ) @@ -238,8 +205,8 @@ mutable struct virtualcustomer <: agent systemmsg::String # system message tools::Dict maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized - chathistory::Vector{Dict{Symbol, Any}} - memory::Dict{Symbol, Any} + chathistory::Vector{Dict{String, Any}} + memory::Dict{String, Any} context # NamedTuple of functions llmFormatName::String end @@ -281,13 +248,13 @@ function virtualcustomer( Dict(:name=>"assistant", :text=> "Hi I'm your assistant.", :timestamp=> Dates.now()), ] """ - memory = Dict{Symbol, Any}( - :shortmem=> OrderedDict{Symbol, Any}( + memory = Dict{String, Any}( + :shortmem=> OrderedDict{String, Any}( ), - :events=> Vector{Dict{Symbol, Any}}(), - :state=> Dict{Symbol, Any}( + :events=> Vector{Dict{String, Any}}(), + :state=> Dict{String, Any}( ), - :recap=> OrderedDict{Symbol, Any}(), + :recap=> OrderedDict{String, Any}(), ) newAgent = virtualcustomer( diff --git a/src/util.jl b/src/util.jl index 1ef6039..689809f 100644 --- a/src/util.jl +++ b/src/util.jl @@ -60,6 +60,17 @@ end """ Add new message to agent. + messages => Dict( + "role" => "user", + "content" => [ + Dict("type" => "text", "text" => "Describe this image for me"), + Dict( + "type" => "image_url", + "image_url" => Dict("url" => data_uri) + ) + ] + ) + Arguments\n ----- a::agent @@ -76,44 +87,24 @@ end Example\n ----- ```jldoctest - julia> using YiemAgent, MQTTClient, GeneralUtils - julia> client, connection = MakeConnection("test.mosquitto.org", 1883) - julia> connect(client, connection) - julia> msgMeta = GeneralUtils.generate_msgMeta("testtopic") - julia> agentConfig = Dict( - :receiveprompt=>Dict( - :mqtttopic=> "testtopic/receive", - ), - :receiveinternal=>Dict( - :mqtttopic=> "testtopic/internal", - ), - :text2text=>Dict( - :mqtttopic=> "testtopic/text2text", - ), - ) - julia> a = YiemAgent.sommelier( - client, - msgMeta, - agentConfig, - ) - julia> YiemAgent.addNewMessage(a, "user", "hello") + ``` Signature\n ----- """ -function addNewMessage(a::T1, name::String, text::T2; - maximumMsg::Integer=30) where {T1<:agent, T2<:AbstractString} +function addNewMessage(a::T1, name::String, userinput::T2; + maximumMsg::Integer=30) where {T1<:agent, T2<:AbstractDict} if name ∉ ["system", "user", "assistant"] # guard against typo error("name is not in agent.availableRole $(@__LINE__)") end - #[PENDING] summarize the oldest 10 message + #TODO summarize the oldest 10 message if length(a.chathistory) > maximumMsg summarize(a.chathistory) else - d = Dict(:name=> name, :text=> text, :timestamp=> Dates.now()) - push!(a.chathistory, d) + userinput["timestamp"] = Dates.now() + push!(a.chathistory, userinput) end end @@ -241,7 +232,7 @@ function eventdict(; note::Union{String, Nothing}=nothing, ) - d = Dict{Symbol, Any}( + d = Dict{String, Any}( :event_description=> event_description, :timestamp=> timestamp, :subject=> subject, diff --git a/test/prompttest_1.jl b/test/prompttest_1.jl index c736b5b..229fbc6 100644 --- a/test/prompttest_1.jl +++ b/test/prompttest_1.jl @@ -66,7 +66,7 @@ tools=Dict( # update input format input = -OrderedDict{Symbol, Any}(:question => "Hello, I would like a get a bottle of wine", :thought_1 => "It's great that the user is looking for a bottle of wine. To give them a personalized recommendation, I need to know more about their preferences.", :action_1 => Dict{Symbol, Any}(:name => "chatbox", :input => "What occasion are you planning to use this wine for?"), :observation_1 => "We are holding a wedding party", :thought_2 => "A wedding party is a great occasion for a special bottle of wine. I need to know what type of food will be served, and how much the user is willing to spend.", :action_2 => Dict{Symbol, Any}(:name => "chatbox", :input => "What type of food will you be serving at the wedding?"), :observation_2 => "It will be Thai dishes.", :thought_3 => "The type of wine that pairs well with Thai dishes is usually a crisp and refreshing white wine, but I also need to consider the budget and personal preferences.", :action_3 => Dict{Symbol, Any}(:name => "chatbox", :input => "How much are you willing to spend on this bottle of wine?"), :observation_3 => "I would spend up to 50 bucks.", :thought_4 => "I have a good idea of the occasion, food, and budget. Now I need to know what type of wine the user is looking for.", :action_4 => Dict{Symbol, Any}(:name => "chatbox", :input => "What type of wine are you usually looking for? Red, White, Sparkling, Rose, Dessert or Fortified?"), :observation_4 => "I like full-bodied Red wine with low tannin.", :thought_5 => "Now that I have all the necessary information, I can start searching for a suitable wine in our inventory.", :action_5 => Dict{Symbol, Any}(:name => "winestock", :input => "red wine with low tannins"), :observation_5 => "I found the following wines in our stock: \n{\n 1: El Enemigo Cabernet Franc 2019\n2: Tantara Chardonnay 2017\n\n}\n", :thought_6 => "Now that I have the information about the wine, it's time to make a recommendation.", :action_6 => Dict{Symbol, Any}(:name => "recommendbox", :input => "El Enemigo Cabernet Franc 2019"), :observation_6 => "I don't like the one you recommend. I want dry wine.") +OrderedDict{String, Any}(:question => "Hello, I would like a get a bottle of wine", :thought_1 => "It's great that the user is looking for a bottle of wine. To give them a personalized recommendation, I need to know more about their preferences.", :action_1 => Dict{String, Any}(:name => "chatbox", :input => "What occasion are you planning to use this wine for?"), :observation_1 => "We are holding a wedding party", :thought_2 => "A wedding party is a great occasion for a special bottle of wine. I need to know what type of food will be served, and how much the user is willing to spend.", :action_2 => Dict{String, Any}(:name => "chatbox", :input => "What type of food will you be serving at the wedding?"), :observation_2 => "It will be Thai dishes.", :thought_3 => "The type of wine that pairs well with Thai dishes is usually a crisp and refreshing white wine, but I also need to consider the budget and personal preferences.", :action_3 => Dict{String, Any}(:name => "chatbox", :input => "How much are you willing to spend on this bottle of wine?"), :observation_3 => "I would spend up to 50 bucks.", :thought_4 => "I have a good idea of the occasion, food, and budget. Now I need to know what type of wine the user is looking for.", :action_4 => Dict{String, Any}(:name => "chatbox", :input => "What type of wine are you usually looking for? Red, White, Sparkling, Rose, Dessert or Fortified?"), :observation_4 => "I like full-bodied Red wine with low tannin.", :thought_5 => "Now that I have all the necessary information, I can start searching for a suitable wine in our inventory.", :action_5 => Dict{String, Any}(:name => "winestock", :input => "red wine with low tannins"), :observation_5 => "I found the following wines in our stock: \n{\n 1: El Enemigo Cabernet Franc 2019\n2: Tantara Chardonnay 2017\n\n}\n", :thought_6 => "Now that I have the information about the wine, it's time to make a recommendation.", :action_6 => Dict{String, Any}(:name => "recommendbox", :input => "El Enemigo Cabernet Franc 2019"), :observation_6 => "I don't like the one you recommend. I want dry wine.") result = YiemAgent.jsoncorrection(a, input) diff --git a/test/runtests.jl b/test/runtests.jl index e69de29..8c2658b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -0,0 +1,108 @@ + +using JSON, Dates, UUIDs, PrettyPrinting, Base64, NATS, HTTP +using GeneralUtils, msghandler + +config = JSON.parsefile("./appconfig.json") + +agent_conn = NATS.connect(config["nats_server_info"]["url"]) + +function text2text_instruct_llm(openai_msg::AbstractDict) + payloads = [("msg", openai_msg, "dictionary")] # List of tuples + _, msg_envelope_json_str = msghandler.smartpack( + config["externalService"]["servicesloadbalancer"]["nats"], + payloads; + msg_purpose="text2text", + broker_url=config["nats_server_info"]["url"], + fileserver_url=config["externalService"]["fileserver"]["url"]) + + reply = NATS.request(agent_conn, + config["externalService"]["servicesloadbalancer"]["nats"], + msg_envelope_json_str, timeout=120) + + incoming_env_json_str = String(reply.payload) + incoming_env = msghandler.smartunpack(incoming_env_json_str) + _llm_response = incoming_env["payloads"][1][2] + llm_response = _llm_response["choices"][1]["message"]["content"] + return llm_response +end + + + + +# 1. Read local file and encode to base64 string +image1_path = "test/large_image.png" +image1_bytes = read(image1_path) +image1_base64_string = base64encode(image1_bytes) + +# 2. Match the MIME type according to your file extension (e.g., png, jpeg) +mime_type = "image/png" +data1_uri = "data:$(mime_type);base64,$(image1_base64_string)" + +# 3. Construct payload with the Data URI +openai_msg = Dict( + "model" => "gemma-4-E4B-it-UD-Q4_K_XL", + "messages" => [ + Dict( + "role" => "user", + "content" => [ + Dict("type" => "text", "text" => "Do you know this wine? Just give me brief intro."), + Dict( + "type" => "image_url", + "image_url" => Dict("url" => data1_uri) + ) + ] + ) + ], + "temperature" => 0.7 +) + +llm_response = text2text_instruct_llm(openai_msg) + + + +# 1. Read local file and encode to base64 string +image2_path = "test/small_image.png" +image2_bytes = read(image2_path) +image2_base64_string = base64encode(image2_bytes) + +# 2. Match the MIME type according to your file extension (e.g., png, jpeg) +mime_type = "image/png" +data2_uri = "data:$(mime_type);base64,$(image2_base64_string)" + + +openai_msg = Dict( + "model" => "gemma-4-E4B-it-UD-Q4_K_XL", + "messages" => [ + Dict( + "role" => "user", + "content" => [ + Dict("type" => "text", "text" => "Do you know this wine? Just give me brief intro."), + Dict( + "type" => "image_url", + "image_url" => Dict("url" => data1_uri) + ) + ] + ), + Dict( + "role" => "assistant", + "content" => [ + Dict("type" => "text", "text" => "Yes, I do!\n\nThis is **Asolo Bella Principessa**, a high-quality Italian sparkling wine made from the Prosecco region.\n\n### 🥂 Brief Intro\n\n* **What it is:** A Prosecco Superiore D.O.C.G., meaning it meets strict quality standards for a premium sparkling wine.\n* **Style:** It is a **Sparkling White Wine** and is designated as **Extra Dry**. This means it is crisp, refreshing, and has a dry finish (not overly sweet).\n* **Flavor Profile:** Expect bright, lively bubbles, often with notes of green apple, pear, and citrus.\n* **Best For:** It's a versatile wine, perfect for celebratory toasts, enjoying with appetizers (like seafood or charcuterie), or simply as a refreshing aperitivo."), + ] + ), + Dict( + "role" => "user", + "content" => [ + Dict("type" => "text", "text" => "How does this wine differ from earlier wine?"), + Dict( + "type" => "image_url", + "image_url" => Dict("url" => data2_uri) + ) + ] + ), + ], + "temperature" => 0.7 +) + +llm_response = text2text_instruct_llm(openai_msg) + + From de2076461067798d85aa862c502df85610c76830 Mon Sep 17 00:00:00 2001 From: narawat Date: Wed, 24 Jun 2026 19:50:43 +0700 Subject: [PATCH 16/23] update --- Manifest.toml | 10 +- Project.toml | 2 +- src/interface.jl | 326 +++++++++++-------------------------------- src/type.jl | 80 +++++++++++ test/large_image.png | Bin 0 -> 1232619 bytes test/runtests.jl | 56 ++++++++ test/small_image.png | Bin 0 -> 1328187 bytes 7 files changed, 224 insertions(+), 250 deletions(-) create mode 100644 test/large_image.png create mode 100644 test/small_image.png diff --git a/Manifest.toml b/Manifest.toml index bf971b5..83d63ea 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.12.6" manifest_format = "2.0" -project_hash = "e6bd85ad2679c39ab370f878253f2eeb45c1b6ae" +project_hash = "7462b22f4fd62982e36c8671793df6d8908c9ad0" [[deps.AliasTables]] deps = ["PtrArrays", "Random"] @@ -217,11 +217,11 @@ version = "1.11.0" [[deps.GeneralUtils]] deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "UUIDs"] -git-tree-sha1 = "8720a31344bc85ad610ae12f7e1247de22070765" +git-tree-sha1 = "76d2628787838a67d6e8192e428991a7522883f0" repo-rev = "main" repo-url = "https://git.yiem.cc/ton/GeneralUtils" uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe" -version = "0.3.2" +version = "0.4.0" [[deps.HTTP]] deps = ["Base64", "CodecZlib", "Dates", "EnumX", "PrecompileTools", "Random", "Reseau", "SHA", "URIs", "UUIDs", "Zlib_jll"] @@ -662,7 +662,7 @@ uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" version = "0.7.0" [[deps.SQLLLM]] -deps = ["CSV", "DataFrames", "DataStructures", "Dates", "FileIO", "GeneralUtils", "HTTP", "JSON3", "LLMMCTS", "LibPQ", "PrettyPrinting", "Random", "Revise", "StatsBase", "Tables", "URIs", "UUIDs"] +deps = ["CSV", "DataFrames", "DataStructures", "Dates", "FileIO", "HTTP", "JSON3", "LLMMCTS", "LibPQ", "PrettyPrinting", "Random", "Revise", "StatsBase", "Tables", "URIs", "UUIDs"] path = "../SQLLLM" uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3" version = "0.2.4" @@ -884,7 +884,7 @@ uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" version = "1.6.1" [[deps.YiemAgent]] -deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs"] +deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "Serialization", "URIs", "UUIDs"] path = "." uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" version = "0.4.0" diff --git a/Project.toml b/Project.toml index f41bfb4..7f390db 100644 --- a/Project.toml +++ b/Project.toml @@ -25,7 +25,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] CSV = "0.10.15" DataFrames = "1.7.0" -GeneralUtils = "0.3.2" +GeneralUtils = "0.4.0" HTTP = "2.4.0" JSON = "1.6.1" NATS = "0.1.0" diff --git a/src/interface.jl b/src/interface.jl index 7d1297b..2ddbbca 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -70,11 +70,11 @@ julia> config = Dict( :broker => "mqtt.yiem.cc" ), :externalservice => Dict( - :text2textinstruct => Dict( + "text"2textinstruct => Dict( :mqtttopic => "/loadbalancer/requestingservice", :description => "text to text service with instruct LLM", :llminfo => Dict( - :name => "llama3instruct" + "name" => "llama3instruct" ) ), ) @@ -89,14 +89,11 @@ julia> output_thoughtDict = Dict( :observation_1 => "" ) ``` - -# TODO - [] update docstring - [] use customerinfo - [] user storeinfo -# Signature -""" +""" #WORKING function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 ) where {T<:agent} println("\nExecuting YiemAgent decisionMaker()") @@ -125,158 +122,23 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # """ # end - recentevents_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recentevents; - includelatest=true) - timeline = createTimeline(a.memory[:events]; eventindex=recentevents_ind) + recentevents_ind = GeneralUtils.recentElementsIndex( + length(a.memory[:events]), recentevents; includelatest=true) - # recentchat_ind = GeneralUtils.recentElementsIndex(length(a.chathistory), recentevents; - # includelatest=true) - # recentchat = createChatLog(a.chathistory; index=recentchat_ind) - recentEvents = createEventsLog(a.memory[:events]; index=recentevents_ind) + requiredKeys = ["plan", "actionname", "actioninput"] - - # # recap as caching - # # query similar result from vectorDB - # recapkeys = keys(a.memory[:recap]) - # _recapkeys_vec = [i for i in recapkeys] + errornote = "N/A" + response = nothing # placeholder for show when error msg show up - # # 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 - # 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 - - systemmsg = - """ - - Your name is $(a.name). You are a sommelier for website-based $(a.retailername)'s wine store. You are working under your mentor supervision. - - - Your customer is coming into the store - - - 1) Establish a connection with the customer by talking to them politely and showing your enthusiasm for their wine preferences. - 2) Provide relevant information and guide them to select the best wines only from your store's inventory that align with their preferences. - - - 1) According to the store's policy and guidelines, make an informed decision about what you need to do to achieve the goal - 2) Keep the conversation with the customer going smoothly - 2) Obey your mentor's suggestions. - - - 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. - - - context: additional information about the current situation - - - 1) plan: Based on the current situation, state a complete action plan to complete the task. Be specific. - 2) actionname: (Typically corresponds to the execution of the first step in your plan) Can be one of the available tool name - 3) actioninput: The input to the action you are about to perform according to your plan. - - - { - "plan": "...", - "actionname": "...", - "actioninput": "..." - } - - - Let's begin! - """ - requiredKeys = [:plan, :actionname, :actioninput] - # database_search_result = - # if length(a.memory[:shortmem][:db_search_result]) != 0 - # availableWineToText(a.memory[:shortmem][:db_search_result]) - # else - # "N/A" - # end - - errornote = "N/A" - response = nothing # placeholder for show when error msg show up for attempt in 1:maxattempt if attempt > 1 println("\nYiemAgent decisionMaker() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())") end - - # QandA = generatequestion(a, a.context[:text2textInstructLLM], timeline) - - context = - """ - - - - Generally speaking, the store inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know exactly until you check your inventory. - - If you found wines in the store's database, they are in stock. - - You can only recommend wines that are currently in our inventory - - Before searching the database for wine, ensure you have at least the following information: 1) budget, 2) wine type, and 3) occasion. Additional details are always helpful. If the user is unsure, provide relevant information and gather insights to make reasonable inferences. - - Ask the user one question at a time. - - 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, if you haven't already, ask the user whether they need any further assistance. Do not offer any additional services. - - Only end the conversation when the user explicitly intends to do so. When ending, ensure a polite farewell and an invitation to return in the future. - - Spicy foods should be paired only with light red wines. - - We do not sell organic, sustainable, gluten-free, and sulfite-free wine. Inform the user imediately if they are looking for these types of wines. Do not sell our wines as such. - - Gift box, gift card, and custom messages are available. Inform the user to contact our sales team. - - - - Greeting the customer warmly by ask them how could you help. Do not ask any other questions during this greeting. - - Encourage the customer to explore different options and try new things. - - If you are unable to locate the desired item in the database after 2 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. - - Your store carries only wine. - - Vintage 0 means non-vintage. - - Start searching the database as broadly as possible within the given information boundary to maximize the chances of finding. Avoid unnecessary parameters unless specified by the user. Refine the search subsequently. - Search the database as broad as possible under the informantion you have will increase the chance to find wine. Avoid uneccessary parameter such as region, country, tasting notes unless the user specify - - - CHATBOX which you can use to talk with the user. Be specific. - - 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 1: "Dry, full-bodied red wine from 1) region: Burgundy, country: France or 2) region: Tuscany, country: Italy. Grape varietal: Merlot or Syrah. price 100 to 1000 USD." - Example query 2: "Red or white wine, medium tannin, price under 700 USD" - Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France - - 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. The output is presentation of the wines. - - 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. - - $(a.memory[:shortmem][:scratchpad]) - Remark: $errornote - - """ unformatPrompt = [ - Dict(:name => "system", :text => systemmsg), + Dict("name" => "system", "text" => systemmsg), ] unformatPrompt = vcat(unformatPrompt, recentEvents) @@ -322,9 +184,9 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # continue # end - if responsedict[:actionname] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"] + if responsedict["actionname"] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"] errornote = "Your previous attempt didn't use the given functions" - println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict[:actionname])", @__FILE__, ":", @__LINE__, " $(Dates.now())") + println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict["actionname"])", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue end @@ -359,8 +221,8 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 delete!(responsedict, :mentioned_winery) - # check whether responsedict[:actioninput] is the same as previous dialogue - if !isempty(a.chathistory) && responsedict[:actioninput] == a.chathistory[end][:text] + # check whether responsedict["actioninput"] is the same as previous dialogue + if !isempty(a.chathistory) && 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 @@ -384,10 +246,10 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # responsedict[:QandA] = QandA # check whether there is a file path exists before writing to it - if !haskey(a.memory[:shortmem], :decisionlog) - a.memory[:shortmem][:decisionlog] = [responsedict] + if !haskey(a.memory["shortmem"], :decisionlog) + a.memory["shortmem"][:decisionlog] = [responsedict] else - push!(a.memory[:shortmem][:decisionlog], responsedict) + push!(a.memory["shortmem"][:decisionlog], responsedict) end # # save to filename ./log/decisionlog.txt @@ -512,7 +374,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext $evaluateecontext - {plan: $(decisiondict[:plan]), actionname: $(decisiondict[:actionname]), actioninput: $(decisiondict[:actioninput])} + {plan: $(decisiondict["plan"]), actionname: $(decisiondict["actionname"]), actioninput: $(decisiondict["actioninput"])} P.S. $errornote @@ -520,7 +382,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext unformatPrompt = [ - Dict(:name => "system", :text => systemmsg), + Dict("name" => "system", "text" => systemmsg), ] # put in model format @@ -610,30 +472,17 @@ message => Dict( ] ) -- TODO add recap to initialState for earlier completed question -""" -function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, - maximumMsg=50) - +# ---------------------------------------------- 100 --------------------------------------------- # +""" #WORKING +function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Object{String, Any}}, maximumMsg=50) + userinput = GeneralUtils.dictify(userinput; keytype=String) + # place holder actionname = nothing result = nothing chatresponse = nothing - userinput = GeneralUtils.dictify(userinput) - - user_text_input, text_position = - if userinput !== nothing - for (i, d) in enumerate(userinput["content"]) - if d["type"] == "text" - (d["text"], i) - end - end - else - (nothing, nothing) - end - - if user_text_input === nothing + if userinput === nothing # thinking loop until AI wants to communicate with the user chatresponse = nothing while chatresponse === nothing @@ -642,6 +491,7 @@ function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, chatresponse = result end end + addNewMessage(a, "assistant", chatresponse; maximumMsg=maximumMsg) return chatresponse @@ -653,17 +503,6 @@ function conversation(a::sommelier; userinput::Union{Dict, Nothing}=nothing, # add usermsg to a.chathistory but how do I handle images? addNewMessage(a, "user", userinput; maximumMsg=maximumMsg) - # add user activity to events memory - # push!(a.memory[:events], - # eventdict(; - # event_description="the user talks to the assistant.", - # timestamp=Dates.now(), - # subject="user", - # actionname="CHATBOX", - # actioninput=userinput[:text], - # ) - # ) - # thinking loop until AI wants to communicate with the user chatresponse = nothing while chatresponse === nothing @@ -684,12 +523,12 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; chatresponse = nothing - if userinput[:text] == "newtopic" + if userinput["text"] == "newtopic" clearhistory(a) return "Okay. What shall we talk about?" else # add usermsg to a.chathistory - addNewMessage(a, "user", userinput[:text]; maximumMsg=maximumMsg) + addNewMessage(a, "user", userinput["text"]; maximumMsg=maximumMsg) # add user activity to events memory push!(a.memory[:events], @@ -698,7 +537,7 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; timestamp=Dates.now(), subject="user", actionname="CHATBOX", - actioninput=userinput[:text], + actioninput=userinput["text"], ) ) chatresponse = generatechat(a; converPartnerName=converPartnerName, recentEventNum=20) @@ -729,19 +568,18 @@ end julia> ``` -TODO update docstring """ # WORKING -function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} where {T<:agent} - # a.memory[:recap] = generateSituationReport(a, a.context[:text2textInstructLLM]; skiprecent=0) +function think(a::T)::namedTuple{(:actionname, :result),Tuple{String,String}} where {T<:agent} + # a.memory[:recap] = generateSituationReport(a, a.context["text"2textInstructLLM]; skiprecent=0) thoughtDict = decisionMaker(a) - actionname = thoughtDict[:actionname] - actioninput = thoughtDict[:actioninput] + actionname = thoughtDict["actionname"] + actioninput = thoughtDict["actioninput"] # map action and input() to llm function response = if actionname == "CHATBOX" || actionname == "ENDCONVERSATION" - (result=thoughtDict[:plan], errormsg=nothing, success=true) + (result=thoughtDict["plan"], errormsg=nothing, success=true) elseif actionname == "CHECKWINE" checkwine(a, actioninput) elseif actionname == "PRESENTBOX" @@ -776,10 +614,10 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh # ) # ) # result = chatresponse - if actionname ∈ ["CHATBOX", "ENDCONVERSATION"] + if actionname ∈ ["CHATBOX"] push!(a.memory[:events], eventdict(; - event_description="the assistant talks to the user.", + event_description="an assistant talks to the user.", timestamp=Dates.now(), subject="assistant", thought=thoughtDict, @@ -788,24 +626,24 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh ) ) result = actioninput - # elseif actionname ∈ ["ENDCONVERSATION"] - # chatresponse = generatechat(a, thoughtDict) - # push!(a.memory[:events], - # eventdict(; - # event_description="the assistant talks to the user.", - # timestamp=Dates.now(), - # subject="assistant", - # thought=thoughtDict, - # actionname=actionname, - # actioninput=chatresponse, - # ) - # ) - # result = chatresponse + elseif actionname ∈ ["ENDCONVERSATION"] + chatresponse = generatechat(a, thoughtDict) + push!(a.memory[:events], + eventdict(; + event_description="an assistant talks to the user to end conversation.", + timestamp=Dates.now(), + subject="assistant", + thought=thoughtDict, + actionname=actionname, + actioninput=chatresponse, + ) + ) + result = chatresponse elseif actionname ∈ ["PRESENTBOX"] chatresponse = presentbox(a, thoughtDict) push!(a.memory[:events], eventdict(; - event_description="the assistant talks to the user.", + event_description="the assistant presents wines to the user.", timestamp=Dates.now(), subject="assistant", thought=thoughtDict, @@ -818,23 +656,23 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh elseif actionname == "CHECKWINE" if rawresponse !== nothing vd = GeneralUtils.dfToVectorDict(rawresponse) # comes in dataframe format - # a.memory[:shortmem][:found_wine] = vd # used by decisionMaker() as a short note - #[PENDING] a.memory[:shortmem][:available_wine] should be OrderedDict instead of vector dict so that no duplicate item are listed? - if length(a.memory[:shortmem][:db_search_result]) != 0 - a.memory[:shortmem][:db_search_result] = vcat(a.memory[:shortmem][:db_search_result], vd) + # a.memory["shortmem"][:found_wine] = vd # used by decisionMaker() as a short note + #[PENDING] a.memory["shortmem"][:available_wine] should be OrderedDict instead of vector dict so that no duplicate item are listed? + if length(a.memory["shortmem"][:db_search_result]) != 0 + a.memory["shortmem"][:db_search_result] = vcat(a.memory["shortmem"][:db_search_result], vd) else - a.memory[:shortmem][:db_search_result] = vd + a.memory["shortmem"][:db_search_result] = vd end # # add to scratchpad - # a.memory[:shortmem][:scratchpad] *= + # a.memory["shortmem"]["scratchpad"] *= # """ # # I searched the database with this search term: $actioninput \nThis is what I found: $result # # """ else - # a.memory[:shortmem][:scratchpad] *= + # a.memory["shortmem"]["scratchpad"] *= # """ # # I searched the database with this search term: $actioninput \nThis is what I found: $result @@ -900,8 +738,8 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev """ requiredKeys = [:dialogue] database_search_result = - if length(a.memory[:shortmem][:db_search_result]) != 0 - availableWineToText(a.memory[:shortmem][:db_search_result]) + if length(a.memory["shortmem"][:db_search_result]) != 0 + availableWineToText(a.memory["shortmem"][:db_search_result]) else "N/A" end @@ -912,7 +750,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev - # yourthought = "$(thoughtDict[:thought]) $(thoughtDict[:plan])" + # yourthought = "$(thoughtDict[:thought]) $(thoughtDict["plan"])" # yourthought1 = nothing for attempt in 1:maxtattempt @@ -920,15 +758,15 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev context = """ - Name of the wines that needs to be introduced: $(thoughtDict[:actioninput]) - $(a.memory[:shortmem][:scratchpad]) + Name of the wines that needs to be introduced: $(thoughtDict["actioninput"]) + $(a.memory["shortmem"]["scratchpad"]) P.S. $errornote """ unformatPrompt = [ - Dict(:name => "system", :text => systemmsg), + Dict("name" => "system", "text" => systemmsg), ] unformatPrompt = vcat(unformatPrompt, recentchat) @@ -1075,10 +913,10 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) """ requiredKeys = [:dialogue] - # a.memory[:shortmem][:available_wine] is a vector of dictionary + # a.memory["shortmem"][:available_wine] is a vector of dictionary # context = - # if length(a.memory[:shortmem][:available_wine]) != 0 - # "Wines previously found in your inventory: $(availableWineToText(a.memory[:shortmem][:available_wine]))" + # if length(a.memory["shortmem"][:available_wine]) != 0 + # "Wines previously found in your inventory: $(availableWineToText(a.memory["shortmem"][:available_wine]))" # else # "N/A" # end @@ -1087,13 +925,13 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) errornote = "N/A" response = nothing # placeholder for show when error msg show up - yourthought = thoughtDict[:plan] + yourthought = thoughtDict["plan"] # yourthought1 = nothing for attempt in 1:maxattempt # if attempt > 1 # use to prevent LLM generate the same respond over and over # println("\nYiemAgent generatchat() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - # yourthought1 = paraphrase(a.context[:text2textInstructLLM], yourthought) + # yourthought1 = paraphrase(a.context["text"2textInstructLLM], yourthought) # else # yourthought1 = yourthought # end @@ -1109,7 +947,7 @@ function generatechat(a::sommelier, thoughtDict; maxattempt::Integer=10) unformatPrompt = [ - Dict(:name => "system", :text => systemmsg), + Dict("name" => "system", "text" => systemmsg), ] # put in model format @@ -1212,7 +1050,7 @@ function generatechat(a::companion; recentevents::Integer=10, unformatPrompt = [ - Dict(:name => "system", :text => a.systemmsg), + Dict("name" => "system", "text" => a.systemmsg), ] unformatPrompt = vcat(unformatPrompt, recentchat) @@ -1233,7 +1071,7 @@ function generatechat(a::companion; recentevents::Integer=10, # check whether LLM just repeat the previous dialogue for msg in a.chathistory - if msg[:text] == response + if msg["text"] == response errornote = "In your previous attempt, you repeated the previous dialogue. Please try again." println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -1274,7 +1112,7 @@ function generatechat(a::virtualcustomer; unformatPrompt = [ - Dict(:name => "system", :text => a.systemmsg), + Dict("name" => "system", "text" => a.systemmsg), ] unformatPrompt = vcat(unformatPrompt, recentEventsDict) # put in model format @@ -1310,7 +1148,7 @@ function generatechat(a::virtualcustomer; end # check if the dialogue is the same as the previous one - if length(responsedict[:dialogue]) != 0 && responsedict[:dialogue] == a.chathistory[end][:text] + if length(responsedict[:dialogue]) != 0 && responsedict[:dialogue] == a.chathistory[end]["text"] errornote = "In your previous attempt you said $(responsedict[:dialogue]) which was the same as the previous one." println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue @@ -1319,7 +1157,7 @@ function generatechat(a::virtualcustomer; # check whether LLM just repeat the previous dialogue dublicate = false for msg in a.chathistory - if msg[:text] == responsedict[:dialogue] + if msg["text"] == responsedict[:dialogue] errornote = "In your previous attempt, you repeated the earlier dialogue. Please try again." println("\nYiemAgent generatechat() $errornote:\n$response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") dublicate = true @@ -1447,12 +1285,12 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String dictkey = ["q1"] # context = - # if length(a.memory[:shortmem][:available_wine]) != 0 - # "Available wines you've found in your inventory so far: $(availableWineToText(a.memory[:shortmem][:available_wine]))" + # if length(a.memory["shortmem"][:available_wine]) != 0 + # "Available wines you've found in your inventory so far: $(availableWineToText(a.memory["shortmem"][:available_wine]))" # else # "N/A" # end - database_search_result = a.memory[:shortmem][:db_search_result] + database_search_result = a.memory["shortmem"][:db_search_result] # recent_ind = GeneralUtils.recentElementsIndex(length(a.memory[:events]), recent) # recentevents = a.memory[:events][recent_ind] @@ -1496,8 +1334,8 @@ function generatequestion(a, text2textInstructLLM::Function, timeline)::String _prompt = [ - Dict(:name => "system", :text => systemmsg), - Dict(:name => "user", :text => usermsg) + Dict("name" => "system", "text" => systemmsg), + Dict("name" => "user", "text" => usermsg) ] # put in model format @@ -1630,8 +1468,8 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent:: _prompt = [ - Dict(:name => "system", :text => systemmsg), - Dict(:name => "user", :text => usermsg) + Dict("name" => "system", "text" => systemmsg), + Dict("name" => "user", "text" => usermsg) ] # put in model format @@ -1702,8 +1540,8 @@ function detectWineryName(a, text) """ _prompt = [ - Dict(:name => "system", :text => systemmsg), - Dict(:name => "user", :text => usermsg) + Dict("name" => "system", "text" => systemmsg), + Dict("name" => "user", "text" => usermsg) ] # put in model format diff --git a/src/type.jl b/src/type.jl index 7c4bfde..001eb43 100644 --- a/src/type.jl +++ b/src/type.jl @@ -194,6 +194,86 @@ function sommelier( context, llmFormatName ) + + systemmsg = + """ + + - Generally speaking, the store inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know exactly until you check your inventory. + - If you found wines in the store's database, they are in stock. + - You can only recommend wines that are currently in our inventory + - Before searching the database for wine, ensure you have at least the following information: 1) budget, 2) wine type, and 3) occasion. Additional details are always helpful. If the user is unsure, provide relevant information and gather insights to make reasonable inferences. + - Ask the user one question at a time. + - 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, if you haven't already, ask the user whether they need any further assistance. Do not offer any additional services. + - Only end the conversation when the user explicitly intends to do so. When ending, ensure a polite farewell and an invitation to return in the future. + - Spicy foods should be paired only with light red wines. + - We do not sell organic, sustainable, gluten-free, and sulfite-free wine. Inform the user imediately if they are looking for these types of wines. Do not sell our wines as such. + - Gift box, gift card, and custom messages are available. Inform the user to contact our sales team. + + + - Greeting the customer warmly by ask them how could you help. Do not ask any other questions during this greeting. + - Encourage the customer to explore different options and try new things. + - If you are unable to locate the desired item in the database after 2 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. + - Your store carries only wine. + - Vintage 0 means non-vintage. + - Start searching the database as broadly as possible within the given information boundary to maximize the chances of finding. Avoid unnecessary parameters unless specified by the user. Refine the search subsequently. + Search the database as broad as possible under the informantion you have will increase the chance to find wine. Avoid uneccessary parameter such as region, country, tasting notes unless the user specify + + - CHATBOX which you can use to talk with the user. Be specific. + - 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 1: "Dry, full-bodied red wine from 1) region: Burgundy, country: France or 2) region: Tuscany, country: Italy. Grape varietal: Merlot or Syrah. price 100 to 1000 USD." + Example query 2: "Red or white wine, medium tannin, price under 700 USD" + Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France + - 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. The output is presentation of the wines. + - 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. + + + Your name is $(newAgent.name). You are a sommelier for website-based $(newAgent.retailername)'s wine store. You are working under your mentor supervision. + + + Your customer is coming into the store + + + 1) Establish a connection with the customer by talking to them politely and showing your enthusiasm for their wine preferences. + 2) Provide relevant information and guide them to select the best wines only from your store's inventory that align with their preferences. + + + 1) According to the store's policy and guidelines, make an informed decision about what you need to do to achieve the goal + 2) Keep the conversation with the customer going smoothly + 2) Obey your mentor's suggestions. + + + 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. + + + context: additional information about the current situation + + + 1) plan: Based on the current situation, state a complete action plan to complete the task. Be specific. + 2) actionname: (Typically corresponds to the execution of the first step in your plan) Can be one of the available tool name + 3) actioninput: The input to the action you are about to perform according to your plan. + + + { + "plan": "...", + "actionname": "...", + "actioninput": "..." + } + + + Let's begin! + """ + + system_msg = Dict( + "role" => "system", + "content" => [ + Dict("type" => "text", "text" => systemmsg), + ] + ) + + push!(newAgent.chathistory, system_msg) return newAgent end diff --git a/test/large_image.png b/test/large_image.png new file mode 100644 index 0000000000000000000000000000000000000000..2a89fd8e1d36d1d6abf90cad15142ea9b83dcf13 GIT binary patch literal 1232619 zcmV(`K-0g8P)T<%s@A*DH~bSxQQqC>JNxXP_h+qIRrORoRjb*52_Ap=%U^!)@`ZQ5*sZ_cd;4O$ z^e=49pZm{dz1w?c?LBMVT5Iuhyl1^xJfCyM-~KqB#=~E?c(3Jm;{A@#$Maz}j;H(a z&waliKR3JIKecf@-;d{hu=Tt9yxZ-zA3rx6ztj1gn(HYZL@yhWUt}VxsfBOU9YjNDUbsu!w`jxkKTyL|}^{m&Z-+Dfe4|l ^FT5Kd$k% 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≪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%0Ai$<@hFxM; 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

bs z8ilte@M*)-ANSp`7W;IJaX+ow%dr=E2=ejMbH!r4_SBuNwMm{^to<=w1!Lhx##XohK6o@yzjp{ z$NBf4{rqRI+&`!93>mPKES&ERpsr8)T-aqku5$xxxxXrh(Q;gIzDHsogAhqK;=6n75c%>;_sXq2NCd=;-{ROi~-&>v6^jKRet-t+`|MkE9yF5&OUzsD7 zigSRRy+Ogp?-7!SDD?QA0U&pR*dS8dDDdIRFnWv?l+umhk6xoKPfQ*2Ddv2$B!az6 zNygJ;Td~nZl3Bdo62>~Z}vDK-$z#v%dBcyw04@@FVI2RQdA z=V@aTm;^72PS_-z^z7}i374UiwPD3Xs;63EWjsspqK8yp7!;JM0j4$)G!muJn*qnB z#lL$9;l+^O#qd9mzx7bX*VluHz1f%7Um{GzLB5A6Di`e%ak=sIAw045yV7I@vfY~o z+u<229s>96IM%E4{YYamtdTWKV^_*zgmT$ts@hq?^R?;04I~{FSmm-+dRv0rl{F+H zK+K7ZsU&s)hH|Dj?2p#9ffo|v0UmLF%B1yC0HO>gw0WHO zOL)eyevDv2MiDk=?g(X#Vj|Jf+@7UQCd98jKR~ae>7#SpHDhn~LVFn;_1` z^~iNI_rfxUjO8X6dp1B+f3s&?qVbN%eie;!`u{y~C@ZCClrxHlFmqBpLP6e~;-g>WDf0w~J!jj-C1 z95J6Od!UO{bij8R76;(K{uKX%(4ij~J?`@u;%8s>+fIPg(%7)(3|9f8d~dT6QpMcf zB2b2NgtygN{%sSui?vfcMDZ>9iK#l`h$12RnCIF5v%y2Q1*V{PPexbVIQLcDOH^|` z?bQ?XFnRI^78p8zmcd#6X5yJee@b0K*~jrBLv8x05JSYOpwJAx)3H8{9`w`k)K8FY zdB$M$+^MUh08NL1COqrMckayjReqTa%zM9&d+IcL#pJ;FjtQ-~5%%7bglW99xEMXR z`7g&oA>@xl)-tr$)^Y7)?DO(gA9TP!BVqb|*7;E5G-8x#?c-p|j=UW`i{GUUXL^R& zqd3p`dY`Kt{S|3S!)#ee-}!m|>bYlQ&co+%YPw3EUEeID<8V9yh&>@Tv1JWs$1uY5 zWt{F^Vc-bOjWbHlJJ#>{8MJ3dfwv8nQyr%SdfH0np8EysOq8;ypJBi4*gwN>HaR%5 zm=&KaP_yTmyL=wWQlv` zdTF2=6B$M5Kz2p~@4W8PDx=fKB1AOm98%$vk0zC{hJ|OOjAVQ$%6X9FE#M#)EE<7q z31-G$x8Whn!6!NtVb!LLS53tgWa7!>#8I_AEJR&PNs2>APCdqK)_DNrb9v8VPXGuv z^SGY|kAuIj(&~ObSJ22mLT;b~ds#;jf&<{@&7h-*!^;j*bezv~i>}@fdIv!Exqf|l z31H!kio^RttMRvw-|c#d4&%rBpJ@6U;cw+2cIZdtWyzzD6G^OsKtuW{Pn`{)BTtYy z2u8V8k0v8{v3b7x7+3t=Y>saR1|QZa5jTD3yx>ylNxp29-PU}qN`$1pld$!gz_m!1 zl}CBOX11qt@UfLQ&<}GW?ESu?*HjdYV2`rTTgdx`;fo;fo)>nDIk@i#RoOp(9J28d z1v@;~1!0WcvRE%S$-8@5KfbcqRs1+f#eHakb z6xl^V>umr^Yz-o0DZFW|Eia@ZC1LXJ>ni~# z(?;T%H%omQ_a`G6TU}^9+Nc&A;}Bz_oL~X36)?@>q$Gw0`?$pmDe zO_qOJT(g*oiW}Sq7|@=VAYYyW>O%*!PT=+*@mwVWZ*Q@V`mu&0G?C+z0F<-Zs2f^W zF&vP>3{NFME@g_|pkX2aV3iITWFd?l%!7Q`{|J`x_uQ0Ob62AKLa8$LoyqLF2FAG3 z$Qt^(gdWPdmL6lcU73LQ&QRQv^R2##67z!oXN4fkE2Xj!M>iP?p+7ZV^6sPzbr!8j zPqVKV8Cm@AEe%FRRfc!|PV$ok$>)ptxg%7R$0kl;FCnv>w;T&SdgH!99Re_q7uM+@ zr!%qSSJA7@CIZqS*E0wn#vtmWwx2LJ@zB@3 z^+k{O{y3lKYs}Z0?=z#dY~XM#tyx#v@;v{H*qxvCd~LJmW3e1p%EPn7@4T}rEX%u) z$8x07%=a>6p>iw{65G;AVj}-ElCIBGtTI0~Xme4KtTGkp81g#qN$0>Dm20sRXU;ed z`-+@YD}h}`yV$AMD0#J^aKjBV-)M;iDNEInVju**{ ziHI2&k5S=wDoFJv>j|J06Ah&>tWM+MM^0D@>NHR}$pRn_a0(RvMvsRW=puw2!h&nH zWr$Ou)@n+OSB_e!LAve3b5cfCxWX0zn5q!s`TS?b9;}Di^voC!IgSlf0VV0YH8n-i?2~AOyvmL;w2qYk>ABzG3hH zIYE1Qxk4{{dFTV2-0lZx>9+$k-_dW%oX7#hI+^=CJTLEWU*kI-euj;T+XO*^p3yyd z(S%dYIWuNmf{ki9lBeOx8e;^&)1w%LNNc6HcAhhNqy{0THEdEwQpy-F5i$YJx_~Mz zylmCbvB}9AdRDCG>*Bo&b622roLqT1SCFI)o1SZmN=Qf9`)d&Q%k>z0Ct}Avy}Z6eexY(-kV|?1 z*pL69N5;>3-1FP7$1uGd&rxaU`-rNG(Q2b3)XKeIvQnYC6utP7ht?y6Y4dS8tmh7r zJ!JLPVIZoK>i~CmjM3KV_e-m~qT*@c#A*ToSUT zM5q<=+vaf9I^`SA@`R?(JG}^;H^-M{02Qs-1lLnOWQ2JTaJe3eoVv{Ig>2|qTFSa~ zDb|ytCc%ScE0YV~EDi=mmDO z(Hy$v{v;AALV*Gtb5Ae<>mI~r4x^XMgoVD3{pnndGRa1%NrGnbvLUxUG`rW$d_jc>|}t&QSX^Xju{0 zF2g$#1d*6PZVQ1e{9co=V>wekz<54bC=$`<{F9`usES#<_jIU0mi6-5F2) z72%jkzyhE}Xv(UC^>?1XPtP&U>j=N2QH!qv>SY^vPx{;XdcT@~V4zM}Zh7sZ zace_gK9U?W6n%LNzn!1!8L6`Amd+z8eR{^Td7kMmVRTfQP=)-Iv*(UiqYM`2N=!MlOjP<+Cqzm4j zdC;p3a-l*OmX@x@aJW>Eb+g%W=VkXR30Z{r%$vvw{G3S={wCnFL^wex<2@>ws65zM z61x-k z7@uL~3fRC99(X}MKfl}ekMCBlHHvtA9>nYGmoM@8HOh_eF}GgzuFy;A9+If6cX(ht ztjEX9JCH}tOaqzl9HP%)XIFcDy#P0Kj6#g>HUu7o?1D{`$~uxDuWnVq#sxsf6AaM}u(5pW(K3wZfLgOI+zTYAgGOYHr&N~S8yv3UXYL2bE-7(i9#u`QCL9J6?Zewq25X2&K zS>&M&w|wZyO$EVHH_zklKP%KGHdYLAGy~uMZInTgQk3e(Y@Ac{vHb9q(x$5fv zfHBH+9rd2unI{&7Y4$z88|RvEk8qX97(`H>S%#QK?>1nn*f0x-8fkVIYE`7n*N=yZ zu6x>OUo(KWVz)Ph0APS4&~5^pw)vCy|A zClC=NQ)Gs<2mCLbBKaB4g^l>+63_0zV^Hvl0Z!6_LJAqCU{LM~84O!63vpy$3*VgX zEtEVgI+aP!dZccBNK!{7fxg#t^Z6As@f zoxqKXx>N3*yiR3X6uYc1992Gd&-q;y7)f=*`0eyGg$$Qbam%_bmecXO2=XZGp!etb z@23rDvC5n_<@xtA9%OpoQjx&}IDk_u?gJp+K5lkZb;}t08>%n5P&>gs$o0$SWWwhO zxdaUTJ{1UO?F?VfL^zzd9J7TL6(1eaSJaqRUh*wj7 z2D~8fq&P6R^WK8Aw35m&yn;=o(=EM=G0uCpVS?(=zBCZ|X90qXWh;$odp z;oQ{*0EUjS349^eonfGti>cBoLP2YWrlvfErwnK?D=8L*Qy`=+t{1xY&X7-drS@XE zF;egVSffbJ9=WwObv+PJ=NjoGa+|jl@b@b!opv7QUdkBX-U#vqQ?FPPes8%iPWon& z^IW^B!iHYcm}S@^=f9`^(wJHj1Umtv%$Z|B17i*zmbY@}8a;|F30PxJSG0lP_(tgO zU3p@AlC67FQ|7x?EWj)8Df0VjO#>dn{pFnlNRY8Wx?ybYH4Q&AfNg!vrP99AyAAzi z*t1g>Ij7nObgeYfRjzv+YHID0dtAZ3?H39C%=|~c?#uQBq$zYLtCJ!R9C^RI$AAs; zW^V?8=|ODe5gcAY%Y7Y1MaG&a{7z@}(Ex58B+z6KE{HbBb{DmAAHjLTL#I$+=}|?b z#F%m(3GBwdb?+Cc4t-;(U~=!)ctA$nQOV_PJ+OPx+kpxM6@= z!w{1M8w;{1333`A9jiU^898|N_lyAN^Ze}fjEF2mOpzyDVbOWePtOldiQRRnZF8|04H`4>%L4XV3HOIdvxs`7gzmmQJamhZk@jpK8)AB22n|r5y1pY}wJ5 zaWX`tw3ax-xZbdMxqb??zxJ~k!{#$qVZ0%0eHx=u#9i=4IgQ0UZrkFR!tu3Fa_j$Z zt2{4b&1VTG1H(7*ljr|m|3Ckaf48!R>$Kjci`EQN1S2Hz;1k{nSaDHqh|B-Z3j`Aa zkR?zs3RGZo8iU$0Hk&MWY67VD3nz+t8GTNSain#8-xh%^x$$Y!N~XRD>MHCb%*>cq z*7NT;I<4y6=4QX^f-GrOmItn%)&;zRvYwMJ5i7$=I$M$E>)>N4>QM+J!;!k~ zi&hyH6)=%CPvHLk#{qP{2NCly#g89cc=nfU+UX*$D;;`ykmCULVLBa?yIm--863skv@qZe#VZHhGGUu?=Iv{hsn` zw8$ZOztH%@&>WQs&u1Axzi=K@mR1{t=3!)^X#=n%X)3oJ#63vZC1e@x7*MnWB1bEK z8EdsBs8#4nx49A>ila6Y-Wzf@^lR5R%CAFWkk&?ef(k(#q91z@Z&h%FE@>QWfS{ha zCJ3q98QO>OGE?4MBN-RagMRLsKGS+Lt-W#%Sy|W5vX+><_6$tu=d;gJxAvY!GL-7y zP2q_LR89Shijg;xusb}8VL12z5o@2}4U4uMPEbt6KYrkt@Scrg9w9$5h9q$=a}8bu z6+1G@3^tRge0^PWbmpH41i0Q?*ZdWemrLgv&<-RHpF?-%JjBq~r~GV7kaj~Jdq(2b;jlHd% zbM6?yAi{+&3ZHD@YyqZ4)Jb^7HsI<^2Pl?>iB2P%J9)ABS*V-zyR9--Y#LkYKU>Ca z(v7xyW@nN+_`s;n>udUQwos&i7AX!Yh1MAEM*-_bk60bnS>B|IdPuQ#hQi$_lxYRB zu0mY+9;-SHV@DA-G2Z5Kkf3{ z8=(HMA9Ufqdf^4P(z$2mjUin0 z?A<d*iqDoz1AG^x9TWpRr`kMNwiD>mn5!3|W!j6$LIrM&iC5h#lUoDAIEf2)D?3NHhUt$i$8q>q6^N0?k}I z%(s$qr2ND>F;sBtBn|>#3#jKN1cJ_xwT}5JN{I5SQu&9sASU1v`q0bRmkJ<>^^L{c z=yBEhmN5v#V29VeNXHk9C)a(a()Ci`B0dPcEhd5W)0i7X)i+nJyiSVfxgonoj*Fn6d`-Q^|Q5A(c*P6m@w+J0Y?h<>!Sxt|O z--KJ%ODl^vI>d}dh^5F;nNSG#pj?C6^s==7EsJ`n|B^NJUP8E`8ZL`iDL=Nxecc(d zduIhjd5!ObltoBv4>FB)`GJ|L!=oFYbm;0f?Zdgp^r5en1C;t8NyFGb1$vD06js{K z<-zM=USu2~uwnIEeP8-V;gJ~H!g(C~5rF27DzAMU7e<}9hb`ZW;KefEKMgO_n$vw_ zT#A&Km6R{)z0wwsj-D$3Z^L~?*l_Qr!X&N06EyO<_sB0sh~x!2FZ4chT-pF;aeEvK z>=1{qcdG*o=e+^1L?zrwW)THr;i=9!NY8%D>U1Jl+7EPHRF*>?D?Io$;@gK(9Z+l@1Z3}q3*au4jNnPa&Lfs*bA%N zO>*joxqO6qj>X%Q*M{%Hb2;>H$@xyuu3SBlS<7L!G|J~5dRj;P-FhG2>$A6Ief^9W z>9aFoLG(rEGeO7i^C>7B03>DXm1TtVX`HOD*AbCf3BKjC2)F+971epCbIzBV$7y=L z`SUW3Svh~Mwb)mW7_c^+C>l!X3Vnvq`f=tNn`v)u#G;Z5RDmry&(NitsijjGE;Tpv z5ZEL6)R^+B*ni4+A5eirtxT9;dX6z)eaLE+gQYLynfF4St{#EF-H->@MVCH(pc~m4 zt`%V=d8Sdaz0t)Vs-#U-mI%&N!hX2k0hIl;p-iem3vCj(8spNYhX%4PnJkWkR@@G( zoc9Da!-IwVlE`6lMY17|S*5R+#gu|L3WLNY(=9#*vlAda2w&wE=5}Z%gU2KGVv!$w-3|58&ba;LmlO3zAmNZEe;S_rwQY<9U@ z0=ZCbDu!VE$3-f60SU^za*~fnMa@t0x1mrKB37n3T`jNc{NtVgluI7#p@8j%e2aFw zB~Xf7jtxDyE;Md<)j<*Zq6a*F-abB<$Jt_ob)Zut^cU;P3sT%Xr_W>=?{Qv)F2b5G zL#cpSD-7@Q=eu0OG8>+-$P;Q&IWu&H&-3A>YX=MSh(7mbd4u$JVGZ7!RRpBOdw6Noqj8UXwJPCFL9DP3LywAp*mAMx4?CP zZ6^QOZ1q-gq8{JrU3pa?OuMR3w#~RjAuA_z@*PRXRbC2u5-VC#z_V6BzAAEFipIO( zUSQ?yAnDxv)014y&P|PFP1L$Q8xlJ=>5xTQ_(7yQTd_c=?RPe#Zy;T$q3q1)|SOqbF?H!Hnqi6??>n!GBEKk2tSrnV|bK2P3axZI(0cWwsmJyOT121_v zCLzM+&NUh#{1rKS*mDI~wdYmJ{nP?R@?yGg{DpLYlEgd4UdGlwbdx-K(R|&eP;w<$ z(bBIq6L(Q)Xj4uspa~2ayaPohREE#%oGb7yd0%m^PU9R(O#r)WlcARRb%8IAxvE{@ zcORs3V_~O08*Z`Zd&qO~aAX?>RD8-v4m$zfuGNOA7a^$xd~MqE2Y82GRyErj8?_gX znR{txS<%9XmEG>?8S80`*+Gh0OZnEGqx_x#$xf2@mL7b}FDj-gpGTxg`=hbf6L1Lh zQOw&$QXl*3Zp%wJ7a(f9`LMwXBXZpf4ePjO9QXFP2lGp1T<(#4oX5~k7;nCl1rzom zbDf^|30s}NYBNK8!%R17ddWiE4vnWu7+;fT)vdID`mN~%X%v|+Z3GmcmHJ%<6v6cj)x!8ITH@`>p)@m7_ zKZbM+Y}kgHCdh2gCkkPk;=|YFH7^!eH})rku4mM-tqtLub3np+!~zex&^iAIg%rBY za;5Y5hM<^#&U4%k+_#nsH!9@ajn^AO?-u^t3=CG%=q=?S{=NrM`uO~?kITma%nw3# zDBg>Y*L{nE26qSa$FZO7dtCeF<=t8+;g3Vm4kCAlrTF4uhkm|#EXoT);i4?Gp{LpB z$EUr#zS4VwP#y=MPS(6iUuhs-s}kHn#;Am1J~&^Ugu@o40ONp=q2$jfqkV78B_Jro zKo7aJVYEo0kny7TlL9IWkc`kr##m<`6KdfRV#v7YX^ux|Y2iky-=V~u?8q_{=kdyR zx6dG_`(6EvTyc0Q{O@7O|2({4_aEQwT9~gA`8*Zn?XQ<0K`v5g$_-g?Z?Qi#a;G?n zRs;e;Tso@>M3uGi_U4ydkPl z723>obY021@}B@CRjEnCGAcs}U|JbQFA$<;=|NHW-toVS4I|mc9L@N8jPc!&19zd~ zL9urcVMGS-zFm%7&4u@F3O(x6hDyvHdc4~b+BR}nEP-8L6(V&QwLJmweTOmbPJoJH zG%z3`7ZTpYBwY;0!aS3lHRNju{8S$H@Oss0&x1kHYygw< zCZ3kq6`2nG*V_bO`j~INqKa{b_Zjo0YVN-Rw~`^{XAhD$LS{kG3HEwtPGn8Mqe`&| zQQVkABqIlA1XVQ0al#8QB2|XFiiBC-w{flLxh?Nm-#v{_7=^e`_<(HN_);HH6Ef0Z z>2(^Lb%DODJ&i}~IS&3eZ)U#-NmXf{F+Y^k%Ihf?nfp@~pelvA_bu@Yhq2<4yaPJYMBf`il(X9e_ENn z9eWf!5<^nn7$2S?*XwvfF2?-9Fxt|~fM?y7&zCjdPxAwCHwZ-^I@q3&F0)6#oa?ha zhE6W~x*x-8t9u`L&1w$cPv41klzSAWZWkTsNRycFZ@yMJ>9+a(Gnv$t2SMlWGeIaN zG3#HA$3A^${`c&A#*vmjTc2Tg_&c9n-%iiJu#ic=Sz=&C<;|CTetmlwkH_OyqN^yW z`Exys+2a6jK#;$)CQiUNlM-Fm&ZK`fdo_;d&|NQ-gu zb|&(nH^;b%PGUgKWlsX&Hsi-_ok^{{7)0v>{sS}eUsJ`fK2>J+bzhN)8S0GLQG z0ElQ5RUf!a-y7E)D za*(fjXPNeE6q4xl)L8Y(f9PxGjehUpMZ*~MBwd}J7xo{U7DD{1eSox>Y*gHleQ(Gg z&ztCEveN6gI$2t}+3Y>7w4}73D0bYB7Avf1D%+emp?90TqR-aGxw>g4#alsf4g(Nx z4wl?w8qbV-4U0KjQaI56xH*YJK9H{sZ$)tRkW&vqycsIUkxn$|FYYd~_Y z=_ca`Jr9MR3C~b+&*sPX-w#6eMgoLFBe2eILG)e!TwcEd?1Z7{6`_7UH>vru{_vA%VQ#&sL1FmhcV= z=u}K7^2?y}dmn(*0o$PgOn@l9QN_dtgn>IlKRQkVy3JIQDj z;i8vy-qh;6q4wOMM|`^_iQE#oMPq0Hj2j^oES-6qD%^EXASwNr7Wi(NyJ5^HN0m)9TdwquMez&m zf$_|&gsL33;EXT;nf6P0x{Bp<=Dr=3S=GmI&C3{Lc&uY5;ieW5hJrhJFlCjZ=z6hi z0#>-wOvLYNBurM1jf$Cu)*3cK&{S1&*6Rh&#v$kk>m5Pxp!7I<<{=HA7;CaG?QvOhb+ zy&BV4j<4_9!+PqLQU=J)YPO|3`InPr^WL2JhjWLhsbQ#=4iKizGt35{C$HJ)dB&%C zCw=vjHk-@Zqk;C`*Id4FPRbGg&8<$J>47t_ucyD~*L>_s=4|E^4{K>0Hwb3FcYfx+ zdi|b}kL8)IEF?v^8OO*#Y!lu#;t1e*J7F{9dRb(@{G59huwk_-~q9}087i@<>O2dL|7Rh+nP zo2||3!~K=u>!D*J8Doy4Rb{c8tU6`VN*##aRDnl?V{fC-hc@^4jlzOza+4d_)_d#x za-Sx`U;C41qfapYA#~&%YSJ^j1Hfrr81XmncUU=~)a407ILf*q6>cUbV4?3OnZr0l zL;`_rw=oY9MtVmmp*I!2-9Mr_;^%gNe{QhQNzy8Ys1vlh$M3qDkx*&-pT;A92^LCB0^%xg4g!gs{ zCHmxj7^dH?2)a6ThQh8DlH0X0((9qMm5rLI z53^@l+%3XQL$)`pS?-5HY+86ht~Td%DD1Eccs86Zq8n6bD42!CbM8U-s+BrGn5>6* zPWtNdZ;f2zy0P3>{5#P@3`YVi-S6})co7bSY#B?>*P`4ot+~SL!Q8l`{|j@%Y!m}Q zPLYQwdL9@;IpJmTe;{Nfl}E{Ykbds;PhdY5aVs`Qe$WVM zJ=aB5h-EJ}V1YlwC|Qkh+D0C*43`m#t&nB40;q_5$TMMXfwxgd0QgondR({fLdF>WVG!fcO{_3rtXH#dwqG#c21tt3mA z#c10T7nuqcY4fuQRCk8mnwrGRpmGn-B3^2zfHAF;ffDz5;E#*+k;OCZDo~?n1L?Ld z0wr0Q*ZSCv3sgfA34Gk*+yKvv55Pu_F>d8S-)dcq*K^>maXXWtpB+O4v2g_B`eRz+` z@bLVsJm>rX`aKsf37}tfJC&W4E3}y0kFZLpIU@l1Yy}wC33c3Q2_M)OgXqU9DUxJq zc1QEb@DM5_McJQ0#}N%tK7K#&XXn65vmx65jy; z=Mm4v0Sjfk*OC1ePQkq~Y{e$!UmoTnWzIB)BJ%{SIiI!?z=sh8YsD*{`Fg+Y-@{WJl@6PT2&}Io92RBbz51o! zkB7*-Uexsb9>;xrs_gweH=3QvLEh~9!pez`$fJtp@wfLkYjbJzK!*phfB((u>u+}b z@;B>;0KI(u?I2jy-e2A$SFCG2aSgbUpfb_BkqCMy>)udi+p8>o|M-Y-M-R=s-DWbo z#m_2FYQKjiIKpVdyN|Js-y0K&n+z2&6cn)2kTF!0yTqEQY&@B;a^7%BczT=V7P_(X zSQXdkrwyWvL{L)?DXVHBg87>Jiv?)g+j9QY`V%=wqfh3XbpqWxWleZ9*;S{=a@o|weaMJysI*1 zzcW8kO z){T3e|MP}F9~b?aE^BK8{2OyS>y@$b&$?^q22)TSa~icLaDb=%2>ZBll?UO&92kwU zkog*G%8g{Mo6pq`GyIAKYYur0TSi+% zpD~s29`5l964T-B>C}0QZo^H`de#|#(x##U{(be{QmBkPX*;d=WqQcU5DX|ZV@Q-z zT`~AN*Lg6Z$VnJUDrf6)Bu3jTtYV!dJ!!It>b%;t1RjvkN|xJ^l%AdDCBz!^2bcTG zj5RUm3G!>G(1bi*XQlDj!wQlY04ehYXlY=TG+7%*>0y$F9pk1~r4_fteUu&4!@rNZSJ zW3I|;IWOuE)VZtzuNcXnY+O|@^YNx^6>*6-H!w4e_o;(%*SyL=uJp6T4BJ5 z{GqZZfJ$vRg-bz{o$S59u#;hvHWkeob0l)Uvxv^p-Ry?=3Oof07j22M@$Ru|JO`XvU^vdA*2%|c{ki2sae|A%t zR*$gg0Ge*C-Wunhd4?Y1*U=Is3M2%`+oD+co%0bo3OGOIANaqgPK}M4#-sS#I!o_6 zL_`jxj}5{F>DgkAV9b!74eD|%^@h))tbJ5R{A6JffZ4)4GW2q5SqP%Dpho4~i1LPB zB|~jVW~$B2n-y|p(|3C6i1BLs$T5?y7{)n_kM`gJ(z+?-rcdB6^cdNmM!={Z>Y=|us7wYE5E+F&sxQ*gH;KinhQU=`bFYNLJ+ySyw0Lu44aXvmCFqt_a_(k(){v3J+NVAKpYm#0^?T~kaqqOZkKgUK*a-l`LsqRzN-G zk`=i9-fL(2NgoloxzBdX7CsY(%Jn0OD8<%&+MWV-d2`geFud{|QCblxHitbLjS^i5 zbyO1NO0?NPHtypI@%YJW9+T;5MpVc1Z}GeHbtYpEWfQo^Y_wZ?91q>A3^({_9M}7} z;v+d44hG#1@H+5a$+@(|*7G%sm4|1V|31%OCr)`jCU&~FC+}6v=bk#5IErigOyG2k zaze{8UQ8Xr0AT0S7rpWt_wuQzi--PM$7Zg+~<8wUVQ__uffJp^8e=XA{Zl zeF~WzAYDHpuV?G_P&!LdhB#K?5Gw(jLmwX|m)DpVYaGKryApK^En^J7T!@-M$$L24 z_4weRR35t;-`S4uzP{Guv)2eWdUXq$_pfR%@EG{9hxg>g;|>`D7CA=8N!?2keT)vG z@akpNkH5WG#E(DzJjennjTJV>^_;Z#gOE8`a$xAh&vU(^BG=^}U@v-(9mhF|i>go& zGVwx^z2)L<%h>Eu+3pNv^?5rhJ(r!46nvK z(b`aCgP_vG6y3vgxnTW91v+~3qI`F25zhGe{ab_z?vb~*G5i%hto%McJqPfZI}dk! zdH>r%_6}nB_BXSagLHlU`yo{SYUSm(!xMIpvG-q&&we?G{d>rU6Ud$G<>mSU>m$LZ zBk2ADugsNUdGBwS7Z08Fak?J&_2c6b6(K)9ULuj-ORbj=AID?!{PAfjqaFa|kh{4V za=@nvq@tQ(iFFj&C`D^sn|FEY<;b}Y(Gb}~g+G+e7jZ4oQ=kYySs6gX*3A}qUwayR zTFPyUO`+2A2ASbzRaPsf`VWTAWif_LeclQQj-dbwuHUj?2kdZueOB7+uV$G7#Er=1 zFBE9a`_gy;QtOT5qr777 z2g;-F@L=x@g^RU#XNAihsRTPiM=7x@uk^btcr%n7u(%pq~e`FMD=E%z*D&=&0X z(F!62OyC>GO#VrVdkNy>x}_KB;9*3yX@6u08?6lih$Dxw3?s1ex|)EY!YoV3)lw{s zdn9xpu4|O>w4nFlncTHkcgT6>n{nU99*XspC9Y$f8*;33KM%!xymyPR>CJORjb2$p zAqQ(4EctPG%dzjEVweYxfnd2vZZu0!MNa?c1}%Bt3hBrM;A8yg(d`7TAx8{@^0l{H zTOwt`V34xUD$K$QT7%q=a;$}EDgix7Dy9}*vf7Y~9Zlnjy%bGwr;JCKqhac0AQ*;$ z=|$PG1qcs3IrO0Zp7QS+PtI+^#*g%vFTlNzUq&U{X)m8%+S^5Juy)W+Wawcvj<=NG z)gW8QbFnu^PUAEuZaBE45jFdAOMXGG#vMvJI~eUThCD-&l~=;ws5m*RU|$Jv~|js4Kf z?3@F)j#<&4+@IHohw#ADNFh&qc;2at{5a*+0|yL)MubRvO*_BNAWq|zP}50FREsLP zk<7=(*s|z{O6pqe4?t4D7gdBXFe?6mJ`}j<}(-IG*h7*jU~i2OjtER!Ug5eMY`s4-eSA*z0wRP_cSg z{9cd8xCGckp@<8UyvkJsbh?|(#yRr5-P9mNhDsD(%A^T%=AYh1_4^Ywbo!Z|MPPOyC)IPrFc zf>6Xcuk?_cgG80>{rLHQ02q)h4@oSC7t~4Ec95{^mw%y0?3eJEc|MuvmU&py%SD#b zdXT;?JSw3FB3h7r%fgef$NhPD;yZiKeI9z`%X^LLpC~MFkjL!;`3@}VRYDz1e=|Vq z9^rVH1koY=m*m2|NNy#+;CL0j$!70T=zaBKEB8sF0mA{wKSL@i4JmaKD5w)?m)h(E z`rJrl7z<`t5O&A+Q=V)x;&2TtvP?oEFH3yPGX0~xzd+9Pltb1c&38PoSSolOwQe^49LuVU2Vot`gQX+{GeE@tu2bFiqC9VFw zO$&>j-S!D%kfGw|zE3)xUJ4PwQuaa2GF(&}xAuW%<&+GLJ%(XCe6G3G2Rt$ad8|Gx z&;ro6uhn>MfCUlMVwaR5>HLtpa>?V04KUZaN6c2{GU-;4*V*{xWFS0Jy|afNu8E={ z%Ax8x7W%1BMD^Q|2v*5~$Sb2hu$LoZC!djWgRQs{98X3qlhKvAN`yatynFvqXlL4I zd8hYia87Ww?@0(?cy@0T`#{>AYqv7Ax5KD$tx+gMt8C2~X$itwx1789JNi?h*|=IG zL;^x139e`(6Tild*BpnyJ-0T48VXg$28y*(H0u5DhQJ$kP zUu}mD4B*(U&}6fDj$X(@37Y}(r=?dcJ>F~4ij}NrZl!`W?lYdzO9rZ?w-i6$`%W^M zADG$MWAymyz1cG|Ht*SKz%a?LLhGym4wKKS8QNiOHZ~ic(%mo z#t>pueAeBi{_U3E8^pcmo+JIzr+GTpbI>_Ot~4%l&Sd9x77WPw*0rq<1I9!%;Z@7A z!)KTIX0quTucormI|ob~MJb~xu6}Q_(D-)RAK5w{1Q$l5Te)#-vPf8I@5`Vhk%|fE zS@bD*j-w`VcT3EhEG{IlWJdV}yS6B63+5m-GNV1aIXW z7GaCv&0a9w=lOc`cW31^UvEBc9N(sj-(xX*c$bIwIc<46uKRwx|9Z^rn}gruZ}*P9 z97_28AYd=s>p`?UZ|B`^PQVUw_I_9d>#<+F9iE5qm^sjH_Y~}xm&42D`8)O*(}9q? z1KQQs@UXN4Ft>V%aIf1z5MEzjqv3EQTwe|k$1g7c!wyD{^LP~A%j*lOeo}72&F^sb zvQZ(j|AYaEW*JpJchUcnG>y3)ug372Y4I)P!@01hZ=5%a^C`=6uF<@8SoZ93o~H}U zB)uvWt@TC8`0H{(F4J9kLWX!+ z*9=!zc)5Syfn!H?PmBRQVJyml5X~DmLGDq8XD;lKgv;-Pe0JfLH2(i4n{(I<(u5hl2ILf zEAXT!U0~$Pthx>P>i9S65|o^~W(u=6R5|R(1w|3AnqD!4!`(NfPM0E4}>LSCbEk)et1ATJRKkkv-Zz!aQO;a1^{ z**jz7ljSuESLknBo>RY{iOaLsd5q3@bUsdof;ks#B|*4f8T#x*$^w&ced1d5bVoW3 zOAq!j*5L=5b3^&ivoYlPa}6RlkCFCjvoo%qBjV0uHp`qP5u2}D%J7QyF&R$AdJ>%- zs0EuKH~OXxzMa8j55d^ES!m(R9v>z2`%mPGwTxr-SL6&R);R|ip&-jbm_V*_X>u~@ z8ITJfgm_fML**}m@zCTf7}mZ3=)#7^t$ zT=8dIr!OFLCRVfi^gOA0t(JM+sI2P)boo&)$7cL;d>%y1iOw-czrMU2P_x+ALxElo zAay+y|Lf(|UakjF-rf#U_SL#qIrK_*dp$fR?;a$N+!iNkkulSw5m-_=5Ux`8ZnULL+bfBtl{ zAgt8)5z2GV&v$}ZCs_CJbX8M>_1A;w+`j)2{jhw~^Raq4-uw8`kADYYd#SOZ-|i>@ zzHw}PaBsf8_a2oJkuO76yfHkEo=dNU=nV{A7FvBfC7Nq~80#ZTqqsh5@$fAr7c zCcWXFT#mM1e?73y)qecIhWP!%<>HqB)h)=_2LQgIXU@w#Gn))4_@<0Bo#YEZ2pkU(m+VCL@z2;3;z+ zs`Zh7X5HoreLi00g1?n(9May9cNLa&zek2O0=!~w9Jmw&E*q^QS#De8vLsm~3EJrS zXf5SF#-K{}My13SWDvcS3W?g-M=&mX*ZW+<(?*UbZp`naM=5owJS=y5PIu@Qt2C|X>-}l`v?>4I;*TVf*xuBN0 z))?m*yhzXKek8vH-=*0oy*Ki3;@sRDM2_66j%dCTa$}kM#(rhZa{L<`C8Osi@8AgUMKvQ4tAh`oV^d%}N^0ljq;6PV+FR@q`yH|j{v+6T*Q7U2{_ZXx>rUDD? z^Z;j-P#Sy~a;yR+3ip*kr<3>tht#p>7>Z|HF6d8L!z;Fjtn3`Smbqjl#PVLy>v3xr z=-?>mat-_tQ5IPwWf;<=b2L5)?7NY~%XHc&ojDN)pl&>Cyn&oFquwgh+K%()9!!t> zRBccbb>5?YMle!u*dP_5e?-W7V>^wZ@6%W?5zFvY#t>j_bgjGIPdI?MkpOr^HLUpJ zj2oom<~2WX|Kxy}9`o_JPlRC^2m9$~^M0*y*?XJDh@W+8FCDW_UNd5hZey%xE)n~( z=S+62!ze6;I{8^ZX(ms2K1&sDzqXlgKEn&EIB_mCgx}T5uPoqy!TQb zj-Lf(CX%I$)MzWKmBXLnfVcK?-22<{_g5!m$7f#-#rf64zz(JR^?Cr~Lz%vN0fd84 zT@KHM6WFVJFRrhVyjjBC=T<&}SPkT2n=J8_cLFFNHm*d`yVQ^lgVuX4CG`Pigk6vUo zy$kS;HkK*J=9BYN=1pll0I)8nb`}zCNNZbOfC0Vht zag+Bs@n*&zL+5fb4?pbjSpbO!gPQ-qEd_M@<;f-{H>t4;P zhasYGV0?bKE8pM0gy+n?S)a$b+>6?d`L^;)c)+e-{(j)oFG0$-_g}+1wjJ{1p^Do< zzP1zdcPd^5Hb2R z(s=%xhuV4A!^h_z%+qPp8l%;cL?Uy*3jZlS+)|sHG8oa0f%7Xc$?qAxDGJ}7EoKmH z>6|eHjiHFycV-5#U4#v6OGP7ER!U<9ySfddfeb**yJ-Z1aWBjtf;HT@`IKBoU7KNq zJHfi$y25f`I6(>V8X~DRdp1M?nA7WLvKF(w#jNWXwkYqB=XW`Y?$Lbt&U@iLMQ^0Q zac8fv2}{gzX<~;Lm$y>U51;&F&|zjcvda1ZPYcHTT#w>t)#KTY~J%A z8!?yZ&E@{;1GAR`{Q2wfUC})p`qty?~O{?D?}c0OVVM?=4@K$ z>pGbo7D%cES>+Aq^|T7?e2exRFV0v)_qse;n>4A`unjyi8>RCa)Z@C#^F2I!4eww} zeH(nBp>RygNV>+n=Y5ba>rA^~{%u78uWo}xH3BrvNo#X7LbZO!H`Q(Fxzh;?Ew9kq0uLGZ{Qi4@ z6bHE8NZE5Y(ceZ^sUCzyYs%06=eO^Xljfw(<)nLwdiQ=^53kqZ3EK}6<`puXi1m=6 z_s9)9CfqLXUs0svn0uec%R#P7y;AcKaJ4B$yF52k4C7B^ImG=bXW<@}V=p4pLf(Lo zwnM(Z9P)OM&4V2Na@<>xjYt*yj4`l+(6`%t&-JqtY$ljtkqPiA+!Mm2I*TB*+!PW1 zjgT@V>o$0OSV0wr&x)KRlSr17M}V&t48$`}8#@Of$(RXH$?G(&gF#+l;TJe_kR@+g zj`22m{!FrON!YZW(2oe?t)&%2u9ftnrT6b7*YmQ8jjS384y((i4j-F!ge2a*2iPZi ze(he>m7$Ae){pQ$Ay4ZbV=T^`;FjkO%Rk9f$d;8ftVBMVhbIr$k4lYwDu^_U z2Q%o3{iq<40%sh?#GM`vtTPk?Nzb0Zw+Lo$S@lmX1`yUX0}>d@6rQNOQd9yh3BJsR z&N0fd{J?roI>ow*V9a}WLzuoBJg$Y_E0j66MTVKPi>HLzWyoEbKwcT$F;X}Kb9>#)87##Wy zdDZ(~VhxWmEF^e6w-(8E8Wm!Icdq9DBrD@(|p8N|#OE-%y0RAK{pS9;)>Qz~c zs`43zeplh1nn)JwdL>Ge89hTBt=2_;pAm)`c%S9&{JrsYMJn`MOW_405d(GuF}wHS zkVvCUw`iT9zx8=WpqS-eKHtZQ{v^&kKgampY^g-LV3MR__OmgWe}-si4W?+E$?6%C zYHkL8l~)Y1)N(IC?yc4w^cu!<5Ji8_z0a+9c(v}eVb9#Q30L- zjc4R+{H=Y2&)0`zCXJf8PnDFxd5&i1RP^w@-%W)8qqKe8c*6#!l=V@`Ms7w5oQ;#C z|3x1+%A3Px29JdQFN!9m^`(zZdLbhcbhF_tgOK(zym4TW1Si>?lVKZuuvAsx0+=pl z1Vn8DHPcdH{o5!UN{ z6(r-PlS*s!kC6~LNuEJWke}n&>oHbu$Imav>E4fHzaATj|9d|`@h=BZe!F}<{(Xr} z=l$?pI7xCMb~!vA*Y~gC74v4kFYlf|b_mbwmezsJjUqzDymWb?ck_Obz;a~{&L?_x zi}?D2=^n~>v)8X*4q^2s#qY4xI|$qvD&}M7i`R+T^*tAIRd|=tGE7qL3)iigo@-VY z@K;UYP{Z={>_tm`(MCQk#w0^6WvKk@EPcMhy3l8(`atCPm8HlF=ey+niD2Rj;r*cj z!;^uxgJ9i1KjU-v4wZvsch_d0o4x0zW&|r<@o!Te>=A7mt#)<)wak7JEZN{nJAiBp zuFJ=l?U&j3b{-r!`&J%j3|^%LY7uZ zHguiyTq}D8l?p(ez}&wVVTTo^{{wmMQE&y33uyMevp#)P{){i}LykMbk%qCTnnI}H z7=u!63Ntr^^~D$l7(#&!V~PE0!-{Ft+oelSqlEWp?%l!*(WZqO>v8gKCYdYTA05a> zli$w+JRCsYn~A%3%&SSpBOS(s1GqbRRjAF`*z)P2aiQDgsX+8dgclnlNvga>pkq=7)j)u_d^n|M08I1hSo{!q_-=`UVn{sc#pJ&jtYx) zQCmbhzpGBmDQA7wE_*d!YZk)fT(adeR~B)CIi!xeEN5&n92~;3 zWw?fk!^>E+12NJl!B+SZDK`WUtOLRf+9$Gyz^R6l?5cIJ)>(_71D9VsZTwd7EIV6Ub-MFelrA zlqbvUX3T66gsA$|7^-4pA+a-J0uEWcf_!A9#zyjE%S(ggc`?8?D)Yp0<5DF^3Ahz|2=SElZ|(;c z=j>*)N351Pw5a6G#dmoP|G9M!8##dZah(WJJkY0m$iBRMIY8;_LBihc>*3wF9^Q@D zR}@lkugUw@-(rJx0PU5eqVJQ}S@SA+^jL*Vcwe!Keq;ah_=NEx zc{k*osaa}RkG$#g=RGWM?xDDBdz9SYSUFQ3)4d>(cni-AHx8>dT*c9OGGw-v5dx#q z-MP-p7Fe6gI}!FgzvDQqmo?dTmCJPTV5QL$oY%NHtC(PUC|jxsh1L)d)f zCg~n8FY|tlwbCOL@b1L;n9r9lzghd!t$2sG>>y0O0eiK@===8eWL^z|L+hL9O z&Iu6KdxTV7-Afvwg}+#N``fX`zgm0w&ECHJ{g9F0?EUaK)kB`{2T1ke94<@SAy*b& zu-5=N(b~Y3EBjnsSaP~f`2^bBsN-|J>@4Z8G7QKux(0CFo0&q6W#QYX%L?=89PHn3 zAF)w>c|V@vb5usWe!O5_kN0XxH!f?!>+FS4rOY>*pa zv~$>~!Q)DuQ3=fDeF|epHuLVo_{8VTO0jJPRhVmpcf%-9a^GnIZj`5DByco3iM-hW z>JjGHgowGWq5(0AtVCmR0{On7nq1^27KQZUUuRz2@T^xui-eZXH4KVF#-fF9nH)Uc z0J~w`!NV309bu8-J+iP1#ASEt5A}fRls6b^QBK=K<(rKvnR}3I8V?FWvz;Wh9fY-2 zl$U7tiYT9kb{Jl`NJMzxALCl9xeiTvfMH1JIbI$P`5Ap2)o5E$4qD&Co8rLTaY2z` z_)cJcxeUI~h#9M5zG!3;qusfVgsDRg??jN{5sJn}!t>R3xoG<`fa$%J&CQ4WXU zNo(^=cor{Fia!3=_K^b>l{a@)aUHo%Sv@-R6N3C=@0@a;y48vH^wejRAQs4)$HmfM zWn7>1>6$&!=@8#_KboH{cdSw}JQbhSbqsVz+AI2`XN?$Z!XJhAI&u{8YT7?qXH5z? zcmmJ0#{6L#MVbnybyhXsxvxM=xd>g#W|n(KGdXb@@qXTa5h3m4p19A%zc%lc(oJXF zH%PjSO8U=={cZW)D2g@4L7YVQsy!lF1%XVF1;=19o-+v9Jv~grsxU~EEPDD^(yBOO z<(032HCHFHV&l67z$C1&@!@!g!aNskqWXT2E1MS)iwP9WKwxq9%`k!+C1gWE5nPq= zR9zNTn>=6&1InC_#@OVsSgSp{J@fZc1|iFAE{$gy8$)ktv8oeb*Zr;*8}^B@v7mCp z?+Arb3_f(=9+pFI@axs%JuJ~l*_Q*nzSqMeb`Y>%UVpXM%bUF)9t#H(FK=HD@5S2z z$lngdQ=^HlH?`~zq8;4Fyp+fRYXrA$&GkYW0W>Q5?nEd_!)6d0_d&}1*pJWeQAN?m zIr@`*9K`Eov)ji3^xuw6<&euB4SyS2CsdO907}~s`VLEzhvRLm`q$NaD?!=}R$!^} z*OJ#)&g91?nKzq7O>>dnR(VJXV6c%{SgiUv#L>*=u*dUjUfk#J8AN+JnDMJh4>{|HaD7;c5Ei@Q$^^lj_Z!5AV{;LD<~G8eUef zwCC%^NmoIk70I&<8~)0oIDANM6!06!U+d;@~KS+|XjkX=KjT{_!X042H?|IIo7h@wX!}4E?EaxKR z(xs}@*C*X!*4u0yhc4>ekl?=WvuF(2aR7IjLZ3T4F7j;PUR4N&`ld)9Zp@w85{&Sv z_I&Jqv3)3Vj&QRi^upiUvU28P-%-ti)_YQdAHl zfkuC3hIPjII{)LxrUjPXWnz{_1L5%WkeE7g-@Q=B_e0kHINtaWWU-#%s7_>WVU1Nk z8IIEMBDBfl<{*2Q0cq@QnX}y5$gAPc1bJqb9)7djHzL&KSaYp!lriRjR^*YvaIleV z>F#23BHS3&hK*&>6*fBo(@6#kLlTX|4>{E6R~UWxc7_tUA+WMm5g_UYM9*VxG|1Gkf4~3(A~Qy~gv=qNmE)#$Cs0^m07q*O^_&}o6LPe3 z=nztjbJMuwGXHs}af?Q@3J*e-l_yCG9YoJw;-Zf8gEZdJ?xdkVl-5|xVKtI$7-_uHFNZ!(%@uJ)a{ zY4TQ(N~XLe(4O?RaBnK;$XROaRYI_oucs30*Zkcb7@RQ+58)d>3`=4Gk)+8Oo zO-bg}l%P5H0Z1z$t-|%hNXG_kR;L9Wlfy(_?FpmAYt2T6P#VL9e`dyT=eK$O@*J{& z&V6IHQXdxi{4AXS8ci(gL`2IXWJRE(tQ9NI7M|G+?f2>;`+5ML*W5uft~%d0Vds@v3g=I{tZ{mRH^L6k+$YgePnxs8rZx2M}_(y5CUN z+81sVilFD{^T(gz_4@qu@wtb!@#ClJ5^G452fYU~GIQ5*X7<1$u(CR-CTFlj0NC3jxK&#DO(6nZy zA}{MaTTdd9a@NOp9!cO?#jdiTM0lIO!=It53hiY+UK_$^cJ{mr9d?ZS%a>p6evsiW zzx@~cpMU;GJdBY4$bu@o`UubB`(6A{?>2{@pIW{F}Xg{V&$9hrAq~ zw(TJF=7l@1UNQ0gxb|BRdJlbaLhpcYyP^k}lFG-p_b8i;hVKe5E#dXlI&xhU7HC5b zmV=kZii#16$-D{=GmK5y)(r(AS|vSZ3PlbQ->wIcJ&X}=Bo?o%su#_(S(GBI#@fh{ zL#FvxQ`raz+vuTBt6N{zJm$SFioTIJNFN25Eh^OE<8xbNB%AQ|o;q0Gv(e15r(PI( zx|k|6n&jFZb5pGjc}BPs<^$(75(tE@YrewT>FRY;PTv#24VIzp=K=(jcKC71Nq(94F0H;61^yd|f*$w&aWZkbOOb17op2RO}r*NkC(@c5=7)es(2 z%S(_lSePq~SMs!KpYP0#13(wC(cXwM_sVZs_rJ!*@|~ax7IMx(G%aShWYlG902&($ zmX~7k@5|F(rhOOte4mz$il|uZWMNeDlW!#>9HjrKrZTr(p5jIihQOj%-i&CBjy2|F ztY?Y&Pp;|0y#(d)1q=h*bSGmKfV;JnPddxfI2(qZj-dz~Q2Q`!^BUM6Sh2Psa!1yE zc@rWE$h5aY#u4hwzDorjU^jRIzHQ8r#r&cQEPh8G*1%$&Mjv=A=;1l`XAd0>GOj(- zsH?TV#8lE);eUI>(nu}%L={HQwLAWKs3PQ~BX6vCdhe?t&$Pi~A1seRd(wl?$cglj zUeYCP!aWK}56U$aE1JKA#>-QBhxQ7a_VGRlhR;#Iv+Y25QPtlNq*bk-8i`m3f{*=R zYseX!dx*klTR^t8_t)o!TIf1O5e&rr3@_yQC!F%^*!dVc8Jp+d^IyC%;Z{4(!Q*%5 z-{k=cqf4K4I^+@kg}FZHLA2%GPy471BBmQ?yBt5lW_@fFy(iact@v>W@nGd{A@Z#jUB^4RuC7x(?V_;5;|Uf#;9O; zd<-IXwQIRVSmN6Ol;2)oj^7VYhI=p$^7VdrPNJ960j9lrVUN6?mk24_eS!F<>YFsp zIM_hY@bhk;2O!@f@5TXHRNnI@-d;rF^~<5RenjbB>vQgw8G6pR<$Md^fY^C#bmiDM zZ?_ty?xUBFSF^eRoW`c^1nqiBt5~H)#5W+nzK2`x`<)@MnC@`gvHbS1#GWlltHNKU z>_nV$!=l_xax1k_CU850kNK77>+}4t*BiHlJIZ^80Ks^%$zpklvGwu!^zc#7e~1tZ z&oO(k`!T=2{{6q%KmNBr?fuuk+s8LQ{6|z2yxs3iIK3Q};XBB1J&5_Q|JC0A_WwLM z*T31@LFPP6(aY4k=hPcJd+1^bZx})nOZ1wl(JmoiM=#5>L4II~Mkq%^tVTUZX3No2e5bt zK>E0SKgPn9_#x+=1wrDnJ6b$&_G2k>ZnF_9=WO&r0m#Ot2H+U$TMdOPLAPMH`;5dA&*R zRu<+k<)N`<1jhTvVZ8Xq@%sMR!tSjlXodX&jKuOlZx@6979kXLy3=!&?#5egc*xQ+A6NTKzf01gj7$X4WB^pv~0 zZR~|gl87k^Irp{i9xra55t4`sZfN15@Vxlls{mUw6^Vk}Xr2mNH5dsKqf-b3OX-Qz z+634X4-+*1u7>hufN4lNEdA`cS30~+(dVqgAQ|h@KWoG$oc zBtySYUNfX@6io}##_(gP(Vlzhxf$<_C(i^;KkIU!bOx`PXQr+WWmWV0qm=##3wL~V z?+O8jM>`CIZS*#b;$*EUJu37Z*5(C<>&hm-hCF$AC=pIQ?}bJpviu!4+fq-T@#fF| z{wt#P@Ou_r7{|?cJhAcV`aH`?@6Ms_=OZnvvhUO*YV(2OO4Hue*jq26EI4Dm&9{hW z_J6*%3nCB@5yvQpI*nPI*aCXpGpT{mnf@6hezeK+c zHg^^%^>gp6WVXwbwBrP7$~+SaTxZVHO*VV=B6vUChpWQy5}aVLB_ERPdnY~LZBL~LXX859v6!| zT?T< z@XC1C1H``s0qY5>5wmXdjTMDS@c|<3PXWBo5hqHW*Mg8rFCy!QSS<4!_Gch z3*kC1%EH{MY0g4#PsWF5uQO@Wsevm;U$fbh*|~X_MNZ9DayYUI69wAm6ud-(oXxPvw2{^76mf=fT9P_msPSgg4AX@IF31?cyP$$C$sq zAD*zc-|Xvu{eK_cuzx!U*xzk?_Z+c*weq53FIy0Jg!d^YYMCh zL9l9)V}K)tI>7s~vw4#L?nFPVmitaG0Z2)uF1y`&7zC`Nn9z1%E?L85B2*Y-h2Fvk zFzCnHD2K=R^=sTqSV3QzFn^=voXNnR$bAV=1f?=I3xSvsax-sc(l@ZAY9oSIMMWu; z!!dGD#)gD&oRU2r<*iH0Tou{kUF-y_3W2mC!*jt2(lG+wmK9PPAy^{`+8AaO-Wm5S zc6sqO%p9Po=c!dqI&Ebb* zJ$35s)|Gd5^1_+I3fXwMA6~J;Bj&|AjQP`Oxnk319Pcte26?3SK8$RA+6xhum=?vj zv5lkzU0m+5Uc-RYyNxpV3@bh93hj;X;8>DAy^pt+E>DdSIy7neHCP^WR6-GjPLNy zju%(o4F(P`$Pt$3jzSpf6^HWmJLi}nkFttqm6v13{5Sx=7q)poRoVTM`Dc{13qwGY z_#2Ia^q!UJSv97@C`roa`R)k)ROmUBi0B=?098gGh7UrcE+^j>1Tbx=%*s%(N?Fu zP0k+XrQxP>o)>&K>D2RB)d!CyiL%ykn+snlBEr`3HcK31lI39UD9Cg1SZUf{v1xL% zjT88SiEx+^I)@V@)MfPLS_Na2P-WugEI?gu!Z~ECPeNA5gPK`83C$R!@uVa4f&|e9 z&@pX@V&FyIsVR(PI$z0iG6XU{DdQRAoKUzKt8dd3m2s9hv@+4qcrW~52I9D%eF-^i z-0+;`H*LNpnSjlk>73B2@5*y`spw!41kB0U0fam}(XD2$moIjG`FeckAYdL==0xo6 zD+)7s!49v)bP%ENs08WS!qOQzJyAWXfROpNONAR`d!t1_3o0z}toV0;+1e3iYGIwc zWp&7q%VTq`PMlugd2lb81MZhYsqX>Y?*S6MNpOsjvDz5DX`gj5KNx|Nx%FD9z#dd7{W zm<>+{&W(_WU}M~@k&EZ^RoE-Xlg}NTyuZKM_uu~!AjvJNZ--~Aeg1j;YeBj`ZmtLp z&*ST1oi8tkC+xr2mw)+x+4akRvA4hdF9-ShYOjYUExe}(A@fjFZ+Y`YI)6BKkm!#qheJb8)I)7 z`mK`ELC9F%f3BPs1(CwzwK2bn^T4pS2pJCJoFx$QkVTYP?+6)lV8^iZ*kn7aOr{>4 zE!us0kNUgIqSywIFolp?8Ucn59}2oyx4FtHa-*0l&4%B#I9UIFJkKA|!!oKzPPxLd zmDmapWsL=)qJfjEc1(xgFFh4DUZrRyGd#|0DK4U=F5sFEr2U#F+qRlI0hK>D>MG2g z$SsQ4Ac(#5JOx-E<4`1jAvDlPeR!%Ohf7{7&7tJ$z!YBTY-=dE;&blavX9#_4qK1h zrK%d#woPl+QrGqAv)mh~qg7-iyvY9E-g6MsD`m#g(L0Nf-56SSi;9??Z4Q{g0n2o> z`vBRxQ@#qD+;bLT0ChrlqimMKFu-~5*fTd2;mkevbIE~9oR2-cKLvp*q%pv=-p6yQ zP?d@WAVL7F!_6I9%L1VxDvh}`G3L9?&C_9hzGMFP(Ihl-D=6`hnb>sRdWl@hEehOl9<>JOUG(#8Q|N67dS!NK4v7HqiAdNWH}vZo%^sF@0E9!C z^TX2&9h>WPHH7=mJH250ey6vUzq28`ic!F;+@il-cmzu%cZ5;o#aPAH)QZALE>gs8 zn)v+LiZmNBiT3*(i9UgY!8V@}uNkY)GB;i=Wn4HN>rBSLLFni2&wKTZ=kX7PavJMM z7=wbazX1uY>*1~=@W>7l2HhllT;_b_fL|B1|Ymg*yxLWeE&V< z{{Q0ZZ@A>xab!UdqSeWB zx|xv??sO7>0S1Hj0{SyP?T$d@KB`@R{PExR{%`-saHL=D@BcY~*rGobEzZtN?>T5cr)RGcOMg0XA@TAe~cD;R@eExYp_Ht(M(?*rabinh`4aDCF-|M_?^gm#8N8p2yECb56IOPBm#Uhzk z4Mf$mrM>E#f~U@a)?%M$&?2xubtPc8v;|Y4mrndNj&NWvA{Tn?Ddrx|=UW&+ z*G&u(C>ZwaH|aY65xDbj1)!@Bm7ReitLBo;hV-trswyL%NNhwOBLYEHj$`viI2ggn z*(cyYkP6>F&f5M|Q$7WsykgiL^eAx4`G1iKHiCzy=Zm*FgFa~%qfXYOXeL(u6Si6H zL*R^&1`kN_`}MhCnfHhl1<|X`K;NI_<)Hv9Dk#s0o?lRoBw*o{r+m(t3}*6zwAqsT z`V!17zJ5*8tzVu%^hD8Y?O0edO1K6-NoEMdGj_|-KpE2+CA{M^RhcLO#++&g5Ge{O z%Dk-1GwE4n6Dr3ORK{H19~f0|lPV<#Qa^bXJlGu1;E>JmDp7!@Eo_TG>m2F9KCc6| z!ZMv_{aV4Wb@V*d3#01|B4nF%C}L9_c!XF_1q$q7*xJG*-Bf^9&7 zsb}k&b=V-sewG8zlV8k&PyP-=&_g~w{QD`o zw7=KRhg26w+A|QvcaCPSh!L;ZYF-e4kQQxqK1-gHixrqBB4CD&95CA=7>|CBaxq-- zH8)pZ-dYYqXdCne1aw7n2pC92zXE3q_!6Aw$gy&LQq8DnUy?kZZD3s$Q=< zA4uJn12HKwv!TDt2Pt`N7}}E+p5x$k1x;klt_4C*$I-hK&MG#nI}WdcdGL6DK(xbu*3@(4d~n>oIO1^8tt1#>hJ(3WWa$jiLp~SBLi>$@x!NibxSeHR2&<9=^9%Z#3jD)bH6I`ivus?>dh;dj9fWRnXWyJz#?-u4kZ zKOoZ%l`1(%WbQW(i;jP120r$1kwI(M6Iw1=rPzCs>9*mo(W#@j`tyWfiv#fc+xq|-&3=4V`}hC- z|2ux~>!^hNALI6Z8&$FYv@iemzl}g@RKWiBZ@31pntCDz`^r@|EBgncfjz1o&hvRT zf-3flcR5~BDN7M;D2#JM5R4#hE6FXl#?1fcCo5na@XTypQ=q{FhRl%zrpJ@()My0H zQb4`ix7nM*!M`;0k;w3MVc(nsuniLZ@7}kFQB~}vZAu~_h_6)?FH6rAfjaN$NFfCi zK%>(;^zy!>lFqbc)7h@iyybg@{oyzRo4~a-`_)%E#}+_uKCAe>pki}Y*&G$Ye^1ZF zqY3SA+*gm@w0>I5uws=o_9&IkA~D5BD%xJ3!*k;-;V)6(rbMxlZ16J#7PLE>vxjpV zpQrOwNT+P+i)V!a!DeZq7_sN8WAA+;F_9pyUxC*=pLPjAqCYPkc<{OTDt@<;fMUo6D^xWFAjm8ZTK9l_ie1TGaQ=w7~S75JS>7wiHsDR68=pYdMlEJ z=hqo?1!)23cT^<<6 zims&A#~Z~cn-GlJ61~TBkp>R``X zB!o?I5R>_McO?mGp3A8CZJpJ}b=-;dc|IoKnrD$~S?7A{eP2c3`m%o`Io=jK8#5Ru zrS%j0;6N4eob zzW|7c+b>@)F=z<@*X@^f?3z4|t;5&HTCZ`9UDmKKRWwz=8htnZeJ)b&JrXSE^lug* zjo+ocJ1ul9kkHrXol5GFSu|sJ(BP~6E*<8lSPA zTWk&ZW=yYMR!{$(OoI4$4YyUh$%rp>P;92x3t2BNH~Dt$f#D%;89;M!n`LFfY66i! zy>!?no;}rVnii?`azU1tfHa(~#i5Ms!4g>bbvISOv|yg`g8(x;;xts1O%_D&%Y8?c zWL7-7_4ROM0Mhbs))Ee{T#alATAD5Q6`wYZ^ZJE3Z9PicEtSUN!LCNfzh-aRfK`QR zlH?|DpeELGL-x!Zd~NR-!rOc%*r;|i2Pqptn+tdNOtCYlIh7y`K_@cFXVUTVUK>No z-in;X4d&+PM`r7eP9FX7*#Y=U^cDCpXK=3>d=D>ZcgQsRO?eaZCln#wkshN$aev=g zLDRgsy5G`~`dU0u6`?G<_r#IPbL5cDZ0aw?qCXKTP<KX%o+0*S_`f{Ol7~8+{H=4Re)CUvpG~ zjMSd@ufN&(!TD`(x33u3+%drUKgZtq+o+cPhiwD2xubVM5Q?mD-W+H;Qa=K%O*9NY zF$Xe=QlFwY7Y98atjKdN81LobJ!<<7VD8WHseUl8B1CnbieeD}YJF@GX*fB+{#->o zYE%Q9U1h8 zE$lQ8>G(quKh8RxV#|PpkFJyMBWe?8AQ>-26@jZ04O?3DzTH;Uy}4hm`v^3trFU#~ zNUP(CWX}X^rZaY0@Z!tKsyM1>rDiW_3rYOOfHpuBB))5$CsL9itl(#;ETGH*mO4i! z4XiKsP!Nd5!0;Xj5BCuF%Jba>3^n{m!3F#Eyzuyaa7RUU$Mv5#6q%R z;`;(@o``hcj`^TfEd*MdS<$wc2o^mWK%5}^fBC8cj6K?0<|3i`>PY}l zdD)X!+72-89}HDxeBWT3OV0W%X)DnVQ$(ZdTzibi@kB5fJ~I$E?c??QtyMszg?pF0 z4SfMOUrE3nfFf*I^fqB@NSAYq zxUo!B6-l9@*;;Xq6=R`iRIe|KswHo8?)k9i6Hugyyha*J49#TL3pickkJz{KkKU{N zYXJ8O#G=LE3>s&P|7PzUtbQX!KVsH1haqn|mb;#dzi+jf_~E_@Kgr8d@`xOAfyY^0 z%wYoYv+@dx=hv&9|J9j{*V#-7=xZUy7qJ&~4Zh}nj~?3`0%CqnoZYo^Mh~x!74=!= znY~BLLy`l)#ygl1UNaK`M$qKFsS%$RYPrB@pjMW%2!J6AawgA{jn>yq5)VC%v;Qx_ zRB;*4MScm962i(t#l%AD8W*%oJw%k1jkIY>3dHg2eV zeSH2cH=a#)z=>YyfZm-=B|Xg4;t)_73Wx&iQzf zM%d2WgAWZhMF3nUj~v${afC=$h z$JXA|cy6yw<~6%KzZ%u#+PUoCS&`v;Xjc}l0;Q|FR2B(ZIec5eqOre)183Ru$hmE2 z(x4)ED)JrkW(sI*am|-|w~_$??Ut%6joE*9f~-t>577W(PECYZhu>RJHdS@B37A3& z_Rv^`%P1Amq+@NjaOC_&`cooW?GODB8HR)1vue0AaUxhzhpH1|qxzA!e3~ZbN zs@d=CZ?aj4(J(M?OVV-9yUR>`zxu2Q(As(CUJ_?mfZdZPCyJ+!hsOk+V@nGA)oNw0 zuQ^q&uyPDglYQ#pPkNq#OMpaYY(aIyxC;n(Jn+YXSo0pX;|U+bC7b6h);WT>bTG8&b5~^)m0y0R_;7z#S(XZCJy;jr+MAoEkRhx%mt{TbA^6S`3v61t9 z9S}Ox#Qo}Re>b0*$V#VWMa{y0w~%z{>~pe~erDZyVJD|#_p}qUidbw40U1;1<8M!H zIjf<%lBQEb&kcQgm_ORdDMEs|&RC`_378Bc?NmI-#6s^#|*JC%}5OnajDp{M)XtU*Bh?B<6b??Md|5 zHH}I*Q8|19d{dqBK!wQTL-v3(cHXM+fPh#lj5|G%5-f>gk)%?b*3R6=QQ<_z)wI4w z+WO6=&`z|*WCHaU{&HQ{e-*1GURb|pj3r|Y(Kpv=V+ra%xdx(b>{K%hVA7^>MUiLC z%FGYXY=o7h5`=>*>hD3op}-o8o0%UI6(Y`3sGQg|MkWwwhq7h!;J3w*MAPbY9utg} zy4mEU_Gx%B%g}T2^(z*l4SaYdjS)8CsU8^q8Z$?oyzaOzyj5Yt_$6y&<#K(|cYp)C z3-z}OePxLqJ_W}cEde&+Lq=7+JZ&5^Y zhx;U$+u_4I07p42nJ3EZ%!EH*VWft-O<1X8d`O@8$!gSI}Wd3f1h zU`s%2+MCV7@y2kkN*m3s~$k*j#PH!bk`kF!xLUX@9PJ_I3Zxq*Bc_j=ejblU??C3J)l_ z#~$-4X<_9xY?A+&LK^;(CP9Na%L}GR{Z3KUc!xrw8lUWgn*94&e>c8Pf{j zngGPR&I&(9bR+&Lfd2=2!%zhiJu&3OGwWS7l-SC$ehM1>87Q!fpM|#HB@il#g}Y@E zFz879{#UY71h&t!5 zD>H!P@69A_Tdpaz%v1?|fva6r3#P2As z*$OMrYo%d5ixKzi`>Na<6!Mwz4<8fz4%KHD*n%zILDk1-4&4ta-piO9M%U`Kn^eTS z4nD-(g)uveLM=Vxzqo#{enzq-#HVVZe-l;8ysU`zsD@FolxsNw8ibM#il9(HMtdZ{i-T|U zk`;_H(x+VfVbgPtH4_A3EE?BSc)qs2C5UM{--t!5Cyf<*s7#-@-WPvXep=I5j~Ty3 z@7QD?M7-i_>C8MAQG+OqtATq$(5r#2rZ}^E+PEd&s4dm8m&|G@N#}|O;92R+{uGwx z(g2xBW?N34$vlSkdatSgKO7YJ`vOQk!P=7T?uh~^=^NL@v{N3Im}!s?F9W97k8xP5 z&?~b>I{-kw3crsj;W~U#5sYAkL4++26d>F|L<2t=pEyg9=V@9|Tr<(zYHt%ZB+CkcBL{f*S>?%usL3^X*HJ z7q6Lz`&R++iOlk56Oie*wAZ(!D$*%h?Ef%4jX^BHic?ibb&PXmo~-ExL#}?mgpL_x2q1747x!cg!gP?;q|E1ZL}n`+=2szE zB6QQ1pdm7pR_0ole$D_}T>jpofx2dZ(1QNp3nNOG>32OVwQYR9ZV;ig?)w%1L!vq( zu<%N(f1X!UJ?G-*!fCI&*0qOIE2{Jr(TaoaTBe0BB@!=sST+LzGh0AsUrmlOpo>FT zfYW8|E$rrtQ;63nFrRyoubJ0X{)K~`^7)Ze0{u)B65k73ne;-QFJ|OX~_udjQp%Xu!Bo-qGnkal(aYoccjy4vL$ zYJMiFTM)h401~=_)GKJA(+&DrNmbz!XQ>s9kLYQYSV%a-hEJN<4B<*v5+abFcCjr0 zf{pb)iljqrlYLfQfi{IxxQ9qttVpt12#w%=XLS_HmKOFR_GX;%hCcV&83dL_!4v=~ zVY*8*zS%`t6QFA6T1G<0gK(e2SLLK0^0nVgIB2J@tu zc1U6<5ykjoQc(SM?h~8VBGgUYZaRHB=4SSw4a(0%+`vS$RD_L{L8~)aU_GdZvbXX% zL8qM+e9LR)p6m#kA!g$7vnM+Ic|sxggy>c;H>xm4zid&(qHs0NRx%bO{ZJQ$0`*KD za~|0yIep6tYN2kTEs#_!b(biWF^Phza+&Ozq5vbnTg1!xwZxULNw`-z^>P2(pPKV`o@!M%)c4JOj()|h z%BK<+c)LnLA3s5U5rB`r|JEiwGUAaf6nuNcMWevr@nP6de>9a8@K};s{zV1Meg?Gt}LW{0SZl!vW|IFiBNmJTI0 z$d*B^XhmJXtFW2hPJ*=%O~6f*xhbL=(n4HeDSxN2RT3)TW`1y+pP@0`nz+$!b|V+`0g|Sd&n!YL^F>eO;wwY4l0~GJ8eco{h(K zRo-n|xW%~E7Fp4`c?fPd?u3mOh3r7kJ#beX;OK_J6{K994k~%OW>R6@gWEl?@8^op z3`iJR*yq5ORiQ01yL11Wh{z6kC11QBO|hC`G%WAB-dLMTC1J4`Y(^x=)Y zVZOY_<0QCPRKfrf5EL>%0L}66%9v;FO9rSM43AitLwbWo*SQy{(s(nf2`?0aOrZ8~iaIJPpgdZrom3*&>dT-AZ6$0A^dEC`i+s${s2@kJK;paRJg>&bTM>dR^p^l;Gw??rABJAl>f zo0Kn&2_F1zA?SGpkph-I0&UF|in!h4jNl?Ecc?;iSk4kH?ngJaLkN#^ z*t(yeE~+W3rqN>>iB~+kOnB0KL{3Xsm(3 znw@Qm6tf?}*nl6|SbTB8XVwRFokxIcB z1Cm{bS%MdS^&a32qxAm%n`U<~OArmpp6h*%OhWZuAqhJm&^o;TtWhDym;ndn7EQ!7 zY&QoUT04}+*-1Wr@1{YV1QJ>-6p*^jU|7c>58}nR1rRIKsP&1?WVI#_nZVt0kGy8C zUjKXD8>@H8eG(43FV8);0h~Fb8PJ0pWrU%g2`bCY-v9RR<{~b>&R^cYU{<$NIYA8( zbs`KA)WwitqVx3Xm|TSDwk8^a|La7b)5!m@Zw+Ai27?@#DE5+3dLNZ4?;#vNb3=98 zmBCd{SwBB5GQsR8;~tHS?|QCkpPAdwj}JXF_A}r~G**b|L>mP`yty5 z_Kely9lagnKF06dlx=IOs58?Wl#YlJ5PvXO>kFl(EC6)b zcV@F96RK?SnX7$H%BOKJWTm!iAop>|$koi4V|yt%;^QzpDe`u^v+C7nP|epWb&-J^ zt8Sh#27R$|9V6@L>%8eqV6P>3h^`g|<|WoPB+&iyeBV46+@TZLIm*ve#SEa#VEL5e z|4bmpYMAe}Xa^aOs3=}ZX#*i3SofLjFS2$mz+*_H%LUenJ$OFyvb z+O#fh2Gv*z+1!+6Zwds>)m9HxiZr6&Yzqh|>2DZYY_R`PU6~Y8?!!|Vce4oa`{fzU zK)=Xf&i~%F?Q*{aiCufSK&ssRkpCNMib1W%nJwyt(&t$uEBrm#565G7plXD$ty@I6 zKdp0|+p=WbS#>L{7E8$%uP;IKlRpd_QWW=#K3EpPgXz1%cas{HwA_o$DS4fo?bb5n zSb;48L^ICcIv~Qqs`R*a1k*i*zg$Kic5M-23ZHW>aUO@DlU;BqNsL5asY*=Ga~iwh zlI+l0o&sa+Qx0I+6g1NgoM%*48q_y2GtdMuyt3Ol(j;i-KwMn8HcIt-9!m$q{yS{&q?2MGh*4_vj)R+oCwfzqSb_`IHpKErh*sWRQN&P8# zf2(2;OVACKxY*EmjnPTgi$Ysp)~)1PMs+P5ZcG%n1a1L1+vUKl;4Q#sk4BQ8Py`SEFQU*0H@{_Fr~5b1Er zqSFySKhVqL;KEcQ_H2_^MtrY1wd~86FU-~|C}pF2XP=vBlPy%=`V|zH8bOQAGh)kH zFHYYSkgi{|XxTH1LIXm;_8Q=<4%yb%|KevkE3eFFVL5!3d$ficA^OEeRl_q>V@krj9TcLg1m&MNkxS5cfJ?SRZx z41JwEDZoBPR-5Rko=gaM#^_wcDvC18Mk=5`SAYIp*~}Rhc7>|RhNGifu`oJ_U?A`{r- z=OwW;v(mC5hB-1v|p#DYm(`En?`y?9Ay#g8o=2^YQ$1?~mw0UkT zyb9{C_1E2R4#eK=?p4ypd2EVF@>nu)^BVL-KSEFfXQJ=b*F|NN|J%wh=!z!Wqh7kGB+!0|N(aV6MK5Q!Eq#VA zJNvbFsL@uP(ViLcYh1@`S^MVlT3+p1xq`B5kU#GuWZ6*#Yx)fT=&j_x>5o-m_ki?5 zbBu=|Fd{Yxe>YetT;D^3io2*%kui^Jty$64`{_AMpUa9^t)b#+N>CB3cvT6*-A~ck zv{~~!36vI9AfqCRVcY^vP0!P-yVz-E`j54eidaRIImQnZ;PTJkhs`bm;IS65k0T~B zf%l^I$Beet(jEk($uD(NubvQ?>>2H8U-lwt;hnBPd$TN5Tn9W={XPN2TH6@tLy=jA zv68M>3R&9*zfao>qq6%gb zt9O9{RkN^<4hx|P%&R+N^n#dICj~oNAJv}ccTyU$rg!*Sf3~Dmvik1v_vy?YuRa^8 zxl>3I**sfIv-bPxWzrlA7048FEptunC^9A9ns}F8WfiFVVLcb8G$i zY(e?<@5|p6tzR$cKf6XlHTj>~l-Lk8JUeyaqpQGN#Ix7+3)*1-vhY**^)r5Esd5Xd z=5b0n@sslP4#vj6xdu!GT2eem0VJKv0>Sg)>L6>r=Qr2-wY`jSs z2&q>7o_N|h9CQMm1bWpnz>kAF`=u<=-nXb4)NYh7e~gXss0V=9 z`)wP+Twx6GS+ygRAy;@(^4wu^2pfIk?(qQtLY#D6A z=pkFwL213ezhkpkj8FOX3)S?18wd z6eS0a;)*Ov?|k@k#v6?5_PW<&|4#>~kc8CC^#N-ka!vG1@!PR5zxXPvQ(6D}SFgE# zm)G69DytM+@QmCB6~yt(U5vx~rbeKRnQr$x&!9i6@$VEasg-4Yr|)bWPr$%chECbU z(~4B~Xiy8lbj3cZ8|CV61L$G)mxebVOYlaDvN5RlO4K&{mmIKRLj8@yn=+nj|33#|0I_DujB)lI=jfb9t+cTY4%S>D)Ppj2 z43#4V&Y)2?W>Ld7QHY}BPpG)9!K-P{aEpk(Vmiy(Ug-eh)j_FV0$%LLJ~Nx#>&FF< zMUN!zu~8T&D&SbN@$gs}Zi|4pzM zl*I&HQWlkOjo-_I5Mxm4eyM6i4bHCs9&DP68g0?9$VxxQ3urHi!j(b2&S*8p3OOnwS3HvI5nG7P zxJ}#dNzqtK(%KGO8>?fDL(c0-p_Ws9j-DLutcKUcwsj>4g7)bLgSpzE^NZf75f~BY z^w?`!uS0Bw0Q%h`mg?|1F~~ahxAg!TK_BgDOQ^Q0N|=#WSMv1)SU#KZApsx<8U}$X z-z#4%B;3tyq|>CG42*NXAvsvGT2omKf?e2hZd*-X5h7PVgRdy2L~$c~Ru#(p{964$ zOqH;C^NdV@U=fG*H7*T5CMuqK=`au*VD`xB7=YMQtc3OheWTu=OF(jBk3zsgSA`u= zc#?2eZr@H8T3|;iQnBgptNI6V)m#Qr-?e9=%8R~D2X33H@$!RpIcFsjx~4eDdY%>F z5(WE=+sb84!|rF5Fz1JT+UF=PeEN8e$3coFDy1hXV~B%X9A>Q1&Ns5Dinzpf9B3Lm z@qURJ*K+^s24Sf$=F|Ak+WMxpzEQ~FBa5T}q%SwMejc;SbmftSfI4IKz)XV$h`|Z`?@L6njbr|a!uRtfI zp>=N@XxtQRv7Z4mWs_B7xtb07i-mdpkO9q5# zMC3>aR4k2Fh?QKP1B~^irpJ?p8C(BG1uX0#g0Ed5>dS9m2B;*(wScNIDilAy+xy>s zLty8sNA@74%4I_fq|P637!ee3NT)762I!IMA@`ign|sx1GVnF|uH{_cvC=eBV4ivDS6z zJ4Ij(WkojjGg)IO?|XltQ(hqCa=X!N*4cxJdw$Y*cMJkIzCZRT=ay0C{@_4(&s^!} zkb6cIZ$n?5R}1Br(@vp+S6SV|Dl`sH4a4QHdoD?!qCFKLKax+hpG&1av-k6v1{Jjt zd0h60Ww2-Ic)R+p&gJtX0Y%4JEr#94BLs*XXX3uQdghL~aqpuF_Wt%|ByGMx${(`x zO|+>5lm~zim9osJYDbCxQ0AMU6uX*W)Og?QA>+PI>3doZCN3mvi$Erd=UoFt&r``T zV=#m{h9OoUnz&Jtn)AgTf&#u*pU6^&qFlGtRxbz6OlxX+u3GE4){*2`Jxo_(uS-db zKD8v^I3Vt#K%-3Cnh8fe^HB4{ne#!upvn<+VWb2U{-`_{6wXa^90S-jQNP%hyG;-Y zz$nGIqAInOT#3j8hdqo+#hPr4igkFs*w68^O~HNa^>|_2 zhDG8Gy@@UqVuJCr)4psqs-0o}6}K#> zb^S_EPQ@u^^0fm+(S3tjPe4`u z{DyH8KKcOPdrH8o&7+KL`UntD0+SzHp}_xpN!|KI>&kLL&2Tc`p$HS>(K&b0xE zZxjYwpXPMb{PYa+Xn-w0I7{4@AaDY=b?`9{hc5Qy0m0iXU@ksm4fv8=zJ=#jU2tbKL+v(tYd}d(?;%)6uRLP2cj)Ss~*Z;tbxDgnmMC?lOck=f8 z4JGF75}@ry&-+Pq&N@p`f3J5Ct9< zgTpwW>yU8lgR%mo06RZ}qBS_iuIQGEr2P5MfUGV-O}uCB$r+j3N;mjve{=>KB^_4m z?~({?Sw4*Bs(g*PxoO_3X? zWz$(xf}+kO6p!=_`T&>Q;+VU(- zR6zw?^zov2+Lm_8|6rhV`1@Ycmqt+SXY%Hh>%)?A%jKBrh}mzuoKK$33EuJfouXDv ztPE1tW=IzOSF5;444Tf_X4$Gi^~sxZI7#4anq7-XPca}1Hk`gqbuBXio3 zz}$PZ`k6#XNvZR{5A1D?NAk~$o zL~ng2y%a;5{KP6chqa0XX^&Z#HbIyw&nfHQo&sVICPg6K?n$u^R)n74kSL*m2m7h` z{yd+g7^ht*nF)b>bULf&%#}M(cU!D%w{y?QP4Gumq z#5I}rASQaB~p=LFm zAgD!K%?xgA(D1B;T^VE^rH(ngU1xv^Q? z{ROg)3}t5D36#0)+UIDKBKs3yj{Pbd*RA~wqRcJ)-zdAO<>&MZahfsNr)iP-yhZ6NMAJ8iD?R-X)aK zGb7Dr-~-0+;d8%2D%oYD-5`FP__tT!AmCBEdXc*PLPLMn=P*<^A4Cp-#G%n|@9*mU zI#9(ba*(L@p_fYzurSO)Hp-I_UMT`Ks)H6#1qx8BP@e#8fM}gi|17G^6keN!5CW_i zBy!nfWN@xZkKi2DI(t&khp^3k$4eAtu%Bu*Yzf4&;;w7tUJ*4!)h)he4Vq=A`*n6$ zkFzJ6X_bMa3%2+?IZtA|4KVgT{@k|ly|La-f1)ZJYBfqu?;6(mq!^CRh&w(2wh72U z7{up$pIvidkRFshR@16zIeGrwW~nDLDzEiYNe>#*CcEtKbt3RVNYDiW6o7XCCk#+_96SUEV#%XcS+LJZkt0=iAA%ks( z{S7vOL!#L$E1*`Gh+!aksyF4#1lFvs%>mksG4=&Ku@@^8@}d$|Z2~RCD6LzlY%=(w z+9hTkGKiUpBBOTZ79Ui7dm}L-Iyf zK{dIaNdQxKVYx!;C3;j9?* zx$(RNP-eA*6{cu=U^VZ_cW$Qus*>{Zn?)6en!(PlDy+ zrA!!O(w6pKv7Xnn#uS%$H#SzBnI-vCq7o)>UV0=rqB_2UFWs~C^hrpTcP7E|wOQc_ zd3q+!I$A@1P{Q3SL{7y!zLC1T)BOqEjXKgCtHFw&6J>qRtp)fiy|1g=X)fLt>$P0S``I{KVLt$4;}F52X=smB{$ z0dx=sVCvwrasQyF_2fA?p{nR>^w)@U{>jQ%vFXs!FzAPBtLYCTgTMn(v4}mDfx3c) z89c-cj@K_5pLkyxCLKm}odmduU++vZD8e zp$R9u{+^b9RzQq0xA~ZOUzC=A%~ni>K;8>MApuwo}BsWh$nKhv6%i z`-=7Uck|8UoBml2(EJ|58Xor(2g`Z;A0rsP596};kquYl<=)umgZ`}-5D*S7dspnd zJPY)!RLbK9VB=<4o3hnYx7Fn1(=%=yIO>XNF4*xnL@T4{gEv8LL|Wr#r2TBJwCIDN z#{qR`T_jj>+fT$$!oH!vG;)Q zKK_0fs|?6Q_9=8ig(>md5s>s$tn{7Iyt3p@ZWmp2>_rDu?I7Ln37J<>N)^qzL1UKp z0LXrP{9sSo=E54E1JE&`aRzw8;b6I%YZh`OE|WoTSvd zJlN`L;73MS89W#La4H6!TA2xj9!L2^_^{$UwQ z+R1g#j>=x=nQi5^+g z{ynpwQ~1FU44tDQW)Ymjca_}NCE}w+I44CSl6g@Q6xdoEjw(yOo{-!!c^3O$&m{)g zTF{^Lps+`yf)v${LQqwwC;e;#IL5D=Kc|qDrA>CfRzXdB%C$4*5b$`xRdy*t6P&w)ow!GtvJA8oH>dp|+Vgx0IxE zp7IAlZ_J*IzOXI?sIsq1^7g0bvRy!|#At&Et}y203a06nijr&sTVfLAs0OEsZNZi) z*k_%VrnSp{UaZmVJB{3>J*oC`!Gl>KncBm&&g|7u9szau3lLKWCEVUgJ8KH!f*8e8ca4K5fCs|J*K^dA2ysZiX=?G-h*O&9yVuE>B*=}*QCOk zy+YwT`=R|srCk2*K`{z@qWW{3-_avtVfLD{d8+o3 zuk)!wK*SAo+L98_CQe+R&ph_uufKW%jYU~({(hg&HWI}YFzEudT+cI=YYA*87&`$z z8ipBrFVv6myuYJ*cs&0a0A>9BcuHu;7$cY%VNFaP3~2V5rfgTBJvrI4-W5Nf-NMzO z38K2HYUmS}&);mGAy(Wtu7PFNVloQ4#~GV)l@xci5DE)_O#c_oIaZvBEGD8qk55#_ zpeXtH#D0H_btu|%SRYrG9F@Z3_|rZgzuRBm1jb^~*V1OQYY;XwfXZq{cD9t{YsMj5 z1I;xE#YJC&(y{<0HRSgz^|8w#ufNC4S;@YzrtF=q?^mv1=2{)QW)))JvN|CkWc@-J zTxlqE;rFiZ8%ChkSy^0vM*6d=W%;2IEbHj^xVK3MU4=)|NXqDj0#|^?)+1A25&%)~ zqIrWLRN$P`?0sYVe%k%UOdr&5oHB+UB27<+NI^?F#OpKNV!o6NDzA@OH1M={?ukwD^6!>db5uoPm9J}&mP@CYbop%=n?3Sy*vz_Q%{RH z>t4Zij^r&kyZY!kP&%IL3@qVX&q)zs#exBTG)CC|%dd zJp}yIxULXUaUflov_Z9*yc8s*C|bcm+Y@y9ew=~~2!_1k(V1=Zkq7MIJK=WEP7u`r zB%ZY2N=6}xbIy5PnSimDPPX^iN5eBjd%(7^Rg5X9_-kJr?>*18gK+hDMBs06M$D9m zQ231*YXxFLzAbK;8&v^v9elYe+vXLr%1W4vHx%`UamEy>YawRAXpZ7bR!e5KPcp5< z!tk4V68N1J{%oa*`B{8I^-F8PThYJE;>+Xt9~Lv5F!Z;~{fW;n5t|F(!AMMoNt~>- zY4V9>VPT+B7Hp7kZN4{3M;1C}#o>80N=8SoY5MZAR;I$1YLAO*yQ{x=8o`>Cpa6Fe zp6PS1)WzoJR|zJK*=uq*`%5|nQC!8?0D^X#iOPryN&=pkDVcl9W&k~7l^IY6T`>}6 zyp{;G>l&hPKWhV|N@1FARp1GI*rH(3Q#RH9W{jwqsG&0kOdG_FoxOY%>msO&9_|Tn zx~`3Xn{};A#97!p1n;UmMGscf*|f$ur1TI}Gqh^pf=)`Qhf-kS1F;l<>rufK5Q$(L zz*YUzG|Z@mbx%u<%7z1u#{gq44D}p|?AskRBMXKUD3o3uF)4i`0q8z$x5xOLyOI{% zPuw@8{welyU)f2;MD<+p)by@;QcH~X`gQRc8E^LM>vecp^XmDWLpGjjno=u`f5%Yf zzz1%pQ3?Bw>ex9z*z@z7JqGAFCG`%PD1N7cc77s$*bMp2^$w3kclq%&eQ3mhThk!Q2e77*JQY;4O)Sy8XBULT1$?X^P`#peKA z9v^Xx&%w41h)8vUG$?O6Nc}$Ioj*r{`9lI8Wv!;@a0j){dIFZ94pOOYRZ&uTxD+{r zS?*j9DGsd+))j@%0CW92UuR}Bi}@0Owl3^k5(K^mr>~WSxTm!lsw?}#IFG#}IG6y@ zJ@1{pQthYUyGBX6FPWio%_#Qu3gqGPdc~U!MI!`+*#tZ*6;oZQFUGZ7&VAEbHEl#x z#@uB1+IzLg0a*6|bfcos-t6P~fzSMH1i?@p^qCH>;c?zZfVL$yF`n0IcynDPhf1(D zGjOe~js-|NpJP%U^|RovQ-HuTMw)fz9OIL->ip&R8v)iS8VVKRT`2ukCa1 z@)`D*x9>mg^YweNC-O7RY&Py{H7Xswi(t6IV$^BNPq*@Og*o>#?x&Jo9CuOJ{pA0C zp06|ZSk3i-=lPIx)ICDLqa4|g{?I@~=TW;+BZX80Iu-ah&T;T{yWbe_kAEY^!~Bke z)hk!q)cPF<`^H#JVI|HTGX@`b(%(>}9iRDpHh??0_)fJ&RKdFdc4Iuz;nYuzi9khM zJoN+B-H&k}KAvGD6uPTeej!cBg9}xI5xg3M#->QMwHUNn_&IUVv9hzLB!kLsa}RkU zqD`6mQ-SP`ta`P#H}4Jm3IO)y{uQ)Dm#n`*U6VB7S|Tx_Gi_n#l_;p(Kmc9JSR(8a zbqJWUu=?ZwJ3uXZn2TrB(sI@d?zaX@fK?{MQrfc|B>c%_lu=v-BNS zq{tOz@1e;N{XRPLn+6RB5RSp~pz4?a8NeBx0NhI1tt;RjU-#wzPPgwL!CprDw_%#a7T(*IfX_z0t#t+vzOyDSM=#SLjl z1b)mW2$rd^+2_=7&isrQS<-qfFEnKZF*0t`A%TQJ<|1gtjw`OMoD?m z`f8OA{+WIrF_0ytcAnE(>Q4!@@PqEVT%nN^yke_VKkr%gQ~r0avEOFzb{88b6eVL% z<~nMoQiKnD|DJiA5<&P9mj(MMZnMOUQ;WD`R_NkAS0O9_Sx{yV?AI>FM2~(eGd#ar z^l!H_*HKM}dCz9ig2C(bbB)xZ|EH3CmiMc;qDSIq()$8TK_Ry*QD9S$;#^`+(orK; zWJQgfNmBSw@p=9+{M?@-`2K-jGYFvBn^C#-z-+Q}b6@7vV#Z1QAL(?MH+MSyzF_i! zU%O_CTh-^_bT|-GpCbXpWP6n*Uif7^@-M&I5`UN_=q^lvHTCjEa{kmz&Mt-n#><@1 zJ0^*LrzAQ%!GWn)ejZ*88*4NGSs$R)*TY4;($-L}8~f9%{g{Y=s@D$-k)fQ6>F3px zx5tC$ay#K)9k}_|ZLc^-Pqi#0m{u%b%No1U-v)Mw*r%7d9+8{~W!+8}Y|#Up7)Iwf zm{(9y#B4E+RPnz-?FVJ^#D6;&JI-$-Dg68R^A~#B)3euK05Tld%~S=OfoBL!tR=co z;6Zk*+a(LM25>1{@h^hO+$LQdkqnIUFY>atrBoQdy8xgS5c~?Dkv~jul{2$4fVO-u zW~QzghdJZqr@Vw+0oDX;XM#RH_^2#Wd90;^)=xcIwgkdUusp$^!103CBZC>C0*p*= zP>pl(fu}3mI5YS0V+3VypsF}!%V!JuM)JVekv(LL<%9^NBTL9COY{&H`O(NK@Op#J zK+jxk0^`Yx4kk;$ENd!$07{%)u@VKZ(g^HmkdOrBRmGsUvz{M)42Z1>< zbSPL#*7perV!!p$)o4x1sL4XY@rpi{RW5h-5U`<0O3BYN^mAZ{wD&kVJ(^c<`@QLT z=zfYkp6_2VT}=Lgi6B>Um3_3B2X%+tVPDs@(HPc?-y`kJKf}Qo84a6gT;6xGrM2BcB_-sg%hQ!0)MNFe)#rT@GK2-GM|3XU2g77u7K(1*m-3 z7<8M2q#~{<{O=kx#S$|0?6)iGAM3g;COgZl+O?kINSD|}mEkGw;eVeO+y0Y4lUagx zJuJHlV$I(ptyOj`-cRR_d$V6{gZ6ldxTQy!bLQu*iMwj-hFO!1)8-eg1Hm2RmGJdf zkQwn&Byf?Uiz=`J0#v|YheiEOuqsNKPEvsLxn2>|g-Y#QL+nx6m7cw}X9myV9Yg0f zm_$6v3j@rww-c;{Z)-RcPgQ=N-Urow7%Q_a#hUukKZRZ~7dtvhAtzP)Mo|g;P0)Yf z!EB(#sl-c#`HKty_pRpmAmiAE9pBS~!)c?)DP2baf#%L20 z5Oc96SCl+ILCHHtMeK6`u+Ps?^?Cj|0F=`d|77cmNsuJ=NmD$DO8kywDq?bpL%H}0 z`Z+6~J(B-U3vEml`iK+wAS4Ue*NpjIdJfsz90 zvILNe5eYzpCDH?41Hqp+fL()FZI<=|swSAQ325SgXye3u69n%?0FcMrUMmN$fQ%Uu z1uYrCTK--7)v(0tr*XPgAaY$4toIibo)s&t(?y}uEE_caD=J2F{UR6^&t&d~e9uq} znps9u_J-F8dfxcAtI|ET=O~Lm@V7goAI@bR?|mPE@b(yg-ft?8?*KKMQ@^60rd{ch zd`>OBZw*J`=1{@W+KeC6pUf!895A>Rp{B|yo#NydW(=c2+e^_^Rjv|2bK`HSaAbL}^7v*Y+u2`wL*YbS)i~Y{;*#fvC2;d=( zpyImce+|aw`<2Ueza~7^y;|zefGtFHO8zdRsW>

gyFG65MO}qnsJ(NCdhZ+DrvP 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�hs6?^JcyZb&|H&^z79$8{) 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%0AU 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 z