-
Notifications
You must be signed in to change notification settings - Fork 0
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).
| 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. |
julia --project=. -e 'using Statistikles; main()'
# or, with the task runner:
just runmain() (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 reachable →
Connected 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).
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.jlrun_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(...)` == trueInside 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 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.
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 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/.
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.
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.
- Installation — get Statistikles running first
- Release-Process — how versions are published
Overview
Using
Development
Project