powerailabs-contextkit 0.2.0__tar.gz → 0.3.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: powerailabs-contextkit
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Assemble: declare prioritized, pinnable context blocks; pack them to a token budget with an inspectable receipt.
5
5
  Author: Raghav Mishra
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "powerailabs-contextkit"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "Assemble: declare prioritized, pinnable context blocks; pack them to a token budget with an inspectable receipt."
5
5
  requires-python = ">=3.11"
6
6
  license = "MIT"
@@ -154,6 +154,46 @@ class Context:
154
154
  rest = [m for m in self._messages if m["role"] != "system"]
155
155
  return system, rest
156
156
 
157
+ def for_gemini(self) -> tuple[str, list[dict]]:
158
+ """Gemini adapter: returns ``(system_instruction, contents)``.
159
+
160
+ ``contents`` are ``{"role": "user"|"model", "parts": [{"text": ...}]}`` (Gemini uses
161
+ ``model``, not ``assistant``); system blocks become the separate ``system_instruction``.
162
+ """
163
+ if not self._messages:
164
+ self.assemble()
165
+ system = "\n\n".join(m["content"] for m in self._messages if m["role"] == "system")
166
+ contents = [
167
+ {
168
+ "role": "model" if m["role"] == "assistant" else "user",
169
+ "parts": [{"text": m["content"]}],
170
+ }
171
+ for m in self._messages
172
+ if m["role"] != "system"
173
+ ]
174
+ return system, contents
175
+
176
+ def for_bedrock(self) -> tuple[list[dict], list[dict]]:
177
+ """Bedrock Converse adapter: returns ``(system, messages)``.
178
+
179
+ ``system`` is ``[{"text": ...}]`` (or empty); ``messages`` are
180
+ ``{"role": "user"|"assistant", "content": [{"text": ...}]}`` — Bedrock allows only those
181
+ two roles, so non-user blocks map to ``assistant``.
182
+ """
183
+ if not self._messages:
184
+ self.assemble()
185
+ system_text = "\n\n".join(m["content"] for m in self._messages if m["role"] == "system")
186
+ system = [{"text": system_text}] if system_text else []
187
+ messages = [
188
+ {
189
+ "role": "user" if m["role"] == "user" else "assistant",
190
+ "content": [{"text": m["content"]}],
191
+ }
192
+ for m in self._messages
193
+ if m["role"] != "system"
194
+ ]
195
+ return system, messages
196
+
157
197
  # ------------------------------------------------------------------ internals
158
198
 
159
199
  def _pack(self, budget_tokens: int, *, emit: bool) -> tuple[list[dict], AssemblyReport]:
@@ -153,3 +153,25 @@ def test_for_anthropic_splits_system():
153
153
  system, messages = ctx.for_anthropic()
154
154
  assert system == "you are helpful"
155
155
  assert all(m["role"] != "system" for m in messages)
156
+
157
+
158
+ def test_for_gemini_adapter():
159
+ ctx = Context(budget_tokens=1000, model="gpt-4o")
160
+ ctx.add(Block("be helpful", priority=10, pin=True, role="system"))
161
+ ctx.add(Block("prior reply", priority=5, role="assistant"))
162
+ ctx.add(Block("question", priority=9, pin=True, role="user"))
163
+ system, contents = ctx.for_gemini()
164
+ assert system == "be helpful"
165
+ roles = [c["role"] for c in contents]
166
+ assert "model" in roles and "user" in roles and "system" not in roles # assistant -> model
167
+ assert contents[0]["parts"] == [{"text": "be helpful"}] or contents[0]["parts"][0]["text"]
168
+
169
+
170
+ def test_for_bedrock_adapter():
171
+ ctx = Context(budget_tokens=1000, model="gpt-4o")
172
+ ctx.add(Block("be helpful", priority=10, pin=True, role="system"))
173
+ ctx.add(Block("question", priority=9, pin=True, role="user"))
174
+ system, messages = ctx.for_bedrock()
175
+ assert system == [{"text": "be helpful"}]
176
+ assert messages == [{"role": "user", "content": [{"text": "question"}]}]
177
+ assert all(m["role"] in ("user", "assistant") for m in messages)