diff --git a/src/interface.jl b/src/interface.jl index 0803f2f..3fa4973 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -371,10 +371,10 @@ function evaluator(state::T1, text2textInstructLLM::Function, llmFormatName::Str state["reward"] = responsedict["score"] end - println("\n--- SQLLLM evaluator() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - pprintln(responsedict) - println("---\n") - + # println("\n--- SQLLLM evaluator() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + # pprintln(responsedict) + # println("---\n") + # error(7777) return responsedict["score"] end error("Evaluator failed to generate an evaluation, Response: \n$response\n<|End of error|>") @@ -596,16 +596,16 @@ function transition(state::T, args::NamedTuple end newNodeKey, newstate = makeNewState(state, thoughtDict, response) - progressvalue::Integer = - if response[:success] - 8 # for faster agent response. if success just skip evaluation - else - evaluatorF(newstate, text2textInstructLLM, llmFormatName) - end + progressvalue::Integer = evaluatorF(newstate, text2textInstructLLM, llmFormatName) + # if response[:success] + # 8 # for faster agent response. if success just skip evaluation + # else + # evaluatorF(newstate, text2textInstructLLM, llmFormatName) + # end - println("\n--- SQLLLM transition() thoughtDict ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - pprintln(thoughtDict) - println("---") + # println("\n--- SQLLLM transition() thoughtDict ", @__FILE__, ":", @__LINE__, " $(Dates.now())") + # pprintln(thoughtDict) + # println("---") # error("SQLLLM transition() end") return (newNodeKey=newNodeKey, newstate=newstate, progressvalue=progressvalue) end @@ -727,42 +727,41 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function; systemmsg = """ - - - 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. - Do not wrap the SQL as it will be executed against the database directly and SQL must be ended with ';'. - - - At each round of conversation, you will be given the following: - - user question - You are working under your mentor supervision and you are also eager to improve your helpfulness. - - - Consult the database search guidelines. Then find the data from a database to satisfy the user's question. - - - Fulfill the objective. - - + # database search guidelines - Keep SQL queries focused only on the provided information. - Do not create any table in the database - A junction table can be used to link tables together. Another use case is for filtering data. - If you can't find a single table that can be used to answer the user's query, try joining multiple tables to see if you can obtain the answer. - Text information in the database usually stored in lower case. If your search returns empty, try using lower case to search. - If there is no search result from the database, remove the restrictive criteria until a search result is available, and proceed from there. - - - 1) plan: Based on the current situation, state a complete action plan to complete the task. Be specific. - 2) action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the available_actions name - 3) action_input: The input to the action you are about to perform according to your plan. + + # situation + At each round of conversation, you will be given the following: + - user question + You are working under your mentor supervision and you are also eager to improve your helpfulness. + + # objective + Consult the database search guidelines. Then find the data from a database to satisfy the user's question. + + # your responsibility includes + Fulfill the objective. + + # you should then respond to the user with interleaving plan, action_name, action_input + 1) **plan**, Based on the current situation, state a complete action plan to complete the task and rationale. Be specific. + 2) **action_name**, (Typically corresponds to the execution of the first step in your plan) Can be one of the available_actions name + 3) **action_input**, The input to the action you are about to perform according to your plan. After the action is executed you gets "action_result". It is the output from the action you selected. - - + + # you should only respond in JSON format as described below "plan": "...", "action_name": "...", "action_input": "..." - + + # available_actions + **RUNSQL**, which you can use to execute SQL against the database. + The input 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. + Do not wrap the SQL as it will be executed against the database directly and SQL must be ended with ';'. """ @@ -975,11 +974,297 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function; end println("\n--- SQLLLM query() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") - println(resultState["result_raw"]) + # pprintln(resultState) println("---\n") return (result_str=latest_action["action_result"], result_raw=resultState["result_raw"]) end +# function query(query::T, executeSQL::Function, text2textInstructLLM::Function; +# insertSQLVectorDB::Union{Function, Nothing}=nothing, +# similarSQLVectorDB::Union{Function, Nothing}=nothing, +# llmFormatName="qwen3" +# ) where {T<:AbstractString} + +# # use similarSQLVectorDB to find similar SQL for the query +# sql, distance = similarSQLVectorDB(query) + +# # if sql is really match, immediately check database then return +# if sql !== nothing && distance <= 1 +# # query vector db to get wine +# response = SQLexecution(executeSQL, sql) +# if response[:success] +# return (result_str=response[:result_str], result_raw=response[:result_raw]) +# else +# error(response[:errormsg]) +# end +# end + +# """ +# chathistory= [ +# Dict( +# "role" => "system", +# "content" => [ +# Dict("type" => "text", "text" => "You are a helpful assistant"), +# ] +# ), +# ] +# """ + +# systemmsg = +# """ +# +# - 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. +# Do not wrap the SQL as it will be executed against the database directly and SQL must be ended with ';'. +# +# +# At each round of conversation, you will be given the following: +# - user question +# You are working under your mentor supervision and you are also eager to improve your helpfulness. +# +# +# Consult the database search guidelines. Then find the data from a database to satisfy the user's question. +# +# +# Fulfill the objective. +# +# +# - Keep SQL queries focused only on the provided information. +# - Do not create any table in the database +# - A junction table can be used to link tables together. Another use case is for filtering data. +# - If you can't find a single table that can be used to answer the user's query, try joining multiple tables to see if you can obtain the answer. +# - Text information in the database usually stored in lower case. If your search returns empty, try using lower case to search. +# - If there is no search result from the database, remove the restrictive criteria until a search result is available, and proceed from there. +# +# +# 1) plan: Based on the current situation, state a complete action plan to complete the task. Be specific. +# 2) action_name: (Typically corresponds to the execution of the first step in your plan) Can be one of the available_actions name +# 3) action_input: The input to the action you are about to perform according to your plan. +# After the action is executed you gets "action_result". It is the output from the action you selected. +# +# +# "plan": "...", +# "action_name": "...", +# "action_input": "..." +# +# """ + + + +# # 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{String, Any}( +# "reward"=> 0, +# "isterminal"=> false, +# "evaluation"=> "None", +# "evaluationscore"=> 0, +# "suggestion"=> "None", +# "accepted_as_answer"=> "No", +# "chathistory"=> Vector{Dict{String, Any}}(), # store system, user and assistant msg +# "question"=> query, +# "context"=> Dict{String, Any}(), +# "action_history"=> OrderedDict{String, Any}( +# # "1"=> Dict("plan"=> "...", "action_name"=> "...", "action_input"=> "...", "action_result"=> "..."), +# # "2"=> Dict("plan"=> "...", "action_name"=> "...", "action_input"=> "...", "action_result"=> "..."), +# # ... +# ), +# ) + +# systemmsg_dict = Dict( +# "role" => "system", +# "content" => [ +# Dict("type" => "text", "text" => systemmsg), +# ] +# ) +# usermsg = Dict( +# "role" => "user", +# "content" => [ +# Dict("type" => "text", "text" => query), +# ] +# ) +# push!(initialstate["chathistory"], systemmsg_dict) +# push!(initialstate["chathistory"], usermsg) + +# #XXX find a way to recreate the schema from a existing database +# table_schema = +# """ +# 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, +# image_url jsonb, +# 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, +# image_url jsonb, +# manufacturer_sku 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 +# ); +# """ + +# # println("\n--- SQLLLM query() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") +# # println("---") +# # error("SQLLLM query() end") + +# initialstate["context"]["table_schema"] = table_schema + +# transitionargs = ( +# executeSQL=executeSQL, +# decisionMaker=decisionMaker, +# evaluator=evaluator, +# reflector=reflector, +# text2textInstructLLM=text2textInstructLLM, +# querySQLVectorDB=similarSQLVectorDB, +# insertSQLVectorDB=insertSQLVectorDB, +# llmFormatName=llmFormatName +# ) + +# earlystop(state) = state["reward"] >= 8 ? true : false + +# root, _, resultState, highValueState = +# LLMMCTS.runMCTS(initialstate, transition, transitionargs; +# horizontalSampleExpansionPhase=1, +# horizontalSampleSimulationPhase=1, +# maxSimulationDepth=1, +# maxiterations=1, +# explorationweight=1.0, +# earlystop=earlystop, +# saveSimulatedNode=true, +# multithread=false) + +# # error("SQLLLM query() end") + +# # compare all high value state answer then select the best one +# if length(highValueState) > 1 +# selected = compareState(query, highValueState, text2textInstructLLM, llmFormatName) +# resultState = highValueState[selected] +# end + +# max_ind = +# if length(resultState["action_history"]) == 0 +# 0 +# else +# k = keys(resultState["action_history"]) +# maximum(parse.(Int, k)) +# end +# latest_action = resultState["action_history"]["$max_ind"] + +# #CHANGE add to vectorDB only if the answer is achieved and the state is terminal +# sql = latest_action["action_input"] +# if insertSQLVectorDB !== nothing && resultState["isterminal"] == true && +# resultState["accepted_as_answer"] == "yes" +# insertSQLVectorDB(resultState["question"], sql) +# end + +# println("\n--- SQLLLM query() ", @__FILE__, ":", @__LINE__, " $(Dates.now())") +# # pprintln(resultState) +# println("---\n") + +# return (result_str=latest_action["action_result"], result_raw=resultState["result_raw"]) +# end """ Make a new state. diff --git a/src/llmfunction.jl b/src/llmfunction.jl index 0cf8f60..93cca1a 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -497,7 +497,7 @@ function SQLexecution(executeSQL::Function, sql::T else sql = sql * ";" end - result = executeSQL(sql) + result = executeSQL(sql) #BUG sometime return table, sometime error df = DataFrame(result) tablesize = size(df) row, column = tablesize