orbitals 0.0.2__tar.gz → 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.
Files changed (42) hide show
  1. {orbitals-0.0.2 → orbitals-0.1.0}/Dockerfile +10 -7
  2. {orbitals-0.0.2 → orbitals-0.1.0}/LICENSE +1 -1
  3. {orbitals-0.0.2 → orbitals-0.1.0}/PKG-INFO +4 -25
  4. {orbitals-0.0.2 → orbitals-0.1.0}/README.md +3 -4
  5. {orbitals-0.0.2 → orbitals-0.1.0}/README.scope-guard.md +6 -12
  6. {orbitals-0.0.2 → orbitals-0.1.0}/pyproject.toml +2 -16
  7. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/guards/base.py +4 -4
  8. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/guards/hf.py +1 -1
  9. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/guards/vllm.py +2 -2
  10. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/types.py +2 -14
  11. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/utils.py +3 -5
  12. orbitals-0.1.0/src/scripts/playground.ipynb +196 -0
  13. {orbitals-0.0.2 → orbitals-0.1.0}/uv.lock +5 -25
  14. orbitals-0.0.2/assets/orbitals-banner.png +0 -0
  15. orbitals-0.0.2/src/scripts/playground.ipynb +0 -267
  16. {orbitals-0.0.2 → orbitals-0.1.0}/.dockerignore +0 -0
  17. {orbitals-0.0.2 → orbitals-0.1.0}/.gitignore +0 -0
  18. {orbitals-0.0.2 → orbitals-0.1.0}/AGENTS.md +0 -0
  19. {orbitals-0.0.2 → orbitals-0.1.0}/assets/orbitals.svg +0 -0
  20. {orbitals-0.0.2 → orbitals-0.1.0}/assets/scope-guard.svg +0 -0
  21. {orbitals-0.0.2 → orbitals-0.1.0}/examples/scope-guard/api.py +0 -0
  22. {orbitals-0.0.2 → orbitals-0.1.0}/examples/scope-guard/async_api.py +0 -0
  23. {orbitals-0.0.2 → orbitals-0.1.0}/examples/scope-guard/local.py +0 -0
  24. {orbitals-0.0.2 → orbitals-0.1.0}/examples/scope-guard/vllm_serve.py +0 -0
  25. {orbitals-0.0.2 → orbitals-0.1.0}/src/hf_pipeline/scope_guard.py +0 -0
  26. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/__init__.py +0 -0
  27. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/cli/__init__.py +0 -0
  28. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/cli/main.py +0 -0
  29. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/__init__.py +0 -0
  30. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/cli/__init__.py +0 -0
  31. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/cli/convert_default_model_name.py +0 -0
  32. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/cli/main.py +0 -0
  33. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/cli/serve.py +0 -0
  34. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/guards/__init__.py +0 -0
  35. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/guards/api.py +0 -0
  36. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/modeling.py +0 -0
  37. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/prompting.py +0 -0
  38. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/serving/__init__.py +0 -0
  39. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/serving/main.py +0 -0
  40. {orbitals-0.0.2 → orbitals-0.1.0}/src/orbitals/scope_guard/serving/vllm_logging_config.json +0 -0
  41. {orbitals-0.0.2 → orbitals-0.1.0}/src/scripts/push_hf_pipeline.py +0 -0
  42. {orbitals-0.0.2 → orbitals-0.1.0}/src/scripts/push_model.py +0 -0
@@ -1,4 +1,4 @@
1
- FROM vllm/vllm-openai:v0.14.1 as builder
1
+ FROM vllm/vllm-openai:v0.11.2 as builder
2
2
 
3
3
  ARG DEBIAN_FRONTEND=noninteractive
4
4
  ARG MODEL
@@ -17,20 +17,23 @@ COPY pyproject.toml uv.lock README.md /app/
17
17
 
18
18
  RUN --mount=type=cache,target=/root/.cache/uv \
19
19
  uv venv -p 3.12 && \
20
- uv sync --frozen --extra scope-guard-serve --no-install-project --no-dev
21
-
22
- RUN --mount=type=cache,target=/root/.cache/uv \
23
- hf download ${MODEL}
20
+ uv sync --frozen --extra serve --no-install-project --no-dev
24
21
 
25
22
  COPY src /app/src/
26
23
 
27
24
  RUN --mount=type=cache,target=/root/.cache/uv \
28
25
  uv sync --locked --extra serve --no-editable --no-dev
29
26
 
27
+ RUN --mount=type=cache,target=/root/.cache/uv \
28
+ --mount=type=secret,id=HF_TOKEN \
29
+ hf auth login --token $(cat /run/secrets/HF_TOKEN) && \
30
+ hf download $(scope-classifier convert-default-model-name ${MODEL}) && \
31
+ rm -rf /root/.huggingface
32
+
30
33
  # TODO remove next line
31
34
  ENTRYPOINT ["/bin/bash", "-c"]
32
35
 
33
- FROM vllm/vllm-openai:v0.14.1 as runner
36
+ FROM vllm/vllm-openai:v0.11.2 as runner
34
37
 
35
38
  WORKDIR /app
36
39
  ENV PATH="/app/.venv/bin:$PATH"
@@ -43,4 +46,4 @@ COPY --from=builder /root/.cache/huggingface/hub /root/.cache/huggingface/hub
43
46
  EXPOSE 8000
44
47
 
45
48
  ENTRYPOINT ["/bin/bash", "-c"]
46
- CMD [ "orbitals", "scope-guard", "serve", "${MODEL}", "--port", "8000", "--host", "0.0.0.0" ]
49
+ CMD [ "scope-classifier", "serve", "${MODEL}", "--backend", "hf", "--port", "8000", "--host", "0.0.0.0" ]
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2026 Principled Intelligence s.r.l.
189
+ Copyright [yyyy] [name of copyright owner]
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
@@ -1,35 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orbitals
3
- Version: 0.0.2
3
+ Version: 0.1.0
4
4
  Summary: LLM Guardrails tailored to your Principles
5
5
  Author-email: Luigi Procopio <luigi@principled-intelligence.com>, Edoardo Barba <edoardo@principled-intelligence.com>
6
6
  License: Apache-2.0
7
7
  License-File: LICENSE
