Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feautre] Add custom redact functionality to SDK #2269

Merged
merged 3 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions agenta-cli/agenta/__init__.py
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly

  • cleaning up dirty code from previous PRs
  • passing down redact and redact_on_error

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Any, Callable, Optional

from .sdk.utils.preinit import PreInitObject

import agenta.client.backend.types as client_types # pylint: disable=wrong-import-order
Expand All @@ -18,7 +20,7 @@
)

from .sdk.utils.logging import log as logging
from .sdk.tracing import Tracing
from .sdk.tracing import Tracing, get_tracer
from .sdk.decorators.tracing import instrument
from .sdk.tracing.conventions import Reference
from .sdk.decorators.routing import entrypoint, app, route
Expand All @@ -36,15 +38,36 @@
DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()

types = client_types
tracing = None

api = None
async_api = None

tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
tracer = get_tracer(tracing)

def init(*args, **kwargs):
global api, async_api, tracing, config
_init(*args, **kwargs)

tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
def init(
host: Optional[str] = None,
api_key: Optional[str] = None,
config_fname: Optional[str] = None,
redact: Optional[Callable[..., Any]] = None,
redact_on_error: Optional[bool] = True,
# DEPRECATING
app_id: Optional[str] = None,
):
global api, async_api, tracing, tracer # pylint: disable=global-statement

_init(
host=host,
api_key=api_key,
config_fname=config_fname,
redact=redact,
redact_on_error=redact_on_error,
app_id=app_id,
)

api = DEFAULT_AGENTA_SINGLETON_INSTANCE.api # type: ignore
async_api = DEFAULT_AGENTA_SINGLETON_INSTANCE.async_api # type: ignore

tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
tracer = get_tracer(tracing)
12 changes: 8 additions & 4 deletions agenta-cli/agenta/sdk/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional
from typing import Optional, Callable, Any

from .utils.preinit import PreInitObject # always the first import!

Expand Down Expand Up @@ -43,17 +43,21 @@

def init(
host: Optional[str] = None,
app_id: Optional[str] = None,
api_key: Optional[str] = None,
config_fname: Optional[str] = None,
redact: Optional[Callable[..., Any]] = None,
redact_on_error: Optional[bool] = True,
# DEPRECATING
app_id: Optional[str] = None,
):
global api, async_api, tracing, tracer
global api, async_api, tracing, tracer # pylint: disable=global-statement

_init(
host=host,
api_key=api_key,
config_fname=config_fname,
# DEPRECATING
redact=redact,
redact_on_error=redact_on_error,
app_id=app_id,
)

Expand Down
13 changes: 10 additions & 3 deletions agenta-cli/agenta/sdk/agenta_init.py
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly

  • cleaning up dirty code from previous PRs
  • passing down redact and redact_on_error

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import toml
from os import getenv
from typing import Optional
from typing import Optional, Callable, Any
from importlib.metadata import version

