From 7c9ceb06f8d4cef4a8ebeffcb0792f70d5787063 Mon Sep 17 00:00:00 2001 From: tonaerospace Date: Tue, 18 Mar 2025 07:34:51 +0700 Subject: [PATCH] update --- src/interface.jl | 31 +++++--- src/llmfunction.jl | 150 +++++++++++++++++++++++++++++++++++++- system_prompt_template.jl | 146 +++++++++++++++++++++++++++++++++++++ test/test_2.jl | 98 ++++++++++++++++++------- 4 files changed, 388 insertions(+), 37 deletions(-) create mode 100644 system_prompt_template.jl diff --git a/src/interface.jl b/src/interface.jl index 20d5cf6..cc9d804 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -10,6 +10,8 @@ using ..util, ..llmfunction + + """ Think and choose action. # Arguments @@ -871,15 +873,24 @@ function query(query::T, executeSQL::Function, text2textInstructLLM::Function; earlystop(state) = state[:reward] >= 8 ? true : false - root, _, resultState = LLMMCTS.runMCTS(initialstate, transition, transitionargs; - horizontalSampleExpansionPhase=5, - horizontalSampleSimulationPhase=2, - maxSimulationDepth=5, - maxiterations=1, - explorationweight=1.0, - earlystop=earlystop, - saveSimulatedNode=true, - multithread=true) + root, _, resultState, highValueState = + LLMMCTS.runMCTS(initialstate, transition, transitionargs; + horizontalSampleExpansionPhase=5, + horizontalSampleSimulationPhase=2, + maxSimulationDepth=5, + maxiterations=1, + explorationweight=1.0, + earlystop=earlystop, + saveSimulatedNode=true, + multithread=true) + + #[WORKING] 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 + resultState = compareState(query, highValueState) + end latestKey, latestInd = GeneralUtils.findHighestIndexKey(resultState[:thoughtHistory], "observation") action_input = Symbol("action_input_$latestInd") # latest sql sql = resultState[:thoughtHistory][action_input] @@ -1119,8 +1130,6 @@ end - - diff --git a/src/llmfunction.jl b/src/llmfunction.jl index 7688c86..ccc5b65 100644 --- a/src/llmfunction.jl +++ b/src/llmfunction.jl @@ -1,7 +1,7 @@ module llmfunction 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, DataStructures, StatsBase @@ -788,6 +788,154 @@ function getTableNameFromSQL(sql::T, text2textInstructLLM::Function)::Vector{Str end +""" 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, +serving as a heuristic to steer the search algorithm towards the most promising regions of the tree. + +# Arguments + - `state<:AbstractDict` + one of Yiem's agent + - `text2textInstructLLM::Function` + A function that handles communication to LLM service + +# Return + - `score::Integer` + +# Example +```jldoctest +julia> +``` + +# TODO + - [] update docs + - [WORKING] implement + +# Signature +""" +function compareState(query, highValueStateList) + + systemmsg = + """ + + - You are a helpful assistant + + + The user has made multiple attempts to solve the question, resulting in various answers + + - Identify and select the most accurate and relevant response from these multiple results for the user + + + - The user's question + - The user's attempted actions and their corresponding results + + + - Selected_response: the number of the most accurate and relevant response + - Rationale: a brief explanation of why you selected this response + + + - Selected_response: ... + - Rationale: ... + + + User's question: "How many German wines do you have?" + Attempt 1: + Action: SELECT * FROM wines WHERE country = 'Germany' + Result: 100 wines + Attempt 2: + Action: SELECT * FROM wines WHERE country = 'Germany' AND type = 'Red' + Result: 50 red wines + Selected_response: 1 + Rationale: The question is about German wines, so the most accurate response is the one that includes all German wines. + + + Let's begin! + """ + + thoughthistory = "" + for (k, v) in state[:thoughtHistory] + thoughthistory *= "$k: $v\n" + end + + errornote = "" + + for attempt in 1:10 + errorFlag = false + + usermsg = + """ + Trajectory: $thoughthistory + Error_note: $errornote + """ + + _prompt = + [ + Dict(:name=> "system", :text=> systemmsg), + Dict(:name=> "user", :text=> usermsg) + ] + + # put in model format + prompt = GeneralUtils.formatLLMtext(_prompt; formatname="qwen") + + header = ["Trajectory_evaluation:", "Answer_evaluation:", "Accepted_as_answer:", "Score:", "Suggestion:"] + dictkey = ["trajectory_evaluation", "answer_evaluation", "accepted_as_answer", "score", "suggestion"] + + response = text2textInstructLLM(prompt) + + # sometime LLM output something like **Comprehension**: which is not expected + response = replace(response, "**"=>"") + response = replace(response, "***"=>"") + + # make sure every header is in the response + for i in header + detected = GeneralUtils.detect_keyword(i, response) + if detected === nothing + errornote = "Your previous response didn't provide $i" + errorFlag = true + end + end + if errorFlag + continue # skip to the next iteration + 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 + continue + end + + accepted_as_answer::AbstractString = responsedict[:accepted_as_answer] + + if accepted_as_answer ∉ ["Yes", "No"] # [PENDING] add errornote into the prompt + error("generated accepted_as_answer has wrong format") + 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("\n~~~ Evaluator() ", @__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 + diff --git a/system_prompt_template.jl b/system_prompt_template.jl new file mode 100644 index 0000000..03d2ce4 --- /dev/null +++ b/system_prompt_template.jl @@ -0,0 +1,146 @@ +""" +Default system message template: + + + - You are a helpful assistant + + + - Describe the current situation + + + - state your vision of how the situation will evolve, what would you want the situation to evolve into + + + - state the goal + + + - Break the goal into smaller steps + + + - state the mini goals that fall under your responsibility + + + + + + + + + + + + + + + + + + Let's begin! + + + + + + + + + +Example: + + +- You are a founder of a tech startup + + +- 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. + + + - 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. + + + - To create an innovative caregiving support platform that reduces the physical and emotional burden on family caregivers while ensuring quality care for bedridden patients + + + - 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 + + + - 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 + + + - User's specific caregiving challenges + - Context and severity of the situation + - Feedback from family caregivers + - Potential solutions based on immediate and long-term impact + + + - 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 + + + - Comprehension: Demonstrate understanding of the specific challenge + - Plan: Outline step-by-step approach to address the issue + - Action_name: (Must be aligned with your plan): The name of the action. Typically corresponds to the execution of the first step in your plan. + Can be one of the following functions: + - 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. + + + Comprehension: ... + Plan: ... + Action_name: ... + Action_input: ... + + + Example 1: + User: "My mother has been bedridden for 3 months, and I'm struggling to monitor her condition while working from home. I'm worried I might miss important signs of deterioration." + + Comprehension: The user is facing challenges balancing work-from-home responsibilities with monitoring their bedridden mother's health condition. There's anxiety about potentially missing critical health changes. + + Plan: + 1. Assess current monitoring needs and gaps + 2. Propose smart monitoring system setup + 3. Implement remote alerts and notifications + 4. Provide training on using the system + 5. Set up regular check-ins for system optimization + + Action_name: CHATBOX + Action_input: Gather specific information about mother's condition, current monitoring methods, and work schedule to tailor the smart monitoring solution effectively. + + Example 2: + User: "I need to implement a fall detection system for my father who is partially mobile but at high risk of falls. What solutions do you recommend?" + + Comprehension: The user requires a reliable fall detection system for a partially mobile patient with high fall risk. Safety is the primary concern while maintaining the patient's limited mobility. + + Plan: + 1. Review available fall detection technologies + 2. Check compatibility with existing infrastructure + 3. Evaluate cost and implementation requirements + 4. Propose specific solution options + 5. Create implementation timeline + + Action_name: CHECKRESOURCES + Action_input: Query database for available fall detection systems, focusing on: + - Motion sensors + - Wearable devices + - Computer vision systems + - Integration capabilities + - Cost ranges + + +Let's begin! +""" diff --git a/test/test_2.jl b/test/test_2.jl index 26b94b1..ea1edd0 100644 --- a/test/test_2.jl +++ b/test/test_2.jl @@ -1,30 +1,78 @@ using Revise -using SQLLLM, LLMMCTS, DataStructures +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) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -initialstate = Dict{Symbol, 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}( - #[] :recap=>, - :question=> "query", - ), - ) - -root = MCTSNode("root", initialstate, 0, 0, 0, 0, false, nothing, Dict{String,MCTSNode}(), - Dict{Symbol,Any}()) - -field = fieldnames(typeof(root)) -for f in field - println(getfield(root, f)) - setfield!(root, f, 1) -end -println("\n done") \ No newline at end of file