Compare commits
29 Commits
v0.2.2
...
bf223b64b2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf223b64b2 | ||
|
|
d9c842bba5 | ||
|
|
b8fd331c1a | ||
|
|
00b0ab01a4 | ||
|
|
fd5ac82662 | ||
|
|
bc0f735ab7 | ||
| 3d03a4d351 | |||
| 568e0ff54f | |||
| 83a20faab6 | |||
| 418c543d44 | |||
| e6ce6f9954 | |||
| 7fd0d6269a | |||
| e391547991 | |||
| 7c9ceb06f8 | |||
| 14c881741e | |||
| 0873b1341f | |||
|
|
00ec7328e7 | ||
| 83ef7d52b2 | |||
| 323c232121 | |||
| 696a77a483 | |||
| 94f2c9479a | |||
| 200a1d3e23 | |||
| a22f9c52d2 | |||
| 2036a07f46 | |||
| d09e9c1071 | |||
| 4f1917e01b | |||
| 7dd6b56e4c | |||
|
|
e9f9e431a9 | ||
|
|
2f38f3cd0d |
@@ -1,8 +1,8 @@
|
|||||||
# This file is machine-generated - editing it directly is not advised
|
# This file is machine-generated - editing it directly is not advised
|
||||||
|
|
||||||
julia_version = "1.11.2"
|
julia_version = "1.11.4"
|
||||||
manifest_format = "2.0"
|
manifest_format = "2.0"
|
||||||
project_hash = "6e88822413ea4a623cd914d84de127dc6c57fceb"
|
project_hash = "9e0d7dca51b949f2ffa5477b895b90988ec62529"
|
||||||
|
|
||||||
[[deps.AliasTables]]
|
[[deps.AliasTables]]
|
||||||
deps = ["PtrArrays", "Random"]
|
deps = ["PtrArrays", "Random"]
|
||||||
@@ -120,9 +120,9 @@ version = "1.11.0"
|
|||||||
|
|
||||||
[[deps.Distributions]]
|
[[deps.Distributions]]
|
||||||
deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"]
|
deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"]
|
||||||
git-tree-sha1 = "3101c32aab536e7a27b1763c0797dba151b899ad"
|
git-tree-sha1 = "03aa5d44647eaec98e1920635cdfed5d5560a8b9"
|
||||||
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
|
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
|
||||||
version = "0.25.113"
|
version = "0.25.117"
|
||||||
|
|
||||||
[deps.Distributions.extensions]
|
[deps.Distributions.extensions]
|
||||||
DistributionsChainRulesCoreExt = "ChainRulesCore"
|
DistributionsChainRulesCoreExt = "ChainRulesCore"
|
||||||
@@ -200,11 +200,9 @@ version = "1.11.0"
|
|||||||
|
|
||||||
[[deps.GeneralUtils]]
|
[[deps.GeneralUtils]]
|
||||||
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON3", "MQTTClient", "PrettyPrinting", "Random", "SHA", "UUIDs"]
|
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON3", "MQTTClient", "PrettyPrinting", "Random", "SHA", "UUIDs"]
|
||||||
git-tree-sha1 = "978d9a5c3fc30205dd72d4a2a2ed4fa85ebee5cf"
|
path = "../GeneralUtils"
|
||||||
repo-rev = "main"
|
|
||||||
repo-url = "https://git.yiem.cc/ton/GeneralUtils"
|
|
||||||
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
||||||
version = "0.1.0"
|
version = "0.2.3"
|
||||||
|
|
||||||
[[deps.HTTP]]
|
[[deps.HTTP]]
|
||||||
deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "PrecompileTools", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"]
|
deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "PrecompileTools", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"]
|
||||||
@@ -214,9 +212,9 @@ version = "1.10.13"
|
|||||||
|
|
||||||
[[deps.HypergeometricFunctions]]
|
[[deps.HypergeometricFunctions]]
|
||||||
deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
|
deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
|
||||||
git-tree-sha1 = "b1c2585431c382e3fe5805874bda6aea90a95de9"
|
git-tree-sha1 = "2bd56245074fab4015b9174f24ceba8293209053"
|
||||||
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
|
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
|
||||||
version = "0.3.25"
|
version = "0.3.27"
|
||||||
|
|
||||||
[[deps.ICU_jll]]
|
[[deps.ICU_jll]]
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
|
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
|
||||||
@@ -305,12 +303,10 @@ uuid = "b39eb1a6-c29a-53d7-8c32-632cd16f18da"
|
|||||||
version = "1.19.3+0"
|
version = "1.19.3+0"
|
||||||
|
|
||||||
[[deps.LLMMCTS]]
|
[[deps.LLMMCTS]]
|
||||||
deps = ["GeneralUtils", "JSON3"]
|
deps = ["GeneralUtils", "JSON3", "PrettyPrinting"]
|
||||||
git-tree-sha1 = "c8ad9715e78bbd19f5ac79e1f1cacf85f141449d"
|
path = "../LLMMCTS"
|
||||||
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.2"
|
version = "0.1.4"
|
||||||
|
|
||||||
[[deps.LaTeXStrings]]
|
[[deps.LaTeXStrings]]
|
||||||
git-tree-sha1 = "dda21b8cbd6a6c40d9d02a73230f9d70fed6918c"
|
git-tree-sha1 = "dda21b8cbd6a6c40d9d02a73230f9d70fed6918c"
|
||||||
@@ -475,7 +471,7 @@ version = "0.3.27+1"
|
|||||||
[[deps.OpenLibm_jll]]
|
[[deps.OpenLibm_jll]]
|
||||||
deps = ["Artifacts", "Libdl"]
|
deps = ["Artifacts", "Libdl"]
|
||||||
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
|
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
|
||||||
version = "0.8.1+2"
|
version = "0.8.1+4"
|
||||||
|
|
||||||
[[deps.OpenSSL]]
|
[[deps.OpenSSL]]
|
||||||
deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"]
|
deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"]
|
||||||
@@ -493,7 +489,7 @@ version = "3.0.15+1"
|
|||||||
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
|
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
|
||||||
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
|
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
|
||||||
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
|
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
|
||||||
version = "0.5.5+0"
|
version = "0.5.5+2"
|
||||||
|
|
||||||
[[deps.OrderedCollections]]
|
[[deps.OrderedCollections]]
|
||||||
git-tree-sha1 = "12f1439c4f986bb868acda6ea33ebc78e19b95ad"
|
git-tree-sha1 = "12f1439c4f986bb868acda6ea33ebc78e19b95ad"
|
||||||
@@ -502,9 +498,9 @@ version = "1.7.0"
|
|||||||
|
|
||||||
[[deps.PDMats]]
|
[[deps.PDMats]]
|
||||||
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
|
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
|
||||||
git-tree-sha1 = "949347156c25054de2db3b166c52ac4728cbad65"
|
git-tree-sha1 = "966b85253e959ea89c53a9abebbf2e964fbf593b"
|
||||||
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
|
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
|
||||||
version = "0.11.31"
|
version = "0.11.32"
|
||||||
|
|
||||||
[[deps.Parsers]]
|
[[deps.Parsers]]
|
||||||
deps = ["Dates", "PrecompileTools", "UUIDs"]
|
deps = ["Dates", "PrecompileTools", "UUIDs"]
|
||||||
@@ -556,15 +552,15 @@ uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
|||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
|
||||||
[[deps.PtrArrays]]
|
[[deps.PtrArrays]]
|
||||||
git-tree-sha1 = "77a42d78b6a92df47ab37e177b2deac405e1c88f"
|
git-tree-sha1 = "1d36ef11a9aaf1e8b74dacc6a731dd1de8fd493d"
|
||||||
uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d"
|
uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d"
|
||||||
version = "1.2.1"
|
version = "1.3.0"
|
||||||
|
|
||||||
[[deps.QuadGK]]
|
[[deps.QuadGK]]
|
||||||
deps = ["DataStructures", "LinearAlgebra"]
|
deps = ["DataStructures", "LinearAlgebra"]
|
||||||
git-tree-sha1 = "cda3b045cf9ef07a08ad46731f5a3165e56cf3da"
|
git-tree-sha1 = "9da16da70037ba9d701192e27befedefb91ec284"
|
||||||
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
|
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
|
||||||
version = "2.11.1"
|
version = "2.11.2"
|
||||||
|
|
||||||
[deps.QuadGK.extensions]
|
[deps.QuadGK.extensions]
|
||||||
QuadGKEnzymeExt = "Enzyme"
|
QuadGKEnzymeExt = "Enzyme"
|
||||||
@@ -664,9 +660,9 @@ version = "1.11.0"
|
|||||||
|
|
||||||
[[deps.SpecialFunctions]]
|
[[deps.SpecialFunctions]]
|
||||||
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
|
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
|
||||||
git-tree-sha1 = "2f5d4697f21388cbe1ff299430dd169ef97d7e14"
|
git-tree-sha1 = "64cca0c26b4f31ba18f13f6c12af7c85f478cfde"
|
||||||
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
|
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
|
||||||
version = "2.4.0"
|
version = "2.5.0"
|
||||||
|
|
||||||
[deps.SpecialFunctions.extensions]
|
[deps.SpecialFunctions.extensions]
|
||||||
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
|
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name = "SQLLLM"
|
name = "SQLLLM"
|
||||||
uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
|
uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
|
||||||
authors = ["narawat lamaiin <narawat@outlook.com>"]
|
authors = ["narawat lamaiin <narawat@outlook.com>"]
|
||||||
version = "0.2.2"
|
version = "0.2.4"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||||
@@ -23,5 +23,4 @@ URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
|
|||||||
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||||
|
|
||||||
[compat]
|
[compat]
|
||||||
GeneralUtils = "0.1, 0.2"
|
Dates = "1.11.0"
|
||||||
LLMMCTS = "0.1"
|
|
||||||
|
|||||||
@@ -1,879 +0,0 @@
|
|||||||
# This file is machine-generated - editing it directly is not advised
|
|
||||||
|
|
||||||
julia_version = "1.11.0"
|
|
||||||
manifest_format = "2.0"
|
|
||||||
project_hash = "dbd62da0dcca1a1b2302848e770ef42c10a9d0d8"
|
|
||||||
|
|
||||||
[[deps.AliasTables]]
|
|
||||||
deps = ["PtrArrays", "Random"]
|
|
||||||
git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff"
|
|
||||||
uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8"
|
|
||||||
version = "1.1.3"
|
|
||||||
|
|
||||||
[[deps.ArgTools]]
|
|
||||||
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
|
|
||||||
version = "1.1.2"
|
|
||||||
|
|
||||||
[[deps.Artifacts]]
|
|
||||||
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.Base64]]
|
|
||||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.BitFlags]]
|
|
||||||
git-tree-sha1 = "0691e34b3bb8be9307330f88d1a3c3f25466c24d"
|
|
||||||
uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35"
|
|
||||||
version = "0.1.9"
|
|
||||||
|
|
||||||
[[deps.CEnum]]
|
|
||||||
git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc"
|
|
||||||
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
|
|
||||||
version = "0.5.0"
|
|
||||||
|
|
||||||
[[deps.CSV]]
|
|
||||||
deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"]
|
|
||||||
git-tree-sha1 = "6c834533dc1fabd820c1db03c839bf97e45a3fab"
|
|
||||||
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
|
||||||
version = "0.10.14"
|
|
||||||
|
|
||||||
[[deps.CodeTracking]]
|
|
||||||
deps = ["InteractiveUtils", "UUIDs"]
|
|
||||||
git-tree-sha1 = "7eee164f122511d3e4e1ebadb7956939ea7e1c77"
|
|
||||||
uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
|
|
||||||
version = "1.3.6"
|
|
||||||
|
|
||||||
[[deps.CodecZlib]]
|
|
||||||
deps = ["TranscodingStreams", "Zlib_jll"]
|
|
||||||
git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759"
|
|
||||||
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
|
|
||||||
version = "0.7.6"
|
|
||||||
|
|
||||||
[[deps.Compat]]
|
|
||||||
deps = ["TOML", "UUIDs"]
|
|
||||||
git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215"
|
|
||||||
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
|
|
||||||
version = "4.16.0"
|
|
||||||
weakdeps = ["Dates", "LinearAlgebra"]
|
|
||||||
|
|
||||||
[deps.Compat.extensions]
|
|
||||||
CompatLinearAlgebraExt = "LinearAlgebra"
|
|
||||||
|
|
||||||
[[deps.CompilerSupportLibraries_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl"]
|
|
||||||
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
|
|
||||||
version = "1.1.1+0"
|
|
||||||
|
|
||||||
[[deps.ConcurrentUtilities]]
|
|
||||||
deps = ["Serialization", "Sockets"]
|
|
||||||
git-tree-sha1 = "ea32b83ca4fefa1768dc84e504cc0a94fb1ab8d1"
|
|
||||||
uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb"
|
|
||||||
version = "2.4.2"
|
|
||||||
|
|
||||||
[[deps.CondaPkg]]
|
|
||||||
deps = ["JSON3", "Markdown", "MicroMamba", "Pidfile", "Pkg", "Preferences", "TOML"]
|
|
||||||
git-tree-sha1 = "8f7faef2ca039ee068cd971a80ccd710d23fb2eb"
|
|
||||||
uuid = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
|
|
||||||
version = "0.2.23"
|
|
||||||
|
|
||||||
[[deps.Crayons]]
|
|
||||||
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
|
|
||||||
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
|
|
||||||
version = "4.1.1"
|
|
||||||
|
|
||||||
[[deps.DBInterface]]
|
|
||||||
git-tree-sha1 = "a444404b3f94deaa43ca2a58e18153a82695282b"
|
|
||||||
uuid = "a10d1c49-ce27-4219-8d33-6db1a4562965"
|
|
||||||
version = "2.6.1"
|
|
||||||
|
|
||||||
[[deps.DataAPI]]
|
|
||||||
git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe"
|
|
||||||
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
|
|
||||||
version = "1.16.0"
|
|
||||||
|
|
||||||
[[deps.DataFrames]]
|
|
||||||
deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
|
|
||||||
git-tree-sha1 = "fb61b4812c49343d7ef0b533ba982c46021938a6"
|
|
||||||
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
|
||||||
version = "1.7.0"
|
|
||||||
|
|
||||||
[[deps.DataStructures]]
|
|
||||||
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
|
|
||||||
git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82"
|
|
||||||
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
|
||||||
version = "0.18.20"
|
|
||||||
|
|
||||||
[[deps.DataValueInterfaces]]
|
|
||||||
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
|
|
||||||
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
|
|
||||||
version = "1.0.0"
|
|
||||||
|
|
||||||
[[deps.Dates]]
|
|
||||||
deps = ["Printf"]
|
|
||||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.Decimals]]
|
|
||||||
git-tree-sha1 = "e98abef36d02a0ec385d68cd7dadbce9b28cbd88"
|
|
||||||
uuid = "abce61dc-4473-55a0-ba07-351d65e31d42"
|
|
||||||
version = "0.4.1"
|
|
||||||
|
|
||||||
[[deps.Distributed]]
|
|
||||||
deps = ["Random", "Serialization", "Sockets"]
|
|
||||||
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.Distributions]]
|
|
||||||
deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"]
|
|
||||||
git-tree-sha1 = "d7477ecdafb813ddee2ae727afa94e9dcb5f3fb0"
|
|
||||||
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
|
|
||||||
version = "0.25.112"
|
|
||||||
|
|
||||||
[deps.Distributions.extensions]
|
|
||||||
DistributionsChainRulesCoreExt = "ChainRulesCore"
|
|
||||||
DistributionsDensityInterfaceExt = "DensityInterface"
|
|
||||||
DistributionsTestExt = "Test"
|
|
||||||
|
|
||||||
[deps.Distributions.weakdeps]
|
|
||||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
|
||||||
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
|
|
||||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
|
||||||
|
|
||||||
[[deps.DocStringExtensions]]
|
|
||||||
deps = ["LibGit2"]
|
|
||||||
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
|
|
||||||
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
|
|
||||||
version = "0.9.3"
|
|
||||||
|
|
||||||
[[deps.Downloads]]
|
|
||||||
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
|
|
||||||
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
|
|
||||||
version = "1.6.0"
|
|
||||||
|
|
||||||
[[deps.ExceptionUnwrapping]]
|
|
||||||
deps = ["Test"]
|
|
||||||
git-tree-sha1 = "dcb08a0d93ec0b1cdc4af184b26b591e9695423a"
|
|
||||||
uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4"
|
|
||||||
version = "0.1.10"
|
|
||||||
|
|
||||||
[[deps.ExprTools]]
|
|
||||||
git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec"
|
|
||||||
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
|
|
||||||
version = "0.1.10"
|
|
||||||
|
|
||||||
[[deps.FileIO]]
|
|
||||||
deps = ["Pkg", "Requires", "UUIDs"]
|
|
||||||
git-tree-sha1 = "62ca0547a14c57e98154423419d8a342dca75ca9"
|
|
||||||
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
|
|
||||||
version = "1.16.4"
|
|
||||||
|
|
||||||
[[deps.FilePathsBase]]
|
|
||||||
deps = ["Compat", "Dates"]
|
|
||||||
git-tree-sha1 = "7878ff7172a8e6beedd1dea14bd27c3c6340d361"
|
|
||||||
uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
|
|
||||||
version = "0.9.22"
|
|
||||||
weakdeps = ["Mmap", "Test"]
|
|
||||||
|
|
||||||
[deps.FilePathsBase.extensions]
|
|
||||||
FilePathsBaseMmapExt = "Mmap"
|
|
||||||
FilePathsBaseTestExt = "Test"
|
|
||||||
|
|
||||||
[[deps.FileWatching]]
|
|
||||||
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.FillArrays]]
|
|
||||||
deps = ["LinearAlgebra"]
|
|
||||||
git-tree-sha1 = "6a70198746448456524cb442b8af316927ff3e1a"
|
|
||||||
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
|
|
||||||
version = "1.13.0"
|
|
||||||
weakdeps = ["PDMats", "SparseArrays", "Statistics"]
|
|
||||||
|
|
||||||
[deps.FillArrays.extensions]
|
|
||||||
FillArraysPDMatsExt = "PDMats"
|
|
||||||
FillArraysSparseArraysExt = "SparseArrays"
|
|
||||||
FillArraysStatisticsExt = "Statistics"
|
|
||||||
|
|
||||||
[[deps.Future]]
|
|
||||||
deps = ["Random"]
|
|
||||||
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.GeneralUtils]]
|
|
||||||
deps = ["CSV", "DataFrames", "DataStructures", "Dates", "Distributions", "JSON3", "MQTTClient", "PrettyPrinting", "Random", "SHA", "UUIDs"]
|
|
||||||
path = "/appfolder/app/privatejuliapkg/GeneralUtils"
|
|
||||||
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[deps.HTTP]]
|
|
||||||
deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"]
|
|
||||||
git-tree-sha1 = "d1d712be3164d61d1fb98e7ce9bcbc6cc06b45ed"
|
|
||||||
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
|
||||||
version = "1.10.8"
|
|
||||||
|
|
||||||
[[deps.HypergeometricFunctions]]
|
|
||||||
deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
|
|
||||||
git-tree-sha1 = "7c4195be1649ae622304031ed46a2f4df989f1eb"
|
|
||||||
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
|
|
||||||
version = "0.3.24"
|
|
||||||
|
|
||||||
[[deps.ICU_jll]]
|
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
|
|
||||||
git-tree-sha1 = "20b6765a3016e1fca0c9c93c80d50061b94218b7"
|
|
||||||
uuid = "a51ab1cf-af8e-5615-a023-bc2c838bba6b"
|
|
||||||
version = "69.1.0+0"
|
|
||||||
|
|
||||||
[[deps.Infinity]]
|
|
||||||
deps = ["Dates", "Random", "Requires"]
|
|
||||||
git-tree-sha1 = "cf8234411cbeb98676c173f930951ea29dca3b23"
|
|
||||||
uuid = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
|
|
||||||
version = "0.2.4"
|
|
||||||
|
|
||||||
[[deps.InlineStrings]]
|
|
||||||
git-tree-sha1 = "45521d31238e87ee9f9732561bfee12d4eebd52d"
|
|
||||||
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
|
|
||||||
version = "1.4.2"
|
|
||||||
|
|
||||||
[deps.InlineStrings.extensions]
|
|
||||||
ArrowTypesExt = "ArrowTypes"
|
|
||||||
ParsersExt = "Parsers"
|
|
||||||
|
|
||||||
[deps.InlineStrings.weakdeps]
|
|
||||||
ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd"
|
|
||||||
Parsers = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
|
|
||||||
|
|
||||||
[[deps.InteractiveUtils]]
|
|
||||||
deps = ["Markdown"]
|
|
||||||
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.Intervals]]
|
|
||||||
deps = ["Dates", "Printf", "RecipesBase", "Serialization", "TimeZones"]
|
|
||||||
git-tree-sha1 = "ac0aaa807ed5eaf13f67afe188ebc07e828ff640"
|
|
||||||
uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5"
|
|
||||||
version = "1.10.0"
|
|
||||||
|
|
||||||
[[deps.InvertedIndices]]
|
|
||||||
git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038"
|
|
||||||
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
|
|
||||||
version = "1.3.0"
|
|
||||||
|
|
||||||
[[deps.IrrationalConstants]]
|
|
||||||
git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2"
|
|
||||||
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
|
|
||||||
version = "0.2.2"
|
|
||||||
|
|
||||||
[[deps.IterTools]]
|
|
||||||
git-tree-sha1 = "42d5f897009e7ff2cf88db414a389e5ed1bdd023"
|
|
||||||
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
|
|
||||||
version = "1.10.0"
|
|
||||||
|
|
||||||
[[deps.IteratorInterfaceExtensions]]
|
|
||||||
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
|
|
||||||
uuid = "82899510-4779-5014-852e-03e436cf321d"
|
|
||||||
version = "1.0.0"
|
|
||||||
|
|
||||||
[[deps.JLLWrappers]]
|
|
||||||
deps = ["Artifacts", "Preferences"]
|
|
||||||
git-tree-sha1 = "be3dc50a92e5a386872a493a10050136d4703f9b"
|
|
||||||
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
|
|
||||||
version = "1.6.1"
|
|
||||||
|
|
||||||
[[deps.JSON3]]
|
|
||||||
deps = ["Dates", "Mmap", "Parsers", "PrecompileTools", "StructTypes", "UUIDs"]
|
|
||||||
git-tree-sha1 = "eb3edce0ed4fa32f75a0a11217433c31d56bd48b"
|
|
||||||
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
|
|
||||||
version = "1.14.0"
|
|
||||||
|
|
||||||
[deps.JSON3.extensions]
|
|
||||||
JSON3ArrowExt = ["ArrowTypes"]
|
|
||||||
|
|
||||||
[deps.JSON3.weakdeps]
|
|
||||||
ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd"
|
|
||||||
|
|
||||||
[[deps.JuliaInterpreter]]
|
|
||||||
deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"]
|
|
||||||
git-tree-sha1 = "2984284a8abcfcc4784d95a9e2ea4e352dd8ede7"
|
|
||||||
uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a"
|
|
||||||
version = "0.9.36"
|
|
||||||
|
|
||||||
[[deps.Kerberos_krb5_jll]]
|
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
|
|
||||||
git-tree-sha1 = "60274b4ab38e8d1248216fe6b6ace75ae09b0502"
|
|
||||||
uuid = "b39eb1a6-c29a-53d7-8c32-632cd16f18da"
|
|
||||||
version = "1.19.3+0"
|
|
||||||
|
|
||||||
[[deps.LLMMCTS]]
|
|
||||||
deps = ["GeneralUtils", "JSON3"]
|
|
||||||
path = "/appfolder/app/privatejuliapkg/LLMMCTS"
|
|
||||||
uuid = "d76c5a4d-449e-4835-8cc4-dd86ec44f241"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[deps.LaTeXStrings]]
|
|
||||||
git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec"
|
|
||||||
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
|
|
||||||
version = "1.3.1"
|
|
||||||
|
|
||||||
[[deps.LayerDicts]]
|
|
||||||
git-tree-sha1 = "6087ad3521d6278ebe5c27ae55e7bbb15ca312cb"
|
|
||||||
uuid = "6f188dcb-512c-564b-bc01-e0f76e72f166"
|
|
||||||
version = "1.0.0"
|
|
||||||
|
|
||||||
[[deps.LazyArtifacts]]
|
|
||||||
deps = ["Artifacts", "Pkg"]
|
|
||||||
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.LibCURL]]
|
|
||||||
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
|
|
||||||
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
|
|
||||||
version = "0.6.4"
|
|
||||||
|
|
||||||
[[deps.LibCURL_jll]]
|
|
||||||
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
|
|
||||||
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
|
|
||||||
version = "8.6.0+0"
|
|
||||||
|
|
||||||
[[deps.LibGit2]]
|
|
||||||
deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"]
|
|
||||||
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.LibGit2_jll]]
|
|
||||||
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"]
|
|
||||||
uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5"
|
|
||||||
version = "1.7.2+0"
|
|
||||||
|
|
||||||
[[deps.LibPQ]]
|
|
||||||
deps = ["CEnum", "DBInterface", "Dates", "Decimals", "DocStringExtensions", "FileWatching", "Infinity", "Intervals", "IterTools", "LayerDicts", "LibPQ_jll", "Libdl", "Memento", "OffsetArrays", "SQLStrings", "Tables", "TimeZones", "UTCDateTimes"]
|
|
||||||
git-tree-sha1 = "3d227cd13cbf1e9a54d7748dab33e078da6f9168"
|
|
||||||
uuid = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1"
|
|
||||||
version = "1.18.0"
|
|
||||||
|
|
||||||
[[deps.LibPQ_jll]]
|
|
||||||
deps = ["Artifacts", "ICU_jll", "JLLWrappers", "Kerberos_krb5_jll", "Libdl", "OpenSSL_jll", "Zstd_jll"]
|
|
||||||
git-tree-sha1 = "09163f837936c8cc44f4691cb41d805eb1769642"
|
|
||||||
uuid = "08be9ffa-1c94-5ee5-a977-46a84ec9b350"
|
|
||||||
version = "16.0.0+0"
|
|
||||||
|
|
||||||
[[deps.LibSSH2_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
|
|
||||||
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
|
|
||||||
version = "1.11.0+1"
|
|
||||||
|
|
||||||
[[deps.Libdl]]
|
|
||||||
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.LinearAlgebra]]
|
|
||||||
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
|
|
||||||
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.LogExpFunctions]]
|
|
||||||
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
|
|
||||||
git-tree-sha1 = "a2d09619db4e765091ee5c6ffe8872849de0feea"
|
|
||||||
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
|
|
||||||
version = "0.3.28"
|
|
||||||
|
|
||||||
[deps.LogExpFunctions.extensions]
|
|
||||||
LogExpFunctionsChainRulesCoreExt = "ChainRulesCore"
|
|
||||||
LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables"
|
|
||||||
LogExpFunctionsInverseFunctionsExt = "InverseFunctions"
|
|
||||||
|
|
||||||
[deps.LogExpFunctions.weakdeps]
|
|
||||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
|
||||||
ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
|
|
||||||
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
|
|
||||||
|
|
||||||
[[deps.Logging]]
|
|
||||||
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.LoggingExtras]]
|
|
||||||
deps = ["Dates", "Logging"]
|
|
||||||
git-tree-sha1 = "c1dd6d7978c12545b4179fb6153b9250c96b0075"
|
|
||||||
uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36"
|
|
||||||
version = "1.0.3"
|
|
||||||
|
|
||||||
[[deps.LoweredCodeUtils]]
|
|
||||||
deps = ["JuliaInterpreter"]
|
|
||||||
git-tree-sha1 = "96d2a4a668f5c098fb8a26ce7da53cde3e462a80"
|
|
||||||
uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
|
|
||||||
version = "3.0.3"
|
|
||||||
|
|
||||||
[[deps.MQTTClient]]
|
|
||||||
deps = ["Distributed", "Random", "Sockets"]
|
|
||||||
git-tree-sha1 = "f2597b290d4bf17b577346153cd2ddf9accb5c26"
|
|
||||||
uuid = "985f35cc-2c3d-4943-b8c1-f0931d5f0959"
|
|
||||||
version = "0.3.1"
|
|
||||||
weakdeps = ["PrecompileTools"]
|
|
||||||
|
|
||||||
[deps.MQTTClient.extensions]
|
|
||||||
PrecompileMQTT = "PrecompileTools"
|
|
||||||
|
|
||||||
[[deps.MacroTools]]
|
|
||||||
deps = ["Markdown", "Random"]
|
|
||||||
git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df"
|
|
||||||
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
|
|
||||||
version = "0.5.13"
|
|
||||||
|
|
||||||
[[deps.Markdown]]
|
|
||||||
deps = ["Base64"]
|
|
||||||
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.MbedTLS]]
|
|
||||||
deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"]
|
|
||||||
git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf"
|
|
||||||
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
|
|
||||||
version = "1.1.9"
|
|
||||||
|
|
||||||
[[deps.MbedTLS_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl"]
|
|
||||||
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
|
|
||||||
version = "2.28.6+0"
|
|
||||||
|
|
||||||
[[deps.Memento]]
|
|
||||||
deps = ["Dates", "Distributed", "Requires", "Serialization", "Sockets", "Test", "UUIDs"]
|
|
||||||
git-tree-sha1 = "bb2e8f4d9f400f6e90d57b34860f6abdc51398e5"
|
|
||||||
uuid = "f28f55f0-a522-5efc-85c2-fe41dfb9b2d9"
|
|
||||||
version = "1.4.1"
|
|
||||||
|
|
||||||
[[deps.MicroMamba]]
|
|
||||||
deps = ["Pkg", "Scratch", "micromamba_jll"]
|
|
||||||
git-tree-sha1 = "011cab361eae7bcd7d278f0a7a00ff9c69000c51"
|
|
||||||
uuid = "0b3b1443-0f03-428d-bdfb-f27f9c1191ea"
|
|
||||||
version = "0.1.14"
|
|
||||||
|
|
||||||
[[deps.Missings]]
|
|
||||||
deps = ["DataAPI"]
|
|
||||||
git-tree-sha1 = "ec4f7fbeab05d7747bdf98eb74d130a2a2ed298d"
|
|
||||||
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
|
|
||||||
version = "1.2.0"
|
|
||||||
|
|
||||||
[[deps.Mmap]]
|
|
||||||
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.Mocking]]
|
|
||||||
deps = ["Compat", "ExprTools"]
|
|
||||||
git-tree-sha1 = "2c140d60d7cb82badf06d8783800d0bcd1a7daa2"
|
|
||||||
uuid = "78c3b35d-d492-501b-9361-3d52fe80e533"
|
|
||||||
version = "0.8.1"
|
|
||||||
|
|
||||||
[[deps.MozillaCACerts_jll]]
|
|
||||||
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
|
|
||||||
version = "2023.12.12"
|
|
||||||
|
|
||||||
[[deps.NetworkOptions]]
|
|
||||||
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
|
|
||||||
version = "1.2.0"
|
|
||||||
|
|
||||||
[[deps.OffsetArrays]]
|
|
||||||
git-tree-sha1 = "1a27764e945a152f7ca7efa04de513d473e9542e"
|
|
||||||
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
|
|
||||||
version = "1.14.1"
|
|
||||||
|
|
||||||
[deps.OffsetArrays.extensions]
|
|
||||||
OffsetArraysAdaptExt = "Adapt"
|
|
||||||
|
|
||||||
[deps.OffsetArrays.weakdeps]
|
|
||||||
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
|
|
||||||
|
|
||||||
[[deps.OpenBLAS_jll]]
|
|
||||||
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
|
|
||||||
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
|
|
||||||
version = "0.3.27+1"
|
|
||||||
|
|
||||||
[[deps.OpenLibm_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl"]
|
|
||||||
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
|
|
||||||
version = "0.8.1+2"
|
|
||||||
|
|
||||||
[[deps.OpenSSL]]
|
|
||||||
deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"]
|
|
||||||
git-tree-sha1 = "38cb508d080d21dc1128f7fb04f20387ed4c0af4"
|
|
||||||
uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c"
|
|
||||||
version = "1.4.3"
|
|
||||||
|
|
||||||
[[deps.OpenSSL_jll]]
|
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl"]
|
|
||||||
git-tree-sha1 = "7493f61f55a6cce7325f197443aa80d32554ba10"
|
|
||||||
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
|
|
||||||
version = "3.0.15+1"
|
|
||||||
|
|
||||||
[[deps.OpenSpecFun_jll]]
|
|
||||||
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
|
|
||||||
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
|
|
||||||
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
|
|
||||||
version = "0.5.5+0"
|
|
||||||
|
|
||||||
[[deps.OrderedCollections]]
|
|
||||||
git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5"
|
|
||||||
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
|
||||||
version = "1.6.3"
|
|
||||||
|
|
||||||
[[deps.PDMats]]
|
|
||||||
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
|
|
||||||
git-tree-sha1 = "949347156c25054de2db3b166c52ac4728cbad65"
|
|
||||||
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
|
|
||||||
version = "0.11.31"
|
|
||||||
|
|
||||||
[[deps.Parsers]]
|
|
||||||
deps = ["Dates", "PrecompileTools", "UUIDs"]
|
|
||||||
git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821"
|
|
||||||
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
|
|
||||||
version = "2.8.1"
|
|
||||||
|
|
||||||
[[deps.Pidfile]]
|
|
||||||
deps = ["FileWatching", "Test"]
|
|
||||||
git-tree-sha1 = "2d8aaf8ee10df53d0dfb9b8ee44ae7c04ced2b03"
|
|
||||||
uuid = "fa939f87-e72e-5be4-a000-7fc836dbe307"
|
|
||||||
version = "1.3.0"
|
|
||||||
|
|
||||||
[[deps.Pkg]]
|
|
||||||
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"]
|
|
||||||
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
|
||||||
version = "1.11.0"
|
|
||||||
weakdeps = ["REPL"]
|
|
||||||
|
|
||||||
[deps.Pkg.extensions]
|
|
||||||
REPLExt = "REPL"
|
|
||||||
|
|
||||||
[[deps.PooledArrays]]
|
|
||||||
deps = ["DataAPI", "Future"]
|
|
||||||
git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3"
|
|
||||||
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
|
|
||||||
version = "1.4.3"
|
|
||||||
|
|
||||||
[[deps.PrecompileTools]]
|
|
||||||
deps = ["Preferences"]
|
|
||||||
git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f"
|
|
||||||
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
|
|
||||||
version = "1.2.1"
|
|
||||||
|
|
||||||
[[deps.Preferences]]
|
|
||||||
deps = ["TOML"]
|
|
||||||
git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6"
|
|
||||||
uuid = "21216c6a-2e73-6563-6e65-726566657250"
|
|
||||||
version = "1.4.3"
|
|
||||||
|
|
||||||
[[deps.PrettyPrinting]]
|
|
||||||
git-tree-sha1 = "142ee93724a9c5d04d78df7006670a93ed1b244e"
|
|
||||||
uuid = "54e16d92-306c-5ea0-a30b-337be88ac337"
|
|
||||||
version = "0.4.2"
|
|
||||||
|
|
||||||
[[deps.PrettyTables]]
|
|
||||||
deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"]
|
|
||||||
git-tree-sha1 = "1101cd475833706e4d0e7b122218257178f48f34"
|
|
||||||
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
|
|
||||||
version = "2.4.0"
|
|
||||||
|
|
||||||
[[deps.Printf]]
|
|
||||||
deps = ["Unicode"]
|
|
||||||
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.PtrArrays]]
|
|
||||||
git-tree-sha1 = "77a42d78b6a92df47ab37e177b2deac405e1c88f"
|
|
||||||
uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d"
|
|
||||||
version = "1.2.1"
|
|
||||||
|
|
||||||
[[deps.PythonCall]]
|
|
||||||
deps = ["CondaPkg", "Dates", "Libdl", "MacroTools", "Markdown", "Pkg", "REPL", "Requires", "Serialization", "Tables", "UnsafePointers"]
|
|
||||||
git-tree-sha1 = "06a778ec6d6e76b0c2fb661436a18bce853ec45f"
|
|
||||||
uuid = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
|
|
||||||
version = "0.9.23"
|
|
||||||
|
|
||||||
[[deps.QuadGK]]
|
|
||||||
deps = ["DataStructures", "LinearAlgebra"]
|
|
||||||
git-tree-sha1 = "cda3b045cf9ef07a08ad46731f5a3165e56cf3da"
|
|
||||||
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
|
|
||||||
version = "2.11.1"
|
|
||||||
|
|
||||||
[deps.QuadGK.extensions]
|
|
||||||
QuadGKEnzymeExt = "Enzyme"
|
|
||||||
|
|
||||||
[deps.QuadGK.weakdeps]
|
|
||||||
Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9"
|
|
||||||
|
|
||||||
[[deps.REPL]]
|
|
||||||
deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"]
|
|
||||||
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.Random]]
|
|
||||||
deps = ["SHA"]
|
|
||||||
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.RecipesBase]]
|
|
||||||
deps = ["PrecompileTools"]
|
|
||||||
git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff"
|
|
||||||
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
|
|
||||||
version = "1.3.4"
|
|
||||||
|
|
||||||
[[deps.Reexport]]
|
|
||||||
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
|
|
||||||
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
|
|
||||||
version = "1.2.2"
|
|
||||||
|
|
||||||
[[deps.Requires]]
|
|
||||||
deps = ["UUIDs"]
|
|
||||||
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
|
|
||||||
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
|
|
||||||
version = "1.3.0"
|
|
||||||
|
|
||||||
[[deps.Revise]]
|
|
||||||
deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "REPL", "Requires", "UUIDs", "Unicode"]
|
|
||||||
git-tree-sha1 = "2d4e5de3ac1c348fd39ddf8adbef82aa56b65576"
|
|
||||||
uuid = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
|
||||||
version = "3.6.1"
|
|
||||||
|
|
||||||
[[deps.Rmath]]
|
|
||||||
deps = ["Random", "Rmath_jll"]
|
|
||||||
git-tree-sha1 = "852bd0f55565a9e973fcfee83a84413270224dc4"
|
|
||||||
uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa"
|
|
||||||
version = "0.8.0"
|
|
||||||
|
|
||||||
[[deps.Rmath_jll]]
|
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl"]
|
|
||||||
git-tree-sha1 = "58cdd8fb2201a6267e1db87ff148dd6c1dbd8ad8"
|
|
||||||
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
|
|
||||||
version = "0.5.1+0"
|
|
||||||
|
|
||||||
[[deps.SHA]]
|
|
||||||
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
|
||||||
version = "0.7.0"
|
|
||||||
|
|
||||||
[[deps.SQLStrings]]
|
|
||||||
git-tree-sha1 = "55de0530689832b1d3d43491ee6b67bd54d3323c"
|
|
||||||
uuid = "af517c2e-c243-48fa-aab8-efac3db270f5"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[deps.Scratch]]
|
|
||||||
deps = ["Dates"]
|
|
||||||
git-tree-sha1 = "3bac05bc7e74a75fd9cba4295cde4045d9fe2386"
|
|
||||||
uuid = "6c6a2e73-6563-6170-7368-637461726353"
|
|
||||||
version = "1.2.1"
|
|
||||||
|
|
||||||
[[deps.SentinelArrays]]
|
|
||||||
deps = ["Dates", "Random"]
|
|
||||||
git-tree-sha1 = "ff11acffdb082493657550959d4feb4b6149e73a"
|
|
||||||
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
|
|
||||||
version = "1.4.5"
|
|
||||||
|
|
||||||
[[deps.Serialization]]
|
|
||||||
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.SimpleBufferStream]]
|
|
||||||
git-tree-sha1 = "f305871d2f381d21527c770d4788c06c097c9bc1"
|
|
||||||
uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7"
|
|
||||||
version = "1.2.0"
|
|
||||||
|
|
||||||
[[deps.Sockets]]
|
|
||||||
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.SortingAlgorithms]]
|
|
||||||
deps = ["DataStructures"]
|
|
||||||
git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085"
|
|
||||||
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
|
|
||||||
version = "1.2.1"
|
|
||||||
|
|
||||||
[[deps.SparseArrays]]
|
|
||||||
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
|
|
||||||
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.SpecialFunctions]]
|
|
||||||
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
|
|
||||||
git-tree-sha1 = "2f5d4697f21388cbe1ff299430dd169ef97d7e14"
|
|
||||||
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
|
|
||||||
version = "2.4.0"
|
|
||||||
|
|
||||||
[deps.SpecialFunctions.extensions]
|
|
||||||
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
|
|
||||||
|
|
||||||
[deps.SpecialFunctions.weakdeps]
|
|
||||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
|
||||||
|
|
||||||
[[deps.Statistics]]
|
|
||||||
deps = ["LinearAlgebra"]
|
|
||||||
git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0"
|
|
||||||
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
|
||||||
version = "1.11.1"
|
|
||||||
weakdeps = ["SparseArrays"]
|
|
||||||
|
|
||||||
[deps.Statistics.extensions]
|
|
||||||
SparseArraysExt = ["SparseArrays"]
|
|
||||||
|
|
||||||
[[deps.StatsAPI]]
|
|
||||||
deps = ["LinearAlgebra"]
|
|
||||||
git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed"
|
|
||||||
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
|
|
||||||
version = "1.7.0"
|
|
||||||
|
|
||||||
[[deps.StatsBase]]
|
|
||||||
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
|
|
||||||
git-tree-sha1 = "5cf7606d6cef84b543b483848d4ae08ad9832b21"
|
|
||||||
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
|
|
||||||
version = "0.34.3"
|
|
||||||
|
|
||||||
[[deps.StatsFuns]]
|
|
||||||
deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
|
|
||||||
git-tree-sha1 = "b423576adc27097764a90e163157bcfc9acf0f46"
|
|
||||||
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
|
|
||||||
version = "1.3.2"
|
|
||||||
|
|
||||||
[deps.StatsFuns.extensions]
|
|
||||||
StatsFunsChainRulesCoreExt = "ChainRulesCore"
|
|
||||||
StatsFunsInverseFunctionsExt = "InverseFunctions"
|
|
||||||
|
|
||||||
[deps.StatsFuns.weakdeps]
|
|
||||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
|
||||||
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
|
|
||||||
|
|
||||||
[[deps.StringManipulation]]
|
|
||||||
deps = ["PrecompileTools"]
|
|
||||||
git-tree-sha1 = "a6b1675a536c5ad1a60e5a5153e1fee12eb146e3"
|
|
||||||
uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
|
|
||||||
version = "0.4.0"
|
|
||||||
|
|
||||||
[[deps.StructTypes]]
|
|
||||||
deps = ["Dates", "UUIDs"]
|
|
||||||
git-tree-sha1 = "159331b30e94d7b11379037feeb9b690950cace8"
|
|
||||||
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.StyledStrings]]
|
|
||||||
uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.SuiteSparse]]
|
|
||||||
deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"]
|
|
||||||
uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"
|
|
||||||
|
|
||||||
[[deps.SuiteSparse_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl", "libblastrampoline_jll"]
|
|
||||||
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
|
|
||||||
version = "7.7.0+0"
|
|
||||||
|
|
||||||
[[deps.TOML]]
|
|
||||||
deps = ["Dates"]
|
|
||||||
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
|
|
||||||
version = "1.0.3"
|
|
||||||
|
|
||||||
[[deps.TZJData]]
|
|
||||||
deps = ["Artifacts"]
|
|
||||||
git-tree-sha1 = "36b40607bf2bf856828690e097e1c799623b0602"
|
|
||||||
uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7"
|
|
||||||
version = "1.3.0+2024b"
|
|
||||||
|
|
||||||
[[deps.TableTraits]]
|
|
||||||
deps = ["IteratorInterfaceExtensions"]
|
|
||||||
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
|
|
||||||
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
|
|
||||||
version = "1.0.1"
|
|
||||||
|
|
||||||
[[deps.Tables]]
|
|
||||||
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"]
|
|
||||||
git-tree-sha1 = "598cd7c1f68d1e205689b1c2fe65a9f85846f297"
|
|
||||||
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
|
||||||
version = "1.12.0"
|
|
||||||
|
|
||||||
[[deps.Tar]]
|
|
||||||
deps = ["ArgTools", "SHA"]
|
|
||||||
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
|
|
||||||
version = "1.10.0"
|
|
||||||
|
|
||||||
[[deps.Test]]
|
|
||||||
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
|
|
||||||
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.TimeZones]]
|
|
||||||
deps = ["Dates", "Downloads", "InlineStrings", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"]
|
|
||||||
git-tree-sha1 = "8323074bc977aa85cf5ad71099a83ac75b0ac107"
|
|
||||||
uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53"
|
|
||||||
version = "1.18.1"
|
|
||||||
weakdeps = ["RecipesBase"]
|
|
||||||
|
|
||||||
[deps.TimeZones.extensions]
|
|
||||||
TimeZonesRecipesBaseExt = "RecipesBase"
|
|
||||||
|
|
||||||
[[deps.TranscodingStreams]]
|
|
||||||
git-tree-sha1 = "0c45878dcfdcfa8480052b6ab162cdd138781742"
|
|
||||||
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
|
|
||||||
version = "0.11.3"
|
|
||||||
|
|
||||||
[[deps.URIs]]
|
|
||||||
git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b"
|
|
||||||
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
|
|
||||||
version = "1.5.1"
|
|
||||||
|
|
||||||
[[deps.UTCDateTimes]]
|
|
||||||
deps = ["Dates", "TimeZones"]
|
|
||||||
git-tree-sha1 = "4af3552bf0cf4a071bf3d14bd20023ea70f31b62"
|
|
||||||
uuid = "0f7cfa37-7abf-4834-b969-a8aa512401c2"
|
|
||||||
version = "1.6.1"
|
|
||||||
|
|
||||||
[[deps.UUIDs]]
|
|
||||||
deps = ["Random", "SHA"]
|
|
||||||
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.Unicode]]
|
|
||||||
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
|
|
||||||
version = "1.11.0"
|
|
||||||
|
|
||||||
[[deps.UnsafePointers]]
|
|
||||||
git-tree-sha1 = "c81331b3b2e60a982be57c046ec91f599ede674a"
|
|
||||||
uuid = "e17b2a0c-0bdf-430a-bd0c-3a23cae4ff39"
|
|
||||||
version = "1.0.0"
|
|
||||||
|
|
||||||
[[deps.WeakRefStrings]]
|
|
||||||
deps = ["DataAPI", "InlineStrings", "Parsers"]
|
|
||||||
git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23"
|
|
||||||
uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5"
|
|
||||||
version = "1.4.2"
|
|
||||||
|
|
||||||
[[deps.WorkerUtilities]]
|
|
||||||
git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7"
|
|
||||||
uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60"
|
|
||||||
version = "1.6.1"
|
|
||||||
|
|
||||||
[[deps.Zlib_jll]]
|
|
||||||
deps = ["Libdl"]
|
|
||||||
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
|
|
||||||
version = "1.2.13+1"
|
|
||||||
|
|
||||||
[[deps.Zstd_jll]]
|
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl"]
|
|
||||||
git-tree-sha1 = "555d1076590a6cc2fdee2ef1469451f872d8b41b"
|
|
||||||
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
|
|
||||||
version = "1.5.6+1"
|
|
||||||
|
|
||||||
[[deps.libblastrampoline_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl"]
|
|
||||||
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
|
|
||||||
version = "5.11.0+0"
|
|
||||||
|
|
||||||
[[deps.micromamba_jll]]
|
|
||||||
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl"]
|
|
||||||
git-tree-sha1 = "b4a5a3943078f9fd11ae0b5ab1bdbf7718617945"
|
|
||||||
uuid = "f8abcde7-e9b7-5caa-b8af-a437887ae8e4"
|
|
||||||
version = "1.5.8+0"
|
|
||||||
|
|
||||||
[[deps.nghttp2_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl"]
|
|
||||||
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
|
|
||||||
version = "1.59.0+0"
|
|
||||||
|
|
||||||
[[deps.p7zip_jll]]
|
|
||||||
deps = ["Artifacts", "Libdl"]
|
|
||||||
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
|
|
||||||
version = "17.4.0+2"
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
name = "SQLLLM"
|
|
||||||
uuid = "2ebc79c7-cc10-4a3a-9665-d2e1d61e63d3"
|
|
||||||
authors = ["narawat lamaiin <narawat@outlook.com>"]
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
|
||||||
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
|
|
||||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
|
||||||
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
|
||||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
|
||||||
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
|
|
||||||
GeneralUtils = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
|
|
||||||
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
|
||||||
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
|
|
||||||
LLMMCTS = "d76c5a4d-449e-4835-8cc4-dd86ec44f241"
|
|
||||||
LibPQ = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1"
|
|
||||||
MQTTClient = "985f35cc-2c3d-4943-b8c1-f0931d5f0959"
|
|
||||||
PrettyPrinting = "54e16d92-306c-5ea0-a30b-337be88ac337"
|
|
||||||
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
|
|
||||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
|
||||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
|
||||||
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
|
|
||||||
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
|
||||||
URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
|
|
||||||
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"mqttServerInfo": {
|
|
||||||
"description": "mqtt server info",
|
|
||||||
"port": 1883,
|
|
||||||
"broker": "mqtt.yiem.cc"
|
|
||||||
},
|
|
||||||
"testingOrProduction": {
|
|
||||||
"value": "testing",
|
|
||||||
"description": "agent status, couldbe testing or production"
|
|
||||||
},
|
|
||||||
"agentid": {
|
|
||||||
"value": "2b74b87a-5413-4fe2-a4d3-405891051680",
|
|
||||||
"description": "a unique id for this agent"
|
|
||||||
},
|
|
||||||
"agentCentralConfigTopic": {
|
|
||||||
"mqtttopic": "/yiem_branch_1/agent/sommelier/backend/config/api/v1.1",
|
|
||||||
"description": "a central agent server's topic to get this agent config"
|
|
||||||
},
|
|
||||||
"servicetopic": {
|
|
||||||
"mqtttopic": [
|
|
||||||
"/yiem/branch_1/agent/wine/backend/prompt/api_v1/testing"
|
|
||||||
],
|
|
||||||
"description": "a topic this agent are waiting for service request"
|
|
||||||
},
|
|
||||||
"role": {
|
|
||||||
"value": "sommelier",
|
|
||||||
"description": "agent role"
|
|
||||||
},
|
|
||||||
"organization": {
|
|
||||||
"value": "yiem_branch_1",
|
|
||||||
"description": "organization name"
|
|
||||||
},
|
|
||||||
"externalservice": {
|
|
||||||
"text2textinstruct": {
|
|
||||||
"mqtttopic": "/loadbalancer/requestingservice",
|
|
||||||
"description": "text to text service with instruct LLM",
|
|
||||||
"llminfo": {
|
|
||||||
"name": "llama3instruct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"virtualWineCustomer_1": {
|
|
||||||
"mqtttopic": "/virtualenvironment/winecustomer",
|
|
||||||
"description": "text to text service with instruct LLM that act as wine customer",
|
|
||||||
"llminfo": {
|
|
||||||
"name": "llama3instruct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"text2textchat": {
|
|
||||||
"mqtttopic": "/loadbalancer/requestingservice",
|
|
||||||
"description": "text to text service with instruct LLM",
|
|
||||||
"llminfo": {
|
|
||||||
"name": "llama3instruct"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
module SQLLLM
|
|
||||||
|
|
||||||
# export
|
|
||||||
|
|
||||||
|
|
||||||
""" Order by dependencies of each file. The 1st included file must not depend on any other
|
|
||||||
files and each file can only depend on the file included before it.
|
|
||||||
"""
|
|
||||||
|
|
||||||
include("type.jl")
|
|
||||||
using .type
|
|
||||||
|
|
||||||
include("util.jl")
|
|
||||||
using .util
|
|
||||||
|
|
||||||
include("llmfunction.jl")
|
|
||||||
using .llmfunction
|
|
||||||
|
|
||||||
include("interface.jl")
|
|
||||||
using .interface
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end # module SQLLLM
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,955 +0,0 @@
|
|||||||
module llmfunction
|
|
||||||
|
|
||||||
export listAllTable_json, listAllTable_str, tableinfo, getdata, finalAnswerBox,
|
|
||||||
getTableNameFromSQL, extractContent_dataframe, SQLexecution
|
|
||||||
|
|
||||||
using HTTP, JSON3, URIs, Random, PrettyPrinting, UUIDs, LibPQ, Tables, DataFrames, CSV,
|
|
||||||
DataStructures, StatsBase
|
|
||||||
using GeneralUtils, LLMMCTS
|
|
||||||
using ..util
|
|
||||||
|
|
||||||
# ---------------------------------------------- 100 --------------------------------------------- #
|
|
||||||
|
|
||||||
|
|
||||||
""" List all tables in the database and return in JSON format.
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `executeSQL::Function`
|
|
||||||
A connection object to Postgres database
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `NamedTuple{(:result, :success), Tuple{DataFrame, Bool}}`
|
|
||||||
|
|
||||||
# Example
|
|
||||||
```jldoctest
|
|
||||||
julia> using LibPQ, SQLLLM
|
|
||||||
julia> function executeSQL(sql)
|
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.122 port=5432 dbname=xyz user=zyx password=1234")
|
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
|
||||||
close(DBconnection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
julia> response = SQLLLM.listAllTable_json(executeSQL)
|
|
||||||
julia> result = response[:result]
|
|
||||||
```
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function listAllTable_json(executeSQL::Function
|
|
||||||
)::NamedTuple{(:result, :success),Tuple{DataFrame,Bool}}
|
|
||||||
|
|
||||||
sql = """
|
|
||||||
SELECT
|
|
||||||
table_name,
|
|
||||||
obj_description(relfilenode, 'pg_class') AS table_comment,
|
|
||||||
string_agg(column_name || ' (' || data_type || ')', ', ') AS columns
|
|
||||||
FROM
|
|
||||||
information_schema.columns
|
|
||||||
JOIN
|
|
||||||
pg_class ON table_name = relname
|
|
||||||
WHERE
|
|
||||||
table_schema = 'public'
|
|
||||||
GROUP BY
|
|
||||||
table_name, relfilenode
|
|
||||||
ORDER BY
|
|
||||||
table_name;
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = executeSQL(sql)
|
|
||||||
df = DataFrame(result)
|
|
||||||
tablesinfo_df = df
|
|
||||||
|
|
||||||
return (result=tablesinfo_df, success=true)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function listAllTable_str(executeSQL::Function
|
|
||||||
)::NamedTuple{(:result, :success),Tuple{String,Bool}}
|
|
||||||
sql = """
|
|
||||||
SELECT
|
|
||||||
table_name,
|
|
||||||
obj_description(relfilenode, 'pg_class') AS table_comment,
|
|
||||||
string_agg(column_name || ' (' || data_type || ')', ', ') AS columns
|
|
||||||
FROM
|
|
||||||
information_schema.columns
|
|
||||||
JOIN
|
|
||||||
pg_class ON table_name = relname
|
|
||||||
WHERE
|
|
||||||
table_schema = 'public'
|
|
||||||
GROUP BY
|
|
||||||
table_name, relfilenode
|
|
||||||
ORDER BY
|
|
||||||
table_name;
|
|
||||||
"""
|
|
||||||
result = executeSQL(sql)
|
|
||||||
df = DataFrame(result)
|
|
||||||
tableinfo = "Here are a list of available tables in the database (each row is in this format: table name; table comment; table columns): \n"
|
|
||||||
for i in 1:size(df)[1]
|
|
||||||
table_name = df[i, 1]
|
|
||||||
table_comment = df[i, 2]
|
|
||||||
columns = df[i, 3]
|
|
||||||
tableinfo *= "$i. $table_name; $table_comment; $columns\n"
|
|
||||||
end
|
|
||||||
return (result=tableinfo, success=true)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
""" Get table description, column comments and the first 3-rows of the table data
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `executeSQL::Function`
|
|
||||||
A connection object to Postgres database
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `tableinfo::String`
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
function tableinfo_str(executeSQL::Function, tablename::String)::NamedTuple{(:result, :success),Tuple{String,Bool}}
|
|
||||||
|
|
||||||
sql = """
|
|
||||||
SELECT
|
|
||||||
column_name,
|
|
||||||
data_type,
|
|
||||||
col_description(format('%s.%s', table_schema, table_name)::regclass::oid, ordinal_position) AS column_comment
|
|
||||||
FROM
|
|
||||||
information_schema.columns
|
|
||||||
WHERE
|
|
||||||
table_name = '$tablename'
|
|
||||||
AND table_schema = 'public';
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = executeSQL(sql)
|
|
||||||
df = DataFrame(result)
|
|
||||||
|
|
||||||
tableinfo = "Here are info of table $tablename (each row is in this format: column name; data type; column comment):\n"
|
|
||||||
for i in 1:size(df)[1]
|
|
||||||
column_name = df[i, 1]
|
|
||||||
column_datatype = df[i, 2]
|
|
||||||
column_comment = df[i, 3]
|
|
||||||
tableinfo *= "$i. $column_name; $column_datatype; $column_comment \n"
|
|
||||||
end
|
|
||||||
|
|
||||||
return (result=tableinfo, success=true)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
""" Get table description, column comments.
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `executeSQL::Function`
|
|
||||||
A connection object to Postgres database
|
|
||||||
- `tablenames<:AbstractVector`
|
|
||||||
A list of table name to get description
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `NamedTuple{(:result), Tuple{String}}`
|
|
||||||
Text contain multiple table info
|
|
||||||
|
|
||||||
# Example
|
|
||||||
```jldoctest
|
|
||||||
julia> using SQLLLM, LibPQ
|
|
||||||
julia> function executeSQL(sql)
|
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.122 port=5432 dbname=xyz user=zyx password=1234")
|
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
|
||||||
close(DBconnection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
julia> response = SQLLLM.tableinfo(executeSQL, ["wine", "food"])
|
|
||||||
julia> result = response[:result]
|
|
||||||
```
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function tableinfo(executeSQL::Function, tablenames::T
|
|
||||||
)::NamedTuple{(:result,),Tuple{String}} where {T<:AbstractVector}
|
|
||||||
# list all tables in a database
|
|
||||||
sql = """
|
|
||||||
SELECT pg_namespace.nspname AS schema_name,
|
|
||||||
relname AS table_name,
|
|
||||||
pg_catalog.obj_description(pg_class.oid) AS comment
|
|
||||||
FROM pg_class
|
|
||||||
INNER JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
|
|
||||||
WHERE pg_namespace.nspname = 'public' -- Replace 'public' with your desired schema
|
|
||||||
AND pg_class.relkind IN ('r', 't');
|
|
||||||
"""
|
|
||||||
|
|
||||||
_result = executeSQL(sql)
|
|
||||||
df = DataFrame(_result)
|
|
||||||
alltable_df = df[:, [:table_name, :comment]]
|
|
||||||
tableNameList = alltable_df.table_name |> collect
|
|
||||||
|
|
||||||
# check if the requested table name exist in the database
|
|
||||||
notExistingTable = []
|
|
||||||
for i in tablenames
|
|
||||||
if i ∉ tableNameList
|
|
||||||
push!(notExistingTable, i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if !isempty(notExistingTable)
|
|
||||||
result = "Error, the following tables does not exist in the database: $(JSON3.write(notExistingTable))"
|
|
||||||
return (result=result,)
|
|
||||||
end
|
|
||||||
|
|
||||||
tableInfoStr = ""
|
|
||||||
for i in tablenames
|
|
||||||
x, _ = tableinfo_str(executeSQL, i)
|
|
||||||
tableInfoStr *= x
|
|
||||||
end
|
|
||||||
|
|
||||||
return (result=tableInfoStr,)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
""" Convert a query process in English into SQL, execute and get the result from the database.
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `query<:AbstractString`
|
|
||||||
A query to a database in SQL.
|
|
||||||
- `context::Union{Dict, Nothing}`
|
|
||||||
A context to be available at transition()
|
|
||||||
- `executeSQL::Function`
|
|
||||||
A connection object connected to the database
|
|
||||||
- `text2textInstructLLM::Function`
|
|
||||||
A function that handles communication to LLM service.
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `NamedTuple{(:result, :errormsg, success), Tuple{String, String, Bool}}`
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
- [x] getdata directly using sql execute
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function getdata(query::T, context::Union{Dict,Nothing}, executeSQL::Function,
|
|
||||||
text2textInstructLLM::Function;
|
|
||||||
) where {T<:AbstractString}
|
|
||||||
|
|
||||||
response = SQLexecution(executeSQL, query)
|
|
||||||
if response[:success]
|
|
||||||
extracted = extractContent_dataframe(response[:result], context, text2textInstructLLM)
|
|
||||||
response_ = (result=extracted, errormsg=nothing, success=true)
|
|
||||||
return response_
|
|
||||||
else
|
|
||||||
response_ = (result=nothing, errormsg=response[:errormsg], success=false)
|
|
||||||
return response_
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# function getdata(query::T, context::Union{Dict, Nothing}, executeSQL::Function,
|
|
||||||
# text2textInstructLLM::Function;
|
|
||||||
# )::NamedTuple{(:result, :errormsg, :success), Tuple{String, Union{String, Nothing}, Bool}} where {T<:AbstractString}
|
|
||||||
|
|
||||||
# # get table info here because it'll be called only 1-time. If this function is in
|
|
||||||
# # getdata_decisionMaker(), it'll be called everytime
|
|
||||||
# mentionedtable = getTableNameFromSQL(query, text2textInstructLLM)
|
|
||||||
# mentionedTableInfo = tableinfo(executeSQL, mentionedtable)[:result]
|
|
||||||
# context[:mentionedTableInfo] = mentionedTableInfo
|
|
||||||
|
|
||||||
# initialstate = Dict{Symbol, Any}(
|
|
||||||
# :reward=> 0,
|
|
||||||
# :isterminal=> false,
|
|
||||||
# :evaluation=> nothing,
|
|
||||||
# :errormsg=> nothing,
|
|
||||||
# :errorexplain=> nothing,
|
|
||||||
|
|
||||||
# :question=> query,
|
|
||||||
# :code=> nothing,
|
|
||||||
# :response=> nothing,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# transitionargs = (
|
|
||||||
# # decisionMaker=getdata_decisionMaker,
|
|
||||||
# # evaluator=getdata_evaluator,
|
|
||||||
# # reflector=getdata_reflector,
|
|
||||||
# context=context,
|
|
||||||
# executeSQL=executeSQL,
|
|
||||||
# text2textInstructLLM=text2textInstructLLM
|
|
||||||
# )
|
|
||||||
# result_1, result_2 = LLMMCTS.runMCTS(initialstate, getdata_transition, transitionargs;
|
|
||||||
# totalsample=1, maxdepth=3, maxiterations=1, explorationweight=1.0)
|
|
||||||
|
|
||||||
# if result_2[:isterminal] == true
|
|
||||||
# return (result=result_2[:response], errormsg=nothing, success=true) # succues=true to finish getdata()
|
|
||||||
# else
|
|
||||||
# # return (response="Failed to act with the following error message: $(result_2[:errorexplain])", select=nothing, reward=0, success=false)
|
|
||||||
# return (result="Failed to get the data. $(result_1[:errormsg])",
|
|
||||||
# errormsg=result_1[:errormsg], success=false)
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
`v::Integer`
|
|
||||||
dummy variable
|
|
||||||
|
|
||||||
# Return
|
|
||||||
|
|
||||||
# Example
|
|
||||||
```jldoctest
|
|
||||||
julia>
|
|
||||||
```
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
- [] update docstring
|
|
||||||
- [PENDING] implement the function
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function getdata_evaluator(newstate, config)
|
|
||||||
|
|
||||||
return (evaluation="None", score=0)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
""" State transition
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `state<:AbstractDict`
|
|
||||||
A game state
|
|
||||||
- `args::NamedTuple`
|
|
||||||
Arguments for various function within transition()
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `NamedTuple{(:newNodeKey, :newstate, :progressvalue), Tuple{String, T, Integer}}`
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function getdata_transition(state::T, args::NamedTuple
|
|
||||||
)::NamedTuple{(:newNodeKey, :newstate, :progressvalue),Tuple{String,T,Integer}} where {T<:AbstractDict}
|
|
||||||
|
|
||||||
|
|
||||||
# decisionMaker::Function = args[:decisionMaker]
|
|
||||||
# evaluator::Function = args[:evaluator]
|
|
||||||
# reflector::Function = args[:reflector]
|
|
||||||
context = args[:context]
|
|
||||||
executeSQL::Function = args[:executeSQL]
|
|
||||||
text2textInstructLLM::Function = args[:text2textInstructLLM]
|
|
||||||
|
|
||||||
thought, sql =
|
|
||||||
if state[:code] !== nothing
|
|
||||||
result = getdata_decisionMaker(state, context, text2textInstructLLM)
|
|
||||||
result[:thought], result[:code]
|
|
||||||
else
|
|
||||||
nothing, state[:question]
|
|
||||||
end
|
|
||||||
|
|
||||||
# make new state
|
|
||||||
newNodeKey = GeneralUtils.uuid4snakecase()
|
|
||||||
newstate = deepcopy(state)
|
|
||||||
|
|
||||||
response, success, errormsg, reward, isterminal =
|
|
||||||
if sql !== nothing
|
|
||||||
response, success, errormsg, reward, isterminal = SQLexecution(executeSQL, sql)
|
|
||||||
else
|
|
||||||
(result=nothing,
|
|
||||||
success=false,
|
|
||||||
errormsg="SQL execution failed. An unexpected error occurred. Please try again.",
|
|
||||||
reward=0,
|
|
||||||
isterminal=false)
|
|
||||||
end
|
|
||||||
println("getdata_transition() 1 ", @__FILE__, " ", @__LINE__)
|
|
||||||
newstate[:code] = sql
|
|
||||||
newstate[:response] = response
|
|
||||||
newstate[:errorexplain] = thought
|
|
||||||
newstate[:errormsg] = errormsg
|
|
||||||
newstate[:reward] = reward
|
|
||||||
newstate[:isterminal] = isterminal
|
|
||||||
if response !== nothing
|
|
||||||
extracted = extractContent_dataframe(response, context, text2textInstructLLM)
|
|
||||||
newstate[:response] = extracted
|
|
||||||
end
|
|
||||||
println("getdata_transition() 2 ", @__FILE__, " ", @__LINE__)
|
|
||||||
stateevaluation = "None"
|
|
||||||
progressvalue = 0
|
|
||||||
|
|
||||||
return (newNodeKey=newNodeKey, newstate=newstate, progressvalue=progressvalue)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
""" Make a decision using LLM
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `state::Dict`
|
|
||||||
A game state
|
|
||||||
- `context::Dict`
|
|
||||||
Additional context for LLM to use
|
|
||||||
- `text2textInstructLLM::Function`
|
|
||||||
A function to handles communication to LLM
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `NamedTuple{(:thought, :code, :success, :errormsg), Tuple{String, String, Bool, Union{String, Nothing}}}`
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function getdata_decisionMaker(state::Dict, context::Dict, text2textInstructLLM::Function
|
|
||||||
)::NamedTuple{(:thought, :code, :success, :errormsg),Tuple{Union{String,Nothing},Union{String,Nothing},Bool,Union{String,Nothing}}}
|
|
||||||
|
|
||||||
Hints = "None"
|
|
||||||
|
|
||||||
# """
|
|
||||||
# Here are some useful SQL programs:
|
|
||||||
# $usefulSQL
|
|
||||||
# """
|
|
||||||
|
|
||||||
# systemmsg =
|
|
||||||
# """
|
|
||||||
# You are an assistant helping the user to execute SQL code from the user's query.
|
|
||||||
|
|
||||||
# At each round of conversation, the user will give you:
|
|
||||||
# Context: ...
|
|
||||||
# User intention: ...
|
|
||||||
# Code executed from the last round: ...
|
|
||||||
# Execution error: execution error of the last round code.
|
|
||||||
|
|
||||||
# You should consider the following guidelines:
|
|
||||||
# - Text information in the database is sometimes stored in lower case. If your search returns empty, try using lower case to search.
|
|
||||||
|
|
||||||
# You should then respond to the user with:
|
|
||||||
# - thought: Why the code does not complete the task. What does the execution error imply exactly?
|
|
||||||
# - plan: Step-by-step instructions of how to complete the task.
|
|
||||||
# 1) Focus on improving the code from the last round.
|
|
||||||
# 2) Do not create any table in the database.
|
|
||||||
# - code:
|
|
||||||
# 1) Write new improved code.
|
|
||||||
# 2) Do not wrap the code and no comment as it will be executed directly without any modification against the database.
|
|
||||||
|
|
||||||
# You should only respond in format as described below and nothing more:
|
|
||||||
# thought: ...
|
|
||||||
# plan:
|
|
||||||
# 1) ...
|
|
||||||
# 2) ...
|
|
||||||
# ...
|
|
||||||
# code: ...
|
|
||||||
|
|
||||||
# Let's begin!
|
|
||||||
# """
|
|
||||||
|
|
||||||
systemmsg = """
|
|
||||||
You are an assistant helping the user to execute SQL code from the user's query.
|
|
||||||
|
|
||||||
At each round of conversation, the user will give you:
|
|
||||||
Context: ...
|
|
||||||
User intention: ...
|
|
||||||
Code executed from the last round: ...
|
|
||||||
Execution error: execution error of the last round code.
|
|
||||||
|
|
||||||
You should consider the following guidelines:
|
|
||||||
- Text information in the database is sometimes stored in lower case. If your search returns empty, try using lower case to search.
|
|
||||||
|
|
||||||
You should then respond to the user with:
|
|
||||||
1) Understanding:
|
|
||||||
- State your understanding about the current situation.
|
|
||||||
2) Reasoning:
|
|
||||||
- State your step by step reasoning about the current situation.
|
|
||||||
3) Plan: Step-by-step instructions of how to complete the task.
|
|
||||||
- Focus on improving the code from the last round.
|
|
||||||
- Do not create any table in the database.
|
|
||||||
4) Code:
|
|
||||||
- Write new improved code.
|
|
||||||
- Do not wrap the code and no comment as it will be executed directly without any modification against the database.
|
|
||||||
|
|
||||||
You should only respond in format as described below and nothing more:
|
|
||||||
Understanding: ...
|
|
||||||
Reasoning: ...
|
|
||||||
Plan:
|
|
||||||
1) ...
|
|
||||||
2) ...
|
|
||||||
...
|
|
||||||
Code: ...
|
|
||||||
|
|
||||||
Let's begin!
|
|
||||||
"""
|
|
||||||
|
|
||||||
noise = ""
|
|
||||||
note_flag = ""
|
|
||||||
for attempt in 1:10
|
|
||||||
usermsg = """
|
|
||||||
Context:
|
|
||||||
$(context[:mentionedTableInfo])
|
|
||||||
User intention: $(context[:userintention])
|
|
||||||
Code executed from the last round: $(state[:code])
|
|
||||||
Execution error: $(state[:errormsg])
|
|
||||||
$noise
|
|
||||||
$note_flag
|
|
||||||
"""
|
|
||||||
|
|
||||||
_prompt =
|
|
||||||
[
|
|
||||||
Dict(:name => "system", :text => systemmsg),
|
|
||||||
Dict(:name => "user", :text => usermsg)
|
|
||||||
]
|
|
||||||
|
|
||||||
# put in model format
|
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
|
||||||
prompt *= """
|
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
|
||||||
try
|
|
||||||
response = text2textInstructLLM(prompt)
|
|
||||||
responsedict = GeneralUtils.textToDict(response,
|
|
||||||
["Understanding", "Reasoning", "Plan", "Code"];
|
|
||||||
rightmarker=":", symbolkey=true, lowercasekey=true)
|
|
||||||
_code = responsedict[:code]
|
|
||||||
code = strip(_code)
|
|
||||||
|
|
||||||
if length(code) < 2
|
|
||||||
error("No code available.")
|
|
||||||
elseif code == state[:code]
|
|
||||||
error("generated code is the same as earlier.")
|
|
||||||
else
|
|
||||||
end
|
|
||||||
|
|
||||||
# check code
|
|
||||||
if occursin("CREATE TABLE", code)
|
|
||||||
note_flag = "Note: Create new table is not allowed."
|
|
||||||
error("create table is not allowed")
|
|
||||||
elseif occursin("```", code)
|
|
||||||
error("Note: code contains backtick ` which is not allowed")
|
|
||||||
elseif code[end] != ';'
|
|
||||||
error("SQL does not ending with ';'")
|
|
||||||
elseif count(';', code) > 1
|
|
||||||
error("Multiple SQL statement are not allowed")
|
|
||||||
else
|
|
||||||
end
|
|
||||||
|
|
||||||
println("\n~~~ getdata_decisionMaker() ", @__FILE__, " ", @__LINE__)
|
|
||||||
pprintln(Dict(responsedict))
|
|
||||||
return (thought=responsedict[:reasoning], code=code, success=true, errormsg=nothing)
|
|
||||||
catch e
|
|
||||||
io = IOBuffer()
|
|
||||||
showerror(io, e)
|
|
||||||
errorMsg = String(take!(io))
|
|
||||||
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
|
||||||
print("Attempt $attempt. Error occurred: $errorMsg\n$st")
|
|
||||||
println("")
|
|
||||||
noise = GeneralUtils.randstrings(3, 5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return (thought=nothing, code=nothing, success=false,
|
|
||||||
errormsg="Failed to generate SQL after numerous attempts.")
|
|
||||||
end
|
|
||||||
|
|
||||||
""" Execute a given SQL.
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `sql::T<:AbstractString`
|
|
||||||
A SQL command
|
|
||||||
- `executeSQL::Function`
|
|
||||||
A connection object to a database
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `NamedTuple{(:result, :errormsg, :reward, :isterminal), Tuple{Union{Nothing, DataFrame}, String, Integer, Bool}}`
|
|
||||||
|
|
||||||
# Example
|
|
||||||
```jldoctest
|
|
||||||
julia> using LibPQ, SQLLLM
|
|
||||||
julia> function executeSQL(sql)
|
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.122 port=5432 dbname=xyz user=zyx password=1234")
|
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
|
||||||
close(DBconnection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
julia> response = SQLLLM.SQLexecution(executeSQL, sql)
|
|
||||||
```
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
# function SQLexecution(executeSQL::Function, sql::T
|
|
||||||
# )::NamedTuple{(:result, :success, :errormsg, :reward, :isterminal), Tuple{Union{DataFrame, Nothing}, Bool, Union{String, Nothing}, Integer, Bool}} where {T<:AbstractString}
|
|
||||||
# println("\n~~~ 1-01 ", @__FILE__, " ", @__LINE__)
|
|
||||||
# #XXX dummy SQL. use for testing
|
|
||||||
# # sql = "SELECT w.wine_name FROM wine w JOIN wine_food wf ON w.wine_id = wf.wine_id JOIN food f ON wf.food_id = f.food_id WHERE f.\"food_name\" = 'lamb';"
|
|
||||||
# # sql = " SELECT w.wine_name FROM wine w JOIN food f ON f.food_name = 'lamb' JOIN wine_food wf ON w.wine_id = wf.wine_id AND f.food_id = wf.food_id GROUP BY w.wine_name ORDER BY COUNT(DISTINCT w.wine_id) DESC;"
|
|
||||||
# # sql = " SELECT COUNT(DISTINCT wf.wine_id) FROM wine w JOIN wine_food wf ON w.wine_id = wf.wine_id JOIN food f ON wf.food_id = f.food_id WHERE f.food_name ILIKE '%lamb%'"
|
|
||||||
|
|
||||||
# #XXX use for package testing, remove when done
|
|
||||||
# # ans = "1.schilfwein zweigelt 2.cabernet sauvignon reserve limited edition"
|
|
||||||
# # ans = "There are 1500 wines that can be paired with lamb."
|
|
||||||
# # ans = "1500"
|
|
||||||
# # return (response=ans, errormsg=nothing, reward=1, isterminal=true)
|
|
||||||
|
|
||||||
# # add LIMIT to the SQL to prevent loading large data
|
|
||||||
# sql = strip(sql)
|
|
||||||
# println("\n~~~ SQL 1", @__FILE__, " ", @__LINE__)
|
|
||||||
# println(sql)
|
|
||||||
# println("\n~~~ 1-02 ", @__FILE__, " ", @__LINE__)
|
|
||||||
|
|
||||||
# if sql[end] != ';'
|
|
||||||
# errorMsg = "Error, SQL execution failed because it does not ended with ';'"
|
|
||||||
# return (result=nothing, success=false, errormsg=errorMsg, reward=0, isterminal=false)
|
|
||||||
# end
|
|
||||||
# println("\n~~~ 1-03 ", @__FILE__, " ", @__LINE__)
|
|
||||||
# if !occursin("LIMIT", sql)
|
|
||||||
# # sql = sql[1:end-1] * " LIMIT 100;"
|
|
||||||
# sql = sql[1:end-1] * " ORDER BY RANDOM() LIMIT 2;"
|
|
||||||
# end
|
|
||||||
|
|
||||||
# println("\n~~~ SQL 2", @__FILE__, " ", @__LINE__)
|
|
||||||
# println(sql)
|
|
||||||
# println("\n~~~ 1-1 ", @__FILE__, " ", @__LINE__)
|
|
||||||
# result = executeSQL(sql)
|
|
||||||
# println("\n~~~ 1-2 ", @__FILE__, " ", @__LINE__)
|
|
||||||
# df = DataFrame(result)
|
|
||||||
# println("\n~~~ raw df ", df)
|
|
||||||
# tablesize = size(df)
|
|
||||||
# println("\n~~~ df size ", tablesize)
|
|
||||||
# println("\n~~~ 6 ", @__FILE__, " ", @__LINE__)
|
|
||||||
# row = tablesize[1]
|
|
||||||
# println("\n~~~ 7 ", @__FILE__, " ", @__LINE__)
|
|
||||||
# if row == 0 # if 0 row
|
|
||||||
# errorMsg = "The resulting table has 0 row. Possible causes: 1) SQL is incorrect 2) There is no data that match your search criteria."
|
|
||||||
# return (result=nothing, success=false, errormsg=errorMsg, reward=0, isterminal=false)
|
|
||||||
# end
|
|
||||||
# println("\n~~~ 8 ", @__FILE__, " ", @__LINE__)
|
|
||||||
# df1 =
|
|
||||||
# if row > 2
|
|
||||||
# # ramdom row to pick
|
|
||||||
# df[sample(1:nrow(df), 2, replace=false), :] # random select 2 rows from df
|
|
||||||
# else
|
|
||||||
# df
|
|
||||||
# end
|
|
||||||
|
|
||||||
# println("\n~~~ SQLexecution result ", @__FILE__, " ", @__LINE__)
|
|
||||||
# println(df1)
|
|
||||||
# return (result=df1, success=true, errormsg=nothing, reward=1, isterminal=true)
|
|
||||||
# end
|
|
||||||
function SQLexecution(executeSQL::Function, sql::T
|
|
||||||
) where {T<:AbstractString}
|
|
||||||
|
|
||||||
try
|
|
||||||
#XXX dummy SQL. use for testing
|
|
||||||
# sql = "SELECT w.wine_name FROM wine w JOIN wine_food wf ON w.wine_id = wf.wine_id JOIN food f ON wf.food_id = f.food_id WHERE f.\"food_name\" = 'lamb';"
|
|
||||||
# sql = " SELECT w.wine_name FROM wine w JOIN food f ON f.food_name = 'lamb' JOIN wine_food wf ON w.wine_id = wf.wine_id AND f.food_id = wf.food_id GROUP BY w.wine_name ORDER BY COUNT(DISTINCT w.wine_id) DESC;"
|
|
||||||
# sql = " SELECT COUNT(DISTINCT wf.wine_id) FROM wine w JOIN wine_food wf ON w.wine_id = wf.wine_id JOIN food f ON wf.food_id = f.food_id WHERE f.food_name ILIKE '%lamb%'"
|
|
||||||
|
|
||||||
#XXX use for package testing, remove when done
|
|
||||||
# ans = "1.schilfwein zweigelt 2.cabernet sauvignon reserve limited edition"
|
|
||||||
# ans = "There are 1500 wines that can be paired with lamb."
|
|
||||||
# ans = "1500"
|
|
||||||
# return (response=ans, errormsg=nothing, reward=1, isterminal=true)
|
|
||||||
|
|
||||||
# add LIMIT to the SQL to prevent loading large data
|
|
||||||
sql = strip(sql)
|
|
||||||
if sql[end] == ';'
|
|
||||||
if !occursin("LIMIT", sql)
|
|
||||||
# sql = sql[1:end-1] * " LIMIT 100;"
|
|
||||||
sql = sql[1:end-1] * " ORDER BY RANDOM() LIMIT 2;"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
sql = sql * ";"
|
|
||||||
end
|
|
||||||
println("\n~~~ SQLexecution() SQL: ", @__FILE__, " ", @__LINE__)
|
|
||||||
println(sql)
|
|
||||||
|
|
||||||
result = executeSQL(sql)
|
|
||||||
df = DataFrame(result)
|
|
||||||
|
|
||||||
tablesize = size(df)
|
|
||||||
row, column = tablesize
|
|
||||||
if row == 0 # if 0 row
|
|
||||||
error("The resulting table has 0 row. Possible causes: 1) You might be searching in the wrong place 2) There could be a typo in your search query.")
|
|
||||||
elseif column > 30
|
|
||||||
error("SQL execution failed. An unexpected error occurred. Please try again.")
|
|
||||||
end
|
|
||||||
|
|
||||||
df1 =
|
|
||||||
if row > 2
|
|
||||||
# ramdom row to pick
|
|
||||||
df[sample(1:nrow(df), 2, replace=false), :] # random select 2 rows from df
|
|
||||||
else
|
|
||||||
df
|
|
||||||
end
|
|
||||||
|
|
||||||
println("\n~~~ SQLexecution() result: ", @__FILE__, " ", @__LINE__)
|
|
||||||
println(df1)
|
|
||||||
return (result=df1, success=true, errormsg=nothing)
|
|
||||||
catch e
|
|
||||||
io = IOBuffer()
|
|
||||||
showerror(io, e)
|
|
||||||
errorMsg = String(take!(io))
|
|
||||||
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
|
||||||
println(errorMsg)
|
|
||||||
response = (result=nothing, success=false, errormsg=errorMsg)
|
|
||||||
return response
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
""" Extract content from a dataframe with LLM.
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `df::DataFrame`
|
|
||||||
A dataframe to be read.
|
|
||||||
- `context::Dict`
|
|
||||||
A dictionary to give LLM more context
|
|
||||||
- `text2textInstructLLM::Function`
|
|
||||||
A function that handles communication to LLM service
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `result::String`
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function extractContent_dataframe(df::DataFrame, context::Dict, text2textInstructLLM::Function
|
|
||||||
)::String
|
|
||||||
tablesize = size(df)
|
|
||||||
row = tablesize[1]
|
|
||||||
column = tablesize[2]
|
|
||||||
#[PENDING] Since selected column depend on the question, there should be a better way to select column on the fly, not hard coded like this.
|
|
||||||
# df1 =
|
|
||||||
# if column > 10 # assuming if columns > 10, agent is getting wine info but the info is too much
|
|
||||||
# selectedcolumn = ["wine_id",
|
|
||||||
# "wine_name",
|
|
||||||
# "winery",
|
|
||||||
# "region",
|
|
||||||
# "country",
|
|
||||||
# "wine_type",
|
|
||||||
# "grape",
|
|
||||||
# "serving_temperature",
|
|
||||||
# "intensity",
|
|
||||||
# "sweetness",
|
|
||||||
# "tannin",
|
|
||||||
# "acidity",
|
|
||||||
# "fizziness",
|
|
||||||
# "tasting_notes"]
|
|
||||||
# df1 = df[:, selectedcolumn]
|
|
||||||
# else
|
|
||||||
# df
|
|
||||||
# end
|
|
||||||
|
|
||||||
df1 = df
|
|
||||||
|
|
||||||
dfstr = dfToString(df1)
|
|
||||||
|
|
||||||
systemmsg = """
|
|
||||||
You are an assistant that readouts the resulting table after the user executing SQL command.
|
|
||||||
|
|
||||||
At each round of conversation, the user will give you:
|
|
||||||
- User intention: ...
|
|
||||||
- Resulting table dimension: ...
|
|
||||||
- Resulting table: The resulting table after executing the user's intention.
|
|
||||||
|
|
||||||
You should then respond to the user with:
|
|
||||||
- About_resulting_table:
|
|
||||||
1) What is the resulting table represent?
|
|
||||||
- Search_summary:
|
|
||||||
1) Summarize the table's content based on the user intension in verbal English.
|
|
||||||
Here are some example:
|
|
||||||
Bad example (you are not Summarize the table content): there are 2 columns in the table i.e. "cash" and "number".
|
|
||||||
2) Do not generate additional text.
|
|
||||||
|
|
||||||
You should only respond in format as described below:
|
|
||||||
About_resulting_table: ...
|
|
||||||
Search_summary: ...
|
|
||||||
|
|
||||||
Let's begin!
|
|
||||||
"""
|
|
||||||
usermsg = """
|
|
||||||
User intention: $(context[:userintention])
|
|
||||||
Resulting table: $dfstr
|
|
||||||
"""
|
|
||||||
_prompt =
|
|
||||||
[
|
|
||||||
Dict(:name => "system", :text => systemmsg),
|
|
||||||
Dict(:name => "user", :text => usermsg)
|
|
||||||
]
|
|
||||||
|
|
||||||
# put in model format
|
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
|
||||||
prompt *= """
|
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
|
||||||
for i in 1:5
|
|
||||||
response = text2textInstructLLM(prompt)
|
|
||||||
responsedict = GeneralUtils.textToDict(response, ["About_resulting_table", "Search_summary"],
|
|
||||||
rightmarker=":", symbolkey=true)
|
|
||||||
|
|
||||||
# result = dfstr
|
|
||||||
result = """
|
|
||||||
Summary: $(responsedict[:Search_summary])
|
|
||||||
More details: $dfstr
|
|
||||||
"""
|
|
||||||
|
|
||||||
if row > 2
|
|
||||||
result *= "There are many more rows, but they are truncated because there are too many of them."
|
|
||||||
end
|
|
||||||
|
|
||||||
println("\n~~~ extractContent_dataframe() ", @__FILE__, " ", @__LINE__)
|
|
||||||
println(result)
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
error("Failed to get Code part.")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
""" Extract a database's table name that mentioned in SQL
|
|
||||||
|
|
||||||
# Arguments
|
|
||||||
- `sql<:AbstractString`
|
|
||||||
SQL command
|
|
||||||
- `text2textInstructLLM::Function`
|
|
||||||
A function that handles communication to LLM service
|
|
||||||
|
|
||||||
# Return
|
|
||||||
- `tablename::Vector{String}`
|
|
||||||
A list of table name
|
|
||||||
|
|
||||||
# Example
|
|
||||||
```jldoctest
|
|
||||||
julia> using SQLLLM, UUIDs, GeneralUtils
|
|
||||||
julia> sql = "Get all rows from the \"food\" table where the description contains the word \"lamb\". Then, join this result with the \"wine_food\" table on the \"food_id\" column to get a list of wines that can be paired with lamb. Finally, group the result by the \"wine_id\" column and count the number of unique wines."
|
|
||||||
julia> function text2textInstructLLM(prompt::String)
|
|
||||||
config = Dict(
|
|
||||||
:mqttServerInfo => Dict(
|
|
||||||
:description => "mqtt server info",
|
|
||||||
:port => 1883,
|
|
||||||
:broker => "mqtt.yiem.cc"
|
|
||||||
),
|
|
||||||
:externalservice => Dict(
|
|
||||||
:text2textinstruct => Dict(
|
|
||||||
:mqtttopic => "/loadbalancer/requestingservice",
|
|
||||||
:description => "text to text service with instruct LLM",
|
|
||||||
:llminfo => Dict(:name => "llama3instruct")
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# apply LLM specific instruct format
|
|
||||||
externalService = config[:externalservice][:text2textinstruct]
|
|
||||||
|
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
|
||||||
externalService[:mqtttopic],
|
|
||||||
senderName= "SQLLLM",
|
|
||||||
senderId= string(uuid4()),
|
|
||||||
receiverName= "text2textinstruct",
|
|
||||||
mqttBroker= config[:mqttServerInfo][:broker],
|
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
|
||||||
)
|
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
|
||||||
:msgMeta=> msgMeta,
|
|
||||||
:payload=> Dict(
|
|
||||||
:text=> prompt,
|
|
||||||
:kwargs=> Dict(
|
|
||||||
:max_tokens=> 512,
|
|
||||||
:stop=> ["<|eot_id|>"],
|
|
||||||
:temperature=> 0.2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
|
||||||
response = _response[:response][:text]
|
|
||||||
|
|
||||||
return response
|
|
||||||
end
|
|
||||||
julia> result = SQLLLM.getTableNameFromSQL(sql, text2textInstructLLM)
|
|
||||||
```
|
|
||||||
|
|
||||||
# Signature
|
|
||||||
"""
|
|
||||||
function getTableNameFromSQL(sql::T, text2textInstructLLM::Function)::Vector{String} where {T<:AbstractString}
|
|
||||||
systemmsg = """
|
|
||||||
Extract table name out of the user query.
|
|
||||||
|
|
||||||
At each round of conversation, the user will give you:
|
|
||||||
Query: ...
|
|
||||||
|
|
||||||
You should then respond to the user with:
|
|
||||||
- table_name: a list of table name that the user mentioned in the query.
|
|
||||||
For example, ["color", "type"]
|
|
||||||
|
|
||||||
You must only respond in format as described below:
|
|
||||||
table_name: ["...", "...", ...]
|
|
||||||
|
|
||||||
Let's begin!
|
|
||||||
"""
|
|
||||||
|
|
||||||
usermsg = """
|
|
||||||
Query: $sql
|
|
||||||
"""
|
|
||||||
|
|
||||||
_prompt =
|
|
||||||
[
|
|
||||||
Dict(:name => "system", :text => systemmsg),
|
|
||||||
Dict(:name => "user", :text => usermsg)
|
|
||||||
]
|
|
||||||
|
|
||||||
# put in model format
|
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
|
||||||
prompt *= """
|
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
|
||||||
|
|
||||||
for attempt in 1:5
|
|
||||||
try
|
|
||||||
response = text2textInstructLLM(prompt)
|
|
||||||
responsedict = GeneralUtils.textToDict(response,
|
|
||||||
["table_name"],
|
|
||||||
rightmarker=":", symbolkey=true)
|
|
||||||
response = copy(JSON3.read(responsedict[:table_name]))
|
|
||||||
|
|
||||||
return response
|
|
||||||
catch e
|
|
||||||
io = IOBuffer()
|
|
||||||
showerror(io, e)
|
|
||||||
errorMsg = String(take!(io))
|
|
||||||
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
|
||||||
println("")
|
|
||||||
println("Attempt $attempt. Error occurred: $errorMsg\n$st")
|
|
||||||
println("")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("getTableNameFromSQL failed to generate a thought")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end # module llmfunction
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
module type
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end # module type
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
module util
|
|
||||||
|
|
||||||
export getDataFrameValue, dfRowtoString, dfToString
|
|
||||||
|
|
||||||
using DataFrames
|
|
||||||
|
|
||||||
|
|
||||||
""" get a value from a dataframe row by a given key
|
|
||||||
"""
|
|
||||||
getDataFrameValue(row::DataFrameRow, key::Symbol) = row.:($key)
|
|
||||||
|
|
||||||
|
|
||||||
""" convert df row into key:value string
|
|
||||||
"""
|
|
||||||
function dfRowtoString(row::DataFrameRow)::String
|
|
||||||
str = ""
|
|
||||||
for key in keys(row)
|
|
||||||
value = getDataFrameValue(row, key)
|
|
||||||
str *= "$key: $value, "
|
|
||||||
end
|
|
||||||
result = str[1:end-2] # remove ", " at the end of row
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
""" convert df table into string
|
|
||||||
"""
|
|
||||||
function dfToString(df::DataFrame)
|
|
||||||
dfstr = ""
|
|
||||||
for (i, row) in enumerate(eachrow(df))
|
|
||||||
rowstr = dfRowtoString(row)
|
|
||||||
dfstr *= "$i) $rowstr\n"
|
|
||||||
end
|
|
||||||
return dfstr
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end # module util
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
using Revise
|
|
||||||
using LibPQ, JSON3, PrettyPrinting, UUIDs, DataFrames, DataStructures, Dates, MQTTClient, Random
|
|
||||||
using SQLLLM, GeneralUtils
|
|
||||||
|
|
||||||
|
|
||||||
function executeSQL(sql)
|
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.12 port=5433 dbname=SQLVectorDB user=yiemtechnologies@gmail.com password=yiem@Postgres_0.0")
|
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
|
||||||
close(DBconnection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
sql =
|
|
||||||
"""
|
|
||||||
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = executeSQL(sql)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sql =
|
|
||||||
"""
|
|
||||||
INSERT INTO items (embedding) VALUES ('[[1,2,3], [1,2,3], [1,2,3]]'), ('[4,5,6]');
|
|
||||||
"""
|
|
||||||
result = executeSQL(sql)
|
|
||||||
|
|
||||||
|
|
||||||
sql =
|
|
||||||
"""
|
|
||||||
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 1;
|
|
||||||
"""
|
|
||||||
result = executeSQL(sql)
|
|
||||||
df = DataFrame(result)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
config = copy(JSON3.read("config.json"))
|
|
||||||
|
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
|
||||||
config[:externalservice][:text2textinstruct][:mqtttopic];
|
|
||||||
msgPurpose= "embedding",
|
|
||||||
senderName= "yiemagent",
|
|
||||||
senderId= string(uuid4()),
|
|
||||||
receiverName= "text2textinstruct",
|
|
||||||
mqttBrokerAddress= "mqtt.yiem.cc",
|
|
||||||
mqttBrokerPort= 1883,
|
|
||||||
)
|
|
||||||
|
|
||||||
text = ["hello world"]
|
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
|
||||||
:msgMeta=> msgMeta,
|
|
||||||
:payload=> Dict(
|
|
||||||
:text=> text,
|
|
||||||
:kwargs=> Dict(
|
|
||||||
:max_tokens=> 2048,
|
|
||||||
:stop=> ["<|eot_id|>"],
|
|
||||||
:temperature=> 0.2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
using Revise
|
|
||||||
|
|
||||||
function testf(a)::NamedTuple{(:a, :b), Tuple{Union{Nothing, Int}, Int}}
|
|
||||||
if a == 1
|
|
||||||
return (a=nothing, b=5)
|
|
||||||
else
|
|
||||||
return (a=5, b=5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
q = testf(1)
|
|
||||||
w = testf(2)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
table_name,comment
|
|
||||||
customer,"The customer table stores information about customers. It includes details such as first name, last name, display name, username, password, gender, country, telephone number, email, birthdate, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
wine,"The wine table stores information about different wines. It includes details namely id, name, brand, manufacturer, region, country, wine_type, grape_variety, serving_temperature, intensity, sweetness, tannin, acidity, fizziness, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
wine_food,"The wine_food table represents the association between wines and food items. It establishes a many-to-many relationship, allowing us to link specific wines with various food items."
|
|
||||||
food,"The food table represents various food items. It stores information related to food names, country of origin, taste attributes (spiciness, sweetness, sourness, savoriness, and bitterness), serving temperature, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
retailer,"The retailer table stores information about different retailers. It includes details related to retailer names, usernames, passwords, addresses, contact persons, telephone numbers, email addresses, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
retailer_wine,"The retailer_wine table represents the relationship between retailers and wines. It stores information about the wines available from which retailers, including vintage, their price, and the currency."
|
|
||||||
retailer_food,"The retailer_food table represents the relationship between retailers and food items. It stores information about the food items available from which retailers, including their price and the currency."
|
|
||||||
|
706
src/interface.jl
706
src/interface.jl
@@ -2,7 +2,7 @@ module interface
|
|||||||
|
|
||||||
export decisionMaker, evaluator, reflector, transition, query
|
export decisionMaker, evaluator, reflector, transition, query
|
||||||
|
|
||||||
using LibPQ, DataStructures, JSON3, UUIDs, PrettyPrinting
|
using LibPQ, DataStructures, JSON3, UUIDs, PrettyPrinting, Dates
|
||||||
using GeneralUtils, LLMMCTS
|
using GeneralUtils, LLMMCTS
|
||||||
using ..util, ..llmfunction
|
using ..util, ..llmfunction
|
||||||
|
|
||||||
@@ -10,6 +10,8 @@ using ..util, ..llmfunction
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
""" Think and choose action.
|
""" Think and choose action.
|
||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
@@ -136,13 +138,16 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
You are a helpful assistant that find the data from a database to satisfy the user's query.
|
You are a helpful assistant that find the data from a database to satisfy the user's query.
|
||||||
You are also eager to improve your helpfulness.
|
You are also eager to improve your helpfulness.
|
||||||
|
|
||||||
At each round of conversation, the user will give you the current situation:
|
For your information:
|
||||||
|
- Observation: Result of the immediately preceding action
|
||||||
|
|
||||||
|
At each round of conversation, the user will give you the following:
|
||||||
User Query: ...
|
User Query: ...
|
||||||
Example: ...
|
Example: ...
|
||||||
Your Q&A: ...
|
Your Q&A: ...
|
||||||
Your work progress: ...
|
Your work progress: ...
|
||||||
Evaluation: Evaluation of the latest action and observation
|
Evaluation: Evaluation of the immediately preceding action and observation
|
||||||
Suggestion: ...
|
Suggestion: Suggestion for the immediately preceding action and observation
|
||||||
|
|
||||||
You must follow the following guidelines:
|
You must follow the following guidelines:
|
||||||
- Keep SQL queries focused only on the provided information.
|
- Keep SQL queries focused only on the provided information.
|
||||||
@@ -154,22 +159,18 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
- If you are unable to find the requested information, kindly inform the user, "The current data in our database does not provide the specific answer to your query".
|
- If you are unable to find the requested information, kindly inform the user, "The current data in our database does not provide the specific answer to your query".
|
||||||
- Text information in the database usually stored in lower case. If your search returns empty, try using lower case to search.
|
- Text information in the database usually stored in lower case. If your search returns empty, try using lower case to search.
|
||||||
|
|
||||||
You should then respond to the user with interleaving Understanding, Reasoning, Plan, Action:
|
You should then respond to the user with interleaving Comprehension, Plan, Action_name, Action_input:
|
||||||
1) Understanding:
|
Comprehension: state your comprehension about the current situation.
|
||||||
- State your understanding about the current situation.
|
Plan: Given the current circumstances, outline a detailed, step-by-step plan to accomplish the task. Be specific.
|
||||||
2) Reasoning:
|
Action_name: (Typically corresponds to the execution of the first step in your plan)
|
||||||
- State your step by step reasoning about the current situation.
|
Can be one of the following function names:
|
||||||
3) Plan: Given the current circumstances, outline a detailed, step-by-step plan to accomplish the task. Be specific.
|
- RUNSQL, which you can use to execute SQL against the database. Action_input for this function must be a single SQL query to be executed against the database.
|
||||||
4) Action_name (Must be aligned with your plan): Can be one of the following functions:
|
|
||||||
- GETDATA, which you can use to get the data from the database. Action_input for this function must be a single SQL query to be executed against the database.
|
|
||||||
For more effective text search, it's necessary to use case-insensitivity and the ILIKE operator.
|
For more effective text search, it's necessary to use case-insensitivity and the ILIKE operator.
|
||||||
Do not wrap the SQL as it will be executed against the database directly and SQL must be ended with ';'.
|
Do not wrap the SQL as it will be executed against the database directly and SQL must be ended with ';'.
|
||||||
5) Action_input: Input to the action
|
4) Action_input: Input to the action
|
||||||
6) Observation: Result of the immediately preceding action
|
|
||||||
|
|
||||||
You should only respond in format as described below:
|
You should only respond in format as described below:
|
||||||
Understanding: ...
|
Comprehension: ...
|
||||||
Reasoning: ...
|
|
||||||
Plan: ...
|
Plan: ...
|
||||||
Action_name: ...
|
Action_name: ...
|
||||||
Action_input: ...
|
Action_input: ...
|
||||||
@@ -185,7 +186,7 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
end
|
end
|
||||||
|
|
||||||
response = nothing # store for show when error msg show up
|
response = nothing # store for show when error msg show up
|
||||||
errornote = ""
|
errornote = "N/A"
|
||||||
|
|
||||||
# provide similar sql only for the first attempt
|
# provide similar sql only for the first attempt
|
||||||
similarSQL_ = "None"
|
similarSQL_ = "None"
|
||||||
@@ -194,8 +195,20 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
similarSQL_ = sql !== nothing ? sql : "None"
|
similarSQL_ = sql !== nothing ? sql : "None"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
header = ["Comprehension:", "Plan:", "Action_name:", "Action_input:"]
|
||||||
|
dictkey = ["comprehension", "plan", "action_name", "action_input"]
|
||||||
|
|
||||||
|
llmkwargs=Dict(
|
||||||
|
:num_ctx => 32768,
|
||||||
|
:temperature => 0.1,
|
||||||
|
)
|
||||||
|
|
||||||
for attempt in 1:10
|
for attempt in 1:10
|
||||||
|
if attempt > 1
|
||||||
|
println("\nERROR SQLLLM decisionMaker() attempt $attempt/10 ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
llmkwargs[:temperature] = 0.1 * attempt
|
||||||
|
end
|
||||||
|
|
||||||
QandA = generatequestion(state, context, text2textInstructLLM; similarSQL=similarSQL_)
|
QandA = generatequestion(state, context, text2textInstructLLM; similarSQL=similarSQL_)
|
||||||
|
|
||||||
usermsg =
|
usermsg =
|
||||||
@@ -207,7 +220,7 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
Your work progress: $workprogress
|
Your work progress: $workprogress
|
||||||
Evaluation: $(state[:evaluation])
|
Evaluation: $(state[:evaluation])
|
||||||
Suggestion: $(state[:suggestion])
|
Suggestion: $(state[:suggestion])
|
||||||
$errornote
|
P.S. $errornote
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_prompt =
|
_prompt =
|
||||||
@@ -217,40 +230,70 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
prompt *=
|
response = text2textInstructLLM(prompt; llmkwargs=llmkwargs)
|
||||||
"""
|
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
# LLM tends to generate observation given that it is in the input
|
||||||
response = text2textInstructLLM(prompt)
|
response =
|
||||||
println("\nSQL decisionMaker() rawresponse: \n", response)
|
if occursin("observation:", response)
|
||||||
|
string(split(response, "observation:")[1])
|
||||||
|
elseif occursin("Observation:", response)
|
||||||
|
string(split(response, "Observation:")[1])
|
||||||
|
elseif occursin("observation_", response)
|
||||||
|
string(split(response, "observation_")[1])
|
||||||
|
elseif occursin("Observation_", response)
|
||||||
|
string(split(response, "Observation_")[1])
|
||||||
|
else
|
||||||
|
response
|
||||||
|
end
|
||||||
|
|
||||||
|
# sometime LLM output something like **Comprehension**: which is not expected
|
||||||
|
response = replace(response, "**"=>"")
|
||||||
|
response = replace(response, "***"=>"")
|
||||||
|
|
||||||
|
# some time LLM output Plan_1: so we need to detect and replace topic numbering
|
||||||
|
regex = r"_[0-1000]+:"
|
||||||
|
matches = collect(eachmatch(regex, response))
|
||||||
|
for m in matches
|
||||||
|
response = replace(response, string(m.match)=>":")
|
||||||
|
end
|
||||||
|
|
||||||
if occursin("NULL", response)
|
if occursin("NULL", response)
|
||||||
errornote = "\nSQL decisionMaker() NULL response is not allowed"
|
errornote = "\nYour previous attempt was NULL. This is not allowed"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
|
println("\nERROR SQLLLM decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
header = ["Understanding", "Reasoning", "Plan", "Action_name", "Action_input", "Observation"]
|
# # detect if there are more than 1 key per categories
|
||||||
|
# wordcount = GeneralUtils.countGivenWords(response, header)
|
||||||
|
# duplicateKeywordFlag = false
|
||||||
|
# for (i, v) in enumerate(wordcount)
|
||||||
|
# keyword = header[i]
|
||||||
|
# keywordNumber = v
|
||||||
|
# if keywordNumber > 1
|
||||||
|
# errornote = "\nSQL query has duplicated keyword, $keyword"
|
||||||
|
# println("Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
# duplicateKeywordFlag = true
|
||||||
|
# break
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# duplicateKeywordFlag == true ? continue : nothing
|
||||||
|
|
||||||
# detect if there are more than 1 key per categories
|
# check whether response has all header
|
||||||
count = GeneralUtils.countGivenWords(response, header)
|
detected_kw = GeneralUtils.detect_keyword(header, response)
|
||||||
duplicateKeywordFlag = false
|
if 0 ∈ values(detected_kw)
|
||||||
for (i, v) in enumerate(count)
|
errornote = "\nYour previous attempt did not have all points according to the required response format"
|
||||||
keyword = header[i]
|
println("\nERROR SQLLLM decisionMaker() $errornote \n$response", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
keywordNumber = v
|
continue
|
||||||
if keywordNumber > 1
|
elseif sum(values(detected_kw)) > length(header)
|
||||||
errornote = "\nSQL query has duplicated keyword, $keyword"
|
errornote = "\nYour previous attempt has duplicated points according to the required response format"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
|
println("\nERROR SQLLLM decisionMaker() $errornote \n$response", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
duplicateKeywordFlag = true
|
continue
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
duplicateKeywordFlag == true ? continue : nothing
|
|
||||||
|
|
||||||
# textToDict() search for action_input
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
responsedict = GeneralUtils.textToDict(response, header,
|
dictKey=dictkey, symbolkey=true)
|
||||||
rightmarker=":", symbolkey=true, lowercasekey=true)
|
|
||||||
|
|
||||||
delete!(responsedict, :observation)
|
delete!(responsedict, :observation)
|
||||||
|
|
||||||
@@ -266,35 +309,25 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
responsedict[:action_input] = sql
|
responsedict[:action_input] = sql
|
||||||
end
|
end
|
||||||
|
|
||||||
toollist = ["TABLEINFO", "GETDATA"]
|
toollist = ["TABLEINFO", "RUNSQL"]
|
||||||
if responsedict[:action_name] ∉ toollist
|
if responsedict[:action_name] ∉ toollist
|
||||||
errornote = "\nYou must only use the given functions"
|
errornote = "\nYour previous attempt has action_name that is not in the tool list"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
|
println("\nERROR SQLLLM decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
|
|
||||||
for i in toollist
|
for i in toollist
|
||||||
if occursin(i, responsedict[:action_input])
|
if occursin(i, responsedict[:action_input])
|
||||||
errornote = "\n action_name is in action_input which is not allowed."
|
errornote = "\nYour previous attempt has action_name in action_input which is not allowed"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
|
println("\nERROR SQLLLM decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i ∈ [:understanding, :reasoning, :plan, :action_name, :action_input]
|
for i ∈ Symbol.(dictkey)
|
||||||
if length(JSON3.write(responsedict[i])) == 0
|
if length(JSON3.write(responsedict[i])) == 0
|
||||||
errornote = "\n $i is empty"
|
errornote = "\nYour previous attempt has empty value for $i"
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
|
println("\nERROR SQLLLM decisionMaker() $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
continue
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# check if there are more than 1 key per categories
|
|
||||||
for i ∈ [:understanding, :reasoning, :plan, :action_name, :action_input]
|
|
||||||
matchkeys = GeneralUtils.findMatchingDictKey(responsedict, i)
|
|
||||||
if length(matchkeys) > 1
|
|
||||||
errornote = "\n $i has more than one key"
|
|
||||||
println("Attempt $attempt $errornote ", @__FILE__, " ", @__LINE__)
|
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -304,9 +337,10 @@ function decisionMaker(state::T1, context, text2textInstructLLM::Function,
|
|||||||
return responsedict
|
return responsedict
|
||||||
|
|
||||||
end
|
end
|
||||||
error("DecisionMaker failed to generate a thought ", response)
|
error("SQLLLM DecisionMaker() failed to generate a thought \n", response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
""" Assigns a scalar value to each new child node to be used for selec-
|
""" Assigns a scalar value to each new child node to be used for selec-
|
||||||
tion and backpropagation. This value effectively quantifies the agent's progress in task completion,
|
tion and backpropagation. This value effectively quantifies the agent's progress in task completion,
|
||||||
serving as a heuristic to steer the search algorithm towards the most promising regions of the tree.
|
serving as a heuristic to steer the search algorithm towards the most promising regions of the tree.
|
||||||
@@ -327,141 +361,9 @@ julia>
|
|||||||
|
|
||||||
# Signature
|
# Signature
|
||||||
"""
|
"""
|
||||||
function evaluator(state::T1, text2textInstructLLM::Function;
|
function evaluator(state::T1, text2textInstructLLM::Function; maxattempt=10
|
||||||
insertSQLVectorDB::Union{Function, Nothing}=nothing
|
|
||||||
) where {T1<:AbstractDict}
|
) where {T1<:AbstractDict}
|
||||||
|
|
||||||
# systemmsg =
|
|
||||||
# """
|
|
||||||
# You are a helpful assistant that analyzes agent's trajectories to find solutions and observations (i.e., the results of actions) to answer the user's questions.
|
|
||||||
|
|
||||||
# Definitions:
|
|
||||||
# "question" is the user's question.
|
|
||||||
# "thought" is step-by-step reasoning about the current situation.
|
|
||||||
# "plan" is what to do to complete the task from the current situation.
|
|
||||||
# "action" is the taken action which can be one of the following functions:
|
|
||||||
# 1) TABLEINFO[list_of_table_name], which you can use to get the data type of a table column.
|
|
||||||
# 2) GETDATA[instruction], which you can use to get the data from the database.
|
|
||||||
# 3) ANSWERBOX[answer], which returns your answer to the user. "answer" is your answer to the user question.
|
|
||||||
# "observation" is result of the action in JSON format.
|
|
||||||
|
|
||||||
# At each round of conversation, the user will give you:
|
|
||||||
# Context: ...
|
|
||||||
# Trajectories: ...
|
|
||||||
|
|
||||||
# You should then respond to the user with:
|
|
||||||
# - Original_question: Repeat the original question.
|
|
||||||
# - Evaluation (you must evaluate all of the following points):
|
|
||||||
# 1) Analyze the trajectories of a solution to answer the user's original question.
|
|
||||||
# Given a question and a trajectory, evaluate its correctness and provide your reasoning and
|
|
||||||
# analysis in detail. Focus on the latest thought, action, and observation.
|
|
||||||
# Incomplete trajectories can be correct if the thoughts and actions so far are correct,
|
|
||||||
# even if the answer is not found yet. Do not generate additional thoughts or actions.
|
|
||||||
# 2) How the observation addresses the original question?
|
|
||||||
# 3) Provide suggestion (if applicable).
|
|
||||||
# - Score: Correctness score s where s is an integer from 0 to 10.
|
|
||||||
# - Accepted_as_answer: Decide whether to accept the observation as the answer to the original question.
|
|
||||||
# 1) The accepted observation should directly answer the question.
|
|
||||||
# 2) The possible responses are either 'Yes' or 'No.'
|
|
||||||
|
|
||||||
# You should only respond in JSON format as described below:
|
|
||||||
# {"original_question": ..., "evaluation": ..., "score": ..., "accepted_as_answer": ...}
|
|
||||||
|
|
||||||
# Here are correct trajectory examples:
|
|
||||||
# user:
|
|
||||||
# {
|
|
||||||
# "question": "I'm looking for a sedan with an automatic driving feature.",
|
|
||||||
# "thought_1": "I have many types of sedans in my inventory, each with diverse features.",
|
|
||||||
# "thought_2": "I should check our inventory first to see if we have the one our customer wants.",
|
|
||||||
# "action_1": {"name": "inventory", "input": "a sedan with an automatic driving feature"},
|
|
||||||
# "observation_1": "Yiem Model A, Conez Model B"
|
|
||||||
# }
|
|
||||||
# assistant:
|
|
||||||
# {
|
|
||||||
# "original_question": "the user is looking for a sedan with an automatic driving feature.",
|
|
||||||
# "evaluation": "This trajectory is correct because it is logical to use the INVENTORY function to search for inventory based on the details provided in the question, which could lead to a potential answer. The user is asking whether do you have a sedan with an automatic driving feature and the observation provides a list of sedan models that you have. Thus, it is accepted as the answer.",
|
|
||||||
# "score": 10,
|
|
||||||
# "accepted_as_answer": "Yes"
|
|
||||||
# }
|
|
||||||
|
|
||||||
# user:
|
|
||||||
# {
|
|
||||||
# "question": "How many cars that fitted with a stereo we have?",
|
|
||||||
# "thought_1": "I have many types of car in my inventory, each with diverse features.",
|
|
||||||
# "thought_3": "I should check our inventory.",
|
|
||||||
# "action_1": {"name": "inventory", "input": "vehicle with a stereo"},
|
|
||||||
# "observation_1": "2015 Conez truck."
|
|
||||||
# }
|
|
||||||
# assistant:
|
|
||||||
# {
|
|
||||||
# "evaluation": “This approach is correct. It's reasonable to use the INVENTORY function to search for inventory. However, the query asked for a car but the observation was a truck. Thus it is not accepted as the answer. To improve, make sure to input the correct terms and match the requested criteria accurately.”,
|
|
||||||
# "score": 5,
|
|
||||||
# "accepted_as_answer": "No"
|
|
||||||
# }
|
|
||||||
|
|
||||||
# Here are incorrect trajectory examples:
|
|
||||||
# user:
|
|
||||||
# {
|
|
||||||
# "question": "I'm looking for a sedan with an automatic driving feature. Do you have it in stock?",
|
|
||||||
# "thought_1": "I have many types of sedans in my inventory, each with diverse features.",
|
|
||||||
# "thought_2": "I will use SEARCHINTERNET function to search for the car.",
|
|
||||||
# "action_1": {"name": "SEARCHINTERNET", "input": "a sedan with an automatic driving feature.},
|
|
||||||
# "observation_1": "Teza Model A, Teza Model B"
|
|
||||||
# }
|
|
||||||
# assistant:
|
|
||||||
# {
|
|
||||||
# "evaluation": "This trajectory is incorrect. Using the SEARCHINTERNET function to search for a sedan in the Internet is illogical because the question asked for the cars available for sale at your dealership. To improve, ensure that you read the question clearly.",
|
|
||||||
# "score": 0,
|
|
||||||
# "accepted_as_answer": "No"
|
|
||||||
# }
|
|
||||||
|
|
||||||
# Let's begin!
|
|
||||||
# """
|
|
||||||
|
|
||||||
# systemmsg =
|
|
||||||
# """
|
|
||||||
# You are a helpful assistant that analyzes agent's trajectories to find solutions and observations (i.e., the results of actions) to answer the user's questions.
|
|
||||||
|
|
||||||
# Definitions:
|
|
||||||
# "question" is the user's question.
|
|
||||||
# "thought" is step-by-step reasoning about the current situation.
|
|
||||||
# "plan" is what to do to complete the task from the current situation.
|
|
||||||
# “action_name” is the name of the action taken, which can be one of the following functions:
|
|
||||||
# 1) CHATBOX[text], which you can use to talk with the user. "text" is in verbal English.
|
|
||||||
# 2) WINESTOCK[query], which you can use to find info about wine in your inventory. "query" is a search term in verbal English. The best query must includes "budget", "type of wine", "characteristics of wine" and "food pairing".
|
|
||||||
# "action_input" is the input to the action
|
|
||||||
# "observation" is result of the action.
|
|
||||||
|
|
||||||
# At each round of conversation, the user will give you:
|
|
||||||
# Context: ...
|
|
||||||
# Trajectories: ...
|
|
||||||
|
|
||||||
# You should then respond to the user with:
|
|
||||||
# - original_question: Repeat the original question.
|
|
||||||
# - evaluation (you must evaluate all of the following points in a single paragraph):
|
|
||||||
# 1) Analyze the trajectories of a solution to answer the user's original question.
|
|
||||||
# Given a question and a trajectory, evaluate its correctness and provide your reasoning and
|
|
||||||
# analysis in detail. Focus on the latest thought, action, and observation.
|
|
||||||
# Incomplete trajectories can be correct if the thoughts and actions so far are correct,
|
|
||||||
# even if the answer is not found yet. Do not generate additional thoughts or actions.
|
|
||||||
# 2) How the observation addresses the question exactly?
|
|
||||||
# - accepted_as_answer: Decide whether to accept the observation as the answer to the original question.
|
|
||||||
# 1) if the observation's content directly answers the question then just accept it as the answer. Oherwise, it is not. The possible responses are either 'Yes' or 'No.'
|
|
||||||
# - score: Correctness score s where s is a single integer between 0 to 9.
|
|
||||||
# 1) 0 means the trajectories are incorrect.
|
|
||||||
# 2) 9 means the trajectories are correct, and the observation's content directly answers the question.
|
|
||||||
# - suggestion: if accepted_as_answer is "No", provide suggestion.
|
|
||||||
|
|
||||||
# You should only respond in format as described below:
|
|
||||||
# original_question: ...
|
|
||||||
# evaluation: ...
|
|
||||||
# accepted_as_answer: ...
|
|
||||||
# score: ...
|
|
||||||
# suggestion: ...
|
|
||||||
|
|
||||||
# Let's begin!
|
|
||||||
# """
|
|
||||||
|
|
||||||
systemmsg =
|
systemmsg =
|
||||||
"""
|
"""
|
||||||
You are a helpful assistant that analyzes agent's trajectory to find solutions and observations (i.e., the results of actions) to answer the user's questions.
|
You are a helpful assistant that analyzes agent's trajectory to find solutions and observations (i.e., the results of actions) to answer the user's questions.
|
||||||
@@ -472,17 +374,22 @@ function evaluator(state::T1, text2textInstructLLM::Function;
|
|||||||
"reasoning" is agent's step-by-step reasoning about the current situation
|
"reasoning" is agent's step-by-step reasoning about the current situation
|
||||||
"plan" is agent's plan to complete the task from the current situation
|
"plan" is agent's plan to complete the task from the current situation
|
||||||
"action_name" is the name of the action taken, which can be one of the following functions:
|
"action_name" is the name of the action taken, which can be one of the following functions:
|
||||||
- GETDATA, which you can use to get the data from the database. Action_input for this function must be a single SQL query to be executed against the database.
|
- RUNSQL, which you can use to execute SQL against the database. Action_input for this function must be a single SQL query to be executed against the database.
|
||||||
For more effective text search, it's necessary to use case-insensitivity and the ILIKE operator.
|
For more effective text search, it's necessary to use case-insensitivity and the ILIKE operator.
|
||||||
Do not wrap the SQL as it will be executed against the database directly and SQL must be ended with ';'.
|
Do not wrap the SQL as it will be executed against the database directly and SQL must be ended with ';'.
|
||||||
"action_input" is the input to the action
|
"action_input" is the input to the action
|
||||||
"observation" is result of the preceding immediate action
|
"observation" is result of the preceding immediate action
|
||||||
|
|
||||||
At each round of conversation, the user will give you:
|
<At each round of conversation, the user will give you>
|
||||||
Context: ...
|
|
||||||
Trajectory: ...
|
Trajectory: ...
|
||||||
|
Error_note: error note from your previous attempt
|
||||||
|
</At each round of conversation, the user will give you>
|
||||||
|
|
||||||
You should then respond to the user with:
|
<You must follow the following guidelines>
|
||||||
|
- When the search returns no result, validate whether the SQL query makes sense before accepting it as a valid answer.
|
||||||
|
</You must follow the following guidelines>
|
||||||
|
|
||||||
|
<You should then respond to the user with>
|
||||||
1) Trajectory_evaluation: Analyze the trajectory of a solution to answer the user's original question.
|
1) Trajectory_evaluation: Analyze the trajectory of a solution to answer the user's original question.
|
||||||
- Evaluate the correctness of each section and the overall trajectory based on the given question.
|
- Evaluate the correctness of each section and the overall trajectory based on the given question.
|
||||||
- Provide detailed reasoning and analysis, focusing on the latest thought, action, and observation.
|
- Provide detailed reasoning and analysis, focusing on the latest thought, action, and observation.
|
||||||
@@ -490,28 +397,31 @@ function evaluator(state::T1, text2textInstructLLM::Function;
|
|||||||
- Do not generate additional thoughts or actions.
|
- Do not generate additional thoughts or actions.
|
||||||
2) Answer_evaluation:
|
2) Answer_evaluation:
|
||||||
- Focus only on the matter mentioned in the question and comprehensively analyze how the latest observation's details addresses the question
|
- Focus only on the matter mentioned in the question and comprehensively analyze how the latest observation's details addresses the question
|
||||||
- State your rationale
|
|
||||||
3) Accepted_as_answer: Decide whether the latest observation's content answers the question. Can be "Yes" or "No"
|
3) Accepted_as_answer: Decide whether the latest observation's content answers the question. Can be "Yes" or "No"
|
||||||
Bad example (The observation didn't answers the question):
|
Bad example (The observation didn't answers the question):
|
||||||
question: Find cars with 4 wheels.
|
question: Find cars with 4 wheels.
|
||||||
observation: There are 2 cars in the table.
|
observation: There are an apple in the table.
|
||||||
Good example (The observation answers the question):
|
Good example (The observation answers the question):
|
||||||
question: Find cars with a stereo.
|
question: Find cars with a stereo.
|
||||||
observation: There are 1 cars in the table. 1) brand: Toyota, model: yaris, color: black.
|
observation: There are 1 cars in the table. 1) brand: Toyota, model: yaris, color: black.
|
||||||
4) Score: Correctness score s where s is a single integer between 0 to 9.
|
4) Score: Correctness score s where s is a single integer between 0 to 9.
|
||||||
Score guideline:
|
For example:
|
||||||
- 0 indicates that both the trajectory is incorrect, failed or errors and the observation is incorrect or failed
|
- 0 indicates that both the trajectory is incorrect, failed or errors and the observation is incorrect or failed
|
||||||
- 4 indicates that the trajectory are correct but the observation is incorrect or failed
|
- 4 indicates that the trajectory are correct but the observation is incorrect or failed
|
||||||
|
- 5 indicates that the trajectory are correct, but no results are returned.
|
||||||
|
- 6 indicates that the trajectory are correct, but the observation's content doesn't directly answer the question
|
||||||
- 8 indicates that both the trajectory are correct, and the observation's content directly answers the question.
|
- 8 indicates that both the trajectory are correct, and the observation's content directly answers the question.
|
||||||
- 9 indicates a perfect perfomance. Both the trajectory are correct, and the observation's content directly answers the question, surpassing your expectations.
|
- 9 indicates a perfect perfomance. Both the trajectory are correct, and the observation's content directly answers the question, surpassing your expectations.
|
||||||
5) Suggestion: if accepted_as_answer is "No", provide suggestion.
|
5) Suggestion: if accepted_as_answer is "No", provide suggestion.
|
||||||
|
</You should then respond to the user with>
|
||||||
|
|
||||||
You should only respond in format as described below:
|
<You should only respond in format as described below>
|
||||||
Trajectory_evaluation: ...
|
Trajectory_evaluation: ...
|
||||||
Answer_evaluation: ...
|
Answer_evaluation: ...
|
||||||
Accepted_as_answer: ...
|
Accepted_as_answer: ...
|
||||||
Score: ...
|
Score: ...
|
||||||
Suggestion: ...
|
Suggestion: ...
|
||||||
|
</You should only respond in format as described below>
|
||||||
|
|
||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
@@ -521,10 +431,12 @@ function evaluator(state::T1, text2textInstructLLM::Function;
|
|||||||
thoughthistory *= "$k: $v\n"
|
thoughthistory *= "$k: $v\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
for attempt in 1:5
|
errornote = ""
|
||||||
|
for attempt in 1:maxattempt
|
||||||
usermsg =
|
usermsg =
|
||||||
"""
|
"""
|
||||||
Trajectory: $thoughthistory
|
Trajectory: $thoughthistory
|
||||||
|
P.S. $errornote
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_prompt =
|
_prompt =
|
||||||
@@ -534,64 +446,72 @@ function evaluator(state::T1, text2textInstructLLM::Function;
|
|||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
prompt *=
|
|
||||||
"""
|
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
|
||||||
|
|
||||||
try
|
header = ["Trajectory_evaluation:", "Answer_evaluation:", "Accepted_as_answer:", "Score:", "Suggestion:"]
|
||||||
response = text2textInstructLLM(prompt)
|
dictkey = ["trajectory_evaluation", "answer_evaluation", "accepted_as_answer", "score", "suggestion"]
|
||||||
responsedict = GeneralUtils.textToDict(response,
|
|
||||||
["Trajectory_evaluation", "Answer_evaluation", "Accepted_as_answer", "Score", "Suggestion"];
|
|
||||||
rightmarker=":", symbolkey=true, lowercasekey=true)
|
|
||||||
|
|
||||||
# check if dict has all required value
|
response = text2textInstructLLM(prompt, modelsize="medium")
|
||||||
trajectoryevaluation_text::AbstractString = responsedict[:trajectory_evaluation]
|
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||||
answerevaluation_text::AbstractString = responsedict[:answer_evaluation]
|
|
||||||
# responsedict[:score] = replace(responsedict[:score], r"\(.*?\)" => "") # remove (...) if there is any.
|
|
||||||
responsedict[:score] = responsedict[:score][1] # some time "6\nThe trajectories are incomplete" is generated but I only need the number.
|
|
||||||
responsedict[:score] = parse(Int, responsedict[:score]) # convert string "5" into integer 5
|
|
||||||
score::Integer = responsedict[:score]
|
|
||||||
accepted_as_answer::AbstractString = responsedict[:accepted_as_answer]
|
|
||||||
suggestion::AbstractString = responsedict[:suggestion]
|
|
||||||
|
|
||||||
if accepted_as_answer ∉ ["Yes", "No"] # [PENDING] add errornote into the prompt
|
# sometime LLM output something like **Comprehension**: which is not expected
|
||||||
error("generated accepted_as_answer has wrong format")
|
response = replace(response, "**"=>"")
|
||||||
end
|
response = replace(response, "***"=>"")
|
||||||
|
|
||||||
# add to state here instead to in transition() because the latter causes julia extension crash (a bug in julia extension)
|
# check whether response has all header
|
||||||
state[:evaluation] = "$(responsedict[:trajectory_evaluation]) $(responsedict[:answer_evaluation])"
|
detected_kw = GeneralUtils.detect_keyword(header, response)
|
||||||
state[:evaluationscore] = responsedict[:score]
|
if 0 ∈ values(detected_kw)
|
||||||
state[:accepted_as_answer] = responsedict[:accepted_as_answer]
|
errornote = "Your previous attempt does not have all answer points"
|
||||||
state[:suggestion] = responsedict[:suggestion]
|
println("\nERROR SQLLLM evaluator() Attempt $attempt/$maxattempt. $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue
|
||||||
# mark as terminal state when the answer is achieved
|
elseif sum(values(detected_kw)) > length(header)
|
||||||
if accepted_as_answer == "Yes"
|
errornote = "Your previous attempt has duplicated answer point"
|
||||||
|
println("\nERROR SQLLLM evaluator() Attempt $attempt/$maxattempt. $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
# mark the state as terminal state because the evaluation say so.
|
continue
|
||||||
state[:isterminal] = true
|
|
||||||
|
|
||||||
# evaluation score as reward because different answers hold different value for the user.
|
|
||||||
state[:reward] = responsedict[:score]
|
|
||||||
end
|
|
||||||
println("\n~~~ Evaluator() ", @__FILE__, " ", @__LINE__)
|
|
||||||
pprintln(Dict(responsedict))
|
|
||||||
|
|
||||||
return responsedict[:score]
|
|
||||||
catch e
|
|
||||||
io = IOBuffer()
|
|
||||||
showerror(io, e)
|
|
||||||
errorMsg = String(take!(io))
|
|
||||||
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
|
||||||
println("")
|
|
||||||
println("Attempt $attempt. Error occurred: $errorMsg\n$st")
|
|
||||||
println("")
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
error("evaluator failed to generate an evaluation")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
|
dictKey=dictkey, symbolkey=true)
|
||||||
|
|
||||||
|
responsedict[:score] = responsedict[:score][1] # some time "6\nThe trajectories are incomplete" is generated but I only need the number.
|
||||||
|
try
|
||||||
|
responsedict[:score] = parse(Int, responsedict[:score]) # convert string "5" into integer 5
|
||||||
|
catch
|
||||||
|
errornote = "Your previous attempt's score has wrong format"
|
||||||
|
println("\nERROR SQLLLM evaluator() Attempt $attempt/$maxattempt. $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
accepted_as_answer::AbstractString = responsedict[:accepted_as_answer]
|
||||||
|
|
||||||
|
if accepted_as_answer ∉ ["Yes", "No"] # [PENDING] add errornote into the prompt
|
||||||
|
errornote = "Your previous attempt's accepted_as_answer has wrong format"
|
||||||
|
println("\nERROR SQLLLM evaluator() Attempt $attempt/$maxattempt. $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
# add to state here instead to in transition() because the latter causes julia extension crash (a bug in julia extension)
|
||||||
|
state[:evaluation] = "$(responsedict[:trajectory_evaluation]) $(responsedict[:answer_evaluation])"
|
||||||
|
state[:evaluationscore] = responsedict[:score]
|
||||||
|
state[:accepted_as_answer] = responsedict[:accepted_as_answer]
|
||||||
|
state[:suggestion] = responsedict[:suggestion]
|
||||||
|
|
||||||
|
# mark as terminal state when the answer is achieved
|
||||||
|
if accepted_as_answer == "Yes"
|
||||||
|
|
||||||
|
# mark the state as terminal state because the evaluation say so.
|
||||||
|
state[:isterminal] = true
|
||||||
|
|
||||||
|
# evaluation score as reward because different answers hold different value for the user.
|
||||||
|
state[:reward] = responsedict[:score]
|
||||||
|
end
|
||||||
|
println("\nEvaluator() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
pprintln(Dict(responsedict))
|
||||||
|
|
||||||
|
return responsedict[:score]
|
||||||
|
end
|
||||||
|
error("Evaluator failed to generate an evaluation, Response: \n$response\n<|End of error|>")
|
||||||
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -688,24 +608,18 @@ function reflector(config::T1, state::T2)::String where {T1<:AbstractDict, T2<:A
|
|||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
prompt *=
|
|
||||||
"""
|
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
|
||||||
|
|
||||||
externalService = config[:externalservice][:text2textinstruct]
|
externalService = config[:externalservice][:text2textinstruct]
|
||||||
|
|
||||||
|
|
||||||
# apply LLM specific instruct format
|
# apply LLM specific instruct format
|
||||||
externalService = config[:externalservice][:text2textinstruct]
|
externalService = config[:externalservice][:text2textinstruct]
|
||||||
|
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
msgMeta = GeneralUtils.generate_msgMeta(
|
||||||
externalService[:mqtttopic],
|
externalService[:mqtttopic];
|
||||||
senderName= "reflector",
|
senderName= "reflector",
|
||||||
senderId= string(uuid4()),
|
senderId= string(uuid4()),
|
||||||
receiverName= "text2textinstruct",
|
receiverName= "text2textinstruct",
|
||||||
mqttBroker= config[:mqttServerInfo][:broker],
|
mqttBrokerAddress= config[:mqttServerInfo][:broker],
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
mqttBrokerPort= config[:mqttServerInfo][:port],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -720,7 +634,7 @@ function reflector(config::T1, state::T2)::String where {T1<:AbstractDict, T2<:A
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for attempt in 1:5
|
for attempt in 1:10
|
||||||
try
|
try
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
||||||
_responseJsonStr = response[:response][:text]
|
_responseJsonStr = response[:response][:text]
|
||||||
@@ -808,13 +722,12 @@ function transition(state::T, args::NamedTuple
|
|||||||
# so that other simulation start from this same node is not contaminated with actioninput
|
# so that other simulation start from this same node is not contaminated with actioninput
|
||||||
listAllTable_json(executeSQL)
|
listAllTable_json(executeSQL)
|
||||||
elseif thoughtDict[:action_name] == "TABLEINFO"
|
elseif thoughtDict[:action_name] == "TABLEINFO"
|
||||||
input = thoughtDict[:action_input] # BUG thoughtDict[:action_input] = "\"wine\""
|
input = thoughtDict[:action_input]
|
||||||
tableinfo(executeSQL, input)
|
tableinfo(executeSQL, input)
|
||||||
elseif thoughtDict[:action_name] == "GETDATA"
|
elseif thoughtDict[:action_name] == "RUNSQL"
|
||||||
response = SQLexecution(executeSQL, thoughtDict[:action_input])
|
response = SQLexecution(executeSQL, thoughtDict[:action_input])
|
||||||
if response[:success]
|
if response[:success]
|
||||||
# intention = Dict(:intention=> "$(thoughtDict[:plan])")
|
extracted = extractContent_dataframe(response[:result], text2textInstructLLM, thoughtDict[:action_input])
|
||||||
extracted = extractContent_dataframe(response[:result], text2textInstructLLM)
|
|
||||||
(rawresponse=response[:result], result=extracted, errormsg=nothing, success=true)
|
(rawresponse=response[:result], result=extracted, errormsg=nothing, success=true)
|
||||||
else
|
else
|
||||||
(result=nothing, errormsg=response[:errormsg], success=false)
|
(result=nothing, errormsg=response[:errormsg], success=false)
|
||||||
@@ -830,8 +743,7 @@ function transition(state::T, args::NamedTuple
|
|||||||
reward::Integer = haskey(response, :reward) ? response[:reward] : 0
|
reward::Integer = haskey(response, :reward) ? response[:reward] : 0
|
||||||
isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false
|
isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false
|
||||||
newNodeKey, newstate = makeNewState(state, thoughtDict, rawresponse, JSON3.write(result), select, reward, isterminal)
|
newNodeKey, newstate = makeNewState(state, thoughtDict, rawresponse, JSON3.write(result), select, reward, isterminal)
|
||||||
progressvalue::Integer = evaluatorF(newstate, text2textInstructLLM;
|
progressvalue::Integer = evaluatorF(newstate, text2textInstructLLM)
|
||||||
insertSQLVectorDB=insertSQLVectorDB)
|
|
||||||
|
|
||||||
return (newNodeKey=newNodeKey, newstate=newstate, progressvalue=progressvalue)
|
return (newNodeKey=newNodeKey, newstate=newstate, progressvalue=progressvalue)
|
||||||
end
|
end
|
||||||
@@ -841,15 +753,22 @@ end
|
|||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
- `query<:AbstractString`
|
- `query<:AbstractString`
|
||||||
a query
|
A natural language query in English
|
||||||
- `executeSQL::Function`
|
- `executeSQL::Function`
|
||||||
a connection object to a database
|
A function that executes SQL queries against the database
|
||||||
- `text2textInstructLLM::Function`
|
- `text2textInstructLLM::Function`
|
||||||
A function that handles communication to text2text instruct LLM service.
|
A function that handles communication with a text-to-text instruction-based language model
|
||||||
|
|
||||||
# Return
|
# Keyword Arguments
|
||||||
- `resulttext::String`
|
- `insertSQLVectorDB::Union{Function, Nothing}=nothing`
|
||||||
The result of the query in English.
|
Optional function to insert SQL queries into a vector database for future reference
|
||||||
|
- `similarSQLVectorDB::Union{Function, Nothing}=nothing`
|
||||||
|
Optional function to find similar SQL queries from a vector database
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
- `NamedTuple{(:text, :rawresponse), Tuple{Any, Any}}`
|
||||||
|
- `:text`: The query result in natural language
|
||||||
|
- `:rawresponse`: The raw database response
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
```jldoctest
|
```jldoctest
|
||||||
@@ -916,7 +835,7 @@ julia> println(result)
|
|||||||
function query(query::T, executeSQL::Function, text2textInstructLLM::Function;
|
function query(query::T, executeSQL::Function, text2textInstructLLM::Function;
|
||||||
insertSQLVectorDB::Union{Function, Nothing}=nothing,
|
insertSQLVectorDB::Union{Function, Nothing}=nothing,
|
||||||
similarSQLVectorDB::Union{Function, Nothing}=nothing,
|
similarSQLVectorDB::Union{Function, Nothing}=nothing,
|
||||||
) where {T<:AbstractString}
|
)::NamedTuple{(:text, :rawresponse), Tuple{Any, Any}} where {T<:AbstractString}
|
||||||
|
|
||||||
# use similarSQLVectorDB to find similar SQL for the query
|
# use similarSQLVectorDB to find similar SQL for the query
|
||||||
sql, distance = similarSQLVectorDB(query)
|
sql, distance = similarSQLVectorDB(query)
|
||||||
@@ -925,7 +844,7 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function;
|
|||||||
response = SQLexecution(executeSQL, sql)
|
response = SQLexecution(executeSQL, sql)
|
||||||
if response[:success]
|
if response[:success]
|
||||||
# intention = Dict(:intention=> "$(thoughtDict[:plan])")
|
# intention = Dict(:intention=> "$(thoughtDict[:plan])")
|
||||||
extracted = extractContent_dataframe(response[:result], text2textInstructLLM)
|
extracted = extractContent_dataframe(response[:result], text2textInstructLLM, sql)
|
||||||
return (text=extracted, rawresponse=response[:result])
|
return (text=extracted, rawresponse=response[:result])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -947,9 +866,128 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function;
|
|||||||
:question=> query,
|
:question=> query,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
# context = Dict(
|
||||||
|
# :tablelist => listAllTable_str(executeSQL)[:result]
|
||||||
|
# )
|
||||||
|
#XXX find a way to recreate the schema from a existing database
|
||||||
context = Dict(
|
context = Dict(
|
||||||
:tablelist => listAllTable_str(executeSQL)[:result]
|
:tablelist =>
|
||||||
|
"""
|
||||||
|
Here are SQL that used to create tables in the database:
|
||||||
|
create table customer (
|
||||||
|
customer_id uuid primary key default gen_random_uuid (),
|
||||||
|
customer_firstname varchar(128),
|
||||||
|
customer_lastname varchar(128),
|
||||||
|
customer_displayname varchar(128) not null,
|
||||||
|
customer_username varchar(128),
|
||||||
|
customer_password varchar(128),
|
||||||
|
customer_gender varchar(128),
|
||||||
|
country varchar(128),
|
||||||
|
telephone varchar(128),
|
||||||
|
email varchar(128) not null,
|
||||||
|
customer_birthdate varchar(128),
|
||||||
|
note text,
|
||||||
|
|
||||||
|
other_attributes jsonb,
|
||||||
|
created_time timestamptz default current_timestamp,
|
||||||
|
updated_time timestamptz default current_timestamp,
|
||||||
|
description text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table retailer (
|
||||||
|
retailer_id uuid primary key default gen_random_uuid (),
|
||||||
|
retailer_name varchar(128) not null,
|
||||||
|
retailer_username varchar(128) not null,
|
||||||
|
retailer_password varchar(128) not null,
|
||||||
|
retailer_address text not null,
|
||||||
|
country varchar(128) not null,
|
||||||
|
contact_person varchar(128) not null,
|
||||||
|
telephone varchar(128) not null,
|
||||||
|
email varchar(128) not null,
|
||||||
|
note text,
|
||||||
|
|
||||||
|
other_attributes jsonb,
|
||||||
|
created_time timestamptz default current_timestamp,
|
||||||
|
updated_time timestamptz default current_timestamp,
|
||||||
|
description text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table food (
|
||||||
|
food_id uuid primary key default gen_random_uuid (),
|
||||||
|
food_name varchar(128) not null,
|
||||||
|
country varchar(128),
|
||||||
|
spiciness integer,
|
||||||
|
sweetness integer,
|
||||||
|
sourness integer,
|
||||||
|
savoriness integer,
|
||||||
|
bitterness integer,
|
||||||
|
serving_temperature integer,
|
||||||
|
note text,
|
||||||
|
other_attributes jsonb,
|
||||||
|
|
||||||
|
created_time timestamptz default current_timestamp,
|
||||||
|
updated_time timestamptz default current_timestamp,
|
||||||
|
description text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table wine (
|
||||||
|
wine_id uuid primary key default gen_random_uuid (),
|
||||||
|
seo_name varchar(128) not null,
|
||||||
|
wine_name varchar(128) not null,
|
||||||
|
winery varchar(128) not null,
|
||||||
|
vintage integer not null,
|
||||||
|
region varchar(128) not null,
|
||||||
|
country varchar(128) not null,
|
||||||
|
wine_type varchar(128) not null,
|
||||||
|
grape varchar(128) not null,
|
||||||
|
serving_temperature varchar(128) not null,
|
||||||
|
intensity integer,
|
||||||
|
sweetness integer,
|
||||||
|
tannin integer,
|
||||||
|
acidity integer,
|
||||||
|
fizziness integer,
|
||||||
|
tasting_notes text,
|
||||||
|
note text,
|
||||||
|
other_attributes jsonb,
|
||||||
|
|
||||||
|
created_time timestamptz default current_timestamp,
|
||||||
|
updated_time timestamptz default current_timestamp,
|
||||||
|
description text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table wine_food (
|
||||||
|
wine_id uuid references wine(wine_id),
|
||||||
|
food_id uuid references food(food_id),
|
||||||
|
constraint wine_food_id primary key (wine_id, food_id),
|
||||||
|
|
||||||
|
created_time timestamptz default current_timestamp,
|
||||||
|
updated_time timestamptz default current_timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE retailer_wine (
|
||||||
|
retailer_id uuid references retailer(retailer_id),
|
||||||
|
wine_id uuid references wine(wine_id),
|
||||||
|
constraint retailer_wine_id primary key (retailer_id, wine_id),
|
||||||
|
price NUMERIC(10, 2),
|
||||||
|
currency varchar(3) not null,
|
||||||
|
|
||||||
|
created_time timestamptz default current_timestamp,
|
||||||
|
updated_time timestamptz default current_timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE retailer_food (
|
||||||
|
retailer_id uuid references retailer(retailer_id),
|
||||||
|
food_id uuid references food(food_id),
|
||||||
|
constraint retailer_food_id primary key (retailer_id, food_id),
|
||||||
|
price NUMERIC(10, 2),
|
||||||
|
currency varchar(3) not null,
|
||||||
|
|
||||||
|
created_time timestamptz default current_timestamp,
|
||||||
|
updated_time timestamptz default current_timestamp
|
||||||
|
);
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
transitionargs = (
|
transitionargs = (
|
||||||
decisionMaker=decisionMaker,
|
decisionMaker=decisionMaker,
|
||||||
evaluator=evaluator,
|
evaluator=evaluator,
|
||||||
@@ -963,9 +1001,25 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function;
|
|||||||
|
|
||||||
earlystop(state) = state[:reward] >= 8 ? true : false
|
earlystop(state) = state[:reward] >= 8 ? true : false
|
||||||
|
|
||||||
_, resultState = LLMMCTS.runMCTS(initialstate, transition, transitionargs;
|
root, _, resultState, highValueState =
|
||||||
totalsample=1, maxdepth=3, maxiterations=3, explorationweight=1.0,
|
LLMMCTS.runMCTS(initialstate, transition, transitionargs;
|
||||||
earlystop=earlystop)
|
horizontalSampleExpansionPhase=3,
|
||||||
|
horizontalSampleSimulationPhase=3,
|
||||||
|
maxSimulationDepth=5,
|
||||||
|
maxiterations=1,
|
||||||
|
explorationweight=1.0,
|
||||||
|
earlystop=earlystop,
|
||||||
|
saveSimulatedNode=true,
|
||||||
|
multithread=false)
|
||||||
|
|
||||||
|
# compare all high value state answer then select the best one
|
||||||
|
if length(highValueState) > 0
|
||||||
|
# open("/appfolder/app/highValueState.json", "w") do io
|
||||||
|
# JSON3.pretty(io, highValueState)
|
||||||
|
# end
|
||||||
|
selected = compareState(query, highValueState, text2textInstructLLM)
|
||||||
|
resultState = highValueState[selected] #BUG compareState() select 0
|
||||||
|
end
|
||||||
latestKey, latestInd = GeneralUtils.findHighestIndexKey(resultState[:thoughtHistory], "observation")
|
latestKey, latestInd = GeneralUtils.findHighestIndexKey(resultState[:thoughtHistory], "observation")
|
||||||
action_input = Symbol("action_input_$latestInd") # latest sql
|
action_input = Symbol("action_input_$latestInd") # latest sql
|
||||||
sql = resultState[:thoughtHistory][action_input]
|
sql = resultState[:thoughtHistory][action_input]
|
||||||
@@ -978,11 +1032,13 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function;
|
|||||||
insertSQLVectorDB(resultState[:thoughtHistory][:question], sql)
|
insertSQLVectorDB(resultState[:thoughtHistory][:question], sql)
|
||||||
end
|
end
|
||||||
|
|
||||||
if extracted === nothing #BUG
|
if extracted === nothing
|
||||||
println("query() return nothing")
|
println("query() return nothing")
|
||||||
end
|
end
|
||||||
|
|
||||||
return (text=extracted, rawresponse=resultState[:rawresponse])
|
result = (text=extracted, rawresponse=resultState[:rawresponse])
|
||||||
|
|
||||||
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -1003,7 +1059,7 @@ function makeNewState(currentstate::T1, thoughtDict::T4, rawresponse, response::
|
|||||||
reward::T3, isterminal::Bool
|
reward::T3, isterminal::Bool
|
||||||
)::NamedTuple{(:newNodeKey, :newstate), Tuple{String, Dict{Symbol, <:Any}}} where {T1<:AbstractDict, T2<:AbstractString, T3<:Number, T4<:AbstractDict}
|
)::NamedTuple{(:newNodeKey, :newstate), Tuple{String, Dict{Symbol, <:Any}}} where {T1<:AbstractDict, T2<:AbstractString, T3<:Number, T4<:AbstractDict}
|
||||||
|
|
||||||
keys = [:understanding, :reasoning, :action_name, :action_input, :observation]
|
keys = [:comprehension, :action_name, :action_input, :observation]
|
||||||
# latestKeys = []
|
# latestKeys = []
|
||||||
|
|
||||||
currentstate_latestKey, currentstate_latestIndice =
|
currentstate_latestKey, currentstate_latestIndice =
|
||||||
@@ -1011,7 +1067,7 @@ function makeNewState(currentstate::T1, thoughtDict::T4, rawresponse, response::
|
|||||||
nextindice = currentstate_latestKey !== nothing ? currentstate_latestIndice + 1 : 1
|
nextindice = currentstate_latestKey !== nothing ? currentstate_latestIndice + 1 : 1
|
||||||
# currentstate_latestKey == :NA ? 1 : currentstate_latestIndice + 1
|
# currentstate_latestKey == :NA ? 1 : currentstate_latestIndice + 1
|
||||||
|
|
||||||
currentstate_latestKey = makeNextKey.(keys, nextindice)
|
currentstate_latestKey = makekey.(keys, nextindice)
|
||||||
|
|
||||||
# add Thought, action, observation to thoughtHistory
|
# add Thought, action, observation to thoughtHistory
|
||||||
newstate = deepcopy(currentstate)
|
newstate = deepcopy(currentstate)
|
||||||
@@ -1034,11 +1090,8 @@ function makeNewState(currentstate::T1, thoughtDict::T4, rawresponse, response::
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
makeNextKey(key, indice) = Symbol("$(key)_$indice")
|
|
||||||
|
|
||||||
|
|
||||||
function generatequestion(state::T1, context, text2textInstructLLM::Function;
|
function generatequestion(state::T1, context, text2textInstructLLM::Function;
|
||||||
similarSQL::Union{T2, Nothing}=nothing
|
similarSQL::Union{T2, Nothing}=nothing, maxattempt=10
|
||||||
)::String where {T1<:AbstractDict, T2<:AbstractString}
|
)::String where {T1<:AbstractDict, T2<:AbstractString}
|
||||||
|
|
||||||
similarSQL =
|
similarSQL =
|
||||||
@@ -1098,6 +1151,9 @@ function generatequestion(state::T1, context, text2textInstructLLM::Function;
|
|||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
header = ["Understanding:", "Q1:"]
|
||||||
|
dictkey = ["understanding", "q1"]
|
||||||
|
|
||||||
workprogress = ""
|
workprogress = ""
|
||||||
for (k, v) in state[:thoughtHistory]
|
for (k, v) in state[:thoughtHistory]
|
||||||
if k ∉ [:query]
|
if k ∉ [:query]
|
||||||
@@ -1107,17 +1163,15 @@ function generatequestion(state::T1, context, text2textInstructLLM::Function;
|
|||||||
|
|
||||||
response = nothing # store for show when error msg show up
|
response = nothing # store for show when error msg show up
|
||||||
errornote = ""
|
errornote = ""
|
||||||
noise = ""
|
|
||||||
|
|
||||||
for attempt in 1:10
|
for attempt in 1:maxattempt
|
||||||
usermsg =
|
usermsg =
|
||||||
"""
|
"""
|
||||||
$(context[:tablelist])
|
$(context[:tablelist])
|
||||||
User query: $(state[:thoughtHistory][:question])
|
User query: $(state[:thoughtHistory][:question])
|
||||||
Example: $similarSQL
|
Example: $similarSQL
|
||||||
Your work progress: $workprogress
|
Your work progress: $workprogress
|
||||||
$errornote
|
P.S. $errornote
|
||||||
$noise
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_prompt =
|
_prompt =
|
||||||
@@ -1127,42 +1181,28 @@ function generatequestion(state::T1, context, text2textInstructLLM::Function;
|
|||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
prompt *=
|
|
||||||
"""
|
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
|
||||||
|
|
||||||
try
|
response = text2textInstructLLM(prompt, modelsize="medium")
|
||||||
response = text2textInstructLLM(prompt)
|
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||||
|
|
||||||
# check if response is valid
|
# check if response is valid
|
||||||
q_number = count("Q", response)
|
q_number = count("Q", response)
|
||||||
if q_number < 1
|
if q_number < 1
|
||||||
errornote = "too few question"
|
errornote = "Your previous attempt has too few question."
|
||||||
error("too few questions only $q_number questions are generated")
|
println("\nERROR YiemAgent generatequestion(). Attempt $attempt/$maxattempt. $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
end
|
continue
|
||||||
if occursin('`', response)
|
|
||||||
response = replace(response, '`'=>"")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# response = string(split(response, "Please")[1]) # LLM usually add comments which is no need.
|
|
||||||
responsedict = GeneralUtils.textToDict(response,
|
|
||||||
["Understanding", "Q1"],
|
|
||||||
rightmarker=":", symbolkey=true; lowercasekey=true)
|
|
||||||
response = "Q1: " * responsedict[:q1]
|
|
||||||
println("\n~~~ SQLLLM generatequestion() ", @__FILE__, " ", @__LINE__)
|
|
||||||
pprintln(Dict(responsedict))
|
|
||||||
return response
|
|
||||||
catch e
|
|
||||||
io = IOBuffer()
|
|
||||||
showerror(io, e)
|
|
||||||
errorMsg = String(take!(io))
|
|
||||||
st = sprint((io, v) -> show(io, "text/plain", v), stacktrace(catch_backtrace()))
|
|
||||||
println("\n~~~ SQLLLM generatequestion() Attempt $attempt. Error occurred: $errorMsg\n$st ", @__FILE__, " ", @__LINE__)
|
|
||||||
noise = GeneralUtils.randstrings(3, 5)
|
|
||||||
end
|
end
|
||||||
|
if occursin('`', response)
|
||||||
|
response = replace(response, '`'=>"")
|
||||||
|
end
|
||||||
|
|
||||||
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
|
dictKey=dictkey, symbolkey=true)
|
||||||
|
response = "Q1: " * responsedict[:q1]
|
||||||
|
println("\nSQLLLM generatequestion() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
pprintln(Dict(responsedict))
|
||||||
|
return response
|
||||||
end
|
end
|
||||||
error("generatequestion failed to generate a thought ", response)
|
error("generatequestion failed to generate a thought ", response)
|
||||||
end
|
end
|
||||||
@@ -1212,8 +1252,6 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
module llmfunction
|
module llmfunction
|
||||||
|
|
||||||
export listAllTable_json, listAllTable_str, tableinfo, getdata, finalAnswerBox,
|
export listAllTable_json, listAllTable_str, tableinfo, getdata, finalAnswerBox,
|
||||||
getTableNameFromSQL, extractContent_dataframe, SQLexecution
|
getTableNameFromSQL, extractContent_dataframe, SQLexecution, compareState
|
||||||
|
|
||||||
using HTTP, JSON3, URIs, Random, PrettyPrinting, UUIDs, LibPQ, Tables, DataFrames, CSV,
|
using HTTP, JSON3, URIs, Random, PrettyPrinting, UUIDs, LibPQ, Tables, DataFrames, CSV,
|
||||||
DataStructures, StatsBase
|
DataStructures, StatsBase, Dates
|
||||||
using GeneralUtils, LLMMCTS
|
using GeneralUtils, LLMMCTS
|
||||||
using ..util
|
using ..util
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ julia> result = response[:result]
|
|||||||
# Signature
|
# Signature
|
||||||
"""
|
"""
|
||||||
function listAllTable_json(executeSQL::Function
|
function listAllTable_json(executeSQL::Function
|
||||||
)::NamedTuple{(:result, :success),Tuple{DataFrame,Bool}}
|
)::NamedTuple{(:result, :success),Tuple{DataFrame,Bool}}
|
||||||
|
|
||||||
sql = """
|
sql = """
|
||||||
SELECT
|
SELECT
|
||||||
@@ -352,79 +352,39 @@ function getdata_decisionMaker(state::Dict, context::Dict, text2textInstructLLM:
|
|||||||
|
|
||||||
Hints = "None"
|
Hints = "None"
|
||||||
|
|
||||||
# """
|
systemmsg =
|
||||||
# Here are some useful SQL programs:
|
"""
|
||||||
# $usefulSQL
|
You are an assistant helping the user to execute SQL code from the user's query.
|
||||||
# """
|
|
||||||
|
|
||||||
# systemmsg =
|
At each round of conversation, the user will give you:
|
||||||
# """
|
Context: ...
|
||||||
# You are an assistant helping the user to execute SQL code from the user's query.
|
User intention: ...
|
||||||
|
Code executed from the last round: ...
|
||||||
|
Execution error: execution error of the last round code.
|
||||||
|
|
||||||
# At each round of conversation, the user will give you:
|
You should consider the following guidelines:
|
||||||
# Context: ...
|
- Text information in the database is sometimes stored in lower case. If your search returns empty, try using lower case to search.
|
||||||
# User intention: ...
|
|
||||||
# Code executed from the last round: ...
|
|
||||||
# Execution error: execution error of the last round code.
|
|
||||||
|
|
||||||
# You should consider the following guidelines:
|
You should then respond to the user with:
|
||||||
# - Text information in the database is sometimes stored in lower case. If your search returns empty, try using lower case to search.
|
1) Comprehension:
|
||||||
|
- State your comprehension about the current situation.
|
||||||
|
3) Plan: Step-by-step instructions of how to complete the task.
|
||||||
|
- Focus on improving the code from the last round.
|
||||||
|
- Do not create any table in the database.
|
||||||
|
4) Code:
|
||||||
|
- Write new improved code.
|
||||||
|
- Do not wrap the code and no comment as it will be executed directly without any modification against the database.
|
||||||
|
|
||||||
# You should then respond to the user with:
|
You should only respond in format as described below and nothing more:
|
||||||
# - thought: Why the code does not complete the task. What does the execution error imply exactly?
|
Comprehension: ...
|
||||||
# - plan: Step-by-step instructions of how to complete the task.
|
Plan:
|
||||||
# 1) Focus on improving the code from the last round.
|
1) ...
|
||||||
# 2) Do not create any table in the database.
|
2) ...
|
||||||
# - code:
|
...
|
||||||
# 1) Write new improved code.
|
Code: ...
|
||||||
# 2) Do not wrap the code and no comment as it will be executed directly without any modification against the database.
|
|
||||||
|
|
||||||
# You should only respond in format as described below and nothing more:
|
Let's begin!
|
||||||
# thought: ...
|
"""
|
||||||
# plan:
|
|
||||||
# 1) ...
|
|
||||||
# 2) ...
|
|
||||||
# ...
|
|
||||||
# code: ...
|
|
||||||
|
|
||||||
# Let's begin!
|
|
||||||
# """
|
|
||||||
|
|
||||||
systemmsg = """
|
|
||||||
You are an assistant helping the user to execute SQL code from the user's query.
|
|
||||||
|
|
||||||
At each round of conversation, the user will give you:
|
|
||||||
Context: ...
|
|
||||||
User intention: ...
|
|
||||||
Code executed from the last round: ...
|
|
||||||
Execution error: execution error of the last round code.
|
|
||||||
|
|
||||||
You should consider the following guidelines:
|
|
||||||
- Text information in the database is sometimes stored in lower case. If your search returns empty, try using lower case to search.
|
|
||||||
|
|
||||||
You should then respond to the user with:
|
|
||||||
1) Understanding:
|
|
||||||
- State your understanding about the current situation.
|
|
||||||
2) Reasoning:
|
|
||||||
- State your step by step reasoning about the current situation.
|
|
||||||
3) Plan: Step-by-step instructions of how to complete the task.
|
|
||||||
- Focus on improving the code from the last round.
|
|
||||||
- Do not create any table in the database.
|
|
||||||
4) Code:
|
|
||||||
- Write new improved code.
|
|
||||||
- Do not wrap the code and no comment as it will be executed directly without any modification against the database.
|
|
||||||
|
|
||||||
You should only respond in format as described below and nothing more:
|
|
||||||
Understanding: ...
|
|
||||||
Reasoning: ...
|
|
||||||
Plan:
|
|
||||||
1) ...
|
|
||||||
2) ...
|
|
||||||
...
|
|
||||||
Code: ...
|
|
||||||
|
|
||||||
Let's begin!
|
|
||||||
"""
|
|
||||||
|
|
||||||
noise = ""
|
noise = ""
|
||||||
note_flag = ""
|
note_flag = ""
|
||||||
@@ -446,15 +406,16 @@ function getdata_decisionMaker(state::Dict, context::Dict, text2textInstructLLM:
|
|||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
prompt *= """
|
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
"""
|
|
||||||
try
|
try
|
||||||
response = text2textInstructLLM(prompt)
|
response = text2textInstructLLM(prompt, modelsize="medium")
|
||||||
responsedict = GeneralUtils.textToDict(response,
|
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||||
["Understanding", "Reasoning", "Plan", "Code"];
|
|
||||||
rightmarker=":", symbolkey=true, lowercasekey=true)
|
header = ["Comprehension:", "Plan:", "Code:"]
|
||||||
|
dictkey = ["comprehension", "plan", "code"]
|
||||||
|
|
||||||
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
|
dictKey=dictkey, symbolkey=true)
|
||||||
_code = responsedict[:code]
|
_code = responsedict[:code]
|
||||||
code = strip(_code)
|
code = strip(_code)
|
||||||
|
|
||||||
@@ -480,7 +441,7 @@ function getdata_decisionMaker(state::Dict, context::Dict, text2textInstructLLM:
|
|||||||
|
|
||||||
println("\n~~~ getdata_decisionMaker() ", @__FILE__, " ", @__LINE__)
|
println("\n~~~ getdata_decisionMaker() ", @__FILE__, " ", @__LINE__)
|
||||||
pprintln(Dict(responsedict))
|
pprintln(Dict(responsedict))
|
||||||
return (thought=responsedict[:reasoning], code=code, success=true, errormsg=nothing)
|
return (thought=responsedict[:comprehension], code=code, success=true, errormsg=nothing)
|
||||||
catch e
|
catch e
|
||||||
io = IOBuffer()
|
io = IOBuffer()
|
||||||
showerror(io, e)
|
showerror(io, e)
|
||||||
@@ -556,7 +517,7 @@ function SQLexecution(executeSQL::Function, sql::T
|
|||||||
|
|
||||||
tablesize = size(df)
|
tablesize = size(df)
|
||||||
row, column = tablesize
|
row, column = tablesize
|
||||||
if row == 0 # if 0 row
|
if row == 0
|
||||||
error("The resulting table has 0 row. Possible causes: 1) Your search criteria might be too specific. Relaxing some conditions could yield better results. Remember, you can always refine your search later. 2) There could be a typo in your search query. 3) You might be searching in the wrong place.")
|
error("The resulting table has 0 row. Possible causes: 1) Your search criteria might be too specific. Relaxing some conditions could yield better results. Remember, you can always refine your search later. 2) There could be a typo in your search query. 3) You might be searching in the wrong place.")
|
||||||
elseif column > 30
|
elseif column > 30
|
||||||
error("SQL execution failed. An unexpected error occurred. Please try again.")
|
error("SQL execution failed. An unexpected error occurred. Please try again.")
|
||||||
@@ -600,7 +561,7 @@ end
|
|||||||
|
|
||||||
# Signature
|
# Signature
|
||||||
"""
|
"""
|
||||||
function extractContent_dataframe(df::DataFrame, text2textInstructLLM::Function
|
function extractContent_dataframe(df::DataFrame, text2textInstructLLM::Function, action::String
|
||||||
)::String
|
)::String
|
||||||
tablesize = size(df)
|
tablesize = size(df)
|
||||||
row = tablesize[1]
|
row = tablesize[1]
|
||||||
@@ -631,32 +592,35 @@ function extractContent_dataframe(df::DataFrame, text2textInstructLLM::Function
|
|||||||
|
|
||||||
dfstr = GeneralUtils.dfToString(df1)
|
dfstr = GeneralUtils.dfToString(df1)
|
||||||
|
|
||||||
systemmsg = """
|
systemmsg =
|
||||||
You are an assistant that readouts the resulting table after the user executing SQL command.
|
"""
|
||||||
|
You are an assistant that readouts the resulting table after the user executing SQL command.
|
||||||
|
|
||||||
At each round of conversation, the user will give you:
|
At each round of conversation, the user will give you:
|
||||||
- User intention: ...
|
- User SQL: the SQL query user executed.
|
||||||
- Resulting table dimension: ...
|
- Resulting table: The resulting table after executing the user's intention.
|
||||||
- Resulting table: The resulting table after executing the user's intention.
|
|
||||||
|
|
||||||
You should then respond to the user with:
|
You should then respond to the user with:
|
||||||
- About_resulting_table:
|
- About_resulting_table:
|
||||||
1) What is the resulting table represent?
|
1) What is the resulting table represent?
|
||||||
- Search_summary:
|
- Search_summary:
|
||||||
1) Summarize the table's content based on the user intension in verbal English.
|
1) Summarize the table's content based on the user intension in verbal English.
|
||||||
Here are some example:
|
Here are some example:
|
||||||
Bad example (you are not Summarize the table content): there are 2 columns in the table i.e. "cash" and "number".
|
Bad example (you are not Summarize the table content): there are 2 columns in the table i.e. "cash" and "number".
|
||||||
2) Do not generate additional text.
|
2) Do not generate additional text.
|
||||||
|
|
||||||
You should only respond in format as described below:
|
You should only respond in format as described below:
|
||||||
About_resulting_table: ...
|
About_resulting_table: ...
|
||||||
Search_summary: ...
|
Search_summary: ...
|
||||||
|
|
||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
usermsg = """
|
|
||||||
Resulting table: $dfstr
|
usermsg =
|
||||||
"""
|
"""
|
||||||
|
User SQL: $action
|
||||||
|
Resulting table: $dfstr
|
||||||
|
"""
|
||||||
_prompt =
|
_prompt =
|
||||||
[
|
[
|
||||||
Dict(:name => "system", :text => systemmsg),
|
Dict(:name => "system", :text => systemmsg),
|
||||||
@@ -664,20 +628,34 @@ function extractContent_dataframe(df::DataFrame, text2textInstructLLM::Function
|
|||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
prompt *= """
|
header = ["About_resulting_table:", "Search_summary:"]
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
dictkey = ["about_resulting_table", "search_summary"]
|
||||||
"""
|
|
||||||
for i in 1:5
|
for i in 1:5
|
||||||
response = text2textInstructLLM(prompt)
|
response = text2textInstructLLM(prompt, modelsize="medium")
|
||||||
responsedict = GeneralUtils.textToDict(response, ["About_resulting_table", "Search_summary"],
|
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||||
rightmarker=":", symbolkey=true)
|
|
||||||
|
kw = []
|
||||||
|
# use for loop and detect_keyword function to get the exact variation of each keyword in the text then push to kw list
|
||||||
|
for keyword in header
|
||||||
|
detected = GeneralUtils.detect_keyword(keyword, response)
|
||||||
|
push!(kw, detected)
|
||||||
|
end
|
||||||
|
if nothing ∈ kw
|
||||||
|
println("Some keywords are missing, Required keywords=$header, Response keywords=$kw ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue # try again next loop
|
||||||
|
end
|
||||||
|
|
||||||
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
|
dictKey=dictkey, symbolkey=true)
|
||||||
|
|
||||||
# result = dfstr
|
# result = dfstr
|
||||||
result = """
|
result =
|
||||||
Summary: $(responsedict[:Search_summary])
|
"""
|
||||||
More details: $dfstr
|
Summary: $(responsedict[:search_summary])
|
||||||
"""
|
More details: $dfstr
|
||||||
|
"""
|
||||||
|
|
||||||
if row > 2
|
if row > 2
|
||||||
result *= "There are many more rows, but they are truncated because there are too many of them."
|
result *= "There are many more rows, but they are truncated because there are too many of them."
|
||||||
@@ -766,11 +744,11 @@ function getTableNameFromSQL(sql::T, text2textInstructLLM::Function)::Vector{Str
|
|||||||
Query: ...
|
Query: ...
|
||||||
|
|
||||||
You should then respond to the user with:
|
You should then respond to the user with:
|
||||||
- table_name: a list of table name that the user mentioned in the query.
|
- Table_name: a list of table name that the user mentioned in the query.
|
||||||
For example, ["color", "type"]
|
For example, ["color", "type"]
|
||||||
|
|
||||||
You must only respond in format as described below:
|
You must only respond in format as described below:
|
||||||
table_name: ["...", "...", ...]
|
Table_name: ["...", "...", ...]
|
||||||
|
|
||||||
Let's begin!
|
Let's begin!
|
||||||
"""
|
"""
|
||||||
@@ -786,17 +764,16 @@ function getTableNameFromSQL(sql::T, text2textInstructLLM::Function)::Vector{Str
|
|||||||
]
|
]
|
||||||
|
|
||||||
# put in model format
|
# put in model format
|
||||||
prompt = GeneralUtils.formatLLMtext(_prompt; formatname="llama3instruct")
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
prompt *= """
|
header = ["Table_name:"]
|
||||||
<|start_header_id|>assistant<|end_header_id|>
|
dictkey = ["table_name"]
|
||||||
"""
|
|
||||||
|
|
||||||
for attempt in 1:5
|
for attempt in 1:5
|
||||||
try
|
try
|
||||||
response = text2textInstructLLM(prompt)
|
response = text2textInstructLLM(prompt, modelsize="medium")
|
||||||
responsedict = GeneralUtils.textToDict(response,
|
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||||
["table_name"],
|
responsedict = GeneralUtils.textToDict(response, header;
|
||||||
rightmarker=":", symbolkey=true)
|
dictKey=dictkey, symbolkey=true)
|
||||||
response = copy(JSON3.read(responsedict[:table_name]))
|
response = copy(JSON3.read(responsedict[:table_name]))
|
||||||
|
|
||||||
return response
|
return response
|
||||||
@@ -814,6 +791,178 @@ function getTableNameFromSQL(sql::T, text2textInstructLLM::Function)::Vector{Str
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
""" Compare multiple solution attempts and select the most accurate one.
|
||||||
|
|
||||||
|
This function evaluates multiple solution attempts for a given question and determines which attempt
|
||||||
|
provides the most accurate and relevant response. It uses an LLM to analyze and compare the attempts,
|
||||||
|
considering their actions and observations.
|
||||||
|
|
||||||
|
# Arguments
|
||||||
|
- `question::String`
|
||||||
|
The original question or task that was attempted to be solved
|
||||||
|
- `highValueStateList::Vector{Dict}`
|
||||||
|
List of states containing different solution attempts and their results
|
||||||
|
- `text2textInstructLLM::Function`
|
||||||
|
A function that handles communication to LLM service
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
- `Integer`
|
||||||
|
The index of the selected best response (1-based indexing)
|
||||||
|
|
||||||
|
# Example
|
||||||
|
```jldoctest
|
||||||
|
julia>
|
||||||
|
```
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
- The function makes up to 10 attempts to get a valid response from the LLM
|
||||||
|
- Each state in highValueStateList should contain a thoughtHistory with action_input and observation
|
||||||
|
- The LLM evaluates attempts based on accuracy and relevance to the original question
|
||||||
|
"""
|
||||||
|
function compareState(question::String, highValueStateList::Vector{T},
|
||||||
|
text2textInstructLLM::Function)::Integer where {T<:AbstractDict}
|
||||||
|
|
||||||
|
systemmsg =
|
||||||
|
"""
|
||||||
|
<Your profile>
|
||||||
|
- You are a helpful assistant
|
||||||
|
</Your profile>
|
||||||
|
<Situation>
|
||||||
|
The user has made multiple attempts to solve the question, resulting in various answers
|
||||||
|
<Your mission>
|
||||||
|
- Identify and select the most accurate and relevant response from these multiple results for the user
|
||||||
|
</Your mission>
|
||||||
|
<At each round of conversation, you will be given the following>
|
||||||
|
Question: the question the user is trying to answer
|
||||||
|
Attempt: the user's attempted actions and their corresponding results
|
||||||
|
</At each round of conversation, you will be given the following>
|
||||||
|
<You should then respond to the user with the following>
|
||||||
|
Comparison: a comparison of all results from all attempts
|
||||||
|
Rationale: a brief explanation of why the selected response is the most accurate and relevant
|
||||||
|
Selected_response_number: the number the selected response in the list of results (e.g., 1, 2, 3, ...)
|
||||||
|
</You should then respond to the user with the following>
|
||||||
|
<You should only respond in format as described below>
|
||||||
|
Comparison: ...
|
||||||
|
Rationale: ...
|
||||||
|
Selected_response_number: ...
|
||||||
|
</You should only respond in format as described below>
|
||||||
|
<Here are some examples>
|
||||||
|
User's question: "How many German wines do you have?"
|
||||||
|
Attempt 1:
|
||||||
|
Action: SELECT COUNT(*) FROM wines WHERE country = 'Germany'
|
||||||
|
Result: 100 wines
|
||||||
|
Attempt 2:
|
||||||
|
Action: SELECT COUNT(*) FROM wines WHERE country = 'Germany' AND type = 'Red'
|
||||||
|
Result: 50 red wines
|
||||||
|
Comparison: The second attempt counts only German red wines while the first attempt includes all German wines.
|
||||||
|
Rationale: The user is asking for the number of German wines without specifying a type, so the most accurate response is the first attempt because it includes all German wines.
|
||||||
|
Selected_response_number:1
|
||||||
|
</Here are some examples>
|
||||||
|
|
||||||
|
Let's begin!
|
||||||
|
"""
|
||||||
|
|
||||||
|
potentialSolution = []
|
||||||
|
keys = [:action_input, :observation]
|
||||||
|
# extract the last action_name, action_input, observation of each state in highValueStateList and store them in a dictionary then push into potentialSolution
|
||||||
|
for state in highValueStateList
|
||||||
|
thoughtHistory = state[:thoughtHistory]
|
||||||
|
_, currentstate_latestIndice =
|
||||||
|
GeneralUtils.findHighestIndexKey(thoughtHistory, keys[1])
|
||||||
|
latestKeys = makekey.(keys, currentstate_latestIndice)
|
||||||
|
d = Dict()
|
||||||
|
# get the last action_name, action_input, observation of currentstate
|
||||||
|
for (i,v) in enumerate(keys)
|
||||||
|
d[v] = thoughtHistory[latestKeys[i]]
|
||||||
|
end
|
||||||
|
push!(potentialSolution, d)
|
||||||
|
end
|
||||||
|
|
||||||
|
"""
|
||||||
|
# put potential solutions from potentialSolution into the following form
|
||||||
|
Attempt 1
|
||||||
|
action_name:
|
||||||
|
action_input:
|
||||||
|
observation:
|
||||||
|
Attempt 2
|
||||||
|
action_name:
|
||||||
|
action_input:
|
||||||
|
observation:
|
||||||
|
...
|
||||||
|
"""
|
||||||
|
potentialSolutionStr = ""
|
||||||
|
for (i, state) in enumerate(potentialSolution)
|
||||||
|
potentialSolutionStr *= "Attempt $i\n"
|
||||||
|
for k in keys
|
||||||
|
potentialSolutionStr *= "$k: $(state[k])\n"
|
||||||
|
println("")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
errornote = ""
|
||||||
|
|
||||||
|
for attempt in 1:10
|
||||||
|
errorFlag = false
|
||||||
|
|
||||||
|
usermsg =
|
||||||
|
"""
|
||||||
|
Question: $question
|
||||||
|
Attempts: $potentialSolutionStr
|
||||||
|
P.S. $errornote
|
||||||
|
"""
|
||||||
|
|
||||||
|
_prompt =
|
||||||
|
[
|
||||||
|
Dict(:name=> "system", :text=> systemmsg),
|
||||||
|
Dict(:name=> "user", :text=> usermsg)
|
||||||
|
]
|
||||||
|
|
||||||
|
# put in model format
|
||||||
|
prompt = GeneralUtils.formatLLMtext(_prompt, "granite3")
|
||||||
|
|
||||||
|
header = ["Comparison:", "Rationale:", "Selected_response_number:"]
|
||||||
|
dictkey = ["comparison", "rationale", "selected_response_number"]
|
||||||
|
|
||||||
|
response = text2textInstructLLM(prompt, modelsize="medium")
|
||||||
|
|
||||||
|
# sometime LLM output something like **Comprehension**: which is not expected
|
||||||
|
response = replace(response, "**"=>"")
|
||||||
|
response = replace(response, "***"=>"")
|
||||||
|
response = GeneralUtils.deFormatLLMtext(response, "granite3")
|
||||||
|
|
||||||
|
# make sure every header is in the response
|
||||||
|
for i in header
|
||||||
|
detected = GeneralUtils.detect_keyword(i, response)
|
||||||
|
if detected === nothing
|
||||||
|
errornote = "Your previous attempt didn't provide $i"
|
||||||
|
errorFlag = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if errorFlag
|
||||||
|
println("\nERROR SQLLLM compareState() Attempt $attempt $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue # skip to the next iteration
|
||||||
|
end
|
||||||
|
|
||||||
|
responsedict = GeneralUtils.textToDict(response, header; dictKey=dictkey, symbolkey=true)
|
||||||
|
|
||||||
|
responsedict[:selected_response_number] = responsedict[:selected_response_number][1] # some time "6\nThe trajectories are incomplete" is generated but I only need the number.
|
||||||
|
try
|
||||||
|
responsedict[:selected_response_number] = parse(Int, responsedict[:selected_response_number]) # convert string "5" into integer 5
|
||||||
|
catch
|
||||||
|
errornote = "In your previous attempt, Selected_response_number was not a number. It must be a number."
|
||||||
|
println("\nERROR SQLLLM compareState() Attempt $attempt. $errornote ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
println("\n~~~ compareState() ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
pprintln(Dict(responsedict))
|
||||||
|
|
||||||
|
return responsedict[:selected_response_number]
|
||||||
|
end
|
||||||
|
error("compareState() failed to generate an evaluation, Response: \n$response\n<|End of error|>", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -850,8 +999,6 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
module util
|
module util
|
||||||
|
|
||||||
|
export makekey
|
||||||
|
|
||||||
|
makekey(key, indice) = Symbol("$(key)_$indice")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
153
system_prompt_template.jl
Normal file
153
system_prompt_template.jl
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
"""
|
||||||
|
Default system message template:
|
||||||
|
|
||||||
|
<Your role>
|
||||||
|
- You are a helpful assistant
|
||||||
|
</Your role>
|
||||||
|
<Situation>
|
||||||
|
- Describe the current situation
|
||||||
|
</Situation>
|
||||||
|
<Your vision>
|
||||||
|
- state your vision of how the situation will evolve, what would you want the situation to evolve into
|
||||||
|
</Your vision>
|
||||||
|
<Your mission>
|
||||||
|
- state the goal
|
||||||
|
</Your mission>
|
||||||
|
<Your mission's objective includes>
|
||||||
|
- Break the goal into smaller steps
|
||||||
|
</Your mission's objective includes>
|
||||||
|
<Your responsibility includes>
|
||||||
|
- state the mini goals that fall under your responsibility
|
||||||
|
</Your responsibility includes>
|
||||||
|
<Your responsibility does NOT includes>
|
||||||
|
-
|
||||||
|
</Your responsibility does NOT includes>
|
||||||
|
<At each round of conversation, you will be given the following information>
|
||||||
|
|
||||||
|
</At each round of conversation, you will be given the following information>
|
||||||
|
<You must follow the following guidelines>
|
||||||
|
-
|
||||||
|
</You must follow the following guidelines>
|
||||||
|
<You should then respond to the user with interleaving Comprehension, Plan, Action_name, Action_input>
|
||||||
|
Comprehension: State your comprehension about the current situation.
|
||||||
|
Plan: Given the current circumstances, outline a detailed, step-by-step plan to accomplish the task. Be specific.
|
||||||
|
Action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the following function names:
|
||||||
|
- CHATBOX which you can use to talk with the user. The input is your intentions for the dialogue. Be specific.
|
||||||
|
- CHECKRESOURCES which you can use to check resources
|
||||||
|
- IMPLEMENT which you can use to implement the solution
|
||||||
|
Action_input: Detail the input for the action.
|
||||||
|
</You should then respond to the user with interleaving Comprehension, Plan, Action_name, Action_input>
|
||||||
|
<You should only respond in format as described below>
|
||||||
|
Comprehension: ...
|
||||||
|
Plan: ...
|
||||||
|
Action_name: ...
|
||||||
|
Action_input: ...
|
||||||
|
</You should only respond in format as described below>
|
||||||
|
<Here are some examples>
|
||||||
|
|
||||||
|
</Here are some examples>
|
||||||
|
|
||||||
|
Let's begin!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
<Your profile>
|
||||||
|
- You are a founder of a tech startup
|
||||||
|
</Your profile>
|
||||||
|
<Situation>
|
||||||
|
- The global rise in bedridden patients, driven by an aging population, presents significant challenges for caregivers. Family members often become primary caretakers, leading to physical and emotional strain. This situation frequently forces caregivers to make difficult choices, including leaving their careers to provide full-time care, which impacts both family finances and personal well-being.
|
||||||
|
</Situation>
|
||||||
|
<Your vision>
|
||||||
|
- We want to develop a system that can help people with bedridden patients and their families so that they could go on with their lives.
|
||||||
|
</Your vision>
|
||||||
|
<Your mission>
|
||||||
|
- To create an innovative caregiving support platform that reduces the physical and emotional burden on family caregivers while ensuring quality care for bedridden patients
|
||||||
|
</Your mission>
|
||||||
|
<Your mission's objectives include>
|
||||||
|
- Develop smart monitoring systems for patient safety
|
||||||
|
- Create automated alert mechanisms for critical situations
|
||||||
|
- Design user-friendly interfaces for remote patient monitoring
|
||||||
|
- Implement AI-driven predictive care recommendations
|
||||||
|
- Build a support network connecting caregivers with healthcare professionals
|
||||||
|
- Establish training modules for family caregivers
|
||||||
|
</Your mission's objectives include>
|
||||||
|
<Your responsibilities include>
|
||||||
|
- Lead product vision and strategy development
|
||||||
|
- Oversee technical implementation and system architecture
|
||||||
|
- Coordinate with healthcare experts for medical validation
|
||||||
|
- Ensure compliance with healthcare regulations
|
||||||
|
- Manage stakeholder relationships
|
||||||
|
- Drive fundraising and business development
|
||||||
|
</Your responsibilities include>
|
||||||
|
<At each round of conversation, you will be given the following>
|
||||||
|
Challenges: user's specific caregiving challenges
|
||||||
|
Context: context and severity of the situation
|
||||||
|
Feedback: comments from family caregivers
|
||||||
|
Solutions: potential solution based on immediate and long-term impact
|
||||||
|
</At each round of conversation, you will be given the following>
|
||||||
|
<You must follow the following guidelines>
|
||||||
|
- Always prioritize patient safety and well-being
|
||||||
|
- Maintain empathy and understanding in all interactions
|
||||||
|
- Focus on practical, implementable solutions
|
||||||
|
- Consider both immediate needs and long-term sustainability
|
||||||
|
- Respect privacy and confidentiality of all stakeholders
|
||||||
|
- Follow healthcare regulations and best practices
|
||||||
|
</You must follow the following guidelines>
|
||||||
|
<You should then respond to the user with interleaving Comprehension, Plan, Action_name, Action_input>
|
||||||
|
Comprehension: State your comprehension about the current situation.
|
||||||
|
Plan: Given the current circumstances, outline a detailed, step-by-step plan to accomplish the task. Be specific.
|
||||||
|
Action_name: (Typically corresponds to the execution of the first step in your plan)
|
||||||
|
Can be one of the following function names:
|
||||||
|
- CHATBOX which you can use to talk with the user. The input is your intentions for the dialogue. Be specific.
|
||||||
|
- CHECKRESOURCES which you can use to check resources
|
||||||
|
- IMPLEMENT which you can use to implement the solution
|
||||||
|
Action_input: Detail the input for the action.
|
||||||
|
</You should then respond to the user with interleaving Comprehension, Plan, Action_name, Action_input>
|
||||||
|
<You should only respond in format as described below>
|
||||||
|
Comprehension: ...
|
||||||
|
Plan: ...
|
||||||
|
Action_name: ...
|
||||||
|
Action_input: ...
|
||||||
|
</You should only respond in format as described below>
|
||||||
|
<Here are some examples>
|
||||||
|
Example 1:
|
||||||
|
Challenges: "My mother needs constant monitoring at night, but I'm exhausted from lack of sleep."
|
||||||
|
Context: Elderly patient with dementia, requires 24/7 supervision
|
||||||
|
Feedback: "Need urgent solution for night monitoring"
|
||||||
|
Solutions: Smart monitoring system with motion sensors and alerts
|
||||||
|
|
||||||
|
Comprehension: The caregiver is experiencing severe sleep deprivation due to nighttime monitoring requirements
|
||||||
|
Plan:
|
||||||
|
1. Assess current monitoring needs
|
||||||
|
2. Propose smart monitoring system installation
|
||||||
|
3. Set up emergency alert system
|
||||||
|
4. Train family on system usage
|
||||||
|
Action_name: CHATBOX
|
||||||
|
Action_input: Discuss specific nighttime behaviors and incidents to determine optimal sensor placement and alert thresholds
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
Challenges: "Managing medication schedules is becoming overwhelming"
|
||||||
|
Context: Patient on multiple medications with complex timing requirements
|
||||||
|
Feedback: "Need help with medication management"
|
||||||
|
Solutions: Automated medication reminder and tracking system
|
||||||
|
|
||||||
|
Comprehension: Caregiver struggling with complex medication management tasks
|
||||||
|
Plan:
|
||||||
|
1. Review current medication schedule
|
||||||
|
2. Implement automated reminder system
|
||||||
|
3. Set up medication tracking log
|
||||||
|
4. Connect with pharmacy for refill automation
|
||||||
|
Action_name: IMPLEMENT
|
||||||
|
Action_input: Deploy medication management module with smart alerts and compliance tracking
|
||||||
|
</Here are some examples>
|
||||||
|
|
||||||
|
Let's begin!
|
||||||
|
"""
|
||||||
41
test/Manifest.toml
Normal file
41
test/Manifest.toml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# This file is machine-generated - editing it directly is not advised
|
||||||
|
|
||||||
|
julia_version = "1.11.4"
|
||||||
|
manifest_format = "2.0"
|
||||||
|
project_hash = "71d91126b5a1fb1020e1098d9d492de2a4438fd2"
|
||||||
|
|
||||||
|
[[deps.Base64]]
|
||||||
|
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||||
|
version = "1.11.0"
|
||||||
|
|
||||||
|
[[deps.InteractiveUtils]]
|
||||||
|
deps = ["Markdown"]
|
||||||
|
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
||||||
|
version = "1.11.0"
|
||||||
|
|
||||||
|
[[deps.Logging]]
|
||||||
|
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||||
|
version = "1.11.0"
|
||||||
|
|
||||||
|
[[deps.Markdown]]
|
||||||
|
deps = ["Base64"]
|
||||||
|
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
||||||
|
version = "1.11.0"
|
||||||
|
|
||||||
|
[[deps.Random]]
|
||||||
|
deps = ["SHA"]
|
||||||
|
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||||
|
version = "1.11.0"
|
||||||
|
|
||||||
|
[[deps.SHA]]
|
||||||
|
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
||||||
|
version = "0.7.0"
|
||||||
|
|
||||||
|
[[deps.Serialization]]
|
||||||
|
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
||||||
|
version = "1.11.0"
|
||||||
|
|
||||||
|
[[deps.Test]]
|
||||||
|
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
|
||||||
|
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||||
|
version = "1.11.0"
|
||||||
2
test/Project.toml
Normal file
2
test/Project.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[deps]
|
||||||
|
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||||
305
test/runtest.jl
305
test/runtest.jl
@@ -1,305 +0,0 @@
|
|||||||
using Revise
|
|
||||||
using LibPQ, JSON3, PrettyPrinting, UUIDs, DataFrames, DataStructures, Base64
|
|
||||||
using GeneralUtils, SQLLLM
|
|
||||||
|
|
||||||
|
|
||||||
config = copy(JSON3.read("config.json"))
|
|
||||||
|
|
||||||
function executeSQL(sql::T) where {T<:AbstractString}
|
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.12 port=10201 dbname=wineDB user=yiemtechnologies password=yiemtechnologies@Postgres_0.0")
|
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
|
||||||
close(DBconnection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
function text2textInstructLLM(prompt::String)
|
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
|
||||||
config[:externalservice][:text2textinstruct][:mqtttopic];
|
|
||||||
msgPurpose="inference",
|
|
||||||
senderName="yiemagent",
|
|
||||||
senderId=string(uuid4()),
|
|
||||||
receiverName="text2textinstruct",
|
|
||||||
mqttBrokerAddress=config[:mqttServerInfo][:broker],
|
|
||||||
mqttBrokerPort=config[:mqttServerInfo][:port],
|
|
||||||
)
|
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
|
||||||
:msgMeta => msgMeta,
|
|
||||||
:payload => Dict(
|
|
||||||
:text => prompt,
|
|
||||||
:kwargs => Dict(
|
|
||||||
:num_ctx => 20480,
|
|
||||||
:temperature => 0.2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
|
||||||
response = _response[:response][:text]
|
|
||||||
|
|
||||||
return response
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function executeSQLVectorDB(sql)
|
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.12 port=10203 dbname=SQLVectorDB user=yiemtechnologies password=yiemtechnologies@Postgres_0.0")
|
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
|
||||||
close(DBconnection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
function addSQLVectorDB(state)
|
|
||||||
# get embedding of the query
|
|
||||||
query = [state[:thoughtHistory][:question]]
|
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
|
||||||
config[:externalservice][:text2textinstruct][:mqtttopic];
|
|
||||||
msgPurpose= "embedding",
|
|
||||||
senderName= "yiemagent",
|
|
||||||
senderId= string(uuid4()),
|
|
||||||
receiverName= "text2textinstruct",
|
|
||||||
mqttBrokerAddress= config[:mqttServerInfo][:broker],
|
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
|
||||||
)
|
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
|
||||||
:msgMeta=> msgMeta,
|
|
||||||
:payload=> Dict(
|
|
||||||
:text=> query
|
|
||||||
)
|
|
||||||
)
|
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
|
||||||
embedding = response[:response][:embeddings][1]
|
|
||||||
|
|
||||||
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
|
|
||||||
sql =
|
|
||||||
"""
|
|
||||||
SELECT *, embedding <-> '$embedding' as distance
|
|
||||||
FROM sql_statement_repository
|
|
||||||
ORDER BY distance LIMIT 1;
|
|
||||||
"""
|
|
||||||
response = executeSQLVectorDB(sql)
|
|
||||||
df = DataFrame(response)
|
|
||||||
row, col = size(df)
|
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
|
||||||
if row == 0 || distance > 10 # no close enough SQL stored in the database
|
|
||||||
latestKey, _ = GeneralUtils.findHighestIndexKey(state[:thoughtHistory], :action_input)
|
|
||||||
_sqlStatement = state[:thoughtHistory][latestKey]
|
|
||||||
if occursin("SELECT", _sqlStatement) # make sure it is an SQL statement before adding into DB
|
|
||||||
sqlStatementBase64 = base64encode(_sqlStatement)
|
|
||||||
sqlStatement = replace(_sqlStatement, "'"=>"")
|
|
||||||
sql =
|
|
||||||
"""
|
|
||||||
INSERT INTO sql_statement_repository (question, sql_statement, sql_statement_base64, embedding) VALUES ('$query', '$sqlStatement', '$sqlStatementBase64', '$embedding');
|
|
||||||
"""
|
|
||||||
_ = executeSQLVectorDB(sql)
|
|
||||||
println("--> added new SQL statement to vectorDB ", @__FILE__, " ", @__LINE__)
|
|
||||||
println(sqlStatement)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function querySQLVectorDB(state)
|
|
||||||
|
|
||||||
# provide similarSQL at the first time thinking only
|
|
||||||
latestKey, _ = GeneralUtils.findHighestIndexKey(state[:thoughtHistory], :action_input)
|
|
||||||
if latestKey === nothing
|
|
||||||
# get embedding of the query
|
|
||||||
query = [state[:thoughtHistory][:question]]
|
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
|
||||||
config[:externalservice][:text2textinstruct][:mqtttopic];
|
|
||||||
msgPurpose= "embedding",
|
|
||||||
senderName= "yiemagent",
|
|
||||||
senderId= string(uuid4()),
|
|
||||||
receiverName= "text2textinstruct",
|
|
||||||
mqttBrokerAddress= config[:mqttServerInfo][:broker],
|
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
|
||||||
)
|
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
|
||||||
:msgMeta=> msgMeta,
|
|
||||||
:payload=> Dict(
|
|
||||||
:text=> query
|
|
||||||
)
|
|
||||||
)
|
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
|
||||||
embedding = response[:response][:embeddings][1]
|
|
||||||
|
|
||||||
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
|
|
||||||
sql =
|
|
||||||
"""
|
|
||||||
SELECT *, embedding <-> '$embedding' as distance
|
|
||||||
FROM sql_statement_repository
|
|
||||||
ORDER BY distance LIMIT 1;
|
|
||||||
"""
|
|
||||||
response = executeSQLVectorDB(sql)
|
|
||||||
df = DataFrame(response)
|
|
||||||
row, col = size(df)
|
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
|
||||||
if row != 0 && distance < 100
|
|
||||||
# if there is usable SQL, return it.
|
|
||||||
sqlStatementBase64 = df[1, :sql_statement_base64]
|
|
||||||
sqlStatement = String(base64decode(sqlStatementBase64))
|
|
||||||
return sqlStatement
|
|
||||||
else
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# query = Dict(:text=> "How many wines from France do you have that can be paired with lamb?")
|
|
||||||
# query = "How many wines are from United States?"
|
|
||||||
query = "retailer: Yiem, wine_type: red, sweetness: 1-2, intensity: 4-5, wine price: 20-40"
|
|
||||||
# query = "wine_type: white, country: United States, sweetness: 1-2, tannin: 3, food to be served with wine: pizza"
|
|
||||||
# query = "wine_type: white, country: Austria, food to be served with wine: pork"
|
|
||||||
# query = "wine price: less than 25, wine_type: rose, country: France, sweetness: 2, tannin: 3, food to be served with wine: pizza"
|
|
||||||
# query = Dict(:text=> "wine_type: white, country: France, sweetness: 1")
|
|
||||||
result = SQLLLM.query(query, executeSQL, text2textInstructLLM;
|
|
||||||
addSQLVectorDB=addSQLVectorDB,
|
|
||||||
querySQLVectorDB=querySQLVectorDB)
|
|
||||||
|
|
||||||
println(result)
|
|
||||||
error(555)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
CREATE TABLE sql_statement_repository (id bigserial PRIMARY KEY, question text, sql_statement text, sql_statement_base64 text, embedding vector(768));
|
|
||||||
|
|
||||||
SELECT * FROM wine WHERE wine_type = 'red' AND country = 'France' AND sweetness >= 1 AND sweetness <= 2 AND intensity >= 4 AND intensity <= 5 ORDER BY RANDOM() LIMIT 2;
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# sql =
|
|
||||||
# """
|
|
||||||
# SELECT COUNT(*) FROM wine_food JOIN wine ON wine_food.wine_id = wine.wine_id JOIN food ON wine_food.food_id = food.food_id WHERE food.description LIKE '%lamb%';
|
|
||||||
# """
|
|
||||||
# response = SQLLLM.SQLexecution(executeSQL, sql);
|
|
||||||
# result = response[:result]
|
|
||||||
# userintention =
|
|
||||||
# """
|
|
||||||
# Since this is the first round, there's no execution error to analyze. However, we can think about how to improve the query to achieve the desired result.
|
|
||||||
# 1) We need to join the wine_food table with the food table on the food_id column.\n 2) We want to filter the results to include only wines that can be paired with lamb by checking if the food_name or additional_search_term matches 'lamb'.\n 3) We'll use a COUNT(DISTINCT) function to count the number of unique wine_id values that meet the condition.
|
|
||||||
# """
|
|
||||||
# userintention_dict = Dict(:userintention=>userintention)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# sql =
|
|
||||||
# """
|
|
||||||
# SELECT DISTINCT wf.wine_id, COUNT(wf.wine_id) AS wine_count FROM wine_food wf JOIN food f ON wf.food_id = f.food_id WHERE f.description LIKE '%lamb%' GROUP BY wf.wine_id ORDER BY wine_count DESC;
|
|
||||||
# """
|
|
||||||
# response = SQLLLM.SQLexecution(executeSQL, sql);
|
|
||||||
# result = response[:result]
|
|
||||||
# userintention =
|
|
||||||
# """
|
|
||||||
# 1. Use TABLEINFO function to get information about the columns in the wine_food table.\n2. Use GETDATA function to retrieve data from the wine_food table that contains information about wines paired with lamb.\n3. Join the retrieved data with the wine table on the wine_id column to get information about the wines that can be paired with lamb.\n4. Count the number of unique wines associated with lamb through the wine_food junction table. 1. Use TABLEINFO function to get information about the columns in the wine_food table.\n2. Use GETDATA function to retrieve data from the wine_food table that contains information about wines paired with lamb.\n3. Join the retrieved data with the wine table on the wine_id column to get information about the wines that can be paired with lamb.\n4. Count the number of unique wines associated with lamb through the wine_food junction table.
|
|
||||||
# """
|
|
||||||
# userintention_dict = Dict(:userintention=>userintention)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# sql =
|
|
||||||
# """
|
|
||||||
# SELECT COUNT(DISTINCT w.wine_name) FROM (SELECT * FROM wine_food wf JOIN food f ON wf.food_id = f.food_id WHERE f.food_name = 'lamb') AS temp_table JOIN wine w ON temp_table.wine_id = w.wine_id;
|
|
||||||
# """
|
|
||||||
# response = SQLLLM.SQLexecution(executeSQL, sql);
|
|
||||||
# result = response[:result]
|
|
||||||
# userintention =
|
|
||||||
# """
|
|
||||||
# 1. Join the wine_food table with the food table using the food_id column in both tables.\n2. Filter the results to only include rows where the associated food is 'lamb'.\n3. Join the resulting table with the wine table using the wine_id column in both tables.\n4. Count the number of unique wines that can be paired with lamb. 1. Join the wine_food table with the food table using the food_id column in both tables.\n2. Filter the results to only include rows where the associated food is 'lamb'.\n3. Join the resulting table with the wine table using the wine_id column in both tables.\n4. Count the number of unique wines that can be paired with lamb.
|
|
||||||
# """
|
|
||||||
# userintention_dict = Dict(:userintention=>userintention)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# sql =
|
|
||||||
# """
|
|
||||||
# SELECT * FROM wine WHERE country = 'France' AND sweetness = 1 AND wine_type = 'white' LIMIT 2;
|
|
||||||
# """
|
|
||||||
# response = SQLLLM.SQLexecution(executeSQL, sql);
|
|
||||||
# result = response[:result]
|
|
||||||
# userintention =
|
|
||||||
# """
|
|
||||||
# "- Identify the primary key in the wine table.\n- Filter the results to only include wines with type white, from France and level of sweetness 1.\n- Retrieve the information about wines that match the specified criteria. - Identify the primary key in the wine table.\n- Filter the results to only include wines with type white, from France and level of sweetness 1.\n- Retrieve the information about wines that match the specified criteria.
|
|
||||||
# """
|
|
||||||
# userintention_dict = Dict(:userintention=>userintention)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# readout = SQLLLM.extractContent_dataframe(result, userintention_dict, text2textInstructLLM)
|
|
||||||
|
|
||||||
# println("runtest.jl is done")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# sql =
|
|
||||||
# """
|
|
||||||
# SELECT * FROM wine WHERE country = 'France' AND sweetness = 1 AND wine_type = 'white' LIMIT 2;
|
|
||||||
# """
|
|
||||||
# _result = executeSQL(sql)
|
|
||||||
# df2 = DataFrame(_result)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# state = Dict(
|
|
||||||
# :isterminal => true,
|
|
||||||
# :lesson => nothing,
|
|
||||||
# :reward => 1,
|
|
||||||
# :evaluation =>
|
|
||||||
# "The user's question is to search the database for wines that have a type of \"white\", are from \"France\", and have a sweetness level of 1. The thought is correct in identifying the conditions needed to filter the wine table. The action taken is to execute a SQL query to retrieve the desired data, which is also correct. The observation provides a search summary and two search results that match the user's question. Each result includes details about the wine such as ID, name, brand, manufacturer, region, country, type, grape variety, serving temperature, intensity, sweetness, tannin, and acidity.",
|
|
||||||
# :accepted_as_answer => "Yes",
|
|
||||||
# :thoughtHistory =>
|
|
||||||
# OrderedDict{Symbol, Any}(:question => "Search the database for wine_type: white, country: France, sweetness: 1", :thought_1 => "The user wants to search the database for wines that have a type of \"white\", are from \"France\", and have a sweetness level of 1. To achieve this, we need to filter the wine table based on these conditions.", :action_name_1 => "GETDATA", :action_input_1 => "SELECT * FROM wine WHERE wine.wine_type = 'white' AND wine.country = 'France' AND wine.sweetness = 1;", :observation_1 => "\"Search summary: The resulting table represents wines.\\nSearch result: 1) wine_id: 5b6b6df9-d87c-4f33-8995-7249c2ecc917, wine_name: corton-charlemagne grand cru, brand: domaine des croix, manufacturer: domaine des croix, region: bourgogne, country: France, wine_type: white, grape_variety: cote de beaune blanc, serving_temperature: 11 to 13 Celsius, intensity: 4, sweetness: 1, tannin: missing, acidity: 3, fizziness: missing\\n2) wine_id: 1ad27d16-ef64-4907-acf1-40631630c143, wine_name: puligny-montrachet 1er cru 'les demoiselles', brand: amiot guy, manufacturer: amiot guy, region: bourgogne, country: France, wine_type: white, grape_variety: cote de beaune blanc, serving_temperature: 11 to 13 Celsius, intensity: 4, sweetness: 1, tannin: missing, acidity: 3, fizziness: missing\\n\\n\""),
|
|
||||||
# :evaluationscore => 9,
|
|
||||||
# :select => nothing,
|
|
||||||
# :suggestion => "None")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# result = SQLLLM.evaluator(state, text2textInstructLLM)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
println("runtest.jl done")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,24 +1,41 @@
|
|||||||
using Revise
|
using Revise
|
||||||
using LibPQ, JSON3, PrettyPrinting, UUIDs, DataFrames, DataStructures, Base64
|
using LibPQ, Dates, JSON3, PrettyPrinting, UUIDs, DataFrames, DataStructures, Base64
|
||||||
using GeneralUtils, SQLLLM
|
using GeneralUtils, SQLLLM
|
||||||
|
|
||||||
|
|
||||||
config = copy(JSON3.read("config.json"))
|
config = copy(JSON3.read("/appfolder/mountvolume/appdata/config.json"))
|
||||||
|
|
||||||
function executeSQL(sql::T) where {T<:AbstractString}
|
function executeSQL(sql::T) where {T<:AbstractString}
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.12 port=10201 dbname=wineDB user=yiemtechnologies password=yiemtechnologies@Postgres_0.0")
|
host = config[:externalservice][:wineDB][:host]
|
||||||
|
port = config[:externalservice][:wineDB][:port]
|
||||||
|
dbname = config[:externalservice][:wineDB][:dbname]
|
||||||
|
user = config[:externalservice][:wineDB][:user]
|
||||||
|
password = config[:externalservice][:wineDB][:password]
|
||||||
|
DBconnection = LibPQ.Connection("host=$host port=$port dbname=$dbname user=$user password=$password")
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
result = LibPQ.execute(DBconnection, sql)
|
||||||
close(DBconnection)
|
close(DBconnection)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
function text2textInstructLLM(prompt::String)
|
function executeSQLVectorDB(sql)
|
||||||
|
host = config[:externalservice][:SQLVectorDB][:host]
|
||||||
|
port = config[:externalservice][:SQLVectorDB][:port]
|
||||||
|
dbname = config[:externalservice][:SQLVectorDB][:dbname]
|
||||||
|
user = config[:externalservice][:SQLVectorDB][:user]
|
||||||
|
password = config[:externalservice][:SQLVectorDB][:password]
|
||||||
|
DBconnection = LibPQ.Connection("host=$host port=$port dbname=$dbname user=$user password=$password")
|
||||||
|
result = LibPQ.execute(DBconnection, sql)
|
||||||
|
close(DBconnection)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function text2textInstructLLM(prompt::String; maxattempt=3)
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
msgMeta = GeneralUtils.generate_msgMeta(
|
||||||
config[:externalservice][:text2textinstruct][:mqtttopic];
|
config[:externalservice][:loadbalancer][:mqtttopic];
|
||||||
msgPurpose="inference",
|
msgPurpose="inference",
|
||||||
senderName="yiemagent",
|
senderName="yiemagent",
|
||||||
senderId=string(uuid4()),
|
senderId=sessionId,
|
||||||
receiverName="text2textinstruct",
|
receiverName="text2textinstruct_small",
|
||||||
mqttBrokerAddress=config[:mqttServerInfo][:broker],
|
mqttBrokerAddress=config[:mqttServerInfo][:broker],
|
||||||
mqttBrokerPort=config[:mqttServerInfo][:port],
|
mqttBrokerPort=config[:mqttServerInfo][:port],
|
||||||
)
|
)
|
||||||
@@ -28,138 +45,135 @@ function text2textInstructLLM(prompt::String)
|
|||||||
:payload => Dict(
|
:payload => Dict(
|
||||||
:text => prompt,
|
:text => prompt,
|
||||||
:kwargs => Dict(
|
:kwargs => Dict(
|
||||||
:num_ctx => 20480,
|
:num_ctx => 16384,
|
||||||
:temperature => 0.2,
|
:temperature => 0.2,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
response = nothing
|
||||||
response = _response[:response][:text]
|
for attempts in 1:maxattempt
|
||||||
|
_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=300, maxattempt=2)
|
||||||
|
payload = _response[:response]
|
||||||
|
if _response[:success] && payload[:text] !== nothing
|
||||||
|
response = _response[:response][:text]
|
||||||
|
break
|
||||||
|
else
|
||||||
|
println("\n<text2textInstructLLM()> attempt $attempts/$maxattempt failed ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
|
pprintln(outgoingMsg)
|
||||||
|
println("</text2textInstructLLM()> attempt $attempts/$maxattempt failed ", @__FILE__, ":", @__LINE__, " $(Dates.now())\n")
|
||||||
|
sleep(3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return response
|
return response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# get text embedding from a LLM service
|
||||||
function executeSQLVectorDB(sql)
|
function getEmbedding(text::T) where {T<:AbstractString}
|
||||||
DBconnection = LibPQ.Connection("host=192.168.88.12 port=10203 dbname=SQLVectorDB user=yiemtechnologies password=yiemtechnologies@Postgres_0.0")
|
|
||||||
result = LibPQ.execute(DBconnection, sql)
|
|
||||||
close(DBconnection)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
function addSQLVectorDB(state)
|
|
||||||
# get embedding of the query
|
|
||||||
query = [state[:thoughtHistory][:question]]
|
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
msgMeta = GeneralUtils.generate_msgMeta(
|
||||||
config[:externalservice][:text2textinstruct][:mqtttopic];
|
config[:externalservice][:loadbalancer][:mqtttopic];
|
||||||
msgPurpose= "embedding",
|
msgPurpose="embedding",
|
||||||
senderName= "yiemagent",
|
senderName="yiemagent",
|
||||||
senderId= string(uuid4()),
|
senderId=sessionId,
|
||||||
receiverName= "text2textinstruct",
|
receiverName="text2textinstruct_small",
|
||||||
mqttBrokerAddress= config[:mqttServerInfo][:broker],
|
mqttBrokerAddress=config[:mqttServerInfo][:broker],
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
mqttBrokerPort=config[:mqttServerInfo][:port],
|
||||||
)
|
)
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
outgoingMsg = Dict(
|
||||||
:msgMeta=> msgMeta,
|
:msgMeta => msgMeta,
|
||||||
:payload=> Dict(
|
:payload => Dict(
|
||||||
:text=> query
|
:text => [text] # must be a vector of string
|
||||||
)
|
|
||||||
)
|
)
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
)
|
||||||
embedding = response[:response][:embeddings][1]
|
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg; timeout=120)
|
||||||
|
embedding = response[:response][:embeddings]
|
||||||
|
return embedding
|
||||||
|
end
|
||||||
|
|
||||||
|
function findSimilarTextFromVectorDB(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 = getEmbedding(text)[1]
|
||||||
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
|
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
|
||||||
sql =
|
sql = """
|
||||||
"""
|
SELECT *, $embeddingColumnName <-> '$embedding' as distance
|
||||||
SELECT *, embedding <-> '$embedding' as distance
|
FROM $tablename
|
||||||
FROM sql_statement_repository
|
ORDER BY distance LIMIT $limit;
|
||||||
ORDER BY distance LIMIT 1;
|
"""
|
||||||
"""
|
response = vectorDB(sql)
|
||||||
response = executeSQLVectorDB(sql)
|
|
||||||
df = DataFrame(response)
|
df = DataFrame(response)
|
||||||
|
return df
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function similarSQLVectorDB(query; maxdistance::Integer=100)
|
||||||
|
tablename = "sqlllm_decision_repository"
|
||||||
|
# get embedding of the query
|
||||||
|
df = findSimilarTextFromVectorDB(query, tablename,
|
||||||
|
"function_input_embedding", executeSQLVectorDB)
|
||||||
|
# println(df[1, [:id, :function_output]])
|
||||||
row, col = size(df)
|
row, col = size(df)
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
distance = row == 0 ? Inf : df[1, :distance]
|
||||||
if row == 0 || distance > 10 # no close enough SQL stored in the database
|
# distance = 100 # CHANGE this is for testing only
|
||||||
latestKey, _ = GeneralUtils.findHighestIndexKey(state[:thoughtHistory], :action_input)
|
if row != 0 && distance < maxdistance
|
||||||
_sqlStatement = state[:thoughtHistory][latestKey]
|
# if there is usable SQL, return it.
|
||||||
if occursin("SELECT", _sqlStatement) # make sure it is an SQL statement before adding into DB
|
output_b64 = df[1, :function_output_base64] # pick the closest match
|
||||||
sqlStatementBase64 = base64encode(_sqlStatement)
|
output_str = String(base64decode(output_b64))
|
||||||
sqlStatement = replace(_sqlStatement, "'"=>"")
|
rowid = df[1, :id]
|
||||||
sql =
|
println("\n~~~ found similar sql. row id $rowid, distance $distance ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
"""
|
return (dict=output_str, distance=distance)
|
||||||
INSERT INTO sql_statement_repository (question, sql_statement, sql_statement_base64, embedding) VALUES ('$query', '$sqlStatement', '$sqlStatementBase64', '$embedding');
|
else
|
||||||
"""
|
println("\n~~~ similar sql not found, max distance $maxdistance ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
_ = executeSQLVectorDB(sql)
|
return (dict=nothing, distance=nothing)
|
||||||
println("--> added new SQL statement to vectorDB ", @__FILE__, " ", @__LINE__)
|
|
||||||
println(sqlStatement)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function querySQLVectorDB(state)
|
|
||||||
|
|
||||||
# provide similarSQL at the first time thinking only
|
function insertSQLVectorDB(query::T1, SQL::T2; maxdistance::Integer=3) where {T1<:AbstractString, T2<:AbstractString}
|
||||||
latestKey, _ = GeneralUtils.findHighestIndexKey(state[:thoughtHistory], :action_input)
|
tablename = "sqlllm_decision_repository"
|
||||||
if latestKey === nothing
|
# get embedding of the query
|
||||||
# get embedding of the query
|
# query = state[:thoughtHistory][:question]
|
||||||
query = [state[:thoughtHistory][:question]]
|
df = findSimilarTextFromVectorDB(query, tablename,
|
||||||
msgMeta = GeneralUtils.generate_msgMeta(
|
"function_input_embedding", executeSQLVectorDB)
|
||||||
config[:externalservice][:text2textinstruct][:mqtttopic];
|
row, col = size(df)
|
||||||
msgPurpose= "embedding",
|
distance = row == 0 ? Inf : df[1, :distance]
|
||||||
senderName= "yiemagent",
|
if row == 0 || distance > maxdistance # no close enough SQL stored in the database
|
||||||
senderId= string(uuid4()),
|
query_embedding = getEmbedding(query)[1]
|
||||||
receiverName= "text2textinstruct",
|
query = replace(query, "'" => "")
|
||||||
mqttBrokerAddress= config[:mqttServerInfo][:broker],
|
sql_base64 = base64encode(SQL)
|
||||||
mqttBrokerPort= config[:mqttServerInfo][:port],
|
sql_ = replace(SQL, "'" => "")
|
||||||
)
|
|
||||||
|
|
||||||
outgoingMsg = Dict(
|
sql = """
|
||||||
:msgMeta=> msgMeta,
|
INSERT INTO $tablename (function_input, function_output, function_output_base64, function_input_embedding) VALUES ('$query', '$sql_', '$sql_base64', '$query_embedding');
|
||||||
:payload=> Dict(
|
"""
|
||||||
:text=> query
|
# println("\n~~~ added new decision to vectorDB ", @__FILE__, ":", @__LINE__, " $(Dates.now())")
|
||||||
)
|
# println(sql)
|
||||||
)
|
_ = executeSQLVectorDB(sql)
|
||||||
response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
|
|
||||||
embedding = response[:response][:embeddings][1]
|
|
||||||
|
|
||||||
# check whether there is close enough vector already store in vectorDB. if no, add, else skip
|
|
||||||
sql =
|
|
||||||
"""
|
|
||||||
SELECT *, embedding <-> '$embedding' as distance
|
|
||||||
FROM sql_statement_repository
|
|
||||||
ORDER BY distance LIMIT 1;
|
|
||||||
"""
|
|
||||||
response = executeSQLVectorDB(sql)
|
|
||||||
df = DataFrame(response)
|
|
||||||
row, col = size(df)
|
|
||||||
distance = row == 0 ? Inf : df[1, :distance]
|
|
||||||
if row != 0 && distance < 100
|
|
||||||
# if there is usable SQL, return it.
|
|
||||||
sqlStatementBase64 = df[1, :sql_statement_base64]
|
|
||||||
sqlStatement = String(base64decode(sqlStatementBase64))
|
|
||||||
return sqlStatement
|
|
||||||
else
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return nothing
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sessionId = "555"
|
||||||
|
|
||||||
|
|
||||||
|
# query = "How many German wines do you have?"
|
||||||
|
# highValueStateList = copy(JSON3.read("/appfolder/app/highValueState_1.json"))
|
||||||
|
# selectedState = SQLLLM.compareState(query, highValueStateList, text2textInstructLLM)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# query = Dict(:text=> "How many wines from France do you have that can be paired with lamb?")
|
# query = Dict(:text=> "How many wines from France do you have that can be paired with lamb?")
|
||||||
# query = "How many wines are from United States?"
|
query = "How many French wines from Yiem store under 100 dollars do you have?"
|
||||||
query = "retailer: Yiem, wine_type: red, sweetness: 1-2, intensity: 4-5, wine price: 20-40"
|
# query = "retailer: Yiem, wine_type: red, sweetness: 1-2, intensity: 4-5, wine price: 20-40"
|
||||||
# query = "wine_type: white, country: United States, sweetness: 1-2, tannin: 3, food to be served with wine: pizza"
|
# query = "wine_type: white, country: United States, sweetness: 1-2, tannin: 3, food to be served with wine: pizza"
|
||||||
# query = "wine_type: white, country: Austria, food to be served with wine: pork"
|
# query = "wine_type: white, country: Austria, food to be served with wine: pork"
|
||||||
# query = "wine price: less than 25, wine_type: rose, country: France, sweetness: 2, tannin: 3, food to be served with wine: pizza"
|
# query = "wine price: less than 25, wine_type: rose, country: France, sweetness: 2, tannin: 3, food to be served with wine: pizza"
|
||||||
# query = Dict(:text=> "wine_type: white, country: France, sweetness: 1")
|
# query = Dict(:text=> "wine_type: white, country: France, sweetness: 1")
|
||||||
result = SQLLLM.query(query, executeSQL, text2textInstructLLM;
|
result = SQLLLM.query(query, executeSQL, text2textInstructLLM;
|
||||||
addSQLVectorDB=addSQLVectorDB,
|
insertSQLVectorDB=insertSQLVectorDB,
|
||||||
querySQLVectorDB=querySQLVectorDB)
|
similarSQLVectorDB=similarSQLVectorDB)
|
||||||
|
|
||||||
println(result)
|
println(result)
|
||||||
error(555)
|
error(555)
|
||||||
@@ -1,16 +1,70 @@
|
|||||||
using Revise
|
# using Revise
|
||||||
|
# using SQLLLM, LLMMCTS, DataStructures, JSON3
|
||||||
|
|
||||||
|
# query = "How many German wines do you have?"
|
||||||
|
# highValueStateList = copy(JSON3.read("/appfolder/app/highValueState_1.json"))
|
||||||
|
# selectedState = SQLLLM.compareState(query, highValueStateList)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function testf(a)::NamedTuple{(:a, :b), Tuple{Union{Nothing, Int}, Int}}
|
|
||||||
if a == 1
|
|
||||||
return (a=nothing, b=5)
|
|
||||||
else
|
|
||||||
return (a=5, b=5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
q = testf(1)
|
|
||||||
w = testf(2)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
table_name,comment
|
|
||||||
customer,"The customer table stores information about customers. It includes details such as first name, last name, display name, username, password, gender, country, telephone number, email, birthdate, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
wine,"The wine table stores information about different wines. It includes details namely id, name, brand, manufacturer, region, country, wine_type, grape_variety, serving_temperature, intensity, sweetness, tannin, acidity, fizziness, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
wine_food,"The wine_food table represents the association between wines and food items. It establishes a many-to-many relationship, allowing us to link specific wines with various food items."
|
|
||||||
food,"The food table represents various food items. It stores information related to food names, country of origin, taste attributes (spiciness, sweetness, sourness, savoriness, and bitterness), serving temperature, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
retailer,"The retailer table stores information about different retailers. It includes details related to retailer names, usernames, passwords, addresses, contact persons, telephone numbers, email addresses, additional_search_term, other attributes (in JSON format) and a description."
|
|
||||||
retailer_wine,"The retailer_wine table represents the relationship between retailers and wines. It stores information about the wines available from which retailers, including vintage, their price, and the currency."
|
|
||||||
retailer_food,"The retailer_food table represents the relationship between retailers and food items. It stores information about the food items available from which retailers, including their price and the currency."
|
|
||||||
|
Reference in New Issue
Block a user