npm package: @stylor/embeddings
Description: JavaScript SDK for Stylor Embedding API - multimodal embeddings for text and images
Latest version: 1.0.0

# Stylor Embedding SDK

JavaScript/TypeScript SDK for the Stylor Embedding API. Works in both Node.js and browser environments.

## Installation

```bash
npm install @stylor/embedding-sdk
```

Or include directly in browser:
```html
<script src="path/to/dist/index.mjs" type="module"></script>
```

## Quick Start

```javascript
import StylorEmbedding from '@stylor/embedding-sdk';

const client = new StylorEmbedding({
  apiKey: 'your-api-key',
  baseUrl: 'https://your-endpoint.modal.run',
});

// Generate text embeddings
const embeddings = await client.embedText(['hello world', 'goodbye world']);
console.log(embeddings[0].length); // 1152

// Generate image embeddings
const imageEmbeddings = await client.embedImageUrl('https://example.com/image.jpg');

// Compare text to image
const result = await client.compareTextToImage(
  'a photo of a dog',
  { url: 'https://example.com/dog.jpg' }
);
console.log(result); // { score: 0.12, normalized: 67.5, interpretation: 'Good match' }
```

## API Reference

### Constructor

```javascript
const client = new StylorEmbedding({
  apiKey: 'required',           // Your API key
  baseUrl: 'https://...',       // API base URL
  model: 'siglip-so400m',       // Default model (optional)
  timeout: 60000,               // Request timeout in ms (optional)
});
```

### Methods

#### `health()`
Check if the API is healthy.

```javascript
const status = await client.health();
// { status: 'healthy', models_loaded: ['siglip-so400m'] }
```

#### `listModels()`
List available models.

```javascript
const models = await client.listModels();
// [{ id: 'siglip-so400m', description: '...', embedding_dim: 1152, ... }]
```

#### `embedText(texts, options?)`
Generate embeddings for text.

```javascript
// Single text
const [embedding] = await client.embedText('hello world');

// Multiple texts
const embeddings = await client.embedText(['hello', 'world']);
```

#### `embedImage(images, options?)`
Generate embeddings for images.

```javascript
// From URL
const embeddings = await client.embedImage([{ url: 'https://...' }]);

// From base64
const embeddings = await client.embedImage([{ base64: 'iVBORw0KGgo...' }]);
```

#### `embedImageUrl(urls, options?)`
Convenience method for URL images.

```javascript
const embeddings = await client.embedImageUrl('https://example.com/image.jpg');
const embeddings = await client.embedImageUrl(['url1', 'url2']);
```

#### `embedImageBase64(base64Data, options?)`
Convenience method for base64 images.

```javascript
const embeddings = await client.embedImageBase64(base64String);
```

### Similarity Methods

#### `compareTexts(textA, textB, options?)`
Compare two texts.

```javascript
const result = await client.compareTexts('dog', 'puppy');
// { score: 0.85, normalized: 92.3, interpretation: 'Strong match' }
```

#### `compareTextToImage(text, image, options?)`
Compare text to an image.

```javascript
const result = await client.compareTextToImage(
  'a golden retriever',
  { url: 'https://example.com/dog.jpg' }
);
// { score: 0.12, normalized: 67.5, interpretation: 'Good match' }
```

#### `compareImages(imageA, imageB, options?)`
Compare two images.

```javascript
const result = await client.compareImages(
  { url: 'https://example.com/dog1.jpg' },
  { url: 'https://example.com/dog2.jpg' }
);
```

### Search Methods

#### `searchTexts(query, candidates, options?)`
Find most similar texts to a query.

```javascript
const results = await client.searchTexts(
  'cute animal',
  ['a dog playing', 'a car driving', 'a cat sleeping'],
  { topK: 2 }
);
// [
//   { index: 0, text: 'a dog playing', similarity: {...} },
//   { index: 2, text: 'a cat sleeping', similarity: {...} }
// ]
```

#### `searchImages(query, images, options?)`
Find most similar images to a text query.

```javascript
const results = await client.searchImages(
  'beach sunset',
  [{ url: 'img1.jpg' }, { url: 'img2.jpg' }, { url: 'img3.jpg' }],
  { topK: 2 }
);
// [{ index: 2, similarity: {...} }, { index: 0, similarity: {...} }]
```

### Static Methods

#### `StylorEmbedding.cosineSimilarity(a, b)`
Calculate cosine similarity between two vectors.

```javascript
const similarity = StylorEmbedding.cosineSimilarity(embedding1, embedding2);
// 0.85
```

#### `StylorEmbedding.normalizeSimilarity(score)`
Normalize a raw similarity score.

```javascript
const result = StylorEmbedding.normalizeSimilarity(0.12);
// { score: 0.12, normalized: 67.5, interpretation: 'Good match' }
```

#### `StylorEmbedding.findSimilar(query, candidates, options?)`
Find most similar embeddings from a list.

```javascript
const results = StylorEmbedding.findSimilar(
  queryEmbedding,
  candidateEmbeddings,
  { topK: 5 }
);
```

## Similarity Score Guide

For SigLIP cross-modal (text-to-image) comparisons:

| Raw Score | Normalized | Interpretation |
|-----------|------------|----------------|
| > 0.15    | 85+        | Strong match   |
| > 0.08    | 58+        | Good match     |
| > 0.02    | 42+        | Weak match     |
| < 0.02    | < 42       | No match       |

Note: Text-to-text similarities are typically higher (0.6-0.9 for related concepts).

## Browser Usage

```html
<script type="module">
  import StylorEmbedding from './dist/index.mjs';

  const client = new StylorEmbedding({
    apiKey: 'your-api-key',
    baseUrl: 'https://your-endpoint.modal.run',
  });

  const result = await client.compareTextToImage(
    'a cat',
    { url: 'https://example.com/cat.jpg' }
  );

  console.log(`Match: ${result.normalized}/100 - ${result.interpretation}`);
</script>
```

## TypeScript

Full TypeScript support included:

```typescript
import StylorEmbedding, {
  StylorConfig,
  SimilarityResult,
  ImageInput
} from '@stylor/embedding-sdk';

const config: StylorConfig = {
  apiKey: 'your-key',
  baseUrl: 'https://...',
};

const client = new StylorEmbedding(config);
const result: SimilarityResult = await client.compareTexts('a', 'b');
```

## License

MIT