8
- Classifier: Programming Language :: Python :: 3 :: Only
9
- Classifier: Programming Language :: Python :: 3.10
10
- Classifier: Programming Language :: Python :: 3.11
11
- Classifier: Programming Language :: Python :: 3.12
12
- Classifier: Programming Language :: Python :: 3.13
13
- Classifier: Programming Language :: Python :: 3.14
14
8
  Requires-Python: >=3.10
15
9
  Requires-Dist: aiohttp
16
10
  Requires-Dist: pydantic>=2.0.0
17
11
  Requires-Dist: requests
18
12
  Requires-Dist: typer>=0.12.3
19
- Provides-Extra: all
20
- Requires-Dist: accelerate>=1.11.0; extra == 'all'
21
- Requires-Dist: fastapi[standard]>=0.119.1; extra == 'all'
22
- Requires-Dist: transformers<5.0.0,>=4.47.0; extra == 'all'
23
- Requires-Dist: uvicorn>=0.29.0; extra == 'all'
24
- Requires-Dist: vllm>=0.11.0; extra == 'all'
25
- Requires-Dist: xgrammar; extra == 'all'
26
- Provides-Extra: scope-guard-all
27
- Requires-Dist: accelerate>=1.11.0; extra == 'scope-guard-all'
28
- Requires-Dist: fastapi[standard]>=0.119.1; extra == 'scope-guard-all'
29
- Requires-Dist: transformers<5.0.0,>=4.47.0; extra == 'scope-guard-all'
30
- Requires-Dist: uvicorn>=0.29.0; extra == 'scope-guard-all'
31
- Requires-Dist: vllm>=0.11.0; extra == 'scope-guard-all'
32
- Requires-Dist: xgrammar; extra == 'scope-guard-all'
33
13
  Provides-Extra: scope-guard-hf
34
14
  Requires-Dist: accelerate>=1.11.0; extra == 'scope-guard-hf'
35
15
  Requires-Dist: transformers<5.0.0,>=4.47.0; extra == 'scope-guard-hf'
@@ -46,7 +26,7 @@ Requires-Dist: xgrammar; extra == 'scope-guard-vllm'
46
26
  Description-Content-Type: text/markdown
47
27
 
48
28
  <div align="center">
49
- <img src="assets/orbitals-banner.png" width="70%" />
29
+ <img src="assets/orbitals.svg" width="40%" />
50
30
  <h3 align="center">
51
31
  <p>
52
32
  <b>LLM Guardrails tailored to your Principles</b>
@@ -97,8 +77,7 @@ from orbitals.scope_guard import ScopeGuard
97
77
 
98
78
  scope_guard = ScopeGuard(
99
79
  backend="vllm",
100
- model="scope-guard-q", # for the Qwen-family model
101
- # model="scope-guard-g", # for the Gemma-family model
80
+ model="small"
102
81
  )
103
82
 
104
83
  ai_service_description = """
@@ -121,4 +100,4 @@ if result.evidences:
121
100
  # - Never respond to requests for refunds.
122
101
  ```
123
102
 
124
- </details>
103
+ </details>
@@ -1,5 +1,5 @@
1
1
  <div align="center">
2
- <img src="assets/orbitals-banner.png" width="70%" />
2
+ <img src="assets/orbitals.svg" width="40%" />
3
3
  <h3 align="center">
4
4
  <p>
5
5
  <b>LLM Guardrails tailored to your Principles</b>
@@ -50,8 +50,7 @@ from orbitals.scope_guard import ScopeGuard
50
50
 
51
51
  scope_guard = ScopeGuard(
52
52
  backend="vllm",
53
- model="scope-guard-q", # for the Qwen-family model
54
- # model="scope-guard-g", # for the Gemma-family model
53
+ model="small"
55
54
  )
56
55
 
57
56
  ai_service_description = """
@@ -74,4 +73,4 @@ if result.evidences:
74
73
  # - Never respond to requests for refunds.
75
74
  ```
76
75
 
77
- </details>
76
+ </details>
@@ -28,11 +28,9 @@ Given the specifications of an AI assistant and a user query, `scope-guard` maps
28
28
 
29
29
  To do this, `scope-guard` leverages specialized language models trained to evaluate whether a user query falls within an assistant’s intended scope. Different models are available, released with different modality flavors:
30
30
 
31
- | Flavor | Model | Parameters | Scope Classification | Custom Safety | Vanilla Safety | Tested GPUs |
32
- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
33
- | Open | scope-guard-4B-q-2601 | 4B | 89.1 | 79.1 | 90,3 | T4, L4, L40S, 4090, 5090 |
34
- | Open | scope-guard-4B-g-2601 | 4B | 90.1 | 78.0 | 88.0 | T4, L4, L40S, 4090, 5090 |
35
- | Closed | scope-guard-pro | ~ | 91.9 | 81.8 | 92.0 | ~ |
31
+ | Flavor | Model | Parameters | Description | Accuracy | Required VRAM |
32
+ | :--- | :--- | :--- | :--- | :--- | :--- |
33
+ | Open | `small` | 1.7B | A compact and fast model for general use. | 85.3 | 8GB |
36
34
 
37
35
  ## Quickstart
38
36
 
@@ -55,8 +53,7 @@ from orbitals.scope_guard import ScopeGuard
55
53
 
56
54
  scope_guard = ScopeGuard(
57
55
  backend="vllm",
58
- model="scope-guard-q", # for the Qwen-family model
59
- # model="scope-guard-g", # for the Gemma-family model
56
+ model="small"
60
57
  )
61
58
 
62
59
  ai_service_description = """
@@ -85,9 +82,6 @@ if result.evidences:
85
82
  <summary>Hosted Flavor</summary>
86
83
  <br>
87
84
 
88
- > Open access to the hosted models is coming soon.
89
- > Need access earlier? Contact us at [orbitals@principled-intelligence.com](mailto:orbitals@principled-intelligence.com).
90
-
91
85
  First, we need to install `orbitals` and `scope-guard`. In this case, plain `orbitals` is all we need:
92
86
 
93
87
  ```bash
@@ -229,7 +223,7 @@ All of this is configured via the `orbitals scope-guard serve` command:
229
223
  pip install orbitals[scope-guard-serve]
230
224
 
231
225
  # start everything
232
- orbitals scope-guard serve scope-guard --port 8000
226
+ orbitals scope-guard serve serve small --port 8000
233
227
  ```
234
228
 
235
229
  Alternatively, we also release a pre-built Docker image:
@@ -266,7 +260,7 @@ Response:
266
260
  ],
267
261
  "scope_class": "Restricted",
268
262
  "time_taken": 0.23,
269
- "model": "<model>"
263
+ "model": "small"
270
264
  }
271
265
  ```
