diff --git a/Manifest.toml b/Manifest.toml index 2b2d363..6acb603 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.12.6" manifest_format = "2.0" -project_hash = "972fb718a7c47dc6826419825a1ab5fe7b0fde84" +project_hash = "a7a5dbec939b5bcaa54ea4aedd3c8ff223c86502" [[deps.AliasTables]] deps = ["PtrArrays", "Random"] @@ -247,11 +247,11 @@ version = "1.11.0" [[deps.GeneralUtils]] deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "UUIDs"] -git-tree-sha1 = "76d2628787838a67d6e8192e428991a7522883f0" +git-tree-sha1 = "f1bad7621e6ac2d235adc8c593b0aff87bd1d93e" repo-rev = "main" repo-url = "https://git.yiem.cc/ton/GeneralUtils" uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe" -version = "0.4.0" +version = "0.4.2" [[deps.HTTP]] deps = ["Base64", "CodecZlib", "Dates", "EnumX", "PrecompileTools", "Random", "Reseau", "SHA", "URIs", "UUIDs", "Zlib_jll"] @@ -925,7 +925,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", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs", "msghandler"] path = "." uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" version = "0.4.0" diff --git a/Project.toml b/Project.toml index 1a77850..074ed42 100644 --- a/Project.toml +++ b/Project.toml @@ -26,7 +26,7 @@ msghandler = "f2724d33-f338-4a57-b9f8-1be882570d10" [compat] CSV = "0.10.15" DataFrames = "1.7.0" -GeneralUtils = "0.4.0" +GeneralUtils = "0.4.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 b5ace45..63a6c10 100644 --- a/example/agent_chat_virtualCustomer.jl +++ b/example/agent_chat_virtualCustomer.jl @@ -426,7 +426,7 @@ function main() # event_description="the assistant talks to the user.", # timestamp=Dates.now(), # subject="assistant", - # actionname="CHATBOX", + # action_name="CHATBOX", # action_input=customer_chat, # ) # ) @@ -453,8 +453,8 @@ function main() 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 + lastAssistantAction = agent.memory[:events][end][:thought][:action_name] + if lastAssistantAction == "ENDCONVERGUIDELINE" # store thoughtDict # save a.memory[:shortmem][:decisionlog] to disk using JSON println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") diff --git a/example/main.jl b/example/main.jl index 781feb0..d506645 100644 --- a/example/main.jl +++ b/example/main.jl @@ -429,7 +429,7 @@ function runAgentInstance( if haskey(agent.memory[:events][end], :thought) lastAssistantAction = agent.memory[:events][end][:thought][:action_name] - if lastAssistantAction == "ENDCONVERSATION" # store thoughtDict + if lastAssistantAction == "ENDCONVERGUIDELINE" # store thoughtDict # save a.memory[:shortmem][:decisionlog] to disk using JSON println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") diff --git a/src/interface.jl b/src/interface.jl index 1ac9d5b..0abc7b2 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -48,6 +48,7 @@ macro executeStringFunction(functionStr, args...) end + """ Think and choose action # Arguments @@ -125,12 +126,11 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 # recentevents_ind = GeneralUtils.recentElementsIndex( # length(a.memory["events"]), recentevents; includelatest=true) - requiredKeys = ["plan", "actionname", "actioninput"] - + requiredKeys = ["plan", "action_name", "action_input"] context = """ - $(a.memory["shortmem"]["scratchpad"]) + $(GeneralUtils.dict_to_string_html(a.memory["shortmem"])) """ @@ -179,9 +179,9 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10 continue end - if responsedict["actionname"] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERSATION"] + if responsedict["action_name"] ∉ ["CHATBOX", "CHECKWINE", "PRESENTBOX", "ENDCONVERGUIDELINE"] 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["action_name"])", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue end @@ -216,8 +216,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["action_input"] is the same as previous dialogue + # 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 @@ -317,16 +317,16 @@ 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 - "actionname" is the name of the action taken, which can be one of the available tool name. - "actioninput" is the input to the action. + "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. - Use only infomation provided by the store policy and guidelines as a bedrocks for your response. - - 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. + - 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 action name and action input should make sense. For example, if the trainee isn't finished talking, he shouldn't use the ENDCONVERGUIDELINE tool. 1) trajectory_evaluation: Analyze the trajectory of a solution to answer the user's original question. @@ -368,7 +368,7 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext $evaluateecontext - {plan: $(decisiondict["plan"]), actionname: $(decisiondict["actionname"]), actioninput: $(decisiondict["actioninput"])} + {plan: $(decisiondict["plan"]), action_name: $(decisiondict["action_name"]), action_input: $(decisiondict["action_input"])} P.S. $errornote @@ -483,7 +483,7 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj end # place holder - actionname = nothing + action_name = nothing result = nothing chatresponse = nothing @@ -498,8 +498,8 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj # thinking loop until AI wants to communicate with the user chatresponse = nothing while chatresponse === nothing - actionname, result = think(a) - if actionname ∈ ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"] + action_name, result = think(a) + if action_name ∈ ["CHATBOX"] chatresponse = result end end @@ -532,8 +532,8 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; 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"], ) ) chatresponse = generatechat(a; converPartnerName=converPartnerName, recentEventNum=20) @@ -545,8 +545,8 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict; event_description="the assistant talks to the user.", timestamp=Dates.now(), subject="assistant", - actionname="CHATBOX", - actioninput=chatresponse, + action_name="CHATBOX", + action_input=chatresponse, ) ) return chatresponse @@ -564,20 +564,20 @@ julia> ``` """ -function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} where {T<:agent} +function think(a::T)::Union{NamedTuple{(:action_name, :result), Tuple{String, String}}, NamedTuple{(:action_name, :result), Tuple{String, Nothing}}} where {T<:agent} # a.memory[:recap] = generateSituationReport(a, a.context["text"2textInstructLLM]; skiprecent=0) thoughtDict = decisionMaker(a) # # map action and input() to llm function # response = - # if thoughtDict["actionname"] == "CHATBOX" || thoughtDict["actionname"] == "ENDCONVERSATION" + # if thoughtDict["action_name"] == "CHATBOX" || thoughtDict["action_name"] == "ENDCONVERGUIDELINE" # (result=thoughtDict["plan"], errormsg=nothing, success=true) - # elseif thoughtDict["actionname"] == "CHECKWINE" - # checkwine(a, thoughtDict["actioninput"]) - # elseif thoughtDict["actionname"] == "PRESENTBOX" - # (result=thoughtDict["actioninput"], errormsg=nothing, success=true) + # elseif thoughtDict["action_name"] == "CHECKWINE" + # checkwine(a, thoughtDict["action_input"]) + # elseif thoughtDict["action_name"] == "PRESENTBOX" + # (result=thoughtDict["action_input"], errormsg=nothing, success=true) # else - # error("undefined LLM function. Requesting $(thoughtDict["actionname"])") + # error("undefined LLM function. Requesting $(thoughtDict["action_name"])") # end # # this section allow LLM functions above to have different return values. @@ -590,52 +590,52 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh # success::Bool = haskey(response, "success") ? response["success"] : false result = nothing - if thoughtDict["actionname"] ∈ ["CHATBOX"] - result = thoughtDict["actioninput"] - elseif thoughtDict["actionname"] ∈ ["ENDCONVERSATION"] - # WORKING add ENDCONVERSATION guideline in to scratchpad - guideline = + if thoughtDict["action_name"] ∈ ["CHATBOX"] + result = thoughtDict["action_input"] + elseif thoughtDict["action_name"] == "ENDCONVERGUIDELINE" + + # add ENDCONVERGUIDELINE guideline in to scratchpad + endconversation_guideline = """ - To end conversation with the user + + - Provide customer with store contact info and business hours + - Invite customer to comeback + + + Business Hours: everyday 9.00-20.00 + Tel. 0863055790 + """ - - a.memory["shortmem"]["scratchpad"] = - result = chatresponse - elseif thoughtDict["actionname"] ∈ ["PRESENTBOX"] - chatresponse = presentbox(a, thoughtDict) #PENDING - result = chatresponse - - elseif thoughtDict["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) + thoughtDict["action_result"] = endconversation_guideline + max_ind = + if length(a.memory["shortmem"]) == 0 + 0 else - a.memory["shortmem"]["db_search_result"] = vd + k = keys(a.memory["shortmem"]) + maximum(parse.(Int, k)) end + a.memory["shortmem"]["$(max_ind + 1)"] = thoughtDict - # # 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 - # - # """ - end + elseif thoughtDict["action_name"] ∈ ["PRESENTBOX"] #PENDING + chatresponse = presentbox(a, thoughtDict) + result = chatresponse + + elseif thoughtDict["action_name"] == "CHECKWINE" + df = checkwine(a, thoughtDict["action_input"]) + thoughtDict["action_result"] = GeneralUtils.dfToString(df) + max_ind = + if length(a.memory["shortmem"]) == 0 + 0 + else + k = keys(a.memory["shortmem"]) + maximum(parse.(Int, k)) + end + a.memory["shortmem"]["$(max_ind + 1)"] = thoughtDict else error("condition is not defined ", @__FILE__, ":", @__LINE__, " $(Dates.now())") end - return (actionname=thoughtDict["actionname"], result=result) + return (action_name=thoughtDict["action_name"], result=result) end @@ -697,7 +697,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev context = """ - Name of the wines that needs to be introduced: $(thoughtDict["actioninput"]) + Name of the wines that needs to be introduced: $(thoughtDict["action_input"]) $(a.memory["shortmem"]["scratchpad"]) P.S. $errornote @@ -1333,4 +1333,74 @@ function detectWineryName(a, text) -end # module interface \ No newline at end of file +end # module interface + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/llmfunction.jl b/src/llmfunction.jl index 273509b..2564501 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -190,7 +190,7 @@ pushfirst!(virtualCustomerChatHistory, Dict("name"=> "system", "text"=> systemms push!(chathistory, newdict) end - push!(chathistory, Dict("name"=> "assistant", "text"=> input)) + push!(chathistory, Dict("name"=> "assistant", "text"=> input)) # put in model format prompt = formatLLMtext(chathistory, "llama3instruct") @@ -309,7 +309,8 @@ 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, + textresult, rawresponse = SQLLLM.query( + inventoryquery, a.context.executeSQL, a.context.text2textInstructLLM; insertSQLVectorDB=a.context.insertSQLVectorDB, @@ -546,7 +547,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10 if j == :wine_price if responsedict["wine_price"] != "N/A" if !occursin("to", responsedict["wine_price"]) - errornote = "In your previous attempt, the 'wine_price' was set to $(responsedict["wine_price"]) which is not a correct format. Please adjust it accordingly." + errornote = "In your previous attempt, the 'wine_price' was set to $(responsedict["wine_price"]) which is not a correct format. Please adjust it accordingly." println("\nERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())") checkFlag = true break @@ -1006,7 +1007,7 @@ function jsoncorrection(config::T1, input::T2, correctJsonExample::T3; externalService = config["externalservice"]["text2textinstruct"] llminfo = externalService["llminfo"] prompt = - if llminfo["name"] == "llama3instruct" + if llminfo["name"] == "llama3instruct" formatLLMtext_llama3instruct("system", _prompt) else error("llm model name is not defied yet $(@__LINE__)") @@ -1053,7 +1054,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". -# "actioninput" is the input to the action +# "action_input" 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/type.jl b/src/type.jl index 55f40cd..4fa4687 100644 --- a/src/type.jl +++ b/src/type.jl @@ -177,7 +177,7 @@ function sommelier( Dict( "role" => "system", "content" => [ - Dict("type" => "text", "text" => "You are a helpful assiatant"), + Dict("type" => "text", "text" => "You are a helpful assistant"), ] ), Dict( @@ -197,10 +197,8 @@ function sommelier( ] """ memory = Dict{String, Any}( - "shortmem"=> OrderedDict{String, Any}( - "db_search_result"=> Any[], - "scratchpad"=> "", - ), + "shortmem"=> OrderedDict{String, Any}(), + "scratchpad"=> "", "events"=> Vector{Dict{String, Any}}(), "state"=> Dict{String, Any}( ), @@ -237,6 +235,7 @@ function sommelier( - Greeting the customer warmly by ask them how could you help. Do not ask any other questions during this greeting. + - Customer may provide images for you to look up. - 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. @@ -250,10 +249,10 @@ function sommelier( 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 to generate proper dialogue 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 generates a natural dialogue to gracefully close the conversation with the user. The input is "nothing" keyword. The output is a natural, context-aware dialogue extension that smoothly concludes the conversation. + - ENDCONVERGUIDELINE which you can use to check the store guidelines about how to end the conversation with the user. The input is "nothing" keyword. The output is the guidelines that you can follow. - 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 name is $(newAgent.name). You are a helpful sommelier for website-based $(newAgent.retailername)'s wine store. You are working under your mentor supervision. Your customer is coming into the store @@ -272,19 +271,17 @@ function sommelier( 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. + 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. + After the tool is executed you gets "action_result". It is the output from the tool you selected. { "plan": "...", - "actionname": "...", - "actioninput": "..." + "action_name": "...", + "action_input": "..." } diff --git a/src/util.jl b/src/util.jl index 1186d1e..85fbb39 100644 --- a/src/util.jl +++ b/src/util.jl @@ -200,9 +200,9 @@ end The subject or entity associated with the event - `thought::Union{AbstractDict, Nothing}` Any associated thoughts or metadata - - `actionname::Union{String, Nothing}` + - `action_name::Union{String, Nothing}` The name of the action performed (e.g., "CHAT", "CHECKINVENTORY") - - `actioninput::Union{String, Nothing}` + - `action_input::Union{String, Nothing}` Input or parameters for the action - `location::Union{String, Nothing}` Where the event took place @@ -223,8 +223,8 @@ 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, @@ -237,8 +237,8 @@ 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, @@ -254,22 +254,22 @@ end # Arguments - `events::T1` - Vector of event dictionaries containing subject, actioninput and optional outcome fields + Vector of event dictionaries containing subject, action_input and optional outcome fields 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 + - :action_input - The action or input performed by the subject - :observation - (Optional) The result or outcome of the action # Returns - `timeline::String` A formatted string representing the events with their subjects, actions, and optional outcomes - Format: "{index}) {subject}> {actioninput} {outcome}\n" for each event + Format: "{index}) {subject}> {action_input} {outcome}\n" for each event # Example events = [ - Dict("subject" => "User", "actioninput" => "Hello", "observation" => nothing), - Dict("subject" => "Assistant", "actioninput" => "Hi there!", "observation" => "with a smile") + Dict("subject" => "User", "action_input" => "Hello", "observation" => nothing), + Dict("subject" => "Assistant", "action_input" => "Hi there!", "observation" => "with a smile") ] timeline = createTimeline(events) # 1) User> Hello @@ -293,14 +293,14 @@ function createTimeline(events::T1; eventindex::Union{UnitRange, Nothing}=nothin for i in ind event = events[i] # If no outcome exists, format without outcome -# if event["actionname"] == "CHATBOX" - # timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"])\n" - # elseif event["actionname"] == "CHECKINVENTORY" && event["observation"] === nothing - # timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: Not done yet.\n" - if event["actionname"] == "CHECKWINE" - timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: $(event["observation"])\\n" +# if event["action_name"] == "CHATBOX" + # timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"])\n" + # elseif event["action_name"] == "CHECKINVENTORY" && event["observation"] === nothing + # timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"]), observation: Not done yet.\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"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"])\\n" + timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"])\\n" end end @@ -325,10 +325,10 @@ end # event = events[i] # # If no outcome exists, format without outcome # if event["observation"] === nothing - # timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: Not done yet.\n" + # timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"]), observation: Not done yet.\n" # # If outcome exists, include it in formatting # else - # timeline *= "Event_$i $(event["subject"])> actionname: $(event["actionname"]), actioninput: $(event["actioninput"]), observation: $(event["observation"])\\n" + # timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"]), observation: $(event["observation"])\\n" # end # end @@ -356,17 +356,17 @@ function createEventsLog(events::T1; index::Union{UnitRange, Nothing}=nothing # If no outcome exists, format without outcome if event["observation"] === nothing subject = event["subject"] - actionname = event["actionname"] - actioninput = event["actioninput"] - str = "actionname: $actionname, actioninput: $actioninput" + action_name = event["action_name"] + action_input = event["action_input"] + str = "action_name: $action_name, action_input: $action_input" d = Dict{String, String}("name"=>subject, "text"=>str) push!(log, d) else subject = event["subject"] - actionname = event["actionname"] - actioninput = event["actioninput"] + action_name = event["action_name"] + action_input = event["action_input"] observation = event["observation"] - str = "actionname: $actionname, actioninput: $actioninput, observation: $observation" + str = "action_name: $action_name, action_input: $action_input, observation: $observation" d = Dict{String, String}("name"=>subject, "text"=>str) push!(log, d) end