From 0c723c9e56495a537806d46bb46feaff31837b91 Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Wed, 7 May 2025 18:24:53 +0100 Subject: [PATCH 1/8] Add support for nscale provider --- litellm/__init__.py | 1 + litellm/constants.py | 3 + .../get_llm_provider_logic.py | 10 ++ .../get_supported_openai_params.py | 2 + litellm/llms/nscale/chat/transformation.py | 44 +++++ ...odel_prices_and_context_window_backup.json | 169 ++++++++++++++++++ litellm/types/utils.py | 1 + litellm/utils.py | 2 + model_prices_and_context_window.json | 169 ++++++++++++++++++ 9 files changed, 401 insertions(+) create mode 100644 litellm/llms/nscale/chat/transformation.py diff --git a/litellm/__init__.py b/litellm/__init__.py index a08230c6ed85..aea62a79b0a2 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -1032,6 +1032,7 @@ def add_known_models(): from .llms.deepseek.chat.transformation import DeepSeekChatConfig from .llms.lm_studio.chat.transformation import LMStudioChatConfig from .llms.lm_studio.embed.transformation import LmStudioEmbeddingConfig +from .llms.nscale.chat.transformation import NscaleConfig from .llms.perplexity.chat.transformation import PerplexityChatConfig from .llms.azure.chat.o_series_transformation import AzureOpenAIO1Config from .llms.watsonx.completion.transformation import IBMWatsonXAIConfig diff --git a/litellm/constants.py b/litellm/constants.py index fa944c0dfaa1..329118c3024d 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -162,6 +162,7 @@ "lm_studio", "galadriel", "meta_llama", + "nscale", ] @@ -223,6 +224,7 @@ "api.x.ai/v1", "api.galadriel.ai/v1", "api.llama.com/compat/v1/", + "inference.api.nscale.com/v1", ] @@ -254,6 +256,7 @@ "lm_studio", "galadriel", "meta_llama", + "nscale", ] openai_text_completion_compatible_providers: List = ( [ # providers that support `/v1/completions` diff --git a/litellm/litellm_core_utils/get_llm_provider_logic.py b/litellm/litellm_core_utils/get_llm_provider_logic.py index bdfe0e902523..29f6b2d3f6ce 100644 --- a/litellm/litellm_core_utils/get_llm_provider_logic.py +++ b/litellm/litellm_core_utils/get_llm_provider_logic.py @@ -218,6 +218,9 @@ def get_llm_provider( # noqa: PLR0915 elif endpoint == "https://api.llama.com/compat/v1": custom_llm_provider = "meta_llama" dynamic_api_key = api_key or get_secret_str("LLAMA_API_KEY") + elif endpoint == litellm.NscaleConfig.API_BASE_URL: + custom_llm_provider = "nscale" + dynamic_api_key = litellm.NscaleConfig.get_api_key() if api_base is not None and not isinstance(api_base, str): raise Exception( @@ -597,6 +600,13 @@ def _get_openai_compatible_provider_info( # noqa: PLR0915 or f"https://{get_secret('SNOWFLAKE_ACCOUNT_ID')}.snowflakecomputing.com/api/v2/cortex/inference:complete" ) # type: ignore dynamic_api_key = api_key or get_secret_str("SNOWFLAKE_JWT") + elif custom_llm_provider == "nscale": + ( + api_base, + dynamic_api_key, + ) = litellm.NscaleConfig()._get_openai_compatible_provider_info( + api_base=api_base, api_key=api_key + ) if api_base is not None and not isinstance(api_base, str): raise Exception("api base needs to be a string. api_base={}".format(api_base)) diff --git a/litellm/litellm_core_utils/get_supported_openai_params.py b/litellm/litellm_core_utils/get_supported_openai_params.py index 2cb8daa4c57f..11981e627bab 100644 --- a/litellm/litellm_core_utils/get_supported_openai_params.py +++ b/litellm/litellm_core_utils/get_supported_openai_params.py @@ -202,6 +202,8 @@ def get_supported_openai_params( # noqa: PLR0915 return litellm.DeepInfraConfig().get_supported_openai_params(model=model) elif custom_llm_provider == "perplexity": return litellm.PerplexityChatConfig().get_supported_openai_params(model=model) + elif custom_llm_provider == "nscale": + return litellm.NscaleConfig().get_supported_openai_params(model=model) elif custom_llm_provider == "anyscale": return [ "temperature", diff --git a/litellm/llms/nscale/chat/transformation.py b/litellm/llms/nscale/chat/transformation.py new file mode 100644 index 000000000000..4fb9c213fde0 --- /dev/null +++ b/litellm/llms/nscale/chat/transformation.py @@ -0,0 +1,44 @@ +from typing import Optional + +from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig +from litellm.secret_managers.main import get_secret_str + + +class NscaleConfig(OpenAIGPTConfig): + """ + Reference: Nscale is OpenAI compatible. + API Key: NSCALE_API_KEY + Default API Base: https://inference.api.nscale.com/v1 + """ + + API_BASE_URL = "https://inference.api.nscale.com/v1" + + @property + def custom_llm_provider(self) -> Optional[str]: + return "nscale" + + @staticmethod + def get_api_key(api_key: Optional[str] = None) -> Optional[str]: + return api_key or get_secret_str("NSCALE_API_KEY") + + @staticmethod + def get_api_base(api_base: Optional[str] = None) -> Optional[str]: + return ( + api_base or get_secret_str("NSCALE_API_BASE") or NscaleConfig.API_BASE_URL + ) + + def _get_openai_compatible_provider_info( + self, api_base: Optional[str], api_key: Optional[str] + ) -> tuple[Optional[str], Optional[str]]: + # This method is called by get_llm_provider to resolve api_base and api_key + resolved_api_base = NscaleConfig.get_api_base(api_base) + resolved_api_key = NscaleConfig.get_api_key(api_key) + return resolved_api_base, resolved_api_key + + def get_supported_openai_params(self, model: str) -> list: + return [ + "max_tokens", + "n", + "temperature", + "top_p", + ] diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 2e473a683694..6867a7f1db3d 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -12197,5 +12197,174 @@ "max_output_tokens": 8192, "litellm_provider": "snowflake", "mode": "chat" + }, + "nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 9e-8, + "output_cost_per_token": 2.9e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/Qwen2.5-Coder-3B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1e-8, + "output_cost_per_token": 3e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/Qwen2.5-Coder-7B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1e-8, + "output_cost_per_token": 3e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/Qwen2.5-Coder-32B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 6e-8, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/QwQ-32B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1.8e-7, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 3.75e-7, + "output_cost_per_token": 3.75e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.75/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-8B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 2.5e-8, + "output_cost_per_token": 2.5e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.05/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 9e-8, + "output_cost_per_token": 9e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.18/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 2e-7, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.40/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 7e-8, + "output_cost_per_token": 7e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.14/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1.5e-7, + "output_cost_per_token": 1.5e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.30/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/mistralai/mixtral-8x22b-instruct-v0.1": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 6e-7, + "output_cost_per_token": 6e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $1.20/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/meta-llama/Llama-3.1-8B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 3e-8, + "output_cost_per_token": 3e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.06/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/meta-llama/Llama-3.3-70B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 2e-7, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.40/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/black-forest-labs/FLUX.1-schnell": { + "mode": "image_generation", + "input_cost_per_pixel": 1.3e-9, + "output_cost_per_pixel": 0.0, + "litellm_provider": "nscale", + "supported_endpoints": [ + "/v1/images/generations" + ], + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#image-models" + }, + "nscale/stabilityai/stable-diffusion-xl-base-1.0": { + "mode": "image_generation", + "input_cost_per_pixel": 3e-9, + "output_cost_per_pixel": 0.0, + "litellm_provider": "nscale", + "supported_endpoints": [ + "/v1/images/generations" + ], + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#image-models" } } diff --git a/litellm/types/utils.py b/litellm/types/utils.py index ab3f0d9d2e26..a3eb6f7fda8f 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -2157,6 +2157,7 @@ class LlmProviders(str, Enum): ASSEMBLYAI = "assemblyai" SNOWFLAKE = "snowflake" LLAMA = "meta_llama" + NSCALE = "nscale" # Create a set of all provider values for quick lookup diff --git a/litellm/utils.py b/litellm/utils.py index e28b0ceca159..0bc579b1182f 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -6383,6 +6383,8 @@ def get_provider_chat_config( # noqa: PLR0915 return litellm.LiteLLMProxyChatConfig() elif litellm.LlmProviders.OPENAI == provider: return litellm.OpenAIGPTConfig() + elif litellm.LlmProviders.NSCALE == provider: + return litellm.NscaleConfig() return None @staticmethod diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 138c7313029c..e1963c707cb8 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -12197,5 +12197,174 @@ "max_output_tokens": 8192, "litellm_provider": "snowflake", "mode": "chat" + }, + "nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 9e-8, + "output_cost_per_token": 2.9e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/Qwen2.5-Coder-3B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1e-8, + "output_cost_per_token": 3e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/Qwen2.5-Coder-7B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1e-8, + "output_cost_per_token": 3e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/Qwen2.5-Coder-32B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 6e-8, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/Qwen/QwQ-32B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1.8e-7, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 3.75e-7, + "output_cost_per_token": 3.75e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.75/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-8B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 2.5e-8, + "output_cost_per_token": 2.5e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.05/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 9e-8, + "output_cost_per_token": 9e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.18/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 2e-7, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.40/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 7e-8, + "output_cost_per_token": 7e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.14/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 1.5e-7, + "output_cost_per_token": 1.5e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.30/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/mistralai/mixtral-8x22b-instruct-v0.1": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 6e-7, + "output_cost_per_token": 6e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $1.20/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/meta-llama/Llama-3.1-8B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 3e-8, + "output_cost_per_token": 3e-8, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.06/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/meta-llama/Llama-3.3-70B-Instruct": { + "max_tokens": null, + "max_input_tokens": null, + "max_output_tokens": null, + "input_cost_per_token": 2e-7, + "output_cost_per_token": 2e-7, + "litellm_provider": "nscale", + "mode": "chat", + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models", + "notes": "Pricing listed as $0.40/1M tokens total. Assumed 50/50 split for input/output." + }, + "nscale/black-forest-labs/FLUX.1-schnell": { + "mode": "image_generation", + "input_cost_per_pixel": 1.3e-9, + "output_cost_per_pixel": 0.0, + "litellm_provider": "nscale", + "supported_endpoints": [ + "/v1/images/generations" + ], + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#image-models" + }, + "nscale/stabilityai/stable-diffusion-xl-base-1.0": { + "mode": "image_generation", + "input_cost_per_pixel": 3e-9, + "output_cost_per_pixel": 0.0, + "litellm_provider": "nscale", + "supported_endpoints": [ + "/v1/images/generations" + ], + "source": "https://docs.nscale.com/docs/inference/serverless-models/current#image-models" } } From fa51413b7085333cee648250615815a2bbb880ca Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Wed, 7 May 2025 22:23:24 +0100 Subject: [PATCH 2/8] Add image generation support and fix unit tests --- litellm/main.py | 2 +- .../chat/test_nscale_chat_transformation.py | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 tests/litellm/llms/nscale/chat/test_nscale_chat_transformation.py diff --git a/litellm/main.py b/litellm/main.py index 4ab47398a7c2..2fb495ab8fc8 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -4788,7 +4788,7 @@ def image_generation( # noqa: PLR0915 model=model, prompt=prompt, timeout=timeout, - api_key=api_key, + api_key=api_key or dynamic_api_key, api_base=api_base, logging_obj=litellm_logging_obj, optional_params=optional_params, diff --git a/tests/litellm/llms/nscale/chat/test_nscale_chat_transformation.py b/tests/litellm/llms/nscale/chat/test_nscale_chat_transformation.py new file mode 100644 index 000000000000..4fcd79ae2a13 --- /dev/null +++ b/tests/litellm/llms/nscale/chat/test_nscale_chat_transformation.py @@ -0,0 +1,55 @@ +import os +import sys +from unittest.mock import patch + +sys.path.insert( + 0, os.path.abspath("../../../../..") +) # Adds the parent directory to the system path + +from litellm.llms.nscale.chat.transformation import NscaleConfig + + +class TestNscaleConfig: + def setup_method(self): + self.config = NscaleConfig() + + def test_custom_llm_provider(self): + """Test that custom_llm_provider returns the correct value""" + assert self.config.custom_llm_provider == "nscale" + + def test_get_api_key(self): + """Test that get_api_key returns the correct API key""" + # Test with provided API key + assert self.config.get_api_key("test-key") == "test-key" + + # Test with environment variable + with patch( + "litellm.llms.nscale.chat.transformation.get_secret_str", + return_value="env-key", + ): + assert self.config.get_api_key() == "env-key" + + # Test with patching environment variable + with patch.dict(os.environ, {"NSCALE_API_KEY": "env-key"}): + assert self.config.get_api_key() == "env-key" + + def test_get_api_base(self): + """Test that get_api_base returns the correct API base URL""" + # Test with provided API base + assert ( + self.config.get_api_base("https://custom-base.com") + == "https://custom-base.com" + ) + + # Test with environment variable + with patch( + "litellm.llms.nscale.chat.transformation.get_secret_str", + return_value="https://env-base.com", + ): + assert self.config.get_api_base() == "https://env-base.com" + + # Test with default API base + with patch( + "litellm.llms.nscale.chat.transformation.get_secret_str", return_value=None + ): + assert self.config.get_api_base() == NscaleConfig.API_BASE_URL From 38eb95816471c3629d29ed90064b20a1f3226de3 Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Wed, 7 May 2025 22:50:00 +0100 Subject: [PATCH 3/8] Add docs for nscale --- docs/my-website/docs/providers/nscale.md | 85 ++++++++++++++++++++++++ docs/my-website/sidebars.js | 1 + 2 files changed, 86 insertions(+) create mode 100644 docs/my-website/docs/providers/nscale.md diff --git a/docs/my-website/docs/providers/nscale.md b/docs/my-website/docs/providers/nscale.md new file mode 100644 index 000000000000..87ca7841baf4 --- /dev/null +++ b/docs/my-website/docs/providers/nscale.md @@ -0,0 +1,85 @@ +# NScale +https://docs.nscale.com/docs/ + +NScale is a European-domiciled full-stack AI cloud platform that allows you to scale your workloads securely, sustainably and cost-effectively - without sacrificing control. It provides production-grade reliability for serverless deployments of LLMs with full data sovereignty and compliance baked in. + +## Key Features +- **EU Sovereign**: Full data sovereignty and compliance with European regulations +- **Low Cost**: Extremely competitive pricing for both text and image generation models +- **Production Grade**: Reliable serverless deployments with full isolation +- **No Setup Required**: Instant access to compute without infrastructure management +- **Full Control**: Your data remains private and isolated + +## API Key +```python +# env variable +os.environ['NSCALE_API_KEY'] +``` + +## Sample Usage - Text Generation +```python +from litellm import completion +import os + +os.environ['NSCALE_API_KEY'] = "" +response = completion( + model="nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[ + {"role": "user", "content": "What is LiteLLM?"} + ] +) +print(response) +``` + +## Sample Usage - Image Generation +```python +from litellm import completion +import os + +os.environ['NSCALE_API_KEY'] = "" +response = completion( + model="nscale/stabilityai/stable-diffusion-xl-base-1.0", + prompt="A beautiful sunset over mountains", + n=1, + size="1024x1024" +) +print(response) +``` + +## Supported Models + +### Chat Models + +| Model Name | Description | Input Cost | Output Cost | +|------------|-------------|------------|-------------| +| nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct | 17B parameter model | $0.09/M tokens | $0.29/M tokens | +| nscale/Qwen/Qwen2.5-Coder-3B-Instruct | 3B parameter coding model | $0.01/M tokens | $0.03/M tokens | +| nscale/Qwen/Qwen2.5-Coder-7B-Instruct | 7B parameter coding model | $0.01/M tokens | $0.03/M tokens | +| nscale/Qwen/Qwen2.5-Coder-32B-Instruct | 32B parameter coding model | $0.06/M tokens | $0.20/M tokens | +| nscale/Qwen/QwQ-32B | 32B parameter model | $0.18/M tokens | $0.20/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B | 70B parameter distilled model | $0.375/M tokens | $0.375/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-8B | 8B parameter distilled model | $0.025/M tokens | $0.025/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B | 1.5B parameter distilled model | $0.09/M tokens | $0.09/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B | 7B parameter distilled model | $0.20/M tokens | $0.20/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B | 14B parameter distilled model | $0.07/M tokens | $0.07/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B | 32B parameter distilled model | $0.15/M tokens | $0.15/M tokens | +| nscale/mistralai/mixtral-8x22b-instruct-v0.1 | Mixtral 8x22B model | $0.60/M tokens | $0.60/M tokens | +| nscale/meta-llama/Llama-3.1-8B-Instruct | 8B parameter model | $0.03/M tokens | $0.03/M tokens | +| nscale/meta-llama/Llama-3.3-70B-Instruct | 70B parameter model | $0.20/M tokens | $0.20/M tokens | + +### Image Generation Models + +| Model Name | Description | Cost per Pixel | +|------------|-------------|----------------| +| nscale/black-forest-labs/FLUX.1-schnell | Fast image generation model | $0.0000000013 | +| nscale/stabilityai/stable-diffusion-xl-base-1.0 | SDXL base model | $0.000000003 | + +## Getting Started +1. Create an account at [console.nscale.com](https://console.nscale.com) +2. Add credit to your account (minimum $5) +3. Create an API key in settings +4. Start making API calls using LiteLLM + +## Additional Resources +- [NScale Documentation](https://docs.nscale.com/docs/getting-started/overview) +- [Blog: Sovereign Serverless](https://www.nscale.com/blog/sovereign-serverless-how-we-designed-full-isolation-without-sacrificing-performance) \ No newline at end of file diff --git a/docs/my-website/sidebars.js b/docs/my-website/sidebars.js index e59b8aae5cd7..9c2440ca4f24 100644 --- a/docs/my-website/sidebars.js +++ b/docs/my-website/sidebars.js @@ -237,6 +237,7 @@ const sidebars = { "providers/watsonx", "providers/predibase", "providers/nvidia_nim", + { type: "doc", id: "providers/nscale", label: "NScale (EU Sovereign)" }, "providers/xai", "providers/lm_studio", "providers/cerebras", From b4d052d4571f414d40bcf8d44994b4d257a01f67 Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Wed, 7 May 2025 23:05:38 +0100 Subject: [PATCH 4/8] Fix unit test import issues --- docs/my-website/docs/providers/nscale.md | 8 +- tests/conftest.py | 121 ++++++++++++++++++ tests/large_text.py | 112 ---------------- .../litellm_core_utils/test_token_counter.py | 16 +-- tests/local_testing/test_router.py | 22 ++-- .../tests/load_test_completion.py | 1 - tests/test_fallbacks.py | 1 - 7 files changed, 144 insertions(+), 137 deletions(-) create mode 100644 tests/conftest.py delete mode 100644 tests/large_text.py diff --git a/docs/my-website/docs/providers/nscale.md b/docs/my-website/docs/providers/nscale.md index 87ca7841baf4..03ba090001cc 100644 --- a/docs/my-website/docs/providers/nscale.md +++ b/docs/my-website/docs/providers/nscale.md @@ -1,11 +1,11 @@ # NScale -https://docs.nscale.com/docs/ +[NScale docs](https://docs.nscale.com/docs/getting-started/overview) NScale is a European-domiciled full-stack AI cloud platform that allows you to scale your workloads securely, sustainably and cost-effectively - without sacrificing control. It provides production-grade reliability for serverless deployments of LLMs with full data sovereignty and compliance baked in. ## Key Features - **EU Sovereign**: Full data sovereignty and compliance with European regulations -- **Low Cost**: Extremely competitive pricing for both text and image generation models +- **Ultra-Low Cost (starting at $0.01 / M tokens)**: Extremely competitive pricing for both text and image generation models - **Production Grade**: Reliable serverless deployments with full isolation - **No Setup Required**: Instant access to compute without infrastructure management - **Full Control**: Your data remains private and isolated @@ -33,11 +33,11 @@ print(response) ## Sample Usage - Image Generation ```python -from litellm import completion +from litellm import image_generation import os os.environ['NSCALE_API_KEY'] = "" -response = completion( +response = image_generation( model="nscale/stabilityai/stable-diffusion-xl-base-1.0", prompt="A beautiful sunset over mountains", n=1, diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000000..7468fe38ef29 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,121 @@ +import pytest +import textwrap + + +@pytest.fixture +def large_text() -> str: + text = textwrap.dedent( + """ + Alexander the Great + This article is about the ancient king of Macedonia. For other uses, see Alexander the Great (disambiguation). + Alexander III of Macedon (Ancient Greek: Ἀλέξανδρος, romanized: Alexandros; 20/21 July 356 BC – 10/11 June 323 BC), most commonly known as Alexander the Great,[c] was a king of the ancient Greek kingdom of Macedon.[d] He succeeded his father Philip II to the throne in 336 BC at the age of 20 and spent most of his ruling years conducting a lengthy military campaign throughout Western Asia, Central Asia, parts of South Asia, and Egypt. By the age of 30, he had created one of the largest empires in history, stretching from Greece to northwestern India.[1] He was undefeated in battle and is widely considered to be one of history's greatest and most successful military commanders.[2][3] + + Until the age of 16, Alexander was tutored by Aristotle. In 335 BC, shortly after his assumption of kingship over Macedon, he campaigned in the Balkans and reasserted control over Thrace and parts of Illyria before marching on the city of Thebes, which was subsequently destroyed in battle. Alexander then led the League of Corinth, and used his authority to launch the pan-Hellenic project envisaged by his father, assuming leadership over all Greeks in their conquest of Persia.[4][5] + + In 334 BC, he invaded the Achaemenid Persian Empire and began a series of campaigns that lasted for 10 years. Following his conquest of Asia Minor, Alexander broke the power of Achaemenid Persia in a series of decisive battles, including those at Issus and Gaugamela; he subsequently overthrew Darius III and conquered the Achaemenid Empire in its entirety.[e] After the fall of Persia, the Macedonian Empire held a vast swath of territory between the Adriatic Sea and the Indus River. Alexander endeavored to reach the "ends of the world and the Great Outer Sea" and invaded India in 326 BC, achieving an important victory over Porus, an ancient Indian king of present-day Punjab, at the Battle of the Hydaspes. Due to the demand of his homesick troops, he eventually turned back at the Beas River and later died in 323 BC in Babylon, the city of Mesopotamia that he had planned to establish as his empire's capital. Alexander's death left unexecuted an additional series of planned military and mercantile campaigns that would have begun with a Greek invasion of Arabia. In the years following his death, a series of civil wars broke out across the Macedonian Empire, eventually leading to its disintegration at the hands of the Diadochi. + + With his death marking the start of the Hellenistic period, Alexander's legacy includes the cultural diffusion and syncretism that his conquests engendered, such as Greco-Buddhism and Hellenistic Judaism. He founded more than twenty cities, with the most prominent being the city of Alexandria in Egypt. Alexander's settlement of Greek colonists and the resulting spread of Greek culture led to the overwhelming dominance of Hellenistic civilization and influence as far east as the Indian subcontinent. The Hellenistic period developed through the Roman Empire into modern Western culture; the Greek language became the lingua franca of the region and was the predominant language of the Byzantine Empire up until its collapse in the mid-15th century AD. Alexander became legendary as a classical hero in the mould of Achilles, featuring prominently in the historical and mythical traditions of both Greek and non-Greek cultures. His military achievements and unprecedented enduring successes in battle made him the measure against which many later military leaders would compare themselves,[f] and his tactics remain a significant subject of study in military academies worldwide.[6] Legends of Alexander's exploits coalesced into the third-century Alexander Romance which, in the premodern period, went through over one hundred recensions, translations, and derivations and was translated into almost every European vernacular and every language of the Islamic world.[7] After the Bible, it was the most popular form of European literature.[8] + + Early life + + Lineage and childhood + + Alexander III was born in Pella, the capital of the Kingdom of Macedon,[9] on the sixth day of the ancient Greek month of Hekatombaion, which probably corresponds to 20 July 356 BC (although the exact date is uncertain).[10][11] He was the son of the erstwhile king of Macedon, Philip II, and his fourth wife, Olympias (daughter of Neoptolemus I, king of Epirus).[12][g] Although Philip had seven or eight wives, Olympias was his principal wife for some time, likely because she gave birth to Alexander.[13] + + Several legends surround Alexander's birth and childhood.[14] According to the ancient Greek biographer Plutarch, on the eve of the consummation of her marriage to Philip, Olympias dreamed that her womb was struck by a thunderbolt that caused a flame to spread "far and wide" before dying away. Sometime after the wedding, Philip is said to have seen himself, in a dream, securing his wife's womb with a seal engraved with a lion's image.[15] Plutarch offered a variety of interpretations for these dreams: that Olympias was pregnant before her marriage, indicated by the sealing of her womb; or that Alexander's father was Zeus. Ancient commentators were divided about whether the ambitious Olympias promulgated the story of Alexander's divine parentage, variously claiming that she had told Alexander, or that she dismissed the suggestion as impious.[15] + + On the day Alexander was born, Philip was preparing a siege on the city of Potidea on the peninsula of Chalcidice. That same day, Philip received news that his general Parmenion had defeated the combined Illyrian and Paeonian armies and that his horses had won at the Olympic Games. It was also said that on this day, the Temple of Artemis in Ephesus, one of the Seven Wonders of the World, burnt down. This led Hegesias of Magnesia to say that it had burnt down because Artemis was away, attending the birth of Alexander.[16] Such legends may have emerged when Alexander was king, and possibly at his instigation, to show that he was superhuman and destined for greatness from conception.[14] + + In his early years, Alexander was raised by a nurse, Lanike, sister of Alexander's future general Cleitus the Black. Later in his childhood, Alexander was tutored by the strict Leonidas, a relative of his mother, and by Lysimachus of Acarnania.[17] Alexander was raised in the manner of noble Macedonian youths, learning to read, play the lyre, ride, fight, and hunt.[18] When Alexander was ten years old, a trader from Thessaly brought Philip a horse, which he offered to sell for thirteen talents. The horse refused to be mounted, and Philip ordered it away. Alexander, however, detecting the horse's fear of its own shadow, asked to tame the horse, which he eventually managed.[14] Plutarch stated that Philip, overjoyed at this display of courage and ambition, kissed his son tearfully, declaring: "My boy, you must find a kingdom big enough for your ambitions. Macedon is too small for you", and bought the horse for him.[19] Alexander named it Bucephalas, meaning "ox-head". Bucephalas carried Alexander as far as India. When the animal died (because of old age, according to Plutarch, at age 30), Alexander named a city after him, Bucephala.[20] + + Education + + When Alexander was 13, Philip began to search for a tutor, and considered such academics as Isocrates and Speusippus, the latter offering to resign from his stewardship of the Academy to take up the post. In the end, Philip chose Aristotle and provided the Temple of the Nymphs at Mieza as a classroom. In return for teaching Alexander, Philip agreed to rebuild Aristotle's hometown of Stageira, which Philip had razed, and to repopulate it by buying and freeing the ex-citizens who were slaves, or pardoning those who were in exile.[21] + + Mieza was like a boarding school for Alexander and the children of Macedonian nobles, such as Ptolemy, Hephaistion, and Cassander. Many of these students would become his friends and future generals, and are often known as the "Companions". Aristotle taught Alexander and his companions about medicine, philosophy, morals, religion, logic, and art. Under Aristotle's tutelage, Alexander developed a passion for the works of Homer, and in particular the Iliad; Aristotle gave him an annotated copy, which Alexander later carried on his campaigns.[22] Alexander was able to quote Euripides from memory.[23] + + During his youth, Alexander was also acquainted with Persian exiles at the Macedonian court, who received the protection of Philip II for several years as they opposed Artaxerxes III.[24][25][26] Among them were Artabazos II and his daughter Barsine, possible future mistress of Alexander, who resided at the Macedonian court from 352 to 342 BC, as well as Amminapes, future satrap of Alexander, or a Persian nobleman named Sisines.[24][27][28][29] This gave the Macedonian court a good knowledge of Persian issues, and may even have influenced some of the innovations in the management of the Macedonian state.[27] + + Suda writes that Anaximenes of Lampsacus was one of Alexander's teachers, and that Anaximenes also accompanied Alexander on his campaigns.[30] + + Heir of Philip II + + Regency and ascent of Macedon + + Main articles: Philip II of Macedon and Rise of Macedon + Further information: History of Macedonia (ancient kingdom) + At the age of 16, Alexander's education under Aristotle ended. Philip II had waged war against the Thracians to the north, which left Alexander in charge as regent and heir apparent.[14] During Philip's absence, the Thracian tribe of Maedi revolted against Macedonia. Alexander responded quickly and drove them from their territory. The territory was colonized, and a city, named Alexandropolis, was founded.[31] + + Upon Philip's return, Alexander was dispatched with a small force to subdue the revolts in southern Thrace. Campaigning against the Greek city of Perinthus, Alexander reportedly saved his father's life. Meanwhile, the city of Amphissa began to work lands that were sacred to Apollo near Delphi, a sacrilege that gave Philip the opportunity to further intervene in Greek affairs. While Philip was occupied in Thrace, Alexander was ordered to muster an army for a campaign in southern Greece. Concerned that other Greek states might intervene, Alexander made it look as though he was preparing to attack Illyria instead. During this turmoil, the Illyrians invaded Macedonia, only to be repelled by Alexander.[32] + + Philip and his army joined his son in 338 BC, and they marched south through Thermopylae, taking it after stubborn resistance from its Theban garrison. They went on to occupy the city of Elatea, only a few days' march from both Athens and Thebes. The Athenians, led by Demosthenes, voted to seek alliance with Thebes against Macedonia. Both Athens and Philip sent embassies to win Thebes's favour, but Athens won the contest.[33] Philip marched on Amphissa (ostensibly acting on the request of the Amphictyonic League), capturing the mercenaries sent there by Demosthenes and accepting the city's surrender. Philip then returned to Elatea, sending a final offer of peace to Athens and Thebes, who both rejected it.[34] + + As Philip marched south, his opponents blocked him near Chaeronea, Boeotia. During the ensuing Battle of Chaeronea, Philip commanded the right wing and Alexander the left, accompanied by a group of Philip's trusted generals. According to the ancient sources, the two sides fought bitterly for some time. Philip deliberately commanded his troops to retreat, counting on the untested Athenian hoplites to follow, thus breaking their line. Alexander was the first to break the Theban lines, followed by Philip's generals. Having damaged the enemy's cohesion, Philip ordered his troops to press forward and quickly routed them. With the Athenians lost, the Thebans were surrounded. Left to fight alone, they were defeated.[35] + + After the victory at Chaeronea, Philip and Alexander marched unopposed into the Peloponnese, welcomed by all cities; however, when they reached Sparta, they were refused, but did not resort to war.[36] At Corinth, Philip established a "Hellenic Alliance" (modelled on the old anti-Persian alliance of the Greco-Persian Wars), which included most Greek city-states except Sparta. Philip was then named Hegemon (often translated as "Supreme Commander") of this league (known by modern scholars as the League of Corinth), and announced his plans to attack the Persian Empire.[37][38] + + Exile and return + + When Philip returned to Pella, he fell in love with and married Cleopatra Eurydice in 338 BC,[39] the niece of his general Attalus.[40] The marriage made Alexander's position as heir less secure, since any son of Cleopatra Eurydice would be a fully Macedonian heir, while Alexander was only half-Macedonian.[41] During the wedding banquet, a drunken Attalus publicly prayed to the gods that the union would produce a legitimate heir.[40] + + At the wedding of Cleopatra, whom Philip fell in love with and married, she being much too young for him, her uncle Attalus in his drink desired the Macedonians would implore the gods to give them a lawful successor to the kingdom by his niece. This so irritated Alexander, that throwing one of the cups at his head, "You villain," said he, "what, am I then a bastard?" Then Philip, taking Attalus's part, rose up and would have run his son through; but by good fortune for them both, either his over-hasty rage, or the wine he had drunk, made his foot slip, so that he fell down on the floor. At which Alexander reproachfully insulted over him: "See there," said he, "the man who makes preparations to pass out of Europe into Asia, overturned in passing from one seat to another." + + — Plutarch, describing the feud at Philip's wedding.[42]none + In 337 BC, Alexander fled Macedon with his mother, dropping her off with her brother, King Alexander I of Epirus in Dodona, capital of the Molossians.[43] He continued to Illyria,[43] where he sought refuge with one or more Illyrian kings, perhaps with Glaucias, and was treated as a guest, despite having defeated them in battle a few years before.[44] However, it appears Philip never intended to disown his politically and militarily trained son.[43] Accordingly, Alexander returned to Macedon after six months due to the efforts of a family friend, Demaratus, who mediated between the two parties.[45] + + In the following year, the Persian satrap (governor) of Caria, Pixodarus, offered his eldest daughter to Alexander's half-brother, Philip Arrhidaeus.[43] Olympias and several of Alexander's friends suggested this showed Philip intended to make Arrhidaeus his heir.[43] Alexander reacted by sending an actor, Thessalus of Corinth, to tell Pixodarus that he should not offer his daughter's hand to an illegitimate son, but instead to Alexander. When Philip heard of this, he stopped the negotiations and scolded Alexander for wishing to marry the daughter of a Carian, explaining that he wanted a better bride for him.[43] Philip exiled four of Alexander's friends, Harpalus, Nearchus, Ptolemy and Erigyius, and had the Corinthians bring Thessalus to him in chains.[46] + + King of Macedon + + Accession + + Further information: Government of Macedonia (ancient kingdom) + In summer 336 BC, while at Aegae attending the wedding of his daughter Cleopatra to Olympias's brother, Alexander I of Epirus, Philip was assassinated by the captain of his bodyguards, Pausanias.[h] As Pausanias tried to escape, he tripped over a vine and was killed by his pursuers, including two of Alexander's companions, Perdiccas and Leonnatus. Alexander was proclaimed king on the spot by the nobles and army at the age of 20.[47][48][49] + + Consolidation of power + + Alexander began his reign by eliminating potential rivals to the throne. He had his cousin, the former Amyntas IV, executed.[51] He also had two Macedonian princes from the region of Lyncestis killed for having been involved in his father's assassination, but spared a third, Alexander Lyncestes. Olympias had Cleopatra Eurydice, and Europa, her daughter by Philip, burned alive. When Alexander learned about this, he was furious. Alexander also ordered the murder of Attalus,[51] who was in command of the advance guard of the army in Asia Minor and Cleopatra's uncle.[52] + + Attalus was at that time corresponding with Demosthenes, regarding the possibility of defecting to Athens. Attalus also had severely insulted Alexander, and following Cleopatra's murder, Alexander may have considered him too dangerous to be left alive.[52] Alexander spared Arrhidaeus, who was by all accounts mentally disabled, possibly as a result of poisoning by Olympias.[47][49][53] + + News of Philip's death roused many states into revolt, including Thebes, Athens, Thessaly, and the Thracian tribes north of Macedon. When news of the revolts reached Alexander, he responded quickly. Though advised to use diplomacy, Alexander mustered 3,000 Macedonian cavalry and rode south towards Thessaly. He found the Thessalian army occupying the pass between Mount Olympus and Mount Ossa, and ordered his men to ride over Mount Ossa. When the Thessalians awoke the next day, they found Alexander in their rear and promptly surrendered, adding their cavalry to Alexander's force. He then continued south towards the Peloponnese.[54] + + Alexander stopped at Thermopylae, where he was recognized as the leader of the Amphictyonic League before heading south to Corinth. Athens sued for peace and Alexander pardoned the rebels. The famous encounter between Alexander and Diogenes the Cynic occurred during Alexander's stay in Corinth. When Alexander asked Diogenes what he could do for him, the philosopher disdainfully asked Alexander to stand a little to the side, as he was blocking the sunlight.[55] This reply apparently delighted Alexander, who is reported to have said "But verily, if I were not Alexander, I would like to be Diogenes."[56] At Corinth, Alexander took the title of Hegemon ("leader") and, like Philip, was appointed commander for the coming war against Persia. He also received news of a Thracian uprising.[57] + + Balkan campaign + + Main article: Alexander's Balkan campaign + Before crossing to Asia, Alexander wanted to safeguard his northern borders. In the spring of 335 BC, he advanced to suppress several revolts. Starting from Amphipolis, he travelled east into the country of the "Independent Thracians"; and at Mount Haemus, the Macedonian army attacked and defeated the Thracian forces manning the heights.[58] The Macedonians marched into the country of the Triballi, and defeated their army near the Lyginus river[59] (a tributary of the Danube). Alexander then marched for three days to the Danube, encountering the Getae tribe on the opposite shore. Crossing the river at night, he surprised them and forced their army to retreat after the first cavalry skirmish.[60] + + News then reached Alexander that the Illyrian chieftain Cleitus and King Glaukias of the Taulantii were in open revolt against his authority. Marching west into Illyria, Alexander defeated each in turn, forcing the two rulers to flee with their troops. With these victories, he secured his northern frontier.[61] + + Destruction of Thebes + + While Alexander campaigned north, the Thebans and Athenians rebelled once again. Alexander immediately headed south.[62] While the other cities again hesitated, Thebes decided to fight. The Theban resistance was ineffective, and Alexander razed the city and divided its territory between the other Boeotian cities. The end of Thebes cowed Athens, leaving all of Greece temporarily at peace.[62] Alexander then set out on his Asian campaign, leaving Antipater as regent.[63] + + Conquest of the Achaemenid Persian Empire + + Main articles: Wars of Alexander the Great and Chronology of the expedition of Alexander the Great into Asia + Asia Minor + + Further information: Battle of the Granicus, Siege of Halicarnassus, and Siege of Miletus + After his victory at the Battle of Chaeronea (338 BC), Philip II began the work of establishing himself as hēgemṓn (Greek: ἡγεμών) of a league which according to Diodorus was to wage a campaign against the Persians for the sundry grievances Greece suffered in 480 and free the Greek cities of the western coast and islands from Achaemenid rule. In 336 he sent Parmenion, Amyntas, Andromenes, Attalus, and an army of 10,000 men into Anatolia to make preparations for an invasion.[64][65] At first, all went well. The Greek cities on the western coast of Anatolia revolted until the news arrived that Philip had been murdered and had been succeeded by his young son Alexander. The Macedonians were demoralized by Philip's death and were subsequently defeated near Magnesia by the Achaemenids under the command of the mercenary Memnon of Rhodes.[64][65] + + Taking over the invasion project of Philip II, Alexander's army crossed the Hellespont in 334 BC with approximately 48,100 soldiers, 6,100 cavalry and a fleet of 120 ships with crews numbering 38,000,[62] drawn from Macedon and various Greek city-states, mercenaries, and feudally raised soldiers from Thrace, Paionia, and Illyria.[66][i] He showed his intent to conquer the entirety of the Persian Empire by throwing a spear into Asian soil and saying he accepted Asia as a gift from the gods. This also showed Alexander's eagerness to fight, in contrast to his father's preference for diplomacy.[62] + + After an initial victory against Persian forces at the Battle of the Granicus, Alexander accepted the surrender of the Persian provincial capital and treasury of Sardis; he then proceeded along the Ionian coast, granting autonomy and democracy to the cities. Miletus, held by Achaemenid forces, required a delicate siege operation, with Persian naval forces nearby. Further south, at Halicarnassus, in Caria, Alexander successfully waged his first large-scale siege, eventually forcing his opponents, the mercenary captain Memnon of Rhodes and the Persian satrap of Caria, Orontobates, to withdraw by sea.[67] Alexander left the government of Caria to a member of the Hecatomnid dynasty, Ada, who adopted Alexander.[68] + + From Halicarnassus, Alexander proceeded into mountainous Lycia and the Pamphylian plain, asserting control over all coastal cities to deny the Persians naval bases. From Pamphylia onwards the coast held no major ports and Alexander moved inland. At Termessos, Alexander humbled but did not storm the Pisidian city.[69] At the ancient Phrygian capital of Gordium, Alexander "undid" the hitherto unsolvable Gordian Knot, a feat said to await the future "king of Asia".[70] According to the story, Alexander proclaimed that it did not matter how the knot was undone and hacked it apart with his sword.[71] + + The Levant and Syria + + Further information: Battle of Issus and Siege of Tyre (332 BC) + In spring 333 BC, Alexander crossed the Taurus into Cilicia. After a long pause due to an illness, he marched on towards Syria. Though outmanoeuvered by Darius's significantly larger army, he marched back to Cilicia, where he defeated Darius at Issus. Darius fled the battle, causing his army to collapse, and left behind his wife, his two daughters, his mother Sisygambis, and a fabulous treasure.[72] He offered a peace treaty that included the lands he had already lost, and a ransom of 10,000 talents for his family. Alexander replied that since he was now king of Asia, it was he alone who decided territorial divisions.[73] Alexander proceeded to take possession of Syria, and most of the coast of the Levant.[68] In the following year, 332 BC, he was forced to attack Tyre, which he captured after a long and difficult siege.[74][75] The men of military age were massacred and the women and children sold into slavery.[76] + + Egypt + + Further information: Siege of Gaza (332 BCE) + When Alexander destroyed Tyre, most of the towns on the route to Egypt quickly capitulated. However, Alexander was met with resistance at Gaza. The stronghold was heavily fortified and built on a hill, requiring a siege. When "his engineers pointed out to him that because of the height of the mound it would be impossible... this encouraged Alexander all the more to make the attempt".[77] After three unsuccessful assaults, the stronghold fell, but not before Alexander had received a serious shoulder wound. As in Tyre, men of military age were put to the sword and the women and children were sold into slavery.[78] + """ + ) + return text diff --git a/tests/large_text.py b/tests/large_text.py deleted file mode 100644 index 86904a6d148f..000000000000 --- a/tests/large_text.py +++ /dev/null @@ -1,112 +0,0 @@ -text = """ -Alexander the Great -This article is about the ancient king of Macedonia. For other uses, see Alexander the Great (disambiguation). -Alexander III of Macedon (Ancient Greek: Ἀλέξανδρος, romanized: Alexandros; 20/21 July 356 BC – 10/11 June 323 BC), most commonly known as Alexander the Great,[c] was a king of the ancient Greek kingdom of Macedon.[d] He succeeded his father Philip II to the throne in 336 BC at the age of 20 and spent most of his ruling years conducting a lengthy military campaign throughout Western Asia, Central Asia, parts of South Asia, and Egypt. By the age of 30, he had created one of the largest empires in history, stretching from Greece to northwestern India.[1] He was undefeated in battle and is widely considered to be one of history's greatest and most successful military commanders.[2][3] - -Until the age of 16, Alexander was tutored by Aristotle. In 335 BC, shortly after his assumption of kingship over Macedon, he campaigned in the Balkans and reasserted control over Thrace and parts of Illyria before marching on the city of Thebes, which was subsequently destroyed in battle. Alexander then led the League of Corinth, and used his authority to launch the pan-Hellenic project envisaged by his father, assuming leadership over all Greeks in their conquest of Persia.[4][5] - -In 334 BC, he invaded the Achaemenid Persian Empire and began a series of campaigns that lasted for 10 years. Following his conquest of Asia Minor, Alexander broke the power of Achaemenid Persia in a series of decisive battles, including those at Issus and Gaugamela; he subsequently overthrew Darius III and conquered the Achaemenid Empire in its entirety.[e] After the fall of Persia, the Macedonian Empire held a vast swath of territory between the Adriatic Sea and the Indus River. Alexander endeavored to reach the "ends of the world and the Great Outer Sea" and invaded India in 326 BC, achieving an important victory over Porus, an ancient Indian king of present-day Punjab, at the Battle of the Hydaspes. Due to the demand of his homesick troops, he eventually turned back at the Beas River and later died in 323 BC in Babylon, the city of Mesopotamia that he had planned to establish as his empire's capital. Alexander's death left unexecuted an additional series of planned military and mercantile campaigns that would have begun with a Greek invasion of Arabia. In the years following his death, a series of civil wars broke out across the Macedonian Empire, eventually leading to its disintegration at the hands of the Diadochi. - -With his death marking the start of the Hellenistic period, Alexander's legacy includes the cultural diffusion and syncretism that his conquests engendered, such as Greco-Buddhism and Hellenistic Judaism. He founded more than twenty cities, with the most prominent being the city of Alexandria in Egypt. Alexander's settlement of Greek colonists and the resulting spread of Greek culture led to the overwhelming dominance of Hellenistic civilization and influence as far east as the Indian subcontinent. The Hellenistic period developed through the Roman Empire into modern Western culture; the Greek language became the lingua franca of the region and was the predominant language of the Byzantine Empire up until its collapse in the mid-15th century AD. Alexander became legendary as a classical hero in the mould of Achilles, featuring prominently in the historical and mythical traditions of both Greek and non-Greek cultures. His military achievements and unprecedented enduring successes in battle made him the measure against which many later military leaders would compare themselves,[f] and his tactics remain a significant subject of study in military academies worldwide.[6] Legends of Alexander's exploits coalesced into the third-century Alexander Romance which, in the premodern period, went through over one hundred recensions, translations, and derivations and was translated into almost every European vernacular and every language of the Islamic world.[7] After the Bible, it was the most popular form of European literature.[8] - -Early life - -Lineage and childhood - -Alexander III was born in Pella, the capital of the Kingdom of Macedon,[9] on the sixth day of the ancient Greek month of Hekatombaion, which probably corresponds to 20 July 356 BC (although the exact date is uncertain).[10][11] He was the son of the erstwhile king of Macedon, Philip II, and his fourth wife, Olympias (daughter of Neoptolemus I, king of Epirus).[12][g] Although Philip had seven or eight wives, Olympias was his principal wife for some time, likely because she gave birth to Alexander.[13] - -Several legends surround Alexander's birth and childhood.[14] According to the ancient Greek biographer Plutarch, on the eve of the consummation of her marriage to Philip, Olympias dreamed that her womb was struck by a thunderbolt that caused a flame to spread "far and wide" before dying away. Sometime after the wedding, Philip is said to have seen himself, in a dream, securing his wife's womb with a seal engraved with a lion's image.[15] Plutarch offered a variety of interpretations for these dreams: that Olympias was pregnant before her marriage, indicated by the sealing of her womb; or that Alexander's father was Zeus. Ancient commentators were divided about whether the ambitious Olympias promulgated the story of Alexander's divine parentage, variously claiming that she had told Alexander, or that she dismissed the suggestion as impious.[15] - -On the day Alexander was born, Philip was preparing a siege on the city of Potidea on the peninsula of Chalcidice. That same day, Philip received news that his general Parmenion had defeated the combined Illyrian and Paeonian armies and that his horses had won at the Olympic Games. It was also said that on this day, the Temple of Artemis in Ephesus, one of the Seven Wonders of the World, burnt down. This led Hegesias of Magnesia to say that it had burnt down because Artemis was away, attending the birth of Alexander.[16] Such legends may have emerged when Alexander was king, and possibly at his instigation, to show that he was superhuman and destined for greatness from conception.[14] - -In his early years, Alexander was raised by a nurse, Lanike, sister of Alexander's future general Cleitus the Black. Later in his childhood, Alexander was tutored by the strict Leonidas, a relative of his mother, and by Lysimachus of Acarnania.[17] Alexander was raised in the manner of noble Macedonian youths, learning to read, play the lyre, ride, fight, and hunt.[18] When Alexander was ten years old, a trader from Thessaly brought Philip a horse, which he offered to sell for thirteen talents. The horse refused to be mounted, and Philip ordered it away. Alexander, however, detecting the horse's fear of its own shadow, asked to tame the horse, which he eventually managed.[14] Plutarch stated that Philip, overjoyed at this display of courage and ambition, kissed his son tearfully, declaring: "My boy, you must find a kingdom big enough for your ambitions. Macedon is too small for you", and bought the horse for him.[19] Alexander named it Bucephalas, meaning "ox-head". Bucephalas carried Alexander as far as India. When the animal died (because of old age, according to Plutarch, at age 30), Alexander named a city after him, Bucephala.[20] - -Education - -When Alexander was 13, Philip began to search for a tutor, and considered such academics as Isocrates and Speusippus, the latter offering to resign from his stewardship of the Academy to take up the post. In the end, Philip chose Aristotle and provided the Temple of the Nymphs at Mieza as a classroom. In return for teaching Alexander, Philip agreed to rebuild Aristotle's hometown of Stageira, which Philip had razed, and to repopulate it by buying and freeing the ex-citizens who were slaves, or pardoning those who were in exile.[21] - -Mieza was like a boarding school for Alexander and the children of Macedonian nobles, such as Ptolemy, Hephaistion, and Cassander. Many of these students would become his friends and future generals, and are often known as the "Companions". Aristotle taught Alexander and his companions about medicine, philosophy, morals, religion, logic, and art. Under Aristotle's tutelage, Alexander developed a passion for the works of Homer, and in particular the Iliad; Aristotle gave him an annotated copy, which Alexander later carried on his campaigns.[22] Alexander was able to quote Euripides from memory.[23] - -During his youth, Alexander was also acquainted with Persian exiles at the Macedonian court, who received the protection of Philip II for several years as they opposed Artaxerxes III.[24][25][26] Among them were Artabazos II and his daughter Barsine, possible future mistress of Alexander, who resided at the Macedonian court from 352 to 342 BC, as well as Amminapes, future satrap of Alexander, or a Persian nobleman named Sisines.[24][27][28][29] This gave the Macedonian court a good knowledge of Persian issues, and may even have influenced some of the innovations in the management of the Macedonian state.[27] - -Suda writes that Anaximenes of Lampsacus was one of Alexander's teachers, and that Anaximenes also accompanied Alexander on his campaigns.[30] - -Heir of Philip II - -Regency and ascent of Macedon - -Main articles: Philip II of Macedon and Rise of Macedon -Further information: History of Macedonia (ancient kingdom) -At the age of 16, Alexander's education under Aristotle ended. Philip II had waged war against the Thracians to the north, which left Alexander in charge as regent and heir apparent.[14] During Philip's absence, the Thracian tribe of Maedi revolted against Macedonia. Alexander responded quickly and drove them from their territory. The territory was colonized, and a city, named Alexandropolis, was founded.[31] - -Upon Philip's return, Alexander was dispatched with a small force to subdue the revolts in southern Thrace. Campaigning against the Greek city of Perinthus, Alexander reportedly saved his father's life. Meanwhile, the city of Amphissa began to work lands that were sacred to Apollo near Delphi, a sacrilege that gave Philip the opportunity to further intervene in Greek affairs. While Philip was occupied in Thrace, Alexander was ordered to muster an army for a campaign in southern Greece. Concerned that other Greek states might intervene, Alexander made it look as though he was preparing to attack Illyria instead. During this turmoil, the Illyrians invaded Macedonia, only to be repelled by Alexander.[32] - -Philip and his army joined his son in 338 BC, and they marched south through Thermopylae, taking it after stubborn resistance from its Theban garrison. They went on to occupy the city of Elatea, only a few days' march from both Athens and Thebes. The Athenians, led by Demosthenes, voted to seek alliance with Thebes against Macedonia. Both Athens and Philip sent embassies to win Thebes's favour, but Athens won the contest.[33] Philip marched on Amphissa (ostensibly acting on the request of the Amphictyonic League), capturing the mercenaries sent there by Demosthenes and accepting the city's surrender. Philip then returned to Elatea, sending a final offer of peace to Athens and Thebes, who both rejected it.[34] - -As Philip marched south, his opponents blocked him near Chaeronea, Boeotia. During the ensuing Battle of Chaeronea, Philip commanded the right wing and Alexander the left, accompanied by a group of Philip's trusted generals. According to the ancient sources, the two sides fought bitterly for some time. Philip deliberately commanded his troops to retreat, counting on the untested Athenian hoplites to follow, thus breaking their line. Alexander was the first to break the Theban lines, followed by Philip's generals. Having damaged the enemy's cohesion, Philip ordered his troops to press forward and quickly routed them. With the Athenians lost, the Thebans were surrounded. Left to fight alone, they were defeated.[35] - -After the victory at Chaeronea, Philip and Alexander marched unopposed into the Peloponnese, welcomed by all cities; however, when they reached Sparta, they were refused, but did not resort to war.[36] At Corinth, Philip established a "Hellenic Alliance" (modelled on the old anti-Persian alliance of the Greco-Persian Wars), which included most Greek city-states except Sparta. Philip was then named Hegemon (often translated as "Supreme Commander") of this league (known by modern scholars as the League of Corinth), and announced his plans to attack the Persian Empire.[37][38] - -Exile and return - -When Philip returned to Pella, he fell in love with and married Cleopatra Eurydice in 338 BC,[39] the niece of his general Attalus.[40] The marriage made Alexander's position as heir less secure, since any son of Cleopatra Eurydice would be a fully Macedonian heir, while Alexander was only half-Macedonian.[41] During the wedding banquet, a drunken Attalus publicly prayed to the gods that the union would produce a legitimate heir.[40] - -At the wedding of Cleopatra, whom Philip fell in love with and married, she being much too young for him, her uncle Attalus in his drink desired the Macedonians would implore the gods to give them a lawful successor to the kingdom by his niece. This so irritated Alexander, that throwing one of the cups at his head, "You villain," said he, "what, am I then a bastard?" Then Philip, taking Attalus's part, rose up and would have run his son through; but by good fortune for them both, either his over-hasty rage, or the wine he had drunk, made his foot slip, so that he fell down on the floor. At which Alexander reproachfully insulted over him: "See there," said he, "the man who makes preparations to pass out of Europe into Asia, overturned in passing from one seat to another." - -— Plutarch, describing the feud at Philip's wedding.[42]none -In 337 BC, Alexander fled Macedon with his mother, dropping her off with her brother, King Alexander I of Epirus in Dodona, capital of the Molossians.[43] He continued to Illyria,[43] where he sought refuge with one or more Illyrian kings, perhaps with Glaucias, and was treated as a guest, despite having defeated them in battle a few years before.[44] However, it appears Philip never intended to disown his politically and militarily trained son.[43] Accordingly, Alexander returned to Macedon after six months due to the efforts of a family friend, Demaratus, who mediated between the two parties.[45] - -In the following year, the Persian satrap (governor) of Caria, Pixodarus, offered his eldest daughter to Alexander's half-brother, Philip Arrhidaeus.[43] Olympias and several of Alexander's friends suggested this showed Philip intended to make Arrhidaeus his heir.[43] Alexander reacted by sending an actor, Thessalus of Corinth, to tell Pixodarus that he should not offer his daughter's hand to an illegitimate son, but instead to Alexander. When Philip heard of this, he stopped the negotiations and scolded Alexander for wishing to marry the daughter of a Carian, explaining that he wanted a better bride for him.[43] Philip exiled four of Alexander's friends, Harpalus, Nearchus, Ptolemy and Erigyius, and had the Corinthians bring Thessalus to him in chains.[46] - -King of Macedon - -Accession - -Further information: Government of Macedonia (ancient kingdom) -In summer 336 BC, while at Aegae attending the wedding of his daughter Cleopatra to Olympias's brother, Alexander I of Epirus, Philip was assassinated by the captain of his bodyguards, Pausanias.[h] As Pausanias tried to escape, he tripped over a vine and was killed by his pursuers, including two of Alexander's companions, Perdiccas and Leonnatus. Alexander was proclaimed king on the spot by the nobles and army at the age of 20.[47][48][49] - -Consolidation of power - -Alexander began his reign by eliminating potential rivals to the throne. He had his cousin, the former Amyntas IV, executed.[51] He also had two Macedonian princes from the region of Lyncestis killed for having been involved in his father's assassination, but spared a third, Alexander Lyncestes. Olympias had Cleopatra Eurydice, and Europa, her daughter by Philip, burned alive. When Alexander learned about this, he was furious. Alexander also ordered the murder of Attalus,[51] who was in command of the advance guard of the army in Asia Minor and Cleopatra's uncle.[52] - -Attalus was at that time corresponding with Demosthenes, regarding the possibility of defecting to Athens. Attalus also had severely insulted Alexander, and following Cleopatra's murder, Alexander may have considered him too dangerous to be left alive.[52] Alexander spared Arrhidaeus, who was by all accounts mentally disabled, possibly as a result of poisoning by Olympias.[47][49][53] - -News of Philip's death roused many states into revolt, including Thebes, Athens, Thessaly, and the Thracian tribes north of Macedon. When news of the revolts reached Alexander, he responded quickly. Though advised to use diplomacy, Alexander mustered 3,000 Macedonian cavalry and rode south towards Thessaly. He found the Thessalian army occupying the pass between Mount Olympus and Mount Ossa, and ordered his men to ride over Mount Ossa. When the Thessalians awoke the next day, they found Alexander in their rear and promptly surrendered, adding their cavalry to Alexander's force. He then continued south towards the Peloponnese.[54] - -Alexander stopped at Thermopylae, where he was recognized as the leader of the Amphictyonic League before heading south to Corinth. Athens sued for peace and Alexander pardoned the rebels. The famous encounter between Alexander and Diogenes the Cynic occurred during Alexander's stay in Corinth. When Alexander asked Diogenes what he could do for him, the philosopher disdainfully asked Alexander to stand a little to the side, as he was blocking the sunlight.[55] This reply apparently delighted Alexander, who is reported to have said "But verily, if I were not Alexander, I would like to be Diogenes."[56] At Corinth, Alexander took the title of Hegemon ("leader") and, like Philip, was appointed commander for the coming war against Persia. He also received news of a Thracian uprising.[57] - -Balkan campaign - -Main article: Alexander's Balkan campaign -Before crossing to Asia, Alexander wanted to safeguard his northern borders. In the spring of 335 BC, he advanced to suppress several revolts. Starting from Amphipolis, he travelled east into the country of the "Independent Thracians"; and at Mount Haemus, the Macedonian army attacked and defeated the Thracian forces manning the heights.[58] The Macedonians marched into the country of the Triballi, and defeated their army near the Lyginus river[59] (a tributary of the Danube). Alexander then marched for three days to the Danube, encountering the Getae tribe on the opposite shore. Crossing the river at night, he surprised them and forced their army to retreat after the first cavalry skirmish.[60] - -News then reached Alexander that the Illyrian chieftain Cleitus and King Glaukias of the Taulantii were in open revolt against his authority. Marching west into Illyria, Alexander defeated each in turn, forcing the two rulers to flee with their troops. With these victories, he secured his northern frontier.[61] - -Destruction of Thebes - -While Alexander campaigned north, the Thebans and Athenians rebelled once again. Alexander immediately headed south.[62] While the other cities again hesitated, Thebes decided to fight. The Theban resistance was ineffective, and Alexander razed the city and divided its territory between the other Boeotian cities. The end of Thebes cowed Athens, leaving all of Greece temporarily at peace.[62] Alexander then set out on his Asian campaign, leaving Antipater as regent.[63] - -Conquest of the Achaemenid Persian Empire - -Main articles: Wars of Alexander the Great and Chronology of the expedition of Alexander the Great into Asia -Asia Minor - -Further information: Battle of the Granicus, Siege of Halicarnassus, and Siege of Miletus -After his victory at the Battle of Chaeronea (338 BC), Philip II began the work of establishing himself as hēgemṓn (Greek: ἡγεμών) of a league which according to Diodorus was to wage a campaign against the Persians for the sundry grievances Greece suffered in 480 and free the Greek cities of the western coast and islands from Achaemenid rule. In 336 he sent Parmenion, Amyntas, Andromenes, Attalus, and an army of 10,000 men into Anatolia to make preparations for an invasion.[64][65] At first, all went well. The Greek cities on the western coast of Anatolia revolted until the news arrived that Philip had been murdered and had been succeeded by his young son Alexander. The Macedonians were demoralized by Philip's death and were subsequently defeated near Magnesia by the Achaemenids under the command of the mercenary Memnon of Rhodes.[64][65] - -Taking over the invasion project of Philip II, Alexander's army crossed the Hellespont in 334 BC with approximately 48,100 soldiers, 6,100 cavalry and a fleet of 120 ships with crews numbering 38,000,[62] drawn from Macedon and various Greek city-states, mercenaries, and feudally raised soldiers from Thrace, Paionia, and Illyria.[66][i] He showed his intent to conquer the entirety of the Persian Empire by throwing a spear into Asian soil and saying he accepted Asia as a gift from the gods. This also showed Alexander's eagerness to fight, in contrast to his father's preference for diplomacy.[62] - -After an initial victory against Persian forces at the Battle of the Granicus, Alexander accepted the surrender of the Persian provincial capital and treasury of Sardis; he then proceeded along the Ionian coast, granting autonomy and democracy to the cities. Miletus, held by Achaemenid forces, required a delicate siege operation, with Persian naval forces nearby. Further south, at Halicarnassus, in Caria, Alexander successfully waged his first large-scale siege, eventually forcing his opponents, the mercenary captain Memnon of Rhodes and the Persian satrap of Caria, Orontobates, to withdraw by sea.[67] Alexander left the government of Caria to a member of the Hecatomnid dynasty, Ada, who adopted Alexander.[68] - -From Halicarnassus, Alexander proceeded into mountainous Lycia and the Pamphylian plain, asserting control over all coastal cities to deny the Persians naval bases. From Pamphylia onwards the coast held no major ports and Alexander moved inland. At Termessos, Alexander humbled but did not storm the Pisidian city.[69] At the ancient Phrygian capital of Gordium, Alexander "undid" the hitherto unsolvable Gordian Knot, a feat said to await the future "king of Asia".[70] According to the story, Alexander proclaimed that it did not matter how the knot was undone and hacked it apart with his sword.[71] - -The Levant and Syria - -Further information: Battle of Issus and Siege of Tyre (332 BC) -In spring 333 BC, Alexander crossed the Taurus into Cilicia. After a long pause due to an illness, he marched on towards Syria. Though outmanoeuvered by Darius's significantly larger army, he marched back to Cilicia, where he defeated Darius at Issus. Darius fled the battle, causing his army to collapse, and left behind his wife, his two daughters, his mother Sisygambis, and a fabulous treasure.[72] He offered a peace treaty that included the lands he had already lost, and a ransom of 10,000 talents for his family. Alexander replied that since he was now king of Asia, it was he alone who decided territorial divisions.[73] Alexander proceeded to take possession of Syria, and most of the coast of the Levant.[68] In the following year, 332 BC, he was forced to attack Tyre, which he captured after a long and difficult siege.[74][75] The men of military age were massacred and the women and children sold into slavery.[76] - -Egypt - -Further information: Siege of Gaza (332 BCE) -When Alexander destroyed Tyre, most of the towns on the route to Egypt quickly capitulated. However, Alexander was met with resistance at Gaza. The stronghold was heavily fortified and built on a hill, requiring a siege. When "his engineers pointed out to him that because of the height of the mound it would be impossible... this encouraged Alexander all the more to make the attempt".[77] After three unsuccessful assaults, the stronghold fell, but not before Alexander had received a serious shoulder wound. As in Tyre, men of military age were put to the sword and the women and children were sold into slavery.[78] -""" diff --git a/tests/litellm/litellm_core_utils/test_token_counter.py b/tests/litellm/litellm_core_utils/test_token_counter.py index 07c1367e5f83..7091a8d4b881 100644 --- a/tests/litellm/litellm_core_utils/test_token_counter.py +++ b/tests/litellm/litellm_core_utils/test_token_counter.py @@ -8,9 +8,10 @@ import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path +# Add project root to Python path +project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) +sys.path.insert(0, project_root) + from unittest.mock import AsyncMock, MagicMock, patch from messages_with_counts import ( @@ -23,7 +24,6 @@ from litellm import create_pretrained_tokenizer, decode, encode, get_modified_max_tokens from litellm import token_counter as token_counter_old from litellm.litellm_core_utils.token_counter import token_counter as token_counter_new -from tests.large_text import text def token_counter_both_assert_same(**args): @@ -259,7 +259,7 @@ def test_gpt_vision_token_counting(): { "role": "user", "content": [ - {"type": "text", "text": "What’s in this image?"}, + {"type": "text", "text": "What's in this image?"}, { "type": "image_url", "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", @@ -277,14 +277,13 @@ def test_gpt_vision_token_counting(): @pytest.mark.parametrize( "model", [ - "gpt-4-vision-preview", "gpt-4o", "claude-3-opus-20240229", "command-nightly", "mistral/mistral-tiny", ], ) -def test_load_test_token_counter(model): +def test_load_test_token_counter(model, large_text): """ Token count large prompt 100 times. @@ -292,12 +291,11 @@ def test_load_test_token_counter(model): """ import tiktoken - messages = [{"role": "user", "content": text}] * 10 + messages = [{"role": "user", "content": large_text}] * 10 start_time = time.time() for _ in range(10): _ = token_counter(model=model, messages=messages) - # enc.encode("".join(m["content"] for m in messages)) end_time = time.time() diff --git a/tests/local_testing/test_router.py b/tests/local_testing/test_router.py index 06cf75705a0f..2131e68b3d4d 100644 --- a/tests/local_testing/test_router.py +++ b/tests/local_testing/test_router.py @@ -683,7 +683,7 @@ async def test2(): @pytest.mark.asyncio @pytest.mark.parametrize("sync_mode", [True, False]) -async def test_async_router_context_window_fallback(sync_mode): +async def test_async_router_context_window_fallback(sync_mode, large_text): """ - Give a gpt-4 model group with different context windows (8192k vs. 128k) - Send a 10k prompt @@ -691,7 +691,7 @@ async def test_async_router_context_window_fallback(sync_mode): """ import os - from large_text import text + text = large_text litellm.set_verbose = False litellm._turn_on_debug() @@ -775,7 +775,9 @@ def test_router_rpm_pre_call_check(): pytest.fail(f"Got unexpected exception on router! - {str(e)}") -def test_router_context_window_check_pre_call_check_in_group_custom_model_info(): +def test_router_context_window_check_pre_call_check_in_group_custom_model_info( + large_text, +): """ - Give a gpt-3.5-turbo model group with different context windows (4k vs. 16k) - Send a 5k prompt @@ -783,7 +785,7 @@ def test_router_context_window_check_pre_call_check_in_group_custom_model_info() """ import os - from large_text import text + text = large_text litellm.set_verbose = False @@ -829,7 +831,7 @@ def test_router_context_window_check_pre_call_check_in_group_custom_model_info() pytest.fail(f"Got unexpected exception on router! - {str(e)}") -def test_router_context_window_check_pre_call_check(): +def test_router_context_window_check_pre_call_check(large_text): """ - Give a gpt-3.5-turbo model group with different context windows (4k vs. 16k) - Send a 5k prompt @@ -837,7 +839,7 @@ def test_router_context_window_check_pre_call_check(): """ import os - from large_text import text + text = large_text litellm.set_verbose = False @@ -883,7 +885,7 @@ def test_router_context_window_check_pre_call_check(): pytest.fail(f"Got unexpected exception on router! - {str(e)}") -def test_router_context_window_check_pre_call_check_out_group(): +def test_router_context_window_check_pre_call_check_out_group(large_text): """ - Give 2 gpt-3.5-turbo model groups with different context windows (4k vs. 16k) - Send a 5k prompt @@ -891,7 +893,7 @@ def test_router_context_window_check_pre_call_check_out_group(): """ import os - from large_text import text + text = large_text litellm.set_verbose = False @@ -1136,7 +1138,7 @@ async def test_aimg_gen_on_router(): "api_base": os.getenv("AZURE_SWEDEN_API_BASE"), "api_key": os.getenv("AZURE_SWEDEN_API_KEY"), }, - } + }, ] router = Router(model_list=model_list, num_retries=3) response = await router.aimage_generation( @@ -2787,4 +2789,4 @@ def test_router_get_model_group_info(): assert model_group_info is not None assert model_group_info.model_group == "gpt-4" assert model_group_info.input_cost_per_token > 0 - assert model_group_info.output_cost_per_token > 0 \ No newline at end of file + assert model_group_info.output_cost_per_token > 0 diff --git a/tests/old_proxy_tests/tests/load_test_completion.py b/tests/old_proxy_tests/tests/load_test_completion.py index 29d8924ab5f1..ce52e6fd25c7 100644 --- a/tests/old_proxy_tests/tests/load_test_completion.py +++ b/tests/old_proxy_tests/tests/load_test_completion.py @@ -4,7 +4,6 @@ from openai import AsyncOpenAI, AsyncAzureOpenAI import uuid import traceback -from large_text import text from dotenv import load_dotenv from statistics import mean, median diff --git a/tests/test_fallbacks.py b/tests/test_fallbacks.py index aab8e985bde9..928af8d7e2bc 100644 --- a/tests/test_fallbacks.py +++ b/tests/test_fallbacks.py @@ -3,7 +3,6 @@ import pytest import asyncio import aiohttp -from large_text import text import time from typing import Optional From 3bb9cc954bc1416650b121a71dcc42fdb38eb41f Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Wed, 7 May 2025 23:20:36 +0100 Subject: [PATCH 5/8] Minor doc improvement --- docs/my-website/docs/providers/nscale.md | 4 ++-- tests/litellm/litellm_core_utils/test_token_counter.py | 10 +++++----- tests/local_testing/test_router.py | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/my-website/docs/providers/nscale.md b/docs/my-website/docs/providers/nscale.md index 03ba090001cc..68694c91821d 100644 --- a/docs/my-website/docs/providers/nscale.md +++ b/docs/my-website/docs/providers/nscale.md @@ -1,5 +1,5 @@ -# NScale -[NScale docs](https://docs.nscale.com/docs/getting-started/overview) +# NScale (EU Sovereign) +**[NScale docs](https://docs.nscale.com/docs/getting-started/overview)** NScale is a European-domiciled full-stack AI cloud platform that allows you to scale your workloads securely, sustainably and cost-effectively - without sacrificing control. It provides production-grade reliability for serverless deployments of LLMs with full data sovereignty and compliance baked in. diff --git a/tests/litellm/litellm_core_utils/test_token_counter.py b/tests/litellm/litellm_core_utils/test_token_counter.py index 7091a8d4b881..9f5b7b695004 100644 --- a/tests/litellm/litellm_core_utils/test_token_counter.py +++ b/tests/litellm/litellm_core_utils/test_token_counter.py @@ -8,10 +8,9 @@ import pytest -# Add project root to Python path -project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) -sys.path.insert(0, project_root) - +sys.path.insert( + 0, os.path.abspath("../../..") +) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch from messages_with_counts import ( @@ -259,7 +258,7 @@ def test_gpt_vision_token_counting(): { "role": "user", "content": [ - {"type": "text", "text": "What's in this image?"}, + {"type": "text", "text": "What’s in this image?"}, { "type": "image_url", "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", @@ -296,6 +295,7 @@ def test_load_test_token_counter(model, large_text): start_time = time.time() for _ in range(10): _ = token_counter(model=model, messages=messages) + # enc.encode("".join(m["content"] for m in messages)) end_time = time.time() diff --git a/tests/local_testing/test_router.py b/tests/local_testing/test_router.py index 2131e68b3d4d..7564fba555ff 100644 --- a/tests/local_testing/test_router.py +++ b/tests/local_testing/test_router.py @@ -2789,4 +2789,5 @@ def test_router_get_model_group_info(): assert model_group_info is not None assert model_group_info.model_group == "gpt-4" assert model_group_info.input_cost_per_token > 0 + assert model_group_info.output_cost_per_token > 0 From 3dd8cd3ab655869a79184e71b0fa32c0a50d9cc2 Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Wed, 7 May 2025 23:32:55 +0100 Subject: [PATCH 6/8] Remove redundant null tokens from model cost map --- ...odel_prices_and_context_window_backup.json | 42 ------------------- model_prices_and_context_window.json | 42 ------------------- 2 files changed, 84 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 6867a7f1db3d..8bf06e61b2c6 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -12199,9 +12199,6 @@ "mode": "chat" }, "nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 9e-8, "output_cost_per_token": 2.9e-7, "litellm_provider": "nscale", @@ -12209,9 +12206,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/Qwen2.5-Coder-3B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1e-8, "output_cost_per_token": 3e-8, "litellm_provider": "nscale", @@ -12219,9 +12213,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/Qwen2.5-Coder-7B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1e-8, "output_cost_per_token": 3e-8, "litellm_provider": "nscale", @@ -12229,9 +12220,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/Qwen2.5-Coder-32B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 6e-8, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", @@ -12239,9 +12227,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/QwQ-32B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1.8e-7, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", @@ -12249,9 +12234,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 3.75e-7, "output_cost_per_token": 3.75e-7, "litellm_provider": "nscale", @@ -12260,9 +12242,6 @@ "notes": "Pricing listed as $0.75/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-8B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 2.5e-8, "output_cost_per_token": 2.5e-8, "litellm_provider": "nscale", @@ -12271,9 +12250,6 @@ "notes": "Pricing listed as $0.05/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 9e-8, "output_cost_per_token": 9e-8, "litellm_provider": "nscale", @@ -12282,9 +12258,6 @@ "notes": "Pricing listed as $0.18/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 2e-7, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", @@ -12293,9 +12266,6 @@ "notes": "Pricing listed as $0.40/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 7e-8, "output_cost_per_token": 7e-8, "litellm_provider": "nscale", @@ -12304,9 +12274,6 @@ "notes": "Pricing listed as $0.14/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1.5e-7, "output_cost_per_token": 1.5e-7, "litellm_provider": "nscale", @@ -12315,9 +12282,6 @@ "notes": "Pricing listed as $0.30/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/mistralai/mixtral-8x22b-instruct-v0.1": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 6e-7, "output_cost_per_token": 6e-7, "litellm_provider": "nscale", @@ -12326,9 +12290,6 @@ "notes": "Pricing listed as $1.20/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/meta-llama/Llama-3.1-8B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 3e-8, "output_cost_per_token": 3e-8, "litellm_provider": "nscale", @@ -12337,9 +12298,6 @@ "notes": "Pricing listed as $0.06/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/meta-llama/Llama-3.3-70B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 2e-7, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index e1963c707cb8..42092d34c943 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -12199,9 +12199,6 @@ "mode": "chat" }, "nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 9e-8, "output_cost_per_token": 2.9e-7, "litellm_provider": "nscale", @@ -12209,9 +12206,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/Qwen2.5-Coder-3B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1e-8, "output_cost_per_token": 3e-8, "litellm_provider": "nscale", @@ -12219,9 +12213,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/Qwen2.5-Coder-7B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1e-8, "output_cost_per_token": 3e-8, "litellm_provider": "nscale", @@ -12229,9 +12220,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/Qwen2.5-Coder-32B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 6e-8, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", @@ -12239,9 +12227,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/Qwen/QwQ-32B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1.8e-7, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", @@ -12249,9 +12234,6 @@ "source": "https://docs.nscale.com/docs/inference/serverless-models/current#chat-models" }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 3.75e-7, "output_cost_per_token": 3.75e-7, "litellm_provider": "nscale", @@ -12260,9 +12242,6 @@ "notes": "Pricing listed as $0.75/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-8B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 2.5e-8, "output_cost_per_token": 2.5e-8, "litellm_provider": "nscale", @@ -12271,9 +12250,6 @@ "notes": "Pricing listed as $0.05/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 9e-8, "output_cost_per_token": 9e-8, "litellm_provider": "nscale", @@ -12282,9 +12258,6 @@ "notes": "Pricing listed as $0.18/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 2e-7, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", @@ -12293,9 +12266,6 @@ "notes": "Pricing listed as $0.40/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 7e-8, "output_cost_per_token": 7e-8, "litellm_provider": "nscale", @@ -12304,9 +12274,6 @@ "notes": "Pricing listed as $0.14/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 1.5e-7, "output_cost_per_token": 1.5e-7, "litellm_provider": "nscale", @@ -12315,9 +12282,6 @@ "notes": "Pricing listed as $0.30/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/mistralai/mixtral-8x22b-instruct-v0.1": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 6e-7, "output_cost_per_token": 6e-7, "litellm_provider": "nscale", @@ -12326,9 +12290,6 @@ "notes": "Pricing listed as $1.20/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/meta-llama/Llama-3.1-8B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 3e-8, "output_cost_per_token": 3e-8, "litellm_provider": "nscale", @@ -12337,9 +12298,6 @@ "notes": "Pricing listed as $0.06/1M tokens total. Assumed 50/50 split for input/output." }, "nscale/meta-llama/Llama-3.3-70B-Instruct": { - "max_tokens": null, - "max_input_tokens": null, - "max_output_tokens": null, "input_cost_per_token": 2e-7, "output_cost_per_token": 2e-7, "litellm_provider": "nscale", From 33c0f9c3659c859933b61ef347a7dc95ca6e090a Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Thu, 8 May 2025 16:04:38 +0100 Subject: [PATCH 7/8] Address PR review comments for doc updates --- docs/my-website/docs/providers/nscale.md | 177 +++++++++++++++++------ docs/my-website/sidebars.js | 2 +- 2 files changed, 136 insertions(+), 43 deletions(-) diff --git a/docs/my-website/docs/providers/nscale.md b/docs/my-website/docs/providers/nscale.md index 68694c91821d..5ebd948db624 100644 --- a/docs/my-website/docs/providers/nscale.md +++ b/docs/my-website/docs/providers/nscale.md @@ -1,7 +1,48 @@ -# NScale (EU Sovereign) -**[NScale docs](https://docs.nscale.com/docs/getting-started/overview)** +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; -NScale is a European-domiciled full-stack AI cloud platform that allows you to scale your workloads securely, sustainably and cost-effectively - without sacrificing control. It provides production-grade reliability for serverless deployments of LLMs with full data sovereignty and compliance baked in. +# Nscale (EU Sovereign) + +| Property | Details | +|-------|-------| +| Description | European-domiciled full-stack AI cloud platform for LLMs and image generation. | +| Provider Route on LiteLLM | `nscale/` | +| Supported Endpoints | `/chat/completions`, `/images/generations` | +| API Reference | [Nscale docs](https://docs.nscale.com/docs/getting-started/overview) | + +## Required Variables + +```python showLineNumbers title="Environment Variables" +os.environ["NSCALE_API_KEY"] = "" # your Nscale API key +``` + +## Supported Models + +### Chat Models + +| Model Name | Description | Input Cost | Output Cost | +|------------|-------------|------------|-------------| +| nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct | 17B parameter model | $0.09/M tokens | $0.29/M tokens | +| nscale/Qwen/Qwen2.5-Coder-3B-Instruct | 3B parameter coding model | $0.01/M tokens | $0.03/M tokens | +| nscale/Qwen/Qwen2.5-Coder-7B-Instruct | 7B parameter coding model | $0.01/M tokens | $0.03/M tokens | +| nscale/Qwen/Qwen2.5-Coder-32B-Instruct | 32B parameter coding model | $0.06/M tokens | $0.20/M tokens | +| nscale/Qwen/QwQ-32B | 32B parameter model | $0.18/M tokens | $0.20/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B | 70B parameter distilled model | $0.375/M tokens | $0.375/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-8B | 8B parameter distilled model | $0.025/M tokens | $0.025/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B | 1.5B parameter distilled model | $0.09/M tokens | $0.09/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B | 7B parameter distilled model | $0.20/M tokens | $0.20/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B | 14B parameter distilled model | $0.07/M tokens | $0.07/M tokens | +| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B | 32B parameter distilled model | $0.15/M tokens | $0.15/M tokens | +| nscale/mistralai/mixtral-8x22b-instruct-v0.1 | Mixtral 8x22B model | $0.60/M tokens | $0.60/M tokens | +| nscale/meta-llama/Llama-3.1-8B-Instruct | 8B parameter model | $0.03/M tokens | $0.03/M tokens | +| nscale/meta-llama/Llama-3.3-70B-Instruct | 70B parameter model | $0.20/M tokens | $0.20/M tokens | + +### Image Generation Models + +| Model Name | Description | Cost per Pixel | +|------------|-------------|----------------| +| nscale/black-forest-labs/FLUX.1-schnell | Fast image generation model | $0.0000000013 | +| nscale/stabilityai/stable-diffusion-xl-base-1.0 | SDXL base model | $0.000000003 | ## Key Features - **EU Sovereign**: Full data sovereignty and compliance with European regulations @@ -10,33 +51,29 @@ NScale is a European-domiciled full-stack AI cloud platform that allows you to s - **No Setup Required**: Instant access to compute without infrastructure management - **Full Control**: Your data remains private and isolated -## API Key -```python -# env variable -os.environ['NSCALE_API_KEY'] -``` +## Usage - LiteLLM Python SDK + +### Text Generation -## Sample Usage - Text Generation -```python +```python showLineNumbers title="Nscale Text Generation" from litellm import completion import os -os.environ['NSCALE_API_KEY'] = "" +os.environ["NSCALE_API_KEY"] = "" # your Nscale API key response = completion( - model="nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", - messages=[ - {"role": "user", "content": "What is LiteLLM?"} - ] + model="nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[{"role": "user", "content": "What is LiteLLM?"}] ) print(response) ``` -## Sample Usage - Image Generation -```python +### Image Generation + +```python showLineNumbers title="Nscale Image Generation" from litellm import image_generation import os -os.environ['NSCALE_API_KEY'] = "" +os.environ["NSCALE_API_KEY"] = "" # your Nscale API key response = image_generation( model="nscale/stabilityai/stable-diffusion-xl-base-1.0", prompt="A beautiful sunset over mountains", @@ -46,33 +83,89 @@ response = image_generation( print(response) ``` -## Supported Models +## Usage - LiteLLM Proxy -### Chat Models +Add the following to your LiteLLM Proxy configuration file: -| Model Name | Description | Input Cost | Output Cost | -|------------|-------------|------------|-------------| -| nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct | 17B parameter model | $0.09/M tokens | $0.29/M tokens | -| nscale/Qwen/Qwen2.5-Coder-3B-Instruct | 3B parameter coding model | $0.01/M tokens | $0.03/M tokens | -| nscale/Qwen/Qwen2.5-Coder-7B-Instruct | 7B parameter coding model | $0.01/M tokens | $0.03/M tokens | -| nscale/Qwen/Qwen2.5-Coder-32B-Instruct | 32B parameter coding model | $0.06/M tokens | $0.20/M tokens | -| nscale/Qwen/QwQ-32B | 32B parameter model | $0.18/M tokens | $0.20/M tokens | -| nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B | 70B parameter distilled model | $0.375/M tokens | $0.375/M tokens | -| nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-8B | 8B parameter distilled model | $0.025/M tokens | $0.025/M tokens | -| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B | 1.5B parameter distilled model | $0.09/M tokens | $0.09/M tokens | -| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B | 7B parameter distilled model | $0.20/M tokens | $0.20/M tokens | -| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B | 14B parameter distilled model | $0.07/M tokens | $0.07/M tokens | -| nscale/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B | 32B parameter distilled model | $0.15/M tokens | $0.15/M tokens | -| nscale/mistralai/mixtral-8x22b-instruct-v0.1 | Mixtral 8x22B model | $0.60/M tokens | $0.60/M tokens | -| nscale/meta-llama/Llama-3.1-8B-Instruct | 8B parameter model | $0.03/M tokens | $0.03/M tokens | -| nscale/meta-llama/Llama-3.3-70B-Instruct | 70B parameter model | $0.20/M tokens | $0.20/M tokens | +```yaml showLineNumbers title="config.yaml" +model_list: + - model_name: nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct + litellm_params: + model: nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct + api_key: os.environ/NSCALE_API_KEY + - model_name: nscale/meta-llama/Llama-3.3-70B-Instruct + litellm_params: + model: nscale/meta-llama/Llama-3.3-70B-Instruct + api_key: os.environ/NSCALE_API_KEY + - model_name: nscale/stabilityai/stable-diffusion-xl-base-1.0 + litellm_params: + model: nscale/stabilityai/stable-diffusion-xl-base-1.0 + api_key: os.environ/NSCALE_API_KEY +``` -### Image Generation Models +Start your LiteLLM Proxy server: -| Model Name | Description | Cost per Pixel | -|------------|-------------|----------------| -| nscale/black-forest-labs/FLUX.1-schnell | Fast image generation model | $0.0000000013 | -| nscale/stabilityai/stable-diffusion-xl-base-1.0 | SDXL base model | $0.000000003 | +```bash showLineNumbers title="Start LiteLLM Proxy" +litellm --config config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + + + + +```python showLineNumbers title="Nscale via Proxy - Non-streaming" +from openai import OpenAI + +# Initialize client with your proxy URL +client = OpenAI( + base_url="http://localhost:4000", # Your proxy URL + api_key="your-proxy-api-key" # Your proxy API key +) + +# Non-streaming response +response = client.chat.completions.create( + model="nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[{"role": "user", "content": "What is LiteLLM?"}] +) + +print(response.choices[0].message.content) +``` + + + + + +```python showLineNumbers title="Nscale via Proxy - LiteLLM SDK" +import litellm + +# Configure LiteLLM to use your proxy +response = litellm.completion( + model="litellm_proxy/nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + messages=[{"role": "user", "content": "What is LiteLLM?"}], + api_base="http://localhost:4000", + api_key="your-proxy-api-key" +) + +print(response.choices[0].message.content) +``` + + + + + +```bash showLineNumbers title="Nscale via Proxy - cURL" +curl http://localhost:4000/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer your-proxy-api-key" \ + -d '{ + "model": "nscale/meta-llama/Llama-4-Scout-17B-16E-Instruct", + "messages": [{"role": "user", "content": "What is LiteLLM?"}] + }' +``` + + + ## Getting Started 1. Create an account at [console.nscale.com](https://console.nscale.com) @@ -81,5 +174,5 @@ print(response) 4. Start making API calls using LiteLLM ## Additional Resources -- [NScale Documentation](https://docs.nscale.com/docs/getting-started/overview) +- [Nscale Documentation](https://docs.nscale.com/docs/getting-started/overview) - [Blog: Sovereign Serverless](https://www.nscale.com/blog/sovereign-serverless-how-we-designed-full-isolation-without-sacrificing-performance) \ No newline at end of file diff --git a/docs/my-website/sidebars.js b/docs/my-website/sidebars.js index 9c2440ca4f24..b8e8b5929a43 100644 --- a/docs/my-website/sidebars.js +++ b/docs/my-website/sidebars.js @@ -237,7 +237,7 @@ const sidebars = { "providers/watsonx", "providers/predibase", "providers/nvidia_nim", - { type: "doc", id: "providers/nscale", label: "NScale (EU Sovereign)" }, + { type: "doc", id: "providers/nscale", label: "Nscale (EU Sovereign)" }, "providers/xai", "providers/lm_studio", "providers/cerebras", From 70725df7dab2516a0f0b7a53ac096bafc6b51e1f Mon Sep 17 00:00:00 2001 From: Tom Matthews Date: Thu, 8 May 2025 16:42:32 +0100 Subject: [PATCH 8/8] Revert changes to large text --- tests/conftest.py | 121 ------------------ tests/large_text.py | 112 ++++++++++++++++ .../litellm_core_utils/test_token_counter.py | 6 +- tests/local_testing/test_router.py | 23 ++-- .../tests/load_test_completion.py | 1 + tests/test_fallbacks.py | 1 + 6 files changed, 128 insertions(+), 136 deletions(-) delete mode 100644 tests/conftest.py create mode 100644 tests/large_text.py diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 7468fe38ef29..000000000000 --- a/tests/conftest.py +++ /dev/null @@ -1,121 +0,0 @@ -import pytest -import textwrap - - -@pytest.fixture -def large_text() -> str: - text = textwrap.dedent( - """ - Alexander the Great - This article is about the ancient king of Macedonia. For other uses, see Alexander the Great (disambiguation). - Alexander III of Macedon (Ancient Greek: Ἀλέξανδρος, romanized: Alexandros; 20/21 July 356 BC – 10/11 June 323 BC), most commonly known as Alexander the Great,[c] was a king of the ancient Greek kingdom of Macedon.[d] He succeeded his father Philip II to the throne in 336 BC at the age of 20 and spent most of his ruling years conducting a lengthy military campaign throughout Western Asia, Central Asia, parts of South Asia, and Egypt. By the age of 30, he had created one of the largest empires in history, stretching from Greece to northwestern India.[1] He was undefeated in battle and is widely considered to be one of history's greatest and most successful military commanders.[2][3] - - Until the age of 16, Alexander was tutored by Aristotle. In 335 BC, shortly after his assumption of kingship over Macedon, he campaigned in the Balkans and reasserted control over Thrace and parts of Illyria before marching on the city of Thebes, which was subsequently destroyed in battle. Alexander then led the League of Corinth, and used his authority to launch the pan-Hellenic project envisaged by his father, assuming leadership over all Greeks in their conquest of Persia.[4][5] - - In 334 BC, he invaded the Achaemenid Persian Empire and began a series of campaigns that lasted for 10 years. Following his conquest of Asia Minor, Alexander broke the power of Achaemenid Persia in a series of decisive battles, including those at Issus and Gaugamela; he subsequently overthrew Darius III and conquered the Achaemenid Empire in its entirety.[e] After the fall of Persia, the Macedonian Empire held a vast swath of territory between the Adriatic Sea and the Indus River. Alexander endeavored to reach the "ends of the world and the Great Outer Sea" and invaded India in 326 BC, achieving an important victory over Porus, an ancient Indian king of present-day Punjab, at the Battle of the Hydaspes. Due to the demand of his homesick troops, he eventually turned back at the Beas River and later died in 323 BC in Babylon, the city of Mesopotamia that he had planned to establish as his empire's capital. Alexander's death left unexecuted an additional series of planned military and mercantile campaigns that would have begun with a Greek invasion of Arabia. In the years following his death, a series of civil wars broke out across the Macedonian Empire, eventually leading to its disintegration at the hands of the Diadochi. - - With his death marking the start of the Hellenistic period, Alexander's legacy includes the cultural diffusion and syncretism that his conquests engendered, such as Greco-Buddhism and Hellenistic Judaism. He founded more than twenty cities, with the most prominent being the city of Alexandria in Egypt. Alexander's settlement of Greek colonists and the resulting spread of Greek culture led to the overwhelming dominance of Hellenistic civilization and influence as far east as the Indian subcontinent. The Hellenistic period developed through the Roman Empire into modern Western culture; the Greek language became the lingua franca of the region and was the predominant language of the Byzantine Empire up until its collapse in the mid-15th century AD. Alexander became legendary as a classical hero in the mould of Achilles, featuring prominently in the historical and mythical traditions of both Greek and non-Greek cultures. His military achievements and unprecedented enduring successes in battle made him the measure against which many later military leaders would compare themselves,[f] and his tactics remain a significant subject of study in military academies worldwide.[6] Legends of Alexander's exploits coalesced into the third-century Alexander Romance which, in the premodern period, went through over one hundred recensions, translations, and derivations and was translated into almost every European vernacular and every language of the Islamic world.[7] After the Bible, it was the most popular form of European literature.[8] - - Early life - - Lineage and childhood - - Alexander III was born in Pella, the capital of the Kingdom of Macedon,[9] on the sixth day of the ancient Greek month of Hekatombaion, which probably corresponds to 20 July 356 BC (although the exact date is uncertain).[10][11] He was the son of the erstwhile king of Macedon, Philip II, and his fourth wife, Olympias (daughter of Neoptolemus I, king of Epirus).[12][g] Although Philip had seven or eight wives, Olympias was his principal wife for some time, likely because she gave birth to Alexander.[13] - - Several legends surround Alexander's birth and childhood.[14] According to the ancient Greek biographer Plutarch, on the eve of the consummation of her marriage to Philip, Olympias dreamed that her womb was struck by a thunderbolt that caused a flame to spread "far and wide" before dying away. Sometime after the wedding, Philip is said to have seen himself, in a dream, securing his wife's womb with a seal engraved with a lion's image.[15] Plutarch offered a variety of interpretations for these dreams: that Olympias was pregnant before her marriage, indicated by the sealing of her womb; or that Alexander's father was Zeus. Ancient commentators were divided about whether the ambitious Olympias promulgated the story of Alexander's divine parentage, variously claiming that she had told Alexander, or that she dismissed the suggestion as impious.[15] - - On the day Alexander was born, Philip was preparing a siege on the city of Potidea on the peninsula of Chalcidice. That same day, Philip received news that his general Parmenion had defeated the combined Illyrian and Paeonian armies and that his horses had won at the Olympic Games. It was also said that on this day, the Temple of Artemis in Ephesus, one of the Seven Wonders of the World, burnt down. This led Hegesias of Magnesia to say that it had burnt down because Artemis was away, attending the birth of Alexander.[16] Such legends may have emerged when Alexander was king, and possibly at his instigation, to show that he was superhuman and destined for greatness from conception.[14] - - In his early years, Alexander was raised by a nurse, Lanike, sister of Alexander's future general Cleitus the Black. Later in his childhood, Alexander was tutored by the strict Leonidas, a relative of his mother, and by Lysimachus of Acarnania.[17] Alexander was raised in the manner of noble Macedonian youths, learning to read, play the lyre, ride, fight, and hunt.[18] When Alexander was ten years old, a trader from Thessaly brought Philip a horse, which he offered to sell for thirteen talents. The horse refused to be mounted, and Philip ordered it away. Alexander, however, detecting the horse's fear of its own shadow, asked to tame the horse, which he eventually managed.[14] Plutarch stated that Philip, overjoyed at this display of courage and ambition, kissed his son tearfully, declaring: "My boy, you must find a kingdom big enough for your ambitions. Macedon is too small for you", and bought the horse for him.[19] Alexander named it Bucephalas, meaning "ox-head". Bucephalas carried Alexander as far as India. When the animal died (because of old age, according to Plutarch, at age 30), Alexander named a city after him, Bucephala.[20] - - Education - - When Alexander was 13, Philip began to search for a tutor, and considered such academics as Isocrates and Speusippus, the latter offering to resign from his stewardship of the Academy to take up the post. In the end, Philip chose Aristotle and provided the Temple of the Nymphs at Mieza as a classroom. In return for teaching Alexander, Philip agreed to rebuild Aristotle's hometown of Stageira, which Philip had razed, and to repopulate it by buying and freeing the ex-citizens who were slaves, or pardoning those who were in exile.[21] - - Mieza was like a boarding school for Alexander and the children of Macedonian nobles, such as Ptolemy, Hephaistion, and Cassander. Many of these students would become his friends and future generals, and are often known as the "Companions". Aristotle taught Alexander and his companions about medicine, philosophy, morals, religion, logic, and art. Under Aristotle's tutelage, Alexander developed a passion for the works of Homer, and in particular the Iliad; Aristotle gave him an annotated copy, which Alexander later carried on his campaigns.[22] Alexander was able to quote Euripides from memory.[23] - - During his youth, Alexander was also acquainted with Persian exiles at the Macedonian court, who received the protection of Philip II for several years as they opposed Artaxerxes III.[24][25][26] Among them were Artabazos II and his daughter Barsine, possible future mistress of Alexander, who resided at the Macedonian court from 352 to 342 BC, as well as Amminapes, future satrap of Alexander, or a Persian nobleman named Sisines.[24][27][28][29] This gave the Macedonian court a good knowledge of Persian issues, and may even have influenced some of the innovations in the management of the Macedonian state.[27] - - Suda writes that Anaximenes of Lampsacus was one of Alexander's teachers, and that Anaximenes also accompanied Alexander on his campaigns.[30] - - Heir of Philip II - - Regency and ascent of Macedon - - Main articles: Philip II of Macedon and Rise of Macedon - Further information: History of Macedonia (ancient kingdom) - At the age of 16, Alexander's education under Aristotle ended. Philip II had waged war against the Thracians to the north, which left Alexander in charge as regent and heir apparent.[14] During Philip's absence, the Thracian tribe of Maedi revolted against Macedonia. Alexander responded quickly and drove them from their territory. The territory was colonized, and a city, named Alexandropolis, was founded.[31] - - Upon Philip's return, Alexander was dispatched with a small force to subdue the revolts in southern Thrace. Campaigning against the Greek city of Perinthus, Alexander reportedly saved his father's life. Meanwhile, the city of Amphissa began to work lands that were sacred to Apollo near Delphi, a sacrilege that gave Philip the opportunity to further intervene in Greek affairs. While Philip was occupied in Thrace, Alexander was ordered to muster an army for a campaign in southern Greece. Concerned that other Greek states might intervene, Alexander made it look as though he was preparing to attack Illyria instead. During this turmoil, the Illyrians invaded Macedonia, only to be repelled by Alexander.[32] - - Philip and his army joined his son in 338 BC, and they marched south through Thermopylae, taking it after stubborn resistance from its Theban garrison. They went on to occupy the city of Elatea, only a few days' march from both Athens and Thebes. The Athenians, led by Demosthenes, voted to seek alliance with Thebes against Macedonia. Both Athens and Philip sent embassies to win Thebes's favour, but Athens won the contest.[33] Philip marched on Amphissa (ostensibly acting on the request of the Amphictyonic League), capturing the mercenaries sent there by Demosthenes and accepting the city's surrender. Philip then returned to Elatea, sending a final offer of peace to Athens and Thebes, who both rejected it.[34] - - As Philip marched south, his opponents blocked him near Chaeronea, Boeotia. During the ensuing Battle of Chaeronea, Philip commanded the right wing and Alexander the left, accompanied by a group of Philip's trusted generals. According to the ancient sources, the two sides fought bitterly for some time. Philip deliberately commanded his troops to retreat, counting on the untested Athenian hoplites to follow, thus breaking their line. Alexander was the first to break the Theban lines, followed by Philip's generals. Having damaged the enemy's cohesion, Philip ordered his troops to press forward and quickly routed them. With the Athenians lost, the Thebans were surrounded. Left to fight alone, they were defeated.[35] - - After the victory at Chaeronea, Philip and Alexander marched unopposed into the Peloponnese, welcomed by all cities; however, when they reached Sparta, they were refused, but did not resort to war.[36] At Corinth, Philip established a "Hellenic Alliance" (modelled on the old anti-Persian alliance of the Greco-Persian Wars), which included most Greek city-states except Sparta. Philip was then named Hegemon (often translated as "Supreme Commander") of this league (known by modern scholars as the League of Corinth), and announced his plans to attack the Persian Empire.[37][38] - - Exile and return - - When Philip returned to Pella, he fell in love with and married Cleopatra Eurydice in 338 BC,[39] the niece of his general Attalus.[40] The marriage made Alexander's position as heir less secure, since any son of Cleopatra Eurydice would be a fully Macedonian heir, while Alexander was only half-Macedonian.[41] During the wedding banquet, a drunken Attalus publicly prayed to the gods that the union would produce a legitimate heir.[40] - - At the wedding of Cleopatra, whom Philip fell in love with and married, she being much too young for him, her uncle Attalus in his drink desired the Macedonians would implore the gods to give them a lawful successor to the kingdom by his niece. This so irritated Alexander, that throwing one of the cups at his head, "You villain," said he, "what, am I then a bastard?" Then Philip, taking Attalus's part, rose up and would have run his son through; but by good fortune for them both, either his over-hasty rage, or the wine he had drunk, made his foot slip, so that he fell down on the floor. At which Alexander reproachfully insulted over him: "See there," said he, "the man who makes preparations to pass out of Europe into Asia, overturned in passing from one seat to another." - - — Plutarch, describing the feud at Philip's wedding.[42]none - In 337 BC, Alexander fled Macedon with his mother, dropping her off with her brother, King Alexander I of Epirus in Dodona, capital of the Molossians.[43] He continued to Illyria,[43] where he sought refuge with one or more Illyrian kings, perhaps with Glaucias, and was treated as a guest, despite having defeated them in battle a few years before.[44] However, it appears Philip never intended to disown his politically and militarily trained son.[43] Accordingly, Alexander returned to Macedon after six months due to the efforts of a family friend, Demaratus, who mediated between the two parties.[45] - - In the following year, the Persian satrap (governor) of Caria, Pixodarus, offered his eldest daughter to Alexander's half-brother, Philip Arrhidaeus.[43] Olympias and several of Alexander's friends suggested this showed Philip intended to make Arrhidaeus his heir.[43] Alexander reacted by sending an actor, Thessalus of Corinth, to tell Pixodarus that he should not offer his daughter's hand to an illegitimate son, but instead to Alexander. When Philip heard of this, he stopped the negotiations and scolded Alexander for wishing to marry the daughter of a Carian, explaining that he wanted a better bride for him.[43] Philip exiled four of Alexander's friends, Harpalus, Nearchus, Ptolemy and Erigyius, and had the Corinthians bring Thessalus to him in chains.[46] - - King of Macedon - - Accession - - Further information: Government of Macedonia (ancient kingdom) - In summer 336 BC, while at Aegae attending the wedding of his daughter Cleopatra to Olympias's brother, Alexander I of Epirus, Philip was assassinated by the captain of his bodyguards, Pausanias.[h] As Pausanias tried to escape, he tripped over a vine and was killed by his pursuers, including two of Alexander's companions, Perdiccas and Leonnatus. Alexander was proclaimed king on the spot by the nobles and army at the age of 20.[47][48][49] - - Consolidation of power - - Alexander began his reign by eliminating potential rivals to the throne. He had his cousin, the former Amyntas IV, executed.[51] He also had two Macedonian princes from the region of Lyncestis killed for having been involved in his father's assassination, but spared a third, Alexander Lyncestes. Olympias had Cleopatra Eurydice, and Europa, her daughter by Philip, burned alive. When Alexander learned about this, he was furious. Alexander also ordered the murder of Attalus,[51] who was in command of the advance guard of the army in Asia Minor and Cleopatra's uncle.[52] - - Attalus was at that time corresponding with Demosthenes, regarding the possibility of defecting to Athens. Attalus also had severely insulted Alexander, and following Cleopatra's murder, Alexander may have considered him too dangerous to be left alive.[52] Alexander spared Arrhidaeus, who was by all accounts mentally disabled, possibly as a result of poisoning by Olympias.[47][49][53] - - News of Philip's death roused many states into revolt, including Thebes, Athens, Thessaly, and the Thracian tribes north of Macedon. When news of the revolts reached Alexander, he responded quickly. Though advised to use diplomacy, Alexander mustered 3,000 Macedonian cavalry and rode south towards Thessaly. He found the Thessalian army occupying the pass between Mount Olympus and Mount Ossa, and ordered his men to ride over Mount Ossa. When the Thessalians awoke the next day, they found Alexander in their rear and promptly surrendered, adding their cavalry to Alexander's force. He then continued south towards the Peloponnese.[54] - - Alexander stopped at Thermopylae, where he was recognized as the leader of the Amphictyonic League before heading south to Corinth. Athens sued for peace and Alexander pardoned the rebels. The famous encounter between Alexander and Diogenes the Cynic occurred during Alexander's stay in Corinth. When Alexander asked Diogenes what he could do for him, the philosopher disdainfully asked Alexander to stand a little to the side, as he was blocking the sunlight.[55] This reply apparently delighted Alexander, who is reported to have said "But verily, if I were not Alexander, I would like to be Diogenes."[56] At Corinth, Alexander took the title of Hegemon ("leader") and, like Philip, was appointed commander for the coming war against Persia. He also received news of a Thracian uprising.[57] - - Balkan campaign - - Main article: Alexander's Balkan campaign - Before crossing to Asia, Alexander wanted to safeguard his northern borders. In the spring of 335 BC, he advanced to suppress several revolts. Starting from Amphipolis, he travelled east into the country of the "Independent Thracians"; and at Mount Haemus, the Macedonian army attacked and defeated the Thracian forces manning the heights.[58] The Macedonians marched into the country of the Triballi, and defeated their army near the Lyginus river[59] (a tributary of the Danube). Alexander then marched for three days to the Danube, encountering the Getae tribe on the opposite shore. Crossing the river at night, he surprised them and forced their army to retreat after the first cavalry skirmish.[60] - - News then reached Alexander that the Illyrian chieftain Cleitus and King Glaukias of the Taulantii were in open revolt against his authority. Marching west into Illyria, Alexander defeated each in turn, forcing the two rulers to flee with their troops. With these victories, he secured his northern frontier.[61] - - Destruction of Thebes - - While Alexander campaigned north, the Thebans and Athenians rebelled once again. Alexander immediately headed south.[62] While the other cities again hesitated, Thebes decided to fight. The Theban resistance was ineffective, and Alexander razed the city and divided its territory between the other Boeotian cities. The end of Thebes cowed Athens, leaving all of Greece temporarily at peace.[62] Alexander then set out on his Asian campaign, leaving Antipater as regent.[63] - - Conquest of the Achaemenid Persian Empire - - Main articles: Wars of Alexander the Great and Chronology of the expedition of Alexander the Great into Asia - Asia Minor - - Further information: Battle of the Granicus, Siege of Halicarnassus, and Siege of Miletus - After his victory at the Battle of Chaeronea (338 BC), Philip II began the work of establishing himself as hēgemṓn (Greek: ἡγεμών) of a league which according to Diodorus was to wage a campaign against the Persians for the sundry grievances Greece suffered in 480 and free the Greek cities of the western coast and islands from Achaemenid rule. In 336 he sent Parmenion, Amyntas, Andromenes, Attalus, and an army of 10,000 men into Anatolia to make preparations for an invasion.[64][65] At first, all went well. The Greek cities on the western coast of Anatolia revolted until the news arrived that Philip had been murdered and had been succeeded by his young son Alexander. The Macedonians were demoralized by Philip's death and were subsequently defeated near Magnesia by the Achaemenids under the command of the mercenary Memnon of Rhodes.[64][65] - - Taking over the invasion project of Philip II, Alexander's army crossed the Hellespont in 334 BC with approximately 48,100 soldiers, 6,100 cavalry and a fleet of 120 ships with crews numbering 38,000,[62] drawn from Macedon and various Greek city-states, mercenaries, and feudally raised soldiers from Thrace, Paionia, and Illyria.[66][i] He showed his intent to conquer the entirety of the Persian Empire by throwing a spear into Asian soil and saying he accepted Asia as a gift from the gods. This also showed Alexander's eagerness to fight, in contrast to his father's preference for diplomacy.[62] - - After an initial victory against Persian forces at the Battle of the Granicus, Alexander accepted the surrender of the Persian provincial capital and treasury of Sardis; he then proceeded along the Ionian coast, granting autonomy and democracy to the cities. Miletus, held by Achaemenid forces, required a delicate siege operation, with Persian naval forces nearby. Further south, at Halicarnassus, in Caria, Alexander successfully waged his first large-scale siege, eventually forcing his opponents, the mercenary captain Memnon of Rhodes and the Persian satrap of Caria, Orontobates, to withdraw by sea.[67] Alexander left the government of Caria to a member of the Hecatomnid dynasty, Ada, who adopted Alexander.[68] - - From Halicarnassus, Alexander proceeded into mountainous Lycia and the Pamphylian plain, asserting control over all coastal cities to deny the Persians naval bases. From Pamphylia onwards the coast held no major ports and Alexander moved inland. At Termessos, Alexander humbled but did not storm the Pisidian city.[69] At the ancient Phrygian capital of Gordium, Alexander "undid" the hitherto unsolvable Gordian Knot, a feat said to await the future "king of Asia".[70] According to the story, Alexander proclaimed that it did not matter how the knot was undone and hacked it apart with his sword.[71] - - The Levant and Syria - - Further information: Battle of Issus and Siege of Tyre (332 BC) - In spring 333 BC, Alexander crossed the Taurus into Cilicia. After a long pause due to an illness, he marched on towards Syria. Though outmanoeuvered by Darius's significantly larger army, he marched back to Cilicia, where he defeated Darius at Issus. Darius fled the battle, causing his army to collapse, and left behind his wife, his two daughters, his mother Sisygambis, and a fabulous treasure.[72] He offered a peace treaty that included the lands he had already lost, and a ransom of 10,000 talents for his family. Alexander replied that since he was now king of Asia, it was he alone who decided territorial divisions.[73] Alexander proceeded to take possession of Syria, and most of the coast of the Levant.[68] In the following year, 332 BC, he was forced to attack Tyre, which he captured after a long and difficult siege.[74][75] The men of military age were massacred and the women and children sold into slavery.[76] - - Egypt - - Further information: Siege of Gaza (332 BCE) - When Alexander destroyed Tyre, most of the towns on the route to Egypt quickly capitulated. However, Alexander was met with resistance at Gaza. The stronghold was heavily fortified and built on a hill, requiring a siege. When "his engineers pointed out to him that because of the height of the mound it would be impossible... this encouraged Alexander all the more to make the attempt".[77] After three unsuccessful assaults, the stronghold fell, but not before Alexander had received a serious shoulder wound. As in Tyre, men of military age were put to the sword and the women and children were sold into slavery.[78] - """ - ) - return text diff --git a/tests/large_text.py b/tests/large_text.py new file mode 100644 index 000000000000..86904a6d148f --- /dev/null +++ b/tests/large_text.py @@ -0,0 +1,112 @@ +text = """ +Alexander the Great +This article is about the ancient king of Macedonia. For other uses, see Alexander the Great (disambiguation). +Alexander III of Macedon (Ancient Greek: Ἀλέξανδρος, romanized: Alexandros; 20/21 July 356 BC – 10/11 June 323 BC), most commonly known as Alexander the Great,[c] was a king of the ancient Greek kingdom of Macedon.[d] He succeeded his father Philip II to the throne in 336 BC at the age of 20 and spent most of his ruling years conducting a lengthy military campaign throughout Western Asia, Central Asia, parts of South Asia, and Egypt. By the age of 30, he had created one of the largest empires in history, stretching from Greece to northwestern India.[1] He was undefeated in battle and is widely considered to be one of history's greatest and most successful military commanders.[2][3] + +Until the age of 16, Alexander was tutored by Aristotle. In 335 BC, shortly after his assumption of kingship over Macedon, he campaigned in the Balkans and reasserted control over Thrace and parts of Illyria before marching on the city of Thebes, which was subsequently destroyed in battle. Alexander then led the League of Corinth, and used his authority to launch the pan-Hellenic project envisaged by his father, assuming leadership over all Greeks in their conquest of Persia.[4][5] + +In 334 BC, he invaded the Achaemenid Persian Empire and began a series of campaigns that lasted for 10 years. Following his conquest of Asia Minor, Alexander broke the power of Achaemenid Persia in a series of decisive battles, including those at Issus and Gaugamela; he subsequently overthrew Darius III and conquered the Achaemenid Empire in its entirety.[e] After the fall of Persia, the Macedonian Empire held a vast swath of territory between the Adriatic Sea and the Indus River. Alexander endeavored to reach the "ends of the world and the Great Outer Sea" and invaded India in 326 BC, achieving an important victory over Porus, an ancient Indian king of present-day Punjab, at the Battle of the Hydaspes. Due to the demand of his homesick troops, he eventually turned back at the Beas River and later died in 323 BC in Babylon, the city of Mesopotamia that he had planned to establish as his empire's capital. Alexander's death left unexecuted an additional series of planned military and mercantile campaigns that would have begun with a Greek invasion of Arabia. In the years following his death, a series of civil wars broke out across the Macedonian Empire, eventually leading to its disintegration at the hands of the Diadochi. + +With his death marking the start of the Hellenistic period, Alexander's legacy includes the cultural diffusion and syncretism that his conquests engendered, such as Greco-Buddhism and Hellenistic Judaism. He founded more than twenty cities, with the most prominent being the city of Alexandria in Egypt. Alexander's settlement of Greek colonists and the resulting spread of Greek culture led to the overwhelming dominance of Hellenistic civilization and influence as far east as the Indian subcontinent. The Hellenistic period developed through the Roman Empire into modern Western culture; the Greek language became the lingua franca of the region and was the predominant language of the Byzantine Empire up until its collapse in the mid-15th century AD. Alexander became legendary as a classical hero in the mould of Achilles, featuring prominently in the historical and mythical traditions of both Greek and non-Greek cultures. His military achievements and unprecedented enduring successes in battle made him the measure against which many later military leaders would compare themselves,[f] and his tactics remain a significant subject of study in military academies worldwide.[6] Legends of Alexander's exploits coalesced into the third-century Alexander Romance which, in the premodern period, went through over one hundred recensions, translations, and derivations and was translated into almost every European vernacular and every language of the Islamic world.[7] After the Bible, it was the most popular form of European literature.[8] + +Early life + +Lineage and childhood + +Alexander III was born in Pella, the capital of the Kingdom of Macedon,[9] on the sixth day of the ancient Greek month of Hekatombaion, which probably corresponds to 20 July 356 BC (although the exact date is uncertain).[10][11] He was the son of the erstwhile king of Macedon, Philip II, and his fourth wife, Olympias (daughter of Neoptolemus I, king of Epirus).[12][g] Although Philip had seven or eight wives, Olympias was his principal wife for some time, likely because she gave birth to Alexander.[13] + +Several legends surround Alexander's birth and childhood.[14] According to the ancient Greek biographer Plutarch, on the eve of the consummation of her marriage to Philip, Olympias dreamed that her womb was struck by a thunderbolt that caused a flame to spread "far and wide" before dying away. Sometime after the wedding, Philip is said to have seen himself, in a dream, securing his wife's womb with a seal engraved with a lion's image.[15] Plutarch offered a variety of interpretations for these dreams: that Olympias was pregnant before her marriage, indicated by the sealing of her womb; or that Alexander's father was Zeus. Ancient commentators were divided about whether the ambitious Olympias promulgated the story of Alexander's divine parentage, variously claiming that she had told Alexander, or that she dismissed the suggestion as impious.[15] + +On the day Alexander was born, Philip was preparing a siege on the city of Potidea on the peninsula of Chalcidice. That same day, Philip received news that his general Parmenion had defeated the combined Illyrian and Paeonian armies and that his horses had won at the Olympic Games. It was also said that on this day, the Temple of Artemis in Ephesus, one of the Seven Wonders of the World, burnt down. This led Hegesias of Magnesia to say that it had burnt down because Artemis was away, attending the birth of Alexander.[16] Such legends may have emerged when Alexander was king, and possibly at his instigation, to show that he was superhuman and destined for greatness from conception.[14] + +In his early years, Alexander was raised by a nurse, Lanike, sister of Alexander's future general Cleitus the Black. Later in his childhood, Alexander was tutored by the strict Leonidas, a relative of his mother, and by Lysimachus of Acarnania.[17] Alexander was raised in the manner of noble Macedonian youths, learning to read, play the lyre, ride, fight, and hunt.[18] When Alexander was ten years old, a trader from Thessaly brought Philip a horse, which he offered to sell for thirteen talents. The horse refused to be mounted, and Philip ordered it away. Alexander, however, detecting the horse's fear of its own shadow, asked to tame the horse, which he eventually managed.[14] Plutarch stated that Philip, overjoyed at this display of courage and ambition, kissed his son tearfully, declaring: "My boy, you must find a kingdom big enough for your ambitions. Macedon is too small for you", and bought the horse for him.[19] Alexander named it Bucephalas, meaning "ox-head". Bucephalas carried Alexander as far as India. When the animal died (because of old age, according to Plutarch, at age 30), Alexander named a city after him, Bucephala.[20] + +Education + +When Alexander was 13, Philip began to search for a tutor, and considered such academics as Isocrates and Speusippus, the latter offering to resign from his stewardship of the Academy to take up the post. In the end, Philip chose Aristotle and provided the Temple of the Nymphs at Mieza as a classroom. In return for teaching Alexander, Philip agreed to rebuild Aristotle's hometown of Stageira, which Philip had razed, and to repopulate it by buying and freeing the ex-citizens who were slaves, or pardoning those who were in exile.[21] + +Mieza was like a boarding school for Alexander and the children of Macedonian nobles, such as Ptolemy, Hephaistion, and Cassander. Many of these students would become his friends and future generals, and are often known as the "Companions". Aristotle taught Alexander and his companions about medicine, philosophy, morals, religion, logic, and art. Under Aristotle's tutelage, Alexander developed a passion for the works of Homer, and in particular the Iliad; Aristotle gave him an annotated copy, which Alexander later carried on his campaigns.[22] Alexander was able to quote Euripides from memory.[23] + +During his youth, Alexander was also acquainted with Persian exiles at the Macedonian court, who received the protection of Philip II for several years as they opposed Artaxerxes III.[24][25][26] Among them were Artabazos II and his daughter Barsine, possible future mistress of Alexander, who resided at the Macedonian court from 352 to 342 BC, as well as Amminapes, future satrap of Alexander, or a Persian nobleman named Sisines.[24][27][28][29] This gave the Macedonian court a good knowledge of Persian issues, and may even have influenced some of the innovations in the management of the Macedonian state.[27] + +Suda writes that Anaximenes of Lampsacus was one of Alexander's teachers, and that Anaximenes also accompanied Alexander on his campaigns.[30] + +Heir of Philip II + +Regency and ascent of Macedon + +Main articles: Philip II of Macedon and Rise of Macedon +Further information: History of Macedonia (ancient kingdom) +At the age of 16, Alexander's education under Aristotle ended. Philip II had waged war against the Thracians to the north, which left Alexander in charge as regent and heir apparent.[14] During Philip's absence, the Thracian tribe of Maedi revolted against Macedonia. Alexander responded quickly and drove them from their territory. The territory was colonized, and a city, named Alexandropolis, was founded.[31] + +Upon Philip's return, Alexander was dispatched with a small force to subdue the revolts in southern Thrace. Campaigning against the Greek city of Perinthus, Alexander reportedly saved his father's life. Meanwhile, the city of Amphissa began to work lands that were sacred to Apollo near Delphi, a sacrilege that gave Philip the opportunity to further intervene in Greek affairs. While Philip was occupied in Thrace, Alexander was ordered to muster an army for a campaign in southern Greece. Concerned that other Greek states might intervene, Alexander made it look as though he was preparing to attack Illyria instead. During this turmoil, the Illyrians invaded Macedonia, only to be repelled by Alexander.[32] + +Philip and his army joined his son in 338 BC, and they marched south through Thermopylae, taking it after stubborn resistance from its Theban garrison. They went on to occupy the city of Elatea, only a few days' march from both Athens and Thebes. The Athenians, led by Demosthenes, voted to seek alliance with Thebes against Macedonia. Both Athens and Philip sent embassies to win Thebes's favour, but Athens won the contest.[33] Philip marched on Amphissa (ostensibly acting on the request of the Amphictyonic League), capturing the mercenaries sent there by Demosthenes and accepting the city's surrender. Philip then returned to Elatea, sending a final offer of peace to Athens and Thebes, who both rejected it.[34] + +As Philip marched south, his opponents blocked him near Chaeronea, Boeotia. During the ensuing Battle of Chaeronea, Philip commanded the right wing and Alexander the left, accompanied by a group of Philip's trusted generals. According to the ancient sources, the two sides fought bitterly for some time. Philip deliberately commanded his troops to retreat, counting on the untested Athenian hoplites to follow, thus breaking their line. Alexander was the first to break the Theban lines, followed by Philip's generals. Having damaged the enemy's cohesion, Philip ordered his troops to press forward and quickly routed them. With the Athenians lost, the Thebans were surrounded. Left to fight alone, they were defeated.[35] + +After the victory at Chaeronea, Philip and Alexander marched unopposed into the Peloponnese, welcomed by all cities; however, when they reached Sparta, they were refused, but did not resort to war.[36] At Corinth, Philip established a "Hellenic Alliance" (modelled on the old anti-Persian alliance of the Greco-Persian Wars), which included most Greek city-states except Sparta. Philip was then named Hegemon (often translated as "Supreme Commander") of this league (known by modern scholars as the League of Corinth), and announced his plans to attack the Persian Empire.[37][38] + +Exile and return + +When Philip returned to Pella, he fell in love with and married Cleopatra Eurydice in 338 BC,[39] the niece of his general Attalus.[40] The marriage made Alexander's position as heir less secure, since any son of Cleopatra Eurydice would be a fully Macedonian heir, while Alexander was only half-Macedonian.[41] During the wedding banquet, a drunken Attalus publicly prayed to the gods that the union would produce a legitimate heir.[40] + +At the wedding of Cleopatra, whom Philip fell in love with and married, she being much too young for him, her uncle Attalus in his drink desired the Macedonians would implore the gods to give them a lawful successor to the kingdom by his niece. This so irritated Alexander, that throwing one of the cups at his head, "You villain," said he, "what, am I then a bastard?" Then Philip, taking Attalus's part, rose up and would have run his son through; but by good fortune for them both, either his over-hasty rage, or the wine he had drunk, made his foot slip, so that he fell down on the floor. At which Alexander reproachfully insulted over him: "See there," said he, "the man who makes preparations to pass out of Europe into Asia, overturned in passing from one seat to another." + +— Plutarch, describing the feud at Philip's wedding.[42]none +In 337 BC, Alexander fled Macedon with his mother, dropping her off with her brother, King Alexander I of Epirus in Dodona, capital of the Molossians.[43] He continued to Illyria,[43] where he sought refuge with one or more Illyrian kings, perhaps with Glaucias, and was treated as a guest, despite having defeated them in battle a few years before.[44] However, it appears Philip never intended to disown his politically and militarily trained son.[43] Accordingly, Alexander returned to Macedon after six months due to the efforts of a family friend, Demaratus, who mediated between the two parties.[45] + +In the following year, the Persian satrap (governor) of Caria, Pixodarus, offered his eldest daughter to Alexander's half-brother, Philip Arrhidaeus.[43] Olympias and several of Alexander's friends suggested this showed Philip intended to make Arrhidaeus his heir.[43] Alexander reacted by sending an actor, Thessalus of Corinth, to tell Pixodarus that he should not offer his daughter's hand to an illegitimate son, but instead to Alexander. When Philip heard of this, he stopped the negotiations and scolded Alexander for wishing to marry the daughter of a Carian, explaining that he wanted a better bride for him.[43] Philip exiled four of Alexander's friends, Harpalus, Nearchus, Ptolemy and Erigyius, and had the Corinthians bring Thessalus to him in chains.[46] + +King of Macedon + +Accession + +Further information: Government of Macedonia (ancient kingdom) +In summer 336 BC, while at Aegae attending the wedding of his daughter Cleopatra to Olympias's brother, Alexander I of Epirus, Philip was assassinated by the captain of his bodyguards, Pausanias.[h] As Pausanias tried to escape, he tripped over a vine and was killed by his pursuers, including two of Alexander's companions, Perdiccas and Leonnatus. Alexander was proclaimed king on the spot by the nobles and army at the age of 20.[47][48][49] + +Consolidation of power + +Alexander began his reign by eliminating potential rivals to the throne. He had his cousin, the former Amyntas IV, executed.[51] He also had two Macedonian princes from the region of Lyncestis killed for having been involved in his father's assassination, but spared a third, Alexander Lyncestes. Olympias had Cleopatra Eurydice, and Europa, her daughter by Philip, burned alive. When Alexander learned about this, he was furious. Alexander also ordered the murder of Attalus,[51] who was in command of the advance guard of the army in Asia Minor and Cleopatra's uncle.[52] + +Attalus was at that time corresponding with Demosthenes, regarding the possibility of defecting to Athens. Attalus also had severely insulted Alexander, and following Cleopatra's murder, Alexander may have considered him too dangerous to be left alive.[52] Alexander spared Arrhidaeus, who was by all accounts mentally disabled, possibly as a result of poisoning by Olympias.[47][49][53] + +News of Philip's death roused many states into revolt, including Thebes, Athens, Thessaly, and the Thracian tribes north of Macedon. When news of the revolts reached Alexander, he responded quickly. Though advised to use diplomacy, Alexander mustered 3,000 Macedonian cavalry and rode south towards Thessaly. He found the Thessalian army occupying the pass between Mount Olympus and Mount Ossa, and ordered his men to ride over Mount Ossa. When the Thessalians awoke the next day, they found Alexander in their rear and promptly surrendered, adding their cavalry to Alexander's force. He then continued south towards the Peloponnese.[54] + +Alexander stopped at Thermopylae, where he was recognized as the leader of the Amphictyonic League before heading south to Corinth. Athens sued for peace and Alexander pardoned the rebels. The famous encounter between Alexander and Diogenes the Cynic occurred during Alexander's stay in Corinth. When Alexander asked Diogenes what he could do for him, the philosopher disdainfully asked Alexander to stand a little to the side, as he was blocking the sunlight.[55] This reply apparently delighted Alexander, who is reported to have said "But verily, if I were not Alexander, I would like to be Diogenes."[56] At Corinth, Alexander took the title of Hegemon ("leader") and, like Philip, was appointed commander for the coming war against Persia. He also received news of a Thracian uprising.[57] + +Balkan campaign + +Main article: Alexander's Balkan campaign +Before crossing to Asia, Alexander wanted to safeguard his northern borders. In the spring of 335 BC, he advanced to suppress several revolts. Starting from Amphipolis, he travelled east into the country of the "Independent Thracians"; and at Mount Haemus, the Macedonian army attacked and defeated the Thracian forces manning the heights.[58] The Macedonians marched into the country of the Triballi, and defeated their army near the Lyginus river[59] (a tributary of the Danube). Alexander then marched for three days to the Danube, encountering the Getae tribe on the opposite shore. Crossing the river at night, he surprised them and forced their army to retreat after the first cavalry skirmish.[60] + +News then reached Alexander that the Illyrian chieftain Cleitus and King Glaukias of the Taulantii were in open revolt against his authority. Marching west into Illyria, Alexander defeated each in turn, forcing the two rulers to flee with their troops. With these victories, he secured his northern frontier.[61] + +Destruction of Thebes + +While Alexander campaigned north, the Thebans and Athenians rebelled once again. Alexander immediately headed south.[62] While the other cities again hesitated, Thebes decided to fight. The Theban resistance was ineffective, and Alexander razed the city and divided its territory between the other Boeotian cities. The end of Thebes cowed Athens, leaving all of Greece temporarily at peace.[62] Alexander then set out on his Asian campaign, leaving Antipater as regent.[63] + +Conquest of the Achaemenid Persian Empire + +Main articles: Wars of Alexander the Great and Chronology of the expedition of Alexander the Great into Asia +Asia Minor + +Further information: Battle of the Granicus, Siege of Halicarnassus, and Siege of Miletus +After his victory at the Battle of Chaeronea (338 BC), Philip II began the work of establishing himself as hēgemṓn (Greek: ἡγεμών) of a league which according to Diodorus was to wage a campaign against the Persians for the sundry grievances Greece suffered in 480 and free the Greek cities of the western coast and islands from Achaemenid rule. In 336 he sent Parmenion, Amyntas, Andromenes, Attalus, and an army of 10,000 men into Anatolia to make preparations for an invasion.[64][65] At first, all went well. The Greek cities on the western coast of Anatolia revolted until the news arrived that Philip had been murdered and had been succeeded by his young son Alexander. The Macedonians were demoralized by Philip's death and were subsequently defeated near Magnesia by the Achaemenids under the command of the mercenary Memnon of Rhodes.[64][65] + +Taking over the invasion project of Philip II, Alexander's army crossed the Hellespont in 334 BC with approximately 48,100 soldiers, 6,100 cavalry and a fleet of 120 ships with crews numbering 38,000,[62] drawn from Macedon and various Greek city-states, mercenaries, and feudally raised soldiers from Thrace, Paionia, and Illyria.[66][i] He showed his intent to conquer the entirety of the Persian Empire by throwing a spear into Asian soil and saying he accepted Asia as a gift from the gods. This also showed Alexander's eagerness to fight, in contrast to his father's preference for diplomacy.[62] + +After an initial victory against Persian forces at the Battle of the Granicus, Alexander accepted the surrender of the Persian provincial capital and treasury of Sardis; he then proceeded along the Ionian coast, granting autonomy and democracy to the cities. Miletus, held by Achaemenid forces, required a delicate siege operation, with Persian naval forces nearby. Further south, at Halicarnassus, in Caria, Alexander successfully waged his first large-scale siege, eventually forcing his opponents, the mercenary captain Memnon of Rhodes and the Persian satrap of Caria, Orontobates, to withdraw by sea.[67] Alexander left the government of Caria to a member of the Hecatomnid dynasty, Ada, who adopted Alexander.[68] + +From Halicarnassus, Alexander proceeded into mountainous Lycia and the Pamphylian plain, asserting control over all coastal cities to deny the Persians naval bases. From Pamphylia onwards the coast held no major ports and Alexander moved inland. At Termessos, Alexander humbled but did not storm the Pisidian city.[69] At the ancient Phrygian capital of Gordium, Alexander "undid" the hitherto unsolvable Gordian Knot, a feat said to await the future "king of Asia".[70] According to the story, Alexander proclaimed that it did not matter how the knot was undone and hacked it apart with his sword.[71] + +The Levant and Syria + +Further information: Battle of Issus and Siege of Tyre (332 BC) +In spring 333 BC, Alexander crossed the Taurus into Cilicia. After a long pause due to an illness, he marched on towards Syria. Though outmanoeuvered by Darius's significantly larger army, he marched back to Cilicia, where he defeated Darius at Issus. Darius fled the battle, causing his army to collapse, and left behind his wife, his two daughters, his mother Sisygambis, and a fabulous treasure.[72] He offered a peace treaty that included the lands he had already lost, and a ransom of 10,000 talents for his family. Alexander replied that since he was now king of Asia, it was he alone who decided territorial divisions.[73] Alexander proceeded to take possession of Syria, and most of the coast of the Levant.[68] In the following year, 332 BC, he was forced to attack Tyre, which he captured after a long and difficult siege.[74][75] The men of military age were massacred and the women and children sold into slavery.[76] + +Egypt + +Further information: Siege of Gaza (332 BCE) +When Alexander destroyed Tyre, most of the towns on the route to Egypt quickly capitulated. However, Alexander was met with resistance at Gaza. The stronghold was heavily fortified and built on a hill, requiring a siege. When "his engineers pointed out to him that because of the height of the mound it would be impossible... this encouraged Alexander all the more to make the attempt".[77] After three unsuccessful assaults, the stronghold fell, but not before Alexander had received a serious shoulder wound. As in Tyre, men of military age were put to the sword and the women and children were sold into slavery.[78] +""" diff --git a/tests/litellm/litellm_core_utils/test_token_counter.py b/tests/litellm/litellm_core_utils/test_token_counter.py index 9f5b7b695004..07c1367e5f83 100644 --- a/tests/litellm/litellm_core_utils/test_token_counter.py +++ b/tests/litellm/litellm_core_utils/test_token_counter.py @@ -23,6 +23,7 @@ from litellm import create_pretrained_tokenizer, decode, encode, get_modified_max_tokens from litellm import token_counter as token_counter_old from litellm.litellm_core_utils.token_counter import token_counter as token_counter_new +from tests.large_text import text def token_counter_both_assert_same(**args): @@ -276,13 +277,14 @@ def test_gpt_vision_token_counting(): @pytest.mark.parametrize( "model", [ + "gpt-4-vision-preview", "gpt-4o", "claude-3-opus-20240229", "command-nightly", "mistral/mistral-tiny", ], ) -def test_load_test_token_counter(model, large_text): +def test_load_test_token_counter(model): """ Token count large prompt 100 times. @@ -290,7 +292,7 @@ def test_load_test_token_counter(model, large_text): """ import tiktoken - messages = [{"role": "user", "content": large_text}] * 10 + messages = [{"role": "user", "content": text}] * 10 start_time = time.time() for _ in range(10): diff --git a/tests/local_testing/test_router.py b/tests/local_testing/test_router.py index 7564fba555ff..06cf75705a0f 100644 --- a/tests/local_testing/test_router.py +++ b/tests/local_testing/test_router.py @@ -683,7 +683,7 @@ async def test2(): @pytest.mark.asyncio @pytest.mark.parametrize("sync_mode", [True, False]) -async def test_async_router_context_window_fallback(sync_mode, large_text): +async def test_async_router_context_window_fallback(sync_mode): """ - Give a gpt-4 model group with different context windows (8192k vs. 128k) - Send a 10k prompt @@ -691,7 +691,7 @@ async def test_async_router_context_window_fallback(sync_mode, large_text): """ import os - text = large_text + from large_text import text litellm.set_verbose = False litellm._turn_on_debug() @@ -775,9 +775,7 @@ def test_router_rpm_pre_call_check(): pytest.fail(f"Got unexpected exception on router! - {str(e)}") -def test_router_context_window_check_pre_call_check_in_group_custom_model_info( - large_text, -): +def test_router_context_window_check_pre_call_check_in_group_custom_model_info(): """ - Give a gpt-3.5-turbo model group with different context windows (4k vs. 16k) - Send a 5k prompt @@ -785,7 +783,7 @@ def test_router_context_window_check_pre_call_check_in_group_custom_model_info( """ import os - text = large_text + from large_text import text litellm.set_verbose = False @@ -831,7 +829,7 @@ def test_router_context_window_check_pre_call_check_in_group_custom_model_info( pytest.fail(f"Got unexpected exception on router! - {str(e)}") -def test_router_context_window_check_pre_call_check(large_text): +def test_router_context_window_check_pre_call_check(): """ - Give a gpt-3.5-turbo model group with different context windows (4k vs. 16k) - Send a 5k prompt @@ -839,7 +837,7 @@ def test_router_context_window_check_pre_call_check(large_text): """ import os - text = large_text + from large_text import text litellm.set_verbose = False @@ -885,7 +883,7 @@ def test_router_context_window_check_pre_call_check(large_text): pytest.fail(f"Got unexpected exception on router! - {str(e)}") -def test_router_context_window_check_pre_call_check_out_group(large_text): +def test_router_context_window_check_pre_call_check_out_group(): """ - Give 2 gpt-3.5-turbo model groups with different context windows (4k vs. 16k) - Send a 5k prompt @@ -893,7 +891,7 @@ def test_router_context_window_check_pre_call_check_out_group(large_text): """ import os - text = large_text + from large_text import text litellm.set_verbose = False @@ -1138,7 +1136,7 @@ async def test_aimg_gen_on_router(): "api_base": os.getenv("AZURE_SWEDEN_API_BASE"), "api_key": os.getenv("AZURE_SWEDEN_API_KEY"), }, - }, + } ] router = Router(model_list=model_list, num_retries=3) response = await router.aimage_generation( @@ -2789,5 +2787,4 @@ def test_router_get_model_group_info(): assert model_group_info is not None assert model_group_info.model_group == "gpt-4" assert model_group_info.input_cost_per_token > 0 - - assert model_group_info.output_cost_per_token > 0 + assert model_group_info.output_cost_per_token > 0 \ No newline at end of file diff --git a/tests/old_proxy_tests/tests/load_test_completion.py b/tests/old_proxy_tests/tests/load_test_completion.py index ce52e6fd25c7..29d8924ab5f1 100644 --- a/tests/old_proxy_tests/tests/load_test_completion.py +++ b/tests/old_proxy_tests/tests/load_test_completion.py @@ -4,6 +4,7 @@ from openai import AsyncOpenAI, AsyncAzureOpenAI import uuid import traceback +from large_text import text from dotenv import load_dotenv from statistics import mean, median diff --git a/tests/test_fallbacks.py b/tests/test_fallbacks.py index 928af8d7e2bc..aab8e985bde9 100644 --- a/tests/test_fallbacks.py +++ b/tests/test_fallbacks.py @@ -3,6 +3,7 @@ import pytest import asyncio import aiohttp +from large_text import text import time from typing import Optional