Check if any LLM spans are present in the trace. Args: spans: List of span dictionaries Returns: Tuple of (has_llm_spans, llm_span_names)
(spans: List[Dict[str, Any]])
| 155 | |
| 156 | |
| 157 | def check_llm_spans(spans: List[Dict[str, Any]]) -> Tuple[bool, List[str]]: |
| 158 | """ |
| 159 | Check if any LLM spans are present in the trace. |
| 160 | |
| 161 | Args: |
| 162 | spans: List of span dictionaries |
| 163 | |
| 164 | Returns: |
| 165 | Tuple of (has_llm_spans, llm_span_names) |
| 166 | """ |
| 167 | llm_spans = [] |
| 168 | |
| 169 | for span in spans: |
| 170 | span_name = span.get("span_name", "unnamed_span") |
| 171 | span_attributes = span.get("span_attributes", {}) |
| 172 | is_llm_span = False |
| 173 | |
| 174 | if span_attributes: |
| 175 | # Check for LLM span kind - handle both flat and nested structures |
| 176 | span_kind = span_attributes.get("agentops.span.kind", "") |
| 177 | if not span_kind: |
| 178 | # Check nested structure: agentops.span.kind or agentops -> span -> kind |
| 179 | agentops_attrs = span_attributes.get("agentops", {}) |
| 180 | if isinstance(agentops_attrs, dict): |
| 181 | span_attrs = agentops_attrs.get("span", {}) |
| 182 | if isinstance(span_attrs, dict): |
| 183 | span_kind = span_attrs.get("kind", "") |
| 184 | |
| 185 | is_llm_span = span_kind == "llm" |
| 186 | |
| 187 | # Alternative check: Look for gen_ai attributes |
| 188 | if not is_llm_span: |
| 189 | gen_ai_attrs = span_attributes.get("gen_ai", {}) |
| 190 | if isinstance(gen_ai_attrs, dict): |
| 191 | if "prompt" in gen_ai_attrs or "completion" in gen_ai_attrs: |
| 192 | is_llm_span = True |
| 193 | |
| 194 | # Check for LLM request type |
| 195 | if not is_llm_span: |
| 196 | llm_request_type = span_attributes.get("gen_ai.request.type", "") |
| 197 | if not llm_request_type: |
| 198 | # Also check for older llm.request.type format |
| 199 | llm_request_type = span_attributes.get("llm.request.type", "") |
| 200 | if llm_request_type in ["chat", "completion"]: |
| 201 | is_llm_span = True |
| 202 | |
| 203 | if is_llm_span: |
| 204 | llm_spans.append(span_name) |
| 205 | |
| 206 | return len(llm_spans) > 0, llm_spans |
| 207 | |
| 208 | |
| 209 | def validate_trace_spans( |
searching dependent graphs…