This commit is contained in:
2026-07-16 22:31:40 +07:00
parent 44bb8baf7c
commit 87bc6a46a1
7 changed files with 273 additions and 138 deletions
+36 -50
View File
@@ -2,9 +2,10 @@ module llmfunction
export virtualWineUserChatbox, jsoncorrection, search_wine_database!, # recommendbox,
virtualWineUserRecommendbox, userChatbox, userRecommendbox, extractWineAttributes_1,
extractWineAttributes_2, paraphrase
extractWineAttributes_2, paraphrase, SQLexecution
using HTTP, JSON, URIs, Random, PrettyPrinting, UUIDs, Dates, DataFrames, DataStructures
using HTTP, JSON, URIs, Random, PrettyPrinting, UUIDs, Dates, DataFrames, DataStructures,
Base64
using GeneralUtils, SQLLLM
using ..type, ..util
@@ -211,7 +212,7 @@ pushfirst!(virtualCustomerChatHistory, Dict("name"=> "system", "text"=> systemms
receiverName= "text2textinstruct",
mqttBroker= config["mqttServerInfo"]["broker"],
mqttBrokerPort= config["mqttServerInfo"]["port"],
msgId = string(uuid4()) #CHANGE remove after testing finished
msgId = string(uuid4()) # remove after testing finished
)
outgoingMsg = Dict(
@@ -286,11 +287,11 @@ function search_wine_database!(a::T, thoughtdict::AbstractDict; useSQLLLM::Bool=
)::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_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", "image_url", "retailer_name", "retailer_id"]
_inventoryquery = "$wineattributes_1, $wineattributes_2, retailer_name: $(a.retailername), retailerid: $(a.retailerid)"
_inventoryquery = "$(thoughtdict["action_input"]), $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())")
@@ -309,47 +310,33 @@ function search_wine_database!(a::T, thoughtdict::AbstractDict; useSQLLLM::Bool=
# 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)
# )
# ]
# )
textresult, sql_result_df, success, _ = SQLexecution(a.context.executeSQL, sql)
items = nothing
if sql_result_df !== nothing
result_vec = GeneralUtils.dfToVectorDict(sql_result_df)
# get image
for d in result_vec
image_url_json_str = d["image_url"]
image_url_json_obj = JSON.parse(image_url_json_str)
base_url = "http://192.168.88.106:8080/"
if haskey(image_url_json_obj, "bottle")
url = base_url * image_url_json_obj["bottle"]
image_data = HTTP.get(url) # vector{int} data
image_base64_string = base64encode(image_data.body)
d["image"] = image_base64_string
else
d["image"] = nothing
end
end
items = result_vec # image is added to each item
end
thoughtdict["action_result"] = textresult
end
return (thoughtdict=thoughtdict, result_raw=result_raw)
return (thoughtdict=thoughtdict, result_raw=items)
end
@@ -366,7 +353,7 @@ function generatesql(a::T, searchterm::String,
- 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.
- If there is no search result from the database, remove the restrictive criteria until a search result is available, and proceed from there.
- Overly strict condition usually yields empth result
# situation
At each round of conversation, you will be given the following:
@@ -720,7 +707,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.
_keyword suffice is the related keyword that appears in user's query.
</you should then respond to the user with>
<you should only respond in JSON format as described below>
"wine_name": "...",
@@ -827,15 +814,15 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
responsedict[k] = _v
end
# println("\n--- extractWineAttributes_1-1()")
# @show responsedict
# @info "---\n" @__LINE__
println("\n--- extractWineAttributes_1-1()")
@show responsedict
@info "---\n" @__LINE__
# check each attributes against each column in a database table with BM25
for (k, v) in responsedict
if k ["wine_price_min", "wine_price_max"]
words_catalog = GeneralUtils.harvest_entity_catalog(a.context.pg_conn_str, "wine", k)
resolved_word = GeneralUtils.resolve_entity(v, words_catalog;threshold=0.9)
resolved_word = GeneralUtils.resolve_entity(v, words_catalog; threshold=0.9)
responsedict[k] = resolved_word
end
end
@@ -849,10 +836,9 @@ function extractWineAttributes_1(a::T1, input::T2; maxattempt=10
end
result = result[1:end-2] # remove the ending ", "
# println("\n--- extractWineAttributes_1-2()")
# @show responsedict
# @show result
# @info "---\n" @__LINE__
println("\n--- extractWineAttributes_1-2()")
@show result
@info "---\n" @__LINE__
return result
end
error("extractWineAttributes_1() failed to get a response")