nsarrazin HF Staff commited on
Commit
cdc7abc
·
unverified ·
1 Parent(s): a954f65

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<Model, "name" | "datasetName" | "websiteUrl" | "modelUrl" | "datasetUrl">;
 
 
 
8
 
9
  export let variant: "light" | "dark" = "light";
10
  </script>
@@ -35,6 +39,16 @@
35
  <div class="max-sm:hidden">&nbsp;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">&nbsp;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
- export const models: ProcessedModel[] = await Promise.all(
320
- modelsRaw.map((e) => processModel(e).then(addEndpoint))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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"