-
Notifications
You must be signed in to change notification settings - Fork 0
Add space demo template #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.* | ||
.yarn/* | ||
!.yarn/patches | ||
!.yarn/plugins | ||
!.yarn/releases | ||
!.yarn/versions | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# env files (can opt-in for commiting if needed) | ||
.env* | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Adapted from https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile | ||
# For more information, see https://nextjs.org/docs/pages/building-your-application/deploying#docker-image | ||
|
||
# Use a base image for building | ||
FROM node:18-slim AS base | ||
|
||
# Install git | ||
RUN apt-get update && apt-get install -y git | ||
|
||
# Clone the repository and navigate to the next-server folder | ||
WORKDIR /app | ||
RUN git clone https://github.com/huggingface/transformers.js-examples . | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cloning the entire repository might include unnecessary files. Consider using a shallow clone or copying only the necessary files to reduce the image size. |
||
|
||
# Set the working directory to the next-server folder | ||
WORKDIR /app/next-server | ||
|
||
# Install dependencies only when needed | ||
FROM base AS deps | ||
|
||
# Install dependencies based on the preferred package manager | ||
RUN \ | ||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding |
||
elif [ -f package-lock.json ]; then npm ci; \ | ||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \ | ||
else echo "Lockfile not found." && exit 1; \ | ||
fi | ||
|
||
# Rebuild the source code only when needed | ||
FROM base AS builder | ||
WORKDIR /app/next-server | ||
COPY --from=deps /app/next-server/node_modules ./node_modules | ||
COPY . . | ||
|
||
RUN \ | ||
if [ -f yarn.lock ]; then yarn run build; \ | ||
elif [ -f package-lock.json ]; then npm run build; \ | ||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \ | ||
else echo "Lockfile not found." && exit 1; \ | ||
fi | ||
|
||
# Production image, copy all the files and run next | ||
FROM base AS runner | ||
WORKDIR /app/next-server | ||
|
||
ENV NODE_ENV=production | ||
|
||
RUN addgroup --system --gid 1001 nodejs | ||
RUN adduser --system --uid 1001 nextjs | ||
|
||
COPY --from=builder /app/next-server/public ./public | ||
|
||
# Set the correct permission for prerender cache | ||
RUN mkdir .next | ||
RUN chown nextjs:nodejs .next | ||
|
||
# Automatically leverage output traces to reduce image size | ||
COPY --from=builder --chown=nextjs:nodejs /app/next-server/.next/standalone ./ | ||
COPY --from=builder --chown=nextjs:nodejs /app/next-server/.next/static ./.next/static | ||
|
||
USER nextjs | ||
|
||
# Allow the running process to write model files to the cache folder. | ||
RUN mkdir -p /app/next-server/node_modules/@huggingface/transformers/.cache | ||
RUN chmod 777 -R /app/next-server/node_modules/@huggingface/transformers/.cache | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||
|
||
EXPOSE 3000 | ||
|
||
ENV PORT=3000 | ||
ENV HOSTNAME="0.0.0.0" | ||
CMD ["node", "server.js"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--- | ||
title: Topcoder Hugging Face Space Template with Docker + Next.js | ||
emoji: 🗄️ | ||
colorFrom: blue | ||
colorTo: purple | ||
sdk: docker | ||
pinned: false | ||
app_port: 3000 | ||
--- | ||
|
||
# Topcoder Hugging Face Space Template with Docker + Next.js | ||
|
||
This project, bootstrapped using [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app), demonstrates how to use `@huggingface/transformers` in [Next.js](https://nextjs.org) in the Topcoder Huggig Face organization. | ||
|
||
Original repo source: https://github.com/huggingface/transformers.js-examples/tree/main/next-server | ||
|
||
## Instructions | ||
|
||
1. Clone the repository: | ||
|
||
```sh | ||
git clone https://github.com/topcoder-platform/tc-huggingface-spaces.git | ||
``` | ||
|
||
2. Change directory to the `spaces/space-demo-template` project: | ||
|
||
```sh | ||
cd tc-huggingface-spaces/spaces/space-demo-template | ||
``` | ||
|
||
3. Install the dependencies: | ||
|
||
```sh | ||
npm install | ||
``` | ||
|
||
4. Run the development server: | ||
|
||
```sh | ||
npm run dev | ||
``` | ||
|
||
5. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. | ||
6. You can start editing the page by modifying `app/page.js` (Next.js) and `app/api/classify/route.js` (Transformers.js). The page auto-updates as you edit the file. | ||
7. Enjoy developing at Topcoder with Hugging Face. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// https://nextjs.org/docs/app/building-your-application/routing/route-handlers | ||
|
||
import { pipeline } from "@huggingface/transformers"; | ||
|
||
// NOTE: We attach the classifier to the global object to avoid unnecessary reloads during development | ||
const classifier = (globalThis.classifier ??= await pipeline( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||
"text-classification", | ||
"Xenova/distilbert-base-uncased-finetuned-sst-2-english", | ||
)); | ||
|
||
export async function GET(request) { | ||
const text = request.nextUrl.searchParams.get("text"); | ||
|
||
if (!text) { | ||
return Response.json({ message: "No text provided" }, { status: 400 }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using a more descriptive error message to help users understand what input is expected, such as 'Query parameter "text" is required'. |
||
} | ||
|
||
const result = await classifier(text); | ||
return Response.json(result[0]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure that |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
"use client"; | ||
|
||
import { useEffect, useState } from "react"; | ||
|
||
export default function Classifier() { | ||
const [text, setText] = useState("I love Topcoder!"); | ||
const [result, setResult] = useState(null); | ||
|
||
useEffect(() => { | ||
const params = new URLSearchParams(); | ||
params.append("text", text); | ||
const url = "/api/classify?" + params.toString(); | ||
|
||
fetch(url) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding error handling for the fetch request to handle potential network errors or server issues. This can improve the user experience by providing feedback if something goes wrong. |
||
.then((res) => res.json()) | ||
.then((o) => setResult(o)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The variable name 'o' is not descriptive. Consider renaming it to something more meaningful, like 'data' or 'response', to improve code readability. |
||
}, [text]); | ||
|
||
return ( | ||
<> | ||
<input | ||
value={text} | ||
onChange={(e) => setText(e.target.value)} | ||
className="border border-gray-300 rounded p-2 dark:bg-black dark:text-white w-full" | ||
></input> | ||
|
||
<pre className="border border-gray-300 rounded p-2 dark:bg-black dark:text-white w-full min-h-[120px]"> | ||
{result ? JSON.stringify(result, null, 2) : "Loading…"} | ||
</pre> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
:root { | ||
--background: #ffffff; | ||
--foreground: #171717; | ||
} | ||
|
||
@media (prefers-color-scheme: dark) { | ||
:root { | ||
--background: #0a0a0a; | ||
--foreground: #ededed; | ||
} | ||
} | ||
|
||
body { | ||
color: var(--foreground); | ||
background: var(--background); | ||
font-family: Arial, Helvetica, sans-serif; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import localFont from "next/font/local"; | ||
import "./globals.css"; | ||
|
||
const geistSans = localFont({ | ||
src: "./fonts/GeistVF.woff", | ||
variable: "--font-geist-sans", | ||
weight: "100 900", | ||
}); | ||
const geistMono = localFont({ | ||
src: "./fonts/GeistMonoVF.woff", | ||
variable: "--font-geist-mono", | ||
weight: "100 900", | ||
}); | ||
|
||
export const metadata = { | ||
title: "Topcoder Hugging Face Space Template with Docker + Next.js", | ||
description: "Generated by create next app", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The description in the metadata object is generic. Consider providing a more specific description that accurately reflects the purpose or functionality of this template. |
||
}; | ||
|
||
export default function RootLayout({ children }) { | ||
return ( | ||
<html lang="en"> | ||
<body | ||
className={`${geistSans.variable} ${geistMono.variable} antialiased`} | ||
> | ||
{children} | ||
</body> | ||
</html> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import Image from "next/image"; | ||
import Classifier from "./classifier"; | ||
|
||
export default function Home() { | ||
return ( | ||
<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)]"> | ||
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start"> | ||
<div className="flex items-center"> | ||
<Image | ||
src="/topcoder-logo.svg" | ||
alt="Topcoder logo" | ||
width={201} | ||
height={31} | ||
priority | ||
/> | ||
<span className="text-4xl font-light mx-5">×</span> | ||
<Image | ||
src="/hf-logo.svg" | ||
alt="Hugging Face logo" | ||
width={50} | ||
height={50} | ||
priority | ||
/> | ||
<span className="text-4xl font-light mx-5">×</span> | ||
<Image | ||
className="dark:invert" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding a fallback for the |
||
src="/next.svg" | ||
alt="Next.js logo" | ||
width={180} | ||
height={38} | ||
priority | ||
/> | ||
</div> | ||
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]"> | ||
<li className="mb-2"> | ||
Get started by editing{" "} | ||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold"> | ||
app/page.js | ||
</code> | ||
. | ||
</li> | ||
<li className="mb-2"> | ||
Update Transformers.js code in{" "} | ||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold"> | ||
app/api/classify/route.js | ||
</code> | ||
. | ||
</li> | ||
<li>Save and see your changes instantly.</li> | ||
</ol> | ||
|
||
<div className="flex gap-4 items-center flex-col sm:flex-row"> | ||
<a | ||
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" | ||
href="https://github.com/topcoder-platform/tc-huggingface-spaces.git" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
Source code | ||
</a> | ||
|
||
{/* <a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The commented-out code block for the 'Read our docs' link should be removed if it's not intended for future use, to keep the codebase clean. |
||
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" | ||
href="https://huggingface.co/docs/transformers.js/index" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
Read our docs | ||
</a> */} | ||
</div> | ||
<Classifier /> | ||
</main> | ||
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center"> | ||
<a | ||
className="flex items-center gap-2 hover:underline hover:underline-offset-4" | ||
href="https://www.topcoder.com/ai-hub/competitions?utm_campaign=huggingface&utm_source=huggingface&utm_medium=Topcoder" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
<Image | ||
aria-hidden | ||
src="/globe.svg" | ||
alt="Globe icon" | ||
width={16} | ||
height={16} | ||
/> | ||
Go to Topcoder AI Hub Competitions → | ||
</a> | ||
</footer> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"compilerOptions": { | ||
"paths": { | ||
"@/*": ["./*"] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
// https://nextjs.org/docs/app/api-reference/config/next-config-js/output | ||
output: "standalone", | ||
// https://nextjs.org/docs/app/api-reference/config/next-config-js/serverExternalPackages | ||
serverExternalPackages: ["@huggingface/transformers"], | ||
}; | ||
|
||
export default nextConfig; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using
apt-get install -y --no-install-recommends git
to avoid installing unnecessary recommended packages, which can help reduce the image size.