context-engineering-core 0.12.1__tar.gz → 0.15.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.
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/CHANGELOG.md +58 -1
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/PKG-INFO +33 -7
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/README.md +27 -6
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/pyproject.toml +4 -2
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/__init__.py +1 -1
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/cli.py +21 -1
- context_engineering_core-0.15.0/src/context_engine/embedding_data/LICENSE +33 -0
- context_engineering_core-0.15.0/src/context_engine/embedding_data/potion-base-8M-int8.npz +0 -0
- context_engineering_core-0.15.0/src/context_engine/embedding_data/potion-base-8M-vocab.txt +29528 -0
- context_engineering_core-0.15.0/src/context_engine/embeddings.py +249 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/data/freeze.json +2 -2
- context_engineering_core-0.15.0/src/context_engine/evaluation/data/paraphrases.json +38 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/grading.py +30 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/harness.py +1 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/strategies.py +134 -19
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/layers/retrieve.py +28 -6
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/mcp_server.py +10 -4
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/pipeline.py +19 -1
- context_engineering_core-0.15.0/src/context_engine/wordpiece.py +114 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/.gitignore +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/LICENSE +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/evidence_answer_policy.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/incident-demo.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/inspection-input.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/rolling_summary.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/sdk_quickstart.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/service-config.example.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/structured_answers.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/examples/validated_answer.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/__main__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/_sqlite.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/_windows_security.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/_windows_storage.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/adapters.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/answers.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/budget.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/config.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/context.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/demo.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/errors.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/__init__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/commands.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/corpus.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/data/ground_truth.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/data/pin_retention.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/data/protocol.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/data/scenario.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/data/summary_fixture.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/execution.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/fixtures.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/__init__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/__main__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/data/ground_truth.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/data/manifest.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/data/protocol.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/data/scenarios.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/data/scoring_manifest.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/data/scoring_protocol.json +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/heldout/scoring.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/protocol.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/reporting.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/results.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/evaluation/run_commands.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/inspection.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/layers/__init__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/layers/cap.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/layers/common.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/layers/pin.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/layers/summarize.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/layers/window.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/memory/__init__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/memory/codec.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/memory/demo.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/memory/store.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/models.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/__init__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/client.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/commands.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/contracts.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/credentials.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/memory.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/store.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/transport.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/providers/windows_credentials.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/py.typed +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/__init__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/__main__.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/app.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/auth.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/client.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/control.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/demo.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/integrations.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/schemas.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/worker.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/service/workers.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/summaries.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/tokens.py +0 -0
- {context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/work.py +0 -0
|
@@ -3,7 +3,64 @@
|
|
|
3
3
|
Earlier versions (0.1.0–0.9.6) are documented in `docs/C01_REPORT.md` through
|
|
4
4
|
`docs/C10_STORAGE_ACL_REPORT.md` and preserved as wheels under `archives/`.
|
|
5
5
|
|
|
6
|
-
## 0.
|
|
6
|
+
## 0.15.0 — 2026-10-31 (unreleased)
|
|
7
|
+
|
|
8
|
+
### Changed (behavior)
|
|
9
|
+
- Hybrid retrieval is the default (`assemble_context(embedder="builtin")`): the
|
|
10
|
+
bundled potion-base-8M model (8-bit vectors, ~7 MB in the package; MIT notice in
|
|
11
|
+
`embedding_data/LICENSE`) with a pure-Python WordPiece tokenizer. No download,
|
|
12
|
+
network or new dependency. `embedder=None` gives the pre-0.15.0 keyword-only path.
|
|
13
|
+
- Default `semantic_weight` 0.7 → 0.5: a needle-in-filler check showed 0.7 losing
|
|
14
|
+
exact keyword matches (22/31 vs 31/31); 0.5 is equal or better on every set.
|
|
15
|
+
- `strategy-eval` includes the hybrid strategies by default (`--no-semantic` to
|
|
16
|
+
skip; `--semantic` removed). `context-engine-mcp` is hybrid by default
|
|
17
|
+
(`--no-semantic`; `--semantic` removed).
|
|
18
|
+
- The frozen benchmark harness pins keyword-only retrieval.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- `BuiltinEmbedder`, `default_embedder()`, `context_engine.wordpiece`.
|
|
22
|
+
- Lenient grading v2 (`answer_correct_lenient`, `GRADERS`) beside frozen strict v1;
|
|
23
|
+
`scripts/regrade_live.py` writes `grading.json` for both live runs.
|
|
24
|
+
|
|
25
|
+
### Unchanged
|
|
26
|
+
- 0.14.0 wheel/freeze archived in `archives/c15-default-semantic-0150/`.
|
|
27
|
+
|
|
28
|
+
## 0.14.0 — 2026-10-31 (PyPI)
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- Optional hybrid retrieval: `assemble_context(..., embedder=, semantic_weight=0.7)`
|
|
32
|
+
(also via `MemoryStore.assemble`) ranks chunks by 0.7 x meaning + 0.3 x keyword
|
|
33
|
+
score. `context_engine.embeddings`: `Embedder` protocol, `Model2VecEmbedder`
|
|
34
|
+
(default model pinned: `minishlab/potion-base-8M@bf8b0566`, extra `[semantic]`),
|
|
35
|
+
`FastEmbedEmbedder` (extra `[fastembed]`), `FunctionEmbedder`. Bounded vector cache.
|
|
36
|
+
- `strategy-eval --semantic` (adds `retrieval_semantic`, `combined_semantic`) and
|
|
37
|
+
`context-engine-mcp --semantic`.
|
|
38
|
+
- Reworded questions: default retention 3/31 → 21/31 with the embedder; original
|
|
39
|
+
questions stay 31/31. Bake-off evidence in `output/embedding-bakeoff-001/`.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- `numpy` is now a declared dependency (it was already installed via `rank-bm25`).
|
|
43
|
+
- Missing optional extras give an install hint instead of a traceback.
|
|
44
|
+
|
|
45
|
+
### Unchanged
|
|
46
|
+
- Without an embedder, all 310 strategy-benchmark assemblies are byte-identical to
|
|
47
|
+
0.13.0 (archived in `archives/c14-semantic-0140/`).
|
|
48
|
+
|
|
49
|
+
## 0.13.0 — 2026-10-31 (unreleased)
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
- Reworded-question stress test: `strategy-eval --questions paraphrased` and
|
|
53
|
+
`compare_strategies(..., questions="paraphrased")`. 31 questions share no content
|
|
54
|
+
word (or 4-letter start of a 5+ letter word) with their evidence, enforced by
|
|
55
|
+
`paraphrase_overlaps`. Result: default retention falls from 31/31 to 3/31 at 900
|
|
56
|
+
and 3000 tokens (retrieval alone: 6/31 and 7/31). README updated.
|
|
57
|
+
- `assemble_strategy(..., question=...)` to assemble a strategy for any question.
|
|
58
|
+
|
|
59
|
+
### Unchanged
|
|
60
|
+
- Engine behavior and defaults. 0.12.1 wheel/freeze archived in
|
|
61
|
+
`archives/c13-paraphrase-0130/`.
|
|
62
|
+
|
|
63
|
+
## 0.12.1 — 2026-10-31 (PyPI)
|
|
7
64
|
|
|
8
65
|
### Changed (performance only; output identical)
|
|
9
66
|
- Budget fit checks compute only the request's estimated token count
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: context-engineering-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0
|
|
4
4
|
Summary: Provider-independent context layers, source contracts, and token budget accounting
|
|
5
5
|
Project-URL: Homepage, https://github.com/Nandu1729/Context-Engine
|
|
6
6
|
Project-URL: Repository, https://github.com/Nandu1729/Context-Engine
|
|
@@ -18,15 +18,20 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
18
18
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
19
|
Classifier: Typing :: Typed
|
|
20
20
|
Requires-Python: >=3.12
|
|
21
|
+
Requires-Dist: numpy>=1.26
|
|
21
22
|
Requires-Dist: pywin32==311; sys_platform == 'win32'
|
|
22
23
|
Requires-Dist: rank-bm25<0.3,>=0.2.2
|
|
23
24
|
Requires-Dist: tiktoken<0.15,>=0.14
|
|
25
|
+
Provides-Extra: fastembed
|
|
26
|
+
Requires-Dist: fastembed<0.10,>=0.9; extra == 'fastembed'
|
|
24
27
|
Provides-Extra: langchain
|
|
25
28
|
Requires-Dist: langchain-core<2,>=1.0; extra == 'langchain'
|
|
26
29
|
Provides-Extra: provider
|
|
27
30
|
Requires-Dist: httpx<0.29,>=0.28; extra == 'provider'
|
|
28
31
|
Provides-Extra: reports
|
|
29
32
|
Requires-Dist: matplotlib<3.12,>=3.11; extra == 'reports'
|
|
33
|
+
Provides-Extra: semantic
|
|
34
|
+
Requires-Dist: model2vec<0.11,>=0.10; extra == 'semantic'
|
|
30
35
|
Provides-Extra: service
|
|
31
36
|
Requires-Dist: fastapi<0.136,>=0.135; extra == 'service'
|
|
32
37
|
Requires-Dist: httpx<0.29,>=0.28; extra == 'service'
|
|
@@ -45,7 +50,7 @@ that fits the budget. Those messages keep the recent turns, the facts you pinned
|
|
|
45
50
|
and the older evidence that matches the question. It never calls a model by
|
|
46
51
|
itself, so you send the messages to any provider you like.
|
|
47
52
|
|
|
48
|
-
> **Status: alpha (0.
|
|
53
|
+
> **Status: alpha (0.15.0).** Good for developers to try locally. It is not yet
|
|
49
54
|
> proven on real-world data, and there is no hosted service. See
|
|
50
55
|
> [What is not proven yet](#what-is-not-proven-yet).
|
|
51
56
|
|
|
@@ -106,6 +111,21 @@ chat_model.invoke(langchain_messages(result)) # pip install 'context-engineerin
|
|
|
106
111
|
history = turns_from_openai(existing_openai_messages, scope) # reuse a chat history you already have
|
|
107
112
|
```
|
|
108
113
|
|
|
114
|
+
### Finds meaning, not just matching words
|
|
115
|
+
|
|
116
|
+
Retrieval combines keyword search with a small embedding model bundled in the
|
|
117
|
+
package, so "retailer" finds "merchant". It runs locally with numpy: no download,
|
|
118
|
+
no network, no extra dependency (the package is ~7 MB because of the model).
|
|
119
|
+
Ranking is 0.5 x meaning score + 0.5 x keyword score.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
result = assemble_context(..., embedder=None) # keyword-only, as before 0.15.0
|
|
123
|
+
from context_engine.embeddings import FastEmbedEmbedder, FunctionEmbedder, Model2VecEmbedder
|
|
124
|
+
result = assemble_context(..., embedder=FastEmbedEmbedder()) # more accurate, slower (extra [fastembed])
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`FunctionEmbedder` wraps your own embedding function or API.
|
|
128
|
+
|
|
109
129
|
### Use it from an MCP client
|
|
110
130
|
|
|
111
131
|
`context-engine-mcp --data-dir ./context-memory` runs a local MCP server (stdio) with
|
|
@@ -154,11 +174,17 @@ These are enforced in code and covered by about 1,400 tests:
|
|
|
154
174
|
- **Answer quality.** Tests measure whether the needed facts *reach* the model's
|
|
155
175
|
context, not whether the model then answers correctly. On the built-in
|
|
156
176
|
benchmark, the default settings keep 31 of 31 planted facts at 900 and 3000
|
|
157
|
-
tokens
|
|
158
|
-
the engine.
|
|
159
|
-
- **
|
|
160
|
-
|
|
161
|
-
|
|
177
|
+
tokens, and a live model run answered 31 of 31 correctly at 900 tokens. But
|
|
178
|
+
that benchmark is one synthetic conversation written alongside the engine.
|
|
179
|
+
- **Reworded questions.** When we reword the 31 benchmark questions so they share
|
|
180
|
+
no words with the stored facts, keyword-only retrieval keeps 3 of 31 facts; the
|
|
181
|
+
default hybrid retrieval keeps 21 of 31 (retrieval alone: 24–25 of 31), with no
|
|
182
|
+
loss on the original questions. In a live model run on the reworded questions,
|
|
183
|
+
keyword-only answered 3 of 31 correctly and hybrid 18 of 31 (21 of 31 with
|
|
184
|
+
lenient grading, which ignores trailing punctuation and dash characters). A fact
|
|
185
|
+
buried in a long, repetitive message and asked with different words is still
|
|
186
|
+
hard (12 of 31). Run the offline test: `context-engine strategy-eval --questions paraphrased`.
|
|
187
|
+
- **Real-world data.** There are no results yet on real user conversations.
|
|
162
188
|
- **Exact provider token counts.** Budgets use a local tokenizer estimate.
|
|
163
189
|
Providers may count differently. On small requests, provider counts were up
|
|
164
190
|
to 1.78× the local estimate in past tests, so leave headroom or calibrate.
|
|
@@ -9,7 +9,7 @@ that fits the budget. Those messages keep the recent turns, the facts you pinned
|
|
|
9
9
|
and the older evidence that matches the question. It never calls a model by
|
|
10
10
|
itself, so you send the messages to any provider you like.
|
|
11
11
|
|
|
12
|
-
> **Status: alpha (0.
|
|
12
|
+
> **Status: alpha (0.15.0).** Good for developers to try locally. It is not yet
|
|
13
13
|
> proven on real-world data, and there is no hosted service. See
|
|
14
14
|
> [What is not proven yet](#what-is-not-proven-yet).
|
|
15
15
|
|
|
@@ -70,6 +70,21 @@ chat_model.invoke(langchain_messages(result)) # pip install 'context-engineerin
|
|
|
70
70
|
history = turns_from_openai(existing_openai_messages, scope) # reuse a chat history you already have
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
### Finds meaning, not just matching words
|
|
74
|
+
|
|
75
|
+
Retrieval combines keyword search with a small embedding model bundled in the
|
|
76
|
+
package, so "retailer" finds "merchant". It runs locally with numpy: no download,
|
|
77
|
+
no network, no extra dependency (the package is ~7 MB because of the model).
|
|
78
|
+
Ranking is 0.5 x meaning score + 0.5 x keyword score.
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
result = assemble_context(..., embedder=None) # keyword-only, as before 0.15.0
|
|
82
|
+
from context_engine.embeddings import FastEmbedEmbedder, FunctionEmbedder, Model2VecEmbedder
|
|
83
|
+
result = assemble_context(..., embedder=FastEmbedEmbedder()) # more accurate, slower (extra [fastembed])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`FunctionEmbedder` wraps your own embedding function or API.
|
|
87
|
+
|
|
73
88
|
### Use it from an MCP client
|
|
74
89
|
|
|
75
90
|
`context-engine-mcp --data-dir ./context-memory` runs a local MCP server (stdio) with
|
|
@@ -118,11 +133,17 @@ These are enforced in code and covered by about 1,400 tests:
|
|
|
118
133
|
- **Answer quality.** Tests measure whether the needed facts *reach* the model's
|
|
119
134
|
context, not whether the model then answers correctly. On the built-in
|
|
120
135
|
benchmark, the default settings keep 31 of 31 planted facts at 900 and 3000
|
|
121
|
-
tokens
|
|
122
|
-
the engine.
|
|
123
|
-
- **
|
|
124
|
-
|
|
125
|
-
|
|
136
|
+
tokens, and a live model run answered 31 of 31 correctly at 900 tokens. But
|
|
137
|
+
that benchmark is one synthetic conversation written alongside the engine.
|
|
138
|
+
- **Reworded questions.** When we reword the 31 benchmark questions so they share
|
|
139
|
+
no words with the stored facts, keyword-only retrieval keeps 3 of 31 facts; the
|
|
140
|
+
default hybrid retrieval keeps 21 of 31 (retrieval alone: 24–25 of 31), with no
|
|
141
|
+
loss on the original questions. In a live model run on the reworded questions,
|
|
142
|
+
keyword-only answered 3 of 31 correctly and hybrid 18 of 31 (21 of 31 with
|
|
143
|
+
lenient grading, which ignores trailing punctuation and dash characters). A fact
|
|
144
|
+
buried in a long, repetitive message and asked with different words is still
|
|
145
|
+
hard (12 of 31). Run the offline test: `context-engine strategy-eval --questions paraphrased`.
|
|
146
|
+
- **Real-world data.** There are no results yet on real user conversations.
|
|
126
147
|
- **Exact provider token counts.** Budgets use a local tokenizer estimate.
|
|
127
148
|
Providers may count differently. On small requests, provider counts were up
|
|
128
149
|
to 1.78× the local estimate in past tests, so leave headroom or calibrate.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "context-engineering-core"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.15.0"
|
|
8
8
|
description = "Provider-independent context layers, source contracts, and token budget accounting"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -21,11 +21,13 @@ classifiers = [
|
|
|
21
21
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
22
|
"Typing :: Typed",
|
|
23
23
|
]
|
|
24
|
-
dependencies = ["tiktoken>=0.14,<0.15", "rank-bm25>=0.2.2,<0.3", "pywin32==311; sys_platform == 'win32'"]
|
|
24
|
+
dependencies = ["tiktoken>=0.14,<0.15", "rank-bm25>=0.2.2,<0.3", "numpy>=1.26", "pywin32==311; sys_platform == 'win32'"]
|
|
25
25
|
|
|
26
26
|
[project.optional-dependencies]
|
|
27
27
|
provider = ["httpx>=0.28,<0.29"]
|
|
28
28
|
langchain = ["langchain-core>=1.0,<2"]
|
|
29
|
+
semantic = ["model2vec>=0.10,<0.11"]
|
|
30
|
+
fastembed = ["fastembed>=0.9,<0.10"]
|
|
29
31
|
reports = ["matplotlib>=3.11,<3.12"]
|
|
30
32
|
service = ["fastapi>=0.135,<0.136", "uvicorn>=0.41,<0.42", "PyJWT[crypto]>=2.12,<3", "httpx>=0.28,<0.29"]
|
|
31
33
|
|
{context_engineering_core-0.12.1 → context_engineering_core-0.15.0}/src/context_engine/cli.py
RENAMED
|
@@ -81,6 +81,17 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
81
81
|
"--budget", type=int, action="append", help="Input allowance; repeatable"
|
|
82
82
|
)
|
|
83
83
|
strategies.add_argument("--probes", action="store_true", help="Include per-fact results")
|
|
84
|
+
strategies.add_argument(
|
|
85
|
+
"--questions",
|
|
86
|
+
choices=("original", "paraphrased"),
|
|
87
|
+
default="original",
|
|
88
|
+
help="paraphrased: reworded questions with no shared words (lexical stress test)",
|
|
89
|
+
)
|
|
90
|
+
strategies.add_argument(
|
|
91
|
+
"--no-semantic",
|
|
92
|
+
action="store_true",
|
|
93
|
+
help="Skip the hybrid strategies (retrieval_semantic, combined_semantic)",
|
|
94
|
+
)
|
|
84
95
|
strategies.add_argument("--data-dir", type=Path)
|
|
85
96
|
strategies.add_argument("--output", type=Path, help="Save JSON to a new file; never overwrite")
|
|
86
97
|
planned = commands.add_parser(
|
|
@@ -136,7 +147,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
136
147
|
budgets = None if args.budget is None else tuple(args.budget)
|
|
137
148
|
if budgets is not None and any(b <= 0 for b in budgets):
|
|
138
149
|
raise ContextEngineError("Budgets must be positive integers")
|
|
139
|
-
result = compare_strategies(
|
|
150
|
+
result = compare_strategies(
|
|
151
|
+
bundle,
|
|
152
|
+
budgets,
|
|
153
|
+
include_probes=args.probes,
|
|
154
|
+
questions=args.questions,
|
|
155
|
+
embedder=None if args.no_semantic else "builtin",
|
|
156
|
+
)
|
|
140
157
|
if args.output is not None:
|
|
141
158
|
save_inspection(args.output, result)
|
|
142
159
|
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
@@ -216,6 +233,9 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
216
233
|
except ContextEngineError as error:
|
|
217
234
|
print(json.dumps(error.to_dict()), file=sys.stderr)
|
|
218
235
|
return 1
|
|
236
|
+
except ImportError as error: # An optional extra (e.g. [semantic]) is missing.
|
|
237
|
+
print(json.dumps({"code": "missing_extra", "message": str(error)}), file=sys.stderr)
|
|
238
|
+
return 2
|
|
219
239
|
|
|
220
240
|
|
|
221
241
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Bundled embedding model data
|
|
2
|
+
============================
|
|
3
|
+
|
|
4
|
+
potion-base-8M-int8.npz and potion-base-8M-vocab.txt are derived from the
|
|
5
|
+
Model2Vec model "minishlab/potion-base-8M" (revision
|
|
6
|
+
bf8b056651a2c21b8d2565580b8569da283cab23), https://huggingface.co/minishlab/potion-base-8M,
|
|
7
|
+
licensed under the MIT License. Its vocabulary comes from BAAI/bge-base-en-v1.5
|
|
8
|
+
(MIT License). The vectors were quantized to 8-bit integers with one float32
|
|
9
|
+
scale per token by the Context Engine project; no other changes.
|
|
10
|
+
|
|
11
|
+
MIT License
|
|
12
|
+
|
|
13
|
+
Copyright (c) 2024 Thomas van Dongen
|
|
14
|
+
(copyright line as in the MIT license of the model2vec project; the model card
|
|
15
|
+
of minishlab/potion-base-8M declares "license: mit")
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
18
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
19
|
+
in the Software without restriction, including without limitation the rights
|
|
20
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
21
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
22
|
+
furnished to do so, subject to the following conditions:
|
|
23
|
+
|
|
24
|
+
The above copyright notice and this permission notice shall be included in all
|
|
25
|
+
copies or substantial portions of the Software.
|
|
26
|
+
|
|
27
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
28
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
29
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
30
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
31
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
32
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
33
|
+
SOFTWARE.
|