This commit is contained in:
narawat lamaiin
2024-08-14 21:21:44 +07:00
parent 38a2f673e9
commit 2c095a584b
5 changed files with 250 additions and 80 deletions

View File

@@ -209,27 +209,28 @@ function decisionMaker(a::T)::Dict{Symbol, Any} where {T<:agent}
# Let's begin! # Let's begin!
# """ # """
QandA = generatequestion(a, a.text2textInstructLLM)
systemmsg = systemmsg =
""" """
You are a helpful assistant acting as a polite, website-based sommelier for an online wine store. You are a helpful assistant acting as a polite, website-based sommelier for an online wine store.
You are currently talking with the user. Your goal is: Help the user select the best wines from your inventory that align with the user's preferences.
Your goal is to recommend the best wines from your inventory that match the user's preferences.
You don't need to do any sale process. Your responsibility includes:
1) Make an informed decision about what you need to do to achieve the goal.
2) Thanks the user when they are done choosing wines and invite them to comeback next time.
Your responsibility does not include:
1) Processing sales orders or engaging in any other sales-related activities.
At each round of conversation, you will be given the current situation: At each round of conversation, you will be given the current situation:
Your conversation with the user: ... Recap: ...
Context: ... Context: ...
Your Q&A: Your Q&A about the situation
You MUST follow the following guidelines: You MUST follow the following guidelines:
- Generally speaking, your inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know which wines your store carries until you check your inventory. - Generally speaking, your inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know which wines your store carries until you check your inventory.
- All wines in your inventory are always in stock. - All wines in your inventory are always in stock.
- Use the "understand-then-check" inventory strategy to understand the user, as there are many wines in the inventory. - Use the "understand-then-check" inventory strategy to understand the user, as there are many wines in the inventory.
- Do not ask the user about wine's flavor e.g. floral, citrusy, nutty or some thing similar as these terms cannot be used to search the database. - Do not ask the user about wine's flavor e.g. floral, citrusy, nutty or some thing similar as these terms cannot be used to search the database.
- Once the user has selected their wine, ask the user if they require any further assistance. Do not offer additional services. - Once the user has selected their wine, ask the user if they need any further assistance. Do not offer any additional services. If the user doesn't need any further assistance, say goodbye and invite them to come back next time.
- If the user doesn't require any further assistance, use the ENDCONVERSATION function to end the conversation.
You should follow the following guidelines as you see fit: You should follow the following guidelines as you see fit:
- If the user interrupts, prioritize the user. - If the user interrupts, prioritize the user.
@@ -238,22 +239,20 @@ function decisionMaker(a::T)::Dict{Symbol, Any} where {T<:agent}
- If you don't already know, find out the occasion for which the user is buying wine. - If you don't already know, find out the occasion for which the user is buying wine.
- If you don't already know, find out the characteristics of wine the user is looking for, such as tannin, sweetness, intensity, acidity. - If you don't already know, find out the characteristics of wine the user is looking for, such as tannin, sweetness, intensity, acidity.
- If you don't already know, find out what food will be served with wine. - If you don't already know, find out what food will be served with wine.
- If you haven't already, compare the wines and present them to the user. - If you haven't already, present the wines you found to the user.
You should then respond to the user with interleaving Thought, Plan, Action: You should then respond to the user with interleaving Thought, Plan, Action:
- thought: 1) thought:
1) State your reasoning about the current situation. - State your reasoning about the current situation.
- plan: Based on the current situation, state a complete plan to complete the task. Be specific. 2) plan: Based on the current situation, state a complete plan to complete the task. Be specific.
- action_name (Must be aligned with your plan): The name of the action which can be one of the following functions: 3) action_name (Must be aligned with your plan): The name of the action which can be one of the following functions:
1) CHATBOX which you can use to generate conversation in order to communicate with the user. The input is your intention for the talk. Be specific. - CHATBOX which you can use to generate conversation in order to communicate with the user. The input is your intention for the talk. Be specific.
2) CHECKINVENTORY which you can use to check info about wine in your inventory. The input is a search term in verbal English. - CHECKINVENTORY which you can use to check info about wine in your inventory. The input is a search term in verbal English.
Good query example: black car, a stereo, 200 mile range, electric motor. Good query example: black car, a stereo, 200 mile range, electric motor.
Good query example: How many car brand are from Asia? - PRESENTBOX which you can use to introduce wines to users for the first time. It is more effective than the CHATBOX function for presenting wines. The input is the names of wines to present.
3) PRESENTBOX which you can use to present the wines to the user. This function is better than CHATBOX at presenting wines. The input is the names of wines to present. - ENDCONVERSATION which you can use when you want to finish the conversation with the user. The input is "NA".
4) ENDCONVERSATION which you can use to end the conversation with the user. The input is "NA". 4) action_input: input details of the action
5) mentioning_wine: Are you mentioning specific wine name to the user? Can be "Yes" or "No"
- action_input: input details of the action
- mentioning_wine: Are you mentioning specific wine name to the user? Can be "Yes" or "No"
You should only respond in format as described below: You should only respond in format as described below:
thought: ... thought: ...
@@ -271,16 +270,15 @@ function decisionMaker(a::T)::Dict{Symbol, Any} where {T<:agent}
else else
"" ""
end end
chathistory = vectorOfDictToText(a.chathistory) # chathistory = vectorOfDictToText(a.chathistory)
errornote = "" errornote = ""
response = nothing # placeholder for show when error msg show up response = nothing # placeholder for show when error msg show up
for attempt in 1:10 for attempt in 1:10
usermsg = usermsg =
""" """
Your conversation with the user: $chathistory Recap: $(a.memory[:recap])
$context Your Q&A: $(a.memory[:QandA])
Your Q&A: $QandA
$errornote $errornote
""" """
@@ -996,10 +994,20 @@ function conversation(a::T, userinput::Dict) where {T<:agent}
# add usermsg to a.chathistory # add usermsg to a.chathistory
addNewMessage(a, "user", userinput[:text]) addNewMessage(a, "user", userinput[:text])
# add user activity to events memory
push!(a.memory[:events],
eventdict(;
event_description= "the user talks to the assistant.",
timestamp= Dates.now(),
subject= "user",
action_or_dialogue= userinput[:text],
)
)
# use dummy memory to check generatechat() for halucination (checking inventory) # use dummy memory to check generatechat() for halucination (checking inventory)
for i in 1:3 for i in 1:3
actionname, result = think(a) actionname, result = think(a)
if actionname == "CHATBOX" || actionname == "PRESENTBOX" if actionname == "CHATBOX" || actionname == "PRESENTBOX" || actionname == "ENDCONVERSATION"
break break
end end
end end
@@ -1025,6 +1033,14 @@ function conversation(a::T, userinput::Dict) where {T<:agent}
addNewMessage(a, "assistant", chatresponse) addNewMessage(a, "assistant", chatresponse)
push!(a.memory[:events],
eventdict(;
event_description= "the assistant talks to the user.",
timestamp= Dates.now(),
subject= "assistant",
action_or_dialogue= chatresponse,
)
)
return chatresponse return chatresponse
end end
end end
@@ -1046,6 +1062,19 @@ julia>
# Signature # Signature
""" """
function think(a::T)::NamedTuple{(:actionname, :result), Tuple{String, String}} where {T<:agent} function think(a::T)::NamedTuple{(:actionname, :result), Tuple{String, String}} where {T<:agent}
a.memory[:recap] = generateSituationReport(a, a.text2textInstructLLM)
a.memory[:QandA] = generatequestion(a, a.text2textInstructLLM)
# after the user selected their wine. No question should be asked
# a.memory[:QandA] =
# if occursin("None", a.memory[:sitrep][:wine_selected])
# generatequestion(a, a.text2textInstructLLM)
# else
# generatequestion(a, a.text2textInstructLLM) #[PENDING] to be removed. this is just for explor
# "None"
# end
thoughtDict = decisionMaker(a) thoughtDict = decisionMaker(a)
actionname = thoughtDict[:action_name] actionname = thoughtDict[:action_name]
@@ -1058,10 +1087,13 @@ function think(a::T)::NamedTuple{(:actionname, :result), Tuple{String, String}}
elseif actionname == "CHECKINVENTORY" elseif actionname == "CHECKINVENTORY"
checkinventory(a, actioninput) checkinventory(a, actioninput)
elseif actionname == "PRESENTBOX" elseif actionname == "PRESENTBOX"
x = "Present the following wines to the user: $actioninput" x = """
1) Present $actioninput for the user to choose: "
2) compare each option against the others and explain why each one is a suitable match for the user's specific needs.
"""
(result=x, errormsg=nothing, success=true) (result=x, errormsg=nothing, success=true)
elseif actionname == "ENDCONVERSATION" elseif actionname == "ENDCONVERSATION"
x = "Thank the user and conclude the conversation by saying goodbye and inviting them to return next time." x = "Conclude the conversation, thanks the user then goodbye and inviting them to return next time."
(result=x, errormsg=nothing, success=true) (result=x, errormsg=nothing, success=true)
else else
error("undefined LLM function. Requesting $actionname") error("undefined LLM function. Requesting $actionname")
@@ -1079,7 +1111,7 @@ function think(a::T)::NamedTuple{(:actionname, :result), Tuple{String, String}}
if actionname == "CHATBOX" if actionname == "CHATBOX"
a.memory[:CHATBOX] = result a.memory[:CHATBOX] = result
elseif actionname == "CHECKINVENTORY" elseif actionname == "CHECKINVENTORY"
# x = "You have searched the inventory, this is what you found: $result" x = "I have searched the inventory, this is what I found: $result"
x = result x = result
push!(a.memory[:shortmem], Dict(Symbol(actionname)=> x)) push!(a.memory[:shortmem], Dict(Symbol(actionname)=> x))
elseif actionname == "PRESENTBOX" # tell the generatechat() elseif actionname == "PRESENTBOX" # tell the generatechat()
@@ -1236,7 +1268,7 @@ julia>
# TODO # TODO
- [] update docs - [] update docs
- [x] implement the function - []
# Signature # Signature
""" """
@@ -1244,9 +1276,10 @@ function generatechat(memory::Dict, chathistory::Vector, text2textInstructLLM::F
systemmsg = systemmsg =
""" """
You are a helpful assistant acting as a polite, website-based sommelier for an online wine store. You are a helpful assistant acting as a polite, website-based sommelier for an online wine store.
You are currently talking with the user. Your goal is: Recommend the best wines from your inventory that align with the user's preferences.
Your goal is to recommend the best wines from your inventory that match the user's preferences.
You don't need to do any sale process. Your responsibility includes:
1) Convey your thoughts to the user
At each round of conversation, you will be given the current situation: At each round of conversation, you will be given the current situation:
Your conversation with the user: ... Your conversation with the user: ...
@@ -1254,14 +1287,14 @@ function generatechat(memory::Dict, chathistory::Vector, text2textInstructLLM::F
Context: ... Context: ...
You MUST follow the following guidelines: You MUST follow the following guidelines:
- Do not offer additional services I didn't thought. - Do not offer additional services you didn't thought.
You should follow the following guidelines: You should follow the following guidelines:
- When recommending wines, compare each option against the others and explain why each one is a suitable match for the user's specific needs. - Focus on the latest conversation.
You should then respond to the user with: You should then respond to the user with:
- chat: Based on your thoughts, what will you say to the user? 1) chat: Given the current situation, what will you say to the user?
- mentioning_wine: Are you mentioning specific wine name to the user? Can be "Yes" or "No" 2) mentioning_wine: Are you mentioning specific wine name to the user? Can be "Yes" or "No"
You should only respond in format as described below: You should only respond in format as described below:
chat: ... chat: ...
@@ -1344,7 +1377,7 @@ function generatechat(memory::Dict, chathistory::Vector, text2textInstructLLM::F
delete!(responsedict, :mentioning_wine) delete!(responsedict, :mentioning_wine)
result = responsedict[:chat] result = responsedict[:chat]
return result return result
catch e catch e
io = IOBuffer() io = IOBuffer()
showerror(io, e) showerror(io, e)
@@ -1364,28 +1397,33 @@ function generatequestion(a, text2textInstructLLM::Function)::String
systemmsg = systemmsg =
""" """
You are a helpful assistant acting as a polite, website-based sommelier for an online wine store. You are a helpful assistant acting as a polite, website-based sommelier for an online wine store.
Your task is to self questioning about the current situation. Your goal is: Help the user select the best wines from your inventory that align with the user's preferences.
You don't need to do any sale process.
Your responsibility includes:
1) Self questioning about the current situation
2) Thanks the user when they are done choosing wines and invite them to comeback next time
Your responsibility does not include:
1) Processing sales orders or engaging in any other sales-related activities.
At each round of conversation, you will be given the current situation: At each round of conversation, you will be given the current situation:
Your conversation with the user: ... Your conversation with the user: ...
Context: ... Context: ...
You must follow the following guidelines: You must follow the following guidelines:
1) Ask at least two questions but no more than five. - Your question should be specific, self-contained and not require any additional context.
2) Your question should be specific, self-contained and not require any additional context. - Do not generate any question or comments at the end.
3) Do not generate any question or comments at the end. - Once the user has selected their wine, ask the user if they need any further assistance. Do not offer any additional services. If the user doesn't need any further assistance, say goodbye and invite them to come back next time.
4) Once the user has selected their wine, congratulate them on their choice. If they don't require any further assistance, politely the conversation without offering additional services.
You should follow the following guidelines: You should follow the following guidelines:
- Focus on the latest conversation.
- Do not ask the user about wine's flavor e.g. floral, citrusy, nutty or some thing similar as these terms cannot be used to search the database. - Do not ask the user about wine's flavor e.g. floral, citrusy, nutty or some thing similar as these terms cannot be used to search the database.
- All wines in your inventory are always in stock. - All wines in your inventory are always in stock.
You should then respond to the user with: You should then respond to the user with:
- Reasoning: State your detailed reasoning of the current situation 1) Reasoning: State your detailed reasoning of the current situation
- Q: Based on the current situation, ask yourself what you need to do in order to help the user 2) Q: Based on the current situation, ask yourself at least two, but no more than five, questions about what you need to do to achieve the goal.
- A: Based on the current situation, answer to yourself the best you can 3) A: Based on the current situation, answer to yourself the best you can
You must only respond in format as described below: You must only respond in format as described below:
Reasoning: ... Reasoning: ...
@@ -1414,6 +1452,7 @@ function generatequestion(a, text2textInstructLLM::Function)::String
usermsg = usermsg =
""" """
Your conversation with the user: $chathistory Your conversation with the user: $chathistory
Recap: $(a.memory[:recap])
$context $context
$errornote $errornote
""" """
@@ -1434,9 +1473,10 @@ function generatequestion(a, text2textInstructLLM::Function)::String
try try
response = text2textInstructLLM(prompt) response = text2textInstructLLM(prompt)
q_number = count("Q ", response) q_number = count("Q ", response)
if q_number < 2 if q_number < 1
error("too few questions only $q_number questions are generated ", @__FILE__, " ", @__LINE__) error("too few questions only $q_number questions are generated ", @__FILE__, " ", @__LINE__)
end end
response = string(split(response, "Please")[1]) # LLM usually add comments which is no need.
println("--> generatequestion ", @__FILE__, " ", @__LINE__) println("--> generatequestion ", @__FILE__, " ", @__LINE__)
pprintln(response) pprintln(response)
return response return response
@@ -1454,6 +1494,106 @@ function generatequestion(a, text2textInstructLLM::Function)::String
end end
function generateSituationReport(a, text2textInstructLLM::Function)::Dict
# systemmsg =
# """
# You are a helpful assistant in the given timeline.
# You task is to writes a situational report on the current situation.
# At each round of conversation, you will be given the current situation:
# Timeline: ...
# Context: ...
# You should then respond to the user with:
# 1) report: State your detailed situational report on the current situation.
# 2) wine_selected: Indicates whether the user selected wine. It can be the name of the selected wine or "None"
# You must only respond in format as described below:
# report: ...
# wine_selected: ...
# Let's begin!
# """
systemmsg =
"""
You are the assistant being in the given events.
Your task is to writes a summary of each event.
At each round of conversation, you will be given the situation:
Events timeline: ...
Context: ...
You should then respond to the user with:
event: a detailed summary of each event without exaggerated details.
You must only respond in format as described below:
event 1: ...
event 2: ...
...
Here are some examples:
event 1: The user ask me about where to buy a toy.
event 2: I told the user to go to the store at 2nd floor.
Let's begin!
"""
timeline = ""
for (i, event) in enumerate(a.memory[:events])
if event[:outcome] === nothing
timeline *= "$i) $(event[:subject])> $(event[:action_or_dialogue])\n"
else
timeline *= "$i) $(event[:subject])> $(event[:action_or_dialogue]) $(event[:outcome])\n"
end
end
errornote = ""
response = nothing # store for show when error msg show up
for attempt in 1:10
usermsg =
"""
Events timeline: $timeline
$errornote
"""
_prompt =
[
Dict(:name=> "system", :text=> systemmsg),
Dict(:name=> "user", :text=> usermsg)
]
# put in model format
prompt = GeneralUtils.formatLLMtext(_prompt, "llama3instruct")
prompt *=
"""
<|start_header_id|>assistant<|end_header_id|>
"""
try
response = text2textInstructLLM(prompt)
# responsedict = GeneralUtils.textToDict(response,
# ["summary", "presented", "selected"],
# rightmarker=":", symbolkey=true)
# println("--> generateSituationReport ", @__FILE__, " ", @__LINE__)
pprintln(response)
return Dict(:recap=>response)
catch e
io = IOBuffer()
showerror(io, e)
errorMsg = String(take!(io))
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
println("")
println("Attempt $attempt. Error occurred: $errorMsg\n$st")
println("")
end
end
error("generateSituationReport failed to generate a thought ", response)
end
# """ # """
@@ -1636,8 +1776,6 @@ end

