Skip to content

Usage and Examples

Jonathan D.A. Jewell edited this page Jul 11, 2026 · 1 revision

Usage and Examples

This page shows how to actually use Statistikles: launching the interactive assistant with main(), running the offline demo with run_examples(), what a chat turn looks like, how to point it at an LM Studio endpoint, and how it behaves when no LLM is reachable.

New here? Install first via Installation.

The core guarantee. Statistikles is a Kautz Type-1 neurosymbolic system: the LLM (neural) understands your question and routes it to a tool; Julia (symbolic) computes every number. If you see a statistic in a reply, it came from a verified Julia function — never from neural inference. This is enforced in code by the numeric-provenance guardrail (see below).

Two ways to run

Entry point Needs an LLM? What it does
main() Optional Prints the banner, probes for an LM Studio endpoint. Connected → interactive chat. Not connected → runs run_examples() and returns.
run_examples() No Runs a fixed set of offline calculations directly against the Julia core.

Launching the assistant — main()

julia --project=. -e 'using Statistikles; main()'
# or, with the task runner:
just run

main() (in src/tools/chat.jl) prints the startup banner, then issues a GET $BASE_URL/models probe:

  ┌─────────────────────────────────────────────────────────────┐
  │  Statistikles v0.1.0                                        │
  │  Neurosymbolic Statistical Analysis Assistant              │
  │                                                             │
  │  DESIGN: LLM = natural language router/interpreter          │
  │          Julia = verified symbolic computation              │
  │                                                             │
  │  Every number is computed, never hallucinated.              │
  └─────────────────────────────────────────────────────────────┘
  • Endpoint reachableConnected to LM Studio (<model>) and the interactive session (statistical_assistant_chat()) starts.

  • Endpoint not reachable → it prints

      Cannot connect to LM Studio at http://localhost:1234/v1
      Start it with: lms server start
      Running offline demo instead...
    

    then runs run_examples() and returns (no hang, no prompt).

The offline demo — run_examples()

julia --project=. -e 'using Statistikles; run_examples()'

Or run the bundled script, which additionally cross-checks the executor's tool dispatch against direct calls:

julia --project=. examples/run_examples.jl

run_examples() computes, in order: descriptive statistics, an independent t-test, a one-way ANOVA, a Pearson correlation, a James–Stein estimate, and a power-analysis sample size — then prints:

  All numbers above were computed by Julia, not an LLM.

examples/run_examples.jl goes one step further, running one calculation both directly and through the tool boundary to show they match:

anova_direct = one_way_anova([[5.0, 6, 7, 8], [8.0, 9, 10, 11], [3.0, 4, 5, 6]])
anova_tool   = Statistikles.execute_tool("anova",
    Dict{String,Any}("groups" => [[5.0, 6, 7, 8], [8.0, 9, 10, 11], [3.0, 4, 5, 6]]))
# prints the two F statistics and `isapprox(...)` == true

The interactive session

Inside the chat loop you type natural-language questions. Three special commands are recognised (from chat.jl):

Type Action
help Print the example-query cheat sheet
offline Run run_examples() without leaving the session
quit Exit (Goodbye.)

Each turn is wrapped in try/catch, so a single malformed turn never kills the session.

A sample turn

