update
This commit is contained in:
@@ -97,7 +97,7 @@ julia> output_thoughtDict = Dict(
|
|||||||
|
|
||||||
# Signature
|
# Signature
|
||||||
"""
|
"""
|
||||||
function decisionMaker(a::T; recentevents::Integer=10, maxattempt=10
|
function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
|
||||||
) where {T<:agent}
|
) where {T<:agent}
|
||||||
|
|
||||||
# lessonDict = copy(JSON3.read("lesson.json"))
|
# lessonDict = copy(JSON3.read("lesson.json"))
|
||||||
@@ -133,13 +133,8 @@ function decisionMaker(a::T; recentevents::Integer=10, maxattempt=10
|
|||||||
includelatest=true)
|
includelatest=true)
|
||||||
recentchat = createChatLog(a.chathistory; index=recentchat_ind)
|
recentchat = createChatLog(a.chathistory; index=recentchat_ind)
|
||||||
# recentEventsDict = createEventsLog(recentevents; index=recent_ind)
|
# recentEventsDict = createEventsLog(recentevents; index=recent_ind)
|
||||||
|
|
||||||
#BUG timeline only cover event 1-9 out of 10 events while recentchat cover 1-9 because
|
|
||||||
# recent_ind is based on chathistory. i should ind based on events. The reason is events always
|
|
||||||
# have more than chathistory due to CHECKINVENTORY() function which store in events BUT NOT in
|
|
||||||
# chathistory
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# # recap as caching
|
# # recap as caching
|
||||||
# # query similar result from vectorDB
|
# # query similar result from vectorDB
|
||||||
# recapkeys = keys(a.memory[:recap])
|
# recapkeys = keys(a.memory[:recap])
|
||||||
@@ -215,7 +210,7 @@ function decisionMaker(a::T; recentevents::Integer=10, maxattempt=10
|
|||||||
- Vintage 0 means non-vintage.
|
- Vintage 0 means non-vintage.
|
||||||
</Store guidelines>
|
</Store guidelines>
|
||||||
At each round of conversation, you will be given the following information:
|
At each round of conversation, you will be given the following information:
|
||||||
Database search result: the result of a database search using SQL commands you have found so far
|
context: additional information about the current situation
|
||||||
|
|
||||||
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.
|
||||||
@@ -253,14 +248,14 @@ function decisionMaker(a::T; recentevents::Integer=10, maxattempt=10
|
|||||||
"""
|
"""
|
||||||
<context>
|
<context>
|
||||||
<Available tools>
|
<Available tools>
|
||||||
- CHATBOX which you can use to talk with the user. The input is your intentions for the dialogue. Be specific.
|
- CHATBOX which you can use to talk with the user. Be specific.
|
||||||
- CHECKINVENTORY allows you to check information about wines you want in your inventory's database. The input must be supported search criteria includeing: wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
|
- CHECKINVENTORY allows you to check information about wines you want in your inventory's database. The input must be supported search criteria includeing: wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
|
||||||
Example query: "Dry, full-bodied red wine from Burgundy, France or Tuscany, Italy. Merlot varietal. price 100 to 1000 USD."
|
Example query: "Dry, full-bodied red wine from Burgundy, France or Tuscany, Italy. Merlot varietal. price 100 to 1000 USD."
|
||||||
- PRESENTBOX which you can use to present wines you have found in your inventory to the user. The input are wine names that you want to present.
|
- PRESENTBOX which you can use to present wines you have found in your inventory to the user. The input are wine names that you want to present.
|
||||||
- ENDCONVERSATION which you can use to properly end the conversation with the user. Input is "NA".
|
- ENDCONVERSATION which you can use to properly end the conversation with the user. Input is a dialogue where you wrap up the conversation, thank the user, and invite them to return next time.
|
||||||
</Available tools>
|
</Available tools>
|
||||||
|
$(a.memory[:shortmem][:scratchpad])
|
||||||
Remark: $errornote
|
Remark: $errornote
|
||||||
Database search result: $database_search_result
|
|
||||||
</context>
|
</context>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -1123,22 +1118,22 @@ julia>
|
|||||||
"""
|
"""
|
||||||
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.func[:text2textInstructLLM]; skiprecent=0)
|
# a.memory[:recap] = generateSituationReport(a, a.func[:text2textInstructLLM]; skiprecent=0)
|
||||||
thoughtDict = decisionMaker(a; recentevents=5)
|
thoughtDict = decisionMaker(a)
|
||||||
|
|
||||||
actionname = thoughtDict[:action_name]
|
actionname = thoughtDict[:action_name]
|
||||||
actioninput = thoughtDict[:action_input]
|
actioninput = thoughtDict[:action_input]
|
||||||
|
|
||||||
# map action and input() to llm function
|
# map action and input() to llm function
|
||||||
response =
|
response =
|
||||||
if actionname == "CHATBOX"
|
if actionname == "CHATBOX" || actionname == "ENDCONVERSATION"
|
||||||
(result=thoughtDict[:plan], errormsg=nothing, success=true)
|
(result=thoughtDict[:plan], errormsg=nothing, success=true)
|
||||||
elseif actionname == "CHECKINVENTORY"
|
elseif actionname == "CHECKINVENTORY"
|
||||||
checkinventory(a, actioninput)
|
checkinventory(a, actioninput)
|
||||||
elseif actionname == "PRESENTBOX"
|
elseif actionname == "PRESENTBOX"
|
||||||
(result=actioninput, errormsg=nothing, success=true)
|
(result=actioninput, errormsg=nothing, success=true)
|
||||||
elseif actionname == "ENDCONVERSATION"
|
# elseif actionname == "ENDCONVERSATION"
|
||||||
x = "Conclude the conversation, thanks the user then 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=actioninput, errormsg=nothing, success=true)
|
# (result=actioninput, errormsg=nothing, success=true)
|
||||||
else
|
else
|
||||||
error("undefined LLM function. Requesting $actionname")
|
error("undefined LLM function. Requesting $actionname")
|
||||||
end
|
end
|
||||||
@@ -1166,7 +1161,7 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
# )
|
# )
|
||||||
# )
|
# )
|
||||||
# result = chatresponse
|
# result = chatresponse
|
||||||
if actionname ∈ ["CHATBOX"]
|
if actionname ∈ ["CHATBOX", "ENDCONVERSATION"]
|
||||||
push!(a.memory[:events],
|
push!(a.memory[:events],
|
||||||
eventdict(;
|
eventdict(;
|
||||||
event_description="the assistant talks to the user.",
|
event_description="the assistant talks to the user.",
|
||||||
@@ -1178,19 +1173,19 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
result = actioninput
|
result = actioninput
|
||||||
elseif actionname ∈ ["ENDCONVERSATION"]
|
# elseif actionname ∈ ["ENDCONVERSATION"]
|
||||||
chatresponse = generatechat(a, thoughtDict)
|
# chatresponse = generatechat(a, thoughtDict)
|
||||||
push!(a.memory[:events],
|
# push!(a.memory[:events],
|
||||||
eventdict(;
|
# eventdict(;
|
||||||
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",
|
||||||
thought=thoughtDict,
|
# thought=thoughtDict,
|
||||||
actionname=actionname,
|
# actionname=actionname,
|
||||||
actioninput=chatresponse,
|
# actioninput=chatresponse,
|
||||||
)
|
# )
|
||||||
)
|
# )
|
||||||
result = chatresponse
|
# result = chatresponse
|
||||||
elseif actionname ∈ ["PRESENTBOX"]
|
elseif actionname ∈ ["PRESENTBOX"]
|
||||||
chatresponse = presentbox(a, thoughtDict)
|
chatresponse = presentbox(a, thoughtDict)
|
||||||
push!(a.memory[:events],
|
push!(a.memory[:events],
|
||||||
@@ -1215,6 +1210,21 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
else
|
else
|
||||||
a.memory[:shortmem][:db_search_result] = vd
|
a.memory[:shortmem][:db_search_result] = vd
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# add to scratchpad
|
||||||
|
a.memory[:shortmem][:scratchpad] *=
|
||||||
|
"""
|
||||||
|
<database_search_result>
|
||||||
|
I searched the database with this search term: $actioninput This is what I found: $result
|
||||||
|
</database_search_result>
|
||||||
|
"""
|
||||||
|
else
|
||||||
|
a.memory[:shortmem][:scratchpad] *=
|
||||||
|
"""
|
||||||
|
<database_search_result>
|
||||||
|
I searched the database with this search term: $actioninput This is what I found: $result
|
||||||
|
</database_search_result>
|
||||||
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
push!(a.memory[:events],
|
push!(a.memory[:events],
|
||||||
@@ -1224,7 +1234,7 @@ function think(a::T)::NamedTuple{(:actionname, :result),Tuple{String,String}} wh
|
|||||||
subject= "assistant",
|
subject= "assistant",
|
||||||
thought=thoughtDict,
|
thought=thoughtDict,
|
||||||
actionname=actionname,
|
actionname=actionname,
|
||||||
actioninput= "I found something in the database using this SQL: $actioninput",
|
actioninput= "I search the database with this search term: $actioninput",
|
||||||
outcome= "This is what I found:, $result"
|
outcome= "This is what I found:, $result"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1296,7 +1306,7 @@ function presentbox(a::sommelier, thoughtDict; maxtattempt::Integer=10, recentev
|
|||||||
"""
|
"""
|
||||||
<context>
|
<context>
|
||||||
Name of the wines that needs to be introduced: $(thoughtDict[:action_input])
|
Name of the wines that needs to be introduced: $(thoughtDict[:action_input])
|
||||||
Database search result: $database_search_result
|
$(a.memory[:shortmem][:scratchpad])
|
||||||
P.S. $errornote
|
P.S. $errornote
|
||||||
</context>
|
</context>
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -500,16 +500,24 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
|
|||||||
# responsedict = GeneralUtils.textToDict(response, header;
|
# responsedict = GeneralUtils.textToDict(response, header;
|
||||||
# dictKey=dictkey, symbolkey=true)
|
# dictKey=dictkey, symbolkey=true)
|
||||||
|
|
||||||
|
removekeys = [:thought, :tasting_notes, :occasion, :food_to_be_paired_with_wine, :vintage]
|
||||||
|
for i in removekeys
|
||||||
|
delete!(responsedict, i)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
delete!(responsedict, :thought)
|
delete!(responsedict, :thought)
|
||||||
delete!(responsedict, :tasting_notes)
|
delete!(responsedict, :tasting_notes)
|
||||||
delete!(responsedict, :occasion)
|
delete!(responsedict, :occasion)
|
||||||
delete!(responsedict, :food_to_be_paired_with_wine)
|
delete!(responsedict, :food_to_be_paired_with_wine)
|
||||||
|
delete!(responsedict, :vintage)
|
||||||
|
|
||||||
# check if winery, wine_name, region, country, wine_type, grape_varietal's value are in the query because sometime AI halucinates
|
# check if winery, wine_name, region, country, wine_type, grape_varietal's value are in the query because sometime AI halucinates
|
||||||
checkFlag = false
|
checkFlag = false
|
||||||
for i in requiredKeys
|
for i in requiredKeys
|
||||||
j = Symbol(i)
|
j = Symbol(i)
|
||||||
if j ∉ [:thought, :tasting_notes, :occasion, :food_to_be_paired_with_wine]
|
if j ∉ removekeys
|
||||||
# in case j is wine_price it needs to be checked differently because its value is ranged
|
# in case j is wine_price it needs to be checked differently because its value is ranged
|
||||||
if j == :wine_price
|
if j == :wine_price
|
||||||
if responsedict[:wine_price] != "N/A"
|
if responsedict[:wine_price] != "N/A"
|
||||||
@@ -592,7 +600,7 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
|
|
||||||
conversiontable =
|
conversiontable =
|
||||||
"""
|
"""
|
||||||
<Conversion Table>
|
<conversion_table>
|
||||||
Intensity level:
|
Intensity level:
|
||||||
1 to 2: May correspond to "light-bodied" or a similar description.
|
1 to 2: May correspond to "light-bodied" or a similar description.
|
||||||
2 to 3: May correspond to "med light bodied", "medium light" or a similar description.
|
2 to 3: May correspond to "med light bodied", "medium light" or a similar description.
|
||||||
@@ -617,16 +625,16 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
3 to 4: May correspond to "medium acidity" or a similar description.
|
3 to 4: May correspond to "medium acidity" or a similar description.
|
||||||
4 to 5: May correspond to "semi high acidity" or a similar description.
|
4 to 5: May correspond to "semi high acidity" or a similar description.
|
||||||
4 to 5: May correspond to "high acidity" or a similar description.
|
4 to 5: May correspond to "high acidity" or a similar description.
|
||||||
</Conversion Table>
|
</conversion_table>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
systemmsg =
|
systemmsg =
|
||||||
"""
|
"""
|
||||||
As an helpful sommelier, your task is to fill out the user's preference form based on the corresponding words from the user's query.
|
As an helpful sommelier, your task is to fill out the user's preference form based on the corresponding words from the user's query.
|
||||||
|
|
||||||
At each round of conversation, the user will give you the current situation:
|
At each round of conversation, you will be given the following information:
|
||||||
Conversion Table: ...
|
conversion_table: a conversion table that maps descriptive words to their corresponding integer levels
|
||||||
User's query: ...
|
query: the words from the user's query that describe their preferences
|
||||||
|
|
||||||
The preference form requires the following information:
|
The preference form requires the following information:
|
||||||
sweetness, acidity, tannin, intensity
|
sweetness, acidity, tannin, intensity
|
||||||
@@ -637,86 +645,109 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
2) Use the conversion table to convert the descriptive word level of sweetness, intensity, tannin, and acidity into a corresponding integer.
|
2) Use the conversion table to convert the descriptive word level of sweetness, intensity, tannin, and acidity into a corresponding integer.
|
||||||
3) Do not generate other comments.
|
3) Do not generate other comments.
|
||||||
You should then respond to the user with:
|
You should then respond to the user with:
|
||||||
Sweetness_keyword: The exact keywords in the user's query describing the sweetness level of the wine.
|
sweetness_keyword: The exact keywords in the user's query describing the sweetness level of the wine.
|
||||||
Sweetness: ( S ), where ( S ) represents integers indicating the range of sweetness levels. Example: 1-2
|
sweetness: ( S ), where ( S ) represents integers indicating the range of sweetness levels. Example: 1-2
|
||||||
Acidity_keyword: The exact keywords in the user's query describing the acidity level of the wine.
|
acidity_keyword: The exact keywords in the user's query describing the acidity level of the wine.
|
||||||
Acidity: ( A ), where ( A ) represents integers indicating the range of acidity level. Example: 3-5
|
acidity: ( A ), where ( A ) represents integers indicating the range of acidity level. Example: 3-5
|
||||||
Tannin_keyword: The exact keywords in the user's query describing the tannin level of the wine.
|
tannin_keyword: The exact keywords in the user's query describing the tannin level of the wine.
|
||||||
Tannin: ( T ), where ( T ) represents integers indicating the range of tannin level. Example: 1-3
|
tannin: ( T ), where ( T ) represents integers indicating the range of tannin level. Example: 1-3
|
||||||
Intensity_keyword: The exact keywords in the user's query describing the intensity level of the wine.
|
intensity_keyword: The exact keywords in the user's query describing the intensity level of the wine.
|
||||||
Intensity: ( I ), where ( I ) represents integers indicating the range of intensity level. Example: 2-4
|
intensity: ( I ), where ( I ) represents integers indicating the range of intensity level. Example: 2-4
|
||||||
You should only respond in format as described below:
|
You should only respond in JSON format as described below:
|
||||||
Sweetness_keyword: ...
|
{
|
||||||
Sweetness: ...
|
"sweetness_keyword": "...",
|
||||||
Acidity_keyword: ...
|
"sweetness": "...",
|
||||||
Acidity: ...
|
"acidity_keyword": "...",
|
||||||
Tannin_keyword: ...
|
"acidity": "...",
|
||||||
Tannin: ...
|
"tannin_keyword": "...",
|
||||||
Intensity_keyword: ...
|
"tannin": "...",
|
||||||
Intensity: ...
|
"intensity_keyword": "...",
|
||||||
|
"intensity": "..."
|
||||||
|
}
|
||||||
|
|
||||||
Here are some examples:
|
Here are some examples:
|
||||||
User's query: I want a wine with a medium-bodied, low acidity, medium tannin.
|
User's query: I want a wine with a medium-bodied, low acidity, medium tannin.
|
||||||
Sweetness_keyword: N/A
|
{
|
||||||
Sweetness: N/A
|
"sweetness_keyword": "N/A",
|
||||||
Acidity_keyword: low acidity
|
"sweetness": "N/A",
|
||||||
Acidity: 1-2
|
"acidity_keyword": "low acidity",
|
||||||
Tannin_keyword: medium tannin
|
"acidity": 1-2,
|
||||||
Tannin: 3-4
|
"tannin_keyword": "medium tannin",
|
||||||
Intensity_keyword: medium-bodied
|
"tannin": 3-4,
|
||||||
Intensity: 3-4
|
"intensity_keyword": "medium-bodied",
|
||||||
|
"intensity": 3-4
|
||||||
|
}
|
||||||
|
|
||||||
User's query: German red wine, under 100, pairs with spicy food
|
User's query: German red wine, under 100, pairs with spicy food
|
||||||
Sweetness_keyword: N/A
|
{
|
||||||
Sweetness: N/A
|
"sweetness_keyword": "N/A",
|
||||||
Acidity_keyword: N/A
|
"sweetness": "N/A",
|
||||||
Acidity: N/A
|
"acidity_keyword": "N/A",
|
||||||
Tannin_keyword: N/A
|
"acidity": "N/A",
|
||||||
Tannin: N/A
|
"tannin_keyword": "N/A",
|
||||||
Intensity_keyword: N/A
|
"tannin": "N/A",
|
||||||
Intensity: N/A
|
"intensity_keyword": "N/A",
|
||||||
|
"intensity": "N/A"
|
||||||
|
}
|
||||||
|
|
||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
header = ["Sweetness_keyword:", "Sweetness:", "Acidity_keyword:", "Acidity:", "Tannin_keyword:", "Tannin:", "Intensity_keyword:", "Intensity:"]
|
requiredKeys = [:sweetness_keyword, :sweetness, :acidity_keyword, :acidity, :tannin_keyword, :tannin, :intensity_keyword, :intensity]
|
||||||
dictkey = ["sweetness_keyword", "sweetness", "acidity_keyword", "acidity", "tannin_keyword", "tannin", "intensity_keyword", "intensity"]
|
|
||||||
|
# header = ["Sweetness_keyword:", "Sweetness:", "Acidity_keyword:", "Acidity:", "Tannin_keyword:", "Tannin:", "Intensity_keyword:", "Intensity:"]
|
||||||
|
# dictkey = ["sweetness_keyword", "sweetness", "acidity_keyword", "acidity", "tannin_keyword", "tannin", "intensity_keyword", "intensity"]
|
||||||
errornote = "N/A"
|
errornote = "N/A"
|
||||||
|
|
||||||
for attempt in 1:10
|
for attempt in 1:10
|
||||||
usermsg =
|
context =
|
||||||
"""
|
"""
|
||||||
$conversiontable
|
$conversiontable
|
||||||
User's query: $input
|
<query>
|
||||||
|
$input
|
||||||
|
</query>
|
||||||
P.S. $errornote
|
P.S. $errornote
|
||||||
|
/no_think
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_prompt =
|
unformatPrompt =
|
||||||
[
|
[
|
||||||
Dict(:name=> "system", :text=> systemmsg),
|
Dict(:name=> "system", :text=> systemmsg),
|
||||||
Dict(:name=> "user", :text=> usermsg)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt, a.llmFormatName)
|
prompt = GeneralUtils.formatLLMtext(unformatPrompt, a.llmFormatName)
|
||||||
|
# add info
|
||||||
|
prompt = prompt * context
|
||||||
|
|
||||||
response = a.func[:text2textInstructLLM](prompt)
|
response = a.func[:text2textInstructLLM](prompt; modelsize="medium", senderId=a.id)
|
||||||
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
response = GeneralUtils.deFormatLLMtext(response, a.llmFormatName)
|
||||||
|
response = GeneralUtils.remove_french_accents(response)
|
||||||
think, response = GeneralUtils.extractthink(response)
|
think, response = GeneralUtils.extractthink(response)
|
||||||
|
|
||||||
# check whether response has all answer's key points
|
responsedict = nothing
|
||||||
detected_kw = GeneralUtils.detect_keyword(header, response)
|
try
|
||||||
if 0 ∈ values(detected_kw)
|
responsedict = copy(JSON3.read(response))
|
||||||
errornote = "In your previous attempt does not have all answer's key points"
|
catch
|
||||||
println("\nERROR YiemAgent extractWineAttributes_2() Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nERROR YiemAgent extractWineAttributes_2() failed to parse response: $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
|
||||||
elseif sum(values(detected_kw)) > length(header)
|
|
||||||
errornote = "In your previous attempt has duplicated answer's key points"
|
|
||||||
println("\nERROR YiemAgent extractWineAttributes_2() Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
responsedict = GeneralUtils.textToDict(response, header;
|
# check whether all answer's key points are in responsedict
|
||||||
dictKey=dictkey, symbolkey=true)
|
_responsedictKey = keys(responsedict)
|
||||||
|
responsedictKey = [i for i in _responsedictKey] # convert into a list
|
||||||
|
is_requiredKeys_in_responsedictKey = [i ∈ responsedictKey for i in requiredKeys]
|
||||||
|
|
||||||
|
if length(is_requiredKeys_in_responsedictKey) > length(requiredKeys)
|
||||||
|
errornote = "Your previous attempt has more key points than answer's required key points."
|
||||||
|
println("\nERROR YiemAgent extractWineAttributes_2() $errornote --> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue
|
||||||
|
elseif !all(is_requiredKeys_in_responsedictKey)
|
||||||
|
zeroind = findall(x -> x == 0, is_requiredKeys_in_responsedictKey)
|
||||||
|
missingkeys = [requiredKeys[i] for i in zeroind]
|
||||||
|
errornote = "$missingkeys are missing from your previous response"
|
||||||
|
println("\nERROR YiemAgent extractWineAttributes_2() $errornote --> $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
# check whether each describing keyword is in the input to prevent halucination
|
# check whether each describing keyword is in the input to prevent halucination
|
||||||
for i in ["sweetness", "acidity", "tannin", "intensity"]
|
for i in ["sweetness", "acidity", "tannin", "intensity"]
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ function sommelier(
|
|||||||
memory = Dict{Symbol, Any}(
|
memory = Dict{Symbol, Any}(
|
||||||
:shortmem=> OrderedDict{Symbol, Any}(
|
:shortmem=> OrderedDict{Symbol, Any}(
|
||||||
:db_search_result=> Any[],
|
:db_search_result=> Any[],
|
||||||
|
:scratchpad=> "", #[PENDING] should be a dict e.g. Dict(:database_search_result=>Dict(:wines=> "", :search_query=> ""))
|
||||||
),
|
),
|
||||||
:events=> Vector{Dict{Symbol, Any}}(),
|
:events=> Vector{Dict{Symbol, Any}}(),
|
||||||
:state=> Dict{Symbol, Any}(
|
:state=> Dict{Symbol, Any}(
|
||||||
|
|||||||
Reference in New Issue
Block a user