Spaces:
Runtime error
Runtime error
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"
|