protoprompt 0.1.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.
- protoprompt-0.1.0/CHANGELOG.md +34 -0
- protoprompt-0.1.0/LICENSE +21 -0
- protoprompt-0.1.0/MANIFEST.in +11 -0
- protoprompt-0.1.0/PKG-INFO +201 -0
- protoprompt-0.1.0/README.en.md +164 -0
- protoprompt-0.1.0/README.md +163 -0
- protoprompt-0.1.0/docs/en/api/context.md +3 -0
- protoprompt-0.1.0/docs/en/api/injector.md +17 -0
- protoprompt-0.1.0/docs/en/api/pipeline.md +5 -0
- protoprompt-0.1.0/docs/en/api/profile.md +9 -0
- protoprompt-0.1.0/docs/en/api/session.md +17 -0
- protoprompt-0.1.0/docs/en/api/store.md +13 -0
- protoprompt-0.1.0/docs/en/api/tokens.md +13 -0
- protoprompt-0.1.0/docs/en/changelog.md +3 -0
- protoprompt-0.1.0/docs/en/concepts/budget.md +72 -0
- protoprompt-0.1.0/docs/en/concepts/compression.md +81 -0
- protoprompt-0.1.0/docs/en/concepts/context.md +44 -0
- protoprompt-0.1.0/docs/en/index.md +67 -0
- protoprompt-0.1.0/docs/en/license.md +3 -0
- protoprompt-0.1.0/docs/en/quickstart.md +97 -0
- protoprompt-0.1.0/docs/ru/api/context.md +3 -0
- protoprompt-0.1.0/docs/ru/api/injector.md +17 -0
- protoprompt-0.1.0/docs/ru/api/pipeline.md +5 -0
- protoprompt-0.1.0/docs/ru/api/profile.md +9 -0
- protoprompt-0.1.0/docs/ru/api/session.md +17 -0
- protoprompt-0.1.0/docs/ru/api/store.md +13 -0
- protoprompt-0.1.0/docs/ru/api/tokens.md +13 -0
- protoprompt-0.1.0/docs/ru/changelog.md +3 -0
- protoprompt-0.1.0/docs/ru/concepts/budget.md +70 -0
- protoprompt-0.1.0/docs/ru/concepts/compression.md +86 -0
- protoprompt-0.1.0/docs/ru/concepts/context.md +44 -0
- protoprompt-0.1.0/docs/ru/index.md +67 -0
- protoprompt-0.1.0/docs/ru/license.md +3 -0
- protoprompt-0.1.0/docs/ru/quickstart.md +99 -0
- protoprompt-0.1.0/mkdocs.en.yml +60 -0
- protoprompt-0.1.0/mkdocs.ru.yml +60 -0
- protoprompt-0.1.0/protoprompt/__init__.py +58 -0
- protoprompt-0.1.0/protoprompt/context.py +33 -0
- protoprompt-0.1.0/protoprompt/exceptions.py +20 -0
- protoprompt-0.1.0/protoprompt/injector.py +69 -0
- protoprompt-0.1.0/protoprompt/injector_budgeted.py +219 -0
- protoprompt-0.1.0/protoprompt/llm.py +12 -0
- protoprompt-0.1.0/protoprompt/pipeline.py +71 -0
- protoprompt-0.1.0/protoprompt/profile/__init__.py +4 -0
- protoprompt-0.1.0/protoprompt/profile/builder.py +62 -0
- protoprompt-0.1.0/protoprompt/profile/schema.py +24 -0
- protoprompt-0.1.0/protoprompt/profile/types.py +12 -0
- protoprompt-0.1.0/protoprompt/session/__init__.py +16 -0
- protoprompt-0.1.0/protoprompt/session/compressor.py +17 -0
- protoprompt-0.1.0/protoprompt/session/strategy.py +200 -0
- protoprompt-0.1.0/protoprompt/session/types.py +17 -0
- protoprompt-0.1.0/protoprompt/store/__init__.py +4 -0
- protoprompt-0.1.0/protoprompt/store/chroma.py +71 -0
- protoprompt-0.1.0/protoprompt/store/memory.py +79 -0
- protoprompt-0.1.0/protoprompt/store/protocol.py +39 -0
- protoprompt-0.1.0/protoprompt/tokens/__init__.py +7 -0
- protoprompt-0.1.0/protoprompt/tokens/protocol.py +25 -0
- protoprompt-0.1.0/protoprompt/tokens/regex_counter.py +52 -0
- protoprompt-0.1.0/protoprompt/tokens/tiktoken_adapter.py +57 -0
- protoprompt-0.1.0/protoprompt.egg-info/PKG-INFO +201 -0
- protoprompt-0.1.0/protoprompt.egg-info/SOURCES.txt +78 -0
- protoprompt-0.1.0/protoprompt.egg-info/dependency_links.txt +1 -0
- protoprompt-0.1.0/protoprompt.egg-info/requires.txt +14 -0
- protoprompt-0.1.0/protoprompt.egg-info/top_level.txt +1 -0
- protoprompt-0.1.0/pyproject.toml +71 -0
- protoprompt-0.1.0/scripts/build_docs.py +143 -0
- protoprompt-0.1.0/setup.cfg +4 -0
- protoprompt-0.1.0/tests/__init__.py +0 -0
- protoprompt-0.1.0/tests/_mocks.py +34 -0
- protoprompt-0.1.0/tests/conftest.py +27 -0
- protoprompt-0.1.0/tests/test_budgeted.py +148 -0
- protoprompt-0.1.0/tests/test_chroma_store.py +70 -0
- protoprompt-0.1.0/tests/test_compressor.py +62 -0
- protoprompt-0.1.0/tests/test_injector.py +92 -0
- protoprompt-0.1.0/tests/test_integration.py +86 -0
- protoprompt-0.1.0/tests/test_llm_strategy.py +103 -0
- protoprompt-0.1.0/tests/test_pipeline.py +81 -0
- protoprompt-0.1.0/tests/test_store.py +50 -0
- protoprompt-0.1.0/tests/test_store_advanced.py +48 -0
- protoprompt-0.1.0/tests/test_tokens.py +87 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be 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
|
+
## [0.1.0] - 2026-07-10
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `protoprompt.tokens` subpackage with pluggable `TokenCounter` protocol
|
|
12
|
+
and a regex-based default implementation. Optional `tiktoken` adapter.
|
|
13
|
+
- `LLMSummaryStrategy` for LLM-based session compression with
|
|
14
|
+
`HeuristicStrategy` fallback on failure.
|
|
15
|
+
- `TokenBudgetedContextBuilder` with priority-based greedy token allocation
|
|
16
|
+
and `BudgetReport` observability.
|
|
17
|
+
- Real ChromaDB integration tests gated on the `chroma` extra.
|
|
18
|
+
- MkDocs Material documentation under `docs/`.
|
|
19
|
+
- GitHub Actions CI workflow across Python 3.11-3.13.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- `ContextBuilder` now embeds the query once and reuses it for RAG and
|
|
23
|
+
session retrieval (was: embedded twice).
|
|
24
|
+
- `InMemStore` supports filtering on any metadata field, not only `doc_id`.
|
|
25
|
+
- `StoreProtocol.query` accepts an optional `score_threshold`.
|
|
26
|
+
- `Pipeline.compress_and_store` writes to a `_new` doc_id first, then deletes
|
|
27
|
+
the old one, to avoid data loss on crash between steps.
|
|
28
|
+
- `ProfileBuilder` logs the original exception instead of silently returning
|
|
29
|
+
an empty profile.
|
|
30
|
+
- `HeuristicStrategy` honours a `min_messages` threshold.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- Public re-exports in `protoprompt.profile`, `protoprompt.session`,
|
|
34
|
+
`protoprompt.store` so IDEs and type checkers see the full API.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EnergoAI Hub
|
|
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.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include README.en.md
|
|
3
|
+
include README.ru.md
|
|
4
|
+
include LICENSE
|
|
5
|
+
include CHANGELOG.md
|
|
6
|
+
recursive-include docs *.md
|
|
7
|
+
recursive-include scripts *.py
|
|
8
|
+
recursive-include examples *.py
|
|
9
|
+
recursive-include tests *.py
|
|
10
|
+
include mkdocs.ru.yml
|
|
11
|
+
include mkdocs.en.yml
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: protoprompt
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Layered context builder for LLM prompts: RAG + compressed session memory + user profile
|
|
5
|
+
Author: EnergoAI Hub
|
|
6
|
+
Maintainer: EnergoAI Hub
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/Idxeed/protoprompt
|
|
9
|
+
Project-URL: Documentation, https://idxeed.github.io/protoprompt/
|
|
10
|
+
Project-URL: Source, https://github.com/Idxeed/protoprompt
|
|
11
|
+
Project-URL: Issues, https://github.com/Idxeed/protoprompt/issues
|
|
12
|
+
Project-URL: Changelog, https://github.com/Idxeed/protoprompt/blob/main/CHANGELOG.md
|
|
13
|
+
Keywords: llm,rag,prompt,context,embedding
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Provides-Extra: chroma
|
|
27
|
+
Requires-Dist: chromadb<0.6,>=0.5; extra == "chroma"
|
|
28
|
+
Provides-Extra: tiktoken
|
|
29
|
+
Requires-Dist: tiktoken>=0.5; extra == "tiktoken"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
34
|
+
Requires-Dist: mkdocs>=1.5; extra == "dev"
|
|
35
|
+
Requires-Dist: mkdocs-material>=9; extra == "dev"
|
|
36
|
+
Requires-Dist: mkdocstrings[python]>=0.24; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# protoprompt
|
|
40
|
+
|
|
41
|
+
[](https://github.com/Idxeed/protoprompt/actions/workflows/ci.yml)
|
|
42
|
+
[](https://codecov.io/gh/Idxeed/protoprompt)
|
|
43
|
+
[](https://www.python.org/)
|
|
44
|
+
[](LICENSE)
|
|
45
|
+
[](README.ru.md)
|
|
46
|
+
[](README.en.md)
|
|
47
|
+
|
|
48
|
+
Слоистый сборщик контекста для LLM-промптов. Три независимых, компонуемых
|
|
49
|
+
слоя кормят модель: **RAG по документам**, **сжатая история сессии** и
|
|
50
|
+
опциональный **профиль пользователя**. Подключаемое векторное хранилище,
|
|
51
|
+
подключаемый токенайзер, подключаемая стратегия сжатия.
|
|
52
|
+
|
|
53
|
+
[English version](README.en.md)
|
|
54
|
+
|
|
55
|
+
## Зачем
|
|
56
|
+
|
|
57
|
+
Прод-LLM-приложения упираются в одну и ту же стену: модели нужен контекст,
|
|
58
|
+
но окно конечно. Собранная вручную сборка промпта превращается в кашу:
|
|
59
|
+
документы ищутся отдельно от истории, system prompt дублируется, и каждая
|
|
60
|
+
команда переписывает один и тот же клей.
|
|
61
|
+
|
|
62
|
+
`protoprompt` разделяет три задачи и даёт каждой чистый протокол:
|
|
63
|
+
|
|
64
|
+
- `StoreProtocol` — векторное хранилище (in-memory для тестов, ChromaDB для прода).
|
|
65
|
+
- `StrategyProtocol` — как сжимать старые ходы длинной сессии.
|
|
66
|
+
- `TokenCounter` — как считать бюджет финального промпта.
|
|
67
|
+
|
|
68
|
+
`ContextBuilder` оркестрирует все три. Результат — единый `system_prompt`
|
|
69
|
+
плюс структурированный `ContextOutput` с описанием того, что вошло (head,
|
|
70
|
+
tail, RAG, profile), чтобы UI мог показать provenance.
|
|
71
|
+
|
|
72
|
+
## Установка
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install protoprompt
|
|
76
|
+
|
|
77
|
+
# С ChromaDB-бэкендом
|
|
78
|
+
pip install "protoprompt[chroma]"
|
|
79
|
+
|
|
80
|
+
# С tiktoken-токенайзером
|
|
81
|
+
pip install "protoprompt[tiktoken]"
|
|
82
|
+
|
|
83
|
+
# Для разработки и документации
|
|
84
|
+
pip install "protoprompt[chroma,dev]"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Быстрый старт
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import asyncio
|
|
91
|
+
from protoprompt import (
|
|
92
|
+
InMemStore,
|
|
93
|
+
ContextBuilder,
|
|
94
|
+
ContextInput,
|
|
95
|
+
Pipeline,
|
|
96
|
+
HeuristicStrategy,
|
|
97
|
+
Session,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class MyLLM:
|
|
102
|
+
async def chat(self, messages, model="", **options):
|
|
103
|
+
return "заглушка"
|
|
104
|
+
|
|
105
|
+
async def embed(self, texts, model=""):
|
|
106
|
+
# замените на реальные эмбеддинги
|
|
107
|
+
return [[0.1] * 384 for _ in texts]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
async def main():
|
|
111
|
+
store = InMemStore()
|
|
112
|
+
store.add("doc-1", ["Париж — столица Франции."], [[0.5] * 384])
|
|
113
|
+
llm = MyLLM()
|
|
114
|
+
|
|
115
|
+
builder = ContextBuilder(store, llm)
|
|
116
|
+
out = await builder.build(ContextInput(
|
|
117
|
+
query="Какая столица Франции?",
|
|
118
|
+
system_prompt="Ты учитель географии.",
|
|
119
|
+
doc_ids=[1],
|
|
120
|
+
))
|
|
121
|
+
print(out.system_prompt)
|
|
122
|
+
|
|
123
|
+
pipeline = Pipeline(
|
|
124
|
+
store, llm,
|
|
125
|
+
strategy=HeuristicStrategy(),
|
|
126
|
+
compress_every_n=10,
|
|
127
|
+
)
|
|
128
|
+
session = Session(chat_id="c1", messages=[
|
|
129
|
+
{"role": "user", "content": "Привет"},
|
|
130
|
+
{"role": "assistant", "content": "Здравствуйте!"},
|
|
131
|
+
])
|
|
132
|
+
if pipeline.should_compress(len(session.messages)):
|
|
133
|
+
await pipeline.compress_and_store(session)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
asyncio.run(main())
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Архитектура
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
+--------------------+
|
|
143
|
+
| ContextBuilder |
|
|
144
|
+
| (оркестратор) |
|
|
145
|
+
+---------+----------+
|
|
146
|
+
|
|
|
147
|
+
+------------------+------------------+------------------+
|
|
148
|
+
| | | |
|
|
149
|
+
v v v v
|
|
150
|
+
+---------------+ +----------------+ +---------------+ +---------+
|
|
151
|
+
| RAG-поиск | | Память сессии | | Профиль польз.| | Store |
|
|
152
|
+
| (vector top-k)| | (сжатая) | | (из LLM) | | query |
|
|
153
|
+
+---------------+ +----------------+ +---------------+ +---------+
|
|
154
|
+
| | |
|
|
155
|
+
+--------+---------+--------+---------+
|
|
156
|
+
| |
|
|
157
|
+
v v
|
|
158
|
+
+----------------+ +----------------+
|
|
159
|
+
| TokenCounter | | StoreProtocol |
|
|
160
|
+
| (pluggable) | | (in-mem/chroma)|
|
|
161
|
+
+----------------+ +----------------+
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Публичный API
|
|
165
|
+
|
|
166
|
+
| Модуль | Экспорты |
|
|
167
|
+
|--------------------------|---------------------------------------------------------------------|
|
|
168
|
+
| `protoprompt` | `Pipeline`, `ContextBuilder`, `ContextInput`, `ContextOutput` |
|
|
169
|
+
| `protoprompt.store` | `StoreProtocol`, `InMemStore`, `ChromaStore` |
|
|
170
|
+
| `protoprompt.session` | `Session`, `CompressedBlock`, `HeuristicStrategy`, `LLMSummaryStrategy` |
|
|
171
|
+
| `protoprompt.profile` | `UserProfile`, `ProfileBuilder` |
|
|
172
|
+
| `protoprompt.tokens` | `TokenCounter`, `RegexTokenCounter`, `TiktokenCounter` |
|
|
173
|
+
| `protoprompt.llm` | `LLMClientProtocol` |
|
|
174
|
+
|
|
175
|
+
## Документация
|
|
176
|
+
|
|
177
|
+
Полная документация собирается в двух языковых версиях:
|
|
178
|
+
|
|
179
|
+
- 🇷🇺 Русская: <https://idxeed.github.io/protoprompt/ru/>
|
|
180
|
+
- 🇬🇧 English: <https://idxeed.github.io/protoprompt/en/>
|
|
181
|
+
|
|
182
|
+
Локальная сборка:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
pip install "protoprompt[dev]"
|
|
186
|
+
python scripts/build_docs.py --serve # обе версии на разных портах
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Разработка
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
git clone https://github.com/Idxeed/protoprompt
|
|
193
|
+
cd protoprompt
|
|
194
|
+
python -m venv .venv && source .venv/bin/activate
|
|
195
|
+
pip install -e ".[chroma,dev]"
|
|
196
|
+
pytest
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Лицензия
|
|
200
|
+
|
|
201
|
+
MIT — см. [LICENSE](LICENSE).
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# protoprompt
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Idxeed/protoprompt/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/Idxeed/protoprompt)
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](README.ru.md)
|
|
8
|
+
[](README.en.md)
|
|
9
|
+
|
|
10
|
+
[Русская версия](README.ru.md)
|
|
11
|
+
|
|
12
|
+
Layered context builder for LLM prompts. Three independent, composable
|
|
13
|
+
layers feed the model: **RAG over documents**, **compressed session
|
|
14
|
+
memory**, and an optional **user profile**. Pluggable vector store,
|
|
15
|
+
pluggable tokenizer, pluggable compression strategy.
|
|
16
|
+
|
|
17
|
+
## Why
|
|
18
|
+
|
|
19
|
+
Production LLM apps hit the same wall: the model needs context, but the
|
|
20
|
+
context window is finite. Hand-rolled prompt assembly gets messy:
|
|
21
|
+
documents are queried separately from session history, the system prompt
|
|
22
|
+
gets duplicated, and you end up rewriting the same glue code per project.
|
|
23
|
+
|
|
24
|
+
`protoprompt` separates the three concerns and gives each a clean
|
|
25
|
+
protocol:
|
|
26
|
+
|
|
27
|
+
- `StoreProtocol` — vector storage (in-memory for tests, ChromaDB for prod).
|
|
28
|
+
- `StrategyProtocol` — how to compress old turns of a long session.
|
|
29
|
+
- `TokenCounter` — how to budget the final prompt.
|
|
30
|
+
|
|
31
|
+
The `ContextBuilder` orchestrates all three. The result is a single
|
|
32
|
+
`system_prompt` plus a structured `ContextOutput` describing what went in
|
|
33
|
+
(head, tail, RAG, profile) so the UI can show provenance.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install protoprompt
|
|
39
|
+
|
|
40
|
+
# With ChromaDB backend
|
|
41
|
+
pip install "protoprompt[chroma]"
|
|
42
|
+
|
|
43
|
+
# With tiktoken-based tokenizer
|
|
44
|
+
pip install "protoprompt[tiktoken]"
|
|
45
|
+
|
|
46
|
+
# Dev / docs
|
|
47
|
+
pip install "protoprompt[chroma,dev]"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Quickstart
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
import asyncio
|
|
54
|
+
from protoprompt import (
|
|
55
|
+
InMemStore,
|
|
56
|
+
ContextBuilder,
|
|
57
|
+
ContextInput,
|
|
58
|
+
Pipeline,
|
|
59
|
+
HeuristicStrategy,
|
|
60
|
+
Session,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class MyLLM:
|
|
65
|
+
async def chat(self, messages, model="", **options):
|
|
66
|
+
return "stub"
|
|
67
|
+
|
|
68
|
+
async def embed(self, texts, model=""):
|
|
69
|
+
# replace with real embeddings
|
|
70
|
+
return [[0.1] * 384 for _ in texts]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
async def main():
|
|
74
|
+
store = InMemStore()
|
|
75
|
+
store.add("doc-1", ["Paris is the capital of France."], [[0.5] * 384])
|
|
76
|
+
llm = MyLLM()
|
|
77
|
+
|
|
78
|
+
builder = ContextBuilder(store, llm)
|
|
79
|
+
out = await builder.build(ContextInput(
|
|
80
|
+
query="What is the capital of France?",
|
|
81
|
+
system_prompt="You are a geography tutor.",
|
|
82
|
+
doc_ids=[1],
|
|
83
|
+
))
|
|
84
|
+
print(out.system_prompt)
|
|
85
|
+
|
|
86
|
+
pipeline = Pipeline(
|
|
87
|
+
store, llm,
|
|
88
|
+
strategy=HeuristicStrategy(),
|
|
89
|
+
compress_every_n=10,
|
|
90
|
+
)
|
|
91
|
+
session = Session(chat_id="c1", messages=[
|
|
92
|
+
{"role": "user", "content": "Hi"},
|
|
93
|
+
{"role": "assistant", "content": "Hello!"},
|
|
94
|
+
])
|
|
95
|
+
if pipeline.should_compress(len(session.messages)):
|
|
96
|
+
await pipeline.compress_and_store(session)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
asyncio.run(main())
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Architecture
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
+--------------------+
|
|
106
|
+
| ContextBuilder |
|
|
107
|
+
| (orchestrator) |
|
|
108
|
+
+---------+----------+
|
|
109
|
+
|
|
|
110
|
+
+------------------+------------------+------------------+
|
|
111
|
+
| | | |
|
|
112
|
+
v v v v
|
|
113
|
+
+---------------+ +----------------+ +---------------+ +---------+
|
|
114
|
+
| RAG retrieval | | Session memory | | User profile | | Store |
|
|
115
|
+
| (vector top-k)| | (compressed) | | (LLM-derived) | | query |
|
|
116
|
+
+---------------+ +----------------+ +---------------+ +---------+
|
|
117
|
+
| | |
|
|
118
|
+
+--------+---------+--------+---------+
|
|
119
|
+
| |
|
|
120
|
+
v v
|
|
121
|
+
+----------------+ +----------------+
|
|
122
|
+
| TokenCounter | | StoreProtocol |
|
|
123
|
+
| (pluggable) | | (in-mem/chroma)|
|
|
124
|
+
+----------------+ +----------------+
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Public API
|
|
128
|
+
|
|
129
|
+
| Module | Exports |
|
|
130
|
+
|--------------------------|-------------------------------------------------------------------|
|
|
131
|
+
| `protoprompt` | `Pipeline`, `ContextBuilder`, `ContextInput`, `ContextOutput` |
|
|
132
|
+
| `protoprompt.store` | `StoreProtocol`, `InMemStore`, `ChromaStore` |
|
|
133
|
+
| `protoprompt.session` | `Session`, `CompressedBlock`, `HeuristicStrategy`, `LLMSummaryStrategy` |
|
|
134
|
+
| `protoprompt.profile` | `UserProfile`, `ProfileBuilder` |
|
|
135
|
+
| `protoprompt.tokens` | `TokenCounter`, `RegexTokenCounter`, `TiktokenCounter` |
|
|
136
|
+
| `protoprompt.llm` | `LLMClientProtocol` |
|
|
137
|
+
|
|
138
|
+
## Documentation
|
|
139
|
+
|
|
140
|
+
Full docs are built in two languages:
|
|
141
|
+
|
|
142
|
+
- 🇷🇺 Russian: <https://idxeed.github.io/protoprompt/ru/>
|
|
143
|
+
- 🇬🇧 English: <https://idxeed.github.io/protoprompt/en/>
|
|
144
|
+
|
|
145
|
+
Build locally:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
pip install "protoprompt[dev]"
|
|
149
|
+
python scripts/build_docs.py --serve # both versions on different ports
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Development
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
git clone https://github.com/Idxeed/protoprompt
|
|
156
|
+
cd protoprompt
|
|
157
|
+
python -m venv .venv && source .venv/bin/activate
|
|
158
|
+
pip install -e ".[chroma,dev]"
|
|
159
|
+
pytest
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# protoprompt
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Idxeed/protoprompt/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/Idxeed/protoprompt)
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](README.ru.md)
|
|
8
|
+
[](README.en.md)
|
|
9
|
+
|
|
10
|
+
Слоистый сборщик контекста для LLM-промптов. Три независимых, компонуемых
|
|
11
|
+
слоя кормят модель: **RAG по документам**, **сжатая история сессии** и
|
|
12
|
+
опциональный **профиль пользователя**. Подключаемое векторное хранилище,
|
|
13
|
+
подключаемый токенайзер, подключаемая стратегия сжатия.
|
|
14
|
+
|
|
15
|
+
[English version](README.en.md)
|
|
16
|
+
|
|
17
|
+
## Зачем
|
|
18
|
+
|
|
19
|
+
Прод-LLM-приложения упираются в одну и ту же стену: модели нужен контекст,
|
|
20
|
+
но окно конечно. Собранная вручную сборка промпта превращается в кашу:
|
|
21
|
+
документы ищутся отдельно от истории, system prompt дублируется, и каждая
|
|
22
|
+
команда переписывает один и тот же клей.
|
|
23
|
+
|
|
24
|
+
`protoprompt` разделяет три задачи и даёт каждой чистый протокол:
|
|
25
|
+
|
|
26
|
+
- `StoreProtocol` — векторное хранилище (in-memory для тестов, ChromaDB для прода).
|
|
27
|
+
- `StrategyProtocol` — как сжимать старые ходы длинной сессии.
|
|
28
|
+
- `TokenCounter` — как считать бюджет финального промпта.
|
|
29
|
+
|
|
30
|
+
`ContextBuilder` оркестрирует все три. Результат — единый `system_prompt`
|
|
31
|
+
плюс структурированный `ContextOutput` с описанием того, что вошло (head,
|
|
32
|
+
tail, RAG, profile), чтобы UI мог показать provenance.
|
|
33
|
+
|
|
34
|
+
## Установка
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install protoprompt
|
|
38
|
+
|
|
39
|
+
# С ChromaDB-бэкендом
|
|
40
|
+
pip install "protoprompt[chroma]"
|
|
41
|
+
|
|
42
|
+
# С tiktoken-токенайзером
|
|
43
|
+
pip install "protoprompt[tiktoken]"
|
|
44
|
+
|
|
45
|
+
# Для разработки и документации
|
|
46
|
+
pip install "protoprompt[chroma,dev]"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Быстрый старт
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import asyncio
|
|
53
|
+
from protoprompt import (
|
|
54
|
+
InMemStore,
|
|
55
|
+
ContextBuilder,
|
|
56
|
+
ContextInput,
|
|
57
|
+
Pipeline,
|
|
58
|
+
HeuristicStrategy,
|
|
59
|
+
Session,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class MyLLM:
|
|
64
|
+
async def chat(self, messages, model="", **options):
|
|
65
|
+
return "заглушка"
|
|
66
|
+
|
|
67
|
+
async def embed(self, texts, model=""):
|
|
68
|
+
# замените на реальные эмбеддинги
|
|
69
|
+
return [[0.1] * 384 for _ in texts]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def main():
|
|
73
|
+
store = InMemStore()
|
|
74
|
+
store.add("doc-1", ["Париж — столица Франции."], [[0.5] * 384])
|
|
75
|
+
llm = MyLLM()
|
|
76
|
+
|
|
77
|
+
builder = ContextBuilder(store, llm)
|
|
78
|
+
out = await builder.build(ContextInput(
|
|
79
|
+
query="Какая столица Франции?",
|
|
80
|
+
system_prompt="Ты учитель географии.",
|
|
81
|
+
doc_ids=[1],
|
|
82
|
+
))
|
|
83
|
+
print(out.system_prompt)
|
|
84
|
+
|
|
85
|
+
pipeline = Pipeline(
|
|
86
|
+
store, llm,
|
|
87
|
+
strategy=HeuristicStrategy(),
|
|
88
|
+
compress_every_n=10,
|
|
89
|
+
)
|
|
90
|
+
session = Session(chat_id="c1", messages=[
|
|
91
|
+
{"role": "user", "content": "Привет"},
|
|
92
|
+
{"role": "assistant", "content": "Здравствуйте!"},
|
|
93
|
+
])
|
|
94
|
+
if pipeline.should_compress(len(session.messages)):
|
|
95
|
+
await pipeline.compress_and_store(session)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
asyncio.run(main())
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Архитектура
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
+--------------------+
|
|
105
|
+
| ContextBuilder |
|
|
106
|
+
| (оркестратор) |
|
|
107
|
+
+---------+----------+
|
|
108
|
+
|
|
|
109
|
+
+------------------+------------------+------------------+
|
|
110
|
+
| | | |
|
|
111
|
+
v v v v
|
|
112
|
+
+---------------+ +----------------+ +---------------+ +---------+
|
|
113
|
+
| RAG-поиск | | Память сессии | | Профиль польз.| | Store |
|
|
114
|
+
| (vector top-k)| | (сжатая) | | (из LLM) | | query |
|
|
115
|
+
+---------------+ +----------------+ +---------------+ +---------+
|
|
116
|
+
| | |
|
|
117
|
+
+--------+---------+--------+---------+
|
|
118
|
+
| |
|
|
119
|
+
v v
|
|
120
|
+
+----------------+ +----------------+
|
|
121
|
+
| TokenCounter | | StoreProtocol |
|
|
122
|
+
| (pluggable) | | (in-mem/chroma)|
|
|
123
|
+
+----------------+ +----------------+
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Публичный API
|
|
127
|
+
|
|
128
|
+
| Модуль | Экспорты |
|
|
129
|
+
|--------------------------|---------------------------------------------------------------------|
|
|
130
|
+
| `protoprompt` | `Pipeline`, `ContextBuilder`, `ContextInput`, `ContextOutput` |
|
|
131
|
+
| `protoprompt.store` | `StoreProtocol`, `InMemStore`, `ChromaStore` |
|
|
132
|
+
| `protoprompt.session` | `Session`, `CompressedBlock`, `HeuristicStrategy`, `LLMSummaryStrategy` |
|
|
133
|
+
| `protoprompt.profile` | `UserProfile`, `ProfileBuilder` |
|
|
134
|
+
| `protoprompt.tokens` | `TokenCounter`, `RegexTokenCounter`, `TiktokenCounter` |
|
|
135
|
+
| `protoprompt.llm` | `LLMClientProtocol` |
|
|
136
|
+
|
|
137
|
+
## Документация
|
|
138
|
+
|
|
139
|
+
Полная документация собирается в двух языковых версиях:
|
|
140
|
+
|
|
141
|
+
- 🇷🇺 Русская: <https://idxeed.github.io/protoprompt/ru/>
|
|
142
|
+
- 🇬🇧 English: <https://idxeed.github.io/protoprompt/en/>
|
|
143
|
+
|
|
144
|
+
Локальная сборка:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pip install "protoprompt[dev]"
|
|
148
|
+
python scripts/build_docs.py --serve # обе версии на разных портах
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Разработка
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
git clone https://github.com/Idxeed/protoprompt
|
|
155
|
+
cd protoprompt
|
|
156
|
+
python -m venv .venv && source .venv/bin/activate
|
|
157
|
+
pip install -e ".[chroma,dev]"
|
|
158
|
+
pytest
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Лицензия
|
|
162
|
+
|
|
163
|
+
MIT — см. [LICENSE](LICENSE).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# API: injector
|
|
2
|
+
|
|
3
|
+
## ContextBuilder
|
|
4
|
+
|
|
5
|
+
::: protoprompt.injector.ContextBuilder
|
|
6
|
+
|
|
7
|
+
## TokenBudgetedContextBuilder
|
|
8
|
+
|
|
9
|
+
::: protoprompt.injector_budgeted.TokenBudgetedContextBuilder
|
|
10
|
+
|
|
11
|
+
## BudgetReport
|
|
12
|
+
|
|
13
|
+
::: protoprompt.injector_budgeted.BudgetReport
|
|
14
|
+
|
|
15
|
+
## Exceptions
|
|
16
|
+
|
|
17
|
+
::: protoprompt.exceptions
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# API: session
|
|
2
|
+
|
|
3
|
+
## Session & CompressedBlock
|
|
4
|
+
|
|
5
|
+
::: protoprompt.session.types
|
|
6
|
+
|
|
7
|
+
## HeuristicStrategy
|
|
8
|
+
|
|
9
|
+
::: protoprompt.session.strategy.HeuristicStrategy
|
|
10
|
+
|
|
11
|
+
## LLMSummaryStrategy
|
|
12
|
+
|
|
13
|
+
::: protoprompt.session.strategy.LLMSummaryStrategy
|
|
14
|
+
|
|
15
|
+
## Compressor
|
|
16
|
+
|
|
17
|
+
::: protoprompt.session.compressor.Compressor
|