Spaces:
Sleeping
Sleeping
| # Julia HTTP Server for Atomic VSA | |
| # Serves VSA computations via REST API | |
| using HTTP | |
| using JSON3 | |
| using Random | |
| using LinearAlgebra | |
| using Statistics | |
| # Load VSA core | |
| include("src/vsa_core.jl") | |
| # ============================================================================ | |
| # VSA Demo System | |
| # ============================================================================ | |
| const D = 2048 # Demo dimensionality | |
| # Global registry | |
| const REGISTRY = VSARegistry() | |
| # Symptoms | |
| const SYMPTOMS = [ | |
| "chest_pain", "shortness_of_breath", "fever", "cough", | |
| "headache", "fatigue", "nausea", "dizziness", | |
| "abdominal_pain", "back_pain", "joint_pain", "rash", | |
| "sore_throat", "runny_nose", "muscle_ache", "chills" | |
| ] | |
| # Triage categories with symptoms | |
| const TRIAGE_CATEGORIES = Dict( | |
| "Emergency - Cardiac" => ["chest_pain", "shortness_of_breath", "dizziness"], | |
| "Urgent - Respiratory" => ["shortness_of_breath", "cough", "fever", "chills"], | |
| "Urgent - Infection" => ["fever", "chills", "fatigue", "muscle_ache"], | |
| "Standard - Flu-like" => ["fever", "cough", "sore_throat", "runny_nose", "muscle_ache"], | |
| "Standard - GI" => ["nausea", "abdominal_pain", "fever"], | |
| "Standard - Musculoskeletal" => ["back_pain", "joint_pain", "muscle_ache"], | |
| "Low Priority - Minor" => ["headache", "fatigue", "runny_nose"], | |
| ) | |
| # Build prototype vectors | |
| const PROTOTYPES = Dict{String, Atom}() | |
| function normalize_atom(atom::Atom) | |
| if atom.data isa SingleData | |
| v = atom.data.vec | |
| n = norm(v) | |
| return n > 0 ? Atom(SingleData(v ./ n)) : atom | |
| end | |
| return atom | |
| end | |
| function build_prototypes!() | |
| for (category, symptom_list) in TRIAGE_CATEGORIES | |
| atoms = Atom[] | |
| field_atom = get_element(REGISTRY, "fields", "symptom_field", D) | |
| for symptom in symptom_list | |
| value_atom = get_element(REGISTRY, "symptoms", symptom, D) | |
| mol = bind(field_atom, value_atom) | |
| push!(atoms, mol) | |
| end | |
| proto = bundle(atoms) | |
| PROTOTYPES[category] = normalize_atom(proto) | |
| end | |
| end | |
| function create_patient_vector(symptoms_list::Vector{String}) | |
| atoms = Atom[] | |
| field_atom = get_element(REGISTRY, "fields", "symptom_field", D) | |
| for symptom in symptoms_list | |
| if symptom in SYMPTOMS | |
| value_atom = get_element(REGISTRY, "symptoms", symptom, D) | |
| mol = bind(field_atom, value_atom) | |
| push!(atoms, mol) | |
| end | |
| end | |
| if isempty(atoms) | |
| return Atom(SingleData(zeros(Float32, D))) | |
| end | |
| return normalize_atom(bundle(atoms)) | |
| end | |
| function classify_patient(symptoms_list::Vector{String}) | |
| patient = create_patient_vector(symptoms_list) | |
| results = [] | |
| for (category, prototype) in PROTOTYPES | |
| sim = similarity(patient, prototype) | |
| push!(results, (category=category, similarity=Float64(sim))) | |
| end | |
| sort!(results, by=x -> x.similarity, rev=true) | |
| return results | |
| end | |
| # ============================================================================ | |
| # HTTP Handlers | |
| # ============================================================================ | |
| function handle_classify(req::HTTP.Request) | |
| try | |
| body = JSON3.read(String(req.body)) | |
| symptoms = String.(body.symptoms) | |
| results = classify_patient(symptoms) | |
| response = Dict( | |
| "results" => [Dict("category" => r.category, "similarity" => round(r.similarity, digits=4)) for r in results], | |
| "patient_symptoms" => symptoms, | |
| "dimensionality" => D | |
| ) | |
| return HTTP.Response(200, ["Content-Type" => "application/json"], JSON3.write(response)) | |
| catch e | |
| return HTTP.Response(400, ["Content-Type" => "application/json"], JSON3.write(Dict("error" => string(e)))) | |
| end | |
| end | |
| function handle_health(req::HTTP.Request) | |
| return HTTP.Response(200, ["Content-Type" => "application/json"], JSON3.write(Dict("status" => "ok", "engine" => "Julia VSA"))) | |
| end | |
| function handle_info(req::HTTP.Request) | |
| info = Dict( | |
| "name" => "Atomic VSA", | |
| "version" => "1.0.0", | |
| "dimensionality" => D, | |
| "symptoms" => SYMPTOMS, | |
| "categories" => collect(keys(TRIAGE_CATEGORIES)), | |
| "engine" => "Julia $(VERSION)" | |
| ) | |
| return HTTP.Response(200, ["Content-Type" => "application/json"], JSON3.write(info)) | |
| end | |
| # Router | |
| function router(req::HTTP.Request) | |
| path = HTTP.URIs.splitpath(req.target) | |
| # CORS headers | |
| headers = [ | |
| "Access-Control-Allow-Origin" => "*", | |
| "Access-Control-Allow-Methods" => "GET, POST, OPTIONS", | |
| "Access-Control-Allow-Headers" => "Content-Type" | |
| ] | |
| if req.method == "OPTIONS" | |
| return HTTP.Response(200, headers) | |
| end | |
| response = if length(path) >= 1 && path[1] == "api" | |
| if length(path) >= 2 | |
| if path[2] == "classify" && req.method == "POST" | |
| handle_classify(req) | |
| elseif path[2] == "health" | |
| handle_health(req) | |
| elseif path[2] == "info" | |
| handle_info(req) | |
| else | |
| HTTP.Response(404, JSON3.write(Dict("error" => "Not found"))) | |
| end | |
| else | |
| HTTP.Response(404, JSON3.write(Dict("error" => "Not found"))) | |
| end | |
| else | |
| HTTP.Response(404, JSON3.write(Dict("error" => "Not found"))) | |
| end | |
| # Add CORS headers to response | |
| for (k, v) in headers | |
| HTTP.setheader(response, k => v) | |
| end | |
| return response | |
| end | |
| # ============================================================================ | |
| # Main | |
| # ============================================================================ | |
| function main() | |
| Random.seed!(42) | |
| println("Building VSA prototypes...") | |
| build_prototypes!() | |
| println("Prototypes built for $(length(PROTOTYPES)) categories") | |
| port = 8080 | |
| println("Starting Julia VSA server on port $port...") | |
| HTTP.serve(router, "0.0.0.0", port) | |
| end | |
| main() | |