A question like "Compare groups: A=[85,90,78,92,88] vs B=[76,82,71,80,85]" flows through the boundary like this (the [symbolic] line is printed by the executor as it runs the Julia function):

  You: Compare groups: A=[85,90,78,92,88] vs B=[76,82,71,80,85]

  Statistikles:
  [symbolic] executing: t_test
  Yes — there is a statistically significant difference (t(38)=2.847,
  p=.007) with a large effect size (Cohen's d=0.90).

Every number in that reply came from the Julia t_test tool. The conceptual flow, from README.adoc:

You: "Is there a significant difference between these two groups?"
     │ (Natural Language Understanding — neural)
LLM routes to: t_test_independent(group1, group2)
     │ (Symbolic Computation — Julia)
Julia computes: t=2.847, df=38, p=0.007, Cohen's d=0.90
     │ (Natural Language Generation — neural)
LLM explains the result in plain English.

Example queries (the help cheat sheet)

print_help() lists ready-to-paste prompts, including:

Analysis Example prompt
Descriptive Describe: 23, 45, 12, 67, 34, 56, 78, 29, 41, 53
t-test Compare groups: A=[85,90,78,92,88] vs B=[76,82,71,80,85]
ANOVA ANOVA on three groups: [5,6,7], [8,9,10], [3,4,5]
Chi-square Test independence: [[30,10],[15,45]]
Correlation Correlate [1,2,3,4,5] with [2,4,5,4,5]
Regression Regress x=[1,2,3,4,5] on y=[2,4,5,4,5]
Non-parametric Mann-Whitney U: [1,3,5,7] vs [2,4,6,8]
Power Sample size for medium effect (d=0.5), 80% power?
Reliability Cronbach's alpha: [[4,5,4],[3,4,3],[5,5,4],[4,4,4]]
Diagnostic Sensitivity/specificity: TP=85, FN=15, TN=90, FP=10
Qualitative Saturation: new themes per interview [5,4,3,2,2,1,1,0,1,0,0]

Conceptual questions are answered directly, e.g. Explain the difference between validity and reliability or When should I use non-parametric tests?

The tools behind the answers

The LLM can only route to registered tools — it never computes. get_tools() in src/tools/definitions.jl registers 29 tool definitions (e.g. descriptive_statistics, t_test, anova, chi_square, correlation, regression, nonparametric_test, permanova, power_analysis, bayes_factor, reliability_analysis, inter_rater_reliability, qualitative_analysis, …), dispatched by execute_tool() in src/tools/executor.jl and backed by the 41 statistics modules under src/stats/.

Connecting an LLM (LM Studio endpoint)

Statistikles talks to any OpenAI-compatible chat-completions endpoint. Point it at LM Studio (or another server) with these environment variables, read in src/tools/lmstudio.jl:

Variable Default Purpose
STATISTIKLES_LM_URL http://localhost:1234/v1 Base URL of the endpoint
STATISTIKLES_API_KEY lm-studio Bearer token sent in the Authorization header
STATISTIKLES_MODEL lmstudio-community/qwen2.5-7b-instruct Model id requested

The request itself (call_lm_studio) posts to $BASE_URL/chat/completions with temperature = 0.7, max_tokens = 4000, and the tool definitions attached, so the model must support function/tool calling.

Example — start LM Studio's server and launch:

lms server start                       # serves http://localhost:1234/v1
julia --project=. -e 'using Statistikles; main()'

Point at a different host/model:

export STATISTIKLES_LM_URL='http://192.168.1.50:1234/v1'
export STATISTIKLES_MODEL='lmstudio-community/qwen2.5-14b-instruct'
julia --project=. -e 'using Statistikles; main()'

Container caveat. Inside the Option 3 container, these variables must be set at build time (before precompile) to take effect — see the container notes in Installation.

The numeric-provenance guardrail

Before any assistant reply is printed, enforce_numeric_boundary! runs validate_numeric_provenance over it: every numeric literal in the prose must trace back to a recorded tool result (or a number the user supplied). If unverified numbers remain, the assistant does one retry asking the model to restate using only tool-derived numbers; if orphans still persist, the reply is printed with a warning block appended — the text is never silently rewritten:

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  UNVERIFIED NUMBERS — POSSIBLE MOLLOCK
  The following number(s) in the reply above did not come from any
  symbolic tool result and could not be verified:
      - <value>
  Trust only numbers produced by [symbolic] tool calls.
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

A mollock is the project's term for a plausible-sounding but fabricated statistic. The guardrail is what turns "the LLM shouldn't invent numbers" into an enforced invariant.

See also

Clone this wiki locally