Skip to content

Commit d62338f

Browse files
CopilotnikhilNava
andcommitted
Security hardening for observability packages
Co-authored-by: nikhilNava <211831449+nikhilNava@users.noreply.github.com>
1 parent aa5acef commit d62338f

1 file changed

Lines changed: 41 additions & 46 deletions

File tree

  • libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain

libraries/microsoft-agents-a365-observability-extensions-langchain/microsoft_agents_a365/observability/extensions/langchain/utils.py

Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ def prompts(inputs: Mapping[str, Any] | None) -> Iterator[tuple[str, list[str]]]
5353
"""Yields prompts if present."""
5454
if not inputs:
5555
return
56-
if not hasattr(inputs, "get"):
57-
raise TypeError(f"expected Mapping, found {type(inputs)}")
56+
if not isinstance(inputs, Mapping):
57+
return
5858
if prompts := inputs.get("prompts"):
5959
yield GEN_AI_SYSTEM_INSTRUCTIONS_KEY, prompts
6060

@@ -63,22 +63,20 @@ def prompts(inputs: Mapping[str, Any] | None) -> Iterator[tuple[str, list[str]]]
6363
def _extract_message_kwargs(message_data: Mapping[str, Any] | None) -> Iterator[[str, Any]]:
6464
if not message_data:
6565
return
66-
if not hasattr(message_data, "get"):
67-
raise TypeError(f"expected Mapping, found {type(message_data)}")
66+
if not isinstance(message_data, Mapping):
67+
return
6868
if kwargs := message_data.get("kwargs"):
69-
if not hasattr(kwargs, "get"):
70-
raise TypeError(f"expected Mapping, found {type(kwargs)}")
69+
if not isinstance(kwargs, Mapping):
70+
return
7171
if content := kwargs.get("content"):
7272
# Just yield as-is (string or list)
7373
yield "message.content", content
7474
if tool_call_id := kwargs.get("tool_call_id"):
75-
if not isinstance(tool_call_id, str):
76-
raise TypeError(f"expected str, found {type(tool_call_id)}")
77-
yield GEN_AI_TOOL_CALL_ID_KEY, tool_call_id
75+
if isinstance(tool_call_id, str):
76+
yield GEN_AI_TOOL_CALL_ID_KEY, tool_call_id
7877
if name := kwargs.get("name"):
79-
if not isinstance(name, str):
80-
raise TypeError(f"expected str, found {type(name)}")
81-
yield "message.name", name
78+
if isinstance(name, str):
79+
yield "message.name", name
8280

8381

