v0.7.0 #25

Merged
ton merged 5 commits from v0.7.0 into main 2026-07-17 00:03:02 +00:00
3 changed files with 57 additions and 54 deletions
Showing only changes of commit b349c3a8b6 - Show all commits
+1 -1
View File
@@ -1,6 +1,6 @@
name = "YiemAgent"
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
version = "0.6.5"
version = "0.7.0"
authors = ["narawat lamaiin <narawat@outlook.com>"]
[deps]
+47 -45
View File
@@ -75,7 +75,7 @@ OrderedDict{String, Any} with 4 entries:
"""
function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
) where {T<:agent}
@info "YiemAgent decisionMaker() 1 " @__LINE__
@info "YiemAgent decisionMaker() start " @__LINE__
# lessonDict = copy(JSON.parsefile("lesson.json"))
# lesson =
@@ -110,7 +110,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
<internal_context_for_assistant>
</internal_context_for_assistant>
"""
@info "YiemAgent decisionMaker() 2 " @__LINE__
# add context to text of the latest message (in the front).
# use for loop because in openai format, each msg may contain both text and image.
for d in a.chathistory[end]["content"]
@@ -123,27 +123,27 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
response = nothing # placeholder for show when error msg show up
for attempt in 1:maxattempt
@info "YiemAgent decisionMaker() 3 " @__LINE__
msg = Dict(
"model" => "gemma-4-E4B-it-UD-Q4_K_XL",
"messages" => a.chathistory,
"temperature" => 0.7
)
@info "YiemAgent decisionMaker() 4 " @__LINE__
response = a.context.text2textInstructLLM(a.id, msg)
@info "YiemAgent decisionMaker() 5 " @__LINE__
response = GeneralUtils.clean_json_response(response)
response = GeneralUtils.remove_french_accents(response)
think, response = GeneralUtils.extractthink(response)
response = String(split(response, ", observation")[1]) # in case LLM generate observation key which it isn't supposed to
response = strip(response)
@info "YiemAgent decisionMaker() 6 " @__LINE__
# dollar sign in Julia means string interpolation
while occursin('$', response)
response = replace(response, '$' => "USD")
end
@info "YiemAgent decisionMaker() 7 " @__LINE__
responsedict = nothing
if occursin(requiredKeys[2], response)
try
@@ -157,22 +157,22 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)-> $responsedict ", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
continue
end
@info "YiemAgent decisionMaker() 8 " @__LINE__
# check whether all answer's key points are in responsedict
println("\n---")
println(responsedict)
println("---\n")
ispass, errormsg = GeneralUtils.checkAgentResponse_JSON(responsedict, requiredKeys)
@info "YiemAgent decisionMaker() 9 " @__LINE__
if !ispass
errornote = errormsg
println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)-> $responsedict ", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
continue
end
@info "YiemAgent decisionMaker() 10 " @__LINE__
if responsedict["action_input"] == "CHAT_BOX" &&
occursin("similar", responsedict["action_input"])
@info "illegal CHAT_BOX search term" @__LINE__
continue
end
@@ -184,7 +184,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
# println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
# pprintln(responsedict)
@info "YiemAgent decisionMaker() 11 " @__LINE__
@info "YiemAgent decisionMaker() end " @__LINE__
return responsedict
end
error("DecisionMaker failed to generate a thought ", response)
@@ -359,7 +359,7 @@ message => Dict(
function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Object{String, Any}},
maximumMsg=50, max_think_loop::Integer=3)
@info "YiemAgent conversation() 0 " @__LINE__
@info "YiemAgent conversation() start " @__LINE__
userinput = GeneralUtils.dictify(userinput; keytype=String, sort_order=["text"])
# find text in usermsg
@@ -375,7 +375,7 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj
clearhistory(a)
return "Okay. What shall we talk about?"
else
@info "YiemAgent conversation() 1 " @__LINE__
# add usermsg to a.chathistory but how do I handle images?
addNewMessage(a, "user", userinput; maximumMsg=maximumMsg)
@@ -384,9 +384,9 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj
while true
loopcount += 1
if loopcount > max_think_loop
@info "YiemAgent conversation() 1-1 think count $loopcount " @__LINE__
thoughtdict, result_raw = generatechat!(a)
@info "YiemAgent conversation() 1-2 think count $loopcount " @__LINE__
assistant_response = Dict{String, Any}(
"role" => "assistant",
@@ -414,15 +414,15 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj
),
]
)
@info "YiemAgent conversation() 1-3 think count $loopcount " @__LINE__
return response_to_frontend
end
@info "YiemAgent conversation() 2-3 think count $loopcount " @__LINE__
thoughtdict, result_raw = think(a)
@info "YiemAgent conversation() 2-4 think count $loopcount " @__LINE__
if thoughtdict["action_name"] ["CHAT_BOX"]
@info "YiemAgent conversation() 2-5 think count $loopcount " @__LINE__
assistant_response = Dict{String, Any}(
"role" => "assistant",
@@ -477,28 +477,28 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj
)
"""
@info "YiemAgent conversation() 2-6 think count $loopcount " @__LINE__
return response_to_frontend
else # still in action
@info "YiemAgent conversation() 2-7 think count $loopcount " @__LINE__
action_name = thoughtdict["action_name"]
action_input = thoughtdict["action_input"]
@info "YiemAgent conversation() 2-8 think count $loopcount " @__LINE__
action_call = Dict{String, Any}(
"role" => "action_call",
"content" => [Dict("type" => "text", "text" => "{action_name: $action_name, action_input: $action_input}"),]
)
@info "YiemAgent conversation() 2-9 think count $loopcount " @__LINE__
addNewMessage(a, "action_call", action_call; maximumMsg=maximumMsg)
@info "YiemAgent conversation() 2-10 think count $loopcount " @__LINE__
action_result = thoughtdict["action_result"]
actionresult = Dict{String, Any}(
"role" => "action_result",
"content" => [Dict("type" => "text", "text" => "$action_result"),]
)
@info "YiemAgent conversation() 2-11 think count $loopcount " @__LINE__
addNewMessage(a, "actionresult", actionresult; maximumMsg=maximumMsg)
@info "YiemAgent conversation() 2-12 think count $loopcount " @__LINE__
@info "YiemAgent conversation() end think count $loopcount " @__LINE__
end
end
end
@@ -518,26 +518,27 @@ julia>
"""
function think(a::T)::NamedTuple{(:thoughtdict, :result_raw), Tuple{OrderedDict, Any}} where {T<:agent}
# a.memory[:recap] = generateSituationReport(a, a.context["text"2textInstructLLM]; skiprecent=0)
@info "YiemAgent think() 1-1 " @__LINE__
@info "YiemAgent think() start " @__LINE__
thoughtdict = decisionMaker(a)
@info "YiemAgent think() 1-2 " @__LINE__
# pprintln(thoughtdict)
@info "YiemAgent think() 1 " @__LINE__
@show thoughtdict
println("---\n")
result_raw = nothing
if thoughtdict["action_name"] ["CHAT_BOX"]
@info "YiemAgent think() 2-1 " @__LINE__
thoughtdict, result_raw = generatechat!(a)
@info "YiemAgent think() 2-2 " @__LINE__
elseif thoughtdict["action_name"] == "END_CONVER_GUIDELINE"
@info "YiemAgent think() 3 " @__LINE__
thoughtdict, result_raw = end_conversation_guideline!(a, thoughtdict)
elseif thoughtdict["action_name"] ["WINE_PRESENTATION_GUIDELINE"]
@info "YiemAgent think() 4 " @__LINE__
thoughtdict, result_raw = wine_presentation_guideline!(a, thoughtdict)
elseif thoughtdict["action_name"] == "SEARCH_WINE_DATABASE"
@info "YiemAgent think() 5 " @__LINE__
thoughtdict, result_raw = search_wine_database!(a, thoughtdict; useSQLLLM=false)
if result_raw !== nothing && result_raw isa Vector
if haskey(a.memory["shortmem"], "items_info")
@@ -548,12 +549,13 @@ function think(a::T)::NamedTuple{(:thoughtdict, :result_raw), Tuple{OrderedDict,
end
else
@info "YiemAgent think() 6 " @__LINE__
error("condition is not defined ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
end
println("\n")
@info "YiemAgent think() end " @__LINE__
@show thoughtdict
@info "YiemAgent think() 7 " @__LINE__
println("---\n")
return (thoughtdict=thoughtdict, result_raw=result_raw)
end
@@ -630,7 +632,7 @@ end
#PENDING
function generatechat!(a::T; maxattempt::Integer=10
)::NamedTuple{(:thoughtdict, :result_raw), Tuple{OrderedDict, Any}} where {T<:agent}
@info "YiemAgent generatechat!() start " @__LINE__
# lessonDict = copy(JSON.parsefile("lesson.json"))
# lesson =
@@ -713,7 +715,7 @@ function generatechat!(a::T; maxattempt::Integer=10
"action_name": "...",
"action_input": "..."
"""
@info "YiemAgent generatechat!() 1 " @__LINE__
system_msg = Dict(
"role" => "system",
"content" => [
@@ -728,7 +730,7 @@ function generatechat!(a::T; maxattempt::Integer=10
errornote = "N/A"
response = nothing # placeholder for show when error msg show up
@info "YiemAgent generatechat!() 2 " @__LINE__
for attempt in 1:maxattempt
if attempt > 1
println("\nYiemAgent generatechat() attempt $attempt/$maxattempt ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
@@ -746,7 +748,7 @@ function generatechat!(a::T; maxattempt::Integer=10
think, response = GeneralUtils.extractthink(response)
response = strip(response)
@info "YiemAgent generatechat!() 3 " @__LINE__
responsedict = nothing
if occursin(requiredKeys[2], response)
try
@@ -761,7 +763,7 @@ function generatechat!(a::T; maxattempt::Integer=10
continue
end
@info "YiemAgent generatechat!() 4 " @__LINE__
# check whether all answer's key points are in responsedict
ispass, errormsg = GeneralUtils.checkAgentResponse_JSON(responsedict, requiredKeys)
if !ispass
@@ -769,7 +771,7 @@ function generatechat!(a::T; maxattempt::Integer=10
println("\nERROR YiemAgent generatechat() $errornote --(not qualify response)> $responsedict ", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
continue
end
@info "YiemAgent generatechat!() 5 " @__LINE__
# if responsedict["action_name"] ∉ ["CHAT_BOX", "SEARCH_WINE_DATABASE", "PRESENT_WINE_GUIDELINE", "END_CONVER_GUIDELINE"]
# errornote = "Your previous attempt didn't use the given functions"
# println("\nERROR YiemAgent decisionMaker() $errornote --(not qualify response)--> $(responsedict["action_name"])", @__FILE__, ":", @__LINE__, " $(Dates.now())")
@@ -779,7 +781,7 @@ function generatechat!(a::T; maxattempt::Integer=10
# println("\nYiem decisionMaker() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
# pprintln(responsedict)
responsedict["action_result"] = "Action result is the next user dialogue."
@info "YiemAgent generatechat!() 6 " @__LINE__
@info "YiemAgent generatechat!() end " @__LINE__
return (thoughtdict=responsedict, result_raw=responsedict["action_input"])
end
error("YiemAgent generatechat() failed to generate a thought ", response)
+9 -8
View File
@@ -810,7 +810,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
responsedict[k] = _v
end
println("\n--- extractWineAttributes_1-1()")
@info "YiemAgent extractWineAttributes_1() " @__LINE__
@show responsedict
@info "---\n" @__LINE__
@@ -832,9 +832,11 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
end
result = result[1:end-2] # remove the ending ", "
println("\n--- extractWineAttributes_1-2()")
@info "YiemAgent extractWineAttributes_1() " @__LINE__
@show result
@info "---\n" @__LINE__
return result
end
error("extractWineAttributes_1() failed to get a response")
@@ -987,9 +989,6 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
for attempt in 1:10
response = a.context.text2textInstructLLM(a.id, msg)
response = GeneralUtils.clean_json_response(response)
println("\n--- extractWineAttributes_2-1()")
println(response)
println("--- \n")
response = GeneralUtils.remove_french_accents(response)
think, response = GeneralUtils.extractthink(response)
@@ -1027,9 +1026,11 @@ function extractWineAttributes_2(a::T1, input::T2)::String where {T1<:agent, T2<
end
end
result = result[1:end-2] # remove the ending ", "
println("\n--- extractWineAttributes_2-2()")
println(result)
println("--- \n")
@info "YiemAgent extractWineAttributes_2() " @__LINE__
@show result
@info "---\n" @__LINE__
return result
end
error("extractWineAttributes_2() failed to get a response")