from agenta.sdk.utils.logging import log
Expand Down Expand Up @@ -36,6 +36,8 @@ def init(
host: Optional[str] = None,
api_key: Optional[str] = None,
config_fname: Optional[str] = None,
redact: Optional[Callable[..., Any]] = None,
redact_on_error: Optional[bool] = True,
# DEPRECATING
app_id: Optional[str] = None,
) -> None:
Expand Down Expand Up @@ -91,6 +93,8 @@ def init(

self.tracing = Tracing(
url=f"{self.host}/api/observability/v1/otlp/traces", # type: ignore
redact=redact,
redact_on_error=redact_on_error,
)

self.tracing.configure(
Expand Down Expand Up @@ -258,7 +262,9 @@ def init(
host: Optional[str] = None,
api_key: Optional[str] = None,
config_fname: Optional[str] = None,
# DEPRECATED
redact: Optional[Callable[..., Any]] = None,
redact_on_error: Optional[bool] = True,
# DEPRECATING
app_id: Optional[str] = None,
):
"""Main function to initialize the agenta sdk.
Expand Down Expand Up @@ -289,7 +295,8 @@ def init(
host=host,
api_key=api_key,
config_fname=config_fname,
# DEPRECATED
redact=redact,
redact_on_error=redact_on_error,
app_id=app_id,
)

Expand Down
38 changes: 31 additions & 7 deletions agenta-cli/agenta/sdk/decorators/tracing.py
Copy link
Contributor Author

@jp-agenta jp-agenta Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where instrument-specific redact is stored and where things happen.

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ def __init__(
config: Optional[Dict[str, Any]] = None,
ignore_inputs: Optional[bool] = None,
ignore_outputs: Optional[bool] = None,
redact: Optional[Callable[..., Any]] = None,
redact_on_error: Optional[bool] = True,
max_depth: Optional[int] = 2,
# DEPRECATING
kind: str = "task",
Expand All @@ -29,6 +31,8 @@ def __init__(
self.config = config
self.ignore_inputs = ignore_inputs
self.ignore_outputs = ignore_outputs
self.redact = redact
self.redact_on_error = redact_on_error
self.max_depth = max_depth

def __call__(self, func: Callable[..., Any]):
Expand Down Expand Up @@ -109,12 +113,10 @@ def _pre_instrument(
)

_inputs = self._redact(
self._parse(
func,
*args,
**kwargs,
),
self.ignore_inputs,
name=span.name,
field="inputs",
io=self._parse(func, *args, **kwargs),
ignore=self.ignore_inputs,
)
span.set_attributes(
attributes={"inputs": _inputs},
Expand Down Expand Up @@ -153,7 +155,12 @@ def _post_instrument(
namespace="metrics.unit.tokens",
)

_outputs = self._redact(self._patch(result), self.ignore_outputs)
_outputs = self._redact(
name=span.name,
field="outputs",
io=self._patch(result),
ignore=self.ignore_outputs,
)
span.set_attributes(
attributes={"outputs": _outputs},
namespace="data",
Expand Down Expand Up @@ -192,6 +199,9 @@ def _parse(

def _redact(
self,
*,
name: str,
field: str,
io: Dict[str, Any],
ignore: Union[List[str], bool] = False,
) -> Dict[str, Any]:
Expand Down Expand Up @@ -220,6 +230,20 @@ def _redact(
)
}

if self.redact is not None:
try:
io = self.redact(name, field, io)
except: # pylint: disable=bare-except
if self.redact_on_error:
io = {}

if ag.tracing.redact is not None:
try:
io = ag.tracing.redact(name, field, io)
except: # pylint: disable=bare-except
if ag.tracing.redact_on_error:
io = {}

return io

def _patch(
Expand Down
8 changes: 7 additions & 1 deletion agenta-cli/agenta/sdk/tracing/tracing.py
Copy link
Contributor Author

@jp-agenta jp-agenta Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where cross-instrument redact is stored

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Any, Dict
from typing import Optional, Any, Dict, Callable
from enum import Enum

from httpx import get as check
Expand Down Expand Up @@ -32,6 +32,8 @@ class Tracing(metaclass=Singleton):
def __init__(
self,
url: str,
redact: Optional[Callable[..., Any]] = None,
redact_on_error: Optional[bool] = True,
) -> None:
# ENDPOINT (OTLP)
self.otlp_url = url
Expand All @@ -49,6 +51,10 @@ def __init__(
# INLINE SPANS for INLINE TRACES (INLINE PROCESSOR)
self.inline_spans: Dict[str, Any] = dict()

# REDACT
self.redact = redact
self.redact_on_error = redact_on_error

# PUBLIC

def configure(
Expand Down
18 changes: 18 additions & 0 deletions agenta-cli/tests/redact/01_ignore_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import agenta as ag

ag.init()


@ag.entrypoint
@ag.instrument(
spankind="WORKFLOW",
ignore_inputs=True,
ignore_outputs=True,
)
def embed(description: str):
return {
"embedding": "somedata",
"ignored": "ignored",
"cost": 15,
"usage": 20,
}
17 changes: 17 additions & 0 deletions agenta-cli/tests/redact/02_ignore_all_inputs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import agenta as ag

ag.init()


@ag.entrypoint
@ag.instrument(
spankind="WORKFLOW",
ignore_inputs=True,
)
def embed(description: str):
return {
"embedding": "somedata",
"ignored": "ignored",
"cost": 15,
"usage": 20,
}
17 changes: 17 additions & 0 deletions agenta-cli/tests/redact/03_ignore_all_outputs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import agenta as ag

ag.init()


@ag.entrypoint
@ag.instrument(
spankind="WORKFLOW",
ignore_inputs=True,
)
def embed(description: str):
return {
"embedding": "somedata",
"ignored": "ignored",
"cost": 15,
"usage": 20,
}
18 changes: 18 additions & 0 deletions agenta-cli/tests/redact/04_ignore_some.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import agenta as ag

ag.init()


@ag.entrypoint
@ag.instrument(
spankind="WORKFLOW",
ignore_inputs=["description"],
ignore_outputs=["embedding", "ignored"],
)
def embed(description: str, theme: str):
return {
"embedding": "somedata",
"ignored": "ignored",
"cost": 15,
"usage": 20,
}
30 changes: 30 additions & 0 deletions agenta-cli/tests/redact/05_redact_instrument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import agenta as ag

ag.init()


def redact(name, field, io):
print(">", name, field, io)

if name == "embed" and field == "inputs":
io = {key: value for key, value in io.items() if key not in ("description",)}

if name == "embed" and field == "outputs":
io = {key: value for key, value in io.items() if key not in ("embedding",)}

print("<", io)
return io


@ag.entrypoint
@ag.instrument(
spankind="WORKFLOW",
redact=redact,
)
def embed(description: str, theme: str):
return {
"embedding": "somedata",
"ignored": "ignored",
"cost": 15,
"usage": 20,
}
31 changes: 31 additions & 0 deletions agenta-cli/tests/redact/06_redact_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import agenta as ag


def redact(name, field, io):
print(">", name, field, io)

if name == "embed" and field == "inputs":
io = {key: value for key, value in io.items() if key not in ("description",)}

if name == "embed" and field == "outputs":
io = {key: value for key, value in io.items() if key not in ("embedding",)}

print("<", io)

return io


ag.init(redact=redact)


@ag.entrypoint
@ag.instrument(
spankind="WORKFLOW",
)
def embed(description: str, theme: str):
return {
"embedding": "somedata",
"ignored": "ignored",
"cost": 15,
"usage": 20,
}
Loading
Loading