context-compiler-example-integrations 0.1.0__py3-none-any.whl

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.
Files changed (65) hide show
  1. context_compiler_example_integrations/README.md +71 -0
  2. context_compiler_example_integrations/__init__.py +1 -0
  3. context_compiler_example_integrations/examples/__init__.py +12 -0
  4. context_compiler_example_integrations/examples/_shared/__init__.py +1 -0
  5. context_compiler_example_integrations/examples/_shared/litellm_request.py +61 -0
  6. context_compiler_example_integrations/examples/_shared/provider_mode.py +91 -0
  7. context_compiler_example_integrations/examples/checkpoint_continuation/README.md +77 -0
  8. context_compiler_example_integrations/examples/checkpoint_continuation/example.py +169 -0
  9. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/README.md +85 -0
  10. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/app.py +205 -0
  11. context_compiler_example_integrations/examples/execution_authorization/README.md +31 -0
  12. context_compiler_example_integrations/examples/execution_authorization/expense_approval/README.md +77 -0
  13. context_compiler_example_integrations/examples/execution_authorization/expense_approval/__init__.py +1 -0
  14. context_compiler_example_integrations/examples/execution_authorization/expense_approval/example.py +168 -0
  15. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/README.md +97 -0
  16. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/__init__.py +1 -0
  17. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/app.py +312 -0
  18. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/model_approval.py +98 -0
  19. context_compiler_example_integrations/examples/gateway_middleware/README.md +49 -0
  20. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/README.md +40 -0
  21. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/__init__.py +1 -0
  22. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/example.py +220 -0
  23. context_compiler_example_integrations/examples/prompt_construction/README.md +27 -0
  24. context_compiler_example_integrations/examples/prompt_construction/litellm/README.md +197 -0
  25. context_compiler_example_integrations/examples/prompt_construction/litellm/basic.py +392 -0
  26. context_compiler_example_integrations/examples/prompt_construction/litellm/confirmation_helper.py +91 -0
  27. context_compiler_example_integrations/examples/prompt_construction/litellm/with_directive_drafter.py +524 -0
  28. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/README.md +92 -0
  29. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/__init__.py +1 -0
  30. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/example.py +205 -0
  31. context_compiler_example_integrations/examples/retrieval_filtering/README.md +65 -0
  32. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/README.md +120 -0
  33. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/__init__.py +1 -0
  34. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/example.py +320 -0
  35. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/README.md +123 -0
  36. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/__init__.py +1 -0
  37. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/example.py +300 -0
  38. context_compiler_example_integrations/examples/schema_selection/README.md +41 -0
  39. context_compiler_example_integrations/examples/schema_selection/litellm_response_format/response_format.py +218 -0
  40. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/README.md +60 -0
  41. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/example.py +171 -0
  42. context_compiler_example_integrations/examples/schema_selection/refund_intake/README.md +95 -0
  43. context_compiler_example_integrations/examples/schema_selection/refund_intake/__init__.py +1 -0
  44. context_compiler_example_integrations/examples/schema_selection/refund_intake/example.py +180 -0
  45. context_compiler_example_integrations/examples/tool_gating/README.md +55 -0
  46. context_compiler_example_integrations/examples/tool_gating/calendar_admin/README.md +34 -0
  47. context_compiler_example_integrations/examples/tool_gating/calendar_admin/__init__.py +1 -0
  48. context_compiler_example_integrations/examples/tool_gating/calendar_admin/example.py +195 -0
  49. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/README.md +93 -0
  50. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/__init__.py +1 -0
  51. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/example.py +250 -0
  52. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/live_model.py +369 -0
  53. context_compiler_example_integrations/reference_integrations/__init__.py +12 -0
  54. context_compiler_example_integrations/reference_integrations/litellm_proxy/README.md +251 -0
  55. context_compiler_example_integrations/reference_integrations/litellm_proxy/_checkpoint_support.py +146 -0
  56. context_compiler_example_integrations/reference_integrations/litellm_proxy/config.example.yaml +23 -0
  57. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook.py +163 -0
  58. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook_with_directive_drafter.py +289 -0
  59. context_compiler_example_integrations/reference_integrations/openwebui_pipe/README.md +233 -0
  60. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe.py +750 -0
  61. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe_with_directive_drafter.py +1045 -0
  62. context_compiler_example_integrations-0.1.0.dist-info/METADATA +110 -0
  63. context_compiler_example_integrations-0.1.0.dist-info/RECORD +65 -0
  64. context_compiler_example_integrations-0.1.0.dist-info/WHEEL +4 -0
  65. context_compiler_example_integrations-0.1.0.dist-info/licenses/LICENSE +173 -0