8482
@stop_on_exception
@@ -87,21 +85,20 @@ def _extract_message_additional_kwargs(
8785
) -> Iterator[tuple[str, Any]]:
8886
if not message_data:
8987
return
90-
if not hasattr(message_data, "get"):
91-
raise TypeError(f"expected Mapping, found {type(message_data)}")
88+
if not isinstance(message_data, Mapping):
89+
return
9290
if kwargs := message_data.get("kwargs"):
93-
if not hasattr(kwargs, "get"):
94-
raise TypeError(f"expected Mapping, found {type(kwargs)}")
91+
if not isinstance(kwargs, Mapping):
92+
return
9593
if additional_kwargs := kwargs.get("additional_kwargs"):
96-
if not hasattr(additional_kwargs, "get"):
97-
raise TypeError(f"expected Mapping, found {type(additional_kwargs)}")
94+
if not isinstance(additional_kwargs, Mapping):
95+
return
9896
if function_call := additional_kwargs.get("function_call"):
99-
if not hasattr(function_call, "get"):
100-
raise TypeError(f"expected Mapping, found {type(function_call)}")
97+
if not isinstance(function_call, Mapping):
98+
return
10199
if name := function_call.get("name"):
102-
if not isinstance(name, str):
103-
raise TypeError(f"expected str, found {type(name)}")
104-
yield GEN_AI_TOOL_NAME_KEY, name
100+
if isinstance(name, str):
101+
yield GEN_AI_TOOL_NAME_KEY, name
105102
if arguments := function_call.get("arguments"):
106103
if isinstance(arguments, str):
107104
yield GEN_AI_TOOL_ARGS_KEY, arguments
@@ -113,8 +110,8 @@ def _extract_message_additional_kwargs(
113110
def _get_tool_call(tool_call: Mapping[str, Any] | None) -> Iterator[tuple[str, Any]]:
114111
if not tool_call:
115112
return
116-
if not hasattr(tool_call, "get"):
117-
raise TypeError(f"expected Mapping, found {type(tool_call)}")
113+
if not isinstance(tool_call, Mapping):
114+
return
118115

119116
# id
120117
id_ = tool_call.get("id")
@@ -125,17 +122,15 @@ def _get_tool_call(tool_call: Mapping[str, Any] | None) -> Iterator[tuple[str, A
125122
name = None
126123
arguments = None
127124

128-
if hasattr(fn, "get"):
125+
if isinstance(fn, Mapping):
129126
name = fn.get("name")
130127
arguments = fn.get("arguments")
131128
else:
132129
name = tool_call.get("name")
133130
arguments = tool_call.get("args")
134131

135132
# name
136-
if name is not None:
137-
if not isinstance(name, str):
138-
raise TypeError(f"expected str, found {type(name)}")
133+
if name is not None and isinstance(name, str):
139134
yield GEN_AI_TOOL_NAME_KEY, name
140135

141136
# arguments -> always emit a JSON string
@@ -152,7 +147,7 @@ def _process_tool_calls(tool_calls: Any) -> str:
152147
if not tool_calls:
153148
return ""
154149
if not isinstance(tool_calls, Iterable):
155-
raise TypeError(f"expected Iterable, found {type(tool_calls)}")
150+
return ""
156151

157152
parts: list[str] = []
158153
for tool_call in tool_calls:
@@ -170,8 +165,8 @@ def _extract_message_tool_calls(
170165
) -> Iterator[tuple[str, str]]:
171166
if not message_data:
172167
return
173-
if not hasattr(message_data, "get"):
174-
raise TypeError(f"expected Mapping, found {type(message_data)}")
168+
if not isinstance(message_data, Mapping):
169+
return
175170

176171
# Collect tool_calls from multiple possible locations
177172
all_tool_calls: list[str] = []
@@ -188,13 +183,13 @@ def collect(calls: Any) -> None:
188183
collect(message_data.get("tool_calls"))
189184

190185
if kwargs := message_data.get("kwargs"):
191-
if not hasattr(kwargs, "get"):
192-
raise TypeError(f"expected Mapping, found {type(kwargs)}")
186+
if not isinstance(kwargs, Mapping):
187+
return
193188
collect(kwargs.get("tool_calls"))
194189

195190
if additional_kwargs := kwargs.get("additional_kwargs"):
196-
if not hasattr(additional_kwargs, "get"):
197-
raise TypeError(f"expected Mapping, found {type(additional_kwargs)}")
191+
if not isinstance(additional_kwargs, Mapping):
192+
return
198193
collect(additional_kwargs.get("tool_calls"))
199194

200195
if all_tool_calls:
@@ -217,13 +212,13 @@ def input_messages(
217212
"""Yields chat messages as a JSON array of content strings."""
218213
if not inputs:
219214
return
220-
if not hasattr(inputs, "get"):
221-
raise TypeError(f"expected Mapping, found {type(inputs)}")
215+
if not isinstance(inputs, Mapping):
216+
return
222217
# There may be more than one set of messages. We'll use just the first set.
223218
if not (multiple_messages := inputs.get("messages")):
224219
return
225220
if not isinstance(multiple_messages, Iterable):
226-
raise TypeError(f"expected Iterable, found {type(multiple_messages)}")
221+
return
227222
# This will only get the first set of messages.
228223
if not (first_messages := next(iter(multiple_messages), None)):
229224
return
@@ -260,7 +255,7 @@ def metadata(run: Run) -> Iterator[tuple[str, str]]:
260255
if not run.extra or not (metadata := run.extra.get("metadata")):
261256
return
262257
if not isinstance(metadata, Mapping):
263-
raise TypeError(f"expected Mapping, found {type(metadata)}")
258+
return
264259
if session_id := (
265260
metadata.get(LANGCHAIN_SESSION_ID)
266261
or metadata.get(LANGCHAIN_CONVERSATION_ID)
@@ -276,8 +271,8 @@ def output_messages(
276271
"""Yields chat messages as a JSON array of content strings."""
277272
if not outputs:
278273
return
279-
if not hasattr(outputs, "get"):
280-
raise TypeError(f"expected Mapping, found {type(outputs)}")
274+
if not isinstance(outputs, Mapping):
275+
return
281276
output_type = outputs.get("type")
282277
if output_type and output_type.lower() == "llmresult":
283278
llm_output = outputs.get("llm_output")
@@ -289,16 +284,16 @@ def output_messages(
289284
if not (multiple_generations := outputs.get("generations")):
290285
return
291286
if not isinstance(multiple_generations, Iterable):
292-
raise TypeError(f"expected Iterable, found {type(multiple_generations)}")
287+
return
293288
# This will only get the first set of generations.
294289
if not (first_generations := next(iter(multiple_generations), None)):
295290
return
296291
if not isinstance(first_generations, Iterable):
297-
raise TypeError(f"expected Iterable, found {type(first_generations)}")
292+
return
298293
contents: list[str] = []
299294
for generation in first_generations:
300-
if not hasattr(generation, "get"):
301-
raise TypeError(f"expected Mapping, found {type(generation)}")
295+
if not isinstance(generation, Mapping):
296+
continue
302297
if message_data := generation.get("message"):
303298
if isinstance(message_data, BaseMessage):
304299
if hasattr(message_data, "content") and message_data.content:

0 commit comments

Comments
 (0)