View File

@@ -3,7 +3,7 @@ module llmfunction
export virtualWineUserChatbox, jsoncorrection, checkinventory, # recommendbox, export virtualWineUserChatbox, jsoncorrection, checkinventory, # recommendbox,
virtualWineUserRecommendbox, userChatbox, userRecommendbox virtualWineUserRecommendbox, userChatbox, userRecommendbox
using HTTP, JSON3, URIs, Random, PrettyPrinting, UUIDs using HTTP, JSON3, URIs, Random, PrettyPrinting, UUIDs, Dates
using GeneralUtils, SQLLLM using GeneralUtils, SQLLLM
using ..type, ..util using ..type, ..util
@@ -289,13 +289,24 @@ julia> result = checkinventory(agent, input)
""" """
function checkinventory(a::T1, input::T2 function checkinventory(a::T1, input::T2
)::NamedTuple{(:result, :success, :errormsg), Tuple{String, Bool, Union{String, Nothing}}} where {T1<:agent, T2<:AbstractString} )::NamedTuple{(:result, :success, :errormsg), Tuple{String, Bool, Union{String, Nothing}}} where {T1<:agent, T2<:AbstractString}
println("--> checkinventory input: $input ", @__FILE__, " ", @__LINE__) println("--> checkinventory order: $input ", @__FILE__, " ", @__LINE__)
wineattributes_1 = extractWineAttributes_1(a, input) wineattributes_1 = extractWineAttributes_1(a, input)
wineattributes_2 = extractWineAttributes_2(a, input) wineattributes_2 = extractWineAttributes_2(a, input)
inventoryquery = "$wineattributes_1, $wineattributes_2" inventoryquery = "$wineattributes_1, $wineattributes_2"
println("--> checkinventory: $inventoryquery ", @__FILE__, " ", @__LINE__) println("--> checkinventory input: $inventoryquery ", @__FILE__, " ", @__LINE__)
result = SQLLLM.query(inventoryquery, a.executeSQL, a.text2textInstructLLM) result = SQLLLM.query(inventoryquery, a.executeSQL, a.text2textInstructLLM)
push!(a.memory[:events],
eventdict(;
event_description= "the assistant searched the database.",
timestamp= Dates.now(),
subject= "assistant",
action_or_dialogue= "I searched the database with this query: $inventoryquery",
outcome= "This is what I found in the database, $result"
)
)
return (result=result, success=true, errormsg=nothing) return (result=result, success=true, errormsg=nothing)
end end
@@ -338,16 +349,16 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
3) Do not generate other comments. 3) Do not generate other comments.
You should then respond to the user with the following points: You should then respond to the user with the following points:
- reasoning: State your understanding of the current situation - reasoning: state your understanding of the current situation
- wine_type: Can be one of: "red", "white", "sparkling", "rose", "dessert" or "fortified" - wine_type: can be one of: "red", "white", "sparkling", "rose", "dessert" or "fortified"
- price: Must be an integer representing the cost of the wine. - price: must be an integer representing the cost of the wine
- occasion: ... - occasion: ...
- food_to_be_paired_with_wine: food that the user will be served with wine - food_to_be_paired_with_wine: food that the user will be served with the wine
- country: wine's country of origin - region: a region in a country where the wine is produced, such as Burgundy, Napa Valley, etc
- region: wine's region of origin such as Burgundy, Napa Valley - country: a country where the wine is produced
- grape variety: a single name of grape used to make wine. - grape_variety: the name of the primary grape used to make the wine
- flavors: Names of items that the wine tastes like. - flavors: names of items that the wine tastes like, such as citrus, lime, etc
- aromas: wine's aroma - aromas: the wine's aromas, such as fruity, floral, etc
You should only respond in the form as described below: You should only respond in the form as described below:
reasoning: ... reasoning: ...
@@ -355,8 +366,8 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
price: ... price: ...
occasion: ... occasion: ...
food_to_be_paired_with_wine: ... food_to_be_paired_with_wine: ...
country: ...
region: ... region: ...
country: ...
grape_variety: ... grape_variety: ...
flavors: ... flavors: ...
aromas: ... aromas: ...
@@ -364,7 +375,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
Let's begin! Let's begin!
""" """
attributes = ["reasoning", "wine_type", "price", "occasion", "food_to_be_paired_with_wine", "country", "region", "grape_variety", "flavors", "aromas"] attributes = ["reasoning", "wine_type", "price", "occasion", "food_to_be_paired_with_wine", "region", "country", "grape_variety", "flavors", "aromas"]
errornote = "" errornote = ""
maxattempt = 5 maxattempt = 5
for attempt in 1:maxattempt for attempt in 1:maxattempt
@@ -427,6 +438,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
# check if grape_variety is mentioned in the input # check if grape_variety is mentioned in the input
if !occursin("NA", responsedict[:grape_variety]) && !occursin(responsedict[:grape_variety], input) if !occursin("NA", responsedict[:grape_variety]) && !occursin(responsedict[:grape_variety], input)
if attempt < maxattempt if attempt < maxattempt
errornote = "You are halucinating, $(responsedict[:grape_variety]) is not mentioned in the input"
error("$(responsedict[:grape_variety]) is not mentioned in the input") error("$(responsedict[:grape_variety]) is not mentioned in the input")
else else
responsedict[:grape_variety] = "NA" responsedict[:grape_variety] = "NA"
@@ -438,6 +450,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
delete!(responsedict, :tasting_notes) delete!(responsedict, :tasting_notes)
delete!(responsedict, :flavors) delete!(responsedict, :flavors)
delete!(responsedict, :aromas) delete!(responsedict, :aromas)
delete!(responsedict, :price)
# remove (some text) # remove (some text)
for (k, v) in responsedict for (k, v) in responsedict
@@ -527,14 +540,10 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
You should then respond to the user with the following points: You should then respond to the user with the following points:
- reasoning: State your understanding of the current situation - reasoning: State your understanding of the current situation
- sweetness: S where S are integers represent the range of sweetness levels - sweetness: ( S ), where ( S ) represents integers indicating the range of sweetness levels. Example: 1-2
Example: 1-2 - acidity: ( A ), where ( A ) represents integers indicating the range of acidity level. Example: 3-5
- acidity: D where D are integers represent the range of acidity level - tannin: ( T ), where ( T ) represents integers indicating the range of tannin level. Example: 1-3
Example: 3-5 - intensity: ( I ), where ( I ) represents integers indicating the range of intensity level. Example: 2-4
- tannin: T where T are integers represent the range of tannin level
Example: 1-3
- intensity: I where I are integers represent the range of intensity level
Example: 2-4
- notes: Anything you want to add - notes: Anything you want to add
You should only respond in the form as described below: You should only respond in the form as described below:

