Spaces:
Running
Running
feat: add link to API playground for compatible models (#1488)
Browse files* feat: add link to API playground for compatible models
* fix: move buttons to correct spot
* fix: inference API placement button
src/lib/components/ModelCardMetadata.svelte
CHANGED
@@ -2,9 +2,13 @@
|
|
2 |
import CarbonEarth from "~icons/carbon/earth";
|
3 |
import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
|
4 |
import BIMeta from "~icons/bi/meta";
|
|
|
5 |
import type { Model } from "$lib/types/Model";
|
6 |
|
7 |
-
export let model: Pick<
|
|
|
|
|
|
|
8 |
|
9 |
export let variant: "light" | "dark" = "light";
|
10 |
</script>
|
@@ -35,6 +39,16 @@
|
|
35 |
<div class="max-sm:hidden"> page</div></a
|
36 |
>
|
37 |
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
{#if model.websiteUrl}
|
39 |
<a
|
40 |
href={model.websiteUrl}
|
|
|
2 |
import CarbonEarth from "~icons/carbon/earth";
|
3 |
import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
|
4 |
import BIMeta from "~icons/bi/meta";
|
5 |
+
import CarbonCode from "~icons/carbon/code";
|
6 |
import type { Model } from "$lib/types/Model";
|
7 |
|
8 |
+
export let model: Pick<
|
9 |
+
Model,
|
10 |
+
"name" | "datasetName" | "websiteUrl" | "modelUrl" | "datasetUrl" | "hasInferenceAPI"
|
11 |
+
>;
|
12 |
|
13 |
export let variant: "light" | "dark" = "light";
|
14 |
</script>
|
|
|
39 |
<div class="max-sm:hidden"> page</div></a
|
40 |
>
|
41 |
{/if}
|
42 |
+
{#if model.hasInferenceAPI}
|
43 |
+
<a
|
44 |
+
href={"https://huggingface.co/playground?modelId=" + model.name}
|
45 |
+
target="_blank"
|
46 |
+
rel="noreferrer"
|
47 |
+
class="flex items-center hover:underline"
|
48 |
+
><CarbonCode class="mr-1.5 shrink-0 text-xs text-gray-400" />
|
49 |
+
API
|
50 |
+
</a>
|
51 |
+
{/if}
|
52 |
{#if model.websiteUrl}
|
53 |
<a
|
54 |
href={model.websiteUrl}
|
src/lib/server/models.ts
CHANGED
@@ -13,6 +13,7 @@ import JSON5 from "json5";
|
|
13 |
import { getTokenizer } from "$lib/utils/getTokenizer";
|
14 |
import { logger } from "$lib/server/logger";
|
15 |
import { ToolResultStatus, type ToolInput } from "$lib/types/Tool";
|
|
|
16 |
|
17 |
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
18 |
|
@@ -253,10 +254,6 @@ const processModel = async (m: z.infer<typeof modelConfig>) => ({
|
|
253 |
parameters: { ...m.parameters, stop_sequences: m.parameters?.stop },
|
254 |
});
|
255 |
|
256 |
-
export type ProcessedModel = Awaited<ReturnType<typeof processModel>> & {
|
257 |
-
getEndpoint: () => Promise<Endpoint>;
|
258 |
-
};
|
259 |
-
|
260 |
const addEndpoint = (m: Awaited<ReturnType<typeof processModel>>) => ({
|
261 |
...m,
|
262 |
getEndpoint: async (): Promise<Endpoint> => {
|
@@ -316,10 +313,40 @@ const addEndpoint = (m: Awaited<ReturnType<typeof processModel>>) => ({
|
|
316 |
},
|
317 |
});
|
318 |
|
319 |
-
|
320 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
);
|
322 |
|
|
|
|
|
323 |
// super ugly but not sure how to make typescript happier
|
324 |
export const validModelIdSchema = z.enum(models.map((m) => m.id) as [string, ...string[]]);
|
325 |
|
@@ -357,5 +384,5 @@ export const smallModel = env.TASK_MODEL
|
|
357 |
|
358 |
export type BackendModel = Optional<
|
359 |
typeof defaultModel,
|
360 |
-
"preprompt" | "parameters" | "multimodal" | "unlisted" | "tools"
|
361 |
>;
|
|
|
13 |
import { getTokenizer } from "$lib/utils/getTokenizer";
|
14 |
import { logger } from "$lib/server/logger";
|
15 |
import { ToolResultStatus, type ToolInput } from "$lib/types/Tool";
|
16 |
+
import { isHuggingChat } from "$lib/utils/isHuggingChat";
|
17 |
|
18 |
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
19 |
|
|
|
254 |
parameters: { ...m.parameters, stop_sequences: m.parameters?.stop },
|
255 |
});
|
256 |
|
|
|
|
|
|
|
|
|
257 |
const addEndpoint = (m: Awaited<ReturnType<typeof processModel>>) => ({
|
258 |
...m,
|
259 |
getEndpoint: async (): Promise<Endpoint> => {
|
|
|
313 |
},
|
314 |
});
|
315 |
|
316 |
+
const hasInferenceAPI = async (m: Awaited<ReturnType<typeof processModel>>) => {
|
317 |
+
if (!isHuggingChat) {
|
318 |
+
return false;
|
319 |
+
}
|
320 |
+
|
321 |
+
const r = await fetch(`https://huggingface.co/api/models/${m.id}`);
|
322 |
+
|
323 |
+
if (!r.ok) {
|
324 |
+
logger.warn(`Failed to check if ${m.id} has inference API: ${r.statusText}`);
|
325 |
+
return false;
|
326 |
+
}
|
327 |
+
|
328 |
+
const json = await r.json();
|
329 |
+
|
330 |
+
if (json.cardData.inference === false) {
|
331 |
+
return false;
|
332 |
+
}
|
333 |
+
|
334 |
+
return true;
|
335 |
+
};
|
336 |
+
|
337 |
+
export const models = await Promise.all(
|
338 |
+
modelsRaw.map((e) =>
|
339 |
+
processModel(e)
|
340 |
+
.then(addEndpoint)
|
341 |
+
.then(async (m) => ({
|
342 |
+
...m,
|
343 |
+
hasInferenceAPI: await hasInferenceAPI(m),
|
344 |
+
}))
|
345 |
+
)
|
346 |
);
|
347 |
|
348 |
+
export type ProcessedModel = (typeof models)[number];
|
349 |
+
|
350 |
// super ugly but not sure how to make typescript happier
|
351 |
export const validModelIdSchema = z.enum(models.map((m) => m.id) as [string, ...string[]]);
|
352 |
|
|
|
384 |
|
385 |
export type BackendModel = Optional<
|
386 |
typeof defaultModel,
|
387 |
+
"preprompt" | "parameters" | "multimodal" | "unlisted" | "tools" | "hasInferenceAPI"
|
388 |
>;
|
src/lib/types/Model.ts
CHANGED
@@ -18,4 +18,5 @@ export type Model = Pick<
|
|
18 |
| "multimodal"
|
19 |
| "unlisted"
|
20 |
| "tools"
|
|
|
21 |
>;
|
|
|
18 |
| "multimodal"
|
19 |
| "unlisted"
|
20 |
| "tools"
|
21 |
+
| "hasInferenceAPI"
|
22 |
>;
|
src/routes/+layout.server.ts
CHANGED
@@ -194,6 +194,7 @@ export const load: LayoutServerLoad = async ({ locals, depends, request }) => {
|
|
194 |
// disable tools on huggingchat android app
|
195 |
!request.headers.get("user-agent")?.includes("co.huggingface.chat_ui_android"),
|
196 |
unlisted: model.unlisted,
|
|
|
197 |
})),
|
198 |
oldModels,
|
199 |
tools: [...toolFromConfigs, ...communityTools]
|
|
|
194 |
// disable tools on huggingchat android app
|
195 |
!request.headers.get("user-agent")?.includes("co.huggingface.chat_ui_android"),
|
196 |
unlisted: model.unlisted,
|
197 |
+
hasInferenceAPI: model.hasInferenceAPI,
|
198 |
})),
|
199 |
oldModels,
|
200 |
tools: [...toolFromConfigs, ...communityTools]
|
src/routes/api/models/+server.ts
CHANGED
@@ -19,6 +19,7 @@ export async function GET() {
|
|
19 |
multimodal: model.multimodal ?? false,
|
20 |
unlisted: model.unlisted ?? false,
|
21 |
tools: model.tools ?? false,
|
|
|
22 |
}));
|
23 |
return Response.json(res);
|
24 |
}
|
|
|
19 |
multimodal: model.multimodal ?? false,
|
20 |
unlisted: model.unlisted ?? false,
|
21 |
tools: model.tools ?? false,
|
22 |
+
hasInferenceAPI: model.hasInferenceAPI ?? false,
|
23 |
}));
|
24 |
return Response.json(res);
|
25 |
}
|
src/routes/settings/(nav)/[...model]/+page.svelte
CHANGED
@@ -9,6 +9,7 @@
|
|
9 |
import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
|
10 |
import CarbonLink from "~icons/carbon/link";
|
11 |
import CarbonChat from "~icons/carbon/chat";
|
|
|
12 |
|
13 |
import { goto } from "$app/navigation";
|
14 |
|
@@ -78,6 +79,19 @@
|
|
78 |
Model website
|
79 |
</a>
|
80 |
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
<CopyToClipBoardBtn
|
82 |
value="{envPublic.PUBLIC_ORIGIN || $page.url.origin}{base}/models/{model.id}"
|
83 |
classNames="!border-none !shadow-none !py-0 !px-1 !rounded-md"
|
|
|
9 |
import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
|
10 |
import CarbonLink from "~icons/carbon/link";
|
11 |
import CarbonChat from "~icons/carbon/chat";
|
12 |
+
import CarbonCode from "~icons/carbon/code";
|
13 |
|
14 |
import { goto } from "$app/navigation";
|
15 |
|
|
|
79 |
Model website
|
80 |
</a>
|
81 |
{/if}
|
82 |
+
|
83 |
+
{#if model.hasInferenceAPI}
|
84 |
+
<a
|
85 |
+
href={"https://huggingface.co/playground?modelId=" + model.name}
|
86 |
+
target="_blank"
|
87 |
+
rel="noreferrer"
|
88 |
+
class="flex items-center truncate underline underline-offset-2"
|
89 |
+
>
|
90 |
+
<CarbonCode class="mr-1.5 shrink-0 text-xs " />
|
91 |
+
API Playground
|
92 |
+
</a>
|
93 |
+
{/if}
|
94 |
+
|
95 |
<CopyToClipBoardBtn
|
96 |
value="{envPublic.PUBLIC_ORIGIN || $page.url.origin}{base}/models/{model.id}"
|
97 |
classNames="!border-none !shadow-none !py-0 !px-1 !rounded-md"
|