updatet #11

Merged
ton merged 1 commits from v0.6.0-output_text_image into v0.6.0 2026-07-15 04:38:18 +00:00
9 changed files with 186 additions and 60 deletions
+76 -16
View File
@@ -2,7 +2,7 @@
julia_version = "1.12.6"
manifest_format = "2.0"
project_hash = "a2c996ffe370e277cbff80af974d2701698f1b6c"
project_hash = "db8baf2dd943e4138b5952183a64465f457da356"
[[deps.Accessors]]
deps = ["CompositionsBase", "ConstructionBase", "Dates", "InverseFunctions", "MacroTools"]
@@ -38,6 +38,12 @@ version = "1.1.3"
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.2"
[[deps.ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "d57bd3762d308bded22c3b82d033bff85f6195c6"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.4.0"
[[deps.ArrowTypes]]
deps = ["Sockets", "UUIDs"]
git-tree-sha1 = "404265cd8128a2515a81d5eae16de90fdef05101"
@@ -181,6 +187,20 @@ git-tree-sha1 = "e98abef36d02a0ec385d68cd7dadbce9b28cbd88"
uuid = "abce61dc-4473-55a0-ba07-351d65e31d42"
version = "0.4.1"
[[deps.Distances]]
deps = ["LinearAlgebra", "Statistics", "StatsAPI"]
git-tree-sha1 = "c7e3a542b999843086e2f29dac96a618c105be1d"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.12"
[deps.Distances.extensions]
DistancesChainRulesCoreExt = "ChainRulesCore"
DistancesSparseArraysExt = "SparseArrays"
[deps.Distances.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
@@ -250,6 +270,7 @@ deps = ["LinearAlgebra"]
git-tree-sha1 = "2f979084d1e13948a3352cf64a25df6bd3b4dca3"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "1.16.0"
weakdeps = ["PDMats", "SparseArrays", "StaticArrays", "Statistics"]
[deps.FillArrays.extensions]
FillArraysPDMatsExt = "PDMats"
@@ -257,12 +278,6 @@ version = "1.16.0"
FillArraysStaticArraysExt = "StaticArrays"
FillArraysStatisticsExt = "Statistics"
[deps.FillArrays.weakdeps]
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
@@ -274,12 +289,23 @@ uuid = "a0844989-3bd2-4988-8bea-c9407ab0941b"
version = "1.1.0"
[[deps.GeneralUtils]]
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "HTTP", "JSON", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "UUIDs"]
git-tree-sha1 = "7c0600c166a5deb2c607018a491c04eb25969c2e"
repo-rev = "main"
repo-url = "https://git.yiem.cc/ton/GeneralUtils"
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "Graphs", "HTTP", "JSON", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "StringDistances", "UUIDs"]
path = "../GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
version = "0.4.9"
version = "0.4.10"
[[deps.Graphs]]
deps = ["ArnoldiMethod", "DataStructures", "Inflate", "LinearAlgebra", "Random", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "7eb45fe833a5b7c51cf6d89c5a841d5967e44be3"
uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
version = "1.14.0"
[deps.Graphs.extensions]
GraphsSharedArraysExt = "SharedArrays"
[deps.Graphs.weakdeps]
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
[[deps.HTTP]]
deps = ["Base64", "CodecZlib", "Dates", "EnumX", "PrecompileTools", "Random", "Reseau", "SHA", "URIs", "UUIDs", "Zlib_jll"]
@@ -310,6 +336,11 @@ git-tree-sha1 = "cf8234411cbeb98676c173f930951ea29dca3b23"
uuid = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
version = "0.2.4"
[[deps.Inflate]]
git-tree-sha1 = "d1b1b796e47d94588b3757fe84fbf65a5ec4a80d"
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
version = "0.1.5"
[[deps.InlineStrings]]
git-tree-sha1 = "8f3d257792a522b4601c24a577954b0a8cd7334d"
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
@@ -760,9 +791,7 @@ version = "0.7.0"
[[deps.SQLLLM]]
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "FileIO", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "PrettyPrinting", "Random", "Revise", "StatsBase", "Tables", "URIs", "UUIDs"]
git-tree-sha1 = "2807a768907f59308d8d71ece599037b0a66b0a5"
repo-rev = "main"
repo-url = "https://git.yiem.cc/ton/SQLLLM"
path = "../SQLLLM"
uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
version = "0.2.7"
@@ -793,6 +822,12 @@ version = "1.4.10"
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
version = "1.11.0"
[[deps.SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "7ddb0b49c109481b046972c0e4ab02b2127d6a75"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.6"
[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
version = "1.11.0"
@@ -826,6 +861,25 @@ version = "2.8.0"
[deps.SpecialFunctions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
[[deps.StaticArrays]]
deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"]
git-tree-sha1 = "246a8bb2e6667f832eea063c3a56aef96429a3db"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.9.18"
[deps.StaticArrays.extensions]
StaticArraysChainRulesCoreExt = "ChainRulesCore"
StaticArraysStatisticsExt = "Statistics"
[deps.StaticArrays.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
[[deps.StaticArraysCore]]
git-tree-sha1 = "6ab403037779dae8c514bad259f32a447262455a"
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
version = "1.4.4"
[[deps.Statistics]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0"
@@ -862,6 +916,12 @@ version = "2.2.0"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.StringDistances]]
deps = ["Distances", "StatsAPI"]
git-tree-sha1 = "cd83a04baf746e3b43b83c61b7de77ab0409b80a"
uuid = "88034a9c-02f8-509d-84a9-84ec65e18404"
version = "1.0.0"
[[deps.StringManipulation]]
deps = ["PrecompileTools"]
git-tree-sha1 = "d05693d339e37d6ab134c5ab53c29fce5ee5d7d5"
@@ -983,7 +1043,7 @@ uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60"
version = "1.6.1"
[[deps.YiemAgent]]
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "Serialization", "URIs", "UUIDs"]
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs"]
path = "."
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
version = "0.5.0"
-2
View File
@@ -25,9 +25,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat]
CSV = "0.10.15"
DataFrames = "1.7.0"
GeneralUtils = "0.4.9"
HTTP = "2.4.0"
JSON = "1.6.1"
LLMMCTS = "0.1.5"
NATS = "0.1.0"
SQLLLM = "0.2.7"
+1 -1
View File
@@ -54,7 +54,7 @@ Your name is $(newAgent.name). You are a helpful sommelier for website-based $(n
# Available Actions
- **CHAT_BOX** which you can use to talk with the user.
- **CHECK_WINE** allows you to check information about wines you want in your inventory's database. The input is text that specify supported search criteria includeing: retailer_name, wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
- **SEARCH_WINE_DATABASE** allows you to check information about wines you want in your inventory's database. The input is text that specify supported search criteria includeing: retailer_name, wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
- Example query 1: "Dry, full-bodied red wine from 1) region: Burgundy, country: France or 2) region: Tuscany, country: Italy. Grape varietal: Merlot or Syrah. price 100 to 1000 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
+6 -5
View File
@@ -6,6 +6,7 @@
"testingOrProduction": "testing",
"agentId": "2b74b87a-5413-4fe2-a4d3-405891051680",
"agentCentralConfigSubject": "/yiem/hq/agent/sommelier/backend/config/api/v1.1",
"this_service_name": "agent_backend",
"this_service_input_channel": {
"mqtt": [
"/yiem/hq/agent/sommpanion/backend/db/api_v1"
@@ -16,7 +17,7 @@
},
"agentRole": "sommelier",
"organization": "yiem_hq",
"externalService": {
"externalservice": {
"servicesloadbalancer": {
"nats": "sommpanion.backend.servicesloadbalancer.v1.inbox"
},
@@ -35,15 +36,15 @@
"description": "A database connection info for LibPQ client",
"url": "192.168.88.106:5432",
"dbname": "winedb",
"user": "yiemtechnologies@gmail.com",
"password": "yiemtechnologies@Postgres_0.0"
"user": "admin",
"password": "admin@Sommpanion_0.0"
},
"sommpanion_vectordb" : {
"description": "A wine database connection info for LibPQ client",
"url": "192.168.88.106:5433",
"dbname": "vectordb",
"user": "yiemtechnologies@gmail.com",
"password": "yiemtechnologies@Postgres_0.0"
"user": "admin",
"password": "admin@Sommpanion_0.0"
},
"fileserver": {
"description": "temporary file server",
+27 -19
View File
@@ -68,7 +68,7 @@ julia> result = decisionMaker(agent)
OrderedDict{String, Any} with 4 entries:
"plan" => "The user provided an image of a sparkling white wine (Asolo Prosecco Bella Principessa from Italy) and requested a search for similar wines in the inventory. According to store guidelines, I must st…
"action_name" => "CHECK_WINE"
"action_name" => "SEARCH_WINE_DATABASE"
"action_input" => "Sparkling white wine from Italy"
"action_result" => "1) winery: Terrazze dell Etna, wine_name: Rose Brut.
```
@@ -177,7 +177,7 @@ function decisionMaker(a::T; recentevents::Integer=20, maxattempt=10
continue
end
# if responsedict["action_name"] ∉ ["CHAT_BOX", "CHECK_WINE", "PRESENT_WINE_GUIDELINE", "END_CONVER_GUIDELINE"]
# 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())")
# continue
@@ -392,7 +392,7 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj
end
@info "YiemAgent conversation() 2-3 think count $loopcount " @__LINE__
thoughtdict, _ = think(a)
thoughtdict, result_raw = think(a)
if thoughtdict["action_name"] ["CHAT_BOX"]
@info "YiemAgent conversation() 2-4 think count $loopcount " @__LINE__
assistant_response = Dict{String, Any}(
@@ -401,7 +401,25 @@ function conversation(a::sommelier; userinput::Union{Dict{String, Any}, JSON.Obj
)
addNewMessage(a, "assistant", assistant_response; maximumMsg=maximumMsg)
return thoughtdict["action_input"]
# elseif thoughtdict["action_name"] ∈ ["CHAT_BOX"]
# @info "YiemAgent conversation() 2-4 think count $loopcount " @__LINE__
# assistant_response = Dict{String, Any}(
# "role" => "assistant",
# "content" => [
# Dict("type" => "text", "text" => thoughtdict["action_input"]),
# Dict( #WORKING put 1st image here
# "type" => "image_url",
# "image_url" => Dict("url" => image1_data_uri)
# ),
# Dict( #WORKING put 2nd image here
# "type" => "image_url",
# "image_url" => Dict("url" => image2_data_uri)
# ),
# ]
# )
# addNewMessage(a, "assistant", assistant_response; maximumMsg=maximumMsg)
return thoughtdict["action_input"] #XXX change output from string to dict
else
action_name = thoughtdict["action_name"]
action_input = thoughtdict["action_input"]
@@ -452,27 +470,17 @@ function think(a::T)::NamedTuple{(:thoughtdict, :result_raw), Tuple{OrderedDict,
elseif thoughtdict["action_name"] ["WINE_PRESENTATION_GUIDELINE"]
@info "YiemAgent think() 4 " @__LINE__
thoughtdict, result_raw = wine_presentation_guideline!(a, thoughtdict)
elseif thoughtdict["action_name"] == "CHECK_WINE"
elseif thoughtdict["action_name"] == "SEARCH_WINE_DATABASE"
@info "YiemAgent think() 5 " @__LINE__
thoughtdict, result_raw = checkwine!(a, thoughtdict; useSQLLLM=false)
thoughtdict, result_raw = search_wine_database!(a, thoughtdict; useSQLLLM=true)
#WORKING result_raw will be a df. i need to get images so i can send to frontend
else
@info "YiemAgent think() 6 " @__LINE__
error("condition is not defined ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
end
# max_ind =
# if length(a.memory["shortmem"]) == 0
# 0
# else
# k = keys(a.memory["shortmem"])
# maximum(parse.(Int, k))
# end
# a.memory["shortmem"]["$(max_ind + 1)"] = thoughtdict
pprintln(thoughtdict)
println("\n")
@show thoughtdict
@info "YiemAgent think() 7 " @__LINE__
return (thoughtdict=thoughtdict, result_raw=result_raw)
end
@@ -700,7 +708,7 @@ function generatechat!(a::T; maxattempt::Integer=10
continue
end
# if responsedict["action_name"] ∉ ["CHAT_BOX", "CHECK_WINE", "PRESENT_WINE_GUIDELINE", "END_CONVER_GUIDELINE"]
# 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())")
# continue
+66 -11
View File
@@ -1,6 +1,6 @@
module llmfunction
export virtualWineUserChatbox, jsoncorrection, checkwine!, # recommendbox,
export virtualWineUserChatbox, jsoncorrection, search_wine_database!, # recommendbox,
virtualWineUserRecommendbox, userChatbox, userRecommendbox, extractWineAttributes_1,
extractWineAttributes_2, paraphrase
@@ -282,15 +282,15 @@ julia> result = checkinventory(agent, input)
"{"wine 1": {\"Winery\": \"Pichon Baron\", \"wine name\": \"Pauillac (Grand Cru Classé)\", \"grape variety\": \"Cabernet Sauvignon\", \"year\": 2010, \"price\": \"125 USD\", \"stock ID\": \"ar-17\"}, }"
```
"""
function checkwine!(a::T, thoughtdict::AbstractDict; useSQLLLM::Bool=false
function search_wine_database!(a::T, thoughtdict::AbstractDict; useSQLLLM::Bool=false
)::NamedTuple{(:thoughtdict, :result_raw), Tuple{OrderedDict, Any}} where {T<:agent}
println("\ncheckinventory order: $(thoughtdict["action_input"]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
wineattributes_1 = extractWineAttributes_1(a, thoughtdict["action_input"])
wineattributes_2 = extractWineAttributes_2(a, thoughtdict["action_input"])
retrieve_attributes = ["winery", "wine_name", "wine_id", "vintage", "region", "country", "wine_type", "grape", "serving_temperature", "sweetness", "intensity", "tannin", "acidity", "tasting_notes", "price", "currency"]
_inventoryquery = "$wineattributes_1, $wineattributes_2"
retrieve_attributes = ["winery", "wine_name", "wine_id", "vintage", "region", "country", "wine_type", "grape", "serving_temperature", "sweetness", "intensity", "tannin", "acidity", "tasting_notes", "price", "currency", "image_url", "retailer_name", "retailer_id"]
_inventoryquery = "$wineattributes_1, $wineattributes_2, retailer_name: $(a.retailername), retailerid: $(a.retailerid)"
inventoryquery = "Retrieves $retrieve_attributes of wines that match the following criteria - {$_inventoryquery}"
println("\ncheckinventory input: $inventoryquery ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
@@ -308,7 +308,44 @@ function checkwine!(a::T, thoughtdict::AbstractDict; useSQLLLM::Bool=false
# direct query with possible sql instead of SQLLLM.
sql = generatesql(a, inventoryquery)
println("\nSQL: $sql ", @__FILE__, ":", @__LINE__, " $(Dates.now()) \n")
textresult, result_raw, _, _ = SQLexecution(a.context.executeSQL, sql)
#WORKING if result_raw != nothing, get image from image_url column of a df.
# then store in a.memory["shortmem]["image"] = OrderedDict(
# Dict(
# "wine_id"=> "wine_id,
# "name"=> "wine name",
# "image_url" => Dict("url" => data1_uri)
# )
# )
# # 1. Read local file and encode to base64 string
# image2_path = "test/small_image.png"
# image2_bytes = read(image2_path)
# image2_base64_string = base64encode(image2_bytes)
# mime_type = "image/png"
# data2_uri = "data:$(mime_type);base64,$(image2_base64_string)"
# # 3. Construct payload with the Data URI
# message = Dict(
# "role" => "user",
# "content" => [
# Dict("type" => "text", "text" => "Do you know type of wine in the image?"),
# Dict(
# "type" => "image_url",
# "image_url" => Dict("url" => data1_uri)
# )
# ]
# )
thoughtdict["action_result"] = textresult
end
@@ -324,7 +361,8 @@ function generatesql(a::T, searchterm::String,
"""
# database_search_guidelines
- Keep SQL queries focused only on the provided information.
- Do not create any table in the database
- Use wildcard character (%) to search more effectively.
- Do not create any table in the database.
- A junction table can be used to link tables together. Another use case is for filtering data.
- If you can't find a single table that can be used to answer the user's search term, try joining multiple tables to see if you can obtain the answer.
- Text information in the database usually stored in lower case. If your search returns empty, try using lower case to search.
@@ -603,7 +641,7 @@ function SQLexecution(executeSQL::Function, sql::T
tablesize = size(df)
row, column = tablesize
if row == 0
return (result_str="No records found.", result_raw=df, success=true, errormsg=nothing)
return (result_str="No records found. Try loosening your search criteria.", result_raw=nothing, success=true, errormsg=nothing)
elseif column > 30
return (result_str="There are more than 30 columns. Please be more specific.", result_raw=df, success=true, errormsg=nothing)
else
@@ -678,6 +716,7 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
wine_price_max: maximum price range of wine. Example: For wine price 20, wine_price_max will be 20. For wine price 10 to 100, wine_price_max will be 100.
occasion: the occasion the user is having the wine for
food_to_be_paired_with_wine: food that the user will be served with the wine such as poultry, fish, steak, etc
_keyword suffice is the related keyword that appears in user's query. each keyword can not be used twice.
</you should then respond to the user with>
<you should only respond in JSON format as described below>
"wine_name": "...",
@@ -756,9 +795,6 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
for attempt in 1:maxattempt
response = a.context.text2textInstructLLM(a.id, msg)
response = GeneralUtils.clean_json_response(response)
println("\n--- extractWineAttributes_1-1()")
println(response)
println("--- \n")
response = GeneralUtils.remove_french_accents(response)
think, response = GeneralUtils.extractthink(response)
@@ -786,6 +822,18 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
_v = replace(v, r"\(.*?\)" => "")
responsedict[k] = _v
end
println("\n--- extractWineAttributes_1-1()")
@show responsedict
@info "---\n" @__LINE__
#WORKING check each attributes against database with BM25
for (k, v) in responsedict
words_catalog = GeneralUtils.harvest_entity_catalog(a.context.pg_conn_str, "wine", k)
resolved_word = GeneralUtils.resolve_entity(v, words_catalog;threshold=0.9)
responsedict[k] = resolved_word
end
result = ""
for (k, v) in responsedict
# some time LLM generate text with "(some comment)". this line removes it
@@ -793,10 +841,17 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
result *= "$k: $v, "
end
end
result = result[1:end-2] # remove the ending ", "
println("\n--- extractWineAttributes_1-2()")
println(result)
println("--- \n")
@show responsedict
@show result
@info "---\n" @__LINE__
return result
end
error("extractWineAttributes_1() failed to get a response")
+7 -3
View File
@@ -16,6 +16,7 @@ mutable struct agentcontext
insertSQLVectorDB::Function
similarSommelierDecision::Function
insertSommelierDecision::Function
pg_conn_str::String
end
abstract type agent end
@@ -93,6 +94,7 @@ mutable struct sommelier <: agent
name::String # agent name
id::String # agent id
retailername::String
retailerid::String
tools::Dict
maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized
chathistory::Vector{Dict{String, Any}}
@@ -140,11 +142,12 @@ julia> agent = sommelier(context, name="WineExpert", id="123", retailername="MyW
```
"""
function sommelier(
context::agentcontext, # app context
context::agentcontext, # agent functions, db connect and other context
;
name::String= "Assistant",
id::String= string(uuid4()),
retailername::String= "retailer_name",
retailername::String= "not specified",
retailerid::String= "not specified",
maxHistoryMsg::Integer= 20,
chathistory::Vector{Dict{String, Any}} = Vector{Dict{String, Any}}(),
llmFormatName::String= "granite3"
@@ -216,6 +219,7 @@ function sommelier(
name,
id,
retailername,
retailerid,
tools,
maxHistoryMsg,
chathistory,
@@ -279,7 +283,7 @@ function sommelier(
# available actions
"CHAT_BOX", which you can use to talk with the user. The input is dialogue you want to chat with the user according to your plan.
"CHECK_WINE", allows you to check information about wines you want in your inventory's database. The input is text that specify supported search criteria includeing: retailer_name, wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
"SEARCH_WINE_DATABASE", allows you to search information about wines you want in your inventory's database. The input is supported search criteria including: retailer_name, wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
Example query 1: "Dry, full-bodied red wine from 1) region: Burgundy, country: France or 2) region: Tuscany, country: Italy. Grape varietal: Merlot or Syrah. price 100 to 1000 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
+1 -1
View File
@@ -297,7 +297,7 @@ function createTimeline(events::T1; eventindex::Union{UnitRange, Nothing}=nothin
# timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"])\n"
# elseif event["action_name"] == "CHECKINVENTORY" && event["observation"] === nothing
# timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"]), observation: Not done yet.\n"
if event["action_name"] == "CHECK_WINE"
if event["action_name"] == "SEARCH_WINE_DATABASE"
timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"]), observation: $(event["observation"])\\n"
else
timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"])\\n"
+2 -2
View File
@@ -128,7 +128,7 @@ systemmsg =
# Available Actions
- **CHAT_BOX** which you can use to talk with the user.
- **CHECK_WINE** allows you to check information about wines you want in your inventory's database. The input is text that specify supported search criteria includeing: retailer_name, wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
- **SEARCH_WINE_DATABASE** allows you to check information about wines you want in your inventory's database. The input is text that specify supported search criteria includeing: retailer_name, wine price, winery, name, vintage, region, country, type, grape varietal, tasting notes, occasion, food pairing, intensity, tannin, sweetness, and acidity.
- Example query 1: "Dry, full-bodied red wine from 1) region: Burgundy, country: France or 2) region: Tuscany, country: Italy. Grape varietal: Merlot or Syrah. price 100 to 1000 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
@@ -157,7 +157,7 @@ openai_msg = Dict(
"content" => [
Dict("type" => "text", "text" =>
"""
" <plan>I will greet the customer warmly as Janie, acknowledge their request to find a similar wine for their wedding party based on the image, identify the wine type and country (Italian Sparkling Wine), and then use the CHECK_WINE action to search the inventory for suitable options.</plan>\n <action_name>CHAT_BOX</action_name>\n <action_input>Hello! I'm Janie, and I'd be delighted to help you find the perfect wine for your wedding party. That beautiful wine in the image appears to be an Italian sparkling wine, which is wonderful for a celebration like a wedding! Since you have an unlimited budget, I can certainly look for some truly exceptional options. To start, I will check our inventory for similar Italian sparkling wines that are perfect for a wedding celebration.</action_input><action_result> User response in the next message </action_result>"
" <plan>I will greet the customer warmly as Janie, acknowledge their request to find a similar wine for their wedding party based on the image, identify the wine type and country (Italian Sparkling Wine), and then use the SEARCH_WINE_DATABASE action to search the inventory for suitable options.</plan>\n <action_name>CHAT_BOX</action_name>\n <action_input>Hello! I'm Janie, and I'd be delighted to help you find the perfect wine for your wedding party. That beautiful wine in the image appears to be an Italian sparkling wine, which is wonderful for a celebration like a wedding! Since you have an unlimited budget, I can certainly look for some truly exceptional options. To start, I will check our inventory for similar Italian sparkling wines that are perfect for a wedding celebration.</action_input><action_result> User response in the next message </action_result>"
"""
),
]