diff --git a/python/langsmith/async_client.py b/python/langsmith/async_client.py index 1dc6f7119..b65d77637 100644 --- a/python/langsmith/async_client.py +++ b/python/langsmith/async_client.py @@ -52,8 +52,10 @@ def __init__( "Content-Type": "application/json", } api_key = ls_utils.get_api_key(api_key) + api_url = ls_utils.get_api_url(api_url) if api_key: _headers[ls_client.X_API_KEY] = api_key + ls_client._validate_api_key_if_hosted(api_url, api_key) if isinstance(timeout_ms, int): timeout_: Union[Tuple, float] = (timeout_ms / 1000, None, None, None) @@ -62,7 +64,7 @@ def __init__( else: timeout_ = 10 self._client = httpx.AsyncClient( - base_url=ls_utils.get_api_url(api_url), headers=_headers, timeout=timeout_ + base_url=api_url, headers=_headers, timeout=timeout_ ) async def __aenter__(self) -> "AsyncClient": diff --git a/python/langsmith/client.py b/python/langsmith/client.py index 3d6e7f134..d91036522 100644 --- a/python/langsmith/client.py +++ b/python/langsmith/client.py @@ -330,8 +330,9 @@ def _validate_api_key_if_hosted(api_url: str, api_key: Optional[str]) -> None: # If the domain is langchain.com, raise error if no api_key if not api_key: if _is_langchain_hosted(api_url): - raise ls_utils.LangSmithUserError( - "API key must be provided when using hosted LangSmith API" + warnings.warn( + "API key must be provided when using hosted LangSmith API", + ls_utils.LangSmithMissingAPIKeyWarning, ) diff --git a/python/langsmith/utils.py b/python/langsmith/utils.py index c28b23c38..8fce4106d 100644 --- a/python/langsmith/utils.py +++ b/python/langsmith/utils.py @@ -74,6 +74,17 @@ class LangSmithConnectionError(LangSmithError): """Couldn't connect to the LangSmith API.""" +## Warning classes + + +class LangSmithWarning(UserWarning): + """Base class for warnings.""" + + +class LangSmithMissingAPIKeyWarning(LangSmithWarning): + """Warning for missing API key.""" + + def tracing_is_enabled(ctx: Optional[dict] = None) -> bool: """Return True if tracing is enabled.""" from langsmith.run_helpers import get_current_run_tree, get_tracing_context diff --git a/python/pyproject.toml b/python/pyproject.toml index ff36e6f2b..fd0149ae8 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langsmith" -version = "0.1.105" +version = "0.1.106" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." authors = ["LangChain "] license = "MIT" diff --git a/python/tests/unit_tests/test_client.py b/python/tests/unit_tests/test_client.py index ed8159804..24a066fe0 100644 --- a/python/tests/unit_tests/test_client.py +++ b/python/tests/unit_tests/test_client.py @@ -10,11 +10,12 @@ import threading import time import uuid +import warnings import weakref from datetime import datetime, timezone from enum import Enum from io import BytesIO -from typing import Any, NamedTuple, Optional +from typing import Any, NamedTuple, Optional, Type, Union from unittest import mock from unittest.mock import MagicMock, patch @@ -28,7 +29,7 @@ import langsmith.env as ls_env import langsmith.utils as ls_utils -from langsmith import EvaluationResult, run_trees +from langsmith import AsyncClient, EvaluationResult, run_trees from langsmith import schemas as ls_schemas from langsmith.client import ( Client, @@ -54,16 +55,6 @@ def test__is_langchain_hosted() -> None: assert _is_langchain_hosted("https://dev.api.smith.langchain.com") -def test_validate_api_key_if_hosted(monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.delenv("LANGCHAIN_API_KEY", raising=False) - monkeypatch.delenv("LANGSMITH_API_KEY", raising=False) - with pytest.raises(ls_utils.LangSmithUserError, match="API key must be provided"): - Client(api_url="https://api.smith.langchain.com") - client = Client(api_url="http://localhost:1984") - assert client.api_url == "http://localhost:1984" - assert client.api_key is None - - def test_validate_api_url(monkeypatch: pytest.MonkeyPatch) -> None: # Scenario 1: Both LANGCHAIN_ENDPOINT and LANGSMITH_ENDPOINT # are set, but api_url is not @@ -1080,3 +1071,17 @@ def test_select_eval_results(): assert client._select_eval_results(input_) == [ expected2, ] + + +@pytest.mark.parametrize("client_cls", [Client, AsyncClient]) +def test_validate_api_key_if_hosted( + monkeypatch: pytest.MonkeyPatch, client_cls: Union[Type[Client], Type[AsyncClient]] +) -> None: + monkeypatch.delenv("LANGCHAIN_API_KEY", raising=False) + monkeypatch.delenv("LANGSMITH_API_KEY", raising=False) + with pytest.warns(ls_utils.LangSmithMissingAPIKeyWarning): + client_cls(api_url="https://api.smith.langchain.com") + with warnings.catch_warnings(): + # Check no warning is raised here. + warnings.simplefilter("error") + client_cls(api_url="http://localhost:1984")