Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 29 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ used only when you explicitly download a tokenizer, from the app's Resources vie

---

## Features (v0.1)
## Features

- Parse PDF, PPTX, DOCX, TXT, MD files
- Count tokens for 10+ LLM models (GPT-4o, Claude, Gemini, DeepSeek, Llama, Mistral)
- Count tokens for 21 models across 7 providers (OpenAI, Anthropic, Google, DeepSeek,
Meta, Mistral, Qwen)
- Context window usage percentage with fit/chunk analysis
- Compare cost and context fit across multiple models side by side, with per-model and
portfolio cost projection
- Self-Host Fit Check: estimate whether an open-weight model actually fits on your own
GPU, Apple Silicon Mac, or cloud instance, given quantization, KV cache precision,
context length, and concurrency
- Local cost estimation per model, with no data ever sent anywhere
- Model Registry: browse every supported model's context window, pricing, and
architecture details
- Resources view: see which tokenizers are downloaded, where they live on disk, and
their size, with a one-click download for anything missing
- CLI and Desktop GUI (CustomTkinter)
- CLI and a native desktop app (React + pywebview) for Windows, macOS, and Linux

---

Expand All @@ -43,29 +51,36 @@ the first time you run it. Click **More info → Run anyway** to continue. This
means the publisher isn't verified, not that the app is unsafe — the source is right
here in this repo.

**macOS Gatekeeper:** for the same reason, macOS may refuse to open the app with an
"is damaged and can't be opened" dialog. Run `xattr -cr NoRefund.app` in Terminal after
extracting it — see `packaging/README.md` for details.

---

## Quick Start

```bash
# Install
pip install -e ".[dev]"
cd frontend && npm install && npm run build && cd ..

# CLI
norefund path/to/file.pdf --model openai:gpt-4o

# GUI
# Desktop app
norefund --gui
```

For frontend development with hot reload, see `CLAUDE.md`'s Commands section.

---

## Project Structure

```
src/norefund/
main.py # Entry point
gui/ # CustomTkinter GUI
main.py # CLI entry point + GUI launch
desktop/ # pywebview shell and JS bridge (api.py, app.py, dto.py, jobs.py)
core/
parsing.py # Document text extraction
tokenization.py # Tokenizer backends
Expand All @@ -74,27 +89,21 @@ src/norefund/
service.py # Orchestration
config/
default_models.yaml # Local model registry
frontend/ # React UI (Calculator, Parser, Compare, Fit Check, Registry, Resources)
tests/
```

---

## Supported Models

| Model | Provider | Context Window |
|---|---|---|
| GPT-4o | OpenAI | 128K |
| GPT-4o Mini | OpenAI | 128K |
| GPT-4.1 | OpenAI | 1M |
| Claude 3.5 Sonnet | Anthropic | 200K |
| Claude 3 Haiku | Anthropic | 200K |
| Gemini 2.0 Flash | Google | 1M |
| Gemini 1.5 Pro | Google | 2M |
| DeepSeek V3 | DeepSeek | 128K |
| Llama 3 8B | Meta (self-hosted) | 8K |
| Mistral 7B | Mistral (self-hosted) | 32K |

**Tokenizer accuracy:** OpenAI models, DeepSeek V3, Llama 3, and Mistral use each
21 models across 7 providers — OpenAI, Anthropic, Google, DeepSeek, Meta, Mistral, and
Qwen, spanning both hosted API models and self-hosted open-weight models. The
in-app **Model Registry** view is the source of truth for the current list, context
windows, and pricing (`config/default_models.yaml` backs it, so it never drifts from
what the app actually uses).

**Tokenizer accuracy:** OpenAI models, DeepSeek V3, Llama, Qwen, and Mistral use each
provider's real tokenizer. Anthropic and Google don't publish a local tokenizer for
Claude or Gemini, so those counts are a `cl100k_base` approximation — the app marks
them `(approx.)` wherever they're shown.
Expand Down
1 change: 0 additions & 1 deletion packaging/norefund.spec
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ hiddenimports += collect_submodules("gi.overrides")
# edgechromium on Windows; macOS has no choice of backend).
excludes = [
"tkinter",
"customtkinter",
"PyQt5",
"PyQt6",
"PySide2",
Expand Down
5 changes: 0 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ classifiers = [
]

dependencies = [
"customtkinter>=5.2.2",
"tiktoken>=0.7.0",
"pypdf>=4.3.1",
"python-pptx>=1.0.2",
Expand All @@ -30,7 +29,6 @@ dependencies = [
"platformdirs>=4.0",
"huggingface_hub>=0.25.0",
"keyring>=25.0",
"Pillow>=10.0",
"reportlab>=4.0",
"pywebview>=6.2.1",
]
Expand All @@ -42,9 +40,6 @@ dev = [
"pytest>=9.1.1",
"pyinstaller>=6.21.0",
]
dnd = [
"tkinterdnd2>=0.4.2",
]
linux = [
"pygobject>=3.50",
]
Expand Down
Empty file removed src/norefund/gui/__init__.py
Empty file.
84 changes: 0 additions & 84 deletions src/norefund/gui/app.py

This file was deleted.

Loading