diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/684.added b/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/684.added new file mode 100644 index 000000000..6722344bb --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/684.added @@ -0,0 +1 @@ +Capture top_k - `gen_ai.request.top_k` and choice count - `gen_ai.request.choice.count` on chat diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index ceb4d387d..cdc4043f9 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -291,6 +291,8 @@ def on_chat_model_start( request_model = request_model.removeprefix("models/") # Initialize variables with default values to avoid "possibly unbound" errors + request_choice_count = None + top_k = None top_p = None frequency_penalty = None presence_penalty = None @@ -300,6 +302,8 @@ def on_chat_model_start( max_tokens = None if params is not None: + request_choice_count = params.get("n") + top_k = params.get("top_k") top_p = params.get("top_p") frequency_penalty = params.get("frequency_penalty") presence_penalty = params.get("presence_penalty") @@ -343,6 +347,8 @@ def on_chat_model_start( llm_invocation.conversation_id = _conversation_id(metadata) llm_invocation.input_messages = input_messages llm_invocation.top_p = top_p + llm_invocation.top_k = top_k + llm_invocation.request_choice_count = request_choice_count llm_invocation.frequency_penalty = frequency_penalty llm_invocation.presence_penalty = presence_penalty llm_invocation.stop_sequences = stop_sequences diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_callback_handler.py index c4c0632f0..4fd79a72a 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_callback_handler.py @@ -2799,6 +2799,42 @@ def test_on_chat_model_start_captures_input_messages_when_content_enabled(): assert blob.content == _REAL_PNG_BYTES +def test_on_chat_model_start_captures_top_k_and_choice_count(): + run_id = _run_id() + handler, _, llm_inv = _make_handler_with_llm_invocation(run_id) + + handler.on_chat_model_start( + serialized={}, + messages=[[HumanMessage(content="Hello")]], + run_id=run_id, + invocation_params={ + "params": { + "model_name": "gpt-4o", + "top_k": 40, + "n": 3, + } + }, + ) + + assert llm_inv.top_k == 40 + assert llm_inv.request_choice_count == 3 + + +def test_on_chat_model_start_defaults_top_k_and_choice_count_to_none(): + run_id = _run_id() + handler, _, llm_inv = _make_handler_with_llm_invocation(run_id) + + handler.on_chat_model_start( + serialized={}, + messages=[[HumanMessage(content="Hello")]], + run_id=run_id, + invocation_params={"model_name": "gpt-4o"}, + ) + + assert llm_inv.top_k is None + assert llm_inv.request_choice_count is None + + def test_on_chat_model_start_preserves_message_name(): run_id = _run_id() handler, telemetry, llm_inv = _make_handler_with_llm_invocation(run_id)