Add Together embedder to TS SDK (#5989)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
This commit is contained in:
@@ -1,15 +1,20 @@
|
|||||||
---
|
---
|
||||||
title: Together
|
title: Together
|
||||||
description: "Configure Together AI as an embedding provider in Mem0 with support for 768-dimensional embedding models."
|
description: "Configure Together AI as an embedding provider in Mem0 with support for 1024-dimensional embedding models."
|
||||||
---
|
---
|
||||||
|
|
||||||
To use Together embedding models, set the `TOGETHER_API_KEY` environment variable. You can obtain the Together API key from the [Together Platform](https://api.together.xyz/settings/api-keys).
|
To use Together embedding models, set the `TOGETHER_API_KEY` environment variable. You can obtain the Together API key from the [Together Platform](https://api.together.ai/settings/projects/~current/api-keys).
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
<Note> The `embedding_model_dims` parameter for `vector_store` should be set to `768` for Together embedder. </Note>
|
<Note> The `embedding_model_dims` parameter for `vector_store` should be set to `1024` for Together embedder. </Note>
|
||||||
|
|
||||||
```python
|
<Warning>
|
||||||
|
**Breaking default change.** The default Together embedding model is now `intfloat/multilingual-e5-large-instruct` (**1024-dim**), replacing the previous default `togethercomputer/m2-bert-80M-8k-retrieval` (**768-dim**). If you created a self-hosted vector store with the old default, its collection is 768-dim and will reject the new 1024-dim vectors **recreate/reindex the collection at 1024 dimensions** after upgrading. To defer the change, pin the previous values explicitly (`model="togethercomputer/m2-bert-80M-8k-retrieval"`, `embedding_dims=768`) note Together no longer lists this model among its recommended embeddings, so reindexing at 1024 is the durable path.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
```python Python
|
||||||
import os
|
import os
|
||||||
from mem0 import Memory
|
from mem0 import Memory
|
||||||
|
|
||||||
@@ -20,7 +25,7 @@ config = {
|
|||||||
"embedder": {
|
"embedder": {
|
||||||
"provider": "together",
|
"provider": "together",
|
||||||
"config": {
|
"config": {
|
||||||
"model": "togethercomputer/m2-bert-80M-8k-retrieval"
|
"model": "intfloat/multilingual-e5-large-instruct"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,18 +34,50 @@ m = Memory.from_config(config)
|
|||||||
messages = [
|
messages = [
|
||||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||||
{"role": "assistant", "content": "How about thriller movies? They can be quite engaging."},
|
{"role": "assistant", "content": "How about thriller movies? They can be quite engaging."},
|
||||||
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
|
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
|
||||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||||
]
|
]
|
||||||
m.add(messages, user_id="john")
|
m.add(messages, user_id="john")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```typescript TypeScript
|
||||||
|
import { Memory } from 'mem0ai/oss';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
embedder: {
|
||||||
|
provider: 'together',
|
||||||
|
config: {
|
||||||
|
apiKey: process.env.TOGETHER_API_KEY || '',
|
||||||
|
model: 'intfloat/multilingual-e5-large-instruct',
|
||||||
|
embeddingDims: 1024,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const memory = new Memory(config);
|
||||||
|
await memory.add("I'm visiting Paris", { userId: "john" });
|
||||||
|
```
|
||||||
|
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
### Config
|
### Config
|
||||||
|
|
||||||
Here are the parameters available for configuring Together embedder:
|
Here are the parameters available for configuring Together embedder:
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<Tab title="Python">
|
||||||
| Parameter | Description | Default Value |
|
| Parameter | Description | Default Value |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `model` | The name of the embedding model to use | `togethercomputer/m2-bert-80M-8k-retrieval` |
|
| `model` | The name of the embedding model to use | `intfloat/multilingual-e5-large-instruct` |
|
||||||
| `embedding_dims` | Dimensions of the embedding model | `768` |
|
| `embedding_dims` | Dimensions of the embedding model | `1024` |
|
||||||
| `api_key` | The Together API key | `None` |
|
| `api_key` | The Together API key | `None` |
|
||||||
|
</Tab>
|
||||||
|
<Tab title="TypeScript">
|
||||||
|
| Parameter | Description | Default Value |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `model` | The name of the embedding model to use | `intfloat/multilingual-e5-large-instruct` |
|
||||||
|
| `embeddingDims` | Dimensions of the embedding model for vector store configuration | `1024` |
|
||||||
|
| `apiKey` | The Together API key | `TOGETHER_API_KEY` |
|
||||||
|
| `baseURL` | Base URL for an OpenAI-compatible Together endpoint | `https://api.together.ai/v1` |
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Mem0 offers support for various embedding models, allowing users to choose the o
|
|||||||
See the list of supported embedders below.
|
See the list of supported embedders below.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
All embedders listed below are supported in the Python implementation. The TypeScript implementation supports: **OpenAI**, **Azure OpenAI**, **Google AI**, **Langchain**, **LM Studio**, and **Ollama**.
|
All embedders listed below are supported in the Python implementation. The TypeScript implementation supports: **OpenAI**, **Azure OpenAI**, **Google AI**, **Langchain**, **LM Studio**, **Ollama**, and **Together**.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
<CardGroup cols={4}>
|
<CardGroup cols={4}>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ title: Together
|
|||||||
description: "Configure Together AI as an LLM provider in Mem0 with API key setup and Mixtral model configuration."
|
description: "Configure Together AI as an LLM provider in Mem0 with API key setup and Mixtral model configuration."
|
||||||
---
|
---
|
||||||
|
|
||||||
To use Together LLM models, you have to set the `TOGETHER_API_KEY` environment variable. You can obtain the Together API key from their [Account settings page](https://api.together.xyz/settings/api-keys).
|
To use Together LLM models, you have to set the `TOGETHER_API_KEY` environment variable. You can obtain the Together API key from their [Account settings page](https://api.together.ai/settings/projects/~current/api-keys).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -37,4 +37,4 @@ m.add(messages, user_id="alice", metadata={"category": "movies"})
|
|||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
All available parameters for the `together` config are present in [Master List of All Params in Config](../config).
|
All available parameters for the `together` config are present in [Master List of All Params in Config](../config).
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { OpenAIEmbedder } from "./openai";
|
||||||
|
import { EmbeddingConfig } from "../types";
|
||||||
|
|
||||||
|
const DEFAULT_BASE_URL = "https://api.together.ai/v1";
|
||||||
|
const DEFAULT_MODEL = "intfloat/multilingual-e5-large-instruct";
|
||||||
|
|
||||||
|
export class TogetherEmbedder extends OpenAIEmbedder {
|
||||||
|
constructor(config: EmbeddingConfig) {
|
||||||
|
const openAICompatibleConfig = { ...config };
|
||||||
|
delete openAICompatibleConfig.embeddingDims;
|
||||||
|
|
||||||
|
const apiKey = config.apiKey || process.env.TOGETHER_API_KEY;
|
||||||
|
if (!apiKey) {
|
||||||
|
throw new Error("Together API key is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
super({
|
||||||
|
...openAICompatibleConfig,
|
||||||
|
apiKey,
|
||||||
|
baseURL: config.baseURL || config.url || DEFAULT_BASE_URL,
|
||||||
|
model: config.model || DEFAULT_MODEL,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ export * from "./embeddings/base";
|
|||||||
export * from "./embeddings/openai";
|
export * from "./embeddings/openai";
|
||||||
export * from "./embeddings/ollama";
|
export * from "./embeddings/ollama";
|
||||||
export * from "./embeddings/lmstudio";
|
export * from "./embeddings/lmstudio";
|
||||||
|
export * from "./embeddings/together";
|
||||||
export * from "./embeddings/google";
|
export * from "./embeddings/google";
|
||||||
export * from "./embeddings/azure";
|
export * from "./embeddings/azure";
|
||||||
export * from "./embeddings/langchain";
|
export * from "./embeddings/langchain";
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { OpenAIEmbedder } from "../embeddings/openai";
|
import { OpenAIEmbedder } from "../embeddings/openai";
|
||||||
import { OllamaEmbedder } from "../embeddings/ollama";
|
import { OllamaEmbedder } from "../embeddings/ollama";
|
||||||
import { LMStudioEmbedder } from "../embeddings/lmstudio";
|
import { LMStudioEmbedder } from "../embeddings/lmstudio";
|
||||||
|
import { TogetherEmbedder } from "../embeddings/together";
|
||||||
import { OpenAILLM } from "../llms/openai";
|
import { OpenAILLM } from "../llms/openai";
|
||||||
import { OpenAIStructuredLLM } from "../llms/openai_structured";
|
import { OpenAIStructuredLLM } from "../llms/openai_structured";
|
||||||
import { AnthropicLLM } from "../llms/anthropic";
|
import { AnthropicLLM } from "../llms/anthropic";
|
||||||
@@ -51,6 +52,8 @@ export class EmbedderFactory {
|
|||||||
return new OllamaEmbedder(config);
|
return new OllamaEmbedder(config);
|
||||||
case "lmstudio":
|
case "lmstudio":
|
||||||
return new LMStudioEmbedder(config);
|
return new LMStudioEmbedder(config);
|
||||||
|
case "together":
|
||||||
|
return new TogetherEmbedder(config);
|
||||||
case "google":
|
case "google":
|
||||||
case "gemini":
|
case "gemini":
|
||||||
return new GoogleEmbedder(config);
|
return new GoogleEmbedder(config);
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ jest.mock("../src/embeddings/lmstudio", () => ({
|
|||||||
.fn()
|
.fn()
|
||||||
.mockImplementation((config) => ({ type: "lmstudio-embedder", config })),
|
.mockImplementation((config) => ({ type: "lmstudio-embedder", config })),
|
||||||
}));
|
}));
|
||||||
|
jest.mock("../src/embeddings/together", () => ({
|
||||||
|
TogetherEmbedder: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation((config) => ({ type: "together-embedder", config })),
|
||||||
|
}));
|
||||||
|
|
||||||
jest.mock("../src/llms/openai", () => ({
|
jest.mock("../src/llms/openai", () => ({
|
||||||
OpenAILLM: jest
|
OpenAILLM: jest
|
||||||
@@ -190,6 +195,7 @@ describe("EmbedderFactory", () => {
|
|||||||
["azure_openai"],
|
["azure_openai"],
|
||||||
["langchain"],
|
["langchain"],
|
||||||
["lmstudio"],
|
["lmstudio"],
|
||||||
|
["together"],
|
||||||
])("creates embedder for provider '%s'", (provider) => {
|
])("creates embedder for provider '%s'", (provider) => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
EmbedderFactory.create(provider, dummyEmbedConfig),
|
EmbedderFactory.create(provider, dummyEmbedConfig),
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/// <reference types="jest" />
|
||||||
|
|
||||||
|
const mockEmbeddingsCreate = jest.fn();
|
||||||
|
const mockOpenAI = jest.fn().mockImplementation(() => ({
|
||||||
|
embeddings: { create: mockEmbeddingsCreate },
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock("openai", () => ({
|
||||||
|
__esModule: true,
|
||||||
|
default: mockOpenAI,
|
||||||
|
}));
|
||||||
|
|
||||||
|
import { TogetherEmbedder } from "../src/embeddings/together";
|
||||||
|
|
||||||
|
const mockEmbedding = [0.1, 0.2, 0.3];
|
||||||
|
const originalEnv = process.env;
|
||||||
|
|
||||||
|
describe("TogetherEmbedder (unit)", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
process.env = { ...originalEnv };
|
||||||
|
delete process.env.TOGETHER_API_KEY;
|
||||||
|
mockOpenAI.mockClear();
|
||||||
|
mockEmbeddingsCreate.mockReset();
|
||||||
|
mockEmbeddingsCreate.mockResolvedValue({
|
||||||
|
data: [{ index: 0, embedding: mockEmbedding }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
process.env = originalEnv;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses Together defaults with an API key from config", async () => {
|
||||||
|
const embedder = new TogetherEmbedder({ apiKey: "test-key" });
|
||||||
|
|
||||||
|
await embedder.embed("hello");
|
||||||
|
|
||||||
|
expect(mockOpenAI).toHaveBeenCalledWith({
|
||||||
|
apiKey: "test-key",
|
||||||
|
baseURL: "https://api.together.ai/v1",
|
||||||
|
});
|
||||||
|
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
|
||||||
|
model: "intfloat/multilingual-e5-large-instruct",
|
||||||
|
input: "hello",
|
||||||
|
encoding_format: "float",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses TOGETHER_API_KEY when config apiKey is not provided", async () => {
|
||||||
|
process.env.TOGETHER_API_KEY = "env-key";
|
||||||
|
|
||||||
|
const embedder = new TogetherEmbedder({});
|
||||||
|
|
||||||
|
await embedder.embed("hello");
|
||||||
|
|
||||||
|
expect(mockOpenAI).toHaveBeenCalledWith({
|
||||||
|
apiKey: "env-key",
|
||||||
|
baseURL: "https://api.together.ai/v1",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("supports custom model and baseURL without forwarding embeddingDims", async () => {
|
||||||
|
const embedder = new TogetherEmbedder({
|
||||||
|
apiKey: "test-key",
|
||||||
|
model: "custom-together-embed",
|
||||||
|
baseURL: "https://proxy.example.com/v1",
|
||||||
|
embeddingDims: 512,
|
||||||
|
});
|
||||||
|
|
||||||
|
await embedder.embed("hello");
|
||||||
|
|
||||||
|
expect(mockOpenAI).toHaveBeenCalledWith({
|
||||||
|
apiKey: "test-key",
|
||||||
|
baseURL: "https://proxy.example.com/v1",
|
||||||
|
});
|
||||||
|
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
|
||||||
|
model: "custom-together-embed",
|
||||||
|
input: "hello",
|
||||||
|
encoding_format: "float",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses url as a baseURL fallback", async () => {
|
||||||
|
const embedder = new TogetherEmbedder({
|
||||||
|
apiKey: "test-key",
|
||||||
|
url: "https://url-fallback.example.com/v1",
|
||||||
|
});
|
||||||
|
|
||||||
|
await embedder.embed("hello");
|
||||||
|
|
||||||
|
expect(mockOpenAI).toHaveBeenCalledWith({
|
||||||
|
apiKey: "test-key",
|
||||||
|
baseURL: "https://url-fallback.example.com/v1",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sorts batch embeddings by response index", async () => {
|
||||||
|
mockEmbeddingsCreate.mockResolvedValueOnce({
|
||||||
|
data: [
|
||||||
|
{ index: 1, embedding: [0.3, 0.4] },
|
||||||
|
{ index: 0, embedding: [0.1, 0.2] },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const embedder = new TogetherEmbedder({ apiKey: "test-key" });
|
||||||
|
|
||||||
|
await expect(embedder.embedBatch(["first", "second"])).resolves.toEqual([
|
||||||
|
[0.1, 0.2],
|
||||||
|
[0.3, 0.4],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws when no API key is available", () => {
|
||||||
|
expect(() => new TogetherEmbedder({})).toThrow(
|
||||||
|
"Together API key is required",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -11,10 +11,9 @@ class TogetherEmbedding(EmbeddingBase):
|
|||||||
def __init__(self, config: Optional[BaseEmbedderConfig] = None):
|
def __init__(self, config: Optional[BaseEmbedderConfig] = None):
|
||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
|
|
||||||
self.config.model = self.config.model or "togethercomputer/m2-bert-80M-8k-retrieval"
|
self.config.model = self.config.model or "intfloat/multilingual-e5-large-instruct"
|
||||||
api_key = self.config.api_key or os.getenv("TOGETHER_API_KEY")
|
api_key = self.config.api_key or os.getenv("TOGETHER_API_KEY")
|
||||||
# TODO: check if this is correct
|
self.config.embedding_dims = self.config.embedding_dims or 1024
|
||||||
self.config.embedding_dims = self.config.embedding_dims or 768
|
|
||||||
self.client = Together(api_key=api_key)
|
self.client = Together(api_key=api_key)
|
||||||
|
|
||||||
def embed(self, text, memory_action: Optional[Literal["add", "search", "update"]] = None):
|
def embed(self, text, memory_action: Optional[Literal["add", "search", "update"]] = None):
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import pytest
|
|||||||
from mem0.configs.embeddings.base import BaseEmbedderConfig
|
from mem0.configs.embeddings.base import BaseEmbedderConfig
|
||||||
from mem0.embeddings.together import TogetherEmbedding
|
from mem0.embeddings.together import TogetherEmbedding
|
||||||
|
|
||||||
|
DEFAULT_MODEL = "intfloat/multilingual-e5-large-instruct"
|
||||||
|
DEFAULT_EMBEDDING_DIMS = 1024
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_together_client():
|
def mock_together_client():
|
||||||
@@ -15,7 +18,7 @@ def mock_together_client():
|
|||||||
|
|
||||||
|
|
||||||
def test_embed_text(mock_together_client):
|
def test_embed_text(mock_together_client):
|
||||||
config = BaseEmbedderConfig(model="togethercomputer/m2-bert-80M-8k-retrieval", embedding_dims=768)
|
config = BaseEmbedderConfig(model=DEFAULT_MODEL, embedding_dims=DEFAULT_EMBEDDING_DIMS)
|
||||||
embedder = TogetherEmbedding(config)
|
embedder = TogetherEmbedding(config)
|
||||||
|
|
||||||
mock_together_client.embeddings.create.return_value = Mock(data=[Mock(embedding=[0.1, 0.2, 0.3, 0.4, 0.5])])
|
mock_together_client.embeddings.create.return_value = Mock(data=[Mock(embedding=[0.1, 0.2, 0.3, 0.4, 0.5])])
|
||||||
@@ -23,14 +26,12 @@ def test_embed_text(mock_together_client):
|
|||||||
text = "Sample text to embed."
|
text = "Sample text to embed."
|
||||||
embedding = embedder.embed(text)
|
embedding = embedder.embed(text)
|
||||||
|
|
||||||
mock_together_client.embeddings.create.assert_called_once_with(
|
mock_together_client.embeddings.create.assert_called_once_with(model=DEFAULT_MODEL, input=text)
|
||||||
model="togethercomputer/m2-bert-80M-8k-retrieval", input=text
|
|
||||||
)
|
|
||||||
assert embedding == [0.1, 0.2, 0.3, 0.4, 0.5]
|
assert embedding == [0.1, 0.2, 0.3, 0.4, 0.5]
|
||||||
|
|
||||||
|
|
||||||
def test_embed_batch_single_call(mock_together_client):
|
def test_embed_batch_single_call(mock_together_client):
|
||||||
config = BaseEmbedderConfig(model="togethercomputer/m2-bert-80M-8k-retrieval", embedding_dims=768)
|
config = BaseEmbedderConfig(model=DEFAULT_MODEL, embedding_dims=DEFAULT_EMBEDDING_DIMS)
|
||||||
embedder = TogetherEmbedding(config)
|
embedder = TogetherEmbedding(config)
|
||||||
|
|
||||||
mock_item0 = Mock(index=0, embedding=[0.1, 0.2, 0.3])
|
mock_item0 = Mock(index=0, embedding=[0.1, 0.2, 0.3])
|
||||||
@@ -40,14 +41,12 @@ def test_embed_batch_single_call(mock_together_client):
|
|||||||
texts = ["First text.", "Second text."]
|
texts = ["First text.", "Second text."]
|
||||||
embeddings = embedder.embed_batch(texts)
|
embeddings = embedder.embed_batch(texts)
|
||||||
|
|
||||||
mock_together_client.embeddings.create.assert_called_once_with(
|
mock_together_client.embeddings.create.assert_called_once_with(model=DEFAULT_MODEL, input=texts)
|
||||||
model="togethercomputer/m2-bert-80M-8k-retrieval", input=texts
|
|
||||||
)
|
|
||||||
assert embeddings == [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]
|
assert embeddings == [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]
|
||||||
|
|
||||||
|
|
||||||
def test_embed_batch_empty_list(mock_together_client):
|
def test_embed_batch_empty_list(mock_together_client):
|
||||||
config = BaseEmbedderConfig(model="togethercomputer/m2-bert-80M-8k-retrieval", embedding_dims=768)
|
config = BaseEmbedderConfig(model=DEFAULT_MODEL, embedding_dims=DEFAULT_EMBEDDING_DIMS)
|
||||||
embedder = TogetherEmbedding(config)
|
embedder = TogetherEmbedding(config)
|
||||||
|
|
||||||
result = embedder.embed_batch([])
|
result = embedder.embed_batch([])
|
||||||
@@ -57,7 +56,7 @@ def test_embed_batch_empty_list(mock_together_client):
|
|||||||
|
|
||||||
|
|
||||||
def test_embed_batch_count_mismatch_raises(mock_together_client):
|
def test_embed_batch_count_mismatch_raises(mock_together_client):
|
||||||
config = BaseEmbedderConfig(model="togethercomputer/m2-bert-80M-8k-retrieval", embedding_dims=768)
|
config = BaseEmbedderConfig(model=DEFAULT_MODEL, embedding_dims=DEFAULT_EMBEDDING_DIMS)
|
||||||
embedder = TogetherEmbedding(config)
|
embedder = TogetherEmbedding(config)
|
||||||
|
|
||||||
mock_item0 = Mock(index=0, embedding=[0.1, 0.2, 0.3])
|
mock_item0 = Mock(index=0, embedding=[0.1, 0.2, 0.3])
|
||||||
@@ -65,3 +64,24 @@ def test_embed_batch_count_mismatch_raises(mock_together_client):
|
|||||||
|
|
||||||
with pytest.raises(ValueError, match="returned 1 embeddings for 2 texts"):
|
with pytest.raises(ValueError, match="returned 1 embeddings for 2 texts"):
|
||||||
embedder.embed_batch(["first text", "second text"])
|
embedder.embed_batch(["first text", "second text"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_config_applies_together_defaults(mock_together_client):
|
||||||
|
embedder = TogetherEmbedding(BaseEmbedderConfig())
|
||||||
|
|
||||||
|
assert embedder.config.model == DEFAULT_MODEL
|
||||||
|
assert embedder.config.embedding_dims == DEFAULT_EMBEDDING_DIMS
|
||||||
|
|
||||||
|
|
||||||
|
def test_explicit_config_overrides_defaults(mock_together_client):
|
||||||
|
# The `config.x or default` wiring must honor user-provided values, not clobber them.
|
||||||
|
config = BaseEmbedderConfig(model="BAAI/bge-base-en-v1.5", embedding_dims=768)
|
||||||
|
embedder = TogetherEmbedding(config)
|
||||||
|
|
||||||
|
assert embedder.config.model == "BAAI/bge-base-en-v1.5"
|
||||||
|
assert embedder.config.embedding_dims == 768
|
||||||
|
|
||||||
|
# ...and the chosen model actually reaches the Together API call.
|
||||||
|
mock_together_client.embeddings.create.return_value = Mock(data=[Mock(embedding=[0.0] * 768)])
|
||||||
|
embedder.embed("hello")
|
||||||
|
mock_together_client.embeddings.create.assert_called_once_with(model="BAAI/bge-base-en-v1.5", input="hello")
|
||||||
|
|||||||
Reference in New Issue
Block a user