Skip to content

Commit

Permalink
generalize helper for extracting token metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
ncybul committed Jan 22, 2025
1 parent 4611816 commit 635935e
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 41 deletions.
1 change: 1 addition & 0 deletions ddtrace/llmobs/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
INPUT_TOKENS_METRIC_KEY = "input_tokens"
OUTPUT_TOKENS_METRIC_KEY = "output_tokens"
TOTAL_TOKENS_METRIC_KEY = "total_tokens"
INTEGRATIONS_USING_INPUT_OUTPUT_TOKENS = {"anthropic"}

EVP_PROXY_AGENT_BASE_PATH = "evp_proxy/v2"
EVP_PROXY_AGENT_ENDPOINT = "{}/api/v2/llmobs".format(EVP_PROXY_AGENT_BASE_PATH)
Expand Down
18 changes: 2 additions & 16 deletions ddtrace/llmobs/_integrations/anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from ddtrace.llmobs._constants import SPAN_KIND
from ddtrace.llmobs._constants import TOTAL_TOKENS_METRIC_KEY
from ddtrace.llmobs._integrations.base import BaseLLMIntegration
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags
from ddtrace.llmobs._utils import _get_attr


Expand Down Expand Up @@ -77,7 +78,7 @@ def _llmobs_set_tags(
INPUT_MESSAGES: input_messages,
METADATA: parameters,
OUTPUT_MESSAGES: output_messages,
METRICS: self._get_llmobs_metrics_tags(span),
METRICS: get_llmobs_metrics_tags("anthropic", span),
}
)

Expand Down Expand Up @@ -188,18 +189,3 @@ def record_usage(self, span: Span, usage: Dict[str, Any]) -> None:
span.set_metric("anthropic.response.usage.output_tokens", output_tokens)
if input_tokens is not None and output_tokens is not None:
span.set_metric("anthropic.response.usage.total_tokens", input_tokens + output_tokens)

@staticmethod
def _get_llmobs_metrics_tags(span):
usage = {}
input_tokens = span.get_metric("anthropic.response.usage.input_tokens")
output_tokens = span.get_metric("anthropic.response.usage.output_tokens")
total_tokens = span.get_metric("anthropic.response.usage.total_tokens")

if input_tokens is not None:
usage[INPUT_TOKENS_METRIC_KEY] = input_tokens
if output_tokens is not None:
usage[OUTPUT_TOKENS_METRIC_KEY] = output_tokens
if total_tokens is not None:
usage[TOTAL_TOKENS_METRIC_KEY] = total_tokens
return usage
14 changes: 2 additions & 12 deletions ddtrace/llmobs/_integrations/bedrock.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from ddtrace.llmobs._constants import SPAN_KIND
from ddtrace.llmobs._constants import TOTAL_TOKENS_METRIC_KEY
from ddtrace.llmobs._integrations import BaseLLMIntegration
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags
from ddtrace.llmobs._utils import _get_llmobs_parent_id


Expand Down Expand Up @@ -57,22 +58,11 @@ def _llmobs_set_tags(
MODEL_PROVIDER: span.get_tag("bedrock.request.model_provider") or "",
INPUT_MESSAGES: input_messages,
METADATA: parameters,
METRICS: self._llmobs_metrics(span, response),
METRICS: get_llmobs_metrics_tags("bedrock", span),
OUTPUT_MESSAGES: output_messages,
}
)

@staticmethod
def _llmobs_metrics(span: Span, response: Optional[Dict[str, Any]]) -> Dict[str, Any]:
metrics = {}
if response and response.get("text"):
prompt_tokens = int(span.get_tag("bedrock.usage.prompt_tokens") or 0)
completion_tokens = int(span.get_tag("bedrock.usage.completion_tokens") or 0)
metrics[INPUT_TOKENS_METRIC_KEY] = prompt_tokens
metrics[OUTPUT_TOKENS_METRIC_KEY] = completion_tokens
metrics[TOTAL_TOKENS_METRIC_KEY] = prompt_tokens + completion_tokens
return metrics

@staticmethod
def _extract_input_message(prompt):
"""Extract input messages from the stored prompt.
Expand Down
4 changes: 2 additions & 2 deletions ddtrace/llmobs/_integrations/gemini.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from ddtrace.llmobs._constants import SPAN_KIND
from ddtrace.llmobs._integrations.base import BaseLLMIntegration
from ddtrace.llmobs._integrations.utils import extract_message_from_part_google
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags_google
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags
from ddtrace.llmobs._integrations.utils import get_system_instructions_from_google_model
from ddtrace.llmobs._integrations.utils import llmobs_get_metadata_google
from ddtrace.llmobs._utils import _get_attr
Expand Down Expand Up @@ -59,7 +59,7 @@ def _llmobs_set_tags(
METADATA: metadata,
INPUT_MESSAGES: input_messages,
OUTPUT_MESSAGES: output_messages,
METRICS: get_llmobs_metrics_tags_google("google_generativeai", span),
METRICS: get_llmobs_metrics_tags("google_generativeai", span),
}
)

Expand Down
11 changes: 2 additions & 9 deletions ddtrace/llmobs/_integrations/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from ddtrace.llmobs._constants import SPAN_KIND
from ddtrace.llmobs._constants import TOTAL_TOKENS_METRIC_KEY
from ddtrace.llmobs._integrations.base import BaseLLMIntegration
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags
from ddtrace.llmobs._utils import _get_attr
from ddtrace.llmobs.utils import Document
from ddtrace.trace import Pin
Expand Down Expand Up @@ -275,12 +276,4 @@ def _extract_llmobs_metrics_tags(span: Span, resp: Any) -> Dict[str, Any]:
OUTPUT_TOKENS_METRIC_KEY: completion_tokens,
TOTAL_TOKENS_METRIC_KEY: prompt_tokens + completion_tokens,
}
prompt_tokens = span.get_metric("openai.response.usage.prompt_tokens")
completion_tokens = span.get_metric("openai.response.usage.completion_tokens")
if prompt_tokens is None or completion_tokens is None:
return {}
return {
INPUT_TOKENS_METRIC_KEY: prompt_tokens,
OUTPUT_TOKENS_METRIC_KEY: completion_tokens,
TOTAL_TOKENS_METRIC_KEY: prompt_tokens + completion_tokens,
}
return get_llmobs_metrics_tags("openai", span)
30 changes: 30 additions & 0 deletions ddtrace/llmobs/_integrations/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from ddtrace.llmobs._constants import INPUT_TOKENS_METRIC_KEY
from ddtrace.llmobs._constants import OUTPUT_TOKENS_METRIC_KEY
from ddtrace.llmobs._constants import TOTAL_TOKENS_METRIC_KEY
from ddtrace.llmobs._constants import INTEGRATIONS_USING_INPUT_OUTPUT_TOKENS
from ddtrace.llmobs._utils import _get_attr


Expand Down Expand Up @@ -132,6 +133,35 @@ def get_llmobs_metrics_tags_google(integration_name, span):
usage[TOTAL_TOKENS_METRIC_KEY] = total_tokens
return usage

def get_llmobs_metrics_tags(integration_name, span):
usage = {}

# bedrock integration tags usage under meta instead of metrics
if integration_name == "bedrock":
input_tokens = int(span.get_tag("bedrock.usage.prompt_tokens") or 0)
output_tokens = int(span.get_tag("bedrock.usage.completion_tokens") or 0)
usage[INPUT_TOKENS_METRIC_KEY] = input_tokens
usage[OUTPUT_TOKENS_METRIC_KEY] = output_tokens
usage[TOTAL_TOKENS_METRIC_KEY] = input_tokens + output_tokens
return usage

prompt_tokens_name = "prompt_tokens"
completion_tokens_name = "completion_tokens"
if integration_name in INTEGRATIONS_USING_INPUT_OUTPUT_TOKENS:
prompt_tokens_name = "input_tokens"
completion_tokens_name = "output_tokens"
input_tokens = span.get_metric("%s.response.usage.%s" % (integration_name, prompt_tokens_name))
output_tokens = span.get_metric("%s.response.usage.%s" % (integration_name, completion_tokens_name))
total_tokens = span.get_metric("%s.response.usage.total_tokens" % integration_name)

if input_tokens is not None:
usage[INPUT_TOKENS_METRIC_KEY] = input_tokens
if output_tokens is not None:
usage[OUTPUT_TOKENS_METRIC_KEY] = output_tokens
if total_tokens is not None:
usage[TOTAL_TOKENS_METRIC_KEY] = total_tokens
return usage


def get_system_instructions_from_google_model(model_instance):
"""
Expand Down
4 changes: 2 additions & 2 deletions ddtrace/llmobs/_integrations/vertexai.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from ddtrace.llmobs._constants import SPAN_KIND
from ddtrace.llmobs._integrations.base import BaseLLMIntegration
from ddtrace.llmobs._integrations.utils import extract_message_from_part_google
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags_google
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags
from ddtrace.llmobs._integrations.utils import get_system_instructions_from_google_model
from ddtrace.llmobs._integrations.utils import llmobs_get_metadata_google
from ddtrace.llmobs._utils import _get_attr
Expand Down Expand Up @@ -60,7 +60,7 @@ def _llmobs_set_tags(
METADATA: metadata,
INPUT_MESSAGES: input_messages,
OUTPUT_MESSAGES: output_messages,
METRICS: get_llmobs_metrics_tags_google("vertexai", span),
METRICS: get_llmobs_metrics_tags("vertexai", span),
}
)

Expand Down

0 comments on commit 635935e

Please sign in to comment.