Atomic-VSA / julia_server.jl
marshad180's picture
Fix: Docker+Julia HTTP server
12e5518 verified
# 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()