272
266
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "orbitals"
7
- version = "0.0.2"
7
+ version = "0.1.0"
8
8
  description = "LLM Guardrails tailored to your Principles"
9
9
  readme = "README.md"
10
10
 
@@ -17,14 +17,7 @@ authors = [
17
17
  ]
18
18
 
19
19
  keywords = []
20
- classifiers = [
21
- "Programming Language :: Python :: 3 :: Only",
22
- "Programming Language :: Python :: 3.10",
23
- "Programming Language :: Python :: 3.11",
24
- "Programming Language :: Python :: 3.12",
25
- "Programming Language :: Python :: 3.13",
26
- "Programming Language :: Python :: 3.14",
27
- ]
20
+ classifiers = []
28
21
 
29
22
  dependencies = ["pydantic>=2.0.0", "typer>=0.12.3", "requests", "aiohttp"]
30
23
 
@@ -37,13 +30,6 @@ scope-guard-serve = [
37
30
  "uvicorn>=0.29.0",
38
31
  "vllm>=0.11.0",
39
32
  ]
40
- scope-guard-all = [
41
- "orbitals[scope-guard-vllm]",
42
- "orbitals[scope-guard-hf]",
43
- "orbitals[scope-guard-serve]",
44
- ]
45
-
46
- all = ["orbitals[scope-guard-all]"]
47
33
 
48
34
  [project.scripts]
49
35
  orbitals = "orbitals.cli.main:app"
@@ -17,7 +17,7 @@ from ..modeling import (
17
17
  ScopeGuardOutput,
18
18
  )
19
19
 
20
- DefaultModel = Literal["scope-guard"]
20
+ DefaultModel = Literal["small"]
21
21
 
22
22
  MODEL_MAPPING = {
23
23
  "scope-guard": "principled-intelligence/scope-guard-4B-q-2601",
@@ -137,7 +137,7 @@ class ScopeGuard(BaseScopeGuard):
137
137
  def __new__(
138
138
  cls,
139
139
  backend: Literal["hf"] = "hf",
140
- model: DefaultModel | str = "scope-guard",
140
+ model: DefaultModel | str = "small",
141
141
  skip_evidences: bool = False,
142
142
  max_new_tokens: int = 10_000,
143
143
  do_sample: bool = False,
@@ -148,7 +148,7 @@ class ScopeGuard(BaseScopeGuard):
148
148
  def __new__(
149
149
  cls,
150
150
  backend: Literal["vllm"],
151
- model: DefaultModel | str = "scope-guard",
151
+ model: DefaultModel | str = "small",
152
152
  skip_evidences: bool = False,
153
153
  temperature: float = 0.0,
154
154
  max_tokens: int = 10_000,
@@ -223,7 +223,7 @@ class AsyncScopeGuard(BaseScopeGuard):
223
223
  def __new__(
224
224
  cls,
225
225
  backend: Literal["vllm-api"],
226
- model: DefaultModel | str = "scope-guard",
226
+ model: DefaultModel | str = "small",
227
227
  skip_evidences: bool = False,
228
228
  vllm_serving_url: str = "http://localhost:8000",
229
229
  temperature: float = 0.0,
@@ -21,7 +21,7 @@ class HuggingFaceScopeGuard(ScopeGuard):
21
21
  def __init__(
22
22
  self,
23
23
  backend: Literal["hf"] = "hf",
24
- model: DefaultModel | str = "scope-guard",
24
+ model: DefaultModel | str = "small",
25
25
  skip_evidences: bool = False,
26
26
  max_new_tokens: int = 10_000,
27
27
  do_sample: bool = False,
@@ -23,7 +23,7 @@ class VLLMScopeGuard(ScopeGuard):
23
23
  def __init__(
24
24
  self,
25
25
  backend: Literal["vllm"] = "vllm",
26
- model: DefaultModel | str = "scope-guard",
26
+ model: DefaultModel | str = "small",
27
27
  skip_evidences: bool = False,
28
28
  temperature: float = 0.0,
29
29
  max_tokens: int = 10_000,
@@ -127,7 +127,7 @@ class AsyncVLLMApiScopeGuard(AsyncScopeGuard):
127
127
  def __init__(
128
128
  self,
129
129
  backend: Literal["vllm-api", "vllm-async-api"] = "vllm-api",
130
- model: DefaultModel | str = "scope-guard",
130
+ model: DefaultModel | str = "small",
131
131
  skip_evidences: bool = False,
132
132
  vllm_serving_url: str = "http://localhost:8000",
133
133
  temperature: float = 0.0,
@@ -1,46 +1,34 @@
1
- from typing import ClassVar, Literal
1
+ from typing import Literal
2
2
 
3
- from pydantic import BaseModel, ConfigDict, Field
3
+ from pydantic import BaseModel, Field
4
4
 
5
5
 
6
6
  class LLMUsage(BaseModel):
7
- model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
8
-
9
7
  prompt_tokens: int
10
8
  completion_tokens: int
11
9
  total_tokens: int
12
10
 
13
11
 
14
12
  class ConversationMessage(BaseModel):
15
- model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
16
-
17
13
  role: Literal["user", "assistant"]
18
14
  content: str
19
15
 
20
16
 
21
17
  class Conversation(BaseModel):
22
- model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
23
-
24
18
  messages: list[ConversationMessage]
25
19
 
26
20
 
27
21
  class SupportingMaterial(BaseModel):
28
- model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
29
-
30
22
  pass
31
23
 
32
24
 
33
25
  class Principle(BaseModel):
34
- model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
35
-
36
26
  title: str = Field(description="Title of the principle")
37
27
  description: str = Field(description="Description of the principle")
38
28
  supporting_materials: list[SupportingMaterial] | None
39
29
 
40
30
 
41
31
  class AIServiceDescription(BaseModel):
42
- model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
43
-
44
32
  identity_role: str = Field(
45
33
  description="Identity, role and objectives of the AI Service. Gives a general idea of what the service is about."
46
34
  )
@@ -31,7 +31,6 @@ def maybe_configure_gpu_usage():
31
31
 
32
32
  best_idx = None
33
33
  best_free = -1
34
- is_multi_gpu = torch.cuda.device_count() > 1
35
34
 
36
35
  for i in range(torch.cuda.device_count()):
37
36
  free_bytes, _ = torch.cuda.mem_get_info(i) # (free, total)
@@ -40,8 +39,7 @@ def maybe_configure_gpu_usage():
40
39
  best_free = free_bytes
41
40
 
42
41
  if best_idx is not None:
43
- if is_multi_gpu:
44
- logging.warning(
45
- f"Auto-configuring to use GPU {best_idx} with {best_free / 1024**3:.2f} GB free"
46
- )
42
+ logging.warning(
43
+ f"Auto-configuring VLLM to use GPU {best_idx} with {best_free / 1024**3:.2f} GB free"
44
+ )
47
45
  os.environ["CUDA_VISIBLE_DEVICES"] = str(best_idx)
@@ -0,0 +1,196 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "f616f063",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "from orbitals.scope_guard.prompting import ScopeClass"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": 2,
16
+ "id": "1ff6a768",
17
+ "metadata": {},
18
+ "outputs": [
19
+ {
20
+ "name": "stdout",
21
+ "output_type": "stream",
22
+ "text": [
23
+ "**Name**: Directly Supported\n",
24
+ "**Description**: The user's query can be definitively handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description.\n",
25
+ "\n",
26
+ "**Name**: Potentially Supported\n",
27
+ "**Description**: The user's query can be plausibly handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description. The request is a reasonable extension or interpretation of the service's capabilities that might be within scope.\n",
28
+ "\n",
29
+ "**Name**: Out of Scope\n",
30
+ "**Description**: The user's query is outside the AI Service's role and functionalities. It's incompatible with the service's documented purpose.\n",
31
+ "\n",
32
+ "**Name**: Restricted\n",
33
+ "**Description**: The user's query cannot be handled by the AI Service due to either behavioral restrictions (content/advice the service must refuse to provide) or service limitations (technical constraints, access restrictions, or knowledge scope limitations).\n",
34
+ "**Examples**:\n",
35
+ "* Do not provide personalized financial advice. → User: Should I invest my savings in Bitcoin?\n",
36
+ "* The AI service does not have access to real-time data. → User: What's the current stock price of Apple?\n",
37
+ "* AI service cannot access external databases. → User: Look up my account balance in the system.\n",
38
+ "\n",
39
+ "**Name**: Chit Chat\n",
40
+ "**Description**: The user's query is a casual or social interaction that does not pertain to the AI Service's functionalities, knowledge scope, or operational capabilities.\n"
41
+ ]
42
+ }
43
+ ],
44
+ "source": [
45
+ "print(ScopeClass.get_classes_manifest())"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": 1,
51
+ "id": "ec2d936b",
52
+ "metadata": {},
53
+ "outputs": [],
54
+ "source": [
55
+ "from orbitals.scope_guard.prompting import SYSTEM_PROMPT"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": 2,
61
+ "id": "991a9bf0",
62
+ "metadata": {},
63
+ "outputs": [
64
+ {
65
+ "name": "stdout",
66
+ "output_type": "stream",
67
+ "text": [
68
+ "You are an expert AI classifier specialized in classifying user queries given the description of an AI service.\n",
69
+ "\n",
70
+ "Your task is to classify the LAST USER MESSAGE in a conversation between a user and an AI Service. Follow these steps:\n",
71
+ "\n",
72
+ "1. **Extract Evidence**: Identify and quote specific excerpts from the AI Service Description that are relevant to understanding whether and how the AI Service can handle the LAST USER MESSAGE. Look for:\n",
73
+ " - Functionalities that might address the user's query\n",
74
+ " - Explicit restrictions or limitations mentioned\n",
75
+ " - Knowledge scope boundaries\n",
76
+ " - Any relevant service capabilities or constraints\n",
77
+ "\n",
78
+ "2. **Classify**: Based on the evidence extracted, assign one of the classification classes below to the LAST USER MESSAGE.\n",
79
+ "\n",
80
+ "## Classification Classes\n",
81
+ "\n",
82
+ "**Name**: Directly Supported\n",
83
+ "**Description**: The user's query can be definitively handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description.\n",
84
+ "\n",
85
+ "**Name**: Potentially Supported\n",
86
+ "**Description**: The user's query can be plausibly handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description. The request is a reasonable extension or interpretation of the service's capabilities that might be within scope.\n",
87
+ "\n",
88
+ "**Name**: Out of Scope\n",
89
+ "**Description**: The user's query is outside the AI Service's role and functionalities. It's incompatible with the service's documented purpose.\n",
90
+ "\n",
91
+ "**Name**: Restricted\n",
92
+ "**Description**: The user's query cannot be handled by the AI Service due to either behavioral restrictions (content/advice the service must refuse to provide) or service limitations (technical constraints, access restrictions, or knowledge scope limitations).\n",
93
+ "**Examples**:\n",
94
+ "* Do not provide personalized financial advice. → User: Should I invest my savings in Bitcoin?\n",
95
+ "* The AI service does not have access to real-time data. → User: What's the current stock price of Apple?\n",
96
+ "* AI service cannot access external databases. → User: Look up my account balance in the system.\n",
97
+ "\n",
98
+ "**Name**: Chit Chat\n",
99
+ "**Description**: The user's query is a casual or social interaction that does not pertain to the AI Service's functionalities, knowledge scope, or operational capabilities.\n",
100
+ "\n",
101
+ "## Important Guidelines\n",
102
+ "* Base your classification EXCLUSIVELY on the AI Service Description provided.\n",
103
+ "* Pay special attention to RESTRICTIONS, CONSTRAINTS, and LIMITATIONS sections in the AI Service Description.\n",
104
+ "* Extract evidence first, then use it to inform your classification decision.\n",
105
+ "* Quote excerpts verbatim from the AI Service Description as evidence.\n",
106
+ "\n",
107
+ "Output the classification in the following JSON schema:\n",
108
+ "{\"$defs\": {\"ScopeClass\": {\"enum\": [\"Directly Supported\", \"Potentially Supported\", \"Out of Scope\", \"Restricted\", \"Chit Chat\"], \"title\": \"ScopeClass\", \"type\": \"string\"}}, \"properties\": {\"evidences\": {\"anyOf\": [{\"items\": {\"type\": \"string\"}, \"type\": \"array\"}, {\"type\": \"null\"}], \"default\": null, \"description\": \"Excerpts quoted directly from the AI Service Description that are relevant to understanding whether and how the AI Service can handle the LAST USER MESSAGE.\", \"title\": \"Evidences\"}, \"scope_class\": {\"$ref\": \"#/$defs/ScopeClass\", \"description\": \"The classification assigned to the LAST USER MESSAGE based on the evidence extracted from the AI Service Description.\"}}, \"required\": [\"scope_class\"], \"title\": \"ScopeGuardResponseModel\", \"type\": \"object\"}\n"
109
+ ]
110
+ }
111
+ ],
112
+ "source": [
113
+ "print(SYSTEM_PROMPT)"
114
+ ]
115
+ },
116
+ {
117
+ "cell_type": "code",
118
+ "execution_count": 1,
119
+ "id": "7f850a8f",
120
+ "metadata": {},
121
+ "outputs": [
122
+ {
123
+ "name": "stderr",
124
+ "output_type": "stream",
125
+ "text": [
126
+ "/home/poccio/principled-intelligence/projects/orbitals/.venv/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
127
+ " from .autonotebook import tqdm as notebook_tqdm\n"
128
+ ]
129
+ },
130
+ {
131
+ "name": "stdout",
132
+ "output_type": "stream",
133
+ "text": [
134
+ "<|im_start|>system\n",
135
+ "You are a friendly chatbot who always responds in the style of a pirate<|im_end|>\n",
136
+ "<|im_start|>user\n",
137
+ "How many helicopters can a human eat in one sitting?<|im_end|>\n",
138
+ "<|im_start|>assistant\n",
139
+ "<think>\n",
140
+ "\n",
141
+ "</think>\n",
142
+ "\n",
143
+ "\n"
144
+ ]
145
+ }
146
+ ],
147
+ "source": [
148
+ "from transformers import AutoTokenizer\n",
149
+ "\n",
150
+ "tokenizer = AutoTokenizer.from_pretrained(\"Qwen/Qwen3-4B\")\n",
151
+ "messages = [\n",
152
+ " {\"role\": \"system\", \"content\": \"You are a friendly chatbot who always responds in the style of a pirate\",},\n",
153
+ " {\"role\": \"user\", \"content\": \"How many helicopters can a human eat in one sitting?\"},\n",
154
+ "]\n",
155
+ "\n",
156
+ "prompt = tokenizer.apply_chat_template(\n",
157
+ " messages, \n",
158
+ " tokenize=False,\n",
159
+ " add_generation_prompt=True,\n",
160
+ " enable_thinking=False,)\n",
161
+ "\n",
162
+ " \n",
163
+ "print(prompt)"
164
+ ]
165
+ },
166
+ {
167
+ "cell_type": "code",
168
+ "execution_count": null,
169
+ "id": "475af9cc",
170
+ "metadata": {},
171
+ "outputs": [],
172
+ "source": []
173
+ }
174
+ ],
175
+ "metadata": {
176
+ "kernelspec": {
177
+ "display_name": "orbitals",
178
+ "language": "python",
179
+ "name": "python3"
180
+ },
181
+ "language_info": {
182
+ "codemirror_mode": {
183
+ "name": "ipython",
184
+ "version": 3
185
+ },
186
+ "file_extension": ".py",
187
+ "mimetype": "text/x-python",
188
+ "name": "python",
189
+ "nbconvert_exporter": "python",
190
+ "pygments_lexer": "ipython3",
191
+ "version": "3.10.13"
192
+ }
193
+ },
194
+ "nbformat": 4,
195
+ "nbformat_minor": 5
196
+ }
@@ -2924,7 +2924,7 @@ wheels = [
2924
2924
 
2925
2925
  [[package]]
2926
2926
  name = "orbitals"
2927
- version = "0.0.2"
2927
+ version = "0.1.0"
2928
2928
  source = { editable = "." }
2929
2929
  dependencies = [
2930
2930
  { name = "aiohttp" },
@@ -2934,22 +2934,6 @@ dependencies = [
2934
2934
  ]
2935
2935
 
2936
2936
  [package.optional-dependencies]
2937
- all = [
2938
- { name = "accelerate" },
2939
- { name = "fastapi", extra = ["standard"] },
2940
- { name = "transformers" },
2941
- { name = "uvicorn" },
2942
- { name = "vllm" },
2943
- { name = "xgrammar" },
2944
- ]
2945
- scope-guard-all = [
2946
- { name = "accelerate" },
2947
- { name = "fastapi", extra = ["standard"] },
2948
- { name = "transformers" },
2949
- { name = "uvicorn" },
2950
- { name = "vllm" },
2951
- { name = "xgrammar" },
2952
- ]
2953
2937
  scope-guard-hf = [
2954
2938
  { name = "accelerate" },
2955
2939
  { name = "transformers" },
@@ -2978,10 +2962,6 @@ requires-dist = [
2978
2962
  { name = "accelerate", marker = "extra == 'scope-guard-hf'", specifier = ">=1.11.0" },
2979
2963
  { name = "aiohttp" },
2980
2964
  { name = "fastapi", extras = ["standard"], marker = "extra == 'scope-guard-serve'", specifier = ">=0.119.1" },
2981
- { name = "orbitals", extras = ["scope-guard-all"], marker = "extra == 'all'" },
2982
- { name = "orbitals", extras = ["scope-guard-hf"], marker = "extra == 'scope-guard-all'" },
2983
- { name = "orbitals", extras = ["scope-guard-serve"], marker = "extra == 'scope-guard-all'" },
2984
- { name = "orbitals", extras = ["scope-guard-vllm"], marker = "extra == 'scope-guard-all'" },
2985
2965
  { name = "orbitals", extras = ["scope-guard-vllm"], marker = "extra == 'scope-guard-serve'" },
2986
2966
  { name = "pydantic", specifier = ">=2.0.0" },
2987
2967
  { name = "requests" },
@@ -2993,7 +2973,7 @@ requires-dist = [
2993
2973
  { name = "vllm", marker = "extra == 'scope-guard-vllm'", specifier = ">=0.11.0" },
2994
2974
  { name = "xgrammar", marker = "extra == 'scope-guard-vllm'" },
2995
2975
  ]
2996
- provides-extras = ["scope-guard-hf", "scope-guard-vllm", "scope-guard-serve", "scope-guard-all", "all"]
2976
+ provides-extras = ["scope-guard-hf", "scope-guard-vllm", "scope-guard-serve"]
2997
2977
 
2998
2978
  [package.metadata.requires-dev]
2999
2979
  dev = [
@@ -5412,11 +5392,11 @@ wheels = [
5412
5392
 
5413
5393
  [[package]]
5414
5394
  name = "wcwidth"
5415
- version = "0.5.0"
5395
+ version = "0.4.0"
5416
5396
  source = { registry = "https://pypi.org/simple" }
5417
- sdist = { url = "https://files.pythonhosted.org/packages/64/6e/62daec357285b927e82263a81f3b4c1790215bc77c42530ce4a69d501a43/wcwidth-0.5.0.tar.gz", hash = "sha256:f89c103c949a693bf563377b2153082bf58e309919dfb7f27b04d862a0089333", size = 246585, upload-time = "2026-01-27T01:31:44.942Z" }
5397
+ sdist = { url = "https://files.pythonhosted.org/packages/98/0a/dc5110cc99c39df65bac29229c4b637a8304e0914850348d98974c8ecfff/wcwidth-0.4.0.tar.gz", hash = "sha256:46478e02cf7149ba150fb93c39880623ee7e5181c64eda167b6a1de51b7a7ba1", size = 237625, upload-time = "2026-01-26T02:35:58.844Z" }
5418
5398
  wheels = [
5419
- { url = "https://files.pythonhosted.org/packages/f2/3e/45583b67c2ff08ad5a582d316fcb2f11d6cf0a50c7707ac09d212d25bc98/wcwidth-0.5.0-py3-none-any.whl", hash = "sha256:1efe1361b83b0ff7877b81ba57c8562c99cf812158b778988ce17ec061095695", size = 93772, upload-time = "2026-01-27T01:31:43.432Z" },
5399
+ { url = "https://files.pythonhosted.org/packages/b7/f6/da704c5e77281d71723bffbd926b754c0efd57cbcd02e74c2ca374c14cef/wcwidth-0.4.0-py3-none-any.whl", hash = "sha256:8af2c81174b3aa17adf05058c543c267e4e5b6767a28e31a673a658c1d766783", size = 88216, upload-time = "2026-01-26T02:35:57.461Z" },
5420
5400
  ]
5421
5401
 
5422
5402
  [[package]]
Binary file
@@ -1,267 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": 1,
6
- "id": "f616f063",
7
- "metadata": {},
8
- "outputs": [],
9
- "source": [
10
- "from orbitals.scope_guard.prompting import ScopeClass"
11
- ]
12
- },
13
- {
14
- "cell_type": "code",
15
- "execution_count": 2,
16
- "id": "1ff6a768",
17
- "metadata": {},
18
- "outputs": [
19
- {
20
- "name": "stdout",
21
- "output_type": "stream",
22
- "text": [
23
- "**Name**: Directly Supported\n",
24
- "**Description**: The user's query can be definitively handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description.\n",
25
- "\n",
26
- "**Name**: Potentially Supported\n",
27
- "**Description**: The user's query can be plausibly handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description. The request is a reasonable extension or interpretation of the service's capabilities that might be within scope.\n",
28
- "\n",
29
- "**Name**: Out of Scope\n",
30
- "**Description**: The user's query is outside the AI Service's role and functionalities. It's incompatible with the service's documented purpose.\n",
31
- "\n",
32
- "**Name**: Restricted\n",
33
- "**Description**: The user's query cannot be handled by the AI Service due to either behavioral restrictions (content/advice the service must refuse to provide) or service limitations (technical constraints, access restrictions, or knowledge scope limitations).\n",
34
- "**Examples**:\n",
35
- "* Do not provide personalized financial advice. → User: Should I invest my savings in Bitcoin?\n",
36
- "* The AI service does not have access to real-time data. → User: What's the current stock price of Apple?\n",
37
- "* AI service cannot access external databases. → User: Look up my account balance in the system.\n",
38
- "\n",
39
- "**Name**: Chit Chat\n",
40
- "**Description**: The user's query is a casual or social interaction that does not pertain to the AI Service's functionalities, knowledge scope, or operational capabilities.\n"
41
- ]
42
- }
43
- ],
44
- "source": [
45
- "print(ScopeClass.get_classes_manifest())"
46
- ]
47
- },
48
- {
49
- "cell_type": "code",
50
- "execution_count": 1,
51
- "id": "ec2d936b",
52
- "metadata": {},
53
- "outputs": [],
54
- "source": [
55
- "from orbitals.scope_guard.prompting import SYSTEM_PROMPT"
56
- ]
57
- },
58
- {
59
- "cell_type": "code",
60
- "execution_count": 2,
61
- "id": "991a9bf0",
62
- "metadata": {},
63
- "outputs": [
64
- {
65
- "name": "stdout",
66
- "output_type": "stream",
67
- "text": [
68
- "You are an expert AI classifier specialized in classifying user queries given the description of an AI service.\n",
69
- "\n",
70
- "Your task is to classify the LAST USER MESSAGE in a conversation between a user and an AI Service. Follow these steps:\n",
71
- "\n",
72
- "1. **Extract Evidence**: Identify and quote specific excerpts from the AI Service Description that are relevant to understanding whether and how the AI Service can handle the LAST USER MESSAGE. Look for:\n",
73
- " - Functionalities that might address the user's query\n",
74
- " - Explicit restrictions or limitations mentioned\n",
75
- " - Knowledge scope boundaries\n",
76
- " - Any relevant service capabilities or constraints\n",
77
- "\n",
78
- "2. **Classify**: Based on the evidence extracted, assign one of the classification classes below to the LAST USER MESSAGE.\n",
79
- "\n",
80
- "## Classification Classes\n",
81
- "\n",
82
- "**Name**: Directly Supported\n",
83
- "**Description**: The user's query can be definitively handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description.\n",
84
- "\n",
85
- "**Name**: Potentially Supported\n",
86
- "**Description**: The user's query can be plausibly handled by the AI Service given the functionalities, knowledge scope, and capabilities described in the AI Service Description. The request is a reasonable extension or interpretation of the service's capabilities that might be within scope.\n",
87
- "\n",
88
- "**Name**: Out of Scope\n",
89
- "**Description**: The user's query is outside the AI Service's role and functionalities. It's incompatible with the service's documented purpose.\n",
90
- "\n",
91
- "**Name**: Restricted\n",
92
- "**Description**: The user's query cannot be handled by the AI Service due to either behavioral restrictions (content/advice the service must refuse to provide) or service limitations (technical constraints, access restrictions, or knowledge scope limitations).\n",
93
- "**Examples**:\n",
94
- "* Do not provide personalized financial advice. → User: Should I invest my savings in Bitcoin?\n",
95
- "* The AI service does not have access to real-time data. → User: What's the current stock price of Apple?\n",
96
- "* AI service cannot access external databases. → User: Look up my account balance in the system.\n",
97
- "\n",
98
- "**Name**: Chit Chat\n",
99
- "**Description**: The user's query is a casual or social interaction that does not pertain to the AI Service's functionalities, knowledge scope, or operational capabilities.\n",
100
- "\n",
101
- "## Important Guidelines\n",
102
- "* Base your classification EXCLUSIVELY on the AI Service Description provided.\n",
103
- "* Pay special attention to RESTRICTIONS, CONSTRAINTS, and LIMITATIONS sections in the AI Service Description.\n",
104
- "* Extract evidence first, then use it to inform your classification decision.\n",
105
- "* Quote excerpts verbatim from the AI Service Description as evidence.\n",
106
- "\n",
107
- "Output the classification in the following JSON schema:\n",
108
- "{\"$defs\": {\"ScopeClass\": {\"enum\": [\"Directly Supported\", \"Potentially Supported\", \"Out of Scope\", \"Restricted\", \"Chit Chat\"], \"title\": \"ScopeClass\", \"type\": \"string\"}}, \"properties\": {\"evidences\": {\"anyOf\": [{\"items\": {\"type\": \"string\"}, \"type\": \"array\"}, {\"type\": \"null\"}], \"default\": null, \"description\": \"Excerpts quoted directly from the AI Service Description that are relevant to understanding whether and how the AI Service can handle the LAST USER MESSAGE.\", \"title\": \"Evidences\"}, \"scope_class\": {\"$ref\": \"#/$defs/ScopeClass\", \"description\": \"The classification assigned to the LAST USER MESSAGE based on the evidence extracted from the AI Service Description.\"}}, \"required\": [\"scope_class\"], \"title\": \"ScopeGuardResponseModel\", \"type\": \"object\"}\n"
109
- ]
110
- }
111
- ],
112
- "source": [
113
- "print(SYSTEM_PROMPT)"
114
- ]
115
- },
116
- {
117
- "cell_type": "code",
118
- "execution_count": 1,
119
- "id": "7f850a8f",
120
- "metadata": {},
121
- "outputs": [
122
- {
123
- "name": "stderr",
124
- "output_type": "stream",
125
- "text": [
126
- "/home/poccio/principled-intelligence/projects/orbitals/.venv/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
127
- " from .autonotebook import tqdm as notebook_tqdm\n"
128
- ]
129
- },
130
- {
131
- "name": "stdout",
132
- "output_type": "stream",
133
- "text": [
134
- "<|im_start|>system\n",
135
- "You are a friendly chatbot who always responds in the style of a pirate<|im_end|>\n",
136
- "<|im_start|>user\n",
137
- "How many helicopters can a human eat in one sitting?<|im_end|>\n",
138
- "<|im_start|>assistant\n",
139
- "<think>\n",
140
- "\n",
141
- "</think>\n",
142
- "\n",
143
- "\n"
144
- ]
145
- }
146
- ],
147
- "source": [
148
- "from transformers import AutoTokenizer\n",
149
- "\n",
150
- "tokenizer = AutoTokenizer.from_pretrained(\"Qwen/Qwen3-4B\")\n",
151
- "messages = [\n",
152
- " {\"role\": \"system\", \"content\": \"You are a friendly chatbot who always responds in the style of a pirate\",},\n",
153
- " {\"role\": \"user\", \"content\": \"How many helicopters can a human eat in one sitting?\"},\n",
154
- "]\n",
155
- "\n",
156
- "prompt = tokenizer.apply_chat_template(\n",
157
- " messages, \n",
158
- " tokenize=False,\n",
159
- " add_generation_prompt=True,\n",
160
- " enable_thinking=False,)\n",
161
- "\n",
162
- " \n",
163
- "print(prompt)"
164
- ]
165
- },
166
- {
167
- "cell_type": "code",
168
- "execution_count": null,
169
- "id": "475af9cc",
170
- "metadata": {},
171
- "outputs": [],
172
- "source": []
173
- },
174
- {
175
- "cell_type": "code",
176
- "execution_count": 1,
177
- "id": "e803ba74",
178
- "metadata": {},
179
- "outputs": [
180
- {
181
- "ename": "ValidationError",
182
- "evalue": "3 validation errors for AIServiceDescription\nconduct_guidelines\n Extra inputs are not permitted [type=extra_forbidden, input_value='Respond clearly and fact...ser clarity and safety.', input_type=str]\n For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden\nconstraints\n Extra inputs are not permitted [type=extra_forbidden, input_value='Cannot modify shipments,...vailable tracking data.', input_type=str]\n For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden\nfallback\n Extra inputs are not permitted [type=extra_forbidden, input_value='If tracking data is miss... inventing information.', input_type=str]\n For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden",
183
- "output_type": "error",
184
- "traceback": [
185
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
186
- "\u001b[0;31mValidationError\u001b[0m Traceback (most recent call last)",
187
- "Cell \u001b[0;32mIn[1], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01morbitals\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mtypes\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m AIServiceDescription\n\u001b[0;32m----> 3\u001b[0m ai_service_description_complete \u001b[38;5;241m=\u001b[39m \u001b[43mAIServiceDescription\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[43midentity_role\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 5\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mYou are PackAssist, a virtual assistant designed to help users understand and \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 6\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtrack their parcel shipments. Your objective is to interpret tracking data and \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 7\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mguide users through delivery-related questions.\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 8\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 9\u001b[0m \u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 10\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mThe service operates within a parcel-delivery environment where users interact \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 11\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mto check the status of shipments sent domestically or internationally. Typical \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 12\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43musers are customers awaiting deliveries or sending parcels.\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 13\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[43m \u001b[49m\u001b[43mfunctionalities\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 15\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mRetrieve tracking updates; explain the meaning of tracking events; provide \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 16\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mestimated delivery windows; assist users in understanding delays or routing steps.\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 17\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 18\u001b[0m \u001b[43m \u001b[49m\u001b[43mknowledge_scope\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 19\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mPublic tracking information, standard logistics workflows, typical transit times, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 20\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mand general procedures for parcel movement. No access to payment, refund, or claim \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 21\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mprocessing systems.\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 22\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 23\u001b[0m \u001b[43m \u001b[49m\u001b[43mconduct_guidelines\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 24\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mRespond clearly and factually; do not speculate on unavailable data; avoid any \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 25\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrefund-related discussion; do not provide financial, legal, or compensation advice; \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 26\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mprioritize user clarity and safety.\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 27\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 28\u001b[0m \u001b[43m \u001b[49m\u001b[43mconstraints\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 29\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mCannot modify shipments, initiate refunds, open claims, contact drivers, or view \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 30\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minternal logistics notes. Limited strictly to interpreting publicly available \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 31\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtracking data.\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 32\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 33\u001b[0m \u001b[43m \u001b[49m\u001b[43mfallback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 34\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mIf tracking data is missing or the request is outside the allowed scope, inform \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 35\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mthe user clearly and redirect them to alternative support channels without \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 36\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minventing information.\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 37\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 38\u001b[0m \u001b[43m \u001b[49m\u001b[43mwebsite_url\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mhttps://www.trackmate-delivery.com\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 39\u001b[0m \u001b[43m)\u001b[49m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28mprint\u001b[39m(ai_service_description_complete\u001b[38;5;241m.\u001b[39mmodel_dump_json(indent\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m4\u001b[39m))\n",
188
- "File \u001b[0;32m~/principled-intelligence/projects/orbitals/.venv/lib/python3.10/site-packages/pydantic/main.py:250\u001b[0m, in \u001b[0;36mBaseModel.__init__\u001b[0;34m(self, **data)\u001b[0m\n\u001b[1;32m 248\u001b[0m \u001b[38;5;66;03m# `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks\u001b[39;00m\n\u001b[1;32m 249\u001b[0m __tracebackhide__ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m--> 250\u001b[0m validated_self \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__pydantic_validator__\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalidate_python\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mself_instance\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m validated_self:\n\u001b[1;32m 252\u001b[0m warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[1;32m 253\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mA custom validator is returning a value other than `self`.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 254\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mReturning anything other than `self` from a top level model validator isn\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt supported when validating via `__init__`.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 255\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mSee the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 256\u001b[0m stacklevel\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2\u001b[39m,\n\u001b[1;32m 257\u001b[0m )\n",
189
- "\u001b[0;31mValidationError\u001b[0m: 3 validation errors for AIServiceDescription\nconduct_guidelines\n Extra inputs are not permitted [type=extra_forbidden, input_value='Respond clearly and fact...ser clarity and safety.', input_type=str]\n For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden\nconstraints\n Extra inputs are not permitted [type=extra_forbidden, input_value='Cannot modify shipments,...vailable tracking data.', input_type=str]\n For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden\nfallback\n Extra inputs are not permitted [type=extra_forbidden, input_value='If tracking data is miss... inventing information.', input_type=str]\n For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden"
190
- ]
191
- }
192
- ],
193
- "source": [
194
- "from orbitals.types import AIServiceDescription\n",
195
- "\n",
196
- "ai_service_description_complete = AIServiceDescription(\n",
197
- " identity_role=(\n",
198
- " \"You are PackAssist, a virtual assistant designed to help users understand and \"\n",
199
- " \"track their parcel shipments. Your objective is to interpret tracking data and \"\n",
200
- " \"guide users through delivery-related questions.\"\n",
201
- " ),\n",
202
- " context=(\n",
203
- " \"The service operates within a parcel-delivery environment where users interact \"\n",
204
- " \"to check the status of shipments sent domestically or internationally. Typical \"\n",
205
- " \"users are customers awaiting deliveries or sending parcels.\"\n",
206
- " ),\n",
207
- " functionalities=(\n",
208
- " \"Retrieve tracking updates; explain the meaning of tracking events; provide \"\n",
209
- " \"estimated delivery windows; assist users in understanding delays or routing steps.\"\n",
210
- " ),\n",
211
- " knowledge_scope=(\n",
212
- " \"Public tracking information, standard logistics workflows, typical transit times, \"\n",
213
- " \"and general procedures for parcel movement. No access to payment, refund, or claim \"\n",
214
- " \"processing systems.\"\n",
215
- " ),\n",
216
- " conduct_guidelines=(\n",
217
- " \"Respond clearly and factually; do not speculate on unavailable data; avoid any \"\n",
218
- " \"refund-related discussion; do not provide financial, legal, or compensation advice; \"\n",
219
- " \"prioritize user clarity and safety.\"\n",
220
- " ),\n",
221
- " constraints=(\n",
222
- " \"Cannot modify shipments, initiate refunds, open claims, contact drivers, or view \"\n",
223
- " \"internal logistics notes. Limited strictly to interpreting publicly available \"\n",
224
- " \"tracking data.\"\n",
225
- " ),\n",
226
- " fallback=(\n",
227
- " \"If tracking data is missing or the request is outside the allowed scope, inform \"\n",
228
- " \"the user clearly and redirect them to alternative support channels without \"\n",
229
- " \"inventing information.\"\n",
230
- " ),\n",
231
- " website_url=\"https://www.trackmate-delivery.com\",\n",
232
- ")\n",
233
- "\n",
234
- "print(ai_service_description_complete.model_dump_json(indent=4))"
235
- ]
236
- },
237
- {
238
- "cell_type": "code",
239
- "execution_count": null,
240
- "id": "ba983336",
241
- "metadata": {},
242
- "outputs": [],
243
- "source": []
244
- }
245
- ],
246
- "metadata": {
247
- "kernelspec": {
248
- "display_name": "orbitals",
249
- "language": "python",
250
- "name": "python3"
251
- },
252
- "language_info": {
253
- "codemirror_mode": {
254
- "name": "ipython",
255
- "version": 3
256
- },
257
- "file_extension": ".py",
258
- "mimetype": "text/x-python",
259
- "name": "python",
260
- "nbconvert_exporter": "python",
261
- "pygments_lexer": "ipython3",
262
- "version": "3.10.13"
263
- }
264
- },
265
- "nbformat": 4,
266
- "nbformat_minor": 5
267
- }
File without changes
File without changes
File without changes
File without changes