""" Utility functions for extracting model information from LangChain LLMs. This module provides utilities to extract provider and model information from LangChain language models for telemetry purposes. """ import importlib.metadata from typing import Any try: from langchain_core.language_models.base import BaseLanguageModel # type: ignore[import-untyped] except ImportError: BaseLanguageModel = None # type: ignore[misc, assignment] def get_package_version() -> str: """Get the current mcp-use package version.""" try: return importlib.metadata.version("mcp-use") except importlib.metadata.PackageNotFoundError: return "unknown" def get_model_provider(llm: Any) -> str: """Extract the model provider from LangChain LLM using BaseChatModel standards.""" if BaseLanguageModel is None: return getattr(llm, "__class__", type(llm)).__name__.lower() # Use LangChain's standard _llm_type property for identification return getattr(llm, "_llm_type", llm.__class__.__name__.lower()) def get_model_name(llm: Any) -> str: """Extract the model name from LangChain LLM using BaseChatModel standards.""" # First try _identifying_params which may contain model info if hasattr(llm, "_identifying_params"): identifying_params = llm._identifying_params if isinstance(identifying_params, dict): # Common keys that contain model names for key in ["model", "model_name", "model_id", "deployment_name"]: if key in identifying_params: return str(identifying_params[key]) # Fallback to direct model attributes return getattr(llm, "model", getattr(llm, "model_name", llm.__class__.__name__)) def extract_model_info(llm: Any) -> tuple[str, str]: """Extract both provider and model name from LangChain LLM. Returns: Tuple of (provider, model_name) """ return get_model_provider(llm), get_model_name(llm)