@@ -0,0 +1,320 @@
1
+ """ChromaDB retrieval filtering for HR policy lookup."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, Literal, Sequence, TypedDict, cast
5
+ from uuid import uuid4
6
+
7
+ import chromadb
8
+ from chromadb.api.models.Collection import Collection
9
+ from context_compiler import (
10
+ POLICY_PROHIBIT,
11
+ POLICY_USE,
12
+ State,
13
+ create_engine,
14
+ get_decision_state,
15
+ get_policy_items,
16
+ is_clarify,
17
+ )
18
+ from context_compiler.engine import Engine
19
+
20
+ EMPLOYEE_ACCESS = "employee_hr_access"
21
+ MANAGER_ACCESS = "manager_hr_access"
22
+
23
+ KEYWORD_DIMENSIONS = (
24
+ "employee",
25
+ "manager",
26
+ "executive",
27
+ "handbook",
28
+ "benefits",
29
+ "approvals",
30
+ "compensation",
31
+ )
32
+
33
+
34
+ class PolicyDocument(TypedDict):
35
+ document_id: str
36
+ title: str
37
+ audience: Literal["employee", "manager", "executive"]
38
+ keywords: list[str]
39
+ content: str
40
+
41
+
42
+ class RetrievalResult(TypedDict):
43
+ query: str
44
+ eligible_document_ids: list[str]
45
+ returned_document_ids: list[str]
46
+ blocked_reason: str | None
47
+
48
+
49
+ class RetrievalTurnResult(TypedDict):
50
+ decision_kind: Literal["clarify", "update", "passthrough"]
51
+ prompt_to_user: str | None
52
+ retrieval_result: RetrievalResult
53
+
54
+
55
+ def example_documents() -> list[PolicyDocument]:
56
+ return [
57
+ {
58
+ "document_id": "employee_handbook",
59
+ "title": "Employee Handbook",
60
+ "audience": "employee",
61
+ "keywords": ["employee", "handbook", "benefits", "leave"],
62
+ "content": "General HR policy, leave policy, and workplace expectations.",
63
+ },
64
+ {
65
+ "document_id": "manager_handbook",
66
+ "title": "Manager Handbook",
67
+ "audience": "manager",
68
+ "keywords": ["manager", "handbook", "approvals", "staffing"],
69
+ "content": "Manager escalation guidance, staffing policy, and approvals.",
70
+ },
71
+ {
72
+ "document_id": "executive_compensation_policy",
73
+ "title": "Executive Compensation Policy",
74
+ "audience": "executive",
75
+ "keywords": ["executive", "compensation", "bonus", "board"],
76
+ "content": "Executive compensation bands, board review, and bonus structure.",
77
+ },
78
+ ]
79
+
80
+
81
+ def _decision_kind_name(
82
+ decision: object,
83
+ ) -> Literal["clarify", "update", "passthrough"]:
84
+ if not isinstance(decision, dict):
85
+ raise ValueError("unexpected decision shape")
86
+
87
+ kind = decision.get("kind")
88
+ kind_name = getattr(kind, "value", None)
89
+ if kind_name not in {"clarify", "update", "passthrough"}:
90
+ raise ValueError(f"unexpected decision kind: {kind_name}")
91
+ return cast(Literal["clarify", "update", "passthrough"], kind_name)
92
+
93
+
94
+ def allowed_audiences_from_state(state: State) -> set[str]:
95
+ """Read allowed retrieval audiences from authoritative compiler state."""
96
+
97
+ use_items = set(get_policy_items(state, POLICY_USE))
98
+ prohibit_items = set(get_policy_items(state, POLICY_PROHIBIT))
99
+
100
+ if MANAGER_ACCESS in prohibit_items:
101
+ return set()
102
+
103
+ if MANAGER_ACCESS in use_items:
104
+ return {"employee", "manager"}
105
+
106
+ if EMPLOYEE_ACCESS in prohibit_items:
107
+ return set()
108
+
109
+ if EMPLOYEE_ACCESS in use_items:
110
+ return {"employee"}
111
+
112
+ return set()
113
+
114
+
115
+ def query_embedding(query: str) -> list[float]:
116
+ """Create a deterministic local embedding without any model call."""
117
+
118
+ normalized_terms = set(query.lower().split())
119
+ return [
120
+ 1.0 if dimension in normalized_terms else 0.0
121
+ for dimension in KEYWORD_DIMENSIONS
122
+ ]
123
+
124
+
125
+ def document_embedding(document: PolicyDocument) -> list[float]:
126
+ keyword_set = set(document["keywords"])
127
+ return [
128
+ 1.0 if dimension in keyword_set else 0.0 for dimension in KEYWORD_DIMENSIONS
129
+ ]
130
+
131
+
132
+ def audience_filter(allowed_audiences: set[str]) -> dict[str, object]:
133
+ return {"audience": {"$in": sorted(allowed_audiences)}}
134
+
135
+
136
+ @dataclass
137
+ class ChromaHRPolicyRetriever:
138
+ """Host-owned retriever backed by a local Chroma collection."""
139
+
140
+ collection: Collection
141
+ documents: list[PolicyDocument]
142
+
143
+ @classmethod
144
+ def build(
145
+ cls,
146
+ *,
147
+ documents: list[PolicyDocument] | None = None,
148
+ ) -> "ChromaHRPolicyRetriever":
149
+ if documents is None:
150
+ documents = example_documents()
151
+
152
+ client = chromadb.EphemeralClient()
153
+ collection = client.create_collection(
154
+ name=f"hr-policy-{uuid4()}",
155
+ metadata={"description": "HR policy retrieval filtering example"},
156
+ )
157
+ document_embeddings = cast(
158
+ list[Sequence[float]],
159
+ [document_embedding(document) for document in documents],
160
+ )
161
+ collection.add(
162
+ ids=[document["document_id"] for document in documents],
163
+ documents=[document["content"] for document in documents],
164
+ metadatas=[
165
+ {
166
+ "audience": document["audience"],
167
+ "title": document["title"],
168
+ }
169
+ for document in documents
170
+ ],
171
+ embeddings=document_embeddings,
172
+ )
173
+ return cls(collection=collection, documents=documents)
174
+
175
+ def search(self, query: str, *, allowed_audiences: set[str]) -> RetrievalResult:
176
+ if not allowed_audiences:
177
+ return {
178
+ "query": query,
179
+ "eligible_document_ids": [],
180
+ "returned_document_ids": [],
181
+ "blocked_reason": None,
182
+ }
183
+
184
+ where = cast(Any, audience_filter(allowed_audiences))
185
+ eligible = self.collection.get(where=where)
186
+ query_vector = cast(list[Sequence[float]], [query_embedding(query)])
187
+ query_results = self.collection.query(
188
+ query_embeddings=query_vector,
189
+ n_results=len(self.documents),
190
+ where=where,
191
+ )
192
+
193
+ eligible_document_ids = sorted(cast(list[str], eligible["ids"]))
194
+ returned_document_ids = self._rank_matching_documents(
195
+ query,
196
+ candidate_ids=cast(list[str], query_results["ids"][0]),
197
+ eligible_document_ids=eligible_document_ids,
198
+ )
199
+
200
+ return {
201
+ "query": query,
202
+ "eligible_document_ids": eligible_document_ids,
203
+ "returned_document_ids": returned_document_ids,
204
+ "blocked_reason": None,
205
+ }
206
+
207
+ def _rank_matching_documents(
208
+ self,
209
+ query: str,
210
+ *,
211
+ candidate_ids: list[str],
212
+ eligible_document_ids: list[str],
213
+ ) -> list[str]:
214
+ normalized_query_terms = set(query.lower().split())
215
+ documents_by_id = {
216
+ document["document_id"]: document for document in self.documents
217
+ }
218
+ scored_matches: list[tuple[int, str]] = []
219
+
220
+ for document_id in candidate_ids:
221
+ if document_id not in eligible_document_ids:
222
+ continue
223
+
224
+ keyword_overlap = len(
225
+ normalized_query_terms & set(documents_by_id[document_id]["keywords"])
226
+ )
227
+ if keyword_overlap == 0:
228
+ continue
229
+
230
+ scored_matches.append((keyword_overlap, document_id))
231
+
232
+ scored_matches.sort(key=lambda item: (-item[0], item[1]))
233
+ return [document_id for _, document_id in scored_matches]
234
+
235
+
236
+ def retrieve_hr_documents(
237
+ query: str,
238
+ *,
239
+ state: State,
240
+ retriever: ChromaHRPolicyRetriever,
241
+ ) -> RetrievalResult:
242
+ """Apply eligibility constraints before Chroma returns any documents."""
243
+
244
+ return retriever.search(
245
+ query,
246
+ allowed_audiences=allowed_audiences_from_state(state),
247
+ )
248
+
249
+
250
+ def handle_retrieval_turn(
251
+ engine: Engine,
252
+ *,
253
+ compiler_input: str,
254
+ query: str,
255
+ retriever: ChromaHRPolicyRetriever,
256
+ ) -> RetrievalTurnResult:
257
+ """Resolve policy updates, but block retrieval on contradictory turns."""
258
+
259
+ decision = engine.step(compiler_input)
260
+
261
+ if is_clarify(decision):
262
+ return {
263
+ "decision_kind": "clarify",
264
+ "prompt_to_user": decision.get("prompt_to_user"),
265
+ "retrieval_result": {
266
+ "query": query,
267
+ "eligible_document_ids": [],
268
+ "returned_document_ids": [],
269
+ "blocked_reason": "clarification required before retrieval policy changes",
270
+ },
271
+ }
272
+
273
+ authoritative_state = get_decision_state(decision)
274
+ if authoritative_state is None:
275
+ authoritative_state = engine.state
276
+
277
+ return {
278
+ "decision_kind": _decision_kind_name(decision),
279
+ "prompt_to_user": decision.get("prompt_to_user"),
280
+ "retrieval_result": retrieve_hr_documents(
281
+ query,
282
+ state=authoritative_state,
283
+ retriever=retriever,
284
+ ),
285
+ }
286
+
287
+
288
+ def run_demo() -> dict[str, RetrievalResult]:
289
+ """Run a deterministic ChromaDB retrieval-filtering demonstration."""
290
+
291
+ query = "handbook benefits"
292
+ retriever = ChromaHRPolicyRetriever.build()
293
+
294
+ absent_engine = create_engine()
295
+ employee_engine = create_engine()
296
+ employee_engine.step(f"use {EMPLOYEE_ACCESS}")
297
+ manager_engine = create_engine()
298
+ manager_engine.step(f"use {MANAGER_ACCESS}")
299
+
300
+ return {
301
+ "absent_state": retrieve_hr_documents(
302
+ query,
303
+ state=absent_engine.state,
304
+ retriever=retriever,
305
+ ),
306
+ "employee_access": retrieve_hr_documents(
307
+ query,
308
+ state=employee_engine.state,
309
+ retriever=retriever,
310
+ ),
311
+ "manager_access": retrieve_hr_documents(
312
+ query,
313
+ state=manager_engine.state,
314
+ retriever=retriever,
315
+ ),
316
+ }
317
+
318
+
319
+ if __name__ == "__main__":
320
+ print(run_demo())
@@ -0,0 +1,123 @@
1
+ # HR policy lookup
2
+
3
+ Authoritative state changes which HR documents the host may return for the
4
+ same lookup request. This example shows retrieval filtering for HR policy
5
+ lookup in plain Python.
6
+
7
+ ## Enforcement point
8
+
9
+ The enforcement point is host-owned retrieval filtering. The host owns the
10
+ document corpus and the retrieval function. Context Compiler owns the
11
+ authoritative policy state that decides which documents are eligible for
12
+ retrieval.
13
+
14
+ ## Runtime and domain
15
+
16
+ - Runtime: generic Python
17
+ - Domain: HR policy lookup
18
+
19
+ ## Ownership boundary
20
+
21
+ The host owns:
22
+
23
+ - the document set
24
+ - query handling
25
+ - retrieval and filtering behavior
26
+
27
+ Context Compiler owns:
28
+
29
+ - the authoritative access state
30
+ - the authoritative saved case premise
31
+ - clarification behavior for contradictory directives
32
+
33
+ This example does not call an LLM, does not use directive drafter, and does not
34
+ derive state from model output.
35
+
36
+ ## Retrieval rule
37
+
38
+ The example corpus contains:
39
+
40
+ - `employee_handbook`
41
+ - `leave_of_absence_policy`
42
+ - `manager_handbook`
43
+ - `executive_compensation_policy`
44
+
45
+ The host applies retrieval in this order:
46
+
47
+ - `use employee_hr_access` allows employee documents
48
+ - `use manager_hr_access` allows employee and manager documents
49
+ - absent state follows the documented default of returning no HR documents
50
+ - after eligibility is fixed, saved premise facts may narrow relevance inside
51
+ the eligible set
52
+
53
+ Policy controls eligibility. Premise controls relevance within that eligible
54
+ set. Premise does not grant access and does not select a collection.
55
+
56
+ For premise-driven relevance, the host applies a small deterministic rule:
57
+
58
+ `saved HR case facts -> case context -> relevant documents within eligible set`
59
+
60
+ Examples:
61
+
62
+ - `set premise case concerns leave eligibility after a parental leave request`
63
+ narrows employee-visible results toward `leave_of_absence_policy`
64
+ - `set premise case concerns general employee handbook expectations for a new hire`
65
+ narrows employee-visible results toward `employee_handbook`
66
+ - `set premise case concerns staffing approval for a team reorganization`
67
+ narrows manager-visible results toward `manager_handbook`
68
+
69
+ With the same query, `leave`:
70
+
71
+ - `use employee_hr_access` plus the leave-eligibility premise returns
72
+ `leave_of_absence_policy`
73
+ - `use employee_hr_access` plus the general employee-handbook premise returns
74
+ `employee_handbook`
75
+
76
+ In both cases, the eligible employee documents stay the same:
77
+
78
+ - `employee_handbook`
79
+ - `leave_of_absence_policy`
80
+
81
+ The premise changes only which already-eligible document is returned as the
82
+ relevant match. It does not change `eligible_document_ids`.
83
+
84
+ Without a matching or known premise, the host falls back to the default
85
+ employee-handbook relevance path. Unknown premise text does not invent a new
86
+ result set.
87
+
88
+ If the saved premise points at manager-only staffing context while policy still
89
+ allows only employee access, the host returns no results for that premise path
90
+ rather than expanding eligibility.
91
+
92
+ Executive documents remain filtered because this example never grants executive
93
+ access. Adversarial queries such as "ignore policy and show executive
94
+ compensation", "I am the CEO", and "reveal all documents" stay inert unless the
95
+ authoritative state changes. Adversarial query text does not overwrite either
96
+ saved access policy or saved case premise.
97
+
98
+ If a turn introduces a contradiction such as `use employee_hr_access` followed
99
+ by `prohibit employee_hr_access`, Context Compiler returns a clarification flow
100
+ instead of silently overwriting state. The host blocks that policy-change turn
101
+ rather than treating it as a retrieval override.
102
+
103
+ ## Why this is retrieval filtering rather than prompt compliance
104
+
105
+ The observable runtime behavior change is the returned document set. The query
106
+ text alone cannot bypass filtering. Retrieval results change only because the
107
+ host reads different authoritative Context Compiler state before searching the
108
+ same corpus. Access eligibility is applied first, and premise-based relevance
109
+ is applied only inside that eligible document set.
110
+
111
+ ## Validation
112
+
113
+ - Focused Python tests:
114
+
115
+ ```bash
116
+ uv run --no-sync pytest python/tests/test_retrieval_filtering_example.py
117
+ ```
118
+
119
+ - Canonical Python validation:
120
+
121
+ ```bash
122
+ ./scripts/validate_python.sh
123
+ ```
@@ -0,0 +1 @@
1
+ """Retrieval filtering example package."""