This commit is contained in:
2026-06-28 22:03:58 +07:00
parent e63dd7d898
commit d076d5f912
8 changed files with 188 additions and 120 deletions
+4 -4
View File
@@ -2,7 +2,7 @@
julia_version = "1.12.6" julia_version = "1.12.6"
manifest_format = "2.0" manifest_format = "2.0"
project_hash = "972fb718a7c47dc6826419825a1ab5fe7b0fde84" project_hash = "a7a5dbec939b5bcaa54ea4aedd3c8ff223c86502"
[[deps.AliasTables]] [[deps.AliasTables]]
deps = ["PtrArrays", "Random"] deps = ["PtrArrays", "Random"]
@@ -247,11 +247,11 @@ version = "1.11.0"
[[deps.GeneralUtils]] [[deps.GeneralUtils]]
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "UUIDs"] 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-rev = "main"
repo-url = "https://git.yiem.cc/ton/GeneralUtils" repo-url = "https://git.yiem.cc/ton/GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe" uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
version = "0.4.0" version = "0.4.2"
[[deps.HTTP]] [[deps.HTTP]]
deps = ["Base64", "CodecZlib", "Dates", "EnumX", "PrecompileTools", "Random", "Reseau", "SHA", "URIs", "UUIDs", "Zlib_jll"] 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" version = "1.6.1"
[[deps.YiemAgent]] [[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 = "." path = "."
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2" uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
version = "0.4.0" version = "0.4.0"
+1 -1
View File
@@ -26,7 +26,7 @@ msghandler = "f2724d33-f338-4a57-b9f8-1be882570d10"
[compat] [compat]
CSV = "0.10.15" CSV = "0.10.15"
DataFrames = "1.7.0" DataFrames = "1.7.0"
GeneralUtils = "0.4.0" GeneralUtils = "0.4.2"
HTTP = "2.4.0" HTTP = "2.4.0"
JSON = "1.6.1" JSON = "1.6.1"
NATS = "0.1.0" NATS = "0.1.0"
+3 -3
View File
@@ -426,7 +426,7 @@ function main()
# event_description="the assistant talks to the user.", # event_description="the assistant talks to the user.",
# timestamp=Dates.now(), # timestamp=Dates.now(),
# subject="assistant", # subject="assistant",
# actionname="CHATBOX", # action_name="CHATBOX",
# action_input=customer_chat, # action_input=customer_chat,
# ) # )
# ) # )
@@ -453,8 +453,8 @@ function main()
println("\nagent respond:\n $agent_response") println("\nagent respond:\n $agent_response")
if haskey(agent.memory[:events][end], :thought) if haskey(agent.memory[:events][end], :thought)
lastAssistantAction = agent.memory[:events][end][:thought][:actionname] 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 # save a.memory[:shortmem][:decisionlog] to disk using JSON
println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") println("\nsaving agent.memory[:shortmem][:decisionlog] to disk")
+1 -1
View File
@@ -429,7 +429,7 @@ function runAgentInstance(
if haskey(agent.memory[:events][end], :thought) if haskey(agent.memory[:events][end], :thought)
lastAssistantAction = agent.memory[:events][end][:thought][:action_name] 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 # save a.memory[:shortmem][:decisionlog] to disk using JSON
println("\nsaving agent.memory[:shortmem][:decisionlog] to disk") println("\nsaving agent.memory[:shortmem][:decisionlog] to disk")
+136 -66
View File
@@ -48,6 +48,7 @@ macro executeStringFunction(functionStr, args...)
end end
""" Think and choose action """ Think and choose action
# Arguments # Arguments
@@ -125,12 +126,11 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
# recentevents_ind = GeneralUtils.recentElementsIndex( # recentevents_ind = GeneralUtils.recentElementsIndex(
# length(a.memory["events"]), recentevents; includelatest=true) # length(a.memory["events"]), recentevents; includelatest=true)
requiredKeys = ["plan", "actionname", "actioninput"] requiredKeys = ["plan", "action_name", "action_input"]
context = context =
""" """
<internal_context_for_assistant> <internal_context_for_assistant>
$(a.memory["shortmem"]["scratchpad"]) $(GeneralUtils.dict_to_string_html(a.memory["shortmem"]))
</internal_context_for_assistant> </internal_context_for_assistant>
""" """
@@ -179,9 +179,9 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
continue continue
end 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" 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 continue
end end
@@ -216,8 +216,8 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
# delete!(responsedict, :mentioned_winery) # delete!(responsedict, :mentioned_winery)
# check whether responsedict["actioninput"] is the same as previous dialogue # check whether responsedict["action_input"] is the same as previous dialogue
# if !isempty(a.chathistory) && responsedict["actioninput"] == 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." # errornote = "In your previous attempt, you repeated the previous dialogue. Please try again."
# println("\nERROR YiemAgent decisionMaker() $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())") # println("\nERROR YiemAgent decisionMaker() $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
# continue # continue
@@ -317,16 +317,16 @@ function evaluator(a::T1, timeline, decisiondict, evaluateecontext
- evaluatee_context: The context that evaluatee use to make a decision - evaluatee_context: The context that evaluatee use to make a decision
- evaluatee_decision: The decision made by the evaluatee, consists of the following elements: - evaluatee_decision: The decision made by the evaluatee, consists of the following elements:
"plan" is the trainee's plan "plan" is the trainee's plan
"actionname" is the name of the action taken, which can be one of the available tool name. "action_name" is the name of the action taken, which can be one of the available tool name.
"actioninput" is the input to the action. "action_input" is the input to the action.
</At each round of conversation, you will be given the following information> </At each round of conversation, you will be given the following information>
<You must follow the following policy> <You must follow the following policy>
- Use only infomation provided by the store policy and guidelines as a bedrocks for your response. - Use only infomation provided by the store policy and guidelines as a bedrocks for your response.
</You must follow the following policy> </You must follow the following policy>
<You should follow the following guidelines> <You should follow the following guidelines>
- The trainee's plan, actionname, and actioninput must be logically consistent - The trainee's plan, action_name, and action_input must be logically consistent
- The trainee's actioninput should be in a proper format as specified by the tools. - 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 ENDCONVERSATION tool. - 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.
</You should follow the following guidelines> </You should follow the following guidelines>
<You should then respond to the user with> <You should then respond to the user with>
1) trajectory_evaluation: Analyze the trajectory of a solution to answer the user's original question. 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 $evaluateecontext
</evaluatee_context> </evaluatee_context>
<evaluatee_decision> <evaluatee_decision>
{plan: $(decisiondict["plan"]), actionname: $(decisiondict["actionname"]), actioninput: $(decisiondict["actioninput"])} {plan: $(decisiondict["plan"]), action_name: $(decisiondict["action_name"]), action_input: $(decisiondict["action_input"])}
</evaluatee_decision> </evaluatee_decision>
P.S. $errornote P.S. $errornote
</context> </context>
@@ -483,7 +483,7 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj
end end
# place holder # place holder
actionname = nothing action_name = nothing
result = nothing result = nothing
chatresponse = 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 # thinking loop until AI wants to communicate with the user
chatresponse = nothing chatresponse = nothing
while chatresponse === nothing while chatresponse === nothing
actionname, result = think(a) action_name, result = think(a)
if actionname ["CHATBOX", "PRESENTBOX", "ENDCONVERSATION"] if action_name ["CHATBOX"]
chatresponse = result chatresponse = result
end end
end end
@@ -532,8 +532,8 @@ function conversation(a::Union{companion, virtualcustomer}, userinput::Dict;
event_description="the user talks to the assistant.", event_description="the user talks to the assistant.",
timestamp=Dates.now(), timestamp=Dates.now(),
subject="user", subject="user",
actionname="CHATBOX", action_name="CHATBOX",
actioninput=userinput["text"], action_input=userinput["text"],
) )
) )
chatresponse = generatechat(a; converPartnerName=converPartnerName, recentEventNum=20) 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.", event_description="the assistant talks to the user.",
timestamp=Dates.now(), timestamp=Dates.now(),
subject="assistant", subject="assistant",
actionname="CHATBOX", action_name="CHATBOX",
actioninput=chatresponse, action_input=chatresponse,
) )
) )
return 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) # a.memory[:recap] = generateSituationReport(a, a.context["text"2textInstructLLM]; skiprecent=0)
thoughtDict = decisionMaker(a) thoughtDict = decisionMaker(a)
# # map action and input() to llm function # # map action and input() to llm function
# response = # response =
# if thoughtDict["actionname"] == "CHATBOX" || thoughtDict["actionname"] == "ENDCONVERSATION" # if thoughtDict["action_name"] == "CHATBOX" || thoughtDict["action_name"] == "ENDCONVERGUIDELINE"
# (result=thoughtDict["plan"], errormsg=nothing, success=true) # (result=thoughtDict["plan"], errormsg=nothing, success=true)
# elseif thoughtDict["actionname"] == "CHECKWINE" # elseif thoughtDict["action_name"] == "CHECKWINE"
# checkwine(a, thoughtDict["actioninput"]) # checkwine(a, thoughtDict["action_input"])
# elseif thoughtDict["actionname"] == "PRESENTBOX" # elseif thoughtDict["action_name"] == "PRESENTBOX"
# (result=thoughtDict["actioninput"], errormsg=nothing, success=true) # (result=thoughtDict["action_input"], errormsg=nothing, success=true)
# else # else
# error("undefined LLM function. Requesting $(thoughtDict["actionname"])") # error("undefined LLM function. Requesting $(thoughtDict["action_name"])")
# end # end
# # this section allow LLM functions above to have different return values. # # 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 # success::Bool = haskey(response, "success") ? response["success"] : false
result = nothing result = nothing
if thoughtDict["actionname"] ["CHATBOX"] if thoughtDict["action_name"] ["CHATBOX"]
result = thoughtDict["actioninput"] result = thoughtDict["action_input"]
elseif thoughtDict["actionname"] ["ENDCONVERSATION"] elseif thoughtDict["action_name"] == "ENDCONVERGUIDELINE"
# WORKING add ENDCONVERSATION guideline in to scratchpad
guideline = # add ENDCONVERGUIDELINE guideline in to scratchpad
endconversation_guideline =
""" """
To end conversation with the user <end_conversation_guideline>
- Provide customer with store contact info and business hours
- Invite customer to comeback
</end_conversation_guideline>
<store_info>
Business Hours: everyday 9.00-20.00
Tel. 0863055790
</store_info>
""" """
thoughtDict["action_result"] = endconversation_guideline
a.memory["shortmem"]["scratchpad"] = max_ind =
result = chatresponse if length(a.memory["shortmem"]) == 0
elseif thoughtDict["actionname"] ["PRESENTBOX"] 0
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)
else else
a.memory["shortmem"]["db_search_result"] = vd k = keys(a.memory["shortmem"])
maximum(parse.(Int, k))
end end
a.memory["shortmem"]["$(max_ind + 1)"] = thoughtDict
# # add to scratchpad elseif thoughtDict["action_name"] ["PRESENTBOX"] #PENDING
# a.memory["shortmem"]["scratchpad"] *= chatresponse = presentbox(a, thoughtDict)
# """ result = chatresponse
# <database_search_result>
# I searched the database with this search term: $actioninput \nThis is what I found: $result elseif thoughtDict["action_name"] == "CHECKWINE"
# </database_search_result> df = checkwine(a, thoughtDict["action_input"])
# """ thoughtDict["action_result"] = GeneralUtils.dfToString(df)
else max_ind =
# a.memory["shortmem"]["scratchpad"] *= if length(a.memory["shortmem"]) == 0
# """ 0
# <database_search_result> else
# I searched the database with this search term: $actioninput \nThis is what I found: $result k = keys(a.memory["shortmem"])
# </database_search_result> maximum(parse.(Int, k))
# """ end
end a.memory["shortmem"]["$(max_ind + 1)"] = thoughtDict
else else
error("condition is not defined ", @__FILE__, ":", @__LINE__, " $(Dates.now())") error("condition is not defined ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
end end
return (actionname=thoughtDict["actionname"], result=result) return (action_name=thoughtDict["action_name"], result=result)
end end
@@ -697,7 +697,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
context = context =
""" """
<context> <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"]) $(a.memory["shortmem"]["scratchpad"])
P.S. $errornote P.S. $errornote
</context> </context>
@@ -1333,4 +1333,74 @@ function detectWineryName(a, text)
end # module interface end # module interface
+6 -5
View File
@@ -190,7 +190,7 @@ pushfirst!(virtualCustomerChatHistory, Dict("name"=> "system", "text"=> systemms
push!(chathistory, newdict) push!(chathistory, newdict)
end end
push!(chathistory, Dict("name"=> "assistant", "text"=> input)) push!(chathistory, Dict("name"=> "assistant", "text"=> input))
# put in model format # put in model format
prompt = formatLLMtext(chathistory, "llama3instruct") 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}" inventoryquery = "Retrieves $retrieve_attributes of wines that match the following criteria - {$_inventoryquery}"
println("\ncheckinventory input: $inventoryquery ", @__FILE__, ":", @__LINE__, " $(Dates.now())") println("\ncheckinventory input: $inventoryquery ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
# add suppport for similarSQLVectorDB # add suppport for similarSQLVectorDB
textresult, rawresponse = SQLLLM.query(inventoryquery, textresult, rawresponse = SQLLLM.query(
inventoryquery,
a.context.executeSQL, a.context.executeSQL,
a.context.text2textInstructLLM; a.context.text2textInstructLLM;
insertSQLVectorDB=a.context.insertSQLVectorDB, insertSQLVectorDB=a.context.insertSQLVectorDB,
@@ -546,7 +547,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
if j == :wine_price if j == :wine_price
if responsedict["wine_price"] != "N/A" if responsedict["wine_price"] != "N/A"
if !occursin("to", responsedict["wine_price"]) 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())") println("\nERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
checkFlag = true checkFlag = true
break break
@@ -1006,7 +1007,7 @@ function jsoncorrection(config::T1, input::T2, correctJsonExample::T3;
externalService = config["externalservice"]["text2textinstruct"] externalService = config["externalservice"]["text2textinstruct"]
llminfo = externalService["llminfo"] llminfo = externalService["llminfo"]
prompt = prompt =
if llminfo["name"] == "llama3instruct" if llminfo["name"] == "llama3instruct"
formatLLMtext_llama3instruct("system", _prompt) formatLLMtext_llama3instruct("system", _prompt)
else else
error("llm model name is not defied yet $(@__LINE__)") 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: # “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. # 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". # 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. # "observation" is result of the preceding immediate action.
# At each round of conversation, the user will give you: # At each round of conversation, the user will give you:
+11 -14
View File
@@ -177,7 +177,7 @@ function sommelier(
Dict( Dict(
"role" => "system", "role" => "system",
"content" => [ "content" => [
Dict("type" => "text", "text" => "You are a helpful assiatant"), Dict("type" => "text", "text" => "You are a helpful assistant"),
] ]
), ),
Dict( Dict(
@@ -197,10 +197,8 @@ function sommelier(
] ]
""" """
memory = Dict{String, Any}( memory = Dict{String, Any}(
"shortmem"=> OrderedDict{String, Any}( "shortmem"=> OrderedDict{String, Any}(),
"db_search_result"=> Any[], "scratchpad"=> "",
"scratchpad"=> "",
),
"events"=> Vector{Dict{String, Any}}(), "events"=> Vector{Dict{String, Any}}(),
"state"=> Dict{String, Any}( "state"=> Dict{String, Any}(
), ),
@@ -237,6 +235,7 @@ function sommelier(
</Store_policy> </Store_policy>
<Store_guidelines> <Store_guidelines>
- Greeting the customer warmly by ask them how could you help. Do not ask any other questions during this greeting. - 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. - 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. - 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. - 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 2: "Red or white wine, medium tannin, price under 700 USD"
Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France 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. - 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.
</Available tools> </Available tools>
<your role> <your role>
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 role> </your role>
<situation> <situation>
Your customer is coming into the store 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. 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. 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.
</your responsibility does NOT includes> </your responsibility does NOT includes>
<at each round of conversation, you will be given the following information>
context: additional information about the current situation
</at each round of conversation, you will be given the following information>
<you should then respond to the user with interleaving Plan, Action_name, Action_input> <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. 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 2) action_name: (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. 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.
</you should then respond to the user with interleaving Plan, Action_name, Action_input> </you should then respond to the user with interleaving Plan, Action_name, Action_input>
<you should only respond in JSON format as described below> <you should only respond in JSON format as described below>
{ {
"plan": "...", "plan": "...",
"actionname": "...", "action_name": "...",
"actioninput": "..." "action_input": "..."
} }
</you should only respond in format as described below> </you should only respond in format as described below>
+26 -26
View File
@@ -200,9 +200,9 @@ end
The subject or entity associated with the event The subject or entity associated with the event
- `thought::Union{AbstractDict, Nothing}` - `thought::Union{AbstractDict, Nothing}`
Any associated thoughts or metadata Any associated thoughts or metadata
- `actionname::Union{String, Nothing}` - `action_name::Union{String, Nothing}`
The name of the action performed (e.g., "CHAT", "CHECKINVENTORY") 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 Input or parameters for the action
- `location::Union{String, Nothing}` - `location::Union{String, Nothing}`
Where the event took place Where the event took place
@@ -223,8 +223,8 @@ function eventdict(;
timestamp::Union{DateTime, Nothing}=nothing, timestamp::Union{DateTime, Nothing}=nothing,
subject::Union{String, Nothing}=nothing, subject::Union{String, Nothing}=nothing,
thought::Union{AbstractDict, Nothing}=nothing, thought::Union{AbstractDict, Nothing}=nothing,
actionname::Union{String, Nothing}=nothing, # "CHAT", "CHECKINVENTORY", "PRESENTBOX", etc action_name::Union{String, Nothing}=nothing, # "CHAT", "CHECKINVENTORY", "PRESENTBOX", etc
actioninput::Union{String, Nothing}=nothing, action_input::Union{String, Nothing}=nothing,
location::Union{String, Nothing}=nothing, location::Union{String, Nothing}=nothing,
equipment_used::Union{String, Nothing}=nothing, equipment_used::Union{String, Nothing}=nothing,
material_used::Union{String, Nothing}=nothing, material_used::Union{String, Nothing}=nothing,
@@ -237,8 +237,8 @@ function eventdict(;
"timestamp"=> timestamp, "timestamp"=> timestamp,
"subject"=> subject, "subject"=> subject,
"thought"=> thought, "thought"=> thought,
"actionname"=> actionname, "action_name"=> action_name,
"actioninput"=> actioninput, "action_input"=> action_input,
"location"=> location, "location"=> location,
"equipment_used"=> equipment_used, "equipment_used"=> equipment_used,
"material_used"=> material_used, "material_used"=> material_used,
@@ -254,22 +254,22 @@ end
# Arguments # Arguments
- `events::T1` - `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: Each event dictionary should have the following keys:
- :subject - The subject or entity performing the action - :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 - :observation - (Optional) The result or outcome of the action
# Returns # Returns
- `timeline::String` - `timeline::String`
A formatted string representing the events with their subjects, actions, and optional outcomes 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 # Example
events = [ events = [
Dict("subject" => "User", "actioninput" => "Hello", "observation" => nothing), Dict("subject" => "User", "action_input" => "Hello", "observation" => nothing),
Dict("subject" => "Assistant", "actioninput" => "Hi there!", "observation" => "with a smile") Dict("subject" => "Assistant", "action_input" => "Hi there!", "observation" => "with a smile")
] ]
timeline = createTimeline(events) timeline = createTimeline(events)
# 1) User> Hello # 1) User> Hello
@@ -293,14 +293,14 @@ function createTimeline(events::T1; eventindex::Union{UnitRange, Nothing}=nothin
for i in ind for i in ind
event = events[i] event = events[i]
# If no outcome exists, format without outcome # If no outcome exists, format without outcome
# if event["actionname"] == "CHATBOX" # if event["action_name"] == "CHATBOX"
# 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"
# elseif event["actionname"] == "CHECKINVENTORY" && event["observation"] === nothing # elseif event["action_name"] == "CHECKINVENTORY" && 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 event["actionname"] == "CHECKWINE" if event["action_name"] == "CHECKWINE"
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"
else 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
end end
@@ -325,10 +325,10 @@ end
# event = events[i] # event = events[i]
# # If no outcome exists, format without outcome # # If no outcome exists, format without outcome
# if event["observation"] === nothing # 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 # # If outcome exists, include it in formatting
# else # 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
# end # end
@@ -356,17 +356,17 @@ function createEventsLog(events::T1; index::Union{UnitRange, Nothing}=nothing
# If no outcome exists, format without outcome # If no outcome exists, format without outcome
if event["observation"] === nothing if event["observation"] === nothing
subject = event["subject"] subject = event["subject"]
actionname = event["actionname"] action_name = event["action_name"]
actioninput = event["actioninput"] action_input = event["action_input"]
str = "actionname: $actionname, actioninput: $actioninput" str = "action_name: $action_name, action_input: $action_input"
d = Dict{String, String}("name"=>subject, "text"=>str) d = Dict{String, String}("name"=>subject, "text"=>str)
push!(log, d) push!(log, d)
else else
subject = event["subject"] subject = event["subject"]
actionname = event["actionname"] action_name = event["action_name"]
actioninput = event["actioninput"] action_input = event["action_input"]
observation = event["observation"] 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) d = Dict{String, String}("name"=>subject, "text"=>str)
push!(log, d) push!(log, d)
end end