View File

@@ -131,7 +131,8 @@ function sommelier(
memory = Dict{Symbol, Any}( memory = Dict{Symbol, Any}(
:chatbox=> "", :chatbox=> "",
:shortmem=> Vector{Dict{Symbol, String}}() :shortmem=> Vector{Dict{Symbol, String}}(),
:events=> Vector{Dict{Symbol, Any}}()
) )
newAgent = sommelier( newAgent = sommelier(

View File

@@ -1,6 +1,6 @@
module util module util
export clearhistory, addNewMessage, vectorOfDictToText export clearhistory, addNewMessage, vectorOfDictToText, eventdict
using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3 using UUIDs, Dates, DataStructures, HTTP, MQTTClient, JSON3
using GeneralUtils using GeneralUtils
@@ -153,7 +153,29 @@ function vectorOfDictToText(vecd::Vector; withkey=true)
end end
function eventdict(;
event_description::Union{String, Nothing}=nothing,
timestamp::Union{DateTime, Nothing}=nothing,
subject::Union{String, Nothing}=nothing,
action_or_dialogue::Union{String, Nothing}=nothing,
location::Union{String, Nothing}=nothing,
equipment_used::Union{String, Nothing}=nothing,
material_used::Union{String, Nothing}=nothing,
outcome::Union{String, Nothing}=nothing,
note::Union{String, Nothing}=nothing,
)
return Dict{Symbol, Any}(
:event_description=> event_description,
:timestamp=> timestamp,
:subject=> subject,
:action_or_dialogue=> action_or_dialogue,
:location=> location,
:equipment_used=> equipment_used,
:material_used=> material_used,
:outcome=> outcome,
:note=> note,
)
end

View File

@@ -88,9 +88,9 @@ end
main() main()
""" """
I'm joining a graduation party this evening. I have unlimited budget but I'm ok with wine in all price range. I want a bottle of dry red wine. I'm joining a graduation party this evening. I have unlimited budget and I'm ok with wines in all price range. I want a bottle of full bodied, dry white wine.
Well, it is a small casual party with close friends and no food serving. Well, it is a small casual party with close friends and no food serving.
I'm open to suggestion since I have no specific idea about wine but I like full bodied wine from France. I'm open to suggestion since I have no specific idea about wine.
""" """