mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
feat(voyage): rebrand to VoyageAI by MongoDB, refresh model list, support both contextual input shapes
This commit is contained in:
parent
9f3ac8bc27
commit
0e11abb15d
9 changed files with 128 additions and 6 deletions
|
|
@ -370,7 +370,7 @@ curl -X POST 'http://0.0.0.0:4000/v1/chat/completions' \
|
|||
| [Vercel AI Gateway (`vercel_ai_gateway`)](https://docs.litellm.ai/docs/providers/vercel_ai_gateway) | ✅ | ✅ | ✅ | | | | | | | |
|
||||
| [VLLM (`vllm`)](https://docs.litellm.ai/docs/providers/vllm) | ✅ | ✅ | ✅ | | | | | | | |
|
||||
| [Volcengine (`volcengine`)](https://docs.litellm.ai/docs/providers/volcano) | ✅ | ✅ | ✅ | | | | | | | |
|
||||
| [Voyage AI (`voyage`)](https://docs.litellm.ai/docs/providers/voyage) | | | | ✅ | | | | | | |
|
||||
| [VoyageAI by MongoDB (`voyage`)](https://docs.litellm.ai/docs/providers/voyage) | | | | ✅ | | | | | | |
|
||||
| [WandB Inference (`wandb`)](https://docs.litellm.ai/docs/providers/wandb_inference) | ✅ | ✅ | ✅ | | | | | | | |
|
||||
| [Watsonx Text (`watsonx_text`)](https://docs.litellm.ai/docs/providers/watsonx) | ✅ | ✅ | ✅ | | | | | | | |
|
||||
| [xAI (`xai`)](https://docs.litellm.ai/docs/providers/xai) | ✅ | ✅ | ✅ | | | | | | | |
|
||||
|
|
|
|||
|
|
@ -105,11 +105,27 @@ class VoyageContextualEmbeddingConfig(BaseEmbeddingConfig):
|
|||
headers: dict,
|
||||
) -> dict:
|
||||
return {
|
||||
"inputs": input,
|
||||
"inputs": self._normalize_contextual_inputs(input),
|
||||
"model": model,
|
||||
**optional_params,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _normalize_contextual_inputs(
|
||||
input: AllEmbeddingInputValues | list[list[str]],
|
||||
) -> AllEmbeddingInputValues | list[list[str]]:
|
||||
"""
|
||||
Voyage's contextualized embeddings API accepts ``inputs`` as either a
|
||||
flat ``list[str]`` (one document's chunks) or a nested ``list[list[str]]``
|
||||
(multiple documents). Both are sent through unchanged; a bare ``str`` is
|
||||
wrapped into a single-element list so the payload always matches the spec.
|
||||
|
||||
Reference: https://docs.voyageai.com/docs/contextualized-chunk-embeddings
|
||||
"""
|
||||
if isinstance(input, str):
|
||||
return [input]
|
||||
return input
|
||||
|
||||
def transform_embedding_response(
|
||||
self,
|
||||
model: str,
|
||||
|
|
|
|||
|
|
@ -56413,6 +56413,26 @@
|
|||
"output_vector_size": 1024,
|
||||
"source": "https://docs.voyageai.com/docs/pricing"
|
||||
},
|
||||
"voyage/voyage-4-nano": {
|
||||
"input_cost_per_token": 0.0,
|
||||
"litellm_provider": "voyage",
|
||||
"max_input_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "embedding",
|
||||
"output_cost_per_token": 0.0,
|
||||
"output_vector_size": 1024,
|
||||
"source": "https://docs.voyageai.com/docs/embeddings"
|
||||
},
|
||||
"voyage/voyage-multilingual-2": {
|
||||
"input_cost_per_token": 1.2e-07,
|
||||
"litellm_provider": "voyage",
|
||||
"max_input_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "embedding",
|
||||
"output_cost_per_token": 0.0,
|
||||
"output_vector_size": 1024,
|
||||
"source": "https://docs.voyageai.com/docs/pricing"
|
||||
},
|
||||
"voyage/voyage-context-4": {
|
||||
"input_cost_per_token": 1.2e-07,
|
||||
"litellm_provider": "voyage",
|
||||
|
|
|
|||
|
|
@ -2283,7 +2283,7 @@
|
|||
}
|
||||
},
|
||||
"voyage": {
|
||||
"display_name": "Voyage AI (`voyage`)",
|
||||
"display_name": "VoyageAI by MongoDB (`voyage`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/voyage",
|
||||
"endpoints": {
|
||||
"chat_completions": false,
|
||||
|
|
|
|||
|
|
@ -3228,7 +3228,7 @@
|
|||
},
|
||||
{
|
||||
"provider": "Voyage",
|
||||
"provider_display_name": "Voyage AI",
|
||||
"provider_display_name": "VoyageAI by MongoDB",
|
||||
"litellm_provider": "voyage",
|
||||
"credential_fields": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56413,6 +56413,26 @@
|
|||
"output_vector_size": 1024,
|
||||
"source": "https://docs.voyageai.com/docs/pricing"
|
||||
},
|
||||
"voyage/voyage-4-nano": {
|
||||
"input_cost_per_token": 0.0,
|
||||
"litellm_provider": "voyage",
|
||||
"max_input_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "embedding",
|
||||
"output_cost_per_token": 0.0,
|
||||
"output_vector_size": 1024,
|
||||
"source": "https://docs.voyageai.com/docs/embeddings"
|
||||
},
|
||||
"voyage/voyage-multilingual-2": {
|
||||
"input_cost_per_token": 1.2e-07,
|
||||
"litellm_provider": "voyage",
|
||||
"max_input_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "embedding",
|
||||
"output_cost_per_token": 0.0,
|
||||
"output_vector_size": 1024,
|
||||
"source": "https://docs.voyageai.com/docs/pricing"
|
||||
},
|
||||
"voyage/voyage-context-4": {
|
||||
"input_cost_per_token": 1.2e-07,
|
||||
"litellm_provider": "voyage",
|
||||
|
|
|
|||
|
|
@ -2594,7 +2594,7 @@
|
|||
}
|
||||
},
|
||||
"voyage": {
|
||||
"display_name": "Voyage AI (`voyage`)",
|
||||
"display_name": "VoyageAI by MongoDB (`voyage`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/voyage",
|
||||
"endpoints": {
|
||||
"chat_completions": false,
|
||||
|
|
|
|||
|
|
@ -195,6 +195,51 @@ class TestVoyageContextualEmbeddings:
|
|||
assert transformed["model"] == "voyage-context-3"
|
||||
assert transformed["encoding_format"] == "float"
|
||||
|
||||
def test_contextual_embedding_flat_list_input(self):
|
||||
"""A flat list[str] is passed through unchanged as inputs (spec allows list[str])"""
|
||||
from litellm.llms.voyage.embedding.transformation_contextual import (
|
||||
VoyageContextualEmbeddingConfig,
|
||||
)
|
||||
|
||||
config = VoyageContextualEmbeddingConfig()
|
||||
flat_input = ["chunk one", "chunk two"]
|
||||
|
||||
transformed = config.transform_embedding_request(
|
||||
"voyage-context-4", flat_input, {}, {}
|
||||
)
|
||||
|
||||
assert transformed["inputs"] == flat_input
|
||||
assert transformed["model"] == "voyage-context-4"
|
||||
|
||||
def test_contextual_embedding_nested_list_input(self):
|
||||
"""A nested list[list[str]] is passed through unchanged as inputs"""
|
||||
from litellm.llms.voyage.embedding.transformation_contextual import (
|
||||
VoyageContextualEmbeddingConfig,
|
||||
)
|
||||
|
||||
config = VoyageContextualEmbeddingConfig()
|
||||
nested_input = [["doc a chunk 1", "doc a chunk 2"], ["doc b chunk 1"]]
|
||||
|
||||
transformed = config.transform_embedding_request(
|
||||
"voyage-context-4", nested_input, {}, {}
|
||||
)
|
||||
|
||||
assert transformed["inputs"] == nested_input
|
||||
|
||||
def test_contextual_embedding_str_input_wrapped(self):
|
||||
"""A bare str is wrapped into a single-element list so inputs is always a list"""
|
||||
from litellm.llms.voyage.embedding.transformation_contextual import (
|
||||
VoyageContextualEmbeddingConfig,
|
||||
)
|
||||
|
||||
config = VoyageContextualEmbeddingConfig()
|
||||
|
||||
transformed = config.transform_embedding_request(
|
||||
"voyage-context-4", "just one chunk", {}, {}
|
||||
)
|
||||
|
||||
assert transformed["inputs"] == ["just one chunk"]
|
||||
|
||||
def test_contextual_embedding_response_transformation(self):
|
||||
"""Test response transformation for contextual embeddings"""
|
||||
from litellm.llms.voyage.embedding.transformation_contextual import (
|
||||
|
|
@ -428,3 +473,24 @@ class TestVoyageContextualEmbeddings:
|
|||
|
||||
except Exception as e:
|
||||
pytest.fail(f"Error occurred: {e}")
|
||||
|
||||
|
||||
def test_voyage_current_models_registered():
|
||||
"""The models currently listed on docs.voyageai.com resolve with voyage pricing/context"""
|
||||
from litellm import get_model_info
|
||||
|
||||
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
|
||||
litellm.model_cost = litellm.get_model_cost_map(url="")
|
||||
|
||||
expected = {
|
||||
"voyage/voyage-4-nano": {"max_input_tokens": 32000, "input_cost_per_token": 0.0},
|
||||
"voyage/voyage-multilingual-2": {"max_input_tokens": 32000, "input_cost_per_token": 1.2e-07},
|
||||
"voyage/voyage-context-4": {"max_input_tokens": 120000, "input_cost_per_token": 1.2e-07},
|
||||
}
|
||||
|
||||
for model, fields in expected.items():
|
||||
info = get_model_info(model)
|
||||
assert info["litellm_provider"] == "voyage", f"{model} wrong provider"
|
||||
assert info["mode"] == "embedding", f"{model} wrong mode"
|
||||
assert info["max_input_tokens"] == fields["max_input_tokens"], f"{model} wrong context"
|
||||
assert info["input_cost_per_token"] == fields["input_cost_per_token"], f"{model} wrong price"
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ export enum Providers {
|
|||
VERTEX_AI_BETA = "Vertex Ai Beta",
|
||||
VLLM = "Local vLLM",
|
||||
VolcEngine = "VolcEngine",
|
||||
Voyage = "Voyage AI",
|
||||
Voyage = "VoyageAI by MongoDB",
|
||||
WANDB = "Wandb",
|
||||
WATSONX = "Watsonx",
|
||||
WATSONX_TEXT = "Watsonx Text",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue