update
This commit is contained in:
@@ -200,9 +200,8 @@ function decisionMaker(a::T; recent::Integer=10)::Dict{Symbol,Any} where {T<:age
|
|||||||
2) Plan: Based on the current situation, state a complete action plan to complete the task. Be specific.
|
2) Plan: Based on the current situation, state a complete action plan to complete the task. Be specific.
|
||||||
3) Action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the following function names:
|
3) Action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the following function names:
|
||||||
- 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. The input is your intentions for the dialogue. Be specific.
|
||||||
- CHECKINVENTORY which you can use to check info about wine you want in your inventory. The input is a search term in verbal English.
|
- CHECKINVENTORY which you can use to check info about wine you want in your inventory. The input is a search term is verbal english and it should includes - winery, wine name, vintage, region, country, wine type, grape varietal, tasting notes, wine price, occasion, food to be paired with wine, intensity, tannin, sweetness, acidity.
|
||||||
Bad query example 1: red wine that pair well with spicy food.
|
Bad query example: red wine that pair well with spicy food.
|
||||||
Bad query example 2: white wine that goes well with party food.
|
|
||||||
|
|
||||||
- ENDCONVERSATION which you can use when the user has finished their conversation with you, so that you can properly end the conversation. Input is "NA".
|
- ENDCONVERSATION which you can use when the user has finished their conversation with you, so that you can properly end the conversation. Input is "NA".
|
||||||
4) Action_input: input of the action
|
4) Action_input: input of the action
|
||||||
@@ -264,6 +263,10 @@ function decisionMaker(a::T; recent::Integer=10)::Dict{Symbol,Any} where {T<:age
|
|||||||
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
|
||||||
|
if attempt > 1
|
||||||
|
println("\nYiemAgent decisionMaker() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
end
|
||||||
|
|
||||||
QandA = generatequestion(a, a.func[:text2textInstructLLM]; recent=3)
|
QandA = generatequestion(a, a.func[:text2textInstructLLM]; recent=3)
|
||||||
|
|
||||||
usermsg =
|
usermsg =
|
||||||
@@ -298,17 +301,22 @@ function decisionMaker(a::T; recent::Integer=10)::Dict{Symbol,Any} where {T<:age
|
|||||||
end
|
end
|
||||||
if count > 1
|
if count > 1
|
||||||
errornote = "You must use only one function"
|
errornote = "You must use only one function"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
# check whether response has all header
|
# check whether response has all header
|
||||||
detected_kw = GeneralUtils.detect_keyword(header, response)
|
detected_kw = GeneralUtils.detect_keyword(header, response)
|
||||||
|
kwvalue = [i for i in values(detected_kw)]
|
||||||
|
zeroind = findall(x -> x == 0, kwvalue)
|
||||||
|
missingkeys = [header[i] for i in zeroind]
|
||||||
if 0 ∈ values(detected_kw)
|
if 0 ∈ values(detected_kw)
|
||||||
errornote = "\nYiemAgent decisionMaker() response does not have all header"
|
errornote = "$missingkeys are missing from your previous response"
|
||||||
|
println("\nYiemAgent decisionMaker() $errornote:\n $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
elseif sum(values(detected_kw)) > length(header)
|
elseif sum(values(detected_kw)) > length(header)
|
||||||
errornote = "\nYiemAgent decisionMaker() response has duplicated header"
|
errornote = "Your response has duplicated points"
|
||||||
|
println("\nYiemAgent decisionMaker() $errornote: $response ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -317,7 +325,7 @@ function decisionMaker(a::T; recent::Integer=10)::Dict{Symbol,Any} where {T<:age
|
|||||||
|
|
||||||
if responsedict[:action_name] ∉ ["CHATBOX", "CHECKINVENTORY", "ENDCONVERSATION"]
|
if responsedict[:action_name] ∉ ["CHATBOX", "CHECKINVENTORY", "ENDCONVERSATION"]
|
||||||
errornote = "You must use the given functions"
|
errornote = "You must use the given functions"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -325,7 +333,7 @@ function decisionMaker(a::T; recent::Integer=10)::Dict{Symbol,Any} where {T<:age
|
|||||||
for i ∈ Symbol.(dictkey)
|
for i ∈ Symbol.(dictkey)
|
||||||
if length(responsedict[i]) == 0
|
if length(responsedict[i]) == 0
|
||||||
errornote = "$i is empty"
|
errornote = "$i is empty"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
checkFlag = true
|
checkFlag = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -338,7 +346,7 @@ function decisionMaker(a::T; recent::Integer=10)::Dict{Symbol,Any} where {T<:age
|
|||||||
matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i)
|
matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i)
|
||||||
if length(matchkeys) > 1
|
if length(matchkeys) > 1
|
||||||
errornote = "DecisionMaker has more than one key per categories"
|
errornote = "DecisionMaker has more than one key per categories"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
checkFlag = true
|
checkFlag = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -372,7 +380,7 @@ function decisionMaker(a::T; recent::Integer=10)::Dict{Symbol,Any} where {T<:age
|
|||||||
isWineInEvent == false
|
isWineInEvent == false
|
||||||
|
|
||||||
errornote = "Note: Before recommending a wine, ensure it's in your inventory. Check your stock first."
|
errornote = "Note: Before recommending a wine, ensure it's in your inventory. Check your stock first."
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nYiemAgent decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1116,14 +1124,14 @@ function generatechat(a::sommelier, thoughtDict)
|
|||||||
You should only respond in format as described below:
|
You should only respond in format as described below:
|
||||||
Dialogue: ...
|
Dialogue: ...
|
||||||
Here are some examples:
|
Here are some examples:
|
||||||
Your ongoing conversation with the user: "user> hello, I need a new car\n"
|
|
||||||
Additional info: "Car previously found in your inventory: 1) Toyota Camry 2020 2) Honda Civic 2021 3) Ford Mustang 2022"
|
Additional info: "Car previously found in your inventory: 1) Toyota Camry 2020 2) Honda Civic 2021 3) Ford Mustang 2022"
|
||||||
Your thoughts: "I should recommend the car we have to the user."
|
Your thoughts: "I should recommend the car we have found in our inventory to the user."
|
||||||
|
Your ongoing conversation with the user: "user> hello, I need a new car\n"
|
||||||
Dialogue: "We have a variety of cars available, including the Toyota Camry 2020, the Honda Civic 2021, and the Ford Mustang 2022. Which one would you like to see?"
|
Dialogue: "We have a variety of cars available, including the Toyota Camry 2020, the Honda Civic 2021, and the Ford Mustang 2022. Which one would you like to see?"
|
||||||
|
|
||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
#[WORKING] remove "chat"
|
|
||||||
header = ["Dialogue:"]
|
header = ["Dialogue:"]
|
||||||
dictkey = ["dialogue"]
|
dictkey = ["dialogue"]
|
||||||
|
|
||||||
@@ -1145,6 +1153,7 @@ function generatechat(a::sommelier, thoughtDict)
|
|||||||
for attempt in 1:10
|
for attempt in 1:10
|
||||||
|
|
||||||
if attempt > 1 # use to prevent LLM generate the same respond over and over
|
if attempt > 1 # use to prevent LLM generate the same respond over and over
|
||||||
|
println("\nYiemAgent generatchat() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
yourthought1 = paraphrase(a.func[:text2textInstructLLM], yourthought)
|
yourthought1 = paraphrase(a.func[:text2textInstructLLM], yourthought)
|
||||||
else
|
else
|
||||||
yourthought1 = yourthought
|
yourthought1 = yourthought
|
||||||
@@ -1166,12 +1175,15 @@ function generatechat(a::sommelier, thoughtDict)
|
|||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="qwen")
|
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="qwen")
|
||||||
|
|
||||||
response = a.func[:text2textInstructLLM](prompt)
|
response = a.func[:text2textInstructLLM](prompt)
|
||||||
|
|
||||||
# sometime the model response like this "here's how I would respond: ..."
|
# sometime the model response like this "here's how I would respond: ..."
|
||||||
if occursin("respond:", response)
|
if occursin("respond:", response)
|
||||||
errornote = "You don't need to intro your response"
|
errornote = "You don't need to put 'response:' in your response"
|
||||||
error("generatechat() response contain : ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("ERROR YiemAgent generatechat() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
elseif occursin("Your thoughts:", response) || occursin("your thoughts:", response)
|
||||||
|
errornote = "You don't need to put 'Your thoughts:' in your response"
|
||||||
|
println("ERROR YiemAgent generatechat() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
end
|
end
|
||||||
response = GeneralUtils.remove_french_accents(response)
|
response = GeneralUtils.remove_french_accents(response)
|
||||||
response = replace(response, '*'=>"")
|
response = replace(response, '*'=>"")
|
||||||
@@ -1651,7 +1663,7 @@ function generatequestion(a, text2textInstructLLM::Function;
|
|||||||
# check whether response has all header
|
# check whether response has all header
|
||||||
detected_kw = GeneralUtils.detect_keyword(header, response)
|
detected_kw = GeneralUtils.detect_keyword(header, response)
|
||||||
if 0 ∈ values(detected_kw)
|
if 0 ∈ values(detected_kw)
|
||||||
errornote = "\nYiemAgent generatequestion() response does not have all header"
|
errornote = "\nresponse does not have all header"
|
||||||
continue
|
continue
|
||||||
elseif sum(values(detected_kw)) > length(header)
|
elseif sum(values(detected_kw)) > length(header)
|
||||||
errornote = "\nYiemAgent generatequestion() response has duplicated header"
|
errornote = "\nYiemAgent generatequestion() response has duplicated header"
|
||||||
@@ -1714,6 +1726,10 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent::
|
|||||||
errornote = ""
|
errornote = ""
|
||||||
response = nothing # store for show when error msg show up
|
response = nothing # store for show when error msg show up
|
||||||
for attempt in 1:10
|
for attempt in 1:10
|
||||||
|
if attempt > 1 # use to prevent LLM generate the same respond over and over
|
||||||
|
println("\nYiemAgent generateSituationReport() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
end
|
||||||
|
|
||||||
usermsg = """
|
usermsg = """
|
||||||
Total events: $(length(events))
|
Total events: $(length(events))
|
||||||
Events timeline: $timeline
|
Events timeline: $timeline
|
||||||
@@ -1738,11 +1754,11 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent::
|
|||||||
missingkeys = [header[i] for i in zeroind]
|
missingkeys = [header[i] for i in zeroind]
|
||||||
if 0 ∈ values(detected_kw)
|
if 0 ∈ values(detected_kw)
|
||||||
errornote = "$missingkeys are missing in your previous attempt"
|
errornote = "$missingkeys are missing in your previous attempt"
|
||||||
println("\nYiemAgent generateSituationReport() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nERROR YiemAgent generateSituationReport() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
elseif sum(values(detected_kw)) > length(header)
|
elseif sum(values(detected_kw)) > length(header)
|
||||||
errornote = "Your previous response has duplicated events"
|
errornote = "Your previous response has duplicated events"
|
||||||
println("\nYiemAgent generateSituationReport() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("\nERROR YiemAgent generateSituationReport() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1757,8 +1773,8 @@ function generateSituationReport(a, text2textInstructLLM::Function; skiprecent::
|
|||||||
error("generateSituationReport failed to generate a response ", response)
|
error("generateSituationReport failed to generate a response ", response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function detectWineryName(a, text)
|
function detectWineryName(a, text)
|
||||||
|
|
||||||
systemmsg =
|
systemmsg =
|
||||||
"""
|
"""
|
||||||
You are a sommelier of a wine store.
|
You are a sommelier of a wine store.
|
||||||
@@ -1791,7 +1807,6 @@ function detectWineryName(a, text)
|
|||||||
usermsg = """
|
usermsg = """
|
||||||
Text: $text
|
Text: $text
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_prompt =
|
_prompt =
|
||||||
[
|
[
|
||||||
Dict(:name => "system", :text => systemmsg),
|
Dict(:name => "system", :text => systemmsg),
|
||||||
|
|||||||
@@ -389,6 +389,10 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
for attempt in 1:10
|
for attempt in 1:10
|
||||||
#[WORKING] I should add generatequestion()
|
#[WORKING] I should add generatequestion()
|
||||||
|
|
||||||
|
if attempt > 1
|
||||||
|
println("\nYiemAgent extractWineAttributes_1() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
end
|
||||||
|
|
||||||
usermsg =
|
usermsg =
|
||||||
"""
|
"""
|
||||||
User's query: $input
|
User's query: $input
|
||||||
@@ -449,7 +453,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
# check whether wine_price is in ranged number
|
# check whether wine_price is in ranged number
|
||||||
if !occursin('-', responsedict[:wine_price])
|
if !occursin('-', responsedict[:wine_price])
|
||||||
errornote = "wine_price must be a range number"
|
errornote = "wine_price must be a range number"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("ERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
checkFlag = true
|
checkFlag = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -464,7 +468,7 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
# price range like 100-100 is not good
|
# price range like 100-100 is not good
|
||||||
if minprice == maxprice
|
if minprice == maxprice
|
||||||
errornote = "wine_price with minimum equals to maximum is not valid"
|
errornote = "wine_price with minimum equals to maximum is not valid"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
println("ERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
checkFlag = true
|
checkFlag = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -480,14 +484,14 @@ function extractWineAttributes_1(a::T1, input::T2)::String where {T1<:agent, T2<
|
|||||||
content = [content]
|
content = [content]
|
||||||
end
|
end
|
||||||
|
|
||||||
for x in content #check whether price are mentioned in the input
|
# for x in content #check whether price are mentioned in the input
|
||||||
if !occursin("NA", responsedict[j]) && !occursin(x, input)
|
# if !occursin("NA", responsedict[j]) && !occursin(x, input)
|
||||||
errornote = "$x is not mentioned in the user query, you must only use the info from the query."
|
# errornote = "$x is not mentioned in the user query, you must only use the info from the query."
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
# println("ERROR YiemAgent extractWineAttributes_1() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
checkFlag == true
|
# checkFlag == true
|
||||||
break
|
# break
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
18
src/util.jl
18
src/util.jl
@@ -268,7 +268,7 @@ end
|
|||||||
# 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: "{subject}> {actioninput} {outcome}\n" for each event
|
Format: "{index}) {subject}> {actioninput} {outcome}\n" for each event
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
|
|
||||||
@@ -277,24 +277,32 @@ events = [
|
|||||||
Dict(:subject => "Assistant", :actioninput => "Hi there!", :outcome => "with a smile")
|
Dict(:subject => "Assistant", :actioninput => "Hi there!", :outcome => "with a smile")
|
||||||
]
|
]
|
||||||
timeline = createTimeline(events)
|
timeline = createTimeline(events)
|
||||||
# User> Hello
|
# 1) User> Hello
|
||||||
# Assistant> Hi there! with a smile
|
# 2) Assistant> Hi there! with a smile
|
||||||
|
|
||||||
"""
|
"""
|
||||||
function createTimeline(events::T1) where {T1<:AbstractVector}
|
function createTimeline(events::T1) where {T1<:AbstractVector}
|
||||||
|
# Initialize empty timeline string
|
||||||
timeline = ""
|
timeline = ""
|
||||||
|
|
||||||
|
# Iterate through events with index
|
||||||
for (i, event) in enumerate(events)
|
for (i, event) in enumerate(events)
|
||||||
|
# If no outcome exists, format without outcome
|
||||||
if event[:outcome] === nothing
|
if event[:outcome] === nothing
|
||||||
timeline *= "$i) $(event[:subject])> $(event[:actioninput])\n"
|
timeline *= "Event_$i) $(event[:subject])> $(event[:actioninput])\n"
|
||||||
|
# If outcome exists, include it in formatting
|
||||||
else
|
else
|
||||||
timeline *= "$i) $(event[:subject])> $(event[:actioninput]) $(event[:outcome])\n"
|
timeline *= "Event_$i) $(event[:subject])> $(event[:actioninput]) $(event[:outcome])\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return formatted timeline string
|
||||||
return timeline
|
return timeline
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# """ Convert a single chat dictionary into LLM model instruct format.
|
# """ Convert a single chat dictionary into LLM model instruct format.
|
||||||
|
|
||||||
# # Llama 3 instruct format example
|
# # Llama 3 instruct format example
|
||||||
|
|||||||
@@ -95,10 +95,7 @@ function getEmbedding(text::T) where {T<:AbstractString}
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
#BUG it returns nothing from ollama
|
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120, maxattempt=3)
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120, maxattempt=2)
|
|
||||||
|
|
||||||
|
|
||||||
embedding = response[:response][:embeddings]
|
embedding = response[:response][:embeddings]
|
||||||
return embedding
|
return embedding
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user