diff --git a/src/interface.jl b/src/interface.jl index debdae0..84d99de 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -23,22 +23,22 @@ using ..util, ..llmfunction A function that handles communication to LLM service # Return - - `thoughtDict::Dict{Symbol, Any}` + - `thoughtDict::Dict{String, Any}` # Example ```jldoctest julia> using SQLLLM, GeneralUtils, UUIDs, DataStructures, PrettyPrinting julia> state = Dict( - :isterminal => false, - :lesson => nothing, - :reward => 0, - :evaluation => "None", - :accepted_as_answer => "No", - :thoughtHistory => OrderedDict{Symbol, Any}(:question => "How many wines do you have that can be paired with lamb?"), - :evaluationscore => 0, - :suggestion => "None" + "isterminal" => false, + "lesson" => nothing, + "reward" => 0, + "evaluation" => "None", + "accepted_as_answer" => "No", + "thoughtHistory" => OrderedDict{String, Any}("question" => "How many wines do you have that can be paired with lamb?"), + "evaluationscore" => 0, + "suggestion" => "None" ) -julia> context = Dict(:tablelist=> "None") +julia> context = Dict("tablelist"=> "None") julia> function text2textInstructLLM(prompt::String) config = Dict( :mqttServerInfo => Dict( @@ -104,7 +104,7 @@ Dict( """ function decisionMaker(state::T1, additionalinfo, text2textInstructLLM::Function, llmFormatName::String ; querySQLVectorDBF::Union{T2, Nothing}=nothing, maxattempt=10 - )::Dict{Symbol, Any} where {T1<:AbstractDict, T2<:Function} + )::Dict{String, Any} where {T1<:AbstractDict, T2<:Function} # lessonDict = # if isfile("lesson.json") @@ -174,8 +174,8 @@ function decisionMaker(state::T1, additionalinfo, text2textInstructLLM::Function """ requiredKeys = [:plan, :action_name, :action_input] workprogress = "" - for (k, v) in state[:thoughtHistory] - if k ∉ [:question] + for (k, v) in state["thoughtHistory"] + if k ∉ ["question"] workprogress *= "$k: $v\n" end end @@ -184,11 +184,11 @@ function decisionMaker(state::T1, additionalinfo, text2textInstructLLM::Function errornote = "N/A" # provide similar sql only for the first attempt - similarSQL_ = "None" - if length(state[:thoughtHistory]) == 1 - sql, distance = querySQLVectorDBF(state[:thoughtHistory][:question]) - similarSQL_ = sql !== nothing ? sql : "None" - end +similarSQL_ = "None" + if length(state["thoughtHistory"]) == 1 + sql, distance = querySQLVectorDBF(state["thoughtHistory"]["question"]) + similarSQL_ = sql !== nothing ? sql : "None" + end for attempt in 1:maxattempt @@ -211,7 +211,7 @@ function decisionMaker(state::T1, additionalinfo, text2textInstructLLM::Function $workprogress This is your mentor's suggestion for the immediately preceding action and observation - $(state[:suggestion]) +$(state["suggestion"]) P.S. $errornote @@ -220,7 +220,7 @@ function decisionMaker(state::T1, additionalinfo, text2textInstructLLM::Function unformatPrompt = [ Dict(:name => "system", :text => systemmsg), - Dict(:name => "user", :text => state[:thoughtHistory][:question]) + Dict("name" => "user", "text" => state["thoughtHistory"]["question"]) ] # put in model format @@ -262,31 +262,31 @@ function decisionMaker(state::T1, additionalinfo, text2textInstructLLM::Function continue end - delete!(responsedict, :observation) + delete!(responsedict, "observation") # remove backticks Error occurred: MethodError: no method matching occursin(::String, ::Vector{String}) - if occursin("```", responsedict[:action_input]) - sql = GeneralUtils.extract_triple_backtick_text(responsedict[:action_input])[1] + if occursin("```", responsedict["action_input"]) + sql = GeneralUtils.extract_triple_backtick_text(responsedict["action_input"])[1] if sql[1:4] == "sql\n" sql = sql[5:end] end sql = split(sql, ';') # some time there are comments in the sql sql = sql[1] * ';' - responsedict[:action_input] = sql + responsedict["action_input"] = sql end toollist = ["TABLEINFO", "RUNSQL"] - if responsedict[:action_name] ∉ toollist + if responsedict["action_name"] ∉ toollist errornote = "Your previous attempt has action_name that is not in the tool list" - println("\nERROR SQLLLM decisionMaker(). Attempt $attempt/$maxattempt. $errornote --(not qualify response)--> $(responsedict[:action_name]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + println("\nERROR SQLLLM decisionMaker(). Attempt $attempt/$maxattempt. $errornote --(not qualify response)--> $(responsedict["action_name"]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue end for i in toollist - if occursin(i, responsedict[:action_input]) + if occursin(i, responsedict["action_input"]) errornote = "Your previous attempt has action_name in action_input which is not allowed" - println("\nERROR SQLLLM decisionMaker(). Attempt $attempt/$maxattempt. $errornote --(not qualify response)--> $(responsedict[:action_input]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + println("\nERROR SQLLLM decisionMaker(). Attempt $attempt/$maxattempt. $errornote --(not qualify response)--> $(responsedict["action_input"]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") continue end end @@ -303,11 +303,11 @@ function decisionMaker(state::T1, additionalinfo, text2textInstructLLM::Function pprintln(Dict(responsedict)) # store for later training - responsedict[:thoughthistory] = state[:thoughtHistory] - responsedict[:system] = systemmsg - responsedict[:prompt] = prompt - responsedict[:context] = context - responsedict[:think] = think +responsedict["thoughthistory"] = state["thoughtHistory"] + responsedict["system"] = systemmsg + responsedict["prompt"] = prompt + responsedict["context"] = context + responsedict["think"] = think # # read sessionId # sessionid = JSON3.read("/appfolder/app/sessionid.json") @@ -339,7 +339,7 @@ end # function decisionMaker(state::T1, context, text2textInstructLLM::Function, llmFormatName::String # ; querySQLVectorDBF::Union{T2, Nothing}=nothing, maxattempt=10 -# )::Dict{Symbol, Any} where {T1<:AbstractDict, T2<:Function} +# )::Dict{String, Any} where {T1<:AbstractDict, T2<:Function} # # lessonDict = # # if isfile("lesson.json") @@ -523,7 +523,7 @@ end # end # responsedict = GeneralUtils.textToDict(response, header; -# dictKey=dictkey, symbolkey=true) +# dictKey=dictkey, symbolkey=false) # delete!(responsedict, :observation) @@ -653,7 +653,7 @@ function evaluator(state::T1, thoughtDict, text2textInstructLLM::Function, llmFo dictkey = ["trajectory_evaluation", "answer_evaluation", "accepted_as_answer", "score", "suggestion"] thoughthistory = "" - for (k, v) in state[:thoughtHistory] + for (k, v) in state["thoughtHistory"] thoughthistory *= "$k: $v\n" end @@ -707,39 +707,39 @@ function evaluator(state::T1, thoughtDict, text2textInstructLLM::Function, llmFo end responsedict = GeneralUtils.textToDict(response, header; - dictKey=dictkey, symbolkey=true) + dictKey=dictkey, symbolkey=false) - responsedict[:score] = responsedict[:score][1] # some time "6\nThe trajectories are incomplete" is generated but I only need the number. + 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 + 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] + accepted_as_answer::AbstractString = responsedict["accepted_as_answer"] if accepted_as_answer ∉ ["yes", "no"] errornote = "Your previous attempt's accepted_as_answer has wrong format" - println("\nERROR SQLLLM evaluator() Attempt $attempt/$maxattempt. $errornote --(not qualify response)--> $(responsedict[:accepted_as_answer]) ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + println("\nERROR SQLLLM evaluator() Attempt $attempt/$maxattempt. $errornote --(not qualify response)--> $(responsedict["accepted_as_answer"]) ", @__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] + 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", "yes"] # mark the state as terminal state because the evaluation say so. - state[:isterminal] = true + state["isterminal"] = true # evaluation score as reward because different answers hold different value for the user. - state[:reward] = responsedict[:score] + state["reward"] = responsedict["score"] end println("\nSQLLLM evaluator() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") @@ -776,7 +776,7 @@ function evaluator(state::T1, thoughtDict, text2textInstructLLM::Function, llmFo # end # end - return responsedict[:score] + return responsedict["score"] end error("Evaluator failed to generate an evaluation, Response: \n$response\n<|End of error|>") end @@ -952,14 +952,14 @@ end ```jldoctest julia> using SQLLLM, DataStructures julia> state = Dict( - :isterminal => false, - :lesson => nothing, - :reward => 0, - :evaluation => "None", - :accepted_as_answer => "No", - :thoughtHistory => OrderedDict{Symbol, Any}(:question => "How many wines do you have that can be paired with lamb?"), - :evaluationscore => 0, - :suggestion => "None" + "isterminal" => false, + "lesson" => nothing, + "reward" => 0, + "evaluation" => "None", + "accepted_as_answer" => "No", + "thoughtHistory" => OrderedDict{String, Any}("question" => "How many wines do you have that can be paired with lamb?"), + "evaluationscore" => 0, + "suggestion" => "None" ) ``` @@ -987,18 +987,18 @@ function transition(state::T, args::NamedTuple # map action and input() to llm function response = - if thoughtDict[:action_name] == "listalltables" - # deepcopy(state[:virtualCustomerChatHistory]) because I want to keep it clean + if thoughtDict["action_name"] == "listalltables" + # deepcopy(state["virtualCustomerChatHistory"]) because I want to keep it clean # so that other simulation start from this same node is not contaminated with actioninput listAllTable_json(executeSQL) - elseif thoughtDict[:action_name] == "TABLEINFO" - input = thoughtDict[:action_input] + elseif thoughtDict["action_name"] == "TABLEINFO" + input = thoughtDict["action_input"] tableinfo(executeSQL, input) elseif thoughtDict[:action_name] == "RUNSQL" - response = SQLexecution(executeSQL, thoughtDict[:action_input]) - if response[:success] - extracted = extractContent_dataframe(response[:result], text2textInstructLLM, - thoughtDict[:action_input], llmFormatName) + response = SQLexecution(executeSQL, thoughtDict["action_input"]) + if response["success"] + extracted = extractContent_dataframe(response["result"], text2textInstructLLM, + thoughtDict["action_input"], llmFormatName) (rawresponse=response[:result], result=extracted, errormsg=nothing, success=true) else (result=nothing, errormsg=response[:errormsg], success=false) @@ -1007,12 +1007,12 @@ function transition(state::T, args::NamedTuple error("undefined LLM function. Requesting $(thoughtDict[:action_name])") end # this section allow LLM functions above to have different return values. - success::Bool = haskey(response, :success) ? response[:success] : false - result = success ? response[:result] : response[:errormsg] - rawresponse = haskey(response, :rawresponse) ? response[:rawresponse] : nothing - select = haskey(response, :select) ? response[:select] : nothing - reward::Integer = haskey(response, :reward) ? response[:reward] : 0 - isterminal::Bool = haskey(response, :isterminal) ? response[:isterminal] : false + success::Bool = haskey(response, "success") ? response["success"] : false + result = success ? response["result"] : response["errormsg"] + rawresponse = haskey(response, "rawresponse") ? response["rawresponse"] : nothing + select = haskey(response, "select") ? response["select"] : nothing + reward::Integer = haskey(response, "reward") ? response["reward"] : 0 + isterminal::Bool = haskey(response, "isterminal") ? response["isterminal"] : false newNodeKey, newstate = makeNewState(state, thoughtDict, rawresponse, JSON3.write(result), select, reward, isterminal) progressvalue::Integer = evaluatorF(newstate, thoughtDict, text2textInstructLLM, llmFormatName) @@ -1124,19 +1124,19 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function; # do MCTS if no data in the database # add extra context for Evaluator so that it knows the observation is from seaching a database - initialstate = Dict{Symbol, Any}( - :reward=> 0, - :isterminal=> false, - :evaluation=> "None", - :evaluationscore=> 0, - :suggestion=> "None", - :accepted_as_answer=> "No", - :lesson=> nothing, + initialstate = Dict{String, Any}( + "reward"=> 0, + "isterminal"=> false, + "evaluation"=> "None", + "evaluationscore"=> 0, + "suggestion"=> "None", + "accepted_as_answer"=> "No", + "lesson"=> nothing, # contain question, thought_1, action_1, observation_1, thought_2, ... - :thoughtHistory=> OrderedDict{Symbol, Any}( + "thoughtHistory"=> OrderedDict{String, Any}( #[] :recap=>, - :question=> query, + "question"=> query, ), ) # context = Dict( @@ -1272,7 +1272,7 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function; llmFormatName=llmFormatName ) - earlystop(state) = state[:reward] >= 8 ? true : false + earlystop(state) = state["reward"] >= 8 ? true : false root, _, resultState, highValueState = LLMMCTS.runMCTS(initialstate, transition, transitionargs; @@ -1294,22 +1294,22 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function; resultState = highValueState[selected] end latestKey, latestInd = GeneralUtils.findHighestIndexKey(resultState[:thoughtHistory], "observation") - action_input = Symbol("action_input_$latestInd") # latest sql - sql = resultState[:thoughtHistory][action_input] - extractedTableContent = resultState[:thoughtHistory][latestKey] +action_input = "action_input_$latestInd" # latest sql + sql = resultState["thoughtHistory"][action_input] + extractedTableContent = resultState["thoughtHistory"][latestKey] # add to vectorDB only if the answer is achieved and the state is terminal - if insertSQLVectorDB !== nothing && resultState[:isterminal] == true && - resultState[:rawresponse] !== nothing + if insertSQLVectorDB !== nothing && resultState["isterminal"] == true && + resultState["rawresponse"] !== nothing - insertSQLVectorDB(resultState[:thoughtHistory][:question], sql) + insertSQLVectorDB(resultState["thoughtHistory"]["question"], sql) end if extractedTableContent === nothing println("\nSQLLLM query() return nothing ", @__FILE__, ":", @__LINE__, " $(Dates.now())") end - result = (text=extractedTableContent, rawresponse=resultState[:rawresponse]) + result = (text=extractedTableContent, rawresponse=resultState["rawresponse"]) return result end @@ -1330,32 +1330,32 @@ julia> """ function makeNewState(currentstate::T1, thoughtDict::T4, rawresponse, response::T2, select::Union{T3, Nothing}, 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{String, <:Any}}} where {T1<:AbstractDict, T2<:AbstractString, T3<:Number, T4<:AbstractDict} keys = [:plan, :action_name, :action_input, :observation] # latestKeys = [] currentstate_latestKey, currentstate_latestIndice = - GeneralUtils.findHighestIndexKey(currentstate[:thoughtHistory], keys[1]) + GeneralUtils.findHighestIndexKey(currentstate["thoughtHistory"], keys[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 = makekey.(keys, nextindice) # add Thought, action, observation to thoughtHistory newstate = deepcopy(currentstate) for (x, y) in zip(keys, currentstate_latestKey) - if x != :observation - newstate[:thoughtHistory][y] = thoughtDict[Symbol(x)] + if x != "observation" + newstate["thoughtHistory"][y] = thoughtDict[x] else - newstate[:thoughtHistory][y] = response + newstate["thoughtHistory"][y] = response end end - newstate[:reward] = reward - newstate[:select] = select - newstate[:isterminal] = isterminal - newstate[:rawresponse] = rawresponse # whatever return from action +newstate["reward"] = reward + newstate["select"] = select + newstate["isterminal"] = isterminal + newstate["rawresponse"] = rawresponse # whatever return from action newNodeKey = GeneralUtils.uuid4snakecase() @@ -1429,8 +1429,8 @@ function generatequestion(state::T1, context, text2textInstructLLM::Function, dictkey = ["q1"] workprogress = "" - for (k, v) in state[:thoughtHistory] - if k ∉ [:query] + for (k, v) in state["thoughtHistory"] + if k ∉ ["query"] workprogress *= "$k: $v\n" end end @@ -1441,8 +1441,8 @@ function generatequestion(state::T1, context, text2textInstructLLM::Function, for attempt in 1:maxattempt usermsg = """ - $(context[:tablelist]) - User query: $(state[:thoughtHistory][:question]) + $(context["tablelist"]) + User query: $(state["thoughtHistory"]["question"]) Example: $similarSQL Your work progress: $workprogress P.S. $errornote @@ -1474,8 +1474,8 @@ function generatequestion(state::T1, context, text2textInstructLLM::Function, end responsedict = GeneralUtils.textToDict(response, header; - dictKey=dictkey, symbolkey=true) - response = "Q1: " * responsedict[:q1] + dictKey=dictkey, symbolkey=false) + response = "Q1: " * responsedict["q1"] println("\nSQLLLM generatequestion() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") pprintln(Dict(responsedict)) return response diff --git a/src/llmfunction.jl b/src/llmfunction.jl index 641c317..0509b3e 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -287,17 +287,17 @@ function getdata_transition(state::T, args::NamedTuple # decisionMaker::Function = args[:decisionMaker] # evaluator::Function = args[:evaluator] # reflector::Function = args[:reflector] - context = args[:context] - executeSQL::Function = args[:executeSQL] - text2textInstructLLM::Function = args[:text2textInstructLLM] +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 + 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() @@ -314,15 +314,15 @@ function getdata_transition(state::T, args::NamedTuple 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 +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 + newstate["response"] = extracted end println("getdata_transition() 2 ", @__FILE__, " ", @__LINE__) stateevaluation = "None" @@ -389,10 +389,10 @@ function getdata_decisionMaker(state::Dict, context::Dict, text2textInstructLLM: 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]) + $(context["mentionedTableInfo"]) + User intention: $(context["userintention"]) + Code executed from the last round: $(state["code"]) + Execution error: $(state["errormsg"]) $noise $note_flag """ @@ -414,13 +414,13 @@ function getdata_decisionMaker(state::Dict, context::Dict, text2textInstructLLM: dictkey = ["plan", "code"] responsedict = GeneralUtils.textToDict(response, header; - dictKey=dictkey, symbolkey=true) - _code = responsedict[:code] + dictKey=dictkey, symbolkey=false) + _code = responsedict["code"] code = strip(_code) if length(code) < 2 error("No code available.") - elseif code == state[:code] + elseif code == state["code"] error("generated code is the same as earlier.") else end @@ -440,7 +440,7 @@ function getdata_decisionMaker(state::Dict, context::Dict, text2textInstructLLM: println("\n~~~ getdata_decisionMaker() ", @__FILE__, " ", @__LINE__) pprintln(Dict(responsedict)) - return (thought=responsedict[:comprehension], code=code, success=true, errormsg=nothing) + return (thought=responsedict["comprehension"], code=code, success=true, errormsg=nothing) catch e io = IOBuffer() showerror(io, e) @@ -651,12 +651,12 @@ function extractContent_dataframe(df::DataFrame, text2textInstructLLM::Function, end responsedict = GeneralUtils.textToDict(response, header; - dictKey=dictkey, symbolkey=true) + dictKey=dictkey, symbolkey=false) # result = dfstr result = """ - Summary: $(responsedict[:search_summary]) + Summary: $(responsedict["search_summary"]) More details: $dfstr """ @@ -778,8 +778,8 @@ function getTableNameFromSQL(sql::T, text2textInstructLLM::Function, response = text2textInstructLLM(prompt, modelsize="medium") response = GeneralUtils.deFormatLLMtext(response, llmFormatName) responsedict = GeneralUtils.textToDict(response, header; - dictKey=dictkey, symbolkey=true) - response = copy(JSON3.read(responsedict[:table_name])) + dictKey=dictkey, symbolkey=false) + response = copy(JSON3.read(responsedict["table_name"])) return response catch e @@ -862,21 +862,21 @@ function compareState(question::String, highValueStateList::Vector{T}, 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 +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 @@ -944,11 +944,11 @@ function compareState(question::String, highValueStateList::Vector{T}, continue end - responsedict = GeneralUtils.textToDict(response, header; dictKey=dictkey, symbolkey=true) + responsedict = GeneralUtils.textToDict(response, header; dictKey=dictkey, symbolkey=false) - 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 +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())") @@ -958,7 +958,7 @@ function compareState(question::String, highValueStateList::Vector{T}, println("\n~~~ compareState() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") pprintln(Dict(responsedict)) - return responsedict[:selected_response_number] + 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 diff --git a/src/util.jl b/src/util.jl index 3839f15..e8640f6 100644 --- a/src/util.jl +++ b/src/util.jl @@ -2,7 +2,7 @@ module util export makekey -makekey(key, indice) = Symbol("$(key)_$indice") +makekey(key, indice) = "$(key)_$indice" diff --git a/test/runtests.jl b/test/runtests.jl index 7d8849b..24d9fbb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -353,7 +353,7 @@ SELECT * FROM wine WHERE wine_type = 'red' AND country = 'France' AND sweetness # "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\""), +# OrderedDict{String, 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")