Skip to content

Commit 8b6937c

Browse files
committed
test: add callback handler unit coverage
1 parent 669ace4 commit 8b6937c

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass
4+
from typing import Any
5+
from uuid import uuid4
6+
7+
from opentelemetry.instrumentation.langchain.callback_handler import (
8+
OpenTelemetryLangChainCallbackHandler,
9+
)
10+
from opentelemetry.sdk.trace import TracerProvider
11+
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
12+
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
13+
InMemorySpanExporter,
14+
)
15+
from opentelemetry.semconv._incubating.attributes import (
16+
gen_ai_attributes as GenAI,
17+
)
18+
from opentelemetry.semconv._incubating.attributes.azure_attributes import (
19+
AZURE_RESOURCE_PROVIDER_NAMESPACE,
20+
)
21+
from opentelemetry.semconv._incubating.attributes.openai_attributes import (
22+
OPENAI_REQUEST_SERVICE_TIER,
23+
OPENAI_RESPONSE_SERVICE_TIER,
24+
OPENAI_RESPONSE_SYSTEM_FINGERPRINT,
25+
)
26+
27+
28+
def _create_handler():
29+
exporter = InMemorySpanExporter()
30+
provider = TracerProvider()
31+
provider.add_span_processor(SimpleSpanProcessor(exporter))
32+
handler = OpenTelemetryLangChainCallbackHandler(
33+
tracer=provider.get_tracer(__name__)
34+
)
35+
return handler, exporter
36+
37+
38+
def test_provider_and_server_metadata_extracted():
39+
handler, exporter = _create_handler()
40+
run_id = uuid4()
41+
42+
handler.on_chat_model_start(
43+
serialized={"name": "CustomLLM"},
44+
messages=[],
45+
run_id=run_id,
46+
tags=None,
47+
parent_run_id=None,
48+
metadata={
49+
"ls_provider": "azure",
50+
"ls_model_name": "gpt-4o",
51+
},
52+
invocation_params={
53+
"params": {
54+
"model": "gpt-4o",
55+
"base_url": "https://example.openai.azure.com/openai/deployments/demo",
56+
"n": 2,
57+
}
58+
},
59+
)
60+
61+
handler.span_manager.end_span(run_id)
62+
63+
span = exporter.get_finished_spans()[0]
64+
assert span.name == "chat gpt-4o"
65+
assert (
66+
span.attributes[GenAI.GEN_AI_PROVIDER_NAME] == "azure.ai.openai"
67+
)
68+
assert (
69+
span.attributes[AZURE_RESOURCE_PROVIDER_NAMESPACE]
70+
== "Microsoft.CognitiveServices"
71+
)
72+
assert span.attributes["server.address"] == "example.openai.azure.com"
73+
assert span.attributes["server.port"] == 443
74+
assert span.attributes[GenAI.GEN_AI_REQUEST_CHOICE_COUNT] == 2
75+
76+
77+
@dataclass
78+
class _DummyLLMResult:
79+
generations: list[Any]
80+
llm_output: dict[str, Any]
81+
82+
83+
def test_llm_end_sets_response_metadata():
84+
handler, exporter = _create_handler()
85+
run_id = uuid4()
86+
87+
handler.on_chat_model_start(
88+
serialized={"name": "ChatOpenAI"},
89+
messages=[],
90+
run_id=run_id,
91+
tags=None,
92+
parent_run_id=None,
93+
metadata={"ls_model_name": "gpt-4"},
94+
invocation_params={"params": {"model": "gpt-4"}},
95+
)
96+
97+
handler.on_llm_end(
98+
_DummyLLMResult(
99+
generations=[],
100+
llm_output={
101+
"model_name": "gpt-4-0125",
102+
"service_tier": "premium",
103+
"system_fingerprint": "fp-test",
104+
"id": "chatcmpl-test",
105+
},
106+
),
107+
run_id=run_id,
108+
parent_run_id=None,
109+
)
110+
111+
span = exporter.get_finished_spans()[0]
112+
assert span.attributes[GenAI.GEN_AI_RESPONSE_MODEL] == "gpt-4-0125"
113+
assert span.attributes[GenAI.GEN_AI_RESPONSE_ID] == "chatcmpl-test"
114+
assert span.attributes[OPENAI_RESPONSE_SERVICE_TIER] == "premium"
115+
assert (
116+
span.attributes[OPENAI_RESPONSE_SYSTEM_FINGERPRINT] == "fp-test"
117+
)
118+
119+
120+
def test_choice_count_not_set_when_one():
121+
handler, exporter = _create_handler()
122+
run_id = uuid4()
123+
124+
handler.on_chat_model_start(
125+
serialized={"name": "ChatOpenAI"},
126+
messages=[],
127+
run_id=run_id,
128+
tags=None,
129+
parent_run_id=None,
130+
metadata={"ls_model_name": "gpt-4"},
131+
invocation_params={
132+
"params": {
133+
"model": "gpt-4",
134+
"n": 1,
135+
}
136+
},
137+
)
138+
139+
handler.span_manager.end_span(run_id)
140+
span = exporter.get_finished_spans()[0]
141+
assert (
142+
GenAI.GEN_AI_REQUEST_CHOICE_COUNT not in span.attributes
143+
)

0 commit comments

Comments
 (0)