update
This commit is contained in:
+4
-4
@@ -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
@@ -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"
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user