weave.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. """Integration module for automatic Weave initialization with W&B.
  2. This module provides automatic initialization of Weave when:
  3. 1. Weave is installed
  4. 2. A W&B run is active with a project
  5. 3. Weave is imported (init-on-import)
  6. The integration can be disabled by setting the WANDB_DISABLE_WEAVE environment variable.
  7. """
  8. from __future__ import annotations
  9. import importlib.util
  10. import os
  11. import sys
  12. import threading
  13. import wandb
  14. _weave_init_lock = threading.Lock()
  15. _DISABLE_WEAVE = "WANDB_DISABLE_WEAVE"
  16. _WEAVE_PACKAGE_NAME = "weave"
  17. # This list is adapted from https://github.com/wandb/weave/blob/master/weave/integrations/__init__.py
  18. _AVAILABLE_WEAVE_INTEGRATIONS = [
  19. "anthropic",
  20. "autogen",
  21. "cohere",
  22. "crewai",
  23. "dspy",
  24. "google.genai",
  25. "groq",
  26. "huggingface_hub.inference",
  27. "instructor",
  28. "langchain",
  29. "litellm",
  30. "llama_index",
  31. "mcp",
  32. "mistral",
  33. "notdiamond",
  34. "openai",
  35. "agents",
  36. "smolagents",
  37. "verdict",
  38. "verifiers",
  39. "vertexai",
  40. ]
  41. def setup(entity: str | None, project: str | None) -> None:
  42. """Set up automatic Weave initialization for the current W&B run.
  43. Args:
  44. project: The W&B project name to use for Weave initialization.
  45. """
  46. # We can't or shouldn't init weave; return
  47. if os.getenv(_DISABLE_WEAVE):
  48. return
  49. if not project:
  50. return
  51. # Use entity/project when available; otherwise fall back to project only
  52. if entity:
  53. project_path = f"{entity}/{project}"
  54. else:
  55. project_path = project
  56. # If weave is not yet imported, we can't init it from here. Instead, we'll
  57. # rely on the weave library itself to detect a run and init itself.
  58. if _WEAVE_PACKAGE_NAME not in sys.modules:
  59. _maybe_suggest_weave_installation()
  60. return
  61. # If weave has already been imported, initialize immediately
  62. wandb.termlog("Initializing weave.")
  63. try:
  64. _weave_init(project_path)
  65. except Exception as e:
  66. wandb.termwarn(f"Failed to automatically initialize weave: {e}")
  67. def _maybe_suggest_weave_installation() -> None:
  68. """Suggest Weave installation or import if any target library is imported."""
  69. imported_libs = [lib for lib in _AVAILABLE_WEAVE_INTEGRATIONS if lib in sys.modules]
  70. if not imported_libs:
  71. return
  72. weave_spec = importlib.util.find_spec(_WEAVE_PACKAGE_NAME)
  73. if weave_spec is None:
  74. # Weave is not installed
  75. msg = (
  76. "Use W&B Weave for improved LLM call tracing. Install Weave with "
  77. "`pip install weave` then add `import weave` to the top of your script."
  78. )
  79. else:
  80. # Weave is installed but not imported
  81. msg = (
  82. "Use W&B Weave for improved LLM call tracing. Weave is installed "
  83. "but not imported. Add `import weave` to the top of your script."
  84. )
  85. wandb.termlog(f"Detected [{', '.join(imported_libs)}] in use.", repeat=False)
  86. wandb.termlog(msg, repeat=False)
  87. wandb.termlog(
  88. "For more information, check out the docs at: https://weave-docs.wandb.ai",
  89. repeat=False,
  90. )
  91. def _weave_init(project_path: str) -> None:
  92. """Call weave.init(), assuming weave has been imported.
  93. Patched in tests.
  94. """
  95. # Lock because weave.init() is not thread-safe.
  96. with _weave_init_lock:
  97. # The import is fast because weave should have been imported.
  98. import weave
  99. weave.init(project_path)