Skip to content

Commit a48196a

Browse files
committed
Add Transformers.js API route for text classification
1 parent cd303e6 commit a48196a

File tree

11 files changed

+413
-91
lines changed

11 files changed

+413
-91
lines changed

next-server/app/api/classify/route.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// https://nextjs.org/docs/app/building-your-application/routing/route-handlers
2+
3+
import { pipeline } from "@huggingface/transformers";
4+
5+
// NOTE: We attach the classifier to the global object to avoid loading it multiple times
6+
const classifier = (globalThis.classifier ??= await pipeline(
7+
"text-classification",
8+
"Xenova/distilbert-base-uncased-finetuned-sst-2-english",
9+
));
10+
11+
export async function GET(request) {
12+
// https://nextjs.org/docs/app/building-your-axpplication/routing/route-handlers#url-query-parameters
13+
const searchParams = request.nextUrl.searchParams;
14+
const text = searchParams.get("text");
15+
16+
const result = await classifier(text);
17+
return Response.json(result[0]);
18+
}

next-server/app/classifier.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
5+
export default function Classifier() {
6+
const [text, setText] = useState("I love Transformers.js!");
7+
const [result, setResult] = useState(null);
8+
9+
useEffect(() => {
10+
const params = new URLSearchParams();
11+
params.append("text", text);
12+
const url = "/api/classify?" + params.toString();
13+
14+
fetch(url)
15+
.then((res) => res.json())
16+
.then((o) => setResult(o));
17+
}, [text]);
18+
19+
return (
20+
<>
21+
<input
22+
value={text}
23+
onChange={(e) => setText(e.target.value)}
24+
className="border border-gray-300 rounded p-2 dark:bg-black dark:text-white w-full"
25+
></input>
26+
27+
<pre className="border border-gray-300 rounded p-2 dark:bg-black dark:text-white w-full min-h-[120px]">
28+
{result ? JSON.stringify(result, null, 2) : "Loading…"}
29+
</pre>
30+
</>
31+
);
32+
}

next-server/app/favicon.ico

21.4 KB
Binary file not shown.

next-server/app/page.js

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
import Image from "next/image";
2+
import Classifier from "./classifier";
23

34
export default function Home() {
45
return (
5-
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
6+
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-8 font-[family-name:var(--font-geist-sans)]">
67
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
7-
<Image
8-
className="dark:invert"
9-
src="/next.svg"
10-
alt="Next.js logo"
11-
width={180}
12-
height={38}
13-
priority
14-
/>
8+
<div className="flex items-center">
9+
<Image
10+
src="/hf-logo.svg"
11+
alt="Hugging Face logo"
12+
width={50}
13+
height={50}
14+
priority
15+
/>
16+
<span className="text-4xl font-light mx-5">&#xd7;</span>
17+
<Image
18+
className="dark:invert"
19+
src="/next.svg"
20+
alt="Next.js logo"
21+
width={180}
22+
height={38}
23+
priority
24+
/>
25+
</div>
1526
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
1627
<li className="mb-2">
1728
Get started by editing{" "}
@@ -20,54 +31,56 @@ export default function Home() {
2031
</code>
2132
.
2233
</li>
34+
<li className="mb-2">
35+
Update Transformers.js code in{" "}
36+
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">
37+
app/api/classify/route.js
38+
</code>
39+
.
40+
</li>
2341
<li>Save and see your changes instantly.</li>
2442
</ol>
2543

2644
<div className="flex gap-4 items-center flex-col sm:flex-row">
2745
<a
2846
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
29-
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
47+
href="https://github.com/huggingface/transformers.js-examples/tree/main/next-server"
3048
target="_blank"
3149
rel="noopener noreferrer"
3250
>
33-
<Image
34-
className="dark:invert"
35-
src="/vercel.svg"
36-
alt="Vercel logomark"
37-
width={20}
38-
height={20}
39-
/>
40-
Deploy now
51+
Source code
4152
</a>
53+
4254
<a
43-
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
44-
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
55+
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
56+
href="https://huggingface.co/docs/transformers.js/index"
4557
target="_blank"
4658
rel="noopener noreferrer"
4759
>
4860
Read our docs
4961
</a>
5062
</div>
63+
<Classifier />
5164
</main>
5265
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
5366
<a
5467
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
55-
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
68+
href="https://github.com/huggingface/transformers.js"
5669
target="_blank"
5770
rel="noopener noreferrer"
5871
>
5972
<Image
6073
aria-hidden
61-
src="/file.svg"
62-
alt="File icon"
74+
src="/github.svg"
75+
alt="GitHub icon"
6376
width={16}
6477
height={16}
6578
/>
66-
Learn
79+
Transformers.js
6780
</a>
6881
<a
6982
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
70-
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
83+
href="https://github.com/huggingface/transformers.js-examples"
7184
target="_blank"
7285
rel="noopener noreferrer"
7386
>
@@ -82,7 +95,7 @@ export default function Home() {
8295
</a>
8396
<a
8497
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
85-
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
98+
href="https://hf.co"
8699
target="_blank"
87100
rel="noopener noreferrer"
88101
>
@@ -93,7 +106,7 @@ export default function Home() {
93106
width={16}
94107
height={16}
95108
/>
96-
Go to nextjs.org
109+
Go to hf.co
97110
</a>
98111
</footer>
99112
</div>

next-server/next.config.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/** @type {import('next').NextConfig} */
2-
const nextConfig = {};
2+
const nextConfig = {
3+
// https://nextjs.org/docs/app/api-reference/next-config-js/serverExternalPackages
4+
serverExternalPackages: ["@huggingface/transformers"],
5+
};
36

47
export default nextConfig;

0 commit comments

Comments
 (0)