aip-agents-binary 0.5.23__py3-none-macosx_13_0_arm64.whl → 0.5.25__py3-none-macosx_13_0_arm64.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.
- aip_agents/agent/base_langgraph_agent.py +6 -0
- aip_agents/agent/langgraph_react_agent.py +96 -14
- aip_agents/agent/langgraph_react_agent.pyi +6 -1
- aip_agents/guardrails/__init__.py +83 -0
- aip_agents/guardrails/__init__.pyi +6 -0
- aip_agents/guardrails/engines/__init__.py +69 -0
- aip_agents/guardrails/engines/__init__.pyi +4 -0
- aip_agents/guardrails/engines/base.py +90 -0
- aip_agents/guardrails/engines/base.pyi +61 -0
- aip_agents/guardrails/engines/nemo.py +101 -0
- aip_agents/guardrails/engines/nemo.pyi +46 -0
- aip_agents/guardrails/engines/phrase_matcher.py +113 -0
- aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
- aip_agents/guardrails/exceptions.py +39 -0
- aip_agents/guardrails/exceptions.pyi +23 -0
- aip_agents/guardrails/manager.py +163 -0
- aip_agents/guardrails/manager.pyi +42 -0
- aip_agents/guardrails/middleware.py +199 -0
- aip_agents/guardrails/middleware.pyi +87 -0
- aip_agents/guardrails/schemas.py +63 -0
- aip_agents/guardrails/schemas.pyi +43 -0
- aip_agents/guardrails/utils.py +45 -0
- aip_agents/guardrails/utils.pyi +19 -0
- aip_agents/mcp/client/persistent_session.py +6 -3
- aip_agents/middleware/base.py +8 -0
- aip_agents/middleware/base.pyi +4 -0
- aip_agents/middleware/manager.py +22 -0
- aip_agents/middleware/manager.pyi +4 -0
- {aip_agents_binary-0.5.23.dist-info → aip_agents_binary-0.5.25.dist-info}/METADATA +3 -1
- {aip_agents_binary-0.5.23.dist-info → aip_agents_binary-0.5.25.dist-info}/RECORD +32 -12
- {aip_agents_binary-0.5.23.dist-info → aip_agents_binary-0.5.25.dist-info}/WHEEL +0 -0
- {aip_agents_binary-0.5.23.dist-info → aip_agents_binary-0.5.25.dist-info}/top_level.txt +0 -0
|
@@ -1225,6 +1225,12 @@ class BaseLangGraphAgent(BaseAgent):
|
|
|
1225
1225
|
async for chunk in transformer.transform_stream(self.arun_a2a_stream(query, **kwargs)):
|
|
1226
1226
|
yield chunk
|
|
1227
1227
|
except Exception as e:
|
|
1228
|
+
# Lazy import to support optional guardrails dependency
|
|
1229
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError
|
|
1230
|
+
|
|
1231
|
+
if isinstance(e, GuardrailViolationError):
|
|
1232
|
+
# Re-raise guardrail violations without modification
|
|
1233
|
+
raise
|
|
1228
1234
|
logger.error(f"Agent '{self.name}': Error in arun_sse_stream: {e}", exc_info=True)
|
|
1229
1235
|
yield SSEChunkTransformer._create_error_chunk(f"Error during streaming: {e}")
|
|
1230
1236
|
|
|
@@ -6,8 +6,11 @@ Authors:
|
|
|
6
6
|
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
7
7
|
Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
|
|
8
8
|
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
9
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
9
10
|
"""
|
|
10
11
|
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
11
14
|
import asyncio
|
|
12
15
|
import time
|
|
13
16
|
import uuid
|
|
@@ -15,9 +18,12 @@ from collections.abc import Awaitable, Callable, Sequence
|
|
|
15
18
|
from dataclasses import asdict, dataclass
|
|
16
19
|
from functools import reduce
|
|
17
20
|
from textwrap import dedent
|
|
18
|
-
from typing import Annotated, Any
|
|
21
|
+
from typing import TYPE_CHECKING, Annotated, Any
|
|
19
22
|
|
|
20
23
|
from deprecated import deprecated
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from aip_agents.guardrails.manager import GuardrailManager
|
|
21
27
|
from gllm_core.event import EventEmitter
|
|
22
28
|
from gllm_core.schema import Chunk
|
|
23
29
|
from langchain_core.language_models import BaseChatModel
|
|
@@ -157,6 +163,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
157
163
|
tool_output_manager: ToolOutputManager | None = None,
|
|
158
164
|
planning: bool = False,
|
|
159
165
|
middlewares: Sequence[AgentMiddleware] | None = None,
|
|
166
|
+
guardrail: GuardrailManager | None = None,
|
|
160
167
|
step_limit_config: StepLimitConfig | None = None,
|
|
161
168
|
**kwargs: Any,
|
|
162
169
|
):
|
|
@@ -178,8 +185,12 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
178
185
|
planning: Enable planning capabilities with TodoListMiddleware. Defaults to False.
|
|
179
186
|
middlewares: Optional sequence of custom middleware to COMPOSE (not override) with built-in middleware.
|
|
180
187
|
Execution order: [TodoListMiddleware (if planning=True),
|
|
188
|
+
GuardrailMiddleware (if guardrail provided),
|
|
181
189
|
...custom middlewares in order provided]
|
|
182
190
|
All middleware hooks execute - this extends capabilities, never replaces them.
|
|
191
|
+
guardrail: Optional GuardrailManager for content filtering and safety checks.
|
|
192
|
+
When provided, automatically wraps in GuardrailMiddleware for transparent
|
|
193
|
+
input/output filtering during agent execution.
|
|
183
194
|
enable_pii: Optional toggle to enable PII handling for tool inputs and outputs.
|
|
184
195
|
step_limit_config: Optional configuration for step limits and delegation depth.
|
|
185
196
|
**kwargs: Additional keyword arguments passed to BaseLangGraphAgent.
|
|
@@ -212,6 +223,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
212
223
|
# Setup middleware
|
|
213
224
|
self._middleware_manager = self._setup_middleware(
|
|
214
225
|
planning=planning,
|
|
226
|
+
guardrail=guardrail,
|
|
215
227
|
custom_middlewares=middlewares,
|
|
216
228
|
)
|
|
217
229
|
|
|
@@ -224,15 +236,17 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
224
236
|
def _setup_middleware(
|
|
225
237
|
self,
|
|
226
238
|
planning: bool,
|
|
239
|
+
guardrail: GuardrailManager | None,
|
|
227
240
|
custom_middlewares: Sequence[AgentMiddleware] | None,
|
|
228
241
|
) -> MiddlewareManager | None:
|
|
229
242
|
"""Setup middleware based on configuration.
|
|
230
243
|
|
|
231
|
-
Creates auto-configured middleware (planning) and composes
|
|
244
|
+
Creates auto-configured middleware (planning, guardrails) and composes
|
|
232
245
|
with custom middleware if provided.
|
|
233
246
|
|
|
234
247
|
Args:
|
|
235
248
|
planning: Whether to enable TodoListMiddleware.
|
|
249
|
+
guardrail: Optional GuardrailManager to wrap in GuardrailMiddleware.
|
|
236
250
|
custom_middlewares: Optional custom middlewares to append.
|
|
237
251
|
|
|
238
252
|
Returns:
|
|
@@ -244,6 +258,12 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
244
258
|
if planning:
|
|
245
259
|
middleware_list.append(TodoListMiddleware())
|
|
246
260
|
|
|
261
|
+
# Auto-configure GuardrailMiddleware if guardrail provided
|
|
262
|
+
if guardrail:
|
|
263
|
+
from aip_agents.guardrails.middleware import GuardrailMiddleware
|
|
264
|
+
|
|
265
|
+
middleware_list.append(GuardrailMiddleware(guardrail))
|
|
266
|
+
|
|
247
267
|
# Append custom middlewares
|
|
248
268
|
if custom_middlewares:
|
|
249
269
|
middleware_list.extend(custom_middlewares)
|
|
@@ -579,14 +599,29 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
579
599
|
current_messages = state["messages"]
|
|
580
600
|
|
|
581
601
|
# Execute LLM call
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
602
|
+
try:
|
|
603
|
+
if self.lm_invoker:
|
|
604
|
+
result = await self._handle_lm_invoker_call(current_messages, state, config)
|
|
605
|
+
elif isinstance(self.model, BaseChatModel):
|
|
606
|
+
result = await self._handle_langchain_model_call(current_messages, state, config)
|
|
607
|
+
else:
|
|
608
|
+
raise ValueError(
|
|
609
|
+
f"Agent '{self.name}': No valid LMInvoker or LangChain model configured for ReAct agent node."
|
|
610
|
+
)
|
|
611
|
+
except Exception as e:
|
|
612
|
+
# Lazy import to support optional guardrails dependency
|
|
613
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError
|
|
614
|
+
|
|
615
|
+
if isinstance(e, GuardrailViolationError):
|
|
616
|
+
return {
|
|
617
|
+
"messages": [
|
|
618
|
+
AIMessage(
|
|
619
|
+
content=f"⚠️ Guardrail violation: {e.result.reason}",
|
|
620
|
+
response_metadata={"finish_reason": "stop"},
|
|
621
|
+
)
|
|
622
|
+
]
|
|
623
|
+
}
|
|
624
|
+
raise
|
|
590
625
|
|
|
591
626
|
# Increment step counter after successful execution
|
|
592
627
|
manager.increment_step()
|
|
@@ -1954,6 +1989,47 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1954
1989
|
)
|
|
1955
1990
|
writer(a2a_event)
|
|
1956
1991
|
|
|
1992
|
+
async def _execute_abefore_model_hook(self, state: dict[str, Any]) -> None:
|
|
1993
|
+
"""Asynchronously execute abefore_model middleware hook and update state.
|
|
1994
|
+
|
|
1995
|
+
Args:
|
|
1996
|
+
state: Current agent state to potentially update.
|
|
1997
|
+
"""
|
|
1998
|
+
if self._middleware_manager:
|
|
1999
|
+
try:
|
|
2000
|
+
before_updates = await self._middleware_manager.abefore_model(state)
|
|
2001
|
+
if before_updates:
|
|
2002
|
+
state.update(before_updates)
|
|
2003
|
+
except Exception as e:
|
|
2004
|
+
# Lazy import to support optional guardrails dependency
|
|
2005
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError
|
|
2006
|
+
|
|
2007
|
+
if isinstance(e, GuardrailViolationError):
|
|
2008
|
+
# Re-raise guardrail violations to be caught by the agent node
|
|
2009
|
+
raise
|
|
2010
|
+
logger.error(f"Agent '{self.name}': Middleware abefore_model hook failed: {e}")
|
|
2011
|
+
|
|
2012
|
+
async def _execute_aafter_model_hook(self, state_updates: dict[str, Any], state: dict[str, Any]) -> None:
|
|
2013
|
+
"""Asynchronously execute aafter_model middleware hook.
|
|
2014
|
+
|
|
2015
|
+
Args:
|
|
2016
|
+
state_updates: Updates to be merged into state.
|
|
2017
|
+
state: Current agent state for context.
|
|
2018
|
+
"""
|
|
2019
|
+
if self._middleware_manager:
|
|
2020
|
+
try:
|
|
2021
|
+
after_updates = await self._middleware_manager.aafter_model(state)
|
|
2022
|
+
if after_updates:
|
|
2023
|
+
state_updates.update(after_updates)
|
|
2024
|
+
except Exception as e:
|
|
2025
|
+
# Lazy import to support optional guardrails dependency
|
|
2026
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError
|
|
2027
|
+
|
|
2028
|
+
if isinstance(e, GuardrailViolationError):
|
|
2029
|
+
# Re-raise guardrail violations
|
|
2030
|
+
raise
|
|
2031
|
+
logger.error(f"Agent '{self.name}': Middleware aafter_model hook failed: {e}")
|
|
2032
|
+
|
|
1957
2033
|
def _execute_before_model_hook(self, state: dict[str, Any]) -> None:
|
|
1958
2034
|
"""Execute before_model middleware hook and update state.
|
|
1959
2035
|
|
|
@@ -1966,6 +2042,12 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1966
2042
|
if before_updates:
|
|
1967
2043
|
state.update(before_updates)
|
|
1968
2044
|
except Exception as e:
|
|
2045
|
+
# Lazy import to support optional guardrails dependency
|
|
2046
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError
|
|
2047
|
+
|
|
2048
|
+
if isinstance(e, GuardrailViolationError):
|
|
2049
|
+
# Re-raise guardrail violations to be caught by the agent node
|
|
2050
|
+
raise
|
|
1969
2051
|
logger.error(f"Agent '{self.name}': Middleware before_model hook failed: {e}")
|
|
1970
2052
|
|
|
1971
2053
|
def _execute_modify_model_request_hook(
|
|
@@ -2029,7 +2111,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
2029
2111
|
dict[str, Any]: A dictionary containing the new messages and updated token usage.
|
|
2030
2112
|
"""
|
|
2031
2113
|
# Execute before_model middleware hook
|
|
2032
|
-
self.
|
|
2114
|
+
await self._execute_abefore_model_hook(state)
|
|
2033
2115
|
|
|
2034
2116
|
# Build tool output aware instruction
|
|
2035
2117
|
enhanced_instruction = self._build_tool_output_aware_instruction(self.instruction, state, config)
|
|
@@ -2063,7 +2145,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
2063
2145
|
state_updates.update(token_usage_updates)
|
|
2064
2146
|
|
|
2065
2147
|
# Execute after_model middleware hook
|
|
2066
|
-
self.
|
|
2148
|
+
await self._execute_aafter_model_hook(state_updates, state)
|
|
2067
2149
|
|
|
2068
2150
|
return state_updates
|
|
2069
2151
|
|
|
@@ -2081,7 +2163,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
2081
2163
|
dict[str, Any]: A dictionary containing the new messages and updated token usage.
|
|
2082
2164
|
"""
|
|
2083
2165
|
# Execute before_model middleware hook
|
|
2084
|
-
self.
|
|
2166
|
+
await self._execute_abefore_model_hook(state)
|
|
2085
2167
|
|
|
2086
2168
|
# Build tool output aware instruction
|
|
2087
2169
|
enhanced_instruction = self._build_tool_output_aware_instruction(self.instruction, state, config)
|
|
@@ -2113,7 +2195,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
2113
2195
|
state_updates.update(token_usage_updates)
|
|
2114
2196
|
|
|
2115
2197
|
# Execute after_model middleware hook
|
|
2116
|
-
self.
|
|
2198
|
+
await self._execute_aafter_model_hook(state_updates, state)
|
|
2117
2199
|
|
|
2118
2200
|
return state_updates
|
|
2119
2201
|
|
|
@@ -2,6 +2,7 @@ from _typeshed import Incomplete
|
|
|
2
2
|
from aip_agents.agent.base_langgraph_agent import BaseLangGraphAgent as BaseLangGraphAgent
|
|
3
3
|
from aip_agents.agent.hitl.langgraph_hitl_mixin import LangGraphHitLMixin as LangGraphHitLMixin
|
|
4
4
|
from aip_agents.agent.hitl.manager import TOOL_EXECUTION_BLOCKING_DECISIONS as TOOL_EXECUTION_BLOCKING_DECISIONS
|
|
5
|
+
from aip_agents.guardrails.manager import GuardrailManager as GuardrailManager
|
|
5
6
|
from aip_agents.middleware.base import AgentMiddleware as AgentMiddleware, ModelRequest as ModelRequest
|
|
6
7
|
from aip_agents.middleware.manager import MiddlewareManager as MiddlewareManager
|
|
7
8
|
from aip_agents.middleware.todolist import TodoList as TodoList, TodoListMiddleware as TodoListMiddleware
|
|
@@ -85,7 +86,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
85
86
|
"""
|
|
86
87
|
tool_output_manager: Incomplete
|
|
87
88
|
step_limit_config: Incomplete
|
|
88
|
-
def __init__(self, name: str, instruction: str = ..., model: BaseChatModel | str | Any | None = None, tools: Sequence[BaseTool] | None = None, agents: Sequence[Any] | None = None, description: str | None = None, thread_id_key: str = 'thread_id', event_emitter: EventEmitter | None = None, tool_output_manager: ToolOutputManager | None = None, planning: bool = False, middlewares: Sequence[AgentMiddleware] | None = None, step_limit_config: StepLimitConfig | None = None, **kwargs: Any) -> None:
|
|
89
|
+
def __init__(self, name: str, instruction: str = ..., model: BaseChatModel | str | Any | None = None, tools: Sequence[BaseTool] | None = None, agents: Sequence[Any] | None = None, description: str | None = None, thread_id_key: str = 'thread_id', event_emitter: EventEmitter | None = None, tool_output_manager: ToolOutputManager | None = None, planning: bool = False, middlewares: Sequence[AgentMiddleware] | None = None, guardrail: GuardrailManager | None = None, step_limit_config: StepLimitConfig | None = None, **kwargs: Any) -> None:
|
|
89
90
|
"""Initialize the LangGraph ReAct Agent.
|
|
90
91
|
|
|
91
92
|
Args:
|
|
@@ -104,8 +105,12 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
104
105
|
planning: Enable planning capabilities with TodoListMiddleware. Defaults to False.
|
|
105
106
|
middlewares: Optional sequence of custom middleware to COMPOSE (not override) with built-in middleware.
|
|
106
107
|
Execution order: [TodoListMiddleware (if planning=True),
|
|
108
|
+
GuardrailMiddleware (if guardrail provided),
|
|
107
109
|
...custom middlewares in order provided]
|
|
108
110
|
All middleware hooks execute - this extends capabilities, never replaces them.
|
|
111
|
+
guardrail: Optional GuardrailManager for content filtering and safety checks.
|
|
112
|
+
When provided, automatically wraps in GuardrailMiddleware for transparent
|
|
113
|
+
input/output filtering during agent execution.
|
|
109
114
|
enable_pii: Optional toggle to enable PII handling for tool inputs and outputs.
|
|
110
115
|
step_limit_config: Optional configuration for step limits and delegation depth.
|
|
111
116
|
**kwargs: Additional keyword arguments passed to BaseLangGraphAgent.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# flake8: noqa: F401
|
|
2
|
+
"""Guardrails package for content filtering and safety checks.
|
|
3
|
+
|
|
4
|
+
This package provides modular guardrail engines and managers for filtering
|
|
5
|
+
harmful content in AI agent interactions. All components support lazy loading
|
|
6
|
+
to work with optional dependencies.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
Basic usage with a phrase matcher engine:
|
|
10
|
+
|
|
11
|
+
.. code-block:: python
|
|
12
|
+
|
|
13
|
+
from aip_agents.guardrails import GuardrailManager, GuardrailMiddleware
|
|
14
|
+
from aip_agents.guardrails.engines import PhraseMatcherEngine
|
|
15
|
+
from aip_agents.guardrails.schemas import GuardrailMode
|
|
16
|
+
|
|
17
|
+
# Create a guardrail engine
|
|
18
|
+
engine = PhraseMatcherEngine(
|
|
19
|
+
banned_phrases=["spam", "inappropriate"]
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Create a manager
|
|
23
|
+
manager = GuardrailManager(engines=[engine])
|
|
24
|
+
|
|
25
|
+
# Create middleware for agent integration
|
|
26
|
+
middleware = GuardrailMiddleware(guardrail_manager=manager)
|
|
27
|
+
|
|
28
|
+
# Use with agent (components are lazy-loaded)
|
|
29
|
+
from aip_agents.agent import LangGraphReactAgent
|
|
30
|
+
agent = LangGraphReactAgent(
|
|
31
|
+
name="my_agent",
|
|
32
|
+
guardrail=manager,
|
|
33
|
+
# ... other agent config
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
Authors:
|
|
37
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from typing import TYPE_CHECKING, Any
|
|
41
|
+
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError
|
|
44
|
+
from aip_agents.guardrails.manager import GuardrailManager
|
|
45
|
+
from aip_agents.guardrails.middleware import GuardrailMiddleware
|
|
46
|
+
from aip_agents.guardrails.schemas import (
|
|
47
|
+
BaseGuardrailEngineConfig,
|
|
48
|
+
GuardrailInput,
|
|
49
|
+
GuardrailMode,
|
|
50
|
+
GuardrailResult,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
_IMPORT_MAP = {
|
|
55
|
+
"GuardrailViolationError": "aip_agents.guardrails.exceptions",
|
|
56
|
+
"GuardrailManager": "aip_agents.guardrails.manager",
|
|
57
|
+
"GuardrailMiddleware": "aip_agents.guardrails.middleware",
|
|
58
|
+
"BaseGuardrailEngineConfig": "aip_agents.guardrails.schemas",
|
|
59
|
+
"GuardrailMode": "aip_agents.guardrails.schemas",
|
|
60
|
+
"GuardrailInput": "aip_agents.guardrails.schemas",
|
|
61
|
+
"GuardrailResult": "aip_agents.guardrails.schemas",
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_cache: dict[str, Any] = {}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def __getattr__(name: str) -> Any:
|
|
68
|
+
"""Lazy import components on first access."""
|
|
69
|
+
if name in _cache:
|
|
70
|
+
return _cache[name]
|
|
71
|
+
|
|
72
|
+
if name in _IMPORT_MAP:
|
|
73
|
+
try:
|
|
74
|
+
module = __import__(_IMPORT_MAP[name], fromlist=[name])
|
|
75
|
+
_cache[name] = getattr(module, name)
|
|
76
|
+
return _cache[name]
|
|
77
|
+
except ImportError as e:
|
|
78
|
+
raise ImportError(f"Failed to import {name}. Optional dependencies may be missing: {e}") from e
|
|
79
|
+
|
|
80
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
__all__ = list(_IMPORT_MAP.keys())
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError as GuardrailViolationError
|
|
2
|
+
from aip_agents.guardrails.manager import GuardrailManager as GuardrailManager
|
|
3
|
+
from aip_agents.guardrails.middleware import GuardrailMiddleware as GuardrailMiddleware
|
|
4
|
+
from aip_agents.guardrails.schemas import BaseGuardrailEngineConfig as BaseGuardrailEngineConfig, GuardrailInput as GuardrailInput, GuardrailMode as GuardrailMode, GuardrailResult as GuardrailResult
|
|
5
|
+
|
|
6
|
+
__all__ = ['GuardrailViolationError', 'GuardrailManager', 'GuardrailMiddleware', 'BaseGuardrailEngineConfig', 'GuardrailMode', 'GuardrailInput', 'GuardrailResult']
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# flake8: noqa: F401
|
|
2
|
+
"""Guardrail engines package with lazy loading support.
|
|
3
|
+
|
|
4
|
+
This package provides guardrail engines that wrap GL SDK implementations.
|
|
5
|
+
Engines are loaded lazily to support optional dependencies.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
Import and use guardrail engines:
|
|
9
|
+
|
|
10
|
+
.. code-block:: python
|
|
11
|
+
|
|
12
|
+
# Lazy import - works even if gllm-guardrail is not installed
|
|
13
|
+
from aip_agents.guardrails.engines import PhraseMatcherEngine, NemoGuardrailEngine
|
|
14
|
+
|
|
15
|
+
# Create a phrase matcher engine
|
|
16
|
+
phrase_engine = PhraseMatcherEngine(
|
|
17
|
+
banned_phrases=["spam", "inappropriate"]
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Create a NeMo guardrail engine (requires gllm-guardrail)
|
|
21
|
+
nemo_engine = NemoGuardrailEngine(
|
|
22
|
+
# NeMo-specific configuration
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Use with GuardrailManager
|
|
26
|
+
from aip_agents.guardrails import GuardrailManager
|
|
27
|
+
manager = GuardrailManager(engines=[phrase_engine, nemo_engine])
|
|
28
|
+
|
|
29
|
+
Note:
|
|
30
|
+
All engines support lazy loading. If `gllm-guardrail` is not installed,
|
|
31
|
+
importing these engines will raise an ImportError only when actually
|
|
32
|
+
instantiated, not at import time.
|
|
33
|
+
|
|
34
|
+
Authors:
|
|
35
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from typing import TYPE_CHECKING, Any
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from aip_agents.guardrails.engines.nemo import NemoGuardrailEngine
|
|
42
|
+
from aip_agents.guardrails.engines.phrase_matcher import PhraseMatcherEngine
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
_IMPORT_MAP = {
|
|
46
|
+
"NemoGuardrailEngine": "aip_agents.guardrails.engines.nemo",
|
|
47
|
+
"PhraseMatcherEngine": "aip_agents.guardrails.engines.phrase_matcher",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_cache: dict[str, Any] = {}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def __getattr__(name: str) -> Any:
|
|
54
|
+
"""Lazy import engines on first access."""
|
|
55
|
+
if name in _cache:
|
|
56
|
+
return _cache[name]
|
|
57
|
+
|
|
58
|
+
if name in _IMPORT_MAP:
|
|
59
|
+
try:
|
|
60
|
+
module = __import__(_IMPORT_MAP[name], fromlist=[name])
|
|
61
|
+
_cache[name] = getattr(module, name)
|
|
62
|
+
return _cache[name]
|
|
63
|
+
except ImportError as e:
|
|
64
|
+
raise ImportError(f"Failed to import {name}. Optional dependencies may be missing: {e}") from e
|
|
65
|
+
|
|
66
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
__all__ = list(_IMPORT_MAP.keys())
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Base interfaces and protocols for guardrail engines.
|
|
2
|
+
|
|
3
|
+
This module defines the base protocol that all guardrail engines must implement,
|
|
4
|
+
providing a consistent interface for content safety checking.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
8
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from typing import Protocol
|
|
13
|
+
|
|
14
|
+
from aip_agents.guardrails.schemas import (
|
|
15
|
+
BaseGuardrailEngineConfig,
|
|
16
|
+
GuardrailResult,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class GuardrailEngine(Protocol):
|
|
21
|
+
"""Protocol defining the interface for guardrail engines.
|
|
22
|
+
|
|
23
|
+
All guardrail engines must implement this protocol to be compatible
|
|
24
|
+
with GuardrailManager. Engines check content for safety violations.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
config: Configuration for this engine's behavior
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
config: BaseGuardrailEngineConfig
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
async def check_input(self, content: str) -> GuardrailResult:
|
|
34
|
+
"""Check user input content for safety violations.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
content: The user input content to check
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
GuardrailResult indicating if content is safe
|
|
41
|
+
"""
|
|
42
|
+
...
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
async def check_output(self, content: str) -> GuardrailResult:
|
|
46
|
+
"""Check AI output content for safety violations.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
content: The AI output content to check
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
GuardrailResult indicating if content is safe
|
|
53
|
+
"""
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def model_dump(self) -> dict:
|
|
58
|
+
"""Serialize engine configuration into a JSON-compatible dictionary."""
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class BaseGuardrailEngine(ABC):
|
|
63
|
+
"""Abstract base class for guardrail engines.
|
|
64
|
+
|
|
65
|
+
Provides common functionality and ensures proper configuration handling.
|
|
66
|
+
Concrete engines should inherit from this class.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, config: BaseGuardrailEngineConfig | None = None) -> None:
|
|
70
|
+
"""Initialize the engine with configuration.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
config: Engine configuration. Uses defaults if None provided.
|
|
74
|
+
"""
|
|
75
|
+
self.config = config or BaseGuardrailEngineConfig()
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
async def check_input(self, content: str) -> GuardrailResult:
|
|
79
|
+
"""Check user input content for safety violations."""
|
|
80
|
+
...
|
|
81
|
+
|
|
82
|
+
@abstractmethod
|
|
83
|
+
async def check_output(self, content: str) -> GuardrailResult:
|
|
84
|
+
"""Check AI output content for safety violations."""
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
@abstractmethod
|
|
88
|
+
def model_dump(self) -> dict:
|
|
89
|
+
"""Serialize engine configuration into a JSON-compatible dictionary."""
|
|
90
|
+
...
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from aip_agents.guardrails.schemas import BaseGuardrailEngineConfig as BaseGuardrailEngineConfig, GuardrailResult as GuardrailResult
|
|
4
|
+
from typing import Protocol
|
|
5
|
+
|
|
6
|
+
class GuardrailEngine(Protocol):
|
|
7
|
+
"""Protocol defining the interface for guardrail engines.
|
|
8
|
+
|
|
9
|
+
All guardrail engines must implement this protocol to be compatible
|
|
10
|
+
with GuardrailManager. Engines check content for safety violations.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
config: Configuration for this engine's behavior
|
|
14
|
+
"""
|
|
15
|
+
config: BaseGuardrailEngineConfig
|
|
16
|
+
@abstractmethod
|
|
17
|
+
async def check_input(self, content: str) -> GuardrailResult:
|
|
18
|
+
"""Check user input content for safety violations.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
content: The user input content to check
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
GuardrailResult indicating if content is safe
|
|
25
|
+
"""
|
|
26
|
+
@abstractmethod
|
|
27
|
+
async def check_output(self, content: str) -> GuardrailResult:
|
|
28
|
+
"""Check AI output content for safety violations.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
content: The AI output content to check
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
GuardrailResult indicating if content is safe
|
|
35
|
+
"""
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def model_dump(self) -> dict:
|
|
38
|
+
"""Serialize engine configuration into a JSON-compatible dictionary."""
|
|
39
|
+
|
|
40
|
+
class BaseGuardrailEngine(ABC):
|
|
41
|
+
"""Abstract base class for guardrail engines.
|
|
42
|
+
|
|
43
|
+
Provides common functionality and ensures proper configuration handling.
|
|
44
|
+
Concrete engines should inherit from this class.
|
|
45
|
+
"""
|
|
46
|
+
config: Incomplete
|
|
47
|
+
def __init__(self, config: BaseGuardrailEngineConfig | None = None) -> None:
|
|
48
|
+
"""Initialize the engine with configuration.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
config: Engine configuration. Uses defaults if None provided.
|
|
52
|
+
"""
|
|
53
|
+
@abstractmethod
|
|
54
|
+
async def check_input(self, content: str) -> GuardrailResult:
|
|
55
|
+
"""Check user input content for safety violations."""
|
|
56
|
+
@abstractmethod
|
|
57
|
+
async def check_output(self, content: str) -> GuardrailResult:
|
|
58
|
+
"""Check AI output content for safety violations."""
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def model_dump(self) -> dict:
|
|
61
|
+
"""Serialize engine configuration into a JSON-compatible dictionary."""
|