learnstat 0.1.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. learnstat-0.2.1/LICENSE +21 -0
  2. {learnstat-0.1.0/learnstat.egg-info → learnstat-0.2.1}/PKG-INFO +71 -8
  3. learnstat-0.1.0/PKG-INFO → learnstat-0.2.1/README.md +197 -164
  4. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/__init__.py +1 -1
  5. learnstat-0.2.1/learnstat/cli.py +331 -0
  6. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/commands.py +24 -1
  7. learnstat-0.2.1/learnstat/config.py +223 -0
  8. learnstat-0.2.1/learnstat/guide.py +266 -0
  9. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/knowledge.py +1 -1
  10. learnstat-0.2.1/learnstat/llm.py +280 -0
  11. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/profile.py +1 -1
  12. learnstat-0.2.1/learnstat/providers.py +78 -0
  13. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/session.py +19 -12
  14. learnstat-0.2.1/learnstat/setup.py +308 -0
  15. learnstat-0.1.0/README.md → learnstat-0.2.1/learnstat.egg-info/PKG-INFO +227 -136
  16. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat.egg-info/SOURCES.txt +6 -0
  17. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat.egg-info/requires.txt +0 -4
  18. {learnstat-0.1.0 → learnstat-0.2.1}/pyproject.toml +7 -3
  19. learnstat-0.2.1/tests/test_ai_config.py +321 -0
  20. {learnstat-0.1.0 → learnstat-0.2.1}/tests/test_ipython.py +2 -1
  21. learnstat-0.1.0/learnstat/cli.py +0 -184
  22. learnstat-0.1.0/learnstat/llm.py +0 -204
  23. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/advisor.py +0 -0
  24. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/ipython_ext.py +0 -0
  25. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/memory.py +0 -0
  26. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/recovery.py +0 -0
  27. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/safety.py +0 -0
  28. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat/suggestions.py +0 -0
  29. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat.egg-info/dependency_links.txt +0 -0
  30. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat.egg-info/entry_points.txt +0 -0
  31. {learnstat-0.1.0 → learnstat-0.2.1}/learnstat.egg-info/top_level.txt +0 -0
  32. {learnstat-0.1.0 → learnstat-0.2.1}/setup.cfg +0 -0
  33. {learnstat-0.1.0 → learnstat-0.2.1}/tests/test_advisor.py +0 -0
  34. {learnstat-0.1.0 → learnstat-0.2.1}/tests/test_commands.py +0 -0
  35. {learnstat-0.1.0 → learnstat-0.2.1}/tests/test_profile_memory.py +0 -0
  36. {learnstat-0.1.0 → learnstat-0.2.1}/tests/test_recovery.py +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Umor Faruk Supto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,30 +1,32 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: learnstat
3
- Version: 0.1.0
3
+ Version: 0.2.1
4
4
  Summary: An AI-assisted learning companion for statistical analysis with pandas, NumPy, SciPy and Matplotlib.
5
5
  License: MIT
6
+ Project-URL: Homepage, https://github.com/umorfaruksupto/leanstat
7
+ Project-URL: Repository, https://github.com/umorfaruksupto/leanstat
8
+ Project-URL: PyPI, https://pypi.org/project/learnstat/
6
9
  Requires-Python: >=3.10
7
10
  Description-Content-Type: text/markdown
11
+ License-File: LICENSE
8
12
  Requires-Dist: pandas>=2.0
9
13
  Requires-Dist: numpy>=1.24
10
14
  Provides-Extra: viz
11
15
  Requires-Dist: matplotlib>=3.7; extra == "viz"
12
16
  Provides-Extra: stats
13
17
  Requires-Dist: scipy>=1.10; extra == "stats"
14
- Provides-Extra: ai
15
- Requires-Dist: anthropic>=1.0; extra == "ai"
16
18
  Provides-Extra: jupyter
17
19
  Requires-Dist: ipython>=8.0; extra == "jupyter"
18
20
  Provides-Extra: all
19
21
  Requires-Dist: matplotlib>=3.7; extra == "all"
20
22
  Requires-Dist: scipy>=1.10; extra == "all"
21
- Requires-Dist: anthropic>=1.0; extra == "all"
22
23
  Requires-Dist: ipython>=8.0; extra == "all"
23
24
  Provides-Extra: dev
24
25
  Requires-Dist: pytest>=7; extra == "dev"
25
26
  Requires-Dist: matplotlib>=3.7; extra == "dev"
26
27
  Requires-Dist: scipy>=1.10; extra == "dev"
27
28
  Requires-Dist: ipython>=8.0; extra == "dev"
29
+ Dynamic: license-file
28
30
 
29
31
  # learnstat
30
32
 
@@ -40,14 +42,70 @@ You write ordinary **pandas / NumPy / SciPy / Matplotlib** code. learnstat:
40
42
 
41
43
  It's not a new language. Everything you learn uses the real pandas, SciPy and Matplotlib APIs, so the skills carry over to the rest of the ecosystem.
42
44
 
45
+ [![PyPI](https://img.shields.io/pypi/v/learnstat)](https://pypi.org/project/learnstat/)
46
+
43
47
  ## Install
44
48
 
49
+ From PyPI: <https://pypi.org/project/learnstat/>
50
+
51
+ ```bash
52
+ pip install "learnstat[all]" # from PyPI
53
+ pip install -e ".[all]" # pandas, numpy, matplotlib, scipy, ipython
54
+ pip install -e . # core only: profiling, rules, recovery
55
+ ```
56
+
57
+ ### Quick start (no commands to learn)
58
+
45
59
  ```bash
46
- pip install -e ".[all]" # pandas, numpy, matplotlib, scipy, anthropic, ipython
47
- pip install -e . # core only: profiling, rules, recovery (no AI)
60
+ pip install learnstat
61
+ learnstat
62
+ ```
63
+
64
+ That is all. learnstat walks you through everything in plain English:
65
+
66
+ 1. **Pick your AI** (optional): choose the company, paste your key, choose a model. learnstat tests it and says OK or what is wrong.
67
+ 2. **Choose your data**: press Enter and a normal file window opens (CSV or Excel), or drag the file into the terminal.
68
+ 3. **Pick what to do from a menu** by typing a number:
69
+
70
+ ```
71
+ 1) See a summary of my data
72
+ 2) Ask the AI a question about my data
73
+ 3) Get suggestions for a Python script
74
+ 4) Run a Python script with automatic help
75
+ 5) Write Python code here (my data is ready as "df")
76
+ 6) Learn a statistics topic
77
+ 7) Load a different data file
78
+ 8) Change the AI (company, key, model)
79
+ 9) Help
48
80
  ```
49
81
 
50
- The AI features are optional. With the `anthropic` package and credentials set up (`ANTHROPIC_API_KEY` or `ant auth login`), explanations get tailored to your dataset, Claude reviews code with `/review`, and Claude can propose fixes for errors the rules can't handle. Without them, everything else still works offline. The default model is `claude-opus-5-5`; set `LEARNSTAT_MODEL` to choose another.
82
+ Nothing else needs to be memorised: every option asks for what it needs, and option 9 explains the menu. Skip the AI and everything still works with built-in rules.
83
+
84
+ ### Add an AI (optional)
85
+
86
+ Just run `learnstat`. If no AI is set up yet it offers a guided setup, and you can repeat it any time with `learnstat setup` (or `/ai` inside a session):
87
+
88
+ 1. **Choose the company**: OpenAI, Anthropic, Google Gemini, xAI, Mistral, DeepSeek, Groq, Together, OpenRouter, Ollama, LM Studio, or any other OpenAI-compatible endpoint.
89
+ 2. **Paste your API key**. The input is hidden, and local servers such as Ollama need no key.
90
+ 3. **Pick a model** from the list your key can actually use. Type part of a name to filter.
91
+ 4. **learnstat checks it** with a live test request and shows `OK` or the exact problem (rejected key, unknown model, no connection, quota), with options to fix it.
92
+ 5. It saves the account and starts the interactive session.
93
+
94
+ Several accounts can be saved and switched: run `learnstat setup` and pick a number, or use `/ai use <name>` in a session. The AI features need no extra package.
95
+
96
+ For scripts and CI there is a non-interactive route:
97
+
98
+ ```bash
99
+ learnstat config set api_key sk-your-key
100
+ learnstat config set base_url https://openrouter.ai/api/v1 # default: the active company's endpoint
101
+ learnstat config set model openai/gpt-4o-mini
102
+ learnstat config list # saved accounts learnstat config use <name> # switch
103
+ learnstat config test # one tiny request learnstat config show # key is masked
104
+ ```
105
+
106
+ Accounts are stored in `~/.learnstat/config.json` (`learnstat config path` prints the location), readable only by you where the OS allows it. The environment variables `LEARNSTAT_API_KEY`, `LEARNSTAT_BASE_URL` and `LEARNSTAT_MODEL` override the active account for one run.
107
+
108
+ With an AI configured, explanations are tailored to your dataset, `/review` checks code for issues the rules miss, and the AI can propose fixes for errors the rules can't handle. Without it, everything else still works offline. Pass `--no-ai` to switch it off for one run.
51
109
 
52
110
  ## Use it
53
111
 
@@ -85,6 +143,7 @@ learnstat check analysis.py # suggestions only, nothing is executed
85
143
  learnstat watch analysis.py # re-checks every time you save the file
86
144
  learnstat run analysis.py # runs with suggestions and guarded recovery
87
145
  learnstat repl --data survey.csv # interactive, with /commands
146
+ learnstat config show # AI settings (see "Add an AI")
88
147
  ```
89
148
 
90
149
  ### Plain Python
@@ -141,7 +200,11 @@ learnstat/
141
200
  knowledge.py offline explanations behind /describe, /alternatives, /learn
142
201
  recovery.py error diagnosis, fix proposal, validation, bounded retry
143
202
  safety.py detection of destructive side effects
144
- llm.py optional Claude backend
203
+ llm.py optional AI backend (OpenAI-compatible endpoint)
204
+ config.py saved AI accounts: provider, api_key, base_url, model
205
+ providers.py presets for the AI companies
206
+ setup.py guided terminal setup (company -> key -> model -> check)
207
+ guide.py the numbered home menu students use
145
208
  session.py ties it together; read_csv/track/check/run
146
209
  commands.py slash commands
147
210
  ipython_ext.py %load_ext learnstat
@@ -1,164 +1,197 @@
1
- Metadata-Version: 2.4
2
- Name: learnstat
3
- Version: 0.1.0
4
- Summary: An AI-assisted learning companion for statistical analysis with pandas, NumPy, SciPy and Matplotlib.
5
- License: MIT
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- Requires-Dist: pandas>=2.0
9
- Requires-Dist: numpy>=1.24
10
- Provides-Extra: viz
11
- Requires-Dist: matplotlib>=3.7; extra == "viz"
12
- Provides-Extra: stats
13
- Requires-Dist: scipy>=1.10; extra == "stats"
14
- Provides-Extra: ai
15
- Requires-Dist: anthropic>=1.0; extra == "ai"
16
- Provides-Extra: jupyter
17
- Requires-Dist: ipython>=8.0; extra == "jupyter"
18
- Provides-Extra: all
19
- Requires-Dist: matplotlib>=3.7; extra == "all"
20
- Requires-Dist: scipy>=1.10; extra == "all"
21
- Requires-Dist: anthropic>=1.0; extra == "all"
22
- Requires-Dist: ipython>=8.0; extra == "all"
23
- Provides-Extra: dev
24
- Requires-Dist: pytest>=7; extra == "dev"
25
- Requires-Dist: matplotlib>=3.7; extra == "dev"
26
- Requires-Dist: scipy>=1.10; extra == "dev"
27
- Requires-Dist: ipython>=8.0; extra == "dev"
28
-
29
- # learnstat
30
-
31
- An AI-assisted learning companion for statistical analysis in Python.
32
-
33
- You write ordinary **pandas / NumPy / SciPy / Matplotlib** code. learnstat:
34
-
35
- 1. **Understands your dataset.** It profiles the data once and keeps a Markdown memory file of it.
36
- 2. **Suggests better approaches as you write.** For example, it flags a pie chart of 12 categories and suggests a sorted bar chart, explaining why.
37
- 3. **Explains itself** through `/describe`, `/alternatives`, `/learn`, `/memory` and `/fix`.
38
- 4. **Recovers from mechanical errors.** It fixes typos in column names, methods and keywords, plus missing imports and unclosed brackets, and shows you every change.
39
- 5. **Leaves analytical decisions to you.** Data-quality and statistical-method problems are explained but never "fixed" automatically.
40
-
41
- It's not a new language. Everything you learn uses the real pandas, SciPy and Matplotlib APIs, so the skills carry over to the rest of the ecosystem.
42
-
43
- ## Install
44
-
45
- ```bash
46
- pip install -e ".[all]" # pandas, numpy, matplotlib, scipy, anthropic, ipython
47
- pip install -e . # core only: profiling, rules, recovery (no AI)
48
- ```
49
-
50
- The AI features are optional. With the `anthropic` package and credentials set up (`ANTHROPIC_API_KEY` or `ant auth login`), explanations get tailored to your dataset, Claude reviews code with `/review`, and Claude can propose fixes for errors the rules can't handle. Without them, everything else still works offline. The default model is `claude-opus-5-5`; set `LEARNSTAT_MODEL` to choose another.
51
-
52
- ## Use it
53
-
54
- ### Jupyter
55
-
56
- ```python
57
- %load_ext learnstat
58
- import learnstat as ls
59
- df = ls.read_csv("survey.csv") # a normal DataFrame, now profiled into .learnstat/survey.md
60
- ```
61
-
62
- ```python
63
- df["country"].value_counts().plot.pie()
64
- # [!] Suggestion #1 (line 1): Pie chart with 12 categories
65
- # Issue: `country` has 12 categories; slices this numerous are hard to compare by angle.
66
- # Instead: A horizontal bar chart of the counts, sorted by size.
67
- # Why: Bars share a common baseline ...
68
- # How: counts = df['country'].value_counts() ...
69
- ```
70
-
71
- ```
72
- /describe <- the concept, why it fits this data, when another method is better
73
- /accept <- puts the suggested code in a NEW cell; your cell is untouched
74
- /reject only 3 countries matter here <- recorded in memory, not suggested again
75
- ```
76
-
77
- When a cell raises an error, learnstat diagnoses the failing statement. If it's a mechanical mistake, learnstat corrects it, re-runs only that statement and the ones after it, and prints the diff. A cell with a syntax error gets a corrected copy placed in the next cell for you to review.
78
-
79
- ### Command line
80
-
81
- ```bash
82
- cd examples && python make_survey.py
83
- learnstat profile survey.csv # writes .learnstat/survey.md and prints it
84
- learnstat check analysis.py # suggestions only, nothing is executed
85
- learnstat watch analysis.py # re-checks every time you save the file
86
- learnstat run analysis.py # runs with suggestions and guarded recovery
87
- learnstat repl --data survey.csv # interactive, with /commands
88
- ```
89
-
90
- ### Plain Python
91
-
92
- ```python
93
- import learnstat as ls
94
- df = ls.read_csv("survey.csv")
95
- ls.check("df['income'].mean()") # suggestions without running
96
- print(ls.command("/describe"))
97
-
98
- s = ls.Session(confirm=lambda q: input(q + " [y/N] ") == "y")
99
- s.ns["df"] = s.read_csv("survey.csv")
100
- result = s.run("df.groupBy('group')['score'].median()")
101
- print(result.final_code) # df.groupby(...)... your source is never modified
102
- ```
103
-
104
- ## Commands
105
-
106
- | Command | What it does |
107
- |---|---|
108
- | `/describe [id]` | Explains the latest (or given) suggestion, or the latest error: the concept, the purpose of the function, why it fits this data, and when something else is better |
109
- | `/alternatives [id]` | Other ways to reach the same goal, with trade-offs |
110
- | `/learn [topic]` | A short lesson with an exercise on your own data |
111
- | `/fix` | The last error diagnosis; in interactive mode, a retry of the failed statement |
112
- | `/memory [show\|note\|decide\|refresh]` | View or update the dataset's persistent profile |
113
- | `/accept [id]`, `/reject [id] [why]` | Accept or reject a suggestion; the decision is saved in memory |
114
- | `/suggestions`, `/review`, `/ask`, `/status`, `/help` | |
115
-
116
- ## Dataset memory
117
-
118
- `ls.read_csv` profiles the data and writes two files to `.learnstat/`:
119
-
120
- - `survey.md`: columns, types, missing values, likely column meanings (marked as guesses), distributions, relationships, data-quality issues, suggested analyses, assumptions, **your analytical decisions** and notes.
121
- - `survey.json`: the machine-readable cache. It includes a content fingerprint, so the data is only re-profiled when it actually changes. Decisions and notes carry over when that happens.
122
-
123
- ## How error recovery stays safe
124
-
125
- - Code runs **one top-level statement at a time**. When statement *k* fails, only statement *k* is corrected and retried, so earlier side effects are never repeated.
126
- - Errors are classified as **syntax, name, attribute, argument, column, data-quality, statistical-method, environment** or other runtime errors.
127
- - Only mechanical mistakes are corrected automatically, and only to a unique, high-similarity match.
128
- - Before a fix runs, it must compile. It must not introduce file, shell or network operations, must not change which variables are assigned, must not add data-altering calls (`dropna`, `fillna`, `astype` and so on), and must not change the statistical method.
129
- - AI-proposed fixes always need your confirmation. So does retrying a loop or block, since that could repeat side effects.
130
- - Retries are bounded (`max_attempts`, 3 by default). If the same error comes back, recovery stops and gives you a concrete next step.
131
- - Code that deletes or overwrites files, runs shell commands or opens network connections only runs after you confirm.
132
- - **This is a policy layer, not a sandbox.** Your code runs in your Python process with your permissions, exactly as if you had run it yourself.
133
-
134
- ## Project layout
135
-
136
- ```
137
- learnstat/
138
- profile.py dataset profiling (no AI)
139
- memory.py Markdown + JSON dataset memory
140
- advisor.py AST-based, data-aware suggestion rules
141
- knowledge.py offline explanations behind /describe, /alternatives, /learn
142
- recovery.py error diagnosis, fix proposal, validation, bounded retry
143
- safety.py detection of destructive side effects
144
- llm.py optional Claude backend
145
- session.py ties it together; read_csv/track/check/run
146
- commands.py slash commands
147
- ipython_ext.py %load_ext learnstat
148
- cli.py learnstat profile|check|watch|run|repl
149
- ```
150
-
151
- Add a rule by writing a function `(call, resolver, code) -> Suggestion | None` in `advisor.py`, appending it to `RULES`, and adding its concept to `knowledge.py`.
152
-
153
- ## Roadmap
154
-
155
- - A language-server (LSP) frontend for suggestions while typing in VS Code and JupyterLab. The advisor is already editor-agnostic.
156
- - More rules: multiple-comparison corrections, chi-square expected counts, normality checks before parametric tests, time-series plotting.
157
- - Learning-progress tracking, so advice fades as the user masters a concept.
158
-
159
- ## Tests
160
-
161
- ```bash
162
- pip install -e ".[dev]"
163
- pytest
164
- ```
1
+ # learnstat
2
+
3
+ An AI-assisted learning companion for statistical analysis in Python.
4
+
5
+ You write ordinary **pandas / NumPy / SciPy / Matplotlib** code. learnstat:
6
+
7
+ 1. **Understands your dataset.** It profiles the data once and keeps a Markdown memory file of it.
8
+ 2. **Suggests better approaches as you write.** For example, it flags a pie chart of 12 categories and suggests a sorted bar chart, explaining why.
9
+ 3. **Explains itself** through `/describe`, `/alternatives`, `/learn`, `/memory` and `/fix`.
10
+ 4. **Recovers from mechanical errors.** It fixes typos in column names, methods and keywords, plus missing imports and unclosed brackets, and shows you every change.
11
+ 5. **Leaves analytical decisions to you.** Data-quality and statistical-method problems are explained but never "fixed" automatically.
12
+
13
+ It's not a new language. Everything you learn uses the real pandas, SciPy and Matplotlib APIs, so the skills carry over to the rest of the ecosystem.
14
+
15
+ [![PyPI](https://img.shields.io/pypi/v/learnstat)](https://pypi.org/project/learnstat/)
16
+
17
+ ## Install
18
+
19
+ From PyPI: <https://pypi.org/project/learnstat/>
20
+
21
+ ```bash
22
+ pip install "learnstat[all]" # from PyPI
23
+ pip install -e ".[all]" # pandas, numpy, matplotlib, scipy, ipython
24
+ pip install -e . # core only: profiling, rules, recovery
25
+ ```
26
+
27
+ ### Quick start (no commands to learn)
28
+
29
+ ```bash
30
+ pip install learnstat
31
+ learnstat
32
+ ```
33
+
34
+ That is all. learnstat walks you through everything in plain English:
35
+
36
+ 1. **Pick your AI** (optional): choose the company, paste your key, choose a model. learnstat tests it and says OK or what is wrong.
37
+ 2. **Choose your data**: press Enter and a normal file window opens (CSV or Excel), or drag the file into the terminal.
38
+ 3. **Pick what to do from a menu** by typing a number:
39
+
40
+ ```
41
+ 1) See a summary of my data
42
+ 2) Ask the AI a question about my data
43
+ 3) Get suggestions for a Python script
44
+ 4) Run a Python script with automatic help
45
+ 5) Write Python code here (my data is ready as "df")
46
+ 6) Learn a statistics topic
47
+ 7) Load a different data file
48
+ 8) Change the AI (company, key, model)
49
+ 9) Help
50
+ ```
51
+
52
+ Nothing else needs to be memorised: every option asks for what it needs, and option 9 explains the menu. Skip the AI and everything still works with built-in rules.
53
+
54
+ ### Add an AI (optional)
55
+
56
+ Just run `learnstat`. If no AI is set up yet it offers a guided setup, and you can repeat it any time with `learnstat setup` (or `/ai` inside a session):
57
+
58
+ 1. **Choose the company**: OpenAI, Anthropic, Google Gemini, xAI, Mistral, DeepSeek, Groq, Together, OpenRouter, Ollama, LM Studio, or any other OpenAI-compatible endpoint.
59
+ 2. **Paste your API key**. The input is hidden, and local servers such as Ollama need no key.
60
+ 3. **Pick a model** from the list your key can actually use. Type part of a name to filter.
61
+ 4. **learnstat checks it** with a live test request and shows `OK` or the exact problem (rejected key, unknown model, no connection, quota), with options to fix it.
62
+ 5. It saves the account and starts the interactive session.
63
+
64
+ Several accounts can be saved and switched: run `learnstat setup` and pick a number, or use `/ai use <name>` in a session. The AI features need no extra package.
65
+
66
+ For scripts and CI there is a non-interactive route:
67
+
68
+ ```bash
69
+ learnstat config set api_key sk-your-key
70
+ learnstat config set base_url https://openrouter.ai/api/v1 # default: the active company's endpoint
71
+ learnstat config set model openai/gpt-4o-mini
72
+ learnstat config list # saved accounts learnstat config use <name> # switch
73
+ learnstat config test # one tiny request learnstat config show # key is masked
74
+ ```
75
+
76
+ Accounts are stored in `~/.learnstat/config.json` (`learnstat config path` prints the location), readable only by you where the OS allows it. The environment variables `LEARNSTAT_API_KEY`, `LEARNSTAT_BASE_URL` and `LEARNSTAT_MODEL` override the active account for one run.
77
+
78
+ With an AI configured, explanations are tailored to your dataset, `/review` checks code for issues the rules miss, and the AI can propose fixes for errors the rules can't handle. Without it, everything else still works offline. Pass `--no-ai` to switch it off for one run.
79
+
80
+ ## Use it
81
+
82
+ ### Jupyter
83
+
84
+ ```python
85
+ %load_ext learnstat
86
+ import learnstat as ls
87
+ df = ls.read_csv("survey.csv") # a normal DataFrame, now profiled into .learnstat/survey.md
88
+ ```
89
+
90
+ ```python
91
+ df["country"].value_counts().plot.pie()
92
+ # [!] Suggestion #1 (line 1): Pie chart with 12 categories
93
+ # Issue: `country` has 12 categories; slices this numerous are hard to compare by angle.
94
+ # Instead: A horizontal bar chart of the counts, sorted by size.
95
+ # Why: Bars share a common baseline ...
96
+ # How: counts = df['country'].value_counts() ...
97
+ ```
98
+
99
+ ```
100
+ /describe <- the concept, why it fits this data, when another method is better
101
+ /accept <- puts the suggested code in a NEW cell; your cell is untouched
102
+ /reject only 3 countries matter here <- recorded in memory, not suggested again
103
+ ```
104
+
105
+ When a cell raises an error, learnstat diagnoses the failing statement. If it's a mechanical mistake, learnstat corrects it, re-runs only that statement and the ones after it, and prints the diff. A cell with a syntax error gets a corrected copy placed in the next cell for you to review.
106
+
107
+ ### Command line
108
+
109
+ ```bash
110
+ cd examples && python make_survey.py
111
+ learnstat profile survey.csv # writes .learnstat/survey.md and prints it
112
+ learnstat check analysis.py # suggestions only, nothing is executed
113
+ learnstat watch analysis.py # re-checks every time you save the file
114
+ learnstat run analysis.py # runs with suggestions and guarded recovery
115
+ learnstat repl --data survey.csv # interactive, with /commands
116
+ learnstat config show # AI settings (see "Add an AI")
117
+ ```
118
+
119
+ ### Plain Python
120
+
121
+ ```python
122
+ import learnstat as ls
123
+ df = ls.read_csv("survey.csv")
124
+ ls.check("df['income'].mean()") # suggestions without running
125
+ print(ls.command("/describe"))
126
+
127
+ s = ls.Session(confirm=lambda q: input(q + " [y/N] ") == "y")
128
+ s.ns["df"] = s.read_csv("survey.csv")
129
+ result = s.run("df.groupBy('group')['score'].median()")
130
+ print(result.final_code) # df.groupby(...)... your source is never modified
131
+ ```
132
+
133
+ ## Commands
134
+
135
+ | Command | What it does |
136
+ |---|---|
137
+ | `/describe [id]` | Explains the latest (or given) suggestion, or the latest error: the concept, the purpose of the function, why it fits this data, and when something else is better |
138
+ | `/alternatives [id]` | Other ways to reach the same goal, with trade-offs |
139
+ | `/learn [topic]` | A short lesson with an exercise on your own data |
140
+ | `/fix` | The last error diagnosis; in interactive mode, a retry of the failed statement |
141
+ | `/memory [show\|note\|decide\|refresh]` | View or update the dataset's persistent profile |
142
+ | `/accept [id]`, `/reject [id] [why]` | Accept or reject a suggestion; the decision is saved in memory |
143
+ | `/suggestions`, `/review`, `/ask`, `/status`, `/help` | |
144
+
145
+ ## Dataset memory
146
+
147
+ `ls.read_csv` profiles the data and writes two files to `.learnstat/`:
148
+
149
+ - `survey.md`: columns, types, missing values, likely column meanings (marked as guesses), distributions, relationships, data-quality issues, suggested analyses, assumptions, **your analytical decisions** and notes.
150
+ - `survey.json`: the machine-readable cache. It includes a content fingerprint, so the data is only re-profiled when it actually changes. Decisions and notes carry over when that happens.
151
+
152
+ ## How error recovery stays safe
153
+
154
+ - Code runs **one top-level statement at a time**. When statement *k* fails, only statement *k* is corrected and retried, so earlier side effects are never repeated.
155
+ - Errors are classified as **syntax, name, attribute, argument, column, data-quality, statistical-method, environment** or other runtime errors.
156
+ - Only mechanical mistakes are corrected automatically, and only to a unique, high-similarity match.
157
+ - Before a fix runs, it must compile. It must not introduce file, shell or network operations, must not change which variables are assigned, must not add data-altering calls (`dropna`, `fillna`, `astype` and so on), and must not change the statistical method.
158
+ - AI-proposed fixes always need your confirmation. So does retrying a loop or block, since that could repeat side effects.
159
+ - Retries are bounded (`max_attempts`, 3 by default). If the same error comes back, recovery stops and gives you a concrete next step.
160
+ - Code that deletes or overwrites files, runs shell commands or opens network connections only runs after you confirm.
161
+ - **This is a policy layer, not a sandbox.** Your code runs in your Python process with your permissions, exactly as if you had run it yourself.
162
+
163
+ ## Project layout
164
+
165
+ ```
166
+ learnstat/
167
+ profile.py dataset profiling (no AI)
168
+ memory.py Markdown + JSON dataset memory
169
+ advisor.py AST-based, data-aware suggestion rules
170
+ knowledge.py offline explanations behind /describe, /alternatives, /learn
171
+ recovery.py error diagnosis, fix proposal, validation, bounded retry
172
+ safety.py detection of destructive side effects
173
+ llm.py optional AI backend (OpenAI-compatible endpoint)
174
+ config.py saved AI accounts: provider, api_key, base_url, model
175
+ providers.py presets for the AI companies
176
+ setup.py guided terminal setup (company -> key -> model -> check)
177
+ guide.py the numbered home menu students use
178
+ session.py ties it together; read_csv/track/check/run
179
+ commands.py slash commands
180
+ ipython_ext.py %load_ext learnstat
181
+ cli.py learnstat profile|check|watch|run|repl
182
+ ```
183
+
184
+ Add a rule by writing a function `(call, resolver, code) -> Suggestion | None` in `advisor.py`, appending it to `RULES`, and adding its concept to `knowledge.py`.
185
+
186
+ ## Roadmap
187
+
188
+ - A language-server (LSP) frontend for suggestions while typing in VS Code and JupyterLab. The advisor is already editor-agnostic.
189
+ - More rules: multiple-comparison corrections, chi-square expected counts, normality checks before parametric tests, time-series plotting.
190
+ - Learning-progress tracking, so advice fades as the user masters a concept.
191
+
192
+ ## Tests
193
+
194
+ ```bash
195
+ pip install -e ".[dev]"
196
+ pytest
197
+ ```
@@ -21,7 +21,7 @@ from .recovery import Executor, RunResult
21
21
  from .session import Session, get_session, set_session
22
22
  from .suggestions import Suggestion
23
23
 
24
- __version__ = "0.1.0"
24
+ __version__ = "0.2.1"
25
25
 
26
26
 
27
27
  def read_csv(path, name: str | None = None, **kwargs):