Skip to content

Commit 4bd72aa

Browse files
committed
WIP gen_ai chat refactor
1 parent fd41dfb commit 4bd72aa

File tree

5 files changed

+58
-9
lines changed

5 files changed

+58
-9
lines changed

util/opentelemetry-util-genai/README.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,24 @@ The GenAI Utils package will include boilerplate and helpers to standardize inst
66
This package will provide APIs and decorators to minimize the work needed to instrument genai libraries,
77
while providing standardization for generating both types of otel, "spans and metrics" and "spans, metrics and events"
88

9+
This package provides these span attributes.
10+
-> gen_ai.operation.name: Str(chat)
11+
-> gen_ai.system: Str(ChatOpenAI)
12+
-> gen_ai.request.model: Str(gpt-3.5-turbo)
13+
-> gen_ai.request.top_p: Double(0.9)
14+
-> gen_ai.request.frequency_penalty: Double(0.5)
15+
-> gen_ai.request.presence_penalty: Double(0.5)
16+
-> gen_ai.request.stop_sequences: Slice(["\n","Human:","AI:"])
17+
-> gen_ai.request.seed: Int(100)
18+
-> gen_ai.request.max_tokens: Int(100)
19+
-> gen_ai.provider.name: Str(openai)
20+
-> gen_ai.request.temperature: Double(0.1)
21+
-> gen_ai.response.finish_reasons: Slice(["stop"])
22+
-> gen_ai.response.model: Str(gpt-3.5-turbo-0125)
23+
-> gen_ai.response.id: Str(chatcmpl-Bz8yrvPnydD9pObv625n2CGBPHS13)
24+
-> gen_ai.usage.input_tokens: Int(24)
25+
-> gen_ai.usage.output_tokens: Int(7)
26+
927
Installation
1028
------------
1129

util/opentelemetry-util-genai/src/opentelemetry/util/genai/client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,23 @@ def __init__(self, emitter_type_full: bool = True, **kwargs):
4242
__name__,
4343
__version__,
4444
tracer_provider,
45-
schema_url=Schemas.V1_28_0.value,
45+
schema_url=Schemas.V1_36_0.value,
4646
)
4747

4848
meter_provider = kwargs.get("meter_provider")
4949
self._meter = get_meter(
5050
__name__,
5151
__version__,
5252
meter_provider,
53-
schema_url=Schemas.V1_28_0.value,
53+
schema_url=Schemas.V1_36_0.value,
5454
)
5555

5656
event_logger_provider = kwargs.get("event_logger_provider")
5757
self._event_logger = get_event_logger(
5858
__name__,
5959
__version__,
6060
event_logger_provider=event_logger_provider,
61-
schema_url=Schemas.V1_28_0.value,
61+
schema_url=Schemas.V1_36_0.value,
6262
)
6363

6464
self._emitter = (

util/opentelemetry-util-genai/src/opentelemetry/util/genai/data.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ class Message:
77
type: str
88
name: str
99

10+
def _to_part_dict(self):
11+
"""Convert the message to a dictionary suitable for OpenTelemetry semconvs.
12+
13+
Ref: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/registry/attributes/gen-ai.md#gen-ai-input-messages
14+
"""
15+
16+
# Support tool_call and tool_call response
17+
return {
18+
"role": self.type,
19+
"parts": [
20+
{
21+
"content": self.content,
22+
"type": "text",
23+
}
24+
],
25+
}
26+
1027

1128
@dataclass
1229
class ChatGeneration:

util/opentelemetry-util-genai/src/opentelemetry/util/genai/emitters.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
use_span,
3535
)
3636
from opentelemetry.trace.status import Status, StatusCode
37+
from opentelemetry.util.types import Attributes
3738

3839
from .data import Error
3940
from .instruments import Instruments
@@ -59,8 +60,11 @@ def _get_property_value(obj, property_name) -> object:
5960

6061

6162
def _message_to_event(message, system, framework) -> Optional[Event]:
63+
# TODO: Convert to logs.
6264
content = _get_property_value(message, "content")
6365
if content:
66+
# update this to event.gen_ai.client.inference.operation.details: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-events.md
67+
6468
message_type = _get_property_value(message, "type")
6569
message_type = "user" if message_type == "human" else message_type
6670
body = {"content": content}
@@ -80,6 +84,7 @@ def _message_to_event(message, system, framework) -> Optional[Event]:
8084
def _chat_generation_to_event(
8185
chat_generation, index, system, framework
8286
) -> Optional[Event]:
87+
# TODO: Convert to logs.
8388
if chat_generation.content:
8489
attributes = {
8590
# TODO: add below to opentelemetry.semconv._incubating.attributes.gen_ai_attributes
@@ -478,14 +483,23 @@ def emit(self, invocation: LLMInvocation):
478483
GenAI.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens
479484
)
480485

486+
message_parts: List[Attributes] = []
481487
for index, message in enumerate(invocation.messages):
482-
content = message.content
483-
span.set_attribute(f"gen_ai.prompt.{index}.content", content)
484-
span.set_attribute(f"gen_ai.prompt.{index}.role", message.type)
488+
message_parts.append(message._to_part_dict())
489+
490+
if len(message_parts) > 0:
491+
span.set_attribute("gen_ai.input.messages", message_parts)
492+
493+
# for index, message in enumerate(invocation.messages):
494+
# content = message.content
495+
# # Set these attributes to upcoming semconv: https://github.com/open-telemetry/semantic-conventions/pull/2179
496+
# span.set_attribute(f"gen_ai.input.messages.{index}.content", [content._to_part_dict()])
497+
# span.set_attribute(f"gen_ai.input.messages.{index}.role", message.type)
485498

486499
for index, chat_generation in enumerate(
487500
invocation.chat_generations
488501
):
502+
# Set these attributes to upcoming semconv: https://github.com/open-telemetry/semantic-conventions/pull/2179
489503
span.set_attribute(
490504
f"gen_ai.completion.{index}.content",
491505
chat_generation.content,

util/opentelemetry-util-genai/src/opentelemetry/util/genai/types.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import time
1616
from dataclasses import dataclass, field
17-
from typing import List, Optional
17+
from typing import Any, Dict, List, Optional
1818
from uuid import UUID
1919

2020
from .data import ChatGeneration, Message
@@ -29,9 +29,9 @@ class LLMInvocation:
2929
run_id: UUID
3030
parent_run_id: Optional[UUID] = None
3131
start_time: float = field(default_factory=time.time)
32-
end_time: float = None
32+
end_time: Optional[float] = None
3333
messages: List[Message] = field(default_factory=list)
3434
chat_generations: List[ChatGeneration] = field(default_factory=list)
35-
attributes: dict = field(default_factory=dict)
35+
attributes: Dict[str, Any] = field(default_factory=dict)
3636
span_id: int = 0
3737
trace_id: int = 0

0 commit comments

Comments
 (0)