From dcd60f0eb0004c5aa82ae4da58d9ce869fe51e16 Mon Sep 17 00:00:00 2001 From: bhaktatejas922 Date: Mon, 7 Jul 2025 13:44:27 -0700 Subject: [PATCH 1/6] morph embeddings --- chromadb/test/ef/test_ef.py | 1 + chromadb/test/ef/test_morph_ef.py | 126 +++++++++++++++ .../utils/embedding_functions/__init__.py | 6 + .../morph_embedding_function.py | 146 ++++++++++++++++++ .../packages/ai-embeddings/all/package.json | 5 +- .../packages/ai-embeddings/all/src/index.ts | 1 + .../packages/ai-embeddings/morph/README.md | 63 ++++++++ .../packages/ai-embeddings/morph/package.json | 37 +++++ .../packages/ai-embeddings/morph/src/index.ts | 60 +++++++ .../ai-embeddings/morph/tsconfig.json | 19 +++ .../docs/embeddings/embedding-functions.md | 1 + .../integrations/chroma-integrations.md | 3 +- .../integrations/embedding-models/morph.md | 118 ++++++++++++++ schemas/embedding_functions/morph.json | 36 +++++ 14 files changed, 619 insertions(+), 3 deletions(-) create mode 100644 chromadb/test/ef/test_morph_ef.py create mode 100644 chromadb/utils/embedding_functions/morph_embedding_function.py create mode 100644 clients/new-js/packages/ai-embeddings/morph/README.md create mode 100644 clients/new-js/packages/ai-embeddings/morph/package.json create mode 100644 clients/new-js/packages/ai-embeddings/morph/src/index.ts create mode 100644 clients/new-js/packages/ai-embeddings/morph/tsconfig.json create mode 100644 docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md create mode 100644 schemas/embedding_functions/morph.json diff --git a/chromadb/test/ef/test_ef.py b/chromadb/test/ef/test_ef.py index 42cbf3d53a8..d95392293f2 100644 --- a/chromadb/test/ef/test_ef.py +++ b/chromadb/test/ef/test_ef.py @@ -37,6 +37,7 @@ def test_get_builtins_holds() -> None: "InstructorEmbeddingFunction", "JinaEmbeddingFunction", "MistralEmbeddingFunction", + "MorphEmbeddingFunction", "ONNXMiniLM_L6_V2", "OllamaEmbeddingFunction", "OpenAIEmbeddingFunction", diff --git a/chromadb/test/ef/test_morph_ef.py b/chromadb/test/ef/test_morph_ef.py new file mode 100644 index 00000000000..37b713c269f --- /dev/null +++ b/chromadb/test/ef/test_morph_ef.py @@ -0,0 +1,126 @@ +import os +import pytest +from chromadb.utils.embedding_functions.morph_embedding_function import ( + MorphEmbeddingFunction, +) + + +def test_morph_embedding_function_with_api_key() -> None: + """Test Morph embedding function when API key is available.""" + if os.environ.get("CHROMA_MORPH_API_KEY") is None: + pytest.skip("CHROMA_MORPH_API_KEY not set") + + ef = MorphEmbeddingFunction( + model_name="morph-embedding-v2" + ) + + # Test with code snippets (Morph's specialty) + code_snippets = [ + "def hello_world():\n print('Hello, World!')", + "class Calculator:\n def add(self, a, b):\n return a + b" + ] + + embeddings = ef(code_snippets) + assert embeddings is not None + assert len(embeddings) == 2 + assert all(isinstance(emb, list) for emb in embeddings) + assert all(len(emb) > 0 for emb in embeddings) + + +def test_morph_embedding_function_with_custom_parameters() -> None: + """Test Morph embedding function with custom parameters.""" + if os.environ.get("CHROMA_MORPH_API_KEY") is None: + pytest.skip("CHROMA_MORPH_API_KEY not set") + + ef = MorphEmbeddingFunction( + model_name="morph-embedding-v2", + api_base="https://api.morphllm.com/v1", + encoding_format="float", + api_key_env_var="CHROMA_MORPH_API_KEY" + ) + + # Test with a simple function + code_snippet = ["function add(a, b) { return a + b; }"] + + embeddings = ef(code_snippet) + assert embeddings is not None + assert len(embeddings) == 1 + assert isinstance(embeddings[0], list) + assert len(embeddings[0]) > 0 + + +def test_morph_embedding_function_config_roundtrip() -> None: + """Test that Morph embedding function configuration can be saved and restored.""" + ef = MorphEmbeddingFunction( + model_name="morph-embedding-v2", + api_base="https://api.morphllm.com/v1", + encoding_format="float", + api_key_env_var="CHROMA_MORPH_API_KEY" + ) + + # Get configuration + config = ef.get_config() + + # Verify configuration contains expected keys + assert "model_name" in config + assert "api_base" in config + assert "encoding_format" in config + assert "api_key_env_var" in config + + # Verify values + assert config["model_name"] == "morph-embedding-v2" + assert config["api_base"] == "https://api.morphllm.com/v1" + assert config["encoding_format"] == "float" + assert config["api_key_env_var"] == "CHROMA_MORPH_API_KEY" + + # Test building from config + new_ef = MorphEmbeddingFunction.build_from_config(config) + new_config = new_ef.get_config() + + # Configurations should match + assert config == new_config + + +def test_morph_embedding_function_name() -> None: + """Test that Morph embedding function returns correct name.""" + assert MorphEmbeddingFunction.name() == "morph" + + +def test_morph_embedding_function_spaces() -> None: + """Test that Morph embedding function supports expected spaces.""" + ef = MorphEmbeddingFunction( + model_name="morph-embedding-v2", + api_key_env_var="CHROMA_MORPH_API_KEY" + ) + + # Test default space + assert ef.default_space() == "cosine" + + # Test supported spaces + supported_spaces = ef.supported_spaces() + assert "cosine" in supported_spaces + assert "l2" in supported_spaces + assert "ip" in supported_spaces + + +def test_morph_embedding_function_validate_config() -> None: + """Test that Morph embedding function validates configuration correctly.""" + from chromadb.utils.embedding_functions.schemas import validate_config_schema + + # Valid configuration + valid_config = { + "model_name": "morph-embedding-v2", + "api_key_env_var": "CHROMA_MORPH_API_KEY" + } + + # This should not raise an exception + MorphEmbeddingFunction.validate_config(valid_config) + + # Invalid configuration (missing required fields) + invalid_config = { + "model_name": "morph-embedding-v2" + # Missing api_key_env_var + } + + with pytest.raises(Exception): + MorphEmbeddingFunction.validate_config(invalid_config) \ No newline at end of file diff --git a/chromadb/utils/embedding_functions/__init__.py b/chromadb/utils/embedding_functions/__init__.py index 348e55e0d47..28984f139cf 100644 --- a/chromadb/utils/embedding_functions/__init__.py +++ b/chromadb/utils/embedding_functions/__init__.py @@ -64,6 +64,9 @@ from chromadb.utils.embedding_functions.mistral_embedding_function import ( MistralEmbeddingFunction, ) +from chromadb.utils.embedding_functions.morph_embedding_function import ( + MorphEmbeddingFunction, +) try: from chromadb.is_thin_client import is_thin_client @@ -84,6 +87,7 @@ "InstructorEmbeddingFunction", "JinaEmbeddingFunction", "MistralEmbeddingFunction", + "MorphEmbeddingFunction", "VoyageAIEmbeddingFunction", "ONNXMiniLM_L6_V2", "OpenCLIPEmbeddingFunction", @@ -145,6 +149,7 @@ def validate_config(config: Dict[str, Any]) -> None: "instructor": InstructorEmbeddingFunction, "jina": JinaEmbeddingFunction, "mistral": MistralEmbeddingFunction, + "morph": MorphEmbeddingFunction, "voyageai": VoyageAIEmbeddingFunction, "onnx_mini_lm_l6_v2": ONNXMiniLM_L6_V2, "open_clip": OpenCLIPEmbeddingFunction, @@ -233,6 +238,7 @@ def config_to_embedding_function(config: Dict[str, Any]) -> EmbeddingFunction: "InstructorEmbeddingFunction", "JinaEmbeddingFunction", "MistralEmbeddingFunction", + "MorphEmbeddingFunction", "VoyageAIEmbeddingFunction", "ONNXMiniLM_L6_V2", "OpenCLIPEmbeddingFunction", diff --git a/chromadb/utils/embedding_functions/morph_embedding_function.py b/chromadb/utils/embedding_functions/morph_embedding_function.py new file mode 100644 index 00000000000..a1d55a34cfd --- /dev/null +++ b/chromadb/utils/embedding_functions/morph_embedding_function.py @@ -0,0 +1,146 @@ +from chromadb.api.types import Embeddings, Documents, EmbeddingFunction, Space +from typing import List, Dict, Any, Optional +import os +import numpy as np +from chromadb.utils.embedding_functions.schemas import validate_config_schema +import warnings + + +class MorphEmbeddingFunction(EmbeddingFunction[Documents]): + def __init__( + self, + api_key: Optional[str] = None, + model_name: str = "morph-embedding-v2", + api_base: str = "https://api.morphllm.com/v1", + encoding_format: str = "float", + api_key_env_var: str = "CHROMA_MORPH_API_KEY", + ): + """ + Initialize the MorphEmbeddingFunction. + + Args: + api_key (str, optional): The API key for the Morph API. If not provided, + it will be read from the environment variable specified by api_key_env_var. + model_name (str, optional): The name of the model to use for embeddings. + Defaults to "morph-embedding-v2". + api_base (str, optional): The base URL for the Morph API. + Defaults to "https://api.morphllm.com/v1". + encoding_format (str, optional): The format for embeddings (float or base64). + Defaults to "float". + api_key_env_var (str, optional): Environment variable name that contains your API key. + Defaults to "CHROMA_MORPH_API_KEY". + """ + try: + import openai + except ImportError: + raise ValueError( + "The openai python package is not installed. Please install it with `pip install openai`" + ) + + if api_key is not None: + warnings.warn( + "Direct api_key configuration will not be persisted. " + "Please use environment variables via api_key_env_var for persistent storage.", + DeprecationWarning, + ) + + self.api_key_env_var = api_key_env_var + self.api_key = api_key or os.getenv(api_key_env_var) + if not self.api_key: + raise ValueError(f"The {api_key_env_var} environment variable is not set.") + + self.model_name = model_name + self.api_base = api_base + self.encoding_format = encoding_format + + # Initialize the OpenAI client with Morph's base URL + self.client = openai.OpenAI( + api_key=self.api_key, + base_url=self.api_base, + ) + + def __call__(self, input: Documents) -> Embeddings: + """ + Generate embeddings for the given documents. + + Args: + input: Documents to generate embeddings for. + + Returns: + Embeddings for the documents. + """ + # Handle empty input + if not input: + return [] + + # Prepare embedding parameters + embedding_params: Dict[str, Any] = { + "model": self.model_name, + "input": input, + "encoding_format": self.encoding_format, + } + + # Get embeddings from Morph API + response = self.client.embeddings.create(**embedding_params) + + # Extract embeddings from response + return [np.array(data.embedding, dtype=np.float32) for data in response.data] + + @staticmethod + def name() -> str: + return "morph" + + def default_space(self) -> Space: + # Morph embeddings work best with cosine similarity + return "cosine" + + def supported_spaces(self) -> List[Space]: + return ["cosine", "l2", "ip"] + + @staticmethod + def build_from_config(config: Dict[str, Any]) -> "EmbeddingFunction[Documents]": + # Extract parameters from config + api_key_env_var = config.get("api_key_env_var") + model_name = config.get("model_name") + api_base = config.get("api_base") + encoding_format = config.get("encoding_format") + + if api_key_env_var is None or model_name is None: + assert False, "This code should not be reached" + + # Create and return the embedding function + return MorphEmbeddingFunction( + api_key_env_var=api_key_env_var, + model_name=model_name, + api_base=api_base if api_base is not None else "https://api.morphllm.com/v1", + encoding_format=encoding_format if encoding_format is not None else "float", + ) + + def get_config(self) -> Dict[str, Any]: + return { + "api_key_env_var": self.api_key_env_var, + "model_name": self.model_name, + "api_base": self.api_base, + "encoding_format": self.encoding_format, + } + + def validate_config_update( + self, old_config: Dict[str, Any], new_config: Dict[str, Any] + ) -> None: + if "model_name" in new_config: + raise ValueError( + "The model name cannot be changed after the embedding function has been initialized." + ) + + @staticmethod + def validate_config(config: Dict[str, Any]) -> None: + """ + Validate the configuration using the JSON schema. + + Args: + config: Configuration to validate + + Raises: + ValidationError: If the configuration does not match the schema + """ + validate_config_schema(config, "morph") \ No newline at end of file diff --git a/clients/new-js/packages/ai-embeddings/all/package.json b/clients/new-js/packages/ai-embeddings/all/package.json index 1bcbce09835..267235a6247 100644 --- a/clients/new-js/packages/ai-embeddings/all/package.json +++ b/clients/new-js/packages/ai-embeddings/all/package.json @@ -42,11 +42,12 @@ "@chroma-core/google-gemini": "workspace:^", "@chroma-core/huggingface-server": "workspace:^", "@chroma-core/jina": "workspace:^", + "@chroma-core/mistral": "workspace:^", + "@chroma-core/morph": "workspace:^", "@chroma-core/ollama": "workspace:^", "@chroma-core/openai": "workspace:^", "@chroma-core/together-ai": "workspace:^", - "@chroma-core/voyageai": "workspace:^", - "@chroma-core/mistral": "workspace:^" + "@chroma-core/voyageai": "workspace:^" }, "engines": { "node": ">=20" diff --git a/clients/new-js/packages/ai-embeddings/all/src/index.ts b/clients/new-js/packages/ai-embeddings/all/src/index.ts index 0901cd8adf3..d3fecf6592b 100644 --- a/clients/new-js/packages/ai-embeddings/all/src/index.ts +++ b/clients/new-js/packages/ai-embeddings/all/src/index.ts @@ -5,6 +5,7 @@ export * from "@chroma-core/google-gemini"; export * from "@chroma-core/huggingface-server"; export * from "@chroma-core/jina"; export * from "@chroma-core/mistral"; +export * from "@chroma-core/morph"; export * from "@chroma-core/ollama"; export * from "@chroma-core/openai"; export * from "@chroma-core/together-ai"; diff --git a/clients/new-js/packages/ai-embeddings/morph/README.md b/clients/new-js/packages/ai-embeddings/morph/README.md new file mode 100644 index 00000000000..4589cb4bb0d --- /dev/null +++ b/clients/new-js/packages/ai-embeddings/morph/README.md @@ -0,0 +1,63 @@ +# @chroma-core/morph + +Chroma integration for Morph embedding models. + +## Installation + +```bash +npm install @chroma-core/morph +``` + +## Usage + +```typescript +import { MorphEmbeddingFunction } from '@chroma-core/morph'; + +// Initialize the embedding function +const morphEmbedding = new MorphEmbeddingFunction({ + api_key: 'your-morph-api-key', // or set CHROMA_MORPH_API_KEY env var + model_name: 'morph-embedding-v2', // default + api_base: 'https://api.morphllm.com/v1', // default + encoding_format: 'float' // default +}); + +// Generate embeddings for code snippets +const codeSnippets = [ + 'function calculateSum(a, b) { return a + b; }', + 'class User { constructor(name) { this.name = name; } }' +]; + +const embeddings = await morphEmbedding.generate(codeSnippets); +console.log(embeddings); +``` + +## Configuration + +The `MorphEmbeddingFunction` constructor accepts the following options: + +- `api_key` (optional): Your Morph API key. If not provided, it will read from the environment variable specified by `api_key_env_var`. +- `model_name` (optional): The Morph model to use. Defaults to `'morph-embedding-v2'`. +- `api_base` (optional): The base URL for the Morph API. Defaults to `'https://api.morphllm.com/v1'`. +- `encoding_format` (optional): The format for embeddings ('float' or 'base64'). Defaults to `'float'`. +- `api_key_env_var` (optional): The environment variable name for the API key. Defaults to `'CHROMA_MORPH_API_KEY'`. + +## Environment Variables + +Set your Morph API key as an environment variable: + +```bash +export CHROMA_MORPH_API_KEY="your-morph-api-key" +``` + +## Features + +- **Code-Optimized**: Morph embeddings are specifically designed for code and functional units +- **OpenAI-Compatible**: Uses the standard OpenAI SDK with Morph's API endpoint +- **High Performance**: State-of-the-art embeddings for code similarity and search +- **Batch Processing**: Supports multiple inputs in a single API call + +## API Reference + +For more information about Morph's embedding models and API, visit: +- [Morph Embedding API Documentation](https://docs.morphllm.com/api-reference/endpoint/embedding) +- [Morph Website](https://morphllm.com/) \ No newline at end of file diff --git a/clients/new-js/packages/ai-embeddings/morph/package.json b/clients/new-js/packages/ai-embeddings/morph/package.json new file mode 100644 index 00000000000..af1db4721b8 --- /dev/null +++ b/clients/new-js/packages/ai-embeddings/morph/package.json @@ -0,0 +1,37 @@ +{ + "name": "@chroma-core/morph", + "version": "1.0.0", + "description": "Chroma integration for Morph embedding models", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc", + "clean": "rm -rf dist", + "test": "jest" + }, + "dependencies": { + "@chroma-core/common": "workspace:*", + "openai": "^4.0.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "typescript": "^5.0.0" + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/chroma-core/chroma.git" + }, + "keywords": [ + "chroma", + "embeddings", + "morph", + "ai", + "vector", + "database" + ], + "author": "Chroma", + "license": "MIT" +} \ No newline at end of file diff --git a/clients/new-js/packages/ai-embeddings/morph/src/index.ts b/clients/new-js/packages/ai-embeddings/morph/src/index.ts new file mode 100644 index 00000000000..0a25828c082 --- /dev/null +++ b/clients/new-js/packages/ai-embeddings/morph/src/index.ts @@ -0,0 +1,60 @@ +import { EmbeddingFunction } from '@chroma-core/common'; +import { OpenAI } from 'openai'; + +export interface MorphEmbeddingFunctionConfig { + api_key?: string; + model_name?: string; + api_base?: string; + encoding_format?: 'float' | 'base64'; + api_key_env_var?: string; +} + +export class MorphEmbeddingFunction implements EmbeddingFunction { + private client: OpenAI; + private model_name: string; + private encoding_format: 'float' | 'base64'; + + constructor(config: MorphEmbeddingFunctionConfig = {}) { + const { + api_key, + model_name = 'morph-embedding-v2', + api_base = 'https://api.morphllm.com/v1', + encoding_format = 'float', + api_key_env_var = 'CHROMA_MORPH_API_KEY' + } = config; + + // Get API key from config or environment + const apiKey = api_key || process.env[api_key_env_var]; + if (!apiKey) { + throw new Error(`API key not found. Please set ${api_key_env_var} environment variable or provide api_key in config.`); + } + + this.client = new OpenAI({ + apiKey, + baseURL: api_base, + }); + + this.model_name = model_name; + this.encoding_format = encoding_format; + } + + public async generate(texts: string[]): Promise { + if (!texts || texts.length === 0) { + return []; + } + + try { + const response = await this.client.embeddings.create({ + model: this.model_name, + input: texts, + encoding_format: this.encoding_format, + }); + + return response.data.map(item => item.embedding); + } catch (error) { + throw new Error(`Morph embedding generation failed: ${error}`); + } + } +} + +export default MorphEmbeddingFunction; \ No newline at end of file diff --git a/clients/new-js/packages/ai-embeddings/morph/tsconfig.json b/clients/new-js/packages/ai-embeddings/morph/tsconfig.json new file mode 100644 index 00000000000..447b1b68de0 --- /dev/null +++ b/clients/new-js/packages/ai-embeddings/morph/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "dist", + "node_modules", + "**/*.test.ts", + "**/*.spec.ts" + ] +} \ No newline at end of file diff --git a/docs/docs.trychroma.com/markdoc/content/docs/embeddings/embedding-functions.md b/docs/docs.trychroma.com/markdoc/content/docs/embeddings/embedding-functions.md index a1c7c1c43ad..ebbfc9aefae 100644 --- a/docs/docs.trychroma.com/markdoc/content/docs/embeddings/embedding-functions.md +++ b/docs/docs.trychroma.com/markdoc/content/docs/embeddings/embedding-functions.md @@ -16,6 +16,7 @@ Chroma provides lightweight wrappers around popular embedding providers, making | [Cloudflare Workers AI](../../integrations/embedding-models/cloudflare-workers-ai) | ✓ | ✓ | | [Together AI](../../integrations/embedding-models/together-ai) | ✓ | ✓ | | [Mistral](../../integrations/embedding-models/mistral) | ✓ | ✓ | +| [Morph](../../integrations/embedding-models/morph) | ✓ | ✓ | We welcome pull requests to add new Embedding Functions to the community. diff --git a/docs/docs.trychroma.com/markdoc/content/integrations/chroma-integrations.md b/docs/docs.trychroma.com/markdoc/content/integrations/chroma-integrations.md index 775bccd615a..826a346c8bb 100644 --- a/docs/docs.trychroma.com/markdoc/content/integrations/chroma-integrations.md +++ b/docs/docs.trychroma.com/markdoc/content/integrations/chroma-integrations.md @@ -23,7 +23,8 @@ Chroma provides lightweight wrappers around popular embedding providers, making | [Ollama Embeddings](./embedding-models/ollama) | ✓ | ✓ | | [Cloudflare Workers AI](./embedding-models/cloudflare-workers-ai.md) | ✓ | ✓ | | [Together AI](./embedding-models/together-ai.md) | ✓ | ✓ | -| [Mistral](./embedding-models/mistral.md) | ✓ | - | +| [Mistral](./embedding-models/mistral.md) | ✓ | ✓ | +| [Morph](./embedding-models/morph.md) | ✓ | ✓ | --- diff --git a/docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md b/docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md new file mode 100644 index 00000000000..34e27179cd3 --- /dev/null +++ b/docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md @@ -0,0 +1,118 @@ +--- +name: Morph +id: morph +--- + +# Morph + +Chroma provides a convenient wrapper around Morph's embedding API. This embedding function runs remotely on Morph's servers and requires an API key. You can get an API key by signing up for an account at [Morph](https://morphllm.com/). + +Morph embeddings are optimized to be state-of-the-art for code and are specifically designed for functional units like Syntax Tree Nodes (functions, classes, etc.) rather than arbitrary text chunks. + +{% Banner type="tip" %} +Visit Morph's [embedding documentation](https://docs.morphllm.com/api-reference/endpoint/embedding) for more information on their code-optimized embedding models. +{% /Banner %} + +{% Tabs %} + +{% Tab label="python" %} + +This embedding function relies on the `openai` python package, which you can install with `pip install openai`. + +```python +import chromadb.utils.embedding_functions as embedding_functions + +# Set your API key as an environment variable +import os +os.environ["CHROMA_MORPH_API_KEY"] = "your-morph-api-key" + +morph_ef = embedding_functions.MorphEmbeddingFunction( + model_name="morph-embedding-v2" +) + +# Use with code snippets for optimal performance +code_snippets = [ + "def calculate_sum(a, b):\n return a + b", + "class User:\n def __init__(self, name):\n self.name = name" +] + +embeddings = morph_ef(code_snippets) +``` + +You can also specify additional parameters: + +```python +morph_ef = embedding_functions.MorphEmbeddingFunction( + model_name="morph-embedding-v2", + api_base="https://api.morphllm.com/v1", # Default base URL + encoding_format="float", # Default format + api_key_env_var="CHROMA_MORPH_API_KEY" # Default env var +) +``` + +{% /Tab %} + +{% Tab label="typescript" %} + +You can use Morph embeddings in TypeScript by installing the OpenAI package and configuring it for Morph's API: + +```typescript +// npm install openai + +import { OpenAI } from 'openai'; + +const client = new OpenAI({ + apiKey: process.env.CHROMA_MORPH_API_KEY, + baseURL: 'https://api.morphllm.com/v1' +}); + +async function generateEmbeddings(codeSnippets: string[]) { + const response = await client.embeddings.create({ + model: "morph-embedding-v2", + input: codeSnippets + }); + + return response.data.map(item => item.embedding); +} + +// Use with code snippets for optimal performance +const codeSnippets = [ + "function calculateSum(a, b) { return a + b; }", + "class User { constructor(name) { this.name = name; } }" +]; + +const embeddings = await generateEmbeddings(codeSnippets); +``` + +{% /Tab %} + +{% /Tabs %} + +## Key Features + +- **Code-Optimized**: Specifically designed for code embeddings and functional units +- **OpenAI-Compatible**: Uses the standard OpenAI SDK with Morph's API endpoint +- **High Performance**: State-of-the-art embeddings for code similarity and search +- **Batch Processing**: Supports multiple inputs in a single API call +- **Flexible Input**: Works with various programming languages and code structures + +## Best Practices + +1. **Functional Units**: Morph embeddings work best with complete functional units (functions, classes, methods) rather than arbitrary code fragments +2. **Syntax Tree Nodes**: Consider using Morph's SDK for automatic syntax tree parsing and embedding +3. **Code Similarity**: Ideal for code search, duplicate detection, and similarity analysis +4. **Mixed Content**: Can handle both code and natural language, making it versatile for documentation and comments + +## Environment Variables + +Set your Morph API key as an environment variable: + +```bash +export CHROMA_MORPH_API_KEY="your-morph-api-key" +``` + +## API Reference + +For more information about Morph's embedding models and API, visit: +- [Morph Embedding API Documentation](https://docs.morphllm.com/api-reference/endpoint/embedding) +- [Morph Website](https://morphllm.com/) \ No newline at end of file diff --git a/schemas/embedding_functions/morph.json b/schemas/embedding_functions/morph.json new file mode 100644 index 00000000000..636994a2baf --- /dev/null +++ b/schemas/embedding_functions/morph.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Morph Embedding Function Schema", + "description": "Schema for the Morph embedding function configuration", + "version": "1.0.0", + "type": "object", + "properties": { + "model_name": { + "type": "string", + "description": "The name of the model to use for embeddings" + }, + "api_key_env_var": { + "type": "string", + "description": "Environment variable name that contains your API key for the Morph API" + }, + "api_base": { + "type": [ + "string", + "null" + ], + "description": "The base URL for the Morph API" + }, + "encoding_format": { + "type": [ + "string", + "null" + ], + "description": "The format for embeddings (float or base64)" + } + }, + "required": [ + "api_key_env_var", + "model_name" + ], + "additionalProperties": false +} \ No newline at end of file From 5dabbfe7c297e5478e26a2a4c280b4dc9eb0bdd2 Mon Sep 17 00:00:00 2001 From: bhaktatejas922 Date: Sat, 26 Jul 2025 20:28:02 -0700 Subject: [PATCH 2/6] morph openai note --- chromadb/utils/embedding_functions/morph_embedding_function.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chromadb/utils/embedding_functions/morph_embedding_function.py b/chromadb/utils/embedding_functions/morph_embedding_function.py index a1d55a34cfd..690bbf73b73 100644 --- a/chromadb/utils/embedding_functions/morph_embedding_function.py +++ b/chromadb/utils/embedding_functions/morph_embedding_function.py @@ -34,7 +34,8 @@ def __init__( import openai except ImportError: raise ValueError( - "The openai python package is not installed. Please install it with `pip install openai`" + "The openai python package is not installed. Please install it with `pip install openai`. " + "Note: Morph uses the OpenAI client library for API communication." ) if api_key is not None: From 98390a4164b3a933c7cdd20687825b75a1fb7bca Mon Sep 17 00:00:00 2001 From: bhaktatejas922 Date: Sat, 26 Jul 2025 20:31:26 -0700 Subject: [PATCH 3/6] Update clients/new-js/packages/ai-embeddings/morph/src/index.ts Co-authored-by: propel-code-bot[bot] <203372662+propel-code-bot[bot]@users.noreply.github.com> --- clients/new-js/packages/ai-embeddings/morph/src/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/clients/new-js/packages/ai-embeddings/morph/src/index.ts b/clients/new-js/packages/ai-embeddings/morph/src/index.ts index 0a25828c082..f09a2a24e5d 100644 --- a/clients/new-js/packages/ai-embeddings/morph/src/index.ts +++ b/clients/new-js/packages/ai-embeddings/morph/src/index.ts @@ -56,5 +56,3 @@ export class MorphEmbeddingFunction implements EmbeddingFunction { } } } - -export default MorphEmbeddingFunction; \ No newline at end of file From d0a402e950c5431ba4fc029e6070b5303f5bf5ed Mon Sep 17 00:00:00 2001 From: bhaktatejas922 Date: Sat, 26 Jul 2025 21:12:25 -0700 Subject: [PATCH 4/6] config stuff --- .../ai-embeddings/common/src/schema-utils.ts | 2 + .../packages/ai-embeddings/morph/package.json | 5 +- .../packages/ai-embeddings/morph/src/index.ts | 88 +++++++++++++++---- 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/clients/new-js/packages/ai-embeddings/common/src/schema-utils.ts b/clients/new-js/packages/ai-embeddings/common/src/schema-utils.ts index 5cf00e5e1f1..05ac863d2af 100644 --- a/clients/new-js/packages/ai-embeddings/common/src/schema-utils.ts +++ b/clients/new-js/packages/ai-embeddings/common/src/schema-utils.ts @@ -22,6 +22,7 @@ import voyageaiSchema from "../../../../../../schemas/embedding_functions/voyage import cloudflareWorkersAiSchema from "../../../../../../schemas/embedding_functions/cloudflare_workers_ai.json"; import togetherAiSchema from "../../../../../../schemas/embedding_functions/together_ai.json"; import mistralSchema from "../../../../../../schemas/embedding_functions/mistral.json"; +import morphSchema from "../../../../../../schemas/embedding_functions/morph.json"; import Ajv from "ajv"; // Define a common interface for all schemas @@ -68,6 +69,7 @@ const schemaMap = { "cloudflare-worker-ai": cloudflareWorkersAiSchema as Schema, "together-ai": togetherAiSchema as Schema, mistral: mistralSchema as Schema, + morph: morphSchema as Schema, }; /** diff --git a/clients/new-js/packages/ai-embeddings/morph/package.json b/clients/new-js/packages/ai-embeddings/morph/package.json index af1db4721b8..9876968881d 100644 --- a/clients/new-js/packages/ai-embeddings/morph/package.json +++ b/clients/new-js/packages/ai-embeddings/morph/package.json @@ -9,8 +9,11 @@ "clean": "rm -rf dist", "test": "jest" }, + "peerDependencies": { + "chromadb": "workspace:^" + }, "dependencies": { - "@chroma-core/common": "workspace:*", + "@chroma-core/ai-embeddings-common": "workspace:^", "openai": "^4.0.0" }, "devDependencies": { diff --git a/clients/new-js/packages/ai-embeddings/morph/src/index.ts b/clients/new-js/packages/ai-embeddings/morph/src/index.ts index f09a2a24e5d..bda7007c573 100644 --- a/clients/new-js/packages/ai-embeddings/morph/src/index.ts +++ b/clients/new-js/packages/ai-embeddings/morph/src/index.ts @@ -1,5 +1,20 @@ -import { EmbeddingFunction } from '@chroma-core/common'; -import { OpenAI } from 'openai'; +import { + ChromaValueError, + EmbeddingFunction, + EmbeddingFunctionSpace, + registerEmbeddingFunction, +} from "chromadb"; +import { validateConfigSchema } from "@chroma-core/ai-embeddings-common"; +import OpenAI from "openai"; + +const NAME = "morph"; + +export interface MorphConfig { + api_key_env_var: string; + model_name: string; + api_base?: string; + encoding_format?: 'float' | 'base64'; +} export interface MorphEmbeddingFunctionConfig { api_key?: string; @@ -10,9 +25,12 @@ export interface MorphEmbeddingFunctionConfig { } export class MorphEmbeddingFunction implements EmbeddingFunction { + public readonly name = NAME; + private readonly apiKeyEnvVar: string; + private readonly modelName: string; + private readonly encodingFormat: 'float' | 'base64'; + private readonly apiBase: string; private client: OpenAI; - private model_name: string; - private encoding_format: 'float' | 'base64'; constructor(config: MorphEmbeddingFunctionConfig = {}) { const { @@ -29,30 +47,62 @@ export class MorphEmbeddingFunction implements EmbeddingFunction { throw new Error(`API key not found. Please set ${api_key_env_var} environment variable or provide api_key in config.`); } + this.modelName = model_name; + this.encodingFormat = encoding_format; + this.apiKeyEnvVar = api_key_env_var; + this.apiBase = api_base; + this.client = new OpenAI({ apiKey, baseURL: api_base, }); - - this.model_name = model_name; - this.encoding_format = encoding_format; } public async generate(texts: string[]): Promise { - if (!texts || texts.length === 0) { - return []; - } + const response = await this.client.embeddings.create({ + model: this.modelName, + input: texts, + encoding_format: this.encodingFormat, + }); + + return response.data.map(item => item.embedding); + } - try { - const response = await this.client.embeddings.create({ - model: this.model_name, - input: texts, - encoding_format: this.encoding_format, - }); + public defaultSpace(): EmbeddingFunctionSpace { + return "cosine"; + } + + public supportedSpaces(): EmbeddingFunctionSpace[] { + return ["cosine", "l2", "ip"]; + } + + public static buildFromConfig(config: MorphConfig): MorphEmbeddingFunction { + return new MorphEmbeddingFunction({ + model_name: config.model_name, + api_key_env_var: config.api_key_env_var, + api_base: config.api_base, + encoding_format: config.encoding_format, + }); + } - return response.data.map(item => item.embedding); - } catch (error) { - throw new Error(`Morph embedding generation failed: ${error}`); + public getConfig(): MorphConfig { + return { + api_key_env_var: this.apiKeyEnvVar, + model_name: this.modelName, + api_base: this.apiBase, + encoding_format: this.encodingFormat, + }; + } + + public validateConfigUpdate(newConfig: Record): void { + if (this.getConfig().model_name !== newConfig.model_name) { + throw new ChromaValueError("Model name cannot be updated"); } } + + public static validateConfig(config: MorphConfig): void { + validateConfigSchema(config, NAME); + } } + +registerEmbeddingFunction(NAME, MorphEmbeddingFunction); From 40e993b548b5e7dac02552ae26ac6db667a4a23e Mon Sep 17 00:00:00 2001 From: Jeffrey Huber Date: Sun, 27 Jul 2025 14:58:14 -0700 Subject: [PATCH 5/6] bump commit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7579f324dcb..dc82dfe14a0 100644 --- a/README.md +++ b/README.md @@ -104,3 +104,4 @@ We currently release new tagged versions of the `pypi` and `npm` packages on Mon ## License [Apache 2.0](./LICENSE) + From c8efaebe9e73bc7947bc027449f4fcfb1640a892 Mon Sep 17 00:00:00 2001 From: "Philip I. Thomas" Date: Fri, 1 Aug 2025 10:25:18 -0700 Subject: [PATCH 6/6] Rename "CHROMA_MORPH_API_KEY" to "MORPH_API_KEY" --- .../morph_embedding_function.py | 12 +- .../packages/ai-embeddings/morph/README.md | 8 +- .../packages/ai-embeddings/morph/src/index.ts | 174 +++++++++--------- .../integrations/embedding-models/morph.md | 12 +- ...ms-integrations-embedding-models-morph.txt | 10 +- 5 files changed, 108 insertions(+), 108 deletions(-) diff --git a/chromadb/utils/embedding_functions/morph_embedding_function.py b/chromadb/utils/embedding_functions/morph_embedding_function.py index 690bbf73b73..ac8e569714d 100644 --- a/chromadb/utils/embedding_functions/morph_embedding_function.py +++ b/chromadb/utils/embedding_functions/morph_embedding_function.py @@ -13,11 +13,11 @@ def __init__( model_name: str = "morph-embedding-v2", api_base: str = "https://api.morphllm.com/v1", encoding_format: str = "float", - api_key_env_var: str = "CHROMA_MORPH_API_KEY", + api_key_env_var: str = "MORPH_API_KEY", ): """ Initialize the MorphEmbeddingFunction. - + Args: api_key (str, optional): The API key for the Morph API. If not provided, it will be read from the environment variable specified by api_key_env_var. @@ -28,7 +28,7 @@ def __init__( encoding_format (str, optional): The format for embeddings (float or base64). Defaults to "float". api_key_env_var (str, optional): Environment variable name that contains your API key. - Defaults to "CHROMA_MORPH_API_KEY". + Defaults to "MORPH_API_KEY". """ try: import openai @@ -63,10 +63,10 @@ def __init__( def __call__(self, input: Documents) -> Embeddings: """ Generate embeddings for the given documents. - + Args: input: Documents to generate embeddings for. - + Returns: Embeddings for the documents. """ @@ -144,4 +144,4 @@ def validate_config(config: Dict[str, Any]) -> None: Raises: ValidationError: If the configuration does not match the schema """ - validate_config_schema(config, "morph") \ No newline at end of file + validate_config_schema(config, "morph") \ No newline at end of file diff --git a/clients/new-js/packages/ai-embeddings/morph/README.md b/clients/new-js/packages/ai-embeddings/morph/README.md index 4589cb4bb0d..01084932f36 100644 --- a/clients/new-js/packages/ai-embeddings/morph/README.md +++ b/clients/new-js/packages/ai-embeddings/morph/README.md @@ -15,7 +15,7 @@ import { MorphEmbeddingFunction } from '@chroma-core/morph'; // Initialize the embedding function const morphEmbedding = new MorphEmbeddingFunction({ - api_key: 'your-morph-api-key', // or set CHROMA_MORPH_API_KEY env var + api_key: 'your-morph-api-key', // or set MORPH_API_KEY env var model_name: 'morph-embedding-v2', // default api_base: 'https://api.morphllm.com/v1', // default encoding_format: 'float' // default @@ -39,14 +39,14 @@ The `MorphEmbeddingFunction` constructor accepts the following options: - `model_name` (optional): The Morph model to use. Defaults to `'morph-embedding-v2'`. - `api_base` (optional): The base URL for the Morph API. Defaults to `'https://api.morphllm.com/v1'`. - `encoding_format` (optional): The format for embeddings ('float' or 'base64'). Defaults to `'float'`. -- `api_key_env_var` (optional): The environment variable name for the API key. Defaults to `'CHROMA_MORPH_API_KEY'`. +- `api_key_env_var` (optional): The environment variable name for the API key. Defaults to `'MORPH_API_KEY'`. ## Environment Variables Set your Morph API key as an environment variable: ```bash -export CHROMA_MORPH_API_KEY="your-morph-api-key" +export MORPH_API_KEY="your-morph-api-key" ``` ## Features @@ -60,4 +60,4 @@ export CHROMA_MORPH_API_KEY="your-morph-api-key" For more information about Morph's embedding models and API, visit: - [Morph Embedding API Documentation](https://docs.morphllm.com/api-reference/endpoint/embedding) -- [Morph Website](https://morphllm.com/) \ No newline at end of file +- [Morph Website](https://morphllm.com/) \ No newline at end of file diff --git a/clients/new-js/packages/ai-embeddings/morph/src/index.ts b/clients/new-js/packages/ai-embeddings/morph/src/index.ts index bda7007c573..37b2f869cf9 100644 --- a/clients/new-js/packages/ai-embeddings/morph/src/index.ts +++ b/clients/new-js/packages/ai-embeddings/morph/src/index.ts @@ -1,8 +1,8 @@ import { - ChromaValueError, - EmbeddingFunction, - EmbeddingFunctionSpace, - registerEmbeddingFunction, + ChromaValueError, + EmbeddingFunction, + EmbeddingFunctionSpace, + registerEmbeddingFunction, } from "chromadb"; import { validateConfigSchema } from "@chroma-core/ai-embeddings-common"; import OpenAI from "openai"; @@ -10,99 +10,99 @@ import OpenAI from "openai"; const NAME = "morph"; export interface MorphConfig { - api_key_env_var: string; - model_name: string; - api_base?: string; - encoding_format?: 'float' | 'base64'; + api_key_env_var: string; + model_name: string; + api_base?: string; + encoding_format?: 'float' | 'base64'; } export interface MorphEmbeddingFunctionConfig { - api_key?: string; - model_name?: string; - api_base?: string; - encoding_format?: 'float' | 'base64'; - api_key_env_var?: string; + api_key?: string; + model_name?: string; + api_base?: string; + encoding_format?: 'float' | 'base64'; + api_key_env_var?: string; } export class MorphEmbeddingFunction implements EmbeddingFunction { - public readonly name = NAME; - private readonly apiKeyEnvVar: string; - private readonly modelName: string; - private readonly encodingFormat: 'float' | 'base64'; - private readonly apiBase: string; - private client: OpenAI; - - constructor(config: MorphEmbeddingFunctionConfig = {}) { - const { - api_key, - model_name = 'morph-embedding-v2', - api_base = 'https://api.morphllm.com/v1', - encoding_format = 'float', - api_key_env_var = 'CHROMA_MORPH_API_KEY' - } = config; - - // Get API key from config or environment - const apiKey = api_key || process.env[api_key_env_var]; - if (!apiKey) { - throw new Error(`API key not found. Please set ${api_key_env_var} environment variable or provide api_key in config.`); - } - - this.modelName = model_name; - this.encodingFormat = encoding_format; - this.apiKeyEnvVar = api_key_env_var; - this.apiBase = api_base; - - this.client = new OpenAI({ - apiKey, - baseURL: api_base, - }); + public readonly name = NAME; + private readonly apiKeyEnvVar: string; + private readonly modelName: string; + private readonly encodingFormat: 'float' | 'base64'; + private readonly apiBase: string; + private client: OpenAI; + + constructor(config: MorphEmbeddingFunctionConfig = {}) { + const { + api_key, + model_name = 'morph-embedding-v2', + api_base = 'https://api.morphllm.com/v1', + encoding_format = 'float', + api_key_env_var = 'MORPH_API_KEY' + } = config; + + // Get API key from config or environment + const apiKey = api_key || process.env[api_key_env_var]; + if (!apiKey) { + throw new Error(`API key not found. Please set ${api_key_env_var} environment variable or provide api_key in config.`); } - public async generate(texts: string[]): Promise { - const response = await this.client.embeddings.create({ - model: this.modelName, - input: texts, - encoding_format: this.encodingFormat, - }); - - return response.data.map(item => item.embedding); - } - - public defaultSpace(): EmbeddingFunctionSpace { - return "cosine"; - } - - public supportedSpaces(): EmbeddingFunctionSpace[] { - return ["cosine", "l2", "ip"]; - } - - public static buildFromConfig(config: MorphConfig): MorphEmbeddingFunction { - return new MorphEmbeddingFunction({ - model_name: config.model_name, - api_key_env_var: config.api_key_env_var, - api_base: config.api_base, - encoding_format: config.encoding_format, - }); - } - - public getConfig(): MorphConfig { - return { - api_key_env_var: this.apiKeyEnvVar, - model_name: this.modelName, - api_base: this.apiBase, - encoding_format: this.encodingFormat, - }; + this.modelName = model_name; + this.encodingFormat = encoding_format; + this.apiKeyEnvVar = api_key_env_var; + this.apiBase = api_base; + + this.client = new OpenAI({ + apiKey, + baseURL: api_base, + }); + } + + public async generate(texts: string[]): Promise { + const response = await this.client.embeddings.create({ + model: this.modelName, + input: texts, + encoding_format: this.encodingFormat, + }); + + return response.data.map(item => item.embedding); + } + + public defaultSpace(): EmbeddingFunctionSpace { + return "cosine"; + } + + public supportedSpaces(): EmbeddingFunctionSpace[] { + return ["cosine", "l2", "ip"]; + } + + public static buildFromConfig(config: MorphConfig): MorphEmbeddingFunction { + return new MorphEmbeddingFunction({ + model_name: config.model_name, + api_key_env_var: config.api_key_env_var, + api_base: config.api_base, + encoding_format: config.encoding_format, + }); + } + + public getConfig(): MorphConfig { + return { + api_key_env_var: this.apiKeyEnvVar, + model_name: this.modelName, + api_base: this.apiBase, + encoding_format: this.encodingFormat, + }; + } + + public validateConfigUpdate(newConfig: Record): void { + if (this.getConfig().model_name !== newConfig.model_name) { + throw new ChromaValueError("Model name cannot be updated"); } + } - public validateConfigUpdate(newConfig: Record): void { - if (this.getConfig().model_name !== newConfig.model_name) { - throw new ChromaValueError("Model name cannot be updated"); - } - } - - public static validateConfig(config: MorphConfig): void { - validateConfigSchema(config, NAME); - } + public static validateConfig(config: MorphConfig): void { + validateConfigSchema(config, NAME); + } } registerEmbeddingFunction(NAME, MorphEmbeddingFunction); diff --git a/docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md b/docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md index 34e27179cd3..69f6b3169de 100644 --- a/docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md +++ b/docs/docs.trychroma.com/markdoc/content/integrations/embedding-models/morph.md @@ -24,7 +24,7 @@ import chromadb.utils.embedding_functions as embedding_functions # Set your API key as an environment variable import os -os.environ["CHROMA_MORPH_API_KEY"] = "your-morph-api-key" +os.environ["MORPH_API_KEY"] = "your-morph-api-key" morph_ef = embedding_functions.MorphEmbeddingFunction( model_name="morph-embedding-v2" @@ -46,7 +46,7 @@ morph_ef = embedding_functions.MorphEmbeddingFunction( model_name="morph-embedding-v2", api_base="https://api.morphllm.com/v1", # Default base URL encoding_format="float", # Default format - api_key_env_var="CHROMA_MORPH_API_KEY" # Default env var + api_key_env_var="MORPH_API_KEY" # Default env var ) ``` @@ -62,7 +62,7 @@ You can use Morph embeddings in TypeScript by installing the OpenAI package and import { OpenAI } from 'openai'; const client = new OpenAI({ - apiKey: process.env.CHROMA_MORPH_API_KEY, + apiKey: process.env.MORPH_API_KEY, baseURL: 'https://api.morphllm.com/v1' }); @@ -71,7 +71,7 @@ async function generateEmbeddings(codeSnippets: string[]) { model: "morph-embedding-v2", input: codeSnippets }); - + return response.data.map(item => item.embedding); } @@ -108,11 +108,11 @@ const embeddings = await generateEmbeddings(codeSnippets); Set your Morph API key as an environment variable: ```bash -export CHROMA_MORPH_API_KEY="your-morph-api-key" +export MORPH_API_KEY="your-morph-api-key" ``` ## API Reference For more information about Morph's embedding models and API, visit: - [Morph Embedding API Documentation](https://docs.morphllm.com/api-reference/endpoint/embedding) -- [Morph Website](https://morphllm.com/) \ No newline at end of file +- [Morph Website](https://morphllm.com/) \ No newline at end of file diff --git a/docs/docs.trychroma.com/public/llms-integrations-embedding-models-morph.txt b/docs/docs.trychroma.com/public/llms-integrations-embedding-models-morph.txt index 72bbbabd718..480584fc7db 100644 --- a/docs/docs.trychroma.com/public/llms-integrations-embedding-models-morph.txt +++ b/docs/docs.trychroma.com/public/llms-integrations-embedding-models-morph.txt @@ -20,7 +20,7 @@ import chromadb.utils.embedding_functions as embedding_functions # Set your API key as an environment variable import os -os.environ["CHROMA_MORPH_API_KEY"] = "your-morph-api-key" +os.environ["MORPH_API_KEY"] = "your-morph-api-key" morph_ef = embedding_functions.MorphEmbeddingFunction( model_name="morph-embedding-v2" @@ -42,7 +42,7 @@ morph_ef = embedding_functions.MorphEmbeddingFunction( model_name="morph-embedding-v2", api_base="https://api.morphllm.com/v1", # Default base URL encoding_format="float", # Default format - api_key_env_var="CHROMA_MORPH_API_KEY" # Default env var + api_key_env_var="MORPH_API_KEY" # Default env var ) ``` @@ -56,7 +56,7 @@ You can use Morph embeddings in TypeScript by installing the OpenAI package and import { OpenAI } from 'openai'; const client = new OpenAI({ - apiKey: process.env.CHROMA_MORPH_API_KEY, + apiKey: process.env.MORPH_API_KEY, baseURL: 'https://api.morphllm.com/v1' }); @@ -65,7 +65,7 @@ async function generateEmbeddings(codeSnippets: string[]) { model: "morph-embedding-v2", input: codeSnippets }); - + return response.data.map(item => item.embedding); } @@ -98,7 +98,7 @@ const embeddings = await generateEmbeddings(codeSnippets); Set your Morph API key as an environment variable: ```bash -export CHROMA_MORPH_API_KEY="your-morph-api-key" +export MORPH_API_KEY="your-morph-api-key" ``` ## API Reference