Skip to content

Commit 1411409

Browse files
authored
Merge pull request #9 from replicate/add-support-tag-mappings,-starting-with-flux-lora
Add support for HF tag mappings, starting with Flux LoRA
2 parents 9bc4350 + 54d23c0 commit 1411409

File tree

4 files changed

+83
-5
lines changed

4 files changed

+83
-5
lines changed

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ In January 2025, Hugging Face announced [Inference Providers](https://huggingfac
66

77
This repo contains a [mapping](src/models.ts) of Replicate models to Hugging Face models, so we can tell Hugging Face when to display a Replicate inference widget on its model pages.
88

9-
This repo also includes tooling to keep those mappings up to date using Hugging Face's Model Mappings API.
9+
This repo also includes tooling to keep those mappings up to date using Hugging Face's [Model Mappings API](https://huggingface.co/docs/inference-providers/register-as-a-provider#3-model-mapping-api).
1010

1111
## Adding a new model
1212

@@ -24,6 +24,25 @@ Add your new model to the `inferenceModels` array, like so:
2424

2525
To see allowable values for `task`, refer to [huggingface.co/tasks](https://huggingface.co/tasks).
2626

27+
## Adding a new tag mapping
28+
29+
To add a new tag mapping, edit [src/tags.ts](src/tags.ts)
30+
31+
Add your new tag to the `inferenceTags` array, like so:
32+
33+
```typescript
34+
{
35+
type: 'tag-filter',
36+
task: 'text-to-image',
37+
tags: ['flux', 'lora'],
38+
providerModel: 'black-forest-labs/flux-dev-lora',
39+
adapterType: 'lora',
40+
status: 'live',
41+
}
42+
```
43+
44+
Tag mappings allow you to map multiple Hugging Face models to a single Replicate model based on their tags. This is useful when you have a single Replicate model that can handle multiple variations of a model (like different LoRA adapters).
45+
2746
## Updating model mappings
2847

2948
This repo uses a [GitHub Actions workflow](.github/workflows/sync.yml) to keep the model mappings up to date, as well as model warm/cold states.

src/hf.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1-
interface MappingItem {
1+
interface ModelMappingItem {
22
task: string;
33
hfModel: string;
44
providerModel: string;
55
status?: 'live' | 'staging';
66
}
77

8+
interface TagFilterMappingItem {
9+
task: string;
10+
providerModel: string;
11+
status?: 'live' | 'staging';
12+
type: 'tag-filter';
13+
tags: string[];
14+
adapterType: 'lora';
15+
}
16+
17+
type MappingItem = ModelMappingItem | TagFilterMappingItem;
18+
819
interface StatusUpdateRequest {
920
hfModel: string;
1021
status: 'live' | 'staging';
@@ -43,12 +54,18 @@ class HFInferenceProviderClient {
4354

4455
if (!response.ok) {
4556
const errorText = await response.text();
46-
throw new Error(`Request failed: ${response.status} ${response.statusText} - ${errorText}`);
57+
const error = new Error(`Request failed: ${response.status} ${response.statusText} - ${errorText}`);
58+
if (response.status !== 409) {
59+
console.error('Request error:', error);
60+
}
61+
throw error;
4762
}
4863

4964
return await response.json();
5065
} catch (error) {
51-
console.error('Request error:', error);
66+
if (error instanceof Error && !error.message.includes('409 Conflict')) {
67+
console.error('Request error:', error);
68+
}
5269
throw error;
5370
}
5471
}

src/index.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type InferenceModel, inferenceModels } from './models.js';
2+
import { type InferenceTag, inferenceTags } from './tags.js';
23

34
import HFInferenceProviderClient from './hf.js';
45

@@ -37,7 +38,6 @@ console.log("\n\nExisting HF model IDs:");
3738
console.log(existingHFModelIds);
3839

3940
const newMappings = replicateModels.filter(model => !existingHFModelIds.includes(model.hfModel));
40-
4141
const existingMappings = replicateModels.filter(model => existingHFModelIds.includes(model.hfModel));
4242

4343
if (newMappings.length > 0) {
@@ -63,4 +63,27 @@ if (existingMappings.length > 0) {
6363
console.log("\n\nNo existing mappings to update.");
6464
}
6565

66+
// Handle tag mappings
67+
console.log("\n\nReplicate tag mappings:");
68+
console.log(inferenceTags);
69+
70+
// Register tag mappings
71+
if (inferenceTags.length > 0) {
72+
console.log("\n\nAdding tag mappings:");
73+
for (const tag of inferenceTags) {
74+
console.log(`${tag.tags.join(', ')} - ${tag.status ?? 'live'}`);
75+
try {
76+
await hf.registerMappingItem(tag);
77+
} catch (error) {
78+
if (error instanceof Error && error.message.includes('409 Conflict')) {
79+
console.log(`Skipping existing mapping for tags: ${tag.tags.join(', ')}`);
80+
continue;
81+
}
82+
throw error;
83+
}
84+
}
85+
} else {
86+
console.log("\n\nNo tag mappings to add.");
87+
}
88+
6689
console.log("\n\nDone!");

src/tags.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export interface InferenceTag {
2+
type: 'tag-filter';
3+
task: string;
4+
tags: string[];
5+
providerModel: string;
6+
adapterType: 'lora';
7+
status?: 'live' | 'staging';
8+
}
9+
10+
export const inferenceTags: InferenceTag[] = [
11+
{
12+
type: 'tag-filter',
13+
task: 'text-to-image',
14+
tags: ['flux', 'lora'],
15+
providerModel: 'black-forest-labs/flux-dev-lora',
16+
adapterType: 'lora',
17+
status: 'live',
18+
}
19+
];

0 commit comments

Comments
 (0)