khushalcodiste commited on
Commit
a022cd7
Β·
1 Parent(s): 9a16713

feat: added

Browse files
Files changed (4) hide show
  1. Dockerfile +16 -6
  2. README.md +6 -5
  3. docker-compose.yml +2 -2
  4. src/server.js +39 -2
Dockerfile CHANGED
@@ -1,20 +1,30 @@
1
  FROM node:22-slim
2
 
3
- WORKDIR /app
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
- COPY package.json ./
 
 
 
 
 
 
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 3000
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: Image2Caption
3
- emoji: 🏒
4
- colorFrom: green
5
- colorTo: pink
6
  sdk: docker
 
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
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
- - "3000:3000"
6
  environment:
7
- - PORT=3000
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: "http://localhost:3000" }],
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 || 3000;
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 &amp; 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();