From c8504686d184e82d2bfcee7f7aee434594091caa Mon Sep 17 00:00:00 2001 From: Shravan Goswami Date: Fri, 15 Aug 2025 13:57:48 +0530 Subject: [PATCH 01/12] improved Data Tab and added non working backend this commit have lots of issues, heavily used LLM code, just saving code --- DoodleBUGS/.gitignore | 1 + DoodleBUGS/public/examples/rats/data.json | 280 ++++-------------- DoodleBUGS/runtime/Project.toml | 9 + DoodleBUGS/runtime/server.jl | 208 +++++++++++++ .../src/components/layouts/MainLayout.vue | 266 ++++++++++++----- .../src/components/layouts/TheNavbar.vue | 52 +++- .../left-sidebar/ExecutionSettingsPanel.vue | 98 ++++++ .../src/components/panels/DataInputPanel.vue | 226 ++++++++++---- .../right-sidebar/ExecutionPanel.vue | 271 +++++++++++++++++ .../src/composables/useGraphValidator.ts | 2 + DoodleBUGS/src/stores/dataStore.ts | 271 +++++++++++++---- DoodleBUGS/src/stores/executionStore.ts | 86 ++++++ DoodleBUGS/src/stores/uiStore.ts | 17 +- 13 files changed, 1363 insertions(+), 424 deletions(-) create mode 100644 DoodleBUGS/runtime/Project.toml create mode 100644 DoodleBUGS/runtime/server.jl create mode 100644 DoodleBUGS/src/components/left-sidebar/ExecutionSettingsPanel.vue create mode 100644 DoodleBUGS/src/components/right-sidebar/ExecutionPanel.vue create mode 100644 DoodleBUGS/src/stores/executionStore.ts diff --git a/DoodleBUGS/.gitignore b/DoodleBUGS/.gitignore index 4aa60c007..e02a85b6d 100644 --- a/DoodleBUGS/.gitignore +++ b/DoodleBUGS/.gitignore @@ -10,6 +10,7 @@ digest.txt root.txt src.txt public.txt +runtime.txt node_modules .DS_Store diff --git a/DoodleBUGS/public/examples/rats/data.json b/DoodleBUGS/public/examples/rats/data.json index c91f4cac4..268812441 100644 --- a/DoodleBUGS/public/examples/rats/data.json +++ b/DoodleBUGS/public/examples/rats/data.json @@ -1,227 +1,57 @@ { - "data": { - "N": 30, - "T": 5, - "x": [ - 8.0, - 15.0, - 22.0, - 29.0, - 36.0 - ], - "xbar": 22, - "Y": [ - [ - 151, - 199, - 246, - 283, - 320 - ], - [ - 145, - 199, - 249, - 293, - 354 - ], - [ - 147, - 214, - 263, - 312, - 328 - ], - [ - 155, - 200, - 237, - 272, - 297 - ], - [ - 135, - 188, - 230, - 280, - 323 - ], - [ - 159, - 210, - 252, - 298, - 331 - ], - [ - 141, - 189, - 231, - 275, - 305 - ], - [ - 159, - 201, - 248, - 297, - 338 - ], - [ - 177, - 220, - 260, - 309, - 331 - ], - [ - 134, - 182, - 220, - 260, - 295 - ], - [ - 160, - 208, - 261, - 313, - 352 - ], - [ - 143, - 188, - 220, - 273, - 314 - ], - [ - 154, - 200, - 244, - 289, - 325 - ], - [ - 161, - 218, - 266, - 304, - 340 - ], - [ - 142, - 184, - 223, - 262, - 298 - ], - [ - 156, - 203, - 243, - 283, - 317 - ], - [ - 157, - 212, - 259, - 307, - 336 - ], - [ - 152, - 203, - 245, - 286, - 324 - ], - [ - 154, - 205, - 253, - 298, - 334 - ], - [ - 139, - 190, - 225, - 267, - 302 - ], - [ - 146, - 196, - 247, - 289, - 321 - ], - [ - 161, - 215, - 254, - 293, - 332 - ], - [ - 153, - 207, - 256, - 303, - 345 - ], - [ - 149, - 198, - 245, - 287, - 324 - ], - [ - 144, - 192, - 242, - 289, - 326 - ], - [ - 162, - 211, - 262, - 315, - 357 - ], - [ - 157, - 202, - 242, - 281, - 316 - ], - [ - 150, - 204, - 256, - 298, - 335 - ], - [ - 151, - 202, - 248, - 290, - 325 - ], - [ - 163, - 216, - 265, - 307, - 342 - ] - ] - }, - "inits": {} + "data": { + "N": 30, + "T": 5, + "x": [8.0, 15.0, 22.0, 29.0, 36.0], + "xbar": 22, + "Y": [ + [151, 199, 246, 283, 320], + [145, 199, 249, 293, 354], + [147, 214, 263, 312, 328], + [155, 200, 237, 272, 297], + [135, 188, 230, 280, 323], + [159, 210, 252, 298, 331], + [141, 189, 231, 275, 305], + [159, 201, 248, 297, 338], + [177, 236, 285, 350, 376], + [134, 182, 220, 260, 296], + [160, 208, 261, 313, 352], + [143, 188, 220, 273, 314], + [154, 200, 244, 289, 325], + [171, 221, 270, 326, 358], + [163, 216, 242, 281, 312], + [160, 207, 248, 288, 324], + [142, 187, 234, 280, 316], + [156, 203, 243, 283, 317], + [157, 212, 259, 307, 336], + [152, 203, 246, 286, 321], + [154, 205, 253, 298, 334], + [139, 190, 225, 267, 302], + [146, 191, 229, 272, 302], + [157, 211, 250, 285, 323], + [132, 185, 237, 286, 331], + [160, 207, 257, 303, 345], + [169, 216, 261, 295, 333], + [157, 205, 248, 289, 316], + [137, 180, 219, 258, 291], + [153, 200, 244, 286, 324] + ] + }, + "inits": { + "alpha": [ + 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, + 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, + 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0 + ], + "beta": [ + 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, + 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, + 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 + ], + "alpha.c": 150.0, + "beta.c": 10.0, + "tau.c": 1.0, + "alpha.tau": 1.0, + "beta.tau": 1.0 + } } \ No newline at end of file diff --git a/DoodleBUGS/runtime/Project.toml b/DoodleBUGS/runtime/Project.toml new file mode 100644 index 000000000..4fe501085 --- /dev/null +++ b/DoodleBUGS/runtime/Project.toml @@ -0,0 +1,9 @@ +[deps] +AdvancedHMC = "0bf59076-c3b1-5ca4-86bd-e02cd72cde3d" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" +JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" +JuliaBUGS = "ba9fb4c0-828e-4473-b6a1-cd2560fee5bf" +LogDensityProblemsAD = "996a588d-648d-4e1f-a8f0-a84b347e47b1" +MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" diff --git a/DoodleBUGS/runtime/server.jl b/DoodleBUGS/runtime/server.jl new file mode 100644 index 000000000..d8be77ad5 --- /dev/null +++ b/DoodleBUGS/runtime/server.jl @@ -0,0 +1,208 @@ +# File: server.jl +# This server is designed to be a generic executor. +# It creates a temporary, sandboxed Julia environment for each request, +# installs specified dependencies, and runs the BUGS model. + +using HTTP +using JSON3 +using Pkg + +# Define CORS headers to allow cross-origin requests from the web app. +const CORS_HEADERS = [ + "Access-Control-Allow-Origin" => "*", + "Access-Control-Allow-Headers" => "Content-Type", + "Access-Control-Allow-Methods" => "POST, GET, OPTIONS", +] + +# A simple middleware to handle CORS preflight (OPTIONS) requests and add headers to all responses. +function cors_handler(handler) + return function(req::HTTP.Request) + if HTTP.method(req) == "OPTIONS" + return HTTP.Response(200, CORS_HEADERS) + else + response = handler(req) + append!(response.headers, CORS_HEADERS) + return response + end + end +end + +# A simple handler for the health check endpoint. +function health_check_handler(req::HTTP.Request) + return HTTP.Response(200, ["Content-Type" => "application/json"], JSON3.write(Dict("status" => "ok"))) +end + + +# The main handler for processing model execution requests. +function run_model_handler(req::HTTP.Request) + logs = String[] + push!(logs, "Backend processing started.") + + # Create a temporary, sandboxed environment for this run + tmp_dir = mktempdir() + push!(logs, "Created temporary sandbox environment at: $(tmp_dir)") + + try + # Activate the sandbox project environment + Pkg.activate(tmp_dir) + + # Parse the JSON body from the request + body = JSON3.read(String(req.body)) + model_code = body.model_code + data_string = body.data_string + inits_string = body.inits_string + dependencies = body.dependencies + settings = get(body, :settings, JSON3.Object()) + + push!(logs, "Request body parsed successfully.") + + # Add specified dependencies to the sandbox environment + push!(logs, "Adding $(length(dependencies)) dependencies to sandbox...") + for dep in dependencies + if isempty(dep.version) + Pkg.add(dep.name) + else + Pkg.add(name=dep.name, version=dep.version) + end + end + push!(logs, "All dependencies installed in sandbox.") + + # Write the user's BUGS model code to a file in the sandbox + model_path = joinpath(tmp_dir, "model.bugs") + write(model_path, model_code) + + # The core logic will be executed in a separate, sandboxed Julia process + # to ensure isolation and use the correct project environment. + script_path = joinpath(tmp_dir, "run_script.jl") + + # This script contains the actual model compilation and sampling logic. + # It will be executed by the sandboxed Julia process. + run_script_content = """ + using JuliaBUGS + using LogDensityProblemsAD + using AdvancedHMC + using MCMCChains + using Random + using JSON3 + + try + # Define the model from the string + model_def = JuliaBUGS.@bugs_str(\"\"\" + $(model_code) + \"\"\", true, false) + + # Parse data and inits from strings into NamedTuples + data_nt = eval(Meta.parse(\"\"\" + $(data_string) + \"\"\")) + inits_nt = eval(Meta.parse(\"\"\" + $(inits_string) + \"\"\")) + + # Compile the model + model = JuliaBUGS.compile(model_def, data_nt, inits_nt) + + # Wrap for AD + ad_model = ADgradient(:ReverseDiff, model; compile=Val(true)) + + # Sampler settings + n_samples = $(get(settings, :n_samples, 1000)) + n_adapts = $(get(settings, :n_adapts, 1000)) + + # Run sampler + D = LogDensityProblems.dimension(model) + initial_θ = rand(D) + samples = AbstractMCMC.sample( + ad_model, + NUTS(0.8), + n_samples; + n_adapts=n_adapts, + chain_type=Chains, + init_params=initial_θ, + discard_initial=n_adapts + ) + + # Format results + summary_stats = summary(samples) + results_json = [Dict(pairs(row)) for row in eachrow(summary_stats)] + + # Write results to a file + open("results.json", "w") do f + JSON3.write(f, Dict("success" => true, "results" => results_json)) + end + + catch e + open("results.json", "w") do f + JSON3.write(f, Dict("success" => false, "error" => sprint(showerror, e))) + end + end + """ + write(script_path, run_script_content) + push!(logs, "Generated execution script in sandbox.") + + # Execute the script in the sandboxed environment + # --project points to the sandbox, ensuring it uses the correct dependencies. + julia_executable = joinpath(Sys.BINDIR, "julia") + cmd = `$(julia_executable) --project=$(tmp_dir) $(script_path)` + + push!(logs, "Executing script in sandboxed process...") + run(cmd) + push!(logs, "Script execution finished.") + + # Read the results generated by the script + results_path = joinpath(tmp_dir, "results.json") + results_content = JSON3.read(read(results_path, String)) + + # Check if the script execution was successful + if !results_content.success + throw(ErrorException(results_content.error)) + end + + # Read generated project files to send back to the user + project_toml_content = read(joinpath(tmp_dir, "Project.toml"), String) + manifest_toml_content = read(joinpath(tmp_dir, "Manifest.toml"), String) + push!(logs, "Successfully retrieved results and project files.") + + # Prepare the final successful response + response_body = Dict( + "success" => true, + "results" => results_content.results, + "logs" => logs, + "files" => [ + Dict("name" => "model.bugs", "content" => model_code), + Dict("name" => "run_script.jl", "content" => run_script_content), + Dict("name" => "Project.toml", "content" => project_toml_content), + Dict("name" => "Manifest.toml", "content" => manifest_toml_content) + ] + ) + return HTTP.Response(200, ["Content-Type" => "application/json"], JSON3.write(response_body)) + + catch e + # If any error occurs during the process, capture and return it + push!(logs, "An error occurred: $(sprint(showerror, e))") + @error "Error during model execution" exception=(e, catch_backtrace()) + + error_response = Dict( + "success" => false, + "error" => sprint(showerror, e), + "logs" => logs + ) + return HTTP.Response(500, ["Content-Type" => "application/json"], JSON3.write(error_response)) + + finally + # Clean up the temporary directory + rm(tmp_dir, recursive=true) + # It's good practice to reactivate the main project environment + Pkg.activate() + end +end + +# Define the router and register the endpoints +const ROUTER = HTTP.Router() +HTTP.register!(ROUTER, "GET", "/api/health", health_check_handler) +HTTP.register!(ROUTER, "POST", "/api/run_model", run_model_handler) + +# Start the server with the CORS handler +port = 8081 +println("Starting JuliaBUGS backend server on http://localhost:$(port)...") +HTTP.serve(cors_handler(ROUTER), "0.0.0.0", port) diff --git a/DoodleBUGS/src/components/layouts/MainLayout.vue b/DoodleBUGS/src/components/layouts/MainLayout.vue index 02fb4c5c0..01459104e 100644 --- a/DoodleBUGS/src/components/layouts/MainLayout.vue +++ b/DoodleBUGS/src/components/layouts/MainLayout.vue @@ -1,14 +1,18 @@ +