fix: exit the goose and show the error message when provider environment variable is not set (#103)

This commit is contained in:
Lifei Zhou
2024-10-04 11:17:29 +10:00
committed by GitHub
parent 9e35c6370e
commit 908af7f157
26 changed files with 345 additions and 86 deletions
@@ -6,6 +6,7 @@ import pytest
from exchange import Message, Text
from exchange.content import ToolResult, ToolUse
from exchange.providers.anthropic import AnthropicProvider
from exchange.providers.base import MissingProviderEnvVariableError
from exchange.tool import Tool
@@ -25,6 +26,15 @@ def anthropic_provider():
return AnthropicProvider.from_env()
def test_from_env_throw_error_when_missing_api_key():
with patch.dict(os.environ, {}, clear=True):
with pytest.raises(MissingProviderEnvVariableError) as context:
AnthropicProvider.from_env()
assert context.value.provider == "anthropic"
assert context.value.env_variable == "ANTHROPIC_API_KEY"
assert context.value.message == "Missing environment variable: ANTHROPIC_API_KEY for provider anthropic."
def test_anthropic_response_to_text_message() -> None:
response = {
"content": [{"type": "text", "text": "Hello from Claude!"}],
@@ -1,14 +1,44 @@
import os
from unittest.mock import patch
import pytest
from exchange import Text, ToolUse
from exchange.providers.azure import AzureProvider
from exchange.providers.base import MissingProviderEnvVariableError
from .conftest import complete, tools
AZURE_MODEL = os.getenv("AZURE_MODEL", "gpt-4o-mini")
@pytest.mark.parametrize(
"env_var_name",
[
("AZURE_CHAT_COMPLETIONS_HOST_NAME"),
("AZURE_CHAT_COMPLETIONS_DEPLOYMENT_NAME"),
("AZURE_CHAT_COMPLETIONS_DEPLOYMENT_API_VERSION"),
("AZURE_CHAT_COMPLETIONS_KEY"),
],
)
def test_from_env_throw_error_when_missing_env_var(env_var_name):
with patch.dict(
os.environ,
{
"AZURE_CHAT_COMPLETIONS_HOST_NAME": "test_host_name",
"AZURE_CHAT_COMPLETIONS_DEPLOYMENT_NAME": "test_deployment_name",
"AZURE_CHAT_COMPLETIONS_DEPLOYMENT_API_VERSION": "test_api_version",
"AZURE_CHAT_COMPLETIONS_KEY": "test_api_key",
},
clear=True,
):
os.environ.pop(env_var_name)
with pytest.raises(MissingProviderEnvVariableError) as context:
AzureProvider.from_env()
assert context.value.provider == "azure"
assert context.value.env_variable == env_var_name
assert context.value.message == f"Missing environment variable: {env_var_name} for provider azure."
@pytest.mark.vcr()
def test_azure_complete(default_azure_env):
reply_message, reply_usage = complete(AzureProvider, AZURE_MODEL)
@@ -5,12 +5,39 @@ from unittest.mock import patch
import pytest
from exchange.content import Text, ToolResult, ToolUse
from exchange.message import Message
from exchange.providers.base import MissingProviderEnvVariableError
from exchange.providers.bedrock import BedrockProvider
from exchange.tool import Tool
logger = logging.getLogger(__name__)
@pytest.mark.parametrize(
"env_var_name",
[
("AWS_ACCESS_KEY_ID"),
("AWS_SECRET_ACCESS_KEY"),
("AWS_SESSION_TOKEN"),
],
)
def test_from_env_throw_error_when_missing_env_var(env_var_name):
with patch.dict(
os.environ,
{
"AWS_ACCESS_KEY_ID": "test_access_key_id",
"AWS_SECRET_ACCESS_KEY": "test_secret_access_key",
"AWS_SESSION_TOKEN": "test_session_token",
},
clear=True,
):
os.environ.pop(env_var_name)
with pytest.raises(MissingProviderEnvVariableError) as context:
BedrockProvider.from_env()
assert context.value.provider == "bedrock"
assert context.value.env_variable == env_var_name
assert context.value.message == f"Missing environment variable: {env_var_name} for provider bedrock."
@pytest.fixture
@patch.dict(
os.environ,
@@ -3,9 +3,35 @@ from unittest.mock import patch
import pytest
from exchange import Message, Text
from exchange.providers.base import MissingProviderEnvVariableError
from exchange.providers.databricks import DatabricksProvider
@pytest.mark.parametrize(
"env_var_name",
[
("DATABRICKS_HOST"),
("DATABRICKS_TOKEN"),
],
)
def test_from_env_throw_error_when_missing_env_var(env_var_name):
with patch.dict(
os.environ,
{
"DATABRICKS_HOST": "test_host",
"DATABRICKS_TOKEN": "test_token",
},
clear=True,
):
os.environ.pop(env_var_name)
with pytest.raises(MissingProviderEnvVariableError) as context:
DatabricksProvider.from_env()
assert context.value.provider == "databricks"
assert context.value.env_variable == env_var_name
assert f"Missing environment variable: {env_var_name} for provider databricks" in context.value.message
assert "https://docs.databricks.com" in context.value.message
@pytest.fixture
@patch.dict(
os.environ,
@@ -5,6 +5,7 @@ import httpx
import pytest
from exchange import Message, Text
from exchange.content import ToolResult, ToolUse
from exchange.providers.base import MissingProviderEnvVariableError
from exchange.providers.google import GoogleProvider
from exchange.tool import Tool
@@ -19,6 +20,16 @@ def example_fn(param: str) -> None:
pass
def test_from_env_throw_error_when_missing_api_key():
with patch.dict(os.environ, {}, clear=True):
with pytest.raises(MissingProviderEnvVariableError) as context:
GoogleProvider.from_env()
assert context.value.provider == "google"
assert context.value.env_variable == "GOOGLE_API_KEY"
assert "Missing environment variable: GOOGLE_API_KEY for provider google" in context.value.message
assert "https://ai.google.dev/gemini-api/docs/api-key" in context.value.message
@pytest.fixture
@patch.dict(os.environ, {"GOOGLE_API_KEY": "test_api_key"})
def google_provider():
@@ -1,14 +1,26 @@
import os
from unittest.mock import patch
import pytest
from exchange import Text, ToolUse
from exchange.providers.base import MissingProviderEnvVariableError
from exchange.providers.openai import OpenAiProvider
from .conftest import complete, vision, tools
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
def test_from_env_throw_error_when_missing_api_key():
with patch.dict(os.environ, {}, clear=True):
with pytest.raises(MissingProviderEnvVariableError) as context:
OpenAiProvider.from_env()
assert context.value.provider == "openai"
assert context.value.env_variable == "OPENAI_API_KEY"
assert "Missing environment variable: OPENAI_API_KEY for provider openai" in context.value.message
assert "https://platform.openai.com" in context.value.message
@pytest.mark.vcr()
def test_openai_complete(default_openai_env):
reply_message, reply_usage = complete(OpenAiProvider, OPENAI_MODEL)
@@ -0,0 +1,18 @@
import pytest
from exchange.invalid_choice_error import InvalidChoiceError
from exchange.providers import get_provider
def test_get_provider_valid():
provider_name = "openai"
provider = get_provider(provider_name)
assert provider.__name__ == "OpenAiProvider"
def test_get_provider_throw_error_for_unknown_provider():
with pytest.raises(InvalidChoiceError) as error:
get_provider("nonexistent")
assert error.value.attribute_name == "provider"
assert error.value.attribute_value == "nonexistent"
assert "openai" in error.value.available_values
assert "openai" in error.value.message
+27
View File
@@ -0,0 +1,27 @@
from exchange.providers.base import MissingProviderEnvVariableError
def test_missing_provider_env_variable_error_without_instructions_url():
env_variable = "API_KEY"
provider = "TestProvider"
error = MissingProviderEnvVariableError(env_variable, provider)
assert error.env_variable == env_variable
assert error.provider == provider
assert error.instructions_url is None
assert error.message == "Missing environment variable: API_KEY for provider TestProvider."
def test_missing_provider_env_variable_error_with_instructions_url():
env_variable = "API_KEY"
provider = "TestProvider"
instructions_url = "http://example.com/instructions"
error = MissingProviderEnvVariableError(env_variable, provider, instructions_url)
assert error.env_variable == env_variable
assert error.provider == provider
assert error.instructions_url == instructions_url
assert error.message == (
"Missing environment variable: API_KEY for provider TestProvider.\n"
"Please see http://example.com/instructions for instructions"
)
@@ -0,0 +1,13 @@
from exchange.invalid_choice_error import InvalidChoiceError
def test_load_invalid_choice_error():
attribute_name = "moderator"
attribute_value = "not_exist"
available_values = ["truncate", "summarizer"]
error = InvalidChoiceError(attribute_name, attribute_value, available_values)
assert error.attribute_name == attribute_name
assert error.attribute_value == attribute_value
assert error.attribute_value == attribute_value
assert error.message == "Unknown moderator: not_exist. Available moderators: truncate, summarizer"
@@ -0,0 +1,17 @@
from exchange.invalid_choice_error import InvalidChoiceError
from exchange.moderators import get_moderator
import pytest
def test_get_moderator():
moderator = get_moderator("truncate")
assert moderator.__name__ == "ContextTruncate"
def test_get_moderator_raise_error_for_unknown_moderator():
with pytest.raises(InvalidChoiceError) as error:
get_moderator("nonexistent")
assert error.value.attribute_name == "moderator"
assert error.value.attribute_value == "nonexistent"
assert "truncate" in error.value.available_values
assert "truncate" in error.value.message