Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8fed0b5e8f | |||
| 567d6b79d7 | |||
| 74be3e5717 | |||
| 402b6fcadd | |||
| ef523aaa48 | |||
| ddbb135b6b | |||
| afda364484 | |||
| af73d955eb | |||
| 39cf9a72a1 | |||
| 1c829ad854 | |||
| da98baddb6 | |||
| c5fbaabf42 | |||
| 8080905bad | |||
| b349c3a8b6 | |||
| 0148e03d6a | |||
| e718cc4a5c | |||
| 87bc6a46a1 | |||
| 44bb8baf7c | |||
| 18b2d54ba7 | |||
| b3c3bb9b75 | |||
| d004193b19 | |||
| 8898226825 | |||
| 686b9b2e92 | |||
| 3acf46964b | |||
| 5c7caf0b49 | |||
| ad917ea8d0 | |||
| edeef4ed2a | |||
| 31daa805f3 | |||
| c9937ab5d7 | |||
| 4610137f04 | |||
| 9d7eed7cde | |||
| aedc53bf86 | |||
| 286da3cf2c | |||
| 7fa988313d | |||
| e5b19dd268 | |||
| 0df4159261 | |||
| 45e8ded111 | |||
| 9167ece0c0 | |||
| a6a9395ecc | |||
| a503d4d759 | |||
| f45a036971 | |||
| 24b85be58b | |||
| a798cd119e | |||
| fa338dd0f8 | |||
| 8d4bf5f01f | |||
| cd6f6ef961 | |||
| fdec34832d | |||
| 3c72373b85 | |||
| 688a8c4df2 | |||
| 8bd4986be2 | |||
| 6e5809fc9b | |||
| 2b7c0041e5 | |||
| 9ff0b48eec | |||
| afeb4c7aef | |||
| 2942a89730 | |||
| 6a66f58e63 | |||
| 1d0353d793 | |||
| 0f6aa7c79f | |||
| 0320fd321f | |||
| c29dccf597 | |||
| 70cf04b0db | |||
| 4d57f0146b | |||
| d33aa14dc8 | |||
| 0ed3edd48a | |||
| fb91b51573 | |||
| 0bbd227920 | |||
| 3487770f77 | |||
| 7d27f9e567 | |||
| 511b4d682d | |||
| 5ba91d8acc | |||
| 709f7e7115 |
+132
-73
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
julia_version = "1.12.6"
|
julia_version = "1.12.6"
|
||||||
manifest_format = "2.0"
|
manifest_format = "2.0"
|
||||||
project_hash = "5b5e1c071ff66b72aeed7d8a4316829e2407ae1a"
|
project_hash = "dc7878808bbc4637a12e709dd495979a784824a5"
|
||||||
|
|
||||||
[[deps.Accessors]]
|
[[deps.Accessors]]
|
||||||
deps = ["CompositionsBase", "ConstructionBase", "Dates", "InverseFunctions", "MacroTools"]
|
deps = ["CompositionsBase", "ConstructionBase", "Dates", "InverseFunctions", "MacroTools"]
|
||||||
@@ -38,11 +38,11 @@ version = "1.1.3"
|
|||||||
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
|
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
|
||||||
[[deps.Arrow]]
|
[[deps.ArnoldiMethod]]
|
||||||
deps = ["ArrowTypes", "BitIntegers", "CodecLz4", "CodecZstd", "ConcurrentUtilities", "DataAPI", "Dates", "EnumX", "Mmap", "PooledArrays", "SentinelArrays", "StringViews", "Tables", "TimeZones", "TranscodingStreams", "UUIDs"]
|
deps = ["LinearAlgebra", "Random", "StaticArrays"]
|
||||||
git-tree-sha1 = "4a69a3eadc1f7da78d950d1ef270c3a62c1f7e01"
|
git-tree-sha1 = "d57bd3762d308bded22c3b82d033bff85f6195c6"
|
||||||
uuid = "69666777-d1a9-59fb-9406-91d4454c9d45"
|
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
|
||||||
version = "2.8.1"
|
version = "0.4.0"
|
||||||
|
|
||||||
[[deps.ArrowTypes]]
|
[[deps.ArrowTypes]]
|
||||||
deps = ["Sockets", "UUIDs"]
|
deps = ["Sockets", "UUIDs"]
|
||||||
@@ -58,12 +58,6 @@ version = "1.11.0"
|
|||||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
|
||||||
[[deps.BitIntegers]]
|
|
||||||
deps = ["Random"]
|
|
||||||
git-tree-sha1 = "091d591a060e43df1dd35faab3ca284925c48e46"
|
|
||||||
uuid = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1"
|
|
||||||
version = "0.3.7"
|
|
||||||
|
|
||||||
[[deps.BufferedStreams]]
|
[[deps.BufferedStreams]]
|
||||||
git-tree-sha1 = "6863c5b7fc997eadcabdbaf6c5f201dc30032643"
|
git-tree-sha1 = "6863c5b7fc997eadcabdbaf6c5f201dc30032643"
|
||||||
uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d"
|
uuid = "e1450e63-4bb3-523b-b2a4-4ffa8c0fd77d"
|
||||||
@@ -96,28 +90,16 @@ git-tree-sha1 = "40956acdbef3d8c7cc38cba42b56034af8f8581a"
|
|||||||
uuid = "6c391c72-fb7b-5838-ba82-7cfb1bcfecbf"
|
uuid = "6c391c72-fb7b-5838-ba82-7cfb1bcfecbf"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
|
||||||
[[deps.CodecLz4]]
|
|
||||||
deps = ["Lz4_jll", "TranscodingStreams"]
|
|
||||||
git-tree-sha1 = "d58afcd2833601636b48ee8cbeb2edcb086522c2"
|
|
||||||
uuid = "5ba52731-8f18-5e0d-9241-30f10d1ec561"
|
|
||||||
version = "0.4.6"
|
|
||||||
|
|
||||||
[[deps.CodecZlib]]
|
[[deps.CodecZlib]]
|
||||||
deps = ["TranscodingStreams", "Zlib_jll"]
|
deps = ["TranscodingStreams", "Zlib_jll"]
|
||||||
git-tree-sha1 = "962834c22b66e32aa10f7611c08c8ca4e20749a9"
|
git-tree-sha1 = "962834c22b66e32aa10f7611c08c8ca4e20749a9"
|
||||||
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
|
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
|
||||||
version = "0.7.8"
|
version = "0.7.8"
|
||||||
|
|
||||||
[[deps.CodecZstd]]
|
|
||||||
deps = ["TranscodingStreams", "Zstd_jll"]
|
|
||||||
git-tree-sha1 = "da54a6cd93c54950c15adf1d336cfd7d71f51a56"
|
|
||||||
uuid = "6b39b394-51ab-5f42-8807-6242bab2b4c2"
|
|
||||||
version = "0.8.7"
|
|
||||||
|
|
||||||
[[deps.CommonSolve]]
|
[[deps.CommonSolve]]
|
||||||
git-tree-sha1 = "99ee296f88c12485402e37c2fd025f95ae097637"
|
git-tree-sha1 = "eeaad7cef88554c2fa56b5a3f71cfd5cb708c662"
|
||||||
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
|
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
|
||||||
version = "0.2.9"
|
version = "0.2.11"
|
||||||
|
|
||||||
[[deps.Compat]]
|
[[deps.Compat]]
|
||||||
deps = ["TOML", "UUIDs"]
|
deps = ["TOML", "UUIDs"]
|
||||||
@@ -148,12 +130,6 @@ weakdeps = ["InverseFunctions"]
|
|||||||
[deps.CompositionsBase.extensions]
|
[deps.CompositionsBase.extensions]
|
||||||
CompositionsBaseInverseFunctionsExt = "InverseFunctions"
|
CompositionsBaseInverseFunctionsExt = "InverseFunctions"
|
||||||
|
|
||||||
[[deps.ConcurrentUtilities]]
|
|
||||||
deps = ["Serialization", "Sockets"]
|
|
||||||
git-tree-sha1 = "21d088c496ea22914fe80906eb5bce65755e5ec8"
|
|
||||||
uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb"
|
|
||||||
version = "2.5.1"
|
|
||||||
|
|
||||||
[[deps.ConstructionBase]]
|
[[deps.ConstructionBase]]
|
||||||
git-tree-sha1 = "b4b092499347b18a015186eae3042f72267106cb"
|
git-tree-sha1 = "b4b092499347b18a015186eae3042f72267106cb"
|
||||||
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
|
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
|
||||||
@@ -211,6 +187,20 @@ git-tree-sha1 = "e98abef36d02a0ec385d68cd7dadbce9b28cbd88"
|
|||||||
uuid = "abce61dc-4473-55a0-ba07-351d65e31d42"
|
uuid = "abce61dc-4473-55a0-ba07-351d65e31d42"
|
||||||
version = "0.4.1"
|
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.Distributed]]
|
||||||
deps = ["Random", "Serialization", "Sockets"]
|
deps = ["Random", "Serialization", "Sockets"]
|
||||||
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
||||||
@@ -254,11 +244,21 @@ git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec"
|
|||||||
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
|
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
|
|
||||||
|
[[deps.EzXML]]
|
||||||
|
deps = ["Printf", "XML2_jll"]
|
||||||
|
git-tree-sha1 = "7ea1aa5869e2626ccae84480e4f37185bc6f41d3"
|
||||||
|
uuid = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615"
|
||||||
|
version = "1.2.3"
|
||||||
|
|
||||||
[[deps.FileIO]]
|
[[deps.FileIO]]
|
||||||
deps = ["Pkg", "Requires", "UUIDs"]
|
deps = ["Pkg", "Requires", "UUIDs"]
|
||||||
git-tree-sha1 = "91e0e5c68d02bcdaae76d3c8ceb4361e8f28d2e9"
|
git-tree-sha1 = "6621fef488e496356c9c9625d0562c12a6070819"
|
||||||
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
|
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
|
||||||
version = "1.16.5"
|
version = "1.20.0"
|
||||||
|
weakdeps = ["HTTP"]
|
||||||
|
|
||||||
|
[deps.FileIO.extensions]
|
||||||
|
HTTPExt = "HTTP"
|
||||||
|
|
||||||
[[deps.FilePathsBase]]
|
[[deps.FilePathsBase]]
|
||||||
deps = ["Compat", "Dates"]
|
deps = ["Compat", "Dates"]
|
||||||
@@ -280,6 +280,7 @@ deps = ["LinearAlgebra"]
|
|||||||
git-tree-sha1 = "2f979084d1e13948a3352cf64a25df6bd3b4dca3"
|
git-tree-sha1 = "2f979084d1e13948a3352cf64a25df6bd3b4dca3"
|
||||||
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
|
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
|
weakdeps = ["PDMats", "SparseArrays", "StaticArrays", "Statistics"]
|
||||||
|
|
||||||
[deps.FillArrays.extensions]
|
[deps.FillArrays.extensions]
|
||||||
FillArraysPDMatsExt = "PDMats"
|
FillArraysPDMatsExt = "PDMats"
|
||||||
@@ -287,12 +288,6 @@ version = "1.16.0"
|
|||||||
FillArraysStaticArraysExt = "StaticArrays"
|
FillArraysStaticArraysExt = "StaticArrays"
|
||||||
FillArraysStatisticsExt = "Statistics"
|
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.Future]]
|
||||||
deps = ["Random"]
|
deps = ["Random"]
|
||||||
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
|
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
|
||||||
@@ -304,18 +299,31 @@ uuid = "a0844989-3bd2-4988-8bea-c9407ab0941b"
|
|||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
||||||
[[deps.GeneralUtils]]
|
[[deps.GeneralUtils]]
|
||||||
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "HTTP", "JSON", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "UUIDs"]
|
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "Graphs", "HTTP", "JSON", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SHA", "StringDistances", "UUIDs"]
|
||||||
git-tree-sha1 = "7c0600c166a5deb2c607018a491c04eb25969c2e"
|
git-tree-sha1 = "a75a088ee8e5faf10f554ca00748e0e6ca58d1ca"
|
||||||
repo-rev = "main"
|
repo-rev = "main"
|
||||||
repo-url = "https://git.yiem.cc/ton/GeneralUtils"
|
repo-url = "https://git.yiem.cc/ton/GeneralUtils"
|
||||||
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
||||||
version = "0.4.9"
|
version = "0.5.1"
|
||||||
|
|
||||||
|
[[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.HTTP]]
|
||||||
deps = ["Base64", "CodecZlib", "Dates", "EnumX", "PrecompileTools", "Random", "Reseau", "SHA", "URIs", "UUIDs", "Zlib_jll"]
|
deps = ["Base64", "CodecZlib", "Dates", "EnumX", "PrecompileTools", "Random", "Reseau", "SHA", "URIs", "UUIDs", "Zlib_jll"]
|
||||||
git-tree-sha1 = "eda1d37cb55d90a17d0957c75841138c88b361a1"
|
git-tree-sha1 = "c2c808326222b6dc4bec295a83b55f79aeec98e0"
|
||||||
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
||||||
version = "2.5.4"
|
version = "2.5.5"
|
||||||
|
|
||||||
[[deps.HashArrayMappedTries]]
|
[[deps.HashArrayMappedTries]]
|
||||||
git-tree-sha1 = "2eaa69a7cab70a52b9687c8bf950a5a93ec895ae"
|
git-tree-sha1 = "2eaa69a7cab70a52b9687c8bf950a5a93ec895ae"
|
||||||
@@ -340,6 +348,11 @@ git-tree-sha1 = "cf8234411cbeb98676c173f930951ea29dca3b23"
|
|||||||
uuid = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
|
uuid = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
|
||||||
|
[[deps.Inflate]]
|
||||||
|
git-tree-sha1 = "d1b1b796e47d94588b3757fe84fbf65a5ec4a80d"
|
||||||
|
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
|
||||||
|
version = "0.1.5"
|
||||||
|
|
||||||
[[deps.InlineStrings]]
|
[[deps.InlineStrings]]
|
||||||
git-tree-sha1 = "8f3d257792a522b4601c24a577954b0a8cd7334d"
|
git-tree-sha1 = "8f3d257792a522b4601c24a577954b0a8cd7334d"
|
||||||
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
|
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
|
||||||
@@ -436,7 +449,9 @@ version = "1.21.3+0"
|
|||||||
|
|
||||||
[[deps.LLMMCTS]]
|
[[deps.LLMMCTS]]
|
||||||
deps = ["GeneralUtils", "JSON", "PrettyPrinting"]
|
deps = ["GeneralUtils", "JSON", "PrettyPrinting"]
|
||||||
path = "../LLMMCTS"
|
git-tree-sha1 = "3dff98131dfa79be8c9bd84fc51cb0ba1832c472"
|
||||||
|
repo-rev = "main"
|
||||||
|
repo-url = "https://git.yiem.cc/ton/LLMMCTS"
|
||||||
uuid = "d76c5a4d-449e-4835-8cc4-dd86ec44f241"
|
uuid = "d76c5a4d-449e-4835-8cc4-dd86ec44f241"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
|
||||||
@@ -491,6 +506,12 @@ version = "1.11.3+1"
|
|||||||
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
|
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
|
||||||
|
[[deps.Libiconv_jll]]
|
||||||
|
deps = ["Artifacts", "JLLWrappers", "Libdl"]
|
||||||
|
git-tree-sha1 = "be484f5c92fad0bd8acfef35fe017900b0b73809"
|
||||||
|
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
|
||||||
|
version = "1.18.0+0"
|
||||||
|
|
||||||
[[deps.LinearAlgebra]]
|
[[deps.LinearAlgebra]]
|
||||||
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
|
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
|
||||||
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||||
@@ -522,12 +543,6 @@ git-tree-sha1 = "3733419e9a71156b389f3e331672d2e95436783f"
|
|||||||
uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
|
uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
|
||||||
version = "3.6.2"
|
version = "3.6.2"
|
||||||
|
|
||||||
[[deps.Lz4_jll]]
|
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl"]
|
|
||||||
git-tree-sha1 = "191686b1ac1ea9c89fc52e996ad15d1d241d1e33"
|
|
||||||
uuid = "5ced341a-0733-55b8-9ab6-a4889d929147"
|
|
||||||
version = "1.10.1+0"
|
|
||||||
|
|
||||||
[[deps.MacroTools]]
|
[[deps.MacroTools]]
|
||||||
git-tree-sha1 = "1e0228a030642014fe5cfe68c2c0a818f9e3f522"
|
git-tree-sha1 = "1e0228a030642014fe5cfe68c2c0a818f9e3f522"
|
||||||
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
|
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
|
||||||
@@ -679,15 +694,17 @@ version = "0.4.2"
|
|||||||
|
|
||||||
[[deps.PrettyTables]]
|
[[deps.PrettyTables]]
|
||||||
deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "REPL", "Reexport", "StringManipulation", "Tables"]
|
deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "REPL", "Reexport", "StringManipulation", "Tables"]
|
||||||
git-tree-sha1 = "624de6279ab7d94fc9f672f0068107eb6619732c"
|
git-tree-sha1 = "ebf455bb866ee6737030e3d3816bb6a0683c4325"
|
||||||
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
|
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
|
||||||
version = "3.3.2"
|
version = "3.4.0"
|
||||||
|
|
||||||
[deps.PrettyTables.extensions]
|
[deps.PrettyTables.extensions]
|
||||||
|
PrettyTablesExcelExt = "XLSX"
|
||||||
PrettyTablesTypstryExt = "Typstry"
|
PrettyTablesTypstryExt = "Typstry"
|
||||||
|
|
||||||
[deps.PrettyTables.weakdeps]
|
[deps.PrettyTables.weakdeps]
|
||||||
Typstry = "f0ed7684-a786-439e-b1e3-3b82803b501e"
|
Typstry = "f0ed7684-a786-439e-b1e3-3b82803b501e"
|
||||||
|
XLSX = "fdbf4ff8-1666-58a4-91e7-1b58723a45e0"
|
||||||
|
|
||||||
[[deps.Printf]]
|
[[deps.Printf]]
|
||||||
deps = ["Unicode"]
|
deps = ["Unicode"]
|
||||||
@@ -768,9 +785,9 @@ version = "0.5.1+0"
|
|||||||
|
|
||||||
[[deps.Roots]]
|
[[deps.Roots]]
|
||||||
deps = ["Accessors", "CommonSolve", "Printf"]
|
deps = ["Accessors", "CommonSolve", "Printf"]
|
||||||
git-tree-sha1 = "ed45bcc7cf3c8887595b973f2b1efbe91dcc50ec"
|
git-tree-sha1 = "a7caaf7ba8cf307112ca443784d1b56b4a591455"
|
||||||
uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
|
uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
|
||||||
version = "3.0.1"
|
version = "3.0.5"
|
||||||
|
|
||||||
[deps.Roots.extensions]
|
[deps.Roots.extensions]
|
||||||
RootsChainRulesCoreExt = "ChainRulesCore"
|
RootsChainRulesCoreExt = "ChainRulesCore"
|
||||||
@@ -794,11 +811,11 @@ version = "0.7.0"
|
|||||||
|
|
||||||
[[deps.SQLLLM]]
|
[[deps.SQLLLM]]
|
||||||
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "FileIO", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "PrettyPrinting", "Random", "Revise", "StatsBase", "Tables", "URIs", "UUIDs"]
|
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "FileIO", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "PrettyPrinting", "Random", "Revise", "StatsBase", "Tables", "URIs", "UUIDs"]
|
||||||
git-tree-sha1 = "997602ed56a285ac29d74c91bb57bc5faeadfad6"
|
git-tree-sha1 = "bae2fd2e2b087753fbb3415896be41df1ae0eb90"
|
||||||
repo-rev = "main"
|
repo-rev = "main"
|
||||||
repo-url = "https://git.yiem.cc/ton/SQLLLM"
|
repo-url = "https://git.yiem.cc/ton/SQLLLM"
|
||||||
uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
|
uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
|
||||||
version = "0.2.5"
|
version = "0.2.8"
|
||||||
|
|
||||||
[[deps.SQLStrings]]
|
[[deps.SQLStrings]]
|
||||||
git-tree-sha1 = "55de0530689832b1d3d43491ee6b67bd54d3323c"
|
git-tree-sha1 = "55de0530689832b1d3d43491ee6b67bd54d3323c"
|
||||||
@@ -823,10 +840,22 @@ git-tree-sha1 = "084c47c7c5ce5cfecefa0a98dff69eb3646b5a80"
|
|||||||
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
|
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
|
||||||
version = "1.4.10"
|
version = "1.4.10"
|
||||||
|
|
||||||
|
[[deps.Serde]]
|
||||||
|
deps = ["CSV", "Dates", "EzXML", "JSON", "TOML", "UUIDs", "YAML"]
|
||||||
|
git-tree-sha1 = "f397fc8779cc53e4677c2708f3802c6996f28d00"
|
||||||
|
uuid = "db9b398d-9517-45f8-9a95-92af99003e0e"
|
||||||
|
version = "3.7.2"
|
||||||
|
|
||||||
[[deps.Serialization]]
|
[[deps.Serialization]]
|
||||||
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
||||||
version = "1.11.0"
|
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]]
|
[[deps.Sockets]]
|
||||||
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
|
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
@@ -860,6 +889,25 @@ version = "2.8.0"
|
|||||||
[deps.SpecialFunctions.weakdeps]
|
[deps.SpecialFunctions.weakdeps]
|
||||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
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.Statistics]]
|
||||||
deps = ["LinearAlgebra"]
|
deps = ["LinearAlgebra"]
|
||||||
git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0"
|
git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0"
|
||||||
@@ -896,17 +944,24 @@ version = "2.2.0"
|
|||||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
||||||
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
|
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.StringEncodings]]
|
||||||
|
deps = ["Libiconv_jll"]
|
||||||
|
git-tree-sha1 = "b765e46ba27ecf6b44faf70df40c57aa3a547dcb"
|
||||||
|
uuid = "69024149-9ee7-55f6-a4c4-859efe599b68"
|
||||||
|
version = "0.3.7"
|
||||||
|
|
||||||
[[deps.StringManipulation]]
|
[[deps.StringManipulation]]
|
||||||
deps = ["PrecompileTools"]
|
deps = ["PrecompileTools"]
|
||||||
git-tree-sha1 = "d05693d339e37d6ab134c5ab53c29fce5ee5d7d5"
|
git-tree-sha1 = "d05693d339e37d6ab134c5ab53c29fce5ee5d7d5"
|
||||||
uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
|
uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
|
|
||||||
[[deps.StringViews]]
|
|
||||||
git-tree-sha1 = "f2dcb92855b31ad92fe8f079d4f75ac57c93e4b8"
|
|
||||||
uuid = "354b36f9-a18e-4713-926e-db85100087ba"
|
|
||||||
version = "1.3.7"
|
|
||||||
|
|
||||||
[[deps.StructTypes]]
|
[[deps.StructTypes]]
|
||||||
deps = ["Dates", "UUIDs"]
|
deps = ["Dates", "UUIDs"]
|
||||||
git-tree-sha1 = "159331b30e94d7b11379037feeb9b690950cace8"
|
git-tree-sha1 = "159331b30e94d7b11379037feeb9b690950cace8"
|
||||||
@@ -1021,11 +1076,23 @@ git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7"
|
|||||||
uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60"
|
uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
|
|
||||||
|
[[deps.XML2_jll]]
|
||||||
|
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Zlib_jll"]
|
||||||
|
git-tree-sha1 = "3f3315d89fc954a28f5b471bce698ed6e27481be"
|
||||||
|
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
|
||||||
|
version = "2.15.3+0"
|
||||||
|
|
||||||
|
[[deps.YAML]]
|
||||||
|
deps = ["Base64", "Dates", "Printf", "StringEncodings"]
|
||||||
|
git-tree-sha1 = "a1c0c7585346251353cddede21f180b96388c403"
|
||||||
|
uuid = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
|
||||||
|
version = "0.4.16"
|
||||||
|
|
||||||
[[deps.YiemAgent]]
|
[[deps.YiemAgent]]
|
||||||
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs", "msghandler"]
|
deps = ["Base64", "CSV", "DataFrames", "DataStructures", "Dates", "GeneralUtils", "HTTP", "JSON", "LLMMCTS", "LibPQ", "NATS", "PrettyPrinting", "Random", "Revise", "SQLLLM", "Serialization", "URIs", "UUIDs"]
|
||||||
path = "."
|
path = "."
|
||||||
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
|
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
|
||||||
version = "0.4.0"
|
version = "0.7.2"
|
||||||
|
|
||||||
[[deps.Zlib_jll]]
|
[[deps.Zlib_jll]]
|
||||||
deps = ["Libdl"]
|
deps = ["Libdl"]
|
||||||
@@ -1049,14 +1116,6 @@ git-tree-sha1 = "011b0a7331b41c25524b64dc42afc9683ee89026"
|
|||||||
uuid = "a9144af2-ca23-56d9-984f-0d03f7b5ccf8"
|
uuid = "a9144af2-ca23-56d9-984f-0d03f7b5ccf8"
|
||||||
version = "1.0.21+0"
|
version = "1.0.21+0"
|
||||||
|
|
||||||
[[deps.msghandler]]
|
|
||||||
deps = ["Arrow", "Base64", "DataFrames", "Dates", "GeneralUtils", "HTTP", "JSON", "NATS", "PrettyPrinting", "Revise", "UUIDs"]
|
|
||||||
git-tree-sha1 = "db16f76f72bd4fa2a87e34ef47bb787204e1f888"
|
|
||||||
repo-rev = "main"
|
|
||||||
repo-url = "https://git.yiem.cc/ton/msghandler"
|
|
||||||
uuid = "f2724d33-f338-4a57-b9f8-1be882570d10"
|
|
||||||
version = "0.5.7"
|
|
||||||
|
|
||||||
[[deps.nghttp2_jll]]
|
[[deps.nghttp2_jll]]
|
||||||
deps = ["Artifacts", "Libdl"]
|
deps = ["Artifacts", "Libdl"]
|
||||||
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
|
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
|
||||||
|
|||||||
+8
-5
@@ -1,9 +1,10 @@
|
|||||||
name = "YiemAgent"
|
name = "YiemAgent"
|
||||||
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
|
uuid = "e012c34b-7f78-48e0-971c-7abb83b6f0a2"
|
||||||
version = "0.4.0"
|
version = "0.7.4"
|
||||||
authors = ["narawat lamaiin <narawat@outlook.com>"]
|
authors = ["narawat lamaiin <narawat@outlook.com>"]
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||||
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||||
@@ -18,17 +19,19 @@ PrettyPrinting = "54e16d92-306c-5ea0-a30b-337be88ac337"
|
|||||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||||
SQLLLM = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
|
SQLLLM = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
|
||||||
|
Serde = "db9b398d-9517-45f8-9a95-92af99003e0e"
|
||||||
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
||||||
URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
|
URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
|
||||||
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||||
msghandler = "f2724d33-f338-4a57-b9f8-1be882570d10"
|
|
||||||
|
|
||||||
[compat]
|
[compat]
|
||||||
|
Base64 = "1.11.0"
|
||||||
CSV = "0.10.15"
|
CSV = "0.10.15"
|
||||||
DataFrames = "1.7.0"
|
DataFrames = "1.7.0"
|
||||||
GeneralUtils = "0.4.9"
|
GeneralUtils = "0.5.1"
|
||||||
HTTP = "2.4.0"
|
HTTP = "2.4.0"
|
||||||
JSON = "1.6.1"
|
JSON = "1.6.1"
|
||||||
|
LLMMCTS = "0.1.5"
|
||||||
NATS = "0.1.0"
|
NATS = "0.1.0"
|
||||||
SQLLLM = "0.2.5"
|
SQLLLM = "0.2.8"
|
||||||
msghandler = "0.5.6"
|
Serde = "3.7.2"
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ Your name is $(newAgent.name). You are a helpful sommelier for website-based $(n
|
|||||||
# Available Actions
|
# Available Actions
|
||||||
|
|
||||||
- **CHAT_BOX** which you can use to talk with the user.
|
- **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 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 2: "Red or white wine, medium tannin, price under 700 USD"
|
||||||
- Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France
|
- Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"testingOrProduction": "testing",
|
"testingOrProduction": "testing",
|
||||||
"agentId": "2b74b87a-5413-4fe2-a4d3-405891051680",
|
"agentId": "2b74b87a-5413-4fe2-a4d3-405891051680",
|
||||||
"agentCentralConfigSubject": "/yiem/hq/agent/sommelier/backend/config/api/v1.1",
|
"agentCentralConfigSubject": "/yiem/hq/agent/sommelier/backend/config/api/v1.1",
|
||||||
|
"this_service_name": "agent_backend",
|
||||||
"this_service_input_channel": {
|
"this_service_input_channel": {
|
||||||
"mqtt": [
|
"mqtt": [
|
||||||
"/yiem/hq/agent/sommpanion/backend/db/api_v1"
|
"/yiem/hq/agent/sommpanion/backend/db/api_v1"
|
||||||
@@ -16,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
"agentRole": "sommelier",
|
"agentRole": "sommelier",
|
||||||
"organization": "yiem_hq",
|
"organization": "yiem_hq",
|
||||||
"externalService": {
|
"externalservice": {
|
||||||
"servicesloadbalancer": {
|
"servicesloadbalancer": {
|
||||||
"nats": "sommpanion.backend.servicesloadbalancer.v1.inbox"
|
"nats": "sommpanion.backend.servicesloadbalancer.v1.inbox"
|
||||||
},
|
},
|
||||||
@@ -35,15 +36,15 @@
|
|||||||
"description": "A database connection info for LibPQ client",
|
"description": "A database connection info for LibPQ client",
|
||||||
"url": "192.168.88.106:5432",
|
"url": "192.168.88.106:5432",
|
||||||
"dbname": "winedb",
|
"dbname": "winedb",
|
||||||
"user": "yiemtechnologies@gmail.com",
|
"user": "admin",
|
||||||
"password": "yiemtechnologies@Postgres_0.0"
|
"password": "admin@Sommpanion_0.0"
|
||||||
},
|
},
|
||||||
"sommpanion_vectordb" : {
|
"sommpanion_vectordb" : {
|
||||||
"description": "A wine database connection info for LibPQ client",
|
"description": "A wine database connection info for LibPQ client",
|
||||||
"url": "192.168.88.106:5433",
|
"url": "192.168.88.106:5433",
|
||||||
"dbname": "vectordb",
|
"dbname": "vectordb",
|
||||||
"user": "yiemtechnologies@gmail.com",
|
"user": "admin",
|
||||||
"password": "yiemtechnologies@Postgres_0.0"
|
"password": "admin@Sommpanion_0.0"
|
||||||
},
|
},
|
||||||
"fileserver": {
|
"fileserver": {
|
||||||
"description": "temporary file server",
|
"description": "temporary file server",
|
||||||
@@ -1,89 +1,56 @@
|
|||||||
using DataStructures
|
using HTTP, JSON, URIs, Random, PrettyPrinting, UUIDs, Dates, DataFrames, DataStructures
|
||||||
|
using GeneralUtils, SQLLLM, YiemAgent
|
||||||
|
|
||||||
function dictify2(x; keytype::Type=Any, sort_order::Union{Nothing, Vector}=nothing)
|
config = JSON.parsefile("./appconfig.json")
|
||||||
# Dict-like objects
|
host_url, _port = split(config["externalservice"]["sommpanion_db"]["url"], ':')
|
||||||
if x isa AbstractDict
|
port = parse(Int, _port)
|
||||||
out = OrderedDict{keytype, Any}()
|
dbname = "winedb"
|
||||||
|
user = config["externalservice"]["sommpanion_db"]["user"]
|
||||||
# 1. Process and normalize all keys from the input dictionary
|
password = config["externalservice"]["sommpanion_db"]["password"]
|
||||||
processed_dict = OrderedDict{keytype, Any}()
|
pg_conn_str = "host=$host_url port=$port dbname=$dbname user=$user password=$password"
|
||||||
for (k, v) in x
|
|
||||||
if keytype === String
|
|
||||||
newk = string(k)
|
|
||||||
elseif keytype === Symbol
|
|
||||||
newk = Symbol(string(k))
|
|
||||||
else
|
|
||||||
newk = k
|
|
||||||
end
|
|
||||||
processed_dict[newk] = dictify(v; keytype=keytype, sort_order=sort_order)
|
|
||||||
end
|
|
||||||
|
|
||||||
# 2. If a sort order is specified, apply it
|
function execute_sql_winedb(sql::T) where {T<:AbstractString}
|
||||||
if !isnothing(sort_order)
|
host_url, _port = split(config["externalservice"]["sommpanion_db"]["url"], ':')
|
||||||
# Normalize the sort_order elements to match the requested keytype
|
port = parse(Int, _port)
|
||||||
normalized_order = map(sort_order) do tk
|
dbname = "winedb"
|
||||||
if keytype === String
|
user = config["externalservice"]["sommpanion_db"]["user"]
|
||||||
return string(tk)
|
password = config["externalservice"]["sommpanion_db"]["password"]
|
||||||
elseif keytype === Symbol
|
db_connection = LibPQ.Connection("host=$host_url port=$port dbname=$dbname user=$user password=$password")
|
||||||
return Symbol(string(tk))
|
result = nothing
|
||||||
else
|
try
|
||||||
return tk
|
result = LibPQ.execute(db_connection, sql)
|
||||||
end
|
catch e
|
||||||
end
|
LibPQ.close(db_connection)
|
||||||
|
|
||||||
# First, insert keys that match the requested order
|
|
||||||
for target_key in normalized_order
|
|
||||||
if haskey(processed_dict, target_key)
|
|
||||||
out[target_key] = processed_dict[target_key]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Then, append any remaining keys that weren't in the sort_order
|
|
||||||
for (k, v) in processed_dict
|
|
||||||
if !haskey(out, k)
|
|
||||||
out[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# If no sort order is given, just use the processed dict
|
|
||||||
out = processed_dict
|
|
||||||
end
|
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
# Arrays / vectors: map elements recursively
|
|
||||||
elseif x isa AbstractArray
|
|
||||||
return [dictify(element; keytype=keytype, sort_order=sort_order) for element in x]
|
|
||||||
|
|
||||||
# Everything else: return as-is
|
|
||||||
else
|
|
||||||
return x
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
LibPQ.close(db_connection)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
function dict_to_string_html2(d::AbstractDict; indent_level=1, indent_str=" ")
|
|
||||||
lines = String[]
|
|
||||||
padding = indent_str ^ indent_level
|
|
||||||
|
|
||||||
# Sort keys for predictable, clean output
|
|
||||||
for k in keys(d)
|
|
||||||
v = d[k]
|
|
||||||
|
|
||||||
if v isa AbstractDict
|
|
||||||
# Open tag, recurse for children, then close tag
|
|
||||||
push!(lines, "$padding<$k>")
|
|
||||||
ind_level = indent_level + 1
|
|
||||||
push!(lines, dict_to_string_html(v; indent_level=ind_level, indent_str=indent_str))
|
|
||||||
push!(lines, "$padding</$k>")
|
|
||||||
else
|
|
||||||
# Leaf node: put key and value on a single line
|
|
||||||
push!(lines, "$padding<$k>$v</$k>")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return join(lines, "\n")
|
|
||||||
|
|
||||||
|
|
||||||
|
sql =
|
||||||
|
"""
|
||||||
|
SELECT T1.winery, T1.wine_name, T1.wine_id, T1.vintage, T1.region, T1.country, T1.wine_type, T1.grape, T1.serving_temperature, T1.sweetness, T1.intensity, T1.tannin, T1.acidity, T1.tasting_notes, T2.price, T2.currency, T1.image_url, T3.retailer_name, T3.retailer_id FROM "wine" AS T1 JOIN "retailer_wine" AS T2 ON T1.wine_id = T2.wine_id JOIN "retailer" AS T3 ON T2.retailer_id = T3.retailer_id WHERE T1.wine_name = 'Montrachet Grand Cru' AND T1.winery = 'Domaine Jacques Prieur' AND T3.retailer_name = 'Yiem Wines Ltd' AND T3.retailer_id = 'f54eab6b-7650-4448-b009-c53f3efbcc3b';
|
||||||
|
"""
|
||||||
|
|
||||||
|
textresult, sql_result_raw, _, _ = YiemAgent.SQLexecution(execute_sql_winedb, sql)
|
||||||
|
result_vec = GeneralUtils.dfToVectorDict(sql_result_raw)
|
||||||
|
|
||||||
|
for d in result_vec
|
||||||
|
wine_name = d["wine_name"]
|
||||||
|
image_url_json_str = d["image_url"]
|
||||||
|
image_url_json_obj = JSON.parse(image_url_json)
|
||||||
|
base_url = "http://192.168.88.106:8080/"
|
||||||
|
image_base64 =
|
||||||
|
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)
|
||||||
|
else
|
||||||
|
nothing
|
||||||
|
end
|
||||||
|
d["image"] = image_base64
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -91,3 +58,143 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using LibPQ
|
||||||
|
using Tables
|
||||||
|
|
||||||
|
"""
|
||||||
|
update_car_regions_one_by_one(conn::LibPQ.Connection, target_word::String)
|
||||||
|
|
||||||
|
Iterates through all rows in the 'car' table where the region is "German",
|
||||||
|
and updates them one-by-one to the `target_word`.
|
||||||
|
"""
|
||||||
|
function update_car_regions_one_by_one(pg_conn_str::String, replace_word::String , target_word::String)
|
||||||
|
conn = LibPQ.Connection(pg_conn_str)
|
||||||
|
# 1. Fetch the target rows. Assumes 'id' is the primary key.
|
||||||
|
# We select the ID to target rows individually during the update step.
|
||||||
|
select_query = "SELECT id FROM car WHERE region = '$replace_word';"
|
||||||
|
|
||||||
|
result = execute(conn, select_query)
|
||||||
|
rows = Tables.rows(result)
|
||||||
|
|
||||||
|
# 2. Prepare the update statement for execution reuse
|
||||||
|
# Using explicit types for parameter placeholders ($1, $2)
|
||||||
|
update_query = "UPDATE car SET region = \$1 WHERE id = \$2;"
|
||||||
|
|
||||||
|
println("Starting one-by-one update...")
|
||||||
|
updated_count = 0
|
||||||
|
|
||||||
|
# 3. Iterate through rows one-by-one
|
||||||
|
for row in rows
|
||||||
|
# LibPQ row values are accessed via properties or column names
|
||||||
|
row_id = row.id
|
||||||
|
|
||||||
|
# Execute the parameterized statement safely
|
||||||
|
execute(conn, update_query, [target_word, row_id])
|
||||||
|
updated_count += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
println("Successfully updated \$updated_count rows.")
|
||||||
|
return updated_count
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function generate_wine_retail_sql(conditions::Dict{String, Any})::String
|
||||||
|
# 1. Base SQL structure
|
||||||
|
base_query = """
|
||||||
|
SELECT
|
||||||
|
w.winery,
|
||||||
|
w.wine_name,
|
||||||
|
w.wine_id,
|
||||||
|
w.vintage,
|
||||||
|
w.region,
|
||||||
|
w.country,
|
||||||
|
w.wine_type,
|
||||||
|
w.grape,
|
||||||
|
w.serving_temperature,
|
||||||
|
w.sweetness,
|
||||||
|
w.intensity,
|
||||||
|
w.tannin,
|
||||||
|
w.acidity,
|
||||||
|
w.tasting_notes,
|
||||||
|
rw.price,
|
||||||
|
rw.currency,
|
||||||
|
w.image_url,
|
||||||
|
NULL AS retailer_name,
|
||||||
|
rw.retailer_id
|
||||||
|
FROM wine AS w
|
||||||
|
JOIN retailer_wine AS rw
|
||||||
|
ON w.wine_id = rw.wine_id
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 2. Dynamic WHERE Clause Builder
|
||||||
|
where_clauses = String[]
|
||||||
|
|
||||||
|
# Iterate over each table condition provided
|
||||||
|
for (table_name, table_conditions) in conditions
|
||||||
|
|
||||||
|
# Determine table alias
|
||||||
|
alias = if table_name == "wine"
|
||||||
|
"w"
|
||||||
|
elseif table_name == "retailer_wine"
|
||||||
|
"rw"
|
||||||
|
else
|
||||||
|
continue # Skip unsupported tables
|
||||||
|
end
|
||||||
|
|
||||||
|
# Process condition dictionaries
|
||||||
|
if isa(table_conditions, Dict) && !isempty(table_conditions)
|
||||||
|
|
||||||
|
for (column_name, filter_details) in table_conditions
|
||||||
|
|
||||||
|
if isa(filter_details, Dict) && haskey(filter_details, "operator")
|
||||||
|
op = filter_details["operator"]
|
||||||
|
raw_val = filter_details["value"]
|
||||||
|
|
||||||
|
# --- Value Type Handling ---
|
||||||
|
# Use tryparse instead of try/catch for cleaner, faster parsing
|
||||||
|
final_val = raw_val
|
||||||
|
|
||||||
|
if op in ("=", "<", ">", "<=", ">=")
|
||||||
|
str_val = string(raw_val)
|
||||||
|
num_val = tryparse(Float64, str_val)
|
||||||
|
|
||||||
|
if !isnothing(num_val)
|
||||||
|
final_val = isinteger(num_val) ? round(Int, num_val) : num_val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# --- SQL Formatting ---
|
||||||
|
if isa(final_val, Number)
|
||||||
|
clause = "$(alias).$(column_name) $(op) $(final_val)"
|
||||||
|
else
|
||||||
|
# Escape single quotes within string values
|
||||||
|
escaped_val = replace(string(final_val), "'" => "''")
|
||||||
|
clause = "$(alias).$(column_name) $(op) '$(escaped_val)'"
|
||||||
|
end
|
||||||
|
|
||||||
|
push!(where_clauses, clause)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# 3. Assemble Final Query
|
||||||
|
where_sql = isempty(where_clauses) ? "" : "WHERE " * join(where_clauses, " AND ")
|
||||||
|
|
||||||
|
return string(base_query, where_sql, ";")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+377
-615
File diff suppressed because it is too large
Load Diff
+716
-205
File diff suppressed because it is too large
Load Diff
+47
-116
@@ -16,83 +16,18 @@ mutable struct agentcontext
|
|||||||
insertSQLVectorDB::Function
|
insertSQLVectorDB::Function
|
||||||
similarSommelierDecision::Function
|
similarSommelierDecision::Function
|
||||||
insertSommelierDecision::Function
|
insertSommelierDecision::Function
|
||||||
|
find_related_tables_for_user_question::Function
|
||||||
|
pg_conn_str::String
|
||||||
|
agentconfig::AbstractDict
|
||||||
end
|
end
|
||||||
|
|
||||||
abstract type agent end
|
abstract type agent end
|
||||||
|
|
||||||
mutable struct companion <: agent
|
|
||||||
name::String # agent name
|
|
||||||
id::String # agent id
|
|
||||||
systemmsg::String # system message
|
|
||||||
tools::Dict # tools
|
|
||||||
maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized
|
|
||||||
chathistory::Vector{Dict{String, Any}}
|
|
||||||
memory::Dict{String, Any}
|
|
||||||
context::NamedTuple # NamedTuple of functions
|
|
||||||
llmFormatName::String
|
|
||||||
end
|
|
||||||
|
|
||||||
function companion(
|
|
||||||
context::agentcontext # NamedTuple of functions
|
|
||||||
;
|
|
||||||
name::String= "Assistant",
|
|
||||||
id::String= GeneralUtils.uuid4snakecase(),
|
|
||||||
maxHistoryMsg::Integer= 20,
|
|
||||||
chathistory::Vector{Dict{String, String}} = Vector{Dict{String, String}}(),
|
|
||||||
llmFormatName::String= "granite3",
|
|
||||||
systemmsg::String=
|
|
||||||
"""
|
|
||||||
Your name: $name
|
|
||||||
Your sex: Female
|
|
||||||
Your role: You are a helpful assistant.
|
|
||||||
You should follow the following guidelines:
|
|
||||||
- Focus on the latest conversation.
|
|
||||||
- Your like to be short and concise.
|
|
||||||
|
|
||||||
Let's begin!
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
|
|
||||||
tools = Dict( # update input format
|
|
||||||
"CHAT_BOX"=> Dict(
|
|
||||||
"description" => "- CHAT_BOX which you can use to talk with the user. The input is your intentions for the dialogue. Be specific.",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
""" Memory
|
|
||||||
Ref: Chat prompt format https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
|
|
||||||
NO "system" message in chathistory because I want to add it at the inference time
|
|
||||||
chathistory= [
|
|
||||||
Dict("name"=>"user", "text"=> "Wassup!", "timestamp"=> Dates.now()),
|
|
||||||
Dict("name"=>"assistant", "text"=> "Hi I'm your assistant.", "timestamp"=> Dates.now()),
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
memory = Dict{String, Any}(
|
|
||||||
"events"=> Vector{Dict{String, Any}}(),
|
|
||||||
"state"=> Dict{String, Any}(), # state of the agent
|
|
||||||
"recap"=> OrderedDict{String, Any}(), # recap summary of the conversation
|
|
||||||
)
|
|
||||||
|
|
||||||
newAgent = companion(
|
|
||||||
name,
|
|
||||||
id,
|
|
||||||
systemmsg,
|
|
||||||
tools,
|
|
||||||
maxHistoryMsg,
|
|
||||||
chathistory,
|
|
||||||
memory,
|
|
||||||
context,
|
|
||||||
llmFormatName
|
|
||||||
)
|
|
||||||
|
|
||||||
return newAgent
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
mutable struct sommelier <: agent
|
mutable struct sommelier <: agent
|
||||||
name::String # agent name
|
name::String # agent name
|
||||||
id::String # agent id
|
id::String # agent id
|
||||||
retailername::String
|
retailername::String
|
||||||
|
retailerid::String
|
||||||
tools::Dict
|
tools::Dict
|
||||||
maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized
|
maxHistoryMsg::Integer # e.g. 21th and earlier messages will get summarized
|
||||||
chathistory::Vector{Dict{String, Any}}
|
chathistory::Vector{Dict{String, Any}}
|
||||||
@@ -140,11 +75,12 @@ julia> agent = sommelier(context, name="WineExpert", id="123", retailername="MyW
|
|||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
function sommelier(
|
function sommelier(
|
||||||
context::agentcontext, # app context
|
context::agentcontext, # agent functions, db connect and other context
|
||||||
;
|
;
|
||||||
name::String= "Assistant",
|
name::String= "Assistant",
|
||||||
id::String= string(uuid4()),
|
id::String= string(uuid4()),
|
||||||
retailername::String= "retailer_name",
|
retailername::String= "not specified",
|
||||||
|
retailerid::String= "not specified",
|
||||||
maxHistoryMsg::Integer= 20,
|
maxHistoryMsg::Integer= 20,
|
||||||
chathistory::Vector{Dict{String, Any}} = Vector{Dict{String, Any}}(),
|
chathistory::Vector{Dict{String, Any}} = Vector{Dict{String, Any}}(),
|
||||||
llmFormatName::String= "granite3"
|
llmFormatName::String= "granite3"
|
||||||
@@ -205,17 +141,14 @@ function sommelier(
|
|||||||
memory = Dict{String, Any}(
|
memory = Dict{String, Any}(
|
||||||
"shortmem"=> OrderedDict{String, Any}(),
|
"shortmem"=> OrderedDict{String, Any}(),
|
||||||
"scratchpad"=> "",
|
"scratchpad"=> "",
|
||||||
"events"=> Vector{Dict{String, Any}}(),
|
|
||||||
"state"=> Dict{String, Any}(
|
|
||||||
),
|
|
||||||
"recap"=> OrderedDict{String, Any}(),
|
"recap"=> OrderedDict{String, Any}(),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
newAgent = sommelier(
|
newAgent = sommelier(
|
||||||
name,
|
name,
|
||||||
id,
|
id,
|
||||||
retailername,
|
retailername,
|
||||||
|
retailerid,
|
||||||
tools,
|
tools,
|
||||||
maxHistoryMsg,
|
maxHistoryMsg,
|
||||||
chathistory,
|
chathistory,
|
||||||
@@ -223,10 +156,9 @@ function sommelier(
|
|||||||
context,
|
context,
|
||||||
llmFormatName
|
llmFormatName
|
||||||
)
|
)
|
||||||
|
|
||||||
systemmsg =
|
systemmsg =
|
||||||
"""
|
"""
|
||||||
<store_policy>
|
# store_policy
|
||||||
- Generally speaking, the store inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know exactly until you check your inventory.
|
- Generally speaking, the store inventory has some wines from France, the United States, Australia, Spain, and Italy, but you won't know exactly until you check your inventory.
|
||||||
- If you found wines in the store's database, they are in stock.
|
- If you found wines in the store's database, they are in stock.
|
||||||
- You can only recommend wines that are currently in our inventory
|
- You can only recommend wines that are currently in our inventory
|
||||||
@@ -238,8 +170,8 @@ function sommelier(
|
|||||||
- Spicy foods should be paired only with light red wines.
|
- Spicy foods should be paired only with light red wines.
|
||||||
- We do not sell organic, sustainable, gluten-free, and sulfite-free wine. Inform the user imediately if they are looking for these types of wines. Do not sell our wines as such.
|
- We do not sell organic, sustainable, gluten-free, and sulfite-free wine. Inform the user imediately if they are looking for these types of wines. Do not sell our wines as such.
|
||||||
- Gift box, gift card, and custom messages are available. Inform the user to contact our sales team.
|
- Gift box, gift card, and custom messages are available. Inform the user to contact our sales team.
|
||||||
</store_policy>
|
|
||||||
<store_guidelines>
|
# store_guidelines
|
||||||
- Greeting the customer warmly by ask them how could you help. Do not ask any other questions during this greeting.
|
- Greeting the customer warmly by ask them how could you help. Do not ask any other questions during this greeting.
|
||||||
- Customer may provide images for you to look up.
|
- Customer may provide images for you to look up.
|
||||||
- Encourage the customer to explore different options and try new things.
|
- Encourage the customer to explore different options and try new things.
|
||||||
@@ -247,47 +179,46 @@ function sommelier(
|
|||||||
- Your store carries only wine.
|
- Your store carries only wine.
|
||||||
- Vintage 0 means non-vintage.
|
- Vintage 0 means non-vintage.
|
||||||
- Start searching the database as broadly as possible within the given information boundary to maximize the chances of finding. Avoid unnecessary parameters unless specified by the user. Refine the search subsequently.
|
- Start searching the database as broadly as possible within the given information boundary to maximize the chances of finding. Avoid unnecessary parameters unless specified by the user. Refine the search subsequently.
|
||||||
</store_guidelines>
|
- User usually ask for something similar. This means you should use the search term based on the profile they like.
|
||||||
<situation>
|
|
||||||
Your customer is coming into the store
|
# situation
|
||||||
</situation>
|
You are having conversation with a customer.
|
||||||
<your role>
|
|
||||||
Your name is $(newAgent.name). You are a helpful sommelier for website-based $(newAgent.retailername)'s wine store. You are working under your mentor supervision.
|
# your role
|
||||||
</your role>
|
Your name is $(newAgent.name). You are a helpful sommelier for website-based $(newAgent.retailername)'s wine store.
|
||||||
<objective>
|
|
||||||
1) Establish a connection with the customer by talking to them politely and showing your enthusiasm for their wine preferences.
|
# objective
|
||||||
2) Provide relevant information and guide them to select the best wines only from your store's inventory that align with their preferences.
|
- Establish a connection with the customer by talking to them politely and showing your enthusiasm for their wine preferences.
|
||||||
</objective>
|
- Provide relevant information and guide them to select the best wines only from your store's inventory that align with their preferences.
|
||||||
<your responsibility includes>
|
|
||||||
1) According to the store's policy and guidelines, make an informed decision about what you need to do to achieve the objective
|
# your responsibility includes
|
||||||
2) Keep the conversation with the customer going smoothly
|
- According to the store's policy and guidelines, and make an informed decision about what available_actions you need to use to achieve the objective.
|
||||||
2) Obey your mentor's suggestions.
|
- Keep the conversation with the customer going smoothly
|
||||||
</your responsibility includes>
|
|
||||||
<your responsibility does NOT includes>
|
# your responsibility does NOT includes
|
||||||
1) Requesting the user to place an order, make a purchase, or confirm the order. These are the job of our sales team at the store.
|
- Requesting the user to place an order, make a purchase, or confirm the order. These are the job of our sales team at the store.
|
||||||
2) Processing sales orders or engaging in any other sales-related activities. These are the job of our sales team at the store.
|
- Processing sales orders or engaging in any other sales-related activities. These are the job of our sales team at the store.
|
||||||
3) Answering questions or offering additional services beyond those related to your store's wine recommendations such as discounts, quantity, rewards programs, promotions, delivery options, shipping, boxes, gift wrapping, packaging, personalized messages or something similar. These are the job of our sales team at the store.
|
- Answering questions or offering additional services beyond those related to your store's wine recommendations such as discounts, quantity, rewards programs, promotions, delivery options, shipping, boxes, gift wrapping, packaging, personalized messages or something similar. These are the job of our sales team at the store.
|
||||||
</your responsibility does NOT includes>
|
|
||||||
<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 and rationale. Be specific.
|
1) "plan", Based on the current situation, state a complete action plan to complete the task and rationale. Be specific.
|
||||||
2) action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the available_actions name
|
2) "action_name", (Typically corresponds to the execution of the first step in your plan) Can be one of the available_actions name
|
||||||
3) action_input: The input to the action you are about to perform according to your plan.
|
3) "action_input", The input to the action you are about to perform according to your plan.
|
||||||
After the action is executed you gets "action_result". It is the output from the action you selected.
|
After the action is executed you gets "action_result". It is the output from the action you selected.
|
||||||
</you should then respond to the user with interleaving plan, action_name, action_input>
|
|
||||||
<you should only respond in JSON format as described below>
|
# you should only respond in JSON format as described below (not Markdown format)
|
||||||
"plan": "...",
|
"plan": "...",
|
||||||
"action_name": "...",
|
"action_name": "...",
|
||||||
"action_input": "..."
|
"action_input": "..."
|
||||||
</you should only respond in JSON format as described below>
|
|
||||||
<available_actions>
|
# available actions
|
||||||
- CHAT_BOX which you can use to talk with the user.
|
"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 strictly supported search term including: retailer_name, wine price, winery, name, vintage, region, country, type of wine, 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 1: "Dry, full-bodied red wine from Burgundy, France. Grape varietal could be Merlot or Syrah. price 100 to 1000 USD."
|
||||||
Example query 2: "Red or white wine, medium tannin, price under 700 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
|
Example query 3: "white wine from Tuscany, Italy or Bordeaux, France
|
||||||
- PRESENT_WINE_GUIDELINE which you can use to check the store guidelines about how to present wines you have found to the user. The input is "nothing" keyword. The output is the guidelines that you can follow.
|
"WINE_PRESENTATION_GUIDELINE", which you can use to check the store guidelines about how to present wines you have found to the user. The input is "nothing" keyword. The output is the guidelines that you can follow.
|
||||||
- END_CONVER_GUIDELINE which you can use to check the store guidelines about how to end the conversation with the user. The input is "nothing" keyword. The output is the guidelines that you can follow.
|
"END_CONVER_GUIDELINE", which you can use to check the store guidelines about how to end the conversation with the user. The input is "nothing" keyword. The output is the guidelines that you can follow.
|
||||||
</available_actions>
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
system_msg = Dict(
|
system_msg = Dict(
|
||||||
|
|||||||
+5
-5
@@ -95,15 +95,15 @@ end
|
|||||||
"""
|
"""
|
||||||
function addNewMessage(a::T1, name::String, userinput::T2;
|
function addNewMessage(a::T1, name::String, userinput::T2;
|
||||||
maximumMsg::Integer=30) where {T1<:agent, T2<:AbstractDict}
|
maximumMsg::Integer=30) where {T1<:agent, T2<:AbstractDict}
|
||||||
if name ∉ ["system", "user", "assistant"] # guard against typo
|
# if name ∉ ["system", "user", "assistant"] # guard against typo
|
||||||
error("name is not in agent.availableRole $(@__LINE__)")
|
# error("name is not in agent.availableRole $(@__LINE__)")
|
||||||
end
|
# end
|
||||||
|
|
||||||
#TODO summarize the oldest 10 message
|
#TODO summarize the oldest 10 message
|
||||||
if length(a.chathistory) > maximumMsg
|
if length(a.chathistory) > maximumMsg
|
||||||
summarize(a.chathistory)
|
summarize(a.chathistory)
|
||||||
else
|
else
|
||||||
userinput["timestamp"] = Dates.now()
|
# userinput["timestamp"] = Dates.now()
|
||||||
push!(a.chathistory, userinput)
|
push!(a.chathistory, userinput)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -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"
|
# timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"])\n"
|
||||||
# elseif event["action_name"] == "CHECKINVENTORY" && event["observation"] === nothing
|
# 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"
|
# 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"
|
timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"]), observation: $(event["observation"])\\n"
|
||||||
else
|
else
|
||||||
timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"])\\n"
|
timeline *= "Event_$i $(event["subject"])> action_name: $(event["action_name"]), action_input: $(event["action_input"])\\n"
|
||||||
|
|||||||
+2
-2
@@ -128,7 +128,7 @@ systemmsg =
|
|||||||
|
|
||||||
# Available Actions
|
# Available Actions
|
||||||
- **CHAT_BOX** which you can use to talk with the user.
|
- **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 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 2: "Red or white wine, medium tannin, price under 700 USD"
|
||||||
- Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France
|
- Example query 3: "white wine, region: Tuscany or Bordeaux, country: Italy or France
|
||||||
@@ -157,7 +157,7 @@ openai_msg = Dict(
|
|||||||
"content" => [
|
"content" => [
|
||||||
Dict("type" => "text", "text" =>
|
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>"
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
+308
-198
@@ -2,200 +2,236 @@ using JSON, Dates, UUIDs, PrettyPrinting, LibPQ, Base64, DataFrames, DataStructu
|
|||||||
NATS, Base.Threads
|
NATS, Base.Threads
|
||||||
using YiemAgent, GeneralUtils, msghandler
|
using YiemAgent, GeneralUtils, msghandler
|
||||||
|
|
||||||
|
function text2text_instruct_llm(sender_id::String, openai_msg::Dict{String, Any})
|
||||||
|
payloads = [("msg", openai_msg, "dictionary")] # List of tuples
|
||||||
|
_, msg_envelope_json_str = msghandler.smartpack(
|
||||||
|
config["externalservice"]["servicesloadbalancer"]["nats"],
|
||||||
|
payloads;
|
||||||
|
sender_id=sender_id,
|
||||||
|
msg_purpose="text2text",
|
||||||
|
broker_url=config["nats_server_info"]["url"],
|
||||||
|
fileserver_url=config["externalservice"]["fileserver"]["url"])
|
||||||
|
|
||||||
function text2text_instruct_llm(sender_id::String, openai_msg::Dict{String, Any})
|
reply = NATS.request(agent_conn,
|
||||||
payloads = [("msg", openai_msg, "dictionary")] # List of tuples
|
config["externalservice"]["servicesloadbalancer"]["nats"],
|
||||||
_, msg_envelope_json_str = msghandler.smartpack(
|
msg_envelope_json_str, timeout=120)
|
||||||
config["externalService"]["servicesloadbalancer"]["nats"],
|
|
||||||
payloads;
|
|
||||||
sender_id=sender_id,
|
|
||||||
msg_purpose="text2text",
|
|
||||||
broker_url=config["nats_server_info"]["url"],
|
|
||||||
fileserver_url=config["externalService"]["fileserver"]["url"])
|
|
||||||
|
|
||||||
reply = NATS.request(agent_conn,
|
incoming_env_json_str = String(reply.payload)
|
||||||
config["externalService"]["servicesloadbalancer"]["nats"],
|
incoming_env = msghandler.smartunpack(incoming_env_json_str)
|
||||||
msg_envelope_json_str, timeout=120)
|
_llm_response = incoming_env["payloads"][1][2]
|
||||||
|
llm_response = _llm_response["choices"][1]["message"]["content"]
|
||||||
incoming_env_json_str = String(reply.payload)
|
return llm_response
|
||||||
incoming_env = msghandler.smartunpack(incoming_env_json_str)
|
|
||||||
_llm_response = incoming_env["payloads"][1][2]
|
|
||||||
llm_response = _llm_response["choices"][1]["message"]["content"]
|
|
||||||
return llm_response
|
|
||||||
end
|
|
||||||
|
|
||||||
#TESTING get text embedding from a LLM service
|
|
||||||
function get_embedding(text::AbstractArray{String})
|
|
||||||
documents_dict = Dict("documents" => text)
|
|
||||||
payloads = [("documents", documents_dict, "dictionary")]
|
|
||||||
_, msg_envelope_json_str = msghandler.smartpack(
|
|
||||||
config["externalService"]["servicesloadbalancer"]["nats"],
|
|
||||||
payloads;
|
|
||||||
msg_purpose="embedding",
|
|
||||||
broker_url=config["nats_server_info"]["url"],
|
|
||||||
fileserver_url=config["externalService"]["fileserver"]["url"])
|
|
||||||
|
|
||||||
reply = NATS.request(agent_conn,
|
|
||||||
config["externalService"]["servicesloadbalancer"]["nats"],
|
|
||||||
msg_envelope_json_str, timeout=120)
|
|
||||||
incoming_env_json_str = String(reply.payload)
|
|
||||||
incoming_env = msghandler.smartunpack(incoming_env_json_str)
|
|
||||||
embedding_response = incoming_env["payloads"][1][2]
|
|
||||||
|
|
||||||
return embedding_response
|
|
||||||
end
|
|
||||||
|
|
||||||
#TESTING
|
|
||||||
function execute_sql_winedb(config::JSON.Object, sql::T) where {T<:AbstractString}
|
|
||||||
host_url, _port = split(config["externalservice"]["sommpanion_db"]["url"], ':')
|
|
||||||
port = parse(Int, _port)
|
|
||||||
dbname = "winedb"
|
|
||||||
user = config["externalservice"]["sommpanion_db"]["user"]
|
|
||||||
password = config["externalservice"]["sommpanion_db"]["password"]
|
|
||||||
db_connection = LibPQ.Connection("host=$host_url port=$port dbname=$dbname user=$user password=$password")
|
|
||||||
result = LibPQ.execute(db_connection, sql)
|
|
||||||
LibPQ.close(db_connection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
#TESTING
|
|
||||||
function similar_sql_vectordb(query; maxdistance::Integer=100)
|
|
||||||
tablename = "sqlllm_decision_repository"
|
|
||||||
# get embedding of the query
|
|
||||||
df = find_similar_text_from_vectordb(query, tablename,
|
|
||||||
"function_input_embedding", execute_sql_vectordb)
|
|
||||||
# println(df[1, [:id, :function_output]])
|
|
||||||
row, col = size(df)
|
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
|
||||||
# distance = 100 # CHANGE this is for testing only
|
|
||||||
if row != 0 && distance < maxdistance
|
|
||||||
# if there is usable SQL, return it.
|
|
||||||
output_b64 = df[1, :function_output_base64] # pick the closest match
|
|
||||||
output_str = String(base64decode(output_b64))
|
|
||||||
rowid = df[1, :id]
|
|
||||||
println("\n~~~ found similar sql. row id $rowid, distance $distance ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
|
||||||
return (dict=output_str, distance=distance)
|
|
||||||
else
|
|
||||||
println("\n~~~ similar sql not found, max distance $maxdistance ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
|
||||||
return (dict=nothing, distance=nothing)
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
#TESTING
|
""" get a single text embedding from a LLM service
|
||||||
function insert_sql_vectordb(query::T1, SQL::T2; maxdistance::Integer=3) where {T1<:AbstractString, T2<:AbstractString}
|
Example
|
||||||
tablename = "sqlllm_decision_repository"
|
text = ["hello"]
|
||||||
# get embedding of the query
|
embedding = get_embedding(text)
|
||||||
# query = state[:thoughtHistory][:question]
|
"""
|
||||||
df = find_similar_text_from_vectordb(query, tablename,
|
function get_embedding(text::AbstractArray{String})
|
||||||
"function_input_embedding", execute_sql_vectordb)
|
documents_dict = Dict("documents" => text)
|
||||||
row, col = size(df)
|
payloads = [("documents", documents_dict, "dictionary")]
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
_, msg_envelope_json_str = msghandler.smartpack(
|
||||||
if row == 0 || distance > maxdistance # no close enough SQL stored in the database
|
config["externalservice"]["servicesloadbalancer"]["nats"],
|
||||||
_query_embedding = get_embedding([query])[1]
|
payloads;
|
||||||
query_embedding = _query_embedding["data"][1]["embedding"]
|
msg_purpose="embedding",
|
||||||
query = replace(query, "'" => "")
|
broker_url=config["nats_server_info"]["url"],
|
||||||
sql_base64 = base64encode(SQL)
|
fileserver_url=config["externalservice"]["fileserver"]["url"])
|
||||||
sql_ = replace(SQL, "'" => "")
|
|
||||||
|
|
||||||
sql = """
|
reply = NATS.request(agent_conn,
|
||||||
INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$query', '$sql_', '$sql_base64', '$query_embedding');
|
config["externalservice"]["servicesloadbalancer"]["nats"],
|
||||||
"""
|
msg_envelope_json_str, timeout=120)
|
||||||
# println("\n~~~ added new decision to vectorDB ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
incoming_env_json_str = String(reply.payload)
|
||||||
# println(sql)
|
incoming_env = msghandler.smartunpack(incoming_env_json_str)
|
||||||
_ = execute_sql_vectordb(sql)
|
embedding_response = incoming_env["payloads"][1][2]
|
||||||
|
|
||||||
|
return embedding_response
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
#TESTING
|
""" sql = "SELECT * FROM wine;"
|
||||||
function execute_sql_vectordb(sql::T) where {T<:AbstractString}
|
result = execute_sql_winedb(sql)
|
||||||
host_url, _port = split(config["SQLVectorDB"]["url"], ':')
|
"""
|
||||||
port = parse(Int, _port)
|
function execute_sql_winedb(sql::T) where {T<:AbstractString}
|
||||||
dbname = config[:externalservice][:SQLVectorDB][:dbname]
|
host_url, _port = split(config["externalservice"]["sommpanion_db"]["url"], ':')
|
||||||
user = config[:externalservice][:SQLVectorDB][:user]
|
port = parse(Int, _port)
|
||||||
password = config[:externalservice][:SQLVectorDB][:password]
|
dbname = "winedb"
|
||||||
DBconnection = LibPQ.Connection("host=$host_url port=$port dbname=$dbname user=$user password=$password")
|
user = config["externalservice"]["sommpanion_db"]["user"]
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
password = config["externalservice"]["sommpanion_db"]["password"]
|
||||||
close(DBconnection)
|
db_connection = LibPQ.Connection("host=$host_url port=$port dbname=$dbname user=$user password=$password")
|
||||||
return result
|
result = nothing
|
||||||
end
|
try
|
||||||
|
result = LibPQ.execute(db_connection, sql)
|
||||||
|
catch e
|
||||||
function similar_sommelier_decision(recentevents::T1; maxdistance::Integer=3
|
LibPQ.close(db_connection)
|
||||||
)::Union{AbstractDict, Nothing} where {T1<:AbstractString}
|
end
|
||||||
tablename = "sommelier_decision_repository"
|
|
||||||
# find similar
|
|
||||||
println("\n~~~ search vectorDB for this: $recentevents ", @__FILE__, " ", @__LINE__)
|
|
||||||
df = find_similar_text_from_vectordb(recentevents, tablename,
|
|
||||||
"function_input_embedding", execute_sql_vectordb)
|
|
||||||
row, col = size(df)
|
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
|
||||||
if row != 0 && distance < maxdistance
|
|
||||||
# if there is usable decision, return it.
|
|
||||||
rowid = df[1, :id]
|
|
||||||
println("\n~~~ found similar decision. row id $rowid, distance $distance ", @__FILE__, " ", @__LINE__)
|
|
||||||
output_b64 = df[1, :function_output_base64] # pick the closest match
|
|
||||||
_output_str = String(base64decode(output_b64))
|
|
||||||
output = copy(JSON.read(_output_str))
|
|
||||||
return output
|
|
||||||
else
|
|
||||||
println("\n~~~ similar decision not found, max distance $maxdistance ", @__FILE__, " ", @__LINE__)
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#TESTING
|
|
||||||
function find_similar_text_from_vectordb(text::T1, tablename::T2, embeddingColumnName::T3,
|
|
||||||
vectorDB::Function; limit::Integer=1
|
|
||||||
)::DataFrame where {T1<:AbstractString, T2<:AbstractString, T3<:AbstractString}
|
|
||||||
# get embedding from LLM service
|
|
||||||
_embedding = get_embedding([text])[1]
|
|
||||||
embedding = _embedding["data"][1]["embedding"]
|
|
||||||
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
|
|
||||||
sql = """
|
|
||||||
SELECT *, $embeddingColumnName <-> '$embedding' as distance
|
|
||||||
FROM $tablename
|
|
||||||
ORDER BY distance LIMIT $limit;
|
|
||||||
"""
|
|
||||||
response = vectorDB(sql)
|
|
||||||
df = DataFrame(response)
|
|
||||||
return df
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function insert_sommelier_decision(recentevents::T1, decision::T2; maxdistance::Integer=5
|
|
||||||
) where {T1<:AbstractString, T2<:AbstractDict}
|
|
||||||
tablename = "sommelier_decision_repository"
|
|
||||||
# find similar
|
|
||||||
df = find_similar_text_from_vectordb(recentevents, tablename,
|
|
||||||
"function_input_embedding", execute_sql_vectordb)
|
|
||||||
row, col = size(df)
|
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
|
||||||
if row == 0 || distance > maxdistance # no close enough SQL stored in the database
|
|
||||||
_embedding = get_embedding([recentevents])[1]
|
|
||||||
recentevents_embedding = _embedding["data"][1]["embedding"]
|
|
||||||
recentevents = replace(recentevents, "'" => "")
|
|
||||||
decision_json = JSON.json(decision)
|
|
||||||
decision_base64 = base64encode(decision_json)
|
|
||||||
decision = replace(decision_json, "'" => "")
|
|
||||||
|
|
||||||
sql =
|
LibPQ.close(db_connection)
|
||||||
"""
|
return result
|
||||||
INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$recentevents', '$decision', '$decision_base64', '$recentevents_embedding');
|
|
||||||
"""
|
|
||||||
println("\n~~~ added new decision to vectorDB ", @__FILE__, " ", @__LINE__)
|
|
||||||
println(sql)
|
|
||||||
_ = execute_sql_vectordb(sql)
|
|
||||||
else
|
|
||||||
println("~~~ similar decision previously cached, distance $distance ", @__FILE__, " ", @__LINE__)
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
""" find similar sql from vector database
|
||||||
|
sql = "SELECT * FROM wine;"
|
||||||
|
result, distance = similar_sql_vectordb(sql)
|
||||||
|
"""
|
||||||
|
function similar_sql_vectordb(sql::T; maxdistance::Number=0.2) where {T<:AbstractString}
|
||||||
|
tablename = "sqlllm_decision_repository"
|
||||||
|
# get embedding of the query
|
||||||
|
df = find_similar_text_from_vectordb(sql, tablename,
|
||||||
|
"function_input_embedding", execute_sql_vectordb)
|
||||||
|
# println(df[1, [:id, :function_output]])
|
||||||
|
row, col = size(df)
|
||||||
|
distance = row == 0 ? Inf : df[1, :distance]
|
||||||
|
if row != 0 && distance < maxdistance
|
||||||
|
# if there is usable SQL, return it.
|
||||||
|
output_b64 = df[1, :function_output_base64] # pick the closest match
|
||||||
|
output_str = String(base64decode(output_b64))
|
||||||
|
rowid = df[1, :id]
|
||||||
|
println("\n--| similar sql found. row id $rowid, distance $distance ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
pprintln(output_str)
|
||||||
|
return (result=output_str, distance=distance)
|
||||||
|
else
|
||||||
|
println("\n--| similar sql not found, max distance $maxdistance ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
return (result=nothing, distance=nothing)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
""" insert query and sql into vector database
|
||||||
|
query = "get all wines from wine table"
|
||||||
|
sql = "SELECT * FROM wine;"
|
||||||
|
insert_sql_vectordb(query, sql)
|
||||||
|
"""
|
||||||
|
function insert_sql_vectordb(query::T1, SQL::T2; maxdistance::Number=3
|
||||||
|
) where {T1<:AbstractString, T2<:AbstractString}
|
||||||
|
|
||||||
|
tablename = "sqlllm_decision_repository"
|
||||||
|
# get embedding of the query
|
||||||
|
# query = state[:thoughtHistory][:question]
|
||||||
|
df = find_similar_text_from_vectordb(query, tablename,
|
||||||
|
"function_input_embedding", execute_sql_vectordb)
|
||||||
|
row, col = size(df)
|
||||||
|
distance = row == 0 ? Inf : df[1, :distance]
|
||||||
|
if row == 0 || distance > maxdistance # no close enough SQL stored in the database
|
||||||
|
_query_embedding = get_embedding([query])
|
||||||
|
_query_embedding = GeneralUtils.dictify(_query_embedding)
|
||||||
|
# println("\n--- _query_embedding() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
# println(_query_embedding)
|
||||||
|
# println("---\n")
|
||||||
|
query_embedding = _query_embedding["data"][1]["embedding"]
|
||||||
|
query = replace(query, "'" => "")
|
||||||
|
sql_base64 = base64encode(SQL)
|
||||||
|
sql_ = replace(SQL, "'" => "")
|
||||||
|
|
||||||
|
sql =
|
||||||
|
"""
|
||||||
|
INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$query', '$sql_', '$sql_base64', '$query_embedding');
|
||||||
|
"""
|
||||||
|
# println("\n--| added new decision to vectorDB ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
# println(sql)
|
||||||
|
_ = execute_sql_vectordb(sql)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
""" execute sql against vectordb
|
||||||
|
sql = "SELECT * FROM wine;"
|
||||||
|
result = execute_sql_vectordb(sql)
|
||||||
|
"""
|
||||||
|
function execute_sql_vectordb(sql::T) where {T<:AbstractString}
|
||||||
|
host_url, _port = split(config["externalservice"]["sommpanion_vectordb"]["url"], ':')
|
||||||
|
port = parse(Int, _port)
|
||||||
|
dbname = config["externalservice"]["sommpanion_vectordb"]["dbname"]
|
||||||
|
user = config["externalservice"]["sommpanion_vectordb"]["user"]
|
||||||
|
password = config["externalservice"]["sommpanion_vectordb"]["password"]
|
||||||
|
DBconnection = LibPQ.Connection("host=$host_url port=$port dbname=$dbname user=$user password=$password")
|
||||||
|
result = LibPQ.execute(DBconnection, sql)
|
||||||
|
close(DBconnection)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
""" search similar decision llm made from vectordb
|
||||||
|
"""
|
||||||
|
function similar_sommelier_decision(recentevents::T1; maxdistance::Integer=3
|
||||||
|
)::Union{AbstractDict, Nothing} where {T1<:AbstractString}
|
||||||
|
|
||||||
|
tablename = "sommelier_decision_repository"
|
||||||
|
# find similar
|
||||||
|
df = find_similar_text_from_vectordb(recentevents, tablename,
|
||||||
|
"function_input_embedding", execute_sql_vectordb)
|
||||||
|
row, col = size(df)
|
||||||
|
distance = row == 0 ? Inf : df[1, :distance]
|
||||||
|
if row != 0 && distance < maxdistance
|
||||||
|
# if there is usable decision, return it.
|
||||||
|
rowid = df[1, :id]
|
||||||
|
println("\n--| found similar decision. row id $rowid, distance $distance ", @__FILE__, " ", @__LINE__)
|
||||||
|
output_b64 = df[1, :function_output_base64] # pick the closest match
|
||||||
|
_output_str = String(base64decode(output_b64))
|
||||||
|
output = copy(JSON.read(_output_str))
|
||||||
|
return output
|
||||||
|
else
|
||||||
|
println("\n--| similar decision not found, max distance $maxdistance ", @__FILE__, " ", @__LINE__)
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
""" search similar text from vectordb
|
||||||
|
"""
|
||||||
|
function find_similar_text_from_vectordb(text::T1, tablename::T2, embeddingColumnName::T3,
|
||||||
|
vectorDB::Function; limit::Integer=1
|
||||||
|
)::DataFrame where {T1<:AbstractString, T2<:AbstractString, T3<:AbstractString}
|
||||||
|
# get embedding from LLM service
|
||||||
|
_embedding = get_embedding([text])
|
||||||
|
_embedding = _embedding["data"][1]["embedding"]
|
||||||
|
_embedding = "$_embedding"
|
||||||
|
|
||||||
|
embedding = _embedding[4:end]
|
||||||
|
|
||||||
|
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
|
||||||
|
sql = """
|
||||||
|
SELECT *, $embeddingColumnName <-> '$embedding' as distance
|
||||||
|
FROM $tablename
|
||||||
|
ORDER BY distance LIMIT $limit;
|
||||||
|
"""
|
||||||
|
response = vectorDB(sql)
|
||||||
|
df = DataFrame(response)
|
||||||
|
|
||||||
|
return df
|
||||||
|
end
|
||||||
|
|
||||||
|
""" insert decision llm made to vectordb
|
||||||
|
"""
|
||||||
|
function insert_sommelier_decision(recentevents::T1, decision::T2; maxdistance::Integer=5
|
||||||
|
) where {T1<:AbstractString, T2<:AbstractDict}
|
||||||
|
tablename = "sommelier_decision_repository"
|
||||||
|
# find similar
|
||||||
|
df = find_similar_text_from_vectordb(recentevents, tablename,
|
||||||
|
"function_input_embedding", execute_sql_vectordb)
|
||||||
|
row, col = size(df)
|
||||||
|
distance = row == 0 ? Inf : df[1, :distance]
|
||||||
|
if row == 0 || distance > maxdistance # no close enough SQL stored in the database
|
||||||
|
_embedding = get_embedding([recentevents])[1]
|
||||||
|
recentevents_embedding = _embedding["data"][1]["embedding"]
|
||||||
|
recentevents = replace(recentevents, "'" => "")
|
||||||
|
decision_json = JSON.json(decision)
|
||||||
|
decision_base64 = base64encode(decision_json)
|
||||||
|
decision = replace(decision_json, "'" => "")
|
||||||
|
|
||||||
|
sql =
|
||||||
|
"""
|
||||||
|
INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$recentevents', '$decision', '$decision_base64', '$recentevents_embedding');
|
||||||
|
"""
|
||||||
|
println("\n--| added new decision to vectorDB ", @__FILE__, " ", @__LINE__)
|
||||||
|
println(sql)
|
||||||
|
_ = execute_sql_vectordb(sql)
|
||||||
|
else
|
||||||
|
println("--| similar decision previously cached, distance $distance ", @__FILE__, " ", @__LINE__)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
config = JSON.parsefile("./appconfig.json")
|
||||||
sessionId = "0"
|
sessionId = "0"
|
||||||
backend_session_topic = "sommpanion.backend.agentbackend.v1.inbox.$sessionId"
|
backend_session_topic = "sommpanion.testsubject"
|
||||||
|
|
||||||
config = JSON.parsefile("./dummy_config.json")
|
|
||||||
agent_ch = Channel(8)
|
agent_ch = Channel(8)
|
||||||
agent_conn = NATS.connect(config["nats_server_info"]["url"])
|
agent_conn = NATS.connect(config["nats_server_info"]["url"])
|
||||||
|
|
||||||
sub2 = NATS.subscribe(agent_conn, backend_session_topic) do msg
|
sub2 = NATS.subscribe(agent_conn, backend_session_topic) do msg
|
||||||
put!(agent_ch, msg)
|
put!(agent_ch, msg)
|
||||||
end
|
end
|
||||||
@@ -210,32 +246,34 @@ agent_context = YiemAgent.agentcontext(
|
|||||||
insert_sommelier_decision
|
insert_sommelier_decision
|
||||||
)
|
)
|
||||||
|
|
||||||
# can't instantiate
|
# can't instantiate
|
||||||
agent = YiemAgent.sommelier(
|
agent = YiemAgent.sommelier(
|
||||||
agent_context;
|
agent_context;
|
||||||
name="Janie",
|
name="Janie",
|
||||||
id=sessionId, # agent instance id
|
id=sessionId, # agent instance id
|
||||||
retailername="Yiem",
|
retailername="Yiem Wine Ltd.",
|
||||||
llmFormatName=""
|
llmFormatName=""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 1. Read local file and encode to base64 string
|
|
||||||
image1_path = "test/large_image.png"
|
image1_path = "test/large_image.png"
|
||||||
image1_bytes = read(image1_path)
|
image1_bytes = read(image1_path)
|
||||||
image1_base64_string = base64encode(image1_bytes)
|
image1_base64_string = base64encode(image1_bytes)
|
||||||
|
|
||||||
# 2. Match the MIME type according to your file extension (e.g., png, jpeg)
|
|
||||||
mime_type = "image/png"
|
mime_type = "image/png"
|
||||||
data1_uri = "data:$(mime_type);base64,$(image1_base64_string)"
|
data1_uri = "data:$(mime_type);base64,$(image1_base64_string)"
|
||||||
|
|
||||||
|
# 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
|
# 3. Construct payload with the Data URI
|
||||||
usermsg = Dict{String, Any}(
|
message = Dict(
|
||||||
"role" => "user",
|
"role" => "user",
|
||||||
"content" => [
|
"content" => [
|
||||||
Dict("type" => "text", "text" => "รู้จักไวน์ที่อยู่ในรูปมั้ย"),
|
Dict("type" => "text", "text" => "Do you know type of wine in the image?"),
|
||||||
Dict(
|
Dict(
|
||||||
"type" => "image_url",
|
"type" => "image_url",
|
||||||
"image_url" => Dict("url" => data1_uri)
|
"image_url" => Dict("url" => data1_uri)
|
||||||
@@ -243,8 +281,80 @@ usermsg = Dict{String, Any}(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
result = YiemAgent.conversation(agent; userinput=usermsg)
|
result = YiemAgent.conversation(agent; userinput=message)
|
||||||
println(result)
|
println("\n$result")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# message = Dict(
|
||||||
|
# "role" => "user",
|
||||||
|
# "content" => [
|
||||||
|
# Dict("type" => "text", "text" =>
|
||||||
|
# "
|
||||||
|
# เป็นงานเลี้ยงทั่วไป
|
||||||
|
# "),
|
||||||
|
# ]
|
||||||
|
# )
|
||||||
|
|
||||||
|
# result = YiemAgent.conversation(agent; userinput=message)
|
||||||
|
# println("\n$result")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# message = Dict(
|
||||||
|
# "role" => "user",
|
||||||
|
# "content" => [
|
||||||
|
# Dict("type" => "text", "text" => "no thanks. that's all"),
|
||||||
|
# ]
|
||||||
|
# )
|
||||||
|
|
||||||
|
# result = YiemAgent.conversation(agent; userinput=message)
|
||||||
|
# println("\n$result")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# message = Dict(
|
||||||
|
# "role" => "user",
|
||||||
|
# "content" => [
|
||||||
|
# Dict("type" => "text", "text" => "What about this wine?"),
|
||||||
|
# Dict(
|
||||||
|
# "type" => "image_url",
|
||||||
|
# "image_url" => Dict("url" => data2_uri)
|
||||||
|
# )
|
||||||
|
# ]
|
||||||
|
# )
|
||||||
|
|
||||||
|
# result = YiemAgent.conversation(agent; userinput=message)
|
||||||
|
# println("\n$result")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user