# abhyasa


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

<img src="https://raw.githubusercontent.com/vedicreader/abhyasa/main/design/logo/abhyasa-icon.png" width="128" alt="abhyasa logo">

[![Download for
macOS](https://img.shields.io/badge/Download_for_macOS-Abhyasa.zip-2F2722?style=for-the-badge&logo=apple&logoColor=white)](https://github.com/vedicreader/abhyasa/releases/download/mac-v0.0.10/Abhyasa.zip)
[All releases](https://github.com/vedicreader/abhyasa/releases)

<figure>
<a
href="https://github.com/vedicreader/abhyasa/actions/workflows/test.yaml"><img
src="https://github.com/vedicreader/abhyasa/actions/workflows/test.yaml/badge.svg" /></a>
<figcaption>CI</figcaption>
</figure>

abhyasa (अभ्यास) is Sanskrit for “steady practice”. It is a tutor for
people who want to learn well and keep their minds active. It asks you
questions, and it never gives the answer first. You answer by voice or
in text, and you can think aloud. The tutor grades your reasoning, not
only the result.

abhyasa keeps a learner model for each concept: how deep you know it,
how well you recall it now, and when you must review it. It also learns
how you learn. If code helps you more than equations, it uses code to
teach a weak concept again. Sometimes it uses a different way on
purpose, so that you get better at that way too.

The app needs macOS 26 on Apple Silicon. The tutor uses a language
model. You choose it from a list in Settings, for example Claude, GPT or
a local model. Your answers go to that model. Speech to text runs on
your Mac by default. All other data stays in your vault on your Mac.

## Download

Click the Download for macOS button at the top. Then do these steps:

1.  Unzip `Abhyasa.zip`.
2.  Move `Abhyasa.app` to Applications.
3.  Open Abhyasa.
4.  Wait for the first start. The app uses uv to get Python and the
    abhyasa package one time. This step takes some minutes.

The app needs uv. If you do not have uv, install it with
`brew install uv`. Each release has a Developer ID signature. Apple
notarized each release.

### Homebrew

``` sh
brew install --cask vedicreader/tap/abhyasa
```

The cask also installs uv. To get a new version, run
`brew upgrade --cask abhyasa`. To remove the app, its settings and its
Python environment, run `brew uninstall --zap --cask abhyasa`. The zap
does not remove your vault, because other tools use it too.

## How it works

Each question goes through the same six steps:

1.  Pick. The code chooses the next concept and the depth. A due review
    comes first. Then a new concept comes, if you know its
    prerequisites. The app shows the reason.
2.  Ask. A model writes one question at that depth, in one way to learn,
    such as code or an analogy. It also writes a correct answer and a
    rubric. You do not see them.
3.  Struggle. You answer. If your answer is wrong, the tutor shows your
    first error. It gives a small hint, but not the fix. You can ask for
    hints, one at a time.
4.  Grade. The model grades your answer and your think-aloud. The code
    grades choice questions and code exercises.
5.  Update. The result and your confidence change the floor, the ceiling
    and the next review date of the concept.
6.  Teach. After a miss, the tutor teaches the smallest step that fixes
    your first error. Then it asks a check question.

When you say “I don’t know X”, X becomes a concept, and it comes first
the next time. The Strengths page (⌥G) shows your strong concepts, your
weak spots with their reasons, and the ways that you learn best.
“Practice my weak spots” starts a session on your weakest concepts.

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr>
<th>term</th>
<th>meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>concept</td>
<td>one idea that the tutor can ask you about</td>
</tr>
<tr>
<td>depth</td>
<td>0 unseen, 1 recognise, 2 recall, 3 explain, 4 apply, 5 transfer</td>
</tr>
<tr>
<td>floor</td>
<td>the highest depth that you pass every time</td>
</tr>
<tr>
<td>ceiling</td>
<td>the lowest depth where you failed</td>
</tr>
<tr>
<td>attempt</td>
<td>one answer, kept as a document in your vault</td>
</tr>
<tr>
<td>session</td>
<td>one sitting of questions. abhyasa saves it after each step, so you
can continue it after a restart</td>
</tr>
<tr>
<td>journey</td>
<td>a goal and a path to it, with one concept for each step. You can see
and change the path</td>
</tr>
<tr>
<td>profile</td>
<td>what abhyasa knows about you: your background, your goals, the
examples that help you and your pace. You can see and change all of
it</td>
</tr>
<tr>
<td>way to learn</td>
<td>code, maths, an analogy, a worked example, a picture or plain words.
Each result counts for the way that the question used</td>
</tr>
<tr>
<td>gap</td>
<td>an idea that you said you do not know. It comes before the concept
where you said it, but it does not block that concept</td>
</tr>
<tr>
<td>hint</td>
<td>one step on a ladder of six, from the least to the most help</td>
</tr>
<tr>
<td>lesson</td>
<td>the smallest step that the tutor teaches after a miss. “Another way”
(⌥A) teaches it again in a different way</td>
</tr>
<tr>
<td>demo</td>
<td>an interactive figure for one concept. You predict, you lock in, and
then you change the inputs</td>
</tr>
</tbody>
</table>

## Keyboard shortcuts

All keys are for the left hand. ⌥ is the Option key. To see all the
keys, press ⌥F, or press ? outside a text box.

If you use [Sanketa](https://github.com/vedicreader/sanketa), it shows
the same keys when abhyasa is in front. abhyasa writes the pack
`~/.config/sanketa/packs/abhyasa.toml` when it starts. It does not write
over a pack that you made.

## Run from source

Install the package and its dependencies:

``` sh
uv sync
```

Start the web app on <http://127.0.0.1:5077>:

``` sh
uv run abhyasa
```

The app answers only requests from this Mac. These variables change the
defaults:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr>
<th>variable</th>
<th>what it sets</th>
<th>default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ABHYASA_VAULT</code></td>
<td>the vault file</td>
<td>your vault: <code>$VISHALAKSHI_VAULT</code>, then
<code>~/.vishalakshi/vault.db</code></td>
</tr>
<tr>
<td><code>ABHYASA_MODEL</code></td>
<td>the model id for questions, grades, hints and lessons. Choose the
model in Settings.</td>
<td><code>claude/sonnet</code> (Claude Sonnet)</td>
</tr>
<tr>
<td><code>ABHYASA_STT</code></td>
<td>the speech-to-text engine: <code>gemma</code>, <code>whisper</code>,
<code>parakeet</code>, <code>openai</code> or
<code>mlx:&lt;repo&gt;</code>. It has priority over the Settings
page.</td>
<td>the Settings page, then <code>gemma</code></td>
</tr>
</tbody>
</table>

## Other ways to use it

The web app, the terminal and the notebooks use the same tutor and the
same data.

### The web app

The web app is made from blocks in `abhyasa/blocks`:

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr>
<th>block</th>
<th>what it does</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>today</code></td>
<td>the home page: continue, your journeys, the next review and this
week</td>
</tr>
<tr>
<td><code>journeys</code></td>
<td>say a goal, and the tutor makes a path of steps. You can move, skip,
add or split a step</td>
</tr>
<tr>
<td><code>history</code></td>
<td>your learning: each past session with what changed, and what you
learned each week. Continue (⌥C) is in the top bar</td>
</tr>
<tr>
<td><code>profile</code></td>
<td>what abhyasa knows about you: a short first conversation, your
edits, and the changes that the tutor makes, each with its reason</td>
</tr>
<tr>
<td><code>strengths</code></td>
<td>your strong concepts, your weak spots and the ways that you learn
best (⌥G)</td>
</tr>
<tr>
<td><code>session</code></td>
<td>one sitting with the tutor: one question at a time, with hints,
confidence and “I don’t know”</td>
</tr>
<tr>
<td><code>voice</code></td>
<td>a microphone for each text box. ⌥D speaks into the box that has the
focus, on any page</td>
</tr>
<tr>
<td><a
href="https://vedicreader.github.io/abhyasa/voice.html#settings"><code>settings</code></a></td>
<td>the speech model, the OpenAI key and the model for each tutor task.
You choose each model from a list of names</td>
</tr>
<tr>
<td><code>concepts</code></td>
<td>the list of concepts, and one page for each concept with its
state</td>
</tr>
<tr>
<td><code>graph</code></td>
<td>the concept graph. You can color it by depth, by how well you know
each concept, by subject or by due date</td>
</tr>
<tr>
<td><code>search</code></td>
<td>one search over the <code>learning</code> shelf and the other
shelves of your vault</td>
</tr>
<tr>
<td><code>add</code></td>
<td>add concepts from a text, a vault document or vedicreader</td>
</tr>
<tr>
<td><code>demo</code></td>
<td>interactive demos from rupaka: on a concept page, under a lesson
after a miss, and one page for each demo</td>
</tr>
<tr>
<td><code>keys</code></td>
<td>the keyboard shortcuts (⌥F)</td>
</tr>
</tbody>
</table>

Each page shows where you are, above its title. Esc goes up one level,
⌥T goes to Today, and Back and Forward work.

### ramabana

In the ramabana terminal agent, the `/learn` extension gives you the
tutor next to your code. To turn it on, make the file
`~/.config/ramabana/extensions/abhyasa.py` with this line:

``` python
from abhyasa.rama import setup
```

### Notebooks

In leela or Jupyter,
[`learn`](https://vedicreader.github.io/abhyasa/nb.html#learn) shows a
question card.
[`exercise`](https://vedicreader.github.io/abhyasa/nb.html#exercise)
gives a code exercise, and its tests run in the kernel.

``` python
from abhyasa.nb import learn, exercise
learn('reciprocal-rank-fusion')
ex = exercise('reciprocal-rank-fusion')
```

## Where the data is

All data is on the `learning` shelf of your vault. Each concept, attempt
and session is one document in the vault. Thus your other tools can
search it. The tests use a vault in a temporary folder. They never open
your real vault.

## Demos

Some ideas are easier to see than to read. A demo is one interactive
figure from [rupaka](https://github.com/vedicreader/rupaka). It asks you
to predict first. It hides the result until you lock in (⌘↩). Then the
controls work, and the last line asks a new question.

- The tutor makes a demo after two misses on a concept with the same
  kind of error. It also makes one for a concept with `visual: true` in
  its meta. The model writes the demo as data. rupaka checks it in a
  headless browser. You do not wait for it.
- After a miss on a concept that has a demo, the session shows the demo
  under the lesson.
- “Show me a demo” (⌥E) on a concept page shows the newest demo, or
  makes one.
- abhyasa keeps each prediction as an attempt with `kind='demo'`. A
  prediction changes the learner model of the concept, as an answer
  does. A prediction with a reason counts at depth 3 (explain). A
  prediction without a reason counts at depth 2 (recall).

`abhyasa.demo.import_gallery(learning)` keeps the rupaka gallery demos,
such as vowel sandhi, for the concepts that match.

## Example

This example runs offline.
[`temp_learning`](https://vedicreader.github.io/abhyasa/store.html#temp_learning)
makes a shelf in a temporary vault, and
[`Fake`](https://vedicreader.github.io/abhyasa/llm.html#fake) takes the
place of the model.

``` python
from abhyasa.store import temp_learning
from abhyasa.llm import Fake
from abhyasa.tutor import Tutor

lr = temp_learning()
lr.put('Ranking', 'Order items by a score.', 'ml')
fake = Fake({'You grade one answer': dict(correct=True, grade=8, first_error='', misconception='', feedback='Yes. Only the order counts.')},
            dflt=dict(question='Why can you compare ranks from two systems, but not their scores?', answer='Ranks share one scale.', rubric=['ranks share one scale']))
t = Tutor(lr, fake, context=False)
```

Ask the first question. `why` gives the reason for the choice, and
`method` gives the way to learn that the question uses. A new concept
starts at depth 3 (explain).

``` python
q = t.next()
assert q.why.startswith('next on the frontier: its prereqs are in place')   # a note on the way to learn can follow
assert q.depth == 3
print(q.question)
```

Answer with high confidence. A `solid` pass at depth 3 changes the floor
to 3.

``` python
r = t.answer(q.id, 'A rank is a position, and positions use the same scale in each list.', confidence=80)
assert r.outcome == 'solid'
assert lr.concept('ranking').floor == 3
```
