Spaces:
Sleeping
Sleeping
Commit Β·
a022cd7
1
Parent(s): 9a16713
feat: added
Browse files- Dockerfile +16 -6
- README.md +6 -5
- docker-compose.yml +2 -2
- src/server.js +39 -2
Dockerfile
CHANGED
|
@@ -1,20 +1,30 @@
|
|
| 1 |
FROM node:22-slim
|
| 2 |
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
# sharp needs these
|
| 6 |
RUN apt-get update && \
|
| 7 |
apt-get install -y --no-install-recommends libvips-dev && \
|
| 8 |
rm -rf /var/lib/apt/lists/*
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
RUN npm install --omit=dev
|
| 12 |
|
| 13 |
-
COPY src/ src/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
# Download model at build time so container starts fast
|
| 16 |
RUN node -e "import('./src/model.js').then(m => m.loadModel()).then(() => process.exit(0))"
|
| 17 |
|
| 18 |
-
EXPOSE
|
| 19 |
|
| 20 |
CMD ["node", "src/server.js"]
|
|
|
|
| 1 |
FROM node:22-slim
|
| 2 |
|
| 3 |
+
# sharp needs libvips
|
|
|
|
|
|
|
| 4 |
RUN apt-get update && \
|
| 5 |
apt-get install -y --no-install-recommends libvips-dev && \
|
| 6 |
rm -rf /var/lib/apt/lists/*
|
| 7 |
|
| 8 |
+
# HF Spaces runs as uid 1000 β create writable dirs
|
| 9 |
+
RUN useradd -m -u 1000 appuser
|
| 10 |
+
RUN mkdir -p /app /home/appuser/.cache && chown -R appuser:appuser /app /home/appuser/.cache
|
| 11 |
+
|
| 12 |
+
WORKDIR /app
|
| 13 |
+
|
| 14 |
+
COPY --chown=appuser:appuser package.json ./
|
| 15 |
RUN npm install --omit=dev
|
| 16 |
|
| 17 |
+
COPY --chown=appuser:appuser src/ src/
|
| 18 |
+
|
| 19 |
+
# Set cache env so transformers.js writes to a writable location
|
| 20 |
+
ENV TRANSFORMERS_CACHE=/home/appuser/.cache/huggingface
|
| 21 |
+
ENV HF_HOME=/home/appuser/.cache/huggingface
|
| 22 |
+
|
| 23 |
+
USER appuser
|
| 24 |
|
| 25 |
# Download model at build time so container starts fast
|
| 26 |
RUN node -e "import('./src/model.js').then(m => m.loadModel()).then(() => process.exit(0))"
|
| 27 |
|
| 28 |
+
EXPOSE 7860
|
| 29 |
|
| 30 |
CMD ["node", "src/server.js"]
|
README.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
|
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
| 1 |
---
|
| 2 |
+
title: img3txt
|
| 3 |
+
emoji: π·
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: purple
|
| 6 |
sdk: docker
|
| 7 |
+
app_port: 7860
|
| 8 |
pinned: false
|
| 9 |
---
|
| 10 |
|
| 11 |
+
Image captioning API using Microsoft Florence-2 (ONNX). Open `/docs` for Swagger UI.
|
docker-compose.yml
CHANGED
|
@@ -2,7 +2,7 @@ services:
|
|
| 2 |
img3txt:
|
| 3 |
build: .
|
| 4 |
ports:
|
| 5 |
-
- "
|
| 6 |
environment:
|
| 7 |
-
- PORT=
|
| 8 |
restart: unless-stopped
|
|
|
|
| 2 |
img3txt:
|
| 3 |
build: .
|
| 4 |
ports:
|
| 5 |
+
- "7860:7860"
|
| 6 |
environment:
|
| 7 |
+
- PORT=7860
|
| 8 |
restart: unless-stopped
|
src/server.js
CHANGED
|
@@ -19,7 +19,7 @@ await app.register(swagger, {
|
|
| 19 |
"Generate captions, OCR, object detection and more from images using Microsoft Florence-2 (ONNX).",
|
| 20 |
version: "1.0.0",
|
| 21 |
},
|
| 22 |
-
servers: [{ url: "
|
| 23 |
tags: [
|
| 24 |
{ name: "caption", description: "Image captioning endpoints" },
|
| 25 |
{ name: "health", description: "Health check" },
|
|
@@ -69,6 +69,43 @@ const errorSchema = {
|
|
| 69 |
|
| 70 |
// --- Routes ---
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
app.get(
|
| 73 |
"/health",
|
| 74 |
{
|
|
@@ -185,7 +222,7 @@ app.post(
|
|
| 185 |
);
|
| 186 |
|
| 187 |
// --- Start ---
|
| 188 |
-
const PORT = process.env.PORT ||
|
| 189 |
|
| 190 |
// Pre-load model then start server
|
| 191 |
await loadModel();
|
|
|
|
| 19 |
"Generate captions, OCR, object detection and more from images using Microsoft Florence-2 (ONNX).",
|
| 20 |
version: "1.0.0",
|
| 21 |
},
|
| 22 |
+
servers: [{ url: "/" }],
|
| 23 |
tags: [
|
| 24 |
{ name: "caption", description: "Image captioning endpoints" },
|
| 25 |
{ name: "health", description: "Health check" },
|
|
|
|
| 69 |
|
| 70 |
// --- Routes ---
|
| 71 |
|
| 72 |
+
// Landing page β HF Spaces iframe shows this
|
| 73 |
+
app.get(
|
| 74 |
+
"/",
|
| 75 |
+
{ schema: { hide: true } },
|
| 76 |
+
async (req, reply) => {
|
| 77 |
+
reply.type("text/html").send(`<!DOCTYPE html>
|
| 78 |
+
<html lang="en"><head><meta charset="utf-8">
|
| 79 |
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
| 80 |
+
<title>img3txt β Florence-2 Image Captioning API</title>
|
| 81 |
+
<style>
|
| 82 |
+
*{margin:0;padding:0;box-sizing:border-box}
|
| 83 |
+
body{font-family:system-ui,sans-serif;background:#0f172a;color:#e2e8f0;display:flex;align-items:center;justify-content:center;min-height:100vh}
|
| 84 |
+
.card{background:#1e293b;border-radius:16px;padding:2.5rem;max-width:520px;width:90%;text-align:center;box-shadow:0 25px 50px rgba(0,0,0,.4)}
|
| 85 |
+
h1{font-size:1.8rem;margin-bottom:.5rem}
|
| 86 |
+
.sub{color:#94a3b8;margin-bottom:1.5rem}
|
| 87 |
+
.btn{display:inline-block;padding:.75rem 1.5rem;background:#3b82f6;color:#fff;border-radius:8px;text-decoration:none;font-weight:600;margin:.25rem}
|
| 88 |
+
.btn:hover{background:#2563eb}
|
| 89 |
+
.tasks{margin-top:1.5rem;text-align:left;background:#0f172a;border-radius:8px;padding:1rem}
|
| 90 |
+
.tasks code{color:#38bdf8}
|
| 91 |
+
</style></head><body>
|
| 92 |
+
<div class="card">
|
| 93 |
+
<h1>img3txt</h1>
|
| 94 |
+
<p class="sub">Image captioning, OCR & object detection powered by Florence-2 (ONNX)</p>
|
| 95 |
+
<a class="btn" href="/docs">Swagger UI</a>
|
| 96 |
+
<a class="btn" href="/health">Health Check</a>
|
| 97 |
+
<div class="tasks">
|
| 98 |
+
<p><strong>POST /caption</strong> with form fields:</p>
|
| 99 |
+
<ul style="margin:.5rem 0 0 1.2rem;color:#94a3b8">
|
| 100 |
+
<li><code>file</code> β image (required)</li>
|
| 101 |
+
<li><code>task</code> β caption, detailed_caption, more_detailed_caption, ocr, ocr_with_region, object_detection, dense_region_caption, region_proposal</li>
|
| 102 |
+
<li><code>max_tokens</code> β default 100</li>
|
| 103 |
+
</ul>
|
| 104 |
+
</div>
|
| 105 |
+
</div></body></html>`);
|
| 106 |
+
}
|
| 107 |
+
);
|
| 108 |
+
|
| 109 |
app.get(
|
| 110 |
"/health",
|
| 111 |
{
|
|
|
|
| 222 |
);
|
| 223 |
|
| 224 |
// --- Start ---
|
| 225 |
+
const PORT = process.env.PORT || 7860;
|
| 226 |
|
| 227 |
// Pre-load model then start server
|
| 228 |
await loadModel();
|