context-compiler 0.9.0.dev4__tar.gz → 0.9.0.dev6__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_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/PKG-INFO +25 -44
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/README.md +24 -35
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/01_llm_contradiction_error.py +18 -4
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/02_llm_constraint_guardrail.py +14 -6
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/03_llm_premise_guardrail.py +21 -3
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/04_llm_tool_denylist_guardrail.py +14 -6
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/05_llm_prompt_drift_vs_state.py +18 -6
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/06_llm_context_compaction.py +3 -2
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/07_llm_prompt_vs_state.py +37 -9
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/08_llm_replacement_precondition.py +16 -6
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/09_llm_confirmation_no_directive.py +22 -13
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/common.py +56 -29
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/01_persistent_guardrails.py +11 -3
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/02_configuration_and_correction.py +7 -3
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/03_ambiguity_with_error.py +6 -2
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/04_tool_governance_denylist.py +6 -3
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/05_llm_integration_pattern.py +7 -5
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/06_step_sequence_and_state_restore.py +8 -3
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/07_single_policy_correction.py +6 -2
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/README.md +0 -7
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/examples/_util.py +19 -3
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/pyproject.toml +2 -1
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/src/context_compiler/__init__.py +2 -20
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/src/context_compiler/decision_helpers.py +4 -20
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/src/context_compiler/engine.py +34 -47
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/src/context_compiler/grammar.py +33 -27
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/src/context_compiler/repl.py +103 -140
- context_compiler-0.9.0.dev4/examples/08_controller_preview_diff.py +0 -44
- context_compiler-0.9.0.dev4/src/context_compiler/audit.py +0 -23
- context_compiler-0.9.0.dev4/src/context_compiler/controller.py +0 -177
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/.gitignore +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/LICENSE +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/README.md +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/__init__.py +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/llm_client.py +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/run_demo.py +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/host_support/__init__.py +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/host_support/provider_mode.py +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/src/context_compiler/const.py +0 -0
- {context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/src/context_compiler/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: context-compiler
|
|
3
|
-
Version: 0.9.0.
|
|
3
|
+
Version: 0.9.0.dev6
|
|
4
4
|
Summary: Deterministic conversational state engine for LLM applications.
|
|
5
5
|
Project-URL: Homepage, https://github.com/rlippmann/context-compiler
|
|
6
6
|
Project-URL: Repository, https://github.com/rlippmann/context-compiler
|
|
@@ -18,14 +18,6 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
18
18
|
Requires-Python: >=3.11
|
|
19
19
|
Provides-Extra: demos
|
|
20
20
|
Requires-Dist: litellm>=1.0.0; extra == 'demos'
|
|
21
|
-
Provides-Extra: dev
|
|
22
|
-
Requires-Dist: coverage; extra == 'dev'
|
|
23
|
-
Requires-Dist: hypothesis; extra == 'dev'
|
|
24
|
-
Requires-Dist: mypy<2.0,>=1.12; extra == 'dev'
|
|
25
|
-
Requires-Dist: pre-commit; extra == 'dev'
|
|
26
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
27
|
-
Requires-Dist: pytest-cov; extra == 'dev'
|
|
28
|
-
Requires-Dist: ruff<1.0,>=0.12; extra == 'dev'
|
|
29
21
|
Description-Content-Type: text/markdown
|
|
30
22
|
|
|
31
23
|
# Context Compiler
|
|
@@ -179,7 +171,11 @@ decision = engine.step(user_input)
|
|
|
179
171
|
if is_error(decision):
|
|
180
172
|
show_to_user(decision["message"])
|
|
181
173
|
elif is_update(decision):
|
|
182
|
-
messages = build_messages(
|
|
174
|
+
messages = build_messages(
|
|
175
|
+
premise=engine.premise,
|
|
176
|
+
policies=engine.policies,
|
|
177
|
+
user_input=user_input,
|
|
178
|
+
)
|
|
183
179
|
render(call_llm(messages))
|
|
184
180
|
else:
|
|
185
181
|
render(call_llm(user_input))
|
|
@@ -223,10 +219,9 @@ Preload options load authoritative state:
|
|
|
223
219
|
- `--initial-state-json` / `--initial-state-file` load saved state
|
|
224
220
|
(via exported state JSON).
|
|
225
221
|
|
|
226
|
-
REPL commands (
|
|
222
|
+
REPL commands (not engine directives):
|
|
227
223
|
|
|
228
224
|
- `state` shows current saved state.
|
|
229
|
-
- `preview <input>` runs deterministic dry-run without mutating live state.
|
|
230
225
|
- `step <input>` is an explicit alias of normal bare-input step behavior.
|
|
231
226
|
|
|
232
227
|
Bare REPL input behavior remains unchanged.
|
|
@@ -267,7 +262,7 @@ Packaging notes:
|
|
|
267
262
|
### Development
|
|
268
263
|
|
|
269
264
|
```bash
|
|
270
|
-
uv sync --
|
|
265
|
+
uv sync --dev
|
|
271
266
|
uv run pytest
|
|
272
267
|
```
|
|
273
268
|
|
|
@@ -276,20 +271,20 @@ uv run pytest
|
|
|
276
271
|
Each user message produces a `Decision`.
|
|
277
272
|
|
|
278
273
|
```python
|
|
279
|
-
class
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
kind: Literal["error"]
|
|
288
|
-
message: str
|
|
289
|
-
|
|
290
|
-
Decision = NoDirectiveDecision | UpdateDecision | ErrorDecision
|
|
274
|
+
class DecisionKind(StrEnum):
|
|
275
|
+
NO_DIRECTIVE = "no_directive"
|
|
276
|
+
UPDATE = "update"
|
|
277
|
+
ERROR = "error"
|
|
278
|
+
|
|
279
|
+
class Decision(TypedDict):
|
|
280
|
+
kind: DecisionKind
|
|
281
|
+
message: str | None
|
|
291
282
|
```
|
|
292
283
|
|
|
284
|
+
`message` is structurally present on every `Decision`, but it is semantically
|
|
285
|
+
meaningful only for `error`. For `no_directive` and `update`, `message` is
|
|
286
|
+
`None`.
|
|
287
|
+
|
|
293
288
|
Meaning:
|
|
294
289
|
|
|
295
290
|
| kind | host behavior |
|
|
@@ -299,7 +294,7 @@ Meaning:
|
|
|
299
294
|
| error | show `message` and do not continue normal downstream processing yet |
|
|
300
295
|
|
|
301
296
|
For normal app code, prefer the exported decision helpers (`is_error`,
|
|
302
|
-
`is_update`, `is_no_directive`, `get_error_message
|
|
297
|
+
`is_update`, `is_no_directive`, `get_error_message`)
|
|
303
298
|
instead of direct key traversal.
|
|
304
299
|
|
|
305
300
|
See [docs/api-reference.md](docs/api-reference.md) for the full public API
|
|
@@ -307,26 +302,12 @@ reference.
|
|
|
307
302
|
|
|
308
303
|
Common API entry points:
|
|
309
304
|
|
|
310
|
-
- engine lifecycle: `create_engine(
|
|
305
|
+
- engine lifecycle: `create_engine()`, `engine.step(...)`,
|
|
311
306
|
`engine.premise`, `engine.policies`, `engine.export_json(...)`,
|
|
312
307
|
`engine.import_json(...)`
|
|
313
308
|
- decision helpers: `is_error(...)`, `is_update(...)`, `is_no_directive(...)`,
|
|
314
|
-
`get_error_message(...)
|
|
309
|
+
`get_error_message(...)`
|
|
315
310
|
- state transport: `engine.export_json(...)`, `engine.import_json(...)`
|
|
316
|
-
- controller API: `step(...)`
|
|
317
|
-
- audit APIs: `preview(...)`, `state_diff(...)`
|
|
318
|
-
|
|
319
|
-
### Controller And Audit APIs (Reusable Outside REPL)
|
|
320
|
-
|
|
321
|
-
- `step(engine, user_input)` returns a reusable result envelope around one
|
|
322
|
-
engine turn
|
|
323
|
-
- `preview(engine, user_input)` performs a deterministic dry run and restores
|
|
324
|
-
live engine state afterward
|
|
325
|
-
- `state_diff(state_before, state_after)` summarizes structural state changes
|
|
326
|
-
|
|
327
|
-
For examples and helper accessors such as `get_step_decision(...)`,
|
|
328
|
-
`get_preview_state_after(...)`, `preview_would_mutate(...)`, and
|
|
329
|
-
`diff_has_changes(...)`, see [docs/api-reference.md](docs/api-reference.md).
|
|
330
311
|
|
|
331
312
|
---
|
|
332
313
|
|
|
@@ -350,8 +331,8 @@ Identical input sequences always produce identical state.
|
|
|
350
331
|
For live engine-owned reads, use `engine.premise` and `engine.policies`.
|
|
351
332
|
`engine.policies` returns a caller-owned copy.
|
|
352
333
|
|
|
353
|
-
`engine.
|
|
354
|
-
|
|
334
|
+
Use `engine.export_json()` and `engine.import_json()` for persistence and
|
|
335
|
+
restoration.
|
|
355
336
|
|
|
356
337
|
---
|
|
357
338
|
|
|
@@ -149,7 +149,11 @@ decision = engine.step(user_input)
|
|
|
149
149
|
if is_error(decision):
|
|
150
150
|
show_to_user(decision["message"])
|
|
151
151
|
elif is_update(decision):
|
|
152
|
-
messages = build_messages(
|
|
152
|
+
messages = build_messages(
|
|
153
|
+
premise=engine.premise,
|
|
154
|
+
policies=engine.policies,
|
|
155
|
+
user_input=user_input,
|
|
156
|
+
)
|
|
153
157
|
render(call_llm(messages))
|
|
154
158
|
else:
|
|
155
159
|
render(call_llm(user_input))
|
|
@@ -193,10 +197,9 @@ Preload options load authoritative state:
|
|
|
193
197
|
- `--initial-state-json` / `--initial-state-file` load saved state
|
|
194
198
|
(via exported state JSON).
|
|
195
199
|
|
|
196
|
-
REPL commands (
|
|
200
|
+
REPL commands (not engine directives):
|
|
197
201
|
|
|
198
202
|
- `state` shows current saved state.
|
|
199
|
-
- `preview <input>` runs deterministic dry-run without mutating live state.
|
|
200
203
|
- `step <input>` is an explicit alias of normal bare-input step behavior.
|
|
201
204
|
|
|
202
205
|
Bare REPL input behavior remains unchanged.
|
|
@@ -237,7 +240,7 @@ Packaging notes:
|
|
|
237
240
|
### Development
|
|
238
241
|
|
|
239
242
|
```bash
|
|
240
|
-
uv sync --
|
|
243
|
+
uv sync --dev
|
|
241
244
|
uv run pytest
|
|
242
245
|
```
|
|
243
246
|
|
|
@@ -246,20 +249,20 @@ uv run pytest
|
|
|
246
249
|
Each user message produces a `Decision`.
|
|
247
250
|
|
|
248
251
|
```python
|
|
249
|
-
class
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
kind: Literal["error"]
|
|
258
|
-
message: str
|
|
259
|
-
|
|
260
|
-
Decision = NoDirectiveDecision | UpdateDecision | ErrorDecision
|
|
252
|
+
class DecisionKind(StrEnum):
|
|
253
|
+
NO_DIRECTIVE = "no_directive"
|
|
254
|
+
UPDATE = "update"
|
|
255
|
+
ERROR = "error"
|
|
256
|
+
|
|
257
|
+
class Decision(TypedDict):
|
|
258
|
+
kind: DecisionKind
|
|
259
|
+
message: str | None
|
|
261
260
|
```
|
|
262
261
|
|
|
262
|
+
`message` is structurally present on every `Decision`, but it is semantically
|
|
263
|
+
meaningful only for `error`. For `no_directive` and `update`, `message` is
|
|
264
|
+
`None`.
|
|
265
|
+
|
|
263
266
|
Meaning:
|
|
264
267
|
|
|
265
268
|
| kind | host behavior |
|
|
@@ -269,7 +272,7 @@ Meaning:
|
|
|
269
272
|
| error | show `message` and do not continue normal downstream processing yet |
|
|
270
273
|
|
|
271
274
|
For normal app code, prefer the exported decision helpers (`is_error`,
|
|
272
|
-
`is_update`, `is_no_directive`, `get_error_message
|
|
275
|
+
`is_update`, `is_no_directive`, `get_error_message`)
|
|
273
276
|
instead of direct key traversal.
|
|
274
277
|
|
|
275
278
|
See [docs/api-reference.md](docs/api-reference.md) for the full public API
|
|
@@ -277,26 +280,12 @@ reference.
|
|
|
277
280
|
|
|
278
281
|
Common API entry points:
|
|
279
282
|
|
|
280
|
-
- engine lifecycle: `create_engine(
|
|
283
|
+
- engine lifecycle: `create_engine()`, `engine.step(...)`,
|
|
281
284
|
`engine.premise`, `engine.policies`, `engine.export_json(...)`,
|
|
282
285
|
`engine.import_json(...)`
|
|
283
286
|
- decision helpers: `is_error(...)`, `is_update(...)`, `is_no_directive(...)`,
|
|
284
|
-
`get_error_message(...)
|
|
287
|
+
`get_error_message(...)`
|
|
285
288
|
- state transport: `engine.export_json(...)`, `engine.import_json(...)`
|
|
286
|
-
- controller API: `step(...)`
|
|
287
|
-
- audit APIs: `preview(...)`, `state_diff(...)`
|
|
288
|
-
|
|
289
|
-
### Controller And Audit APIs (Reusable Outside REPL)
|
|
290
|
-
|
|
291
|
-
- `step(engine, user_input)` returns a reusable result envelope around one
|
|
292
|
-
engine turn
|
|
293
|
-
- `preview(engine, user_input)` performs a deterministic dry run and restores
|
|
294
|
-
live engine state afterward
|
|
295
|
-
- `state_diff(state_before, state_after)` summarizes structural state changes
|
|
296
|
-
|
|
297
|
-
For examples and helper accessors such as `get_step_decision(...)`,
|
|
298
|
-
`get_preview_state_after(...)`, `preview_would_mutate(...)`, and
|
|
299
|
-
`diff_has_changes(...)`, see [docs/api-reference.md](docs/api-reference.md).
|
|
300
289
|
|
|
301
290
|
---
|
|
302
291
|
|
|
@@ -320,8 +309,8 @@ Identical input sequences always produce identical state.
|
|
|
320
309
|
For live engine-owned reads, use `engine.premise` and `engine.policies`.
|
|
321
310
|
`engine.policies` returns a caller-owned copy.
|
|
322
311
|
|
|
323
|
-
`engine.
|
|
324
|
-
|
|
312
|
+
Use `engine.export_json()` and `engine.import_json()` for persistence and
|
|
313
|
+
restoration.
|
|
325
314
|
|
|
326
315
|
---
|
|
327
316
|
|
{context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/01_llm_contradiction_error.py
RENAMED
|
@@ -7,6 +7,7 @@ from demos.common import (
|
|
|
7
7
|
build_reinjected_messages,
|
|
8
8
|
compact_user_turns,
|
|
9
9
|
extract_tag_value,
|
|
10
|
+
observe_engine,
|
|
10
11
|
print_decision,
|
|
11
12
|
print_host_check,
|
|
12
13
|
print_messages,
|
|
@@ -14,6 +15,7 @@ from demos.common import (
|
|
|
14
15
|
print_spec_report,
|
|
15
16
|
print_tag_comparison,
|
|
16
17
|
print_user_inputs,
|
|
18
|
+
state_observations,
|
|
17
19
|
yes_no,
|
|
18
20
|
)
|
|
19
21
|
from demos.llm_client import complete_messages
|
|
@@ -25,9 +27,11 @@ def main() -> None:
|
|
|
25
27
|
print_user_inputs(user_inputs)
|
|
26
28
|
|
|
27
29
|
first = engine.step(user_inputs[0])
|
|
28
|
-
|
|
30
|
+
premise, policies = observe_engine(engine)
|
|
31
|
+
print_decision("turn 1", first, premise=premise, policies=policies)
|
|
29
32
|
second = engine.step(user_inputs[1])
|
|
30
|
-
|
|
33
|
+
premise, policies = observe_engine(engine)
|
|
34
|
+
print_decision("turn 2", second, premise=premise, policies=policies)
|
|
31
35
|
|
|
32
36
|
baseline_messages = build_baseline_messages(
|
|
33
37
|
[
|
|
@@ -67,7 +71,12 @@ def main() -> None:
|
|
|
67
71
|
mediated_output = f"[no call] error required: {second['message']}\nACTION:error"
|
|
68
72
|
print_model_output("Compiler-mediated (full)", mediated_output)
|
|
69
73
|
else:
|
|
70
|
-
|
|
74
|
+
premise, policies = observe_engine(engine)
|
|
75
|
+
mediated_messages = build_mediated_messages_from_transcript(
|
|
76
|
+
premise=premise,
|
|
77
|
+
policies=policies,
|
|
78
|
+
user_turns=user_inputs,
|
|
79
|
+
)
|
|
71
80
|
print_messages("compiler-mediated (full)", mediated_messages)
|
|
72
81
|
mediated_output = complete_messages(mediated_messages)
|
|
73
82
|
print_model_output("Compiler-mediated (full)", mediated_output)
|
|
@@ -78,7 +87,12 @@ def main() -> None:
|
|
|
78
87
|
compact_output = f"[no call] error required: {compacted_prompt}\nACTION:error"
|
|
79
88
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
80
89
|
else:
|
|
81
|
-
|
|
90
|
+
compacted_premise, compacted_policies = state_observations(compacted_state)
|
|
91
|
+
compact_messages = build_mediated_messages_from_transcript(
|
|
92
|
+
premise=compacted_premise,
|
|
93
|
+
policies=compacted_policies,
|
|
94
|
+
user_turns=compacted_turns,
|
|
95
|
+
)
|
|
82
96
|
print_messages("compiler-mediated + compact", compact_messages)
|
|
83
97
|
compact_output = complete_messages(compact_messages)
|
|
84
98
|
print_model_output("Compiler-mediated + compact", compact_output)
|
{context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/02_llm_constraint_guardrail.py
RENAMED
|
@@ -8,12 +8,14 @@ from demos.common import (
|
|
|
8
8
|
build_mediated_messages_from_transcript,
|
|
9
9
|
build_reinjected_messages,
|
|
10
10
|
compact_user_turns,
|
|
11
|
+
observe_engine,
|
|
11
12
|
print_decision,
|
|
12
13
|
print_host_check,
|
|
13
14
|
print_messages,
|
|
14
15
|
print_model_output,
|
|
15
16
|
print_spec_report,
|
|
16
17
|
print_user_inputs,
|
|
18
|
+
state_observations,
|
|
17
19
|
yes_no,
|
|
18
20
|
)
|
|
19
21
|
from demos.llm_client import complete_messages
|
|
@@ -115,10 +117,12 @@ def main() -> None:
|
|
|
115
117
|
print_user_inputs(user_inputs)
|
|
116
118
|
|
|
117
119
|
first = engine.step(user_inputs[0])
|
|
118
|
-
|
|
120
|
+
premise, policies = observe_engine(engine)
|
|
121
|
+
print_decision("turn 1", first, premise=premise, policies=policies)
|
|
119
122
|
|
|
120
123
|
second = engine.step(user_inputs[1])
|
|
121
|
-
|
|
124
|
+
premise, policies = observe_engine(engine)
|
|
125
|
+
print_decision("turn 2", second, premise=premise, policies=policies)
|
|
122
126
|
|
|
123
127
|
baseline_messages = build_baseline_messages(
|
|
124
128
|
[user_inputs[1]],
|
|
@@ -154,9 +158,11 @@ def main() -> None:
|
|
|
154
158
|
reinjected_safe_alternative = safe_alternative_detected(reinjected_output)
|
|
155
159
|
reinjected_violation = recipe_includes_prohibited_item(reinjected_output)
|
|
156
160
|
|
|
161
|
+
premise, policies = observe_engine(engine)
|
|
157
162
|
mediated_messages = build_mediated_messages_from_transcript(
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
premise=premise,
|
|
164
|
+
policies=policies,
|
|
165
|
+
user_turns=user_inputs,
|
|
160
166
|
extra_system_prompt=(
|
|
161
167
|
"If the user requests a prohibited item, refuse the literal request. "
|
|
162
168
|
"State briefly that the request conflicts with compiled policy, then provide "
|
|
@@ -178,9 +184,11 @@ def main() -> None:
|
|
|
178
184
|
compact_refusal = True
|
|
179
185
|
compact_violation = False
|
|
180
186
|
else:
|
|
187
|
+
compacted_premise, compacted_policies = state_observations(compacted_state)
|
|
181
188
|
compact_messages = build_mediated_messages_from_transcript(
|
|
182
|
-
|
|
183
|
-
|
|
189
|
+
premise=compacted_premise,
|
|
190
|
+
policies=compacted_policies,
|
|
191
|
+
user_turns=compacted_turns,
|
|
184
192
|
extra_system_prompt=(
|
|
185
193
|
"If the user requests a prohibited item, refuse the literal request. "
|
|
186
194
|
"State briefly that the request conflicts with compiled policy, then provide "
|
{context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/03_llm_premise_guardrail.py
RENAMED
|
@@ -9,6 +9,7 @@ from demos.common import (
|
|
|
9
9
|
build_reinjected_messages,
|
|
10
10
|
compact_user_turns,
|
|
11
11
|
extract_tag_value,
|
|
12
|
+
observe_engine,
|
|
12
13
|
print_decision,
|
|
13
14
|
print_host_check,
|
|
14
15
|
print_messages,
|
|
@@ -16,6 +17,7 @@ from demos.common import (
|
|
|
16
17
|
print_spec_report,
|
|
17
18
|
print_tag_comparison,
|
|
18
19
|
print_user_inputs,
|
|
20
|
+
state_observations,
|
|
19
21
|
yes_no,
|
|
20
22
|
)
|
|
21
23
|
from demos.llm_client import complete_messages
|
|
@@ -78,7 +80,13 @@ def main() -> None:
|
|
|
78
80
|
|
|
79
81
|
for index, user_input in enumerate(user_inputs, start=1):
|
|
80
82
|
decision = engine.step(user_input)
|
|
81
|
-
|
|
83
|
+
premise, policies = observe_engine(engine)
|
|
84
|
+
print_decision(
|
|
85
|
+
f"turn {index}",
|
|
86
|
+
decision,
|
|
87
|
+
premise=premise,
|
|
88
|
+
policies=policies,
|
|
89
|
+
)
|
|
82
90
|
|
|
83
91
|
baseline_messages = build_baseline_messages(
|
|
84
92
|
[user_inputs[0], user_inputs[1], user_inputs[2]],
|
|
@@ -100,7 +108,12 @@ def main() -> None:
|
|
|
100
108
|
reinjected_output = complete_messages(reinjected_messages)
|
|
101
109
|
print_model_output("Reinjected-state", reinjected_output)
|
|
102
110
|
|
|
103
|
-
|
|
111
|
+
premise, policies = observe_engine(engine)
|
|
112
|
+
mediated_messages = build_mediated_messages_from_transcript(
|
|
113
|
+
premise=premise,
|
|
114
|
+
policies=policies,
|
|
115
|
+
user_turns=user_inputs,
|
|
116
|
+
)
|
|
104
117
|
print_messages("compiler-mediated (full)", mediated_messages)
|
|
105
118
|
mediated_output = complete_messages(mediated_messages)
|
|
106
119
|
print_model_output("Compiler-mediated (full)", mediated_output)
|
|
@@ -111,7 +124,12 @@ def main() -> None:
|
|
|
111
124
|
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
112
125
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
113
126
|
else:
|
|
114
|
-
|
|
127
|
+
compacted_premise, compacted_policies = state_observations(compacted_state)
|
|
128
|
+
compact_messages = build_mediated_messages_from_transcript(
|
|
129
|
+
premise=compacted_premise,
|
|
130
|
+
policies=compacted_policies,
|
|
131
|
+
user_turns=compacted_turns,
|
|
132
|
+
)
|
|
115
133
|
print_messages("compiler-mediated + compact", compact_messages)
|
|
116
134
|
compact_output = complete_messages(compact_messages)
|
|
117
135
|
print_model_output("Compiler-mediated + compact", compact_output)
|
{context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/04_llm_tool_denylist_guardrail.py
RENAMED
|
@@ -10,6 +10,7 @@ from demos.common import (
|
|
|
10
10
|
compact_user_turns,
|
|
11
11
|
extract_tag_value,
|
|
12
12
|
is_verbose,
|
|
13
|
+
observe_engine,
|
|
13
14
|
print_decision,
|
|
14
15
|
print_host_check,
|
|
15
16
|
print_messages,
|
|
@@ -17,6 +18,7 @@ from demos.common import (
|
|
|
17
18
|
print_spec_report,
|
|
18
19
|
print_tag_comparison,
|
|
19
20
|
print_user_inputs,
|
|
21
|
+
state_observations,
|
|
20
22
|
)
|
|
21
23
|
from demos.llm_client import complete_messages
|
|
22
24
|
|
|
@@ -69,10 +71,12 @@ def main() -> None:
|
|
|
69
71
|
print_user_inputs(user_inputs)
|
|
70
72
|
|
|
71
73
|
first = engine.step(user_inputs[0])
|
|
72
|
-
|
|
74
|
+
premise, policies = observe_engine(engine)
|
|
75
|
+
print_decision("turn 1", first, premise=premise, policies=policies)
|
|
73
76
|
|
|
74
77
|
second = engine.step(user_inputs[1])
|
|
75
|
-
|
|
78
|
+
premise, policies = observe_engine(engine)
|
|
79
|
+
print_decision("turn 2", second, premise=premise, policies=policies)
|
|
76
80
|
|
|
77
81
|
baseline_messages = build_baseline_messages(
|
|
78
82
|
[user_inputs[1]],
|
|
@@ -107,9 +111,11 @@ def main() -> None:
|
|
|
107
111
|
reinjected_output = complete_messages(reinjected_messages)
|
|
108
112
|
print_model_output("Reinjected-state", reinjected_output)
|
|
109
113
|
|
|
114
|
+
premise, policies = observe_engine(engine)
|
|
110
115
|
mediated_messages = build_mediated_messages_from_transcript(
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
premise=premise,
|
|
117
|
+
policies=policies,
|
|
118
|
+
user_turns=user_inputs,
|
|
113
119
|
extra_system_prompt=(
|
|
114
120
|
"Only choose tools that are not prohibited."
|
|
115
121
|
+ "\nCandidate tools: "
|
|
@@ -128,9 +134,11 @@ def main() -> None:
|
|
|
128
134
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
129
135
|
compact_tool = None
|
|
130
136
|
else:
|
|
137
|
+
compacted_premise, compacted_policies = state_observations(compacted_state)
|
|
131
138
|
compact_messages = build_mediated_messages_from_transcript(
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
premise=compacted_premise,
|
|
140
|
+
policies=compacted_policies,
|
|
141
|
+
user_turns=compacted_turns,
|
|
134
142
|
extra_system_prompt=(
|
|
135
143
|
"Only choose tools that are not prohibited."
|
|
136
144
|
+ "\nCandidate tools: "
|
{context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/05_llm_prompt_drift_vs_state.py
RENAMED
|
@@ -11,6 +11,7 @@ from demos.common import (
|
|
|
11
11
|
build_reinjected_messages,
|
|
12
12
|
compact_user_turns,
|
|
13
13
|
extract_tag_value,
|
|
14
|
+
observe_engine,
|
|
14
15
|
print_decision,
|
|
15
16
|
print_host_check,
|
|
16
17
|
print_messages,
|
|
@@ -18,6 +19,7 @@ from demos.common import (
|
|
|
18
19
|
print_spec_report,
|
|
19
20
|
print_tag_comparison,
|
|
20
21
|
print_user_inputs,
|
|
22
|
+
state_observations,
|
|
21
23
|
yes_no,
|
|
22
24
|
)
|
|
23
25
|
from demos.llm_client import complete_messages
|
|
@@ -218,7 +220,13 @@ def _run_demo(turns: int = _DEFAULT_TURNS) -> None:
|
|
|
218
220
|
|
|
219
221
|
for index, user_input in enumerate(user_inputs, start=1):
|
|
220
222
|
decision = engine.step(user_input)
|
|
221
|
-
|
|
223
|
+
premise, policies = observe_engine(engine)
|
|
224
|
+
print_decision(
|
|
225
|
+
f"turn {index}",
|
|
226
|
+
decision,
|
|
227
|
+
premise=premise,
|
|
228
|
+
policies=policies,
|
|
229
|
+
)
|
|
222
230
|
|
|
223
231
|
baseline_messages = build_baseline_messages(
|
|
224
232
|
user_inputs,
|
|
@@ -242,9 +250,11 @@ def _run_demo(turns: int = _DEFAULT_TURNS) -> None:
|
|
|
242
250
|
reinjected_output = complete_messages(reinjected_messages)
|
|
243
251
|
print_model_output("Reinjected-state", reinjected_output)
|
|
244
252
|
|
|
253
|
+
premise, policies = observe_engine(engine)
|
|
245
254
|
mediated_messages = build_mediated_messages_from_transcript(
|
|
246
|
-
|
|
247
|
-
|
|
255
|
+
premise=premise,
|
|
256
|
+
policies=policies,
|
|
257
|
+
user_turns=user_inputs,
|
|
248
258
|
extra_system_prompt=_FORMAT_CONTRACT_SYSTEM_PROMPT,
|
|
249
259
|
)
|
|
250
260
|
print_messages("compiler-mediated (full)", mediated_messages)
|
|
@@ -257,7 +267,8 @@ def _run_demo(turns: int = _DEFAULT_TURNS) -> None:
|
|
|
257
267
|
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
258
268
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
259
269
|
else:
|
|
260
|
-
|
|
270
|
+
compacted_premise, compacted_policies = state_observations(compacted_state)
|
|
271
|
+
premise_value = compacted_premise
|
|
261
272
|
if (
|
|
262
273
|
premise_value is not None
|
|
263
274
|
and _ORIGINAL_DIRECTIVE not in compacted_turns
|
|
@@ -265,8 +276,9 @@ def _run_demo(turns: int = _DEFAULT_TURNS) -> None:
|
|
|
265
276
|
):
|
|
266
277
|
compacted_turns = [f"Premise reminder: {premise_value}", *compacted_turns]
|
|
267
278
|
compact_messages = build_mediated_messages_from_transcript(
|
|
268
|
-
|
|
269
|
-
|
|
279
|
+
premise=compacted_premise,
|
|
280
|
+
policies=compacted_policies,
|
|
281
|
+
user_turns=compacted_turns,
|
|
270
282
|
extra_system_prompt=_FORMAT_CONTRACT_SYSTEM_PROMPT,
|
|
271
283
|
)
|
|
272
284
|
print_messages("compiler-mediated + compact", compact_messages)
|
{context_compiler-0.9.0.dev4 → context_compiler-0.9.0.dev6}/demos/06_llm_context_compaction.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Demo 6: host-side prompt replacement from authoritative step-derived state."""
|
|
2
2
|
|
|
3
3
|
from context_compiler import DECISION_UPDATE, create_engine
|
|
4
|
-
from demos.common import compact_user_turns, is_verbose, print_info_report
|
|
4
|
+
from demos.common import compact_user_turns, is_verbose, print_info_report, state_observations
|
|
5
5
|
|
|
6
6
|
DEMO_NAME = "06_context_compaction — superseded directives eliminated"
|
|
7
7
|
FINAL_PREMISE = "chickpea curry"
|
|
@@ -148,8 +148,9 @@ def main() -> None:
|
|
|
148
148
|
baseline_context = "\n".join(f"User: {turn}" for turn in transcript_turns)
|
|
149
149
|
compiled_context = f"- premise: {compiled_premise}"
|
|
150
150
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(transcript_turns)
|
|
151
|
+
compacted_premise, _compacted_policies = state_observations(compacted_state)
|
|
151
152
|
assert compacted_prompt is None
|
|
152
|
-
assert
|
|
153
|
+
assert compacted_premise == FINAL_PREMISE
|
|
153
154
|
compacted_context = "\n".join(f"User: {turn}" for turn in compacted_turns)
|
|
154
155
|
baseline_prompt = _build_baseline_prompt(transcript_turns)
|
|
155
156
|
compiled_prompt = _build_compiled_prompt(compiled_premise)
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
"""Demo 7: prompt engineering and compiled state are complementary."""
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
+
from collections.abc import Mapping
|
|
4
5
|
|
|
5
|
-
from context_compiler import
|
|
6
|
+
from context_compiler import create_engine
|
|
7
|
+
from context_compiler.engine import PolicyValue
|
|
6
8
|
from demos.common import (
|
|
7
9
|
build_baseline_messages,
|
|
8
10
|
build_compiled_system_prompt,
|
|
9
11
|
build_reinjected_messages,
|
|
10
12
|
compact_user_turns,
|
|
11
13
|
extract_tag_value,
|
|
14
|
+
observe_engine,
|
|
12
15
|
print_decision,
|
|
13
16
|
print_host_check,
|
|
14
17
|
print_messages,
|
|
15
18
|
print_model_output,
|
|
16
19
|
print_spec_report,
|
|
17
20
|
print_user_inputs,
|
|
21
|
+
state_observations,
|
|
18
22
|
yes_no,
|
|
19
23
|
)
|
|
20
24
|
from demos.llm_client import Message, complete_messages
|
|
@@ -74,14 +78,22 @@ def build_strong_messages(user_inputs: list[str]) -> list[Message]:
|
|
|
74
78
|
)
|
|
75
79
|
|
|
76
80
|
|
|
77
|
-
def build_compiler_messages(
|
|
78
|
-
|
|
81
|
+
def build_compiler_messages(
|
|
82
|
+
*, premise: str | None, policies: Mapping[str, PolicyValue], user_inputs: list[str]
|
|
83
|
+
) -> list[Message]:
|
|
84
|
+
compiled_prefix = build_compiled_system_prompt(premise=premise, policies=policies)
|
|
79
85
|
compiler_system_prompt = f"{compiled_prefix}\n{STRONG_PROMPT_ENGINEERING_TEXT}"
|
|
80
86
|
return build_baseline_messages(user_inputs, baseline_system_prompt=compiler_system_prompt)
|
|
81
87
|
|
|
82
88
|
|
|
83
|
-
def build_compact_compiler_messages(
|
|
84
|
-
|
|
89
|
+
def build_compact_compiler_messages(
|
|
90
|
+
*, premise: str | None, policies: Mapping[str, PolicyValue], compacted_inputs: list[str]
|
|
91
|
+
) -> list[Message]:
|
|
92
|
+
return build_compiler_messages(
|
|
93
|
+
premise=premise,
|
|
94
|
+
policies=policies,
|
|
95
|
+
user_inputs=compacted_inputs,
|
|
96
|
+
)
|
|
85
97
|
|
|
86
98
|
|
|
87
99
|
def _actual_summary(*, weak_pass: bool, strong_pass: bool, compiler_pass: bool) -> str:
|
|
@@ -108,7 +120,13 @@ def main() -> None:
|
|
|
108
120
|
|
|
109
121
|
for index, user_input in enumerate(USER_INPUTS, start=1):
|
|
110
122
|
decision = engine.step(user_input)
|
|
111
|
-
|
|
123
|
+
premise, policies = observe_engine(engine)
|
|
124
|
+
print_decision(
|
|
125
|
+
f"turn {index}",
|
|
126
|
+
decision,
|
|
127
|
+
premise=premise,
|
|
128
|
+
policies=policies,
|
|
129
|
+
)
|
|
112
130
|
|
|
113
131
|
weak_messages = build_weak_messages(USER_INPUTS)
|
|
114
132
|
print_messages("weak-baseline", weak_messages)
|
|
@@ -131,7 +149,12 @@ def main() -> None:
|
|
|
131
149
|
reinjected_output = complete_messages(reinjected_messages)
|
|
132
150
|
print_model_output("Reinjected-state", reinjected_output)
|
|
133
151
|
|
|
134
|
-
|
|
152
|
+
premise, policies = observe_engine(engine)
|
|
153
|
+
compiler_messages = build_compiler_messages(
|
|
154
|
+
premise=premise,
|
|
155
|
+
policies=policies,
|
|
156
|
+
user_inputs=USER_INPUTS,
|
|
157
|
+
)
|
|
135
158
|
print_messages("compiler-mediated (full)", compiler_messages)
|
|
136
159
|
compiler_output = complete_messages(compiler_messages)
|
|
137
160
|
print_model_output("Compiler-mediated (full)", compiler_output)
|
|
@@ -142,7 +165,12 @@ def main() -> None:
|
|
|
142
165
|
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
143
166
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
144
167
|
else:
|
|
145
|
-
|
|
168
|
+
compacted_premise, compacted_policies = state_observations(compacted_state)
|
|
169
|
+
compact_messages = build_compact_compiler_messages(
|
|
170
|
+
premise=compacted_premise,
|
|
171
|
+
policies=compacted_policies,
|
|
172
|
+
compacted_inputs=compacted_inputs,
|
|
173
|
+
)
|
|
146
174
|
print_messages("compiler-mediated + compact", compact_messages)
|
|
147
175
|
compact_output = complete_messages(compact_messages)
|
|
148
176
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
@@ -158,7 +186,7 @@ def main() -> None:
|
|
|
158
186
|
compiler_pass = premise_matches_expected(compiler_output)
|
|
159
187
|
compact_pass = compacted_prompt is None and premise_matches_expected(compact_output)
|
|
160
188
|
|
|
161
|
-
compiled_prefix = build_compiled_system_prompt(
|
|
189
|
+
compiled_prefix = build_compiled_system_prompt(premise=premise, policies=policies)
|
|
162
190
|
shared_prompt_text = compiler_messages[0]["content"].endswith(STRONG_PROMPT_ENGINEERING_TEXT)
|
|
163
191
|
compiler_augmented_only = (
|
|
164
192
|
compiler_messages[1:] == strong_messages[1:]
|