gufomind 1.0.0__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.
- gufomind-1.0.0/CHANGELOG.md +60 -0
- gufomind-1.0.0/LICENSE +9 -0
- gufomind-1.0.0/MANIFEST.in +12 -0
- gufomind-1.0.0/PKG-INFO +512 -0
- gufomind-1.0.0/README.md +456 -0
- gufomind-1.0.0/pyproject.toml +118 -0
- gufomind-1.0.0/setup.cfg +4 -0
- gufomind-1.0.0/src/gufomind/__init__.py +15 -0
- gufomind-1.0.0/src/gufomind/categorization/__init__.py +26 -0
- gufomind-1.0.0/src/gufomind/categorization/categorizer.py +413 -0
- gufomind-1.0.0/src/gufomind/categorization/seeds.py +83 -0
- gufomind-1.0.0/src/gufomind/categorization/service.py +238 -0
- gufomind-1.0.0/src/gufomind/chunking/__init__.py +25 -0
- gufomind-1.0.0/src/gufomind/chunking/splitter.py +252 -0
- gufomind-1.0.0/src/gufomind/cli.py +1299 -0
- gufomind-1.0.0/src/gufomind/composition.py +469 -0
- gufomind-1.0.0/src/gufomind/config.py +485 -0
- gufomind-1.0.0/src/gufomind/core/__init__.py +1 -0
- gufomind-1.0.0/src/gufomind/core/audit.py +67 -0
- gufomind-1.0.0/src/gufomind/core/errors.py +16 -0
- gufomind-1.0.0/src/gufomind/core/ids.py +50 -0
- gufomind-1.0.0/src/gufomind/core/models.py +404 -0
- gufomind-1.0.0/src/gufomind/core/ports.py +545 -0
- gufomind-1.0.0/src/gufomind/embeddings/__init__.py +11 -0
- gufomind-1.0.0/src/gufomind/embeddings/encoder.py +173 -0
- gufomind-1.0.0/src/gufomind/enrichment.py +162 -0
- gufomind-1.0.0/src/gufomind/importers/__init__.py +22 -0
- gufomind-1.0.0/src/gufomind/importers/base.py +100 -0
- gufomind-1.0.0/src/gufomind/importers/deepseek.py +257 -0
- gufomind-1.0.0/src/gufomind/importers/personal.py +213 -0
- gufomind-1.0.0/src/gufomind/importers/registry.py +49 -0
- gufomind-1.0.0/src/gufomind/ingestion.py +197 -0
- gufomind-1.0.0/src/gufomind/licensing/__init__.py +51 -0
- gufomind-1.0.0/src/gufomind/licensing/codec.py +84 -0
- gufomind-1.0.0/src/gufomind/licensing/fingerprint.py +45 -0
- gufomind-1.0.0/src/gufomind/licensing/key_format.py +139 -0
- gufomind-1.0.0/src/gufomind/licensing/manager.py +444 -0
- gufomind-1.0.0/src/gufomind/licensing/paths.py +39 -0
- gufomind-1.0.0/src/gufomind/licensing/public_key.py +8 -0
- gufomind-1.0.0/src/gufomind/licensing/server_client.py +178 -0
- gufomind-1.0.0/src/gufomind/licensing/signing.py +70 -0
- gufomind-1.0.0/src/gufomind/llm/__init__.py +33 -0
- gufomind-1.0.0/src/gufomind/llm/anthropic_client.py +396 -0
- gufomind-1.0.0/src/gufomind/llm/base_client.py +479 -0
- gufomind-1.0.0/src/gufomind/llm/deepseek_client.py +75 -0
- gufomind-1.0.0/src/gufomind/llm/ollama_client.py +438 -0
- gufomind-1.0.0/src/gufomind/llm/openai_client.py +104 -0
- gufomind-1.0.0/src/gufomind/llm/openai_compatible_client.py +259 -0
- gufomind-1.0.0/src/gufomind/llm/openrouter_client.py +130 -0
- gufomind-1.0.0/src/gufomind/py.typed +0 -0
- gufomind-1.0.0/src/gufomind/rag/__init__.py +9 -0
- gufomind-1.0.0/src/gufomind/rag/chat_service.py +226 -0
- gufomind-1.0.0/src/gufomind/rag/pipeline.py +326 -0
- gufomind-1.0.0/src/gufomind/rag/retriever.py +64 -0
- gufomind-1.0.0/src/gufomind/rag/style_transfer.py +422 -0
- gufomind-1.0.0/src/gufomind/settings_meta.py +234 -0
- gufomind-1.0.0/src/gufomind/storage/__init__.py +34 -0
- gufomind-1.0.0/src/gufomind/storage/jsonl_session_store.py +301 -0
- gufomind-1.0.0/src/gufomind/storage/lancedb_store.py +655 -0
- gufomind-1.0.0/src/gufomind/user_settings.py +259 -0
- gufomind-1.0.0/src/gufomind/web/__init__.py +8 -0
- gufomind-1.0.0/src/gufomind/web/app.py +194 -0
- gufomind-1.0.0/src/gufomind/web/deps.py +120 -0
- gufomind-1.0.0/src/gufomind/web/middleware.py +74 -0
- gufomind-1.0.0/src/gufomind/web/routes/__init__.py +22 -0
- gufomind-1.0.0/src/gufomind/web/routes/base.py +53 -0
- gufomind-1.0.0/src/gufomind/web/routes/chat.py +178 -0
- gufomind-1.0.0/src/gufomind/web/routes/health.py +17 -0
- gufomind-1.0.0/src/gufomind/web/routes/runtime.py +62 -0
- gufomind-1.0.0/src/gufomind/web/routes/sessions.py +82 -0
- gufomind-1.0.0/src/gufomind/web/routes/settings.py +574 -0
- gufomind-1.0.0/src/gufomind/web/routes/settings_ui.py +175 -0
- gufomind-1.0.0/src/gufomind/web/routes/ui.py +106 -0
- gufomind-1.0.0/src/gufomind/web/run.py +48 -0
- gufomind-1.0.0/src/gufomind/web/sse.py +28 -0
- gufomind-1.0.0/src/gufomind/web/static/app.css +462 -0
- gufomind-1.0.0/src/gufomind/web/static/app.js +198 -0
- gufomind-1.0.0/src/gufomind/web/static/htmx.min.js +1 -0
- gufomind-1.0.0/src/gufomind/web/static/marked.min.js +69 -0
- gufomind-1.0.0/src/gufomind/web/static/purify.min.js +7 -0
- gufomind-1.0.0/src/gufomind/web/templates/base.html +35 -0
- gufomind-1.0.0/src/gufomind/web/templates/chat.html +14 -0
- gufomind-1.0.0/src/gufomind/web/templates/partials/chat_view.html +21 -0
- gufomind-1.0.0/src/gufomind/web/templates/partials/session_list.html +23 -0
- gufomind-1.0.0/src/gufomind/web/templates/partials/settings_form.html +58 -0
- gufomind-1.0.0/src/gufomind/web/templates/settings.html +8 -0
- gufomind-1.0.0/src/gufomind.egg-info/SOURCES.txt +127 -0
- gufomind-1.0.0/tests/test_anthropic_client.py +382 -0
- gufomind-1.0.0/tests/test_audit.py +40 -0
- gufomind-1.0.0/tests/test_base_llm_client.py +169 -0
- gufomind-1.0.0/tests/test_categorization_service.py +343 -0
- gufomind-1.0.0/tests/test_categorizer.py +585 -0
- gufomind-1.0.0/tests/test_chat_service.py +309 -0
- gufomind-1.0.0/tests/test_cli.py +1807 -0
- gufomind-1.0.0/tests/test_composition.py +414 -0
- gufomind-1.0.0/tests/test_config.py +146 -0
- gufomind-1.0.0/tests/test_deepseek_client.py +356 -0
- gufomind-1.0.0/tests/test_encoder.py +222 -0
- gufomind-1.0.0/tests/test_enrichment.py +182 -0
- gufomind-1.0.0/tests/test_ids.py +45 -0
- gufomind-1.0.0/tests/test_importers.py +606 -0
- gufomind-1.0.0/tests/test_ingestion.py +376 -0
- gufomind-1.0.0/tests/test_license_manager.py +599 -0
- gufomind-1.0.0/tests/test_licensing.py +179 -0
- gufomind-1.0.0/tests/test_migration.py +234 -0
- gufomind-1.0.0/tests/test_models.py +187 -0
- gufomind-1.0.0/tests/test_ollama_client.py +327 -0
- gufomind-1.0.0/tests/test_openai_client.py +64 -0
- gufomind-1.0.0/tests/test_openai_compatible_client.py +377 -0
- gufomind-1.0.0/tests/test_openrouter_client.py +158 -0
- gufomind-1.0.0/tests/test_pipeline.py +511 -0
- gufomind-1.0.0/tests/test_retriever.py +158 -0
- gufomind-1.0.0/tests/test_security.py +340 -0
- gufomind-1.0.0/tests/test_server_client.py +168 -0
- gufomind-1.0.0/tests/test_session_store.py +244 -0
- gufomind-1.0.0/tests/test_settings_api.py +843 -0
- gufomind-1.0.0/tests/test_settings_sources.py +151 -0
- gufomind-1.0.0/tests/test_settings_ui.py +262 -0
- gufomind-1.0.0/tests/test_splitter.py +356 -0
- gufomind-1.0.0/tests/test_store.py +899 -0
- gufomind-1.0.0/tests/test_style_transfer.py +484 -0
- gufomind-1.0.0/tests/test_style_transfer_integration.py +58 -0
- gufomind-1.0.0/tests/test_user_settings.py +157 -0
- gufomind-1.0.0/tests/test_web_chat.py +208 -0
- gufomind-1.0.0/tests/test_web_enrich.py +72 -0
- gufomind-1.0.0/tests/test_web_lifespan.py +186 -0
- gufomind-1.0.0/tests/test_web_routes.py +87 -0
- gufomind-1.0.0/tests/test_web_sessions.py +166 -0
- gufomind-1.0.0/tests/test_web_sse.py +219 -0
- gufomind-1.0.0/tests/test_web_ui.py +121 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to GufoMind are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.0.0] — 2026-10-07
|
|
11
|
+
|
|
12
|
+
First public release.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Import** — import AI chat exports (DeepSeek) and personal writing
|
|
17
|
+
(Markdown + YAML frontmatter) into a local LanceDB knowledge base.
|
|
18
|
+
- **Auto-categorization** — an LLM tags every chunk with 36 default topics
|
|
19
|
+
(fully customizable).
|
|
20
|
+
- **RAG** — `gufo ask` answers questions grounded in your own data, with
|
|
21
|
+
source references.
|
|
22
|
+
- **Dialogue memory** — `gufo chat` remembers context within a session.
|
|
23
|
+
- **Web UI** — `gufo web` (FastAPI + HTMX) with a chat, a sessions sidebar,
|
|
24
|
+
a source panel and a settings page.
|
|
25
|
+
- **Style transfer** — `gufo write "topic" -t poem` generates new text in your
|
|
26
|
+
own voice, grounded in your personal writing samples.
|
|
27
|
+
- **Settings page** — edit runtime settings (retrieval, LLM, chunking,
|
|
28
|
+
license) from the web UI without touching `.env`. Layered resolution:
|
|
29
|
+
`env > user settings > .env > defaults`.
|
|
30
|
+
- **Multi-provider LLM support** — Ollama (local, free), DeepSeek, OpenAI,
|
|
31
|
+
Anthropic, OpenRouter.
|
|
32
|
+
- **Streaming** — token-by-token output in the CLI (`--stream`) and the web UI
|
|
33
|
+
(SSE).
|
|
34
|
+
- **Per-file chunking control** — a `chunk: none` frontmatter key keeps
|
|
35
|
+
short-form writing (poems, notes) as a single chunk.
|
|
36
|
+
- **Genre filter** — a repeatable `--type` in `gufo write` narrows the style
|
|
37
|
+
samples by genre (`poem` / `song` / `post` / `article` / `note`).
|
|
38
|
+
- **CLI aliases** — the `gufo` and `gufomind` console commands are equivalent.
|
|
39
|
+
- **Licensing** — Ed25519 offline verification with a periodic remote check.
|
|
40
|
+
- **Web security baseline** — TrustedHost + Origin-check middleware
|
|
41
|
+
(localhost-only by default).
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **Project renamed to GufoMind.** Python import path `gufo_rag` →
|
|
46
|
+
`gufomind`; environment prefix `CHATMIND_` → `GUFO_`; distribution
|
|
47
|
+
`gufo-rag` → `gufomind`.
|
|
48
|
+
- **`.env` migration required** if you used the old prefix:
|
|
49
|
+
`sed -i '' 's/CHATMIND_/GUFO_/g' .env`
|
|
50
|
+
- Minimum Python is **3.10** (3.12 recommended for the ML stack).
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- `writing_kind` is no longer dropped by the splitter (before Phase 7.6 every
|
|
55
|
+
chunk carried a NULL genre).
|
|
56
|
+
- Re-ingesting after a chunking change is now idempotent: `replace_document`
|
|
57
|
+
replaces a document's chunks by `document_id` instead of leaving orphan rows.
|
|
58
|
+
|
|
59
|
+
[Unreleased]: https://github.com/chalpanov1/gufomind/compare/v1.0.0...HEAD
|
|
60
|
+
[1.0.0]: https://github.com/chalpanov1/gufomind/releases/tag/v1.0.0
|
gufomind-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Copyright (c) 2026 Alexander Chalpanov. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This software and associated documentation files (the "Software")
|
|
4
|
+
are proprietary and confidential. Unauthorized copying,
|
|
5
|
+
modification, distribution, or use of the Software, in whole or
|
|
6
|
+
in part, is strictly prohibited without the express written
|
|
7
|
+
permission of the copyright holder.
|
|
8
|
+
|
|
9
|
+
The Software is provided "AS IS", without warranty of any kind.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Include documentation files that setuptools does not pick up by default.
|
|
2
|
+
include CHANGELOG.md
|
|
3
|
+
|
|
4
|
+
# Exclude build artifacts from sdist.
|
|
5
|
+
prune src/gufomind.egg-info
|
|
6
|
+
|
|
7
|
+
# Exclude local data and secrets (defense in depth; gitignore already covers).
|
|
8
|
+
prune data
|
|
9
|
+
prune dist
|
|
10
|
+
prune build
|
|
11
|
+
exclude .env
|
|
12
|
+
exclude contextforai.md
|
gufomind-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gufomind
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Personal RAG over your AI chat history — import, categorize, search, and query your conversations in your own voice.
|
|
5
|
+
Author-email: Chalpanov <chalpanovrich1@yandex.ru>
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://github.com/chalpanov1/gufomind
|
|
8
|
+
Project-URL: Repository, https://github.com/chalpanov1/gufomind
|
|
9
|
+
Project-URL: Issues, https://github.com/chalpanov1/gufomind/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/chalpanov1/gufomind/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: rag,llm,personal-ai,chat-history,style-transfer,local-first,knowledge-base,lancedb,personal-knowledge-management
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Text Processing :: Indexing
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: typer>=0.12
|
|
26
|
+
Requires-Dist: rich>=13.0
|
|
27
|
+
Requires-Dist: pydantic>=2.0
|
|
28
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
29
|
+
Requires-Dist: python-dotenv>=1.0
|
|
30
|
+
Requires-Dist: lancedb<0.41,>=0.39
|
|
31
|
+
Requires-Dist: sentence-transformers>=2.7
|
|
32
|
+
Requires-Dist: langchain-text-splitters>=0.2
|
|
33
|
+
Requires-Dist: tiktoken>=0.7
|
|
34
|
+
Requires-Dist: ollama>=0.3
|
|
35
|
+
Requires-Dist: httpx>=0.27
|
|
36
|
+
Requires-Dist: pandas>=2.0
|
|
37
|
+
Requires-Dist: pyarrow>=15.0
|
|
38
|
+
Requires-Dist: tqdm>=4.66
|
|
39
|
+
Requires-Dist: platformdirs>=4.0
|
|
40
|
+
Requires-Dist: python-frontmatter>=1.1
|
|
41
|
+
Requires-Dist: pyyaml>=6.0
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
45
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
46
|
+
Requires-Dist: mypy>=1.11; extra == "dev"
|
|
47
|
+
Provides-Extra: web
|
|
48
|
+
Requires-Dist: fastapi>=0.111; extra == "web"
|
|
49
|
+
Requires-Dist: uvicorn[standard]>=0.30; extra == "web"
|
|
50
|
+
Requires-Dist: jinja2>=3.1; extra == "web"
|
|
51
|
+
Requires-Dist: markdown-it-py>=3.0; extra == "web"
|
|
52
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "web"
|
|
53
|
+
Provides-Extra: licensing
|
|
54
|
+
Requires-Dist: pynacl>=1.5; extra == "licensing"
|
|
55
|
+
Dynamic: license-file
|
|
56
|
+
|
|
57
|
+
# 🦉 GufoMind
|
|
58
|
+
|
|
59
|
+
> **Personal RAG over your AI chat history** — import, categorize, search and
|
|
60
|
+
> query all of your conversations in one place, and generate new content in your
|
|
61
|
+
> own voice.
|
|
62
|
+
|
|
63
|
+
[](https://github.com/chalpanov1/gufomind/actions/workflows/ci.yml)
|
|
64
|
+
[](CHANGELOG.md)
|
|
65
|
+
[](LICENSE)
|
|
66
|
+
[](https://www.python.org/downloads/)
|
|
67
|
+
[](CHANGELOG.md)
|
|
68
|
+
|
|
69
|
+
GufoMind (Gufo — Italian for *owl*) is a **local personal-RAG system**: it turns
|
|
70
|
+
the scattered history of your AI conversations, your personal writing and your
|
|
71
|
+
own chat sessions into **one local knowledge core** — and then lets you talk to
|
|
72
|
+
it, search it, and write with it. Website: <https://gufomind.ru>.
|
|
73
|
+
|
|
74
|
+
## Naming
|
|
75
|
+
|
|
76
|
+
- **Product name:** GufoMind
|
|
77
|
+
- **Website:** https://gufomind.ru
|
|
78
|
+
- **CLI command:** `gufo`
|
|
79
|
+
- **Python package / PyPI:** `gufomind`
|
|
80
|
+
- **Env var prefix:** `GUFO_`.
|
|
81
|
+
|
|
82
|
+
The product was previously called *Gufo-RAG*. The rename happened before
|
|
83
|
+
the first public PyPI release, so no migration is required for end users.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## ✨ Why Gufo?
|
|
88
|
+
|
|
89
|
+
- Your best ideas are buried in dozens of AI chats across DeepSeek, ChatGPT,
|
|
90
|
+
Claude and Gemini — and they are not searchable.
|
|
91
|
+
- Your personal writing (posts, notes, poems, lyrics) lives somewhere else
|
|
92
|
+
entirely.
|
|
93
|
+
- Asking the same question twice is a waste of time and tokens.
|
|
94
|
+
|
|
95
|
+
Gufo fixes this: everything goes into **one vector database on your machine**,
|
|
96
|
+
and every new conversation makes that base smarter.
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Conversation → save → chunk → embed → vector store → search → new conversation
|
|
100
|
+
▲ │
|
|
101
|
+
└────────────── the loop keeps enriching the base ───────────────┘
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 🎯 Features
|
|
105
|
+
|
|
106
|
+
| | Feature | Status |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| 1 | Import chats from DeepSeek / ChatGPT / Claude / Gemini + personal texts | 🚧 Phase 1 |
|
|
109
|
+
| 2 | Automatic categorization (topics tagged by an LLM) | ✅ v0.2.0 |
|
|
110
|
+
| 3 | RAG pipeline — `gufo ask` answers grounded in your archive | ✅ v0.3.0 |
|
|
111
|
+
| 4 | Hybrid search — vectors + BM25 + re-ranker | ⬜ Phase 3.5 |
|
|
112
|
+
| 5 | Dialogue memory — the assistant remembers the context | ✅ v0.4.0 |
|
|
113
|
+
| 6 | Multi-LLM + streaming — Ollama, OpenAI, DeepSeek, Anthropic, OpenRouter | ✅ v0.5.0 |
|
|
114
|
+
| 7 | Web interface with a chat client and auto-saved sessions | ✅ v0.6.0 |
|
|
115
|
+
| 8 | Style transfer — write in the author's own voice | ✅ v0.7.0 |
|
|
116
|
+
| 9 | Write grounded in a chosen genre — repeatable `--type` · per-file `chunk: none` | ✅ v0.7.6 |
|
|
117
|
+
| 10 | Settings page in the web UI — edit runtime settings without touching `.env` | ✅ v0.7.7 |
|
|
118
|
+
|
|
119
|
+
Legend: ✅ done · 🚧 in progress · ⬜ planned
|
|
120
|
+
|
|
121
|
+
**Web interface (v0.6)** — `gufo web`:
|
|
122
|
+
|
|
123
|
+
- ✅ Streamed answers (SSE) rendered as markdown
|
|
124
|
+
- ✅ Multi-turn sessions with memory, listed in a sidebar
|
|
125
|
+
- ✅ Sources panel under each answer
|
|
126
|
+
- ✅ "Enrich the base" — turn a conversation into searchable chunks
|
|
127
|
+
- ✅ Dark/light theme, responsive layout
|
|
128
|
+
|
|
129
|
+
**Current status** (v0.6.0):
|
|
130
|
+
|
|
131
|
+
- **Phase 0 (Foundation)** — ✅ complete.
|
|
132
|
+
- **Phase 1 (Multi-Importer)** — 🚧 in progress. `gufo ingest` works end-to-end
|
|
133
|
+
for DeepSeek exports (verified on a real 64 MB, 236-conversation export →
|
|
134
|
+
23,966 chunks). The ChatGPT / Claude / Gemini and personal-text importers are
|
|
135
|
+
still to come.
|
|
136
|
+
- **Phase 2 (Auto-categorization)** — ✅ complete. `gufo categorize` tags every
|
|
137
|
+
chunk through the DeepSeek API (verified on the full base: 23,966 chunks →
|
|
138
|
+
23,618 with topics, 348 unclassified, 0 failures, 41m 40s).
|
|
139
|
+
- **Phase 3 (Vector RAG)** — ✅ complete. `gufo ask` answers questions grounded in
|
|
140
|
+
your archive, with sources (verified live against the real base). Hybrid search
|
|
141
|
+
(BM25 + re-ranker) follows in Phase 3.5.
|
|
142
|
+
- **Phase 4 (Dialogue Memory)** — ✅ complete. `gufo chat` holds a multi-turn
|
|
143
|
+
dialogue, persists each session to JSONL and resumes it with `--session <id>`.
|
|
144
|
+
- **Phase 5 (Multi-LLM + Streaming)** — ✅ complete. Five providers behind one
|
|
145
|
+
`.env` switch (`ollama`, `deepseek`, `openai`, `anthropic`, `openrouter`) and
|
|
146
|
+
streaming answers in the CLI (`gufo ask --stream`, `gufo chat --stream`).
|
|
147
|
+
- **Phase 6 (Web Interface + Chat)** — ✅ complete. `gufo web` serves a local
|
|
148
|
+
FastAPI + HTMX chat at `http://127.0.0.1:8000`: streamed answers over SSE, a
|
|
149
|
+
sessions sidebar, a sources panel, and an "Enrich the base" action that turns a
|
|
150
|
+
conversation into searchable chunks.
|
|
151
|
+
- **Phase 7 (Style Transfer)** — ✅ complete (v0.7.0). `gufo write` drafts new
|
|
152
|
+
texts in your own voice, grounded in personal writing samples.
|
|
153
|
+
- **Phase 7.5 (Style Transfer polish)** — ✅ complete (no version bump).
|
|
154
|
+
Post-audit fixes: a non-blocking license check and prompt hardening.
|
|
155
|
+
- **Phase 7.6 (Writing kind filter + chunking)** — ✅ complete (v0.7.6).
|
|
156
|
+
Optional, repeatable `--type`; per-file `chunk: none`; idempotent re-ingest.
|
|
157
|
+
- **Phase 7.7 (Settings page + security)** — ✅ complete (v0.7.7). A **⚙️ Settings**
|
|
158
|
+
page in the web UI edits runtime settings live (retrieval, LLM, chunking) on
|
|
159
|
+
top of a layered loader (`env > user settings > .env > defaults`), with secrets
|
|
160
|
+
kept in the OS user-data directory; the local server gains a TrustedHost
|
|
161
|
+
allowlist and a cross-origin (CSRF) check.
|
|
162
|
+
|
|
163
|
+
See [ROADMAP.md](ROADMAP.md).
|
|
164
|
+
|
|
165
|
+
## 📦 Installation
|
|
166
|
+
|
|
167
|
+
> Gufo is not published to PyPI yet. Until then, install it from source.
|
|
168
|
+
|
|
169
|
+
### From source (development)
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
git clone https://github.com/chalpanov1/gufomind.git
|
|
173
|
+
cd gufomind
|
|
174
|
+
|
|
175
|
+
python3.12 -m venv .venv
|
|
176
|
+
source .venv/bin/activate
|
|
177
|
+
|
|
178
|
+
pip install -e ".[dev]"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
> **Optional:** put `HF_TOKEN=...` in `.env` to authenticate Hugging Face model
|
|
182
|
+
> downloads — it is faster and removes the "unauthenticated requests" warning.
|
|
183
|
+
> Create a read-scoped token at
|
|
184
|
+
> [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens).
|
|
185
|
+
|
|
186
|
+
### Verify the installation
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
gufo --version # prints the installed version
|
|
190
|
+
gufo stats # shows the resolved configuration
|
|
191
|
+
gufo --help # lists all commands
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Once published (planned)
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
pipx install gufomind # recommended: isolated CLI install
|
|
198
|
+
# or
|
|
199
|
+
pip install gufomind
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## ⚙️ Configuration
|
|
203
|
+
|
|
204
|
+
Copy the example file and adjust it:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
cp .env.example .env
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
| Variable | Default | Meaning |
|
|
211
|
+
|---|---|---|
|
|
212
|
+
| `GUFO_DATA_DIR` | `./data` | root directory for local data |
|
|
213
|
+
| `GUFO_DB_PATH` | `./data/vector_db` | LanceDB database directory |
|
|
214
|
+
| `GUFO_TABLE_NAME` | `knowledge_base` | LanceDB table name |
|
|
215
|
+
| `GUFO_SESSIONS_DIR` | `./data/sessions` | directory of `gufo chat` sessions (one JSONL file per session) |
|
|
216
|
+
| `GUFO_EMBEDDING_MODEL` | `paraphrase-multilingual-MiniLM-L12-v2` | sentence-transformers model |
|
|
217
|
+
| `HF_TOKEN` | — | Hugging Face token (faster downloads, gated models) |
|
|
218
|
+
| `GUFO_LLM_PROVIDER` | **required** | `ollama` (local, slow) \| `deepseek` (cloud) \| `openai` \| `anthropic` \| `openrouter` |
|
|
219
|
+
| `GUFO_LLM_MODEL` | per-provider default | optional model override; unset uses the provider default (`gufo stats` shows it) |
|
|
220
|
+
| `GUFO_LLM_TIMEOUT` | `60` | seconds to wait for one LLM request |
|
|
221
|
+
| `OLLAMA_HOST` | `http://localhost:11434` | Ollama server URL |
|
|
222
|
+
| `GUFO_CHUNK_SIZE` | `512` | target chunk size in tokens |
|
|
223
|
+
| `GUFO_CHUNK_OVERLAP` | `50` | overlap between chunks |
|
|
224
|
+
| `GUFO_TOP_K` | `20` | chunks passed to the LLM |
|
|
225
|
+
| `GUFO_FETCH_K` | `30` | candidates fetched before re-ranking |
|
|
226
|
+
| `GUFO_TEMPERATURE` | `0.3` | generation temperature |
|
|
227
|
+
| `GUFO_HISTORY_WINDOW` | `20` | recent turns of a session passed to the LLM as history |
|
|
228
|
+
| `GUFO_RETRIEVAL_HISTORY_TURNS` | `2` | prior user turns folded into the search query |
|
|
229
|
+
| `GUFO_INCLUDE_THINKING` | `false` | keep the model's chain-of-thought blocks on import |
|
|
230
|
+
| `DEEPSEEK_API_KEY` | — | API key for the `deepseek` provider / `gufo categorize` |
|
|
231
|
+
| `DEEPSEEK_BASE_URL` | `https://api.deepseek.com` | DeepSeek API root |
|
|
232
|
+
| `OPENAI_API_KEY` | — | API key for the `openai` provider |
|
|
233
|
+
| `OPENAI_BASE_URL` | `https://api.openai.com/v1` | OpenAI API root |
|
|
234
|
+
| `ANTHROPIC_API_KEY` | — | API key for the `anthropic` provider |
|
|
235
|
+
| `ANTHROPIC_BASE_URL` | `https://api.anthropic.com/v1` | Anthropic API root |
|
|
236
|
+
| `OPENROUTER_API_KEY` | — | API key for the `openrouter` provider |
|
|
237
|
+
| `OPENROUTER_BASE_URL` | `https://openrouter.ai/api/v1` | OpenRouter API root |
|
|
238
|
+
| `OPENROUTER_REFERER` | — | optional `HTTP-Referer` attribution header |
|
|
239
|
+
| `OPENROUTER_TITLE` | — | optional `X-Title` attribution header |
|
|
240
|
+
| `GUFO_CATEGORIZATION_MODEL` | `deepseek-chat` | model used to tag chunks |
|
|
241
|
+
| `GUFO_CATEGORIZATION_BATCH_SIZE` | `20` | chunks per LLM request |
|
|
242
|
+
| `GUFO_CATEGORIZATION_MAX_TOPICS` | `5` | maximum topics per chunk |
|
|
243
|
+
| `GUFO_CATEGORIZATION_SEED_TOPICS` | built-in list of 36 | comma-separated topic seeds |
|
|
244
|
+
| `GUFO_LICENSE_SERVER_URL` | `https://license.gufomind.ru` | license server base URL |
|
|
245
|
+
| `GUFO_LICENSE_CHECK_INTERVAL_DAYS` | `30` | days a successful remote check is trusted |
|
|
246
|
+
| `GUFO_LICENSE_GRACE_PERIOD_DAYS` | `90` | offline grace period since the last successful check |
|
|
247
|
+
| `GUFO_STYLE_K` | `5` | style samples retrieved for `gufo write` (1–20) |
|
|
248
|
+
| `GUFO_LOG_LEVEL` | `WARNING` | log level: `DEBUG` / `INFO` / `WARNING` / `ERROR` |
|
|
249
|
+
| `GUFO_IGNORE_USER_SETTINGS` | — | set to `1` to ignore settings saved from the web UI (emergency kill-switch) |
|
|
250
|
+
|
|
251
|
+
> Values saved from the web UI's **⚙️ Settings** page live in your OS user-data
|
|
252
|
+
> directory, not in `.env` — see [Settings page](#settings-page). Precedence is
|
|
253
|
+
> **real env vars > user settings > `.env` > defaults**.
|
|
254
|
+
|
|
255
|
+
> Environment variables use the `GUFO_` prefix. The previous prefix
|
|
256
|
+
> (`CHATMIND_`) was renamed in Phase 8 with no backward-compatible alias.
|
|
257
|
+
|
|
258
|
+
## 💸 Categorization cost
|
|
259
|
+
|
|
260
|
+
Running `gufo categorize` uses an LLM to tag every chunk. The cost depends
|
|
261
|
+
entirely on which model you use — from **$0 (local Ollama)** to **$80+ (OpenAI
|
|
262
|
+
GPT-4o)** for a 24,000-chunk base.
|
|
263
|
+
|
|
264
|
+
| Provider / Model | Cost for 24k chunks | Time | Notes |
|
|
265
|
+
|---|---|---|---|
|
|
266
|
+
| **Ollama (local)** | **$0** | ~hours on M1 | Free, private, slow |
|
|
267
|
+
| **DeepSeek (off-peak)** | **~$1.66** | ~40 min | Cheapest API. Reference run. |
|
|
268
|
+
| DeepSeek (peak hours) | ~$3–4 | ~40 min | 2× off-peak pricing |
|
|
269
|
+
| OpenAI gpt-4o-mini | ~$5–8 | ~15 min | Faster, more expensive |
|
|
270
|
+
| Anthropic Claude Haiku | ~$10–15 | ~20 min | Mid-range |
|
|
271
|
+
| OpenAI gpt-4o | ~$60–80 | ~15 min | Fastest, most expensive |
|
|
272
|
+
|
|
273
|
+
**Incremental runs** (new chunks only) cost proportionally less: 100 new chunks
|
|
274
|
+
≈ $0.007 with DeepSeek off-peak.
|
|
275
|
+
|
|
276
|
+
**Why categorize?**
|
|
277
|
+
|
|
278
|
+
- **Without it:** `gufo ask` searches by semantic similarity only.
|
|
279
|
+
- **With it:** you can filter by exact topics — `gufo ask "..." --topic databases`
|
|
280
|
+
returns only database-related chunks.
|
|
281
|
+
|
|
282
|
+
> These numbers are indicative and follow the provider's pricing; local Ollama is
|
|
283
|
+
> free but needs a machine that can run the model. A `--force` run asks for
|
|
284
|
+
> confirmation first — pass `--yes` to skip the prompt in scripts and CI.
|
|
285
|
+
|
|
286
|
+
## 🚀 Usage
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# Show the resolved configuration and the state of the base
|
|
290
|
+
gufo stats
|
|
291
|
+
|
|
292
|
+
# Import an export into the knowledge base (Phase 1)
|
|
293
|
+
gufo ingest ./exports/deepseek_conversations.json
|
|
294
|
+
|
|
295
|
+
# Tag every chunk with topics through the DeepSeek API (Phase 2)
|
|
296
|
+
gufo categorize # incremental: only untagged chunks
|
|
297
|
+
gufo categorize --force # re-tag everything
|
|
298
|
+
|
|
299
|
+
# Ask a question (Phase 3)
|
|
300
|
+
gufo ask "Что я писал про векторные базы данных?"
|
|
301
|
+
|
|
302
|
+
# Stream the answer as it is generated (Phase 5)
|
|
303
|
+
gufo ask "Что я писал про векторные базы данных?" --stream
|
|
304
|
+
|
|
305
|
+
# Chat with a memory of the dialogue (Phase 4)
|
|
306
|
+
gufo chat # start a new session
|
|
307
|
+
gufo chat --session <id> # resume a saved session
|
|
308
|
+
gufo chat --stream # stream each answer as it arrives
|
|
309
|
+
# inside the REPL: /exit · /new · /clear · /sessions
|
|
310
|
+
|
|
311
|
+
# Chat in the browser, with a sessions sidebar and sources (Phase 6)
|
|
312
|
+
gufo web # serves http://127.0.0.1:8000
|
|
313
|
+
gufo web --open # ...and open the browser
|
|
314
|
+
gufo web --port 9000 # pick another port
|
|
315
|
+
|
|
316
|
+
# Write in your own voice (Phase 7). The first --type is what to write;
|
|
317
|
+
# any further --type values pick the genres to draw samples from.
|
|
318
|
+
gufo write "утро" # a post (default), grounded in everything you wrote
|
|
319
|
+
gufo write "тишина" -t poem # a poem, grounded only in poems
|
|
320
|
+
gufo write "тишина" -t poem -t song # a poem, inspired by poems and songs
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Settings page
|
|
324
|
+
|
|
325
|
+
Open the **⚙️ Settings** page from the sidebar to change runtime settings
|
|
326
|
+
without editing `.env` or restarting:
|
|
327
|
+
|
|
328
|
+
- **Retrieval** (`top_k`, `history_window`, …) — applied instantly.
|
|
329
|
+
- **LLM** (provider, model, temperature, API keys) — the client is rebuilt on
|
|
330
|
+
save; in-flight streams continue on the old client.
|
|
331
|
+
- **Chunking** (`chunk_size`, `chunk_overlap`) — applied to the next ingest /
|
|
332
|
+
enrich run.
|
|
333
|
+
- **License** intervals — applied on the next restart.
|
|
334
|
+
- **Read-only** fields (`embedding_model`, `db_path`, …) are shown but cannot be
|
|
335
|
+
edited from the UI. To change them, edit `settings.json` and restart the
|
|
336
|
+
process.
|
|
337
|
+
|
|
338
|
+
Your settings are stored in your OS's user-data directory
|
|
339
|
+
(`~/Library/Application Support/Gufo/` on macOS, `~/.local/share/gufo/` on
|
|
340
|
+
Linux, `%APPDATA%\Gufo\` on Windows):
|
|
341
|
+
|
|
342
|
+
- `settings.json` — non-secret values.
|
|
343
|
+
- `secrets.json` — API keys, written with `0600` (owner-only) permissions.
|
|
344
|
+
|
|
345
|
+
**Precedence:** real environment variables > your `settings.json` > `.env` >
|
|
346
|
+
defaults. If a field shows `source: env`, editing it in the UI will have no
|
|
347
|
+
effect until the environment variable is unset.
|
|
348
|
+
|
|
349
|
+
### Network exposure
|
|
350
|
+
|
|
351
|
+
The web server binds to `127.0.0.1` (loopback) by default and is protected by
|
|
352
|
+
two middlewares:
|
|
353
|
+
|
|
354
|
+
- **TrustedHostMiddleware** — only `localhost`, `127.0.0.1` and `[::1]` are
|
|
355
|
+
accepted; anything else returns `400`.
|
|
356
|
+
- **Origin check** — mutating requests (`POST`/`PUT`/`DELETE`) must carry a
|
|
357
|
+
same-origin `Origin` (or `Referer`) header; cross-origin requests get `403`.
|
|
358
|
+
Non-browser clients (curl, scripts) that send neither header are allowed.
|
|
359
|
+
|
|
360
|
+
Running `gufo web --host 0.0.0.0` (or any non-loopback address) triggers a
|
|
361
|
+
warning and requires explicit confirmation, then opens the allowlist to `["*"]`.
|
|
362
|
+
**GufoMind has no authentication** — never expose it to an untrusted network.
|
|
363
|
+
|
|
364
|
+
⚠️ Bypassing the CLI (`uvicorn gufomind.web.run:app --host 0.0.0.0`) keeps the
|
|
365
|
+
loopback allowlist and will reject LAN clients. Always use `gufo web`.
|
|
366
|
+
|
|
367
|
+
### Personal writing (Markdown + YAML frontmatter)
|
|
368
|
+
|
|
369
|
+
Put your own writing (poems, posts, articles, songs, notes) in a folder as
|
|
370
|
+
`.md` files. Each file starts with YAML frontmatter:
|
|
371
|
+
|
|
372
|
+
```yaml
|
|
373
|
+
---
|
|
374
|
+
type: poem # poem | post | article | song | note
|
|
375
|
+
title: Morning # optional; falls back to the file name
|
|
376
|
+
topics: [life] # optional
|
|
377
|
+
chunk: none # optional; see below
|
|
378
|
+
date: 2026-10-04 # optional
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
Your text here.
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**`chunk: none`** disables chunk splitting for that file. Use it for short-form
|
|
385
|
+
writing (poems, haiku, notes) so a single work stays one chunk and its voice
|
|
386
|
+
sample is not truncated mid-stanza.
|
|
387
|
+
|
|
388
|
+
**Re-importing is idempotent**: chunks are keyed by a stable document id, and a
|
|
389
|
+
re-import replaces the previous chunks of the same file — no duplicates even if
|
|
390
|
+
you change `chunk`, `type` or `title` between imports.
|
|
391
|
+
|
|
392
|
+
#### Migrating from pre-v0.7.6
|
|
393
|
+
|
|
394
|
+
Personal chunks imported before v0.7.6 have `document_id = NULL`. A re-import
|
|
395
|
+
**with the same chunking structure** works fine — `merge_insert` matches by
|
|
396
|
+
chunk `id` and backfills `document_id`. However, a re-import **after a
|
|
397
|
+
chunking-structure change** (e.g. adding `chunk: none` to a file) will produce
|
|
398
|
+
duplicate chunks: the old NULL rows are not matched by `replace_document` and
|
|
399
|
+
stay behind.
|
|
400
|
+
|
|
401
|
+
To migrate cleanly, run **once**:
|
|
402
|
+
|
|
403
|
+
gufo ingest --reset <path-to-personal-texts>
|
|
404
|
+
|
|
405
|
+
This drops the table and re-imports everything with `document_id` populated. A
|
|
406
|
+
one-shot backfill command is planned for a future release (see ROADMAP backlog).
|
|
407
|
+
|
|
408
|
+
## 🔎 Retrieval tuning
|
|
409
|
+
|
|
410
|
+
By default `gufo ask` and `gufo chat` retrieve the **20** most relevant chunks
|
|
411
|
+
and pass them to the LLM. That balances coverage (enough chunks to answer) and
|
|
412
|
+
precision — LLM attention degrades beyond roughly 25 chunks ("lost in the
|
|
413
|
+
middle"), so a larger `top_k` can dilute focus on a focused question.
|
|
414
|
+
|
|
415
|
+
Adjust it per call with `--top-k N`:
|
|
416
|
+
|
|
417
|
+
- **Lower (8–10)** — faster and cheaper; good for a focused question about one
|
|
418
|
+
specific thing, but it may miss relevant chunks for questions that span a
|
|
419
|
+
whole project.
|
|
420
|
+
- **Higher (30–50)** — more coverage for broad, cross-cutting questions; may hurt
|
|
421
|
+
precision on focused ones because of attention dilution.
|
|
422
|
+
|
|
423
|
+
Rules of thumb:
|
|
424
|
+
|
|
425
|
+
- Default **20** is tuned for a ~24k-chunk base. On a small base (<5k chunks),
|
|
426
|
+
**10–15** is usually enough.
|
|
427
|
+
- The cost is small: 20 chunks × ~512 tokens ≈ 10k tokens of context — pennies on
|
|
428
|
+
a cloud provider and comfortably inside a 32k local Ollama model.
|
|
429
|
+
- Prefer raising `--top-k` over lowering it when answers feel incomplete: better
|
|
430
|
+
to hand the model a few extra candidates than to miss the one that mattered.
|
|
431
|
+
|
|
432
|
+
## 🧱 Data model
|
|
433
|
+
|
|
434
|
+
Every chunk carries three independent axes of metadata, so results can be
|
|
435
|
+
filtered in almost any combination:
|
|
436
|
+
|
|
437
|
+
| Axis | Values |
|
|
438
|
+
|---|---|
|
|
439
|
+
| **source** | `deepseek`, `chatgpt`, `claude`, `gemini`, `personal`, `session`, `manual` |
|
|
440
|
+
| **content_type** | `chat`, `writing`, `note`, `article`, `code` |
|
|
441
|
+
| **topics** | free-form tags, e.g. `models`, `databases`, `business` |
|
|
442
|
+
|
|
443
|
+
```python
|
|
444
|
+
# All my personal writing about business — used to generate a new post
|
|
445
|
+
search(
|
|
446
|
+
query="предпринимательство, рост, стратегия",
|
|
447
|
+
filters={"source": "personal", "content_type": "writing", "topics": ["business"]},
|
|
448
|
+
)
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## 🗂️ Project structure
|
|
452
|
+
|
|
453
|
+
```
|
|
454
|
+
gufomind/
|
|
455
|
+
├── .clinerules/ # coding rules for the AI agent
|
|
456
|
+
├── memory-bank/ # long-term project memory
|
|
457
|
+
├── src/gufomind/
|
|
458
|
+
│ ├── cli.py # typer CLI
|
|
459
|
+
│ ├── config.py # pydantic-settings (single source of truth)
|
|
460
|
+
│ ├── core/models.py # Message, Chat, Chunk, SearchResult
|
|
461
|
+
│ ├── importers/ # one importer per source
|
|
462
|
+
│ ├── chunking/ # token-aware splitter
|
|
463
|
+
│ ├── embeddings/ # sentence-transformers encoder
|
|
464
|
+
│ ├── storage/ # LanceDB store
|
|
465
|
+
│ ├── categorization/ # LLM topic tagging (port adapter + use case)
|
|
466
|
+
│ ├── llm/ # LLM clients (Ollama, OpenAI, DeepSeek, ...)
|
|
467
|
+
│ └── rag/ # retrieval + generation pipeline
|
|
468
|
+
├── tests/
|
|
469
|
+
└── data/ # local data (git-ignored)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
## 🗺️ Roadmap
|
|
473
|
+
|
|
474
|
+
See [ROADMAP.md](ROADMAP.md) for the full plan. Short version:
|
|
475
|
+
|
|
476
|
+
| Phase | Name |
|
|
477
|
+
|---|---|
|
|
478
|
+
| 0 | Foundation ✅ v0.1.0 |
|
|
479
|
+
| 1 | Multi-Importer 🚧 |
|
|
480
|
+
| 2 | Auto-categorization ✅ v0.2.0 |
|
|
481
|
+
| 3 | Vector RAG ✅ v0.3.0 |
|
|
482
|
+
| 3.5 | Hybrid Search ⬜ |
|
|
483
|
+
| 4 | Dialogue Memory ✅ v0.4.0 |
|
|
484
|
+
| 5 | Multi-LLM ✅ v0.5.0 |
|
|
485
|
+
| 6 | Web Interface + Chat ✅ v0.6.0 |
|
|
486
|
+
| 7 | Style Transfer ✅ v0.7.0 |
|
|
487
|
+
| 7.5 | Style Transfer polish ✅ |
|
|
488
|
+
| 7.6 | Writing kind filter + chunking ✅ v0.7.6 |
|
|
489
|
+
| 7.7 | Settings page + security ✅ v0.7.7 |
|
|
490
|
+
| 8 | Release ⬜ |
|
|
491
|
+
|
|
492
|
+
## 🛠️ Development
|
|
493
|
+
|
|
494
|
+
The project follows the coding standards in
|
|
495
|
+
[`.clinerules/01-coding-standards.md`](.clinerules/01-coding-standards.md) and the
|
|
496
|
+
workflow in [`.clinerules/04-workflow.md`](.clinerules/04-workflow.md).
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
ruff check . # lint
|
|
500
|
+
ruff format . # format
|
|
501
|
+
pytest # tests
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Commits follow [Conventional Commits](https://www.conventionalcommits.org/).
|
|
505
|
+
|
|
506
|
+
## 📄 License
|
|
507
|
+
|
|
508
|
+
Copyright © 2026 Alexander Chalpanov. All rights reserved.
|
|
509
|
+
|
|
510
|
+
This is **proprietary, closed-source software** — not open source. See
|
|
511
|
+
[LICENSE](LICENSE) for the full terms. Unauthorized copying, modification,
|
|
512
|
+
distribution or use, in whole or in part, is strictly prohibited.
|