nirkyy commited on
Commit
1318bf3
·
verified ·
1 Parent(s): 543841a

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +89 -75
Dockerfile CHANGED
@@ -1,81 +1,95 @@
1
- FROM python:3.11-alpine
2
 
3
  WORKDIR /app
4
 
5
- ENV PORT=7860
6
- ENV MODEL_ID="gemini-1.5-flash-latest"
7
- ENV GENERATE_CONTENT_API="streamGenerateContent"
8
-
9
- RUN apk update && \
10
- apk add --no-cache curl jq bash && \
11
- pip install --no-cache-dir --upgrade pip && \
12
- pip install --no-cache-dir flask flask-cors gunicorn && \
13
- rm -rf /var/cache/apk/*
14
-
15
- # Metode penulisan file paling robust: echo dengan string kutip tunggal.
16
- # -e memungkinkan interpretasi \n. Kutip tunggal mencegah SEMUA ekspansi shell.
17
- RUN echo -e '#!/bin/bash\n\
18
- set -e\n\
19
- \n\
20
- SYSTEM_PROMPT="$1"\n\
21
- USER_PROMPT="$2"\n\
22
- \n\
23
- API_KEYS=("apikey1" "apikey2" "apikey3")\n\
24
- RANDOM_INDEX=$((RANDOM % ${#API_KEYS[@]}))\n\
25
- GEMINI_API_KEY=${API_KEYS[$RANDOM_INDEX]}\n\
26
- \n\
27
- JSON_PAYLOAD=$(jq -n \\\n\
28
- --arg sp "$SYSTEM_PROMPT" \\\n\
29
- --arg up "$USER_PROMPT" \\\n\
30
- '\''{ "system_instruction": { "parts": [ { "text": $sp } ] }, "contents": [ { "role": "user", "parts": [ { "text": $up } ] } ] }'\'')\n\
31
- \n\
32
- API_URL="https://generativelanguage.googleapis.com/v1beta/models/${MODEL_ID}:${GENERATE_CONTENT_API}?key=${GEMINI_API_KEY}"\n\
33
- \n\
34
- curl -s -X POST -H "Content-Type: application/json" "$API_URL" -d "$JSON_PAYLOAD" | \\\n\
35
- jq -r ".candidates[0].content.parts[0].text" | \\\n\
36
- tr -d "\\n"\
37
- ' > /usr/local/bin/gemini_handler
38
-
39
- RUN chmod +x /usr/local/bin/gemini_handler
40
-
41
- # Menulis app.py dengan metode yang sama. Perhatikan semua string di Python menggunakan kutip ganda
42
- # untuk menghindari konflik dengan kutip tunggal di echo.
43
- RUN echo -e 'import os\n\
44
- import subprocess\n\
45
- from flask import Flask, request, jsonify\n\
46
- from flask_cors import CORS\n\
47
- \n\
48
- app = Flask(__name__)\n\
49
- CORS(app)\n\
50
- \n\
51
- @app.route("/")\n\
52
- def health_check():\n\
53
- return jsonify({"status": "ok", "message": "API is running"})\n\
54
- \n\
55
- @app.route("/chat", methods=["POST"])\n\
56
- def chat_handler():\n\
57
- data = request.get_json()\n\
58
- if not data or "prompt" not in data:\n\
59
- return jsonify({"error": "Missing '\''prompt'\'' in request body"}), 400\n\
60
- \n\
61
- system_prompt = data.get("system", "You are a helpful assistant.")\n\
62
- user_prompt = data.get("prompt")\n\
63
- \n\
64
- try:\n\
65
- result = subprocess.run(\n\
66
- ["/usr/local/bin/gemini_handler", system_prompt, user_prompt],\n\
67
- capture_output=True,\n\
68
- text=True,\n\
69
- check=True,\n\
70
- timeout=60\n\
71
- )\n\
72
- return jsonify({"response": result.stdout.strip()})\n\
73
- except subprocess.CalledProcessError as e:\n\
74
- return jsonify({"error": "Failed to call Gemini API", "details": e.stderr}), 500\n\
75
- except subprocess.TimeoutExpired:\n\
76
- return jsonify({"error": "Request to Gemini API timed out"}), 504\n\
77
- ' > app.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  EXPOSE 7860
80
 
81
- CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--workers", "1", "app:app"]
 
1
+ FROM node:20-slim
2
 
3
  WORKDIR /app
4
 
5
+ RUN cat << EOF > package.json
6
+ {
7
+ "name": "gemini-proxy-server",
8
+ "version": "1.0.0",
9
+ "main": "index.js",
10
+ "scripts": {
11
+ "start": "node index.js"
12
+ },
13
+ "dependencies": {
14
+ "axios": "^1.7.2",
15
+ "cors": "^2.8.5",
16
+ "express": "^4.19.2"
17
+ }
18
+ }
19
+ EOF
20
+
21
+ RUN npm install --only=production
22
+
23
+ RUN cat << EOF > index.js
24
+ const express = require('express');
25
+ const cors = require('cors');
26
+ const axios = require('axios');
27
+
28
+ const app = express();
29
+ const PORT = 7860;
30
+ const MODEL_ID = "gemini-flash-lite-latest";
31
+ const API_URL_BASE = "https://generativelanguage.googleapis.com/v1beta/models";
32
+
33
+ const apiKeys = [
34
+ "apikey1",
35
+ "apikey2",
36
+ "apikey3",
37
+ "apikey4",
38
+ "apikey5"
39
+ ];
40
+
41
+ const getRandomApiKey = () => {
42
+ const randomIndex = Math.floor(Math.random() * apiKeys.length);
43
+ return apiKeys[randomIndex];
44
+ };
45
+
46
+ app.use(cors());
47
+ app.use(express.json());
48
+
49
+ app.post('/api/generate', async (req, res) => {
50
+ const { prompt } = req.body;
51
+
52
+ if (!prompt) {
53
+ return res.status(400).json({ error: 'Request body harus menyertakan "prompt"' });
54
+ }
55
+
56
+ try {
57
+ const apiKey = getRandomApiKey();
58
+ const apiUrl = `\${API_URL_BASE}/\${MODEL_ID}:streamGenerateContent?key=\${apiKey}`;
59
+
60
+ const requestBody = {
61
+ contents: [{
62
+ role: "user",
63
+ parts: [{ "text": prompt }],
64
+ }],
65
+ generationConfig: {
66
+ thinkingConfig: {
67
+ thinkingBudget: 0,
68
+ },
69
+ },
70
+ };
71
+
72
+ const geminiResponse = await axios.post(apiUrl, requestBody, {
73
+ headers: { 'Content-Type': 'application/json' },
74
+ responseType: 'stream'
75
+ });
76
+
77
+ res.setHeader('Content-Type', geminiResponse.headers['content-type']);
78
+ geminiResponse.data.pipe(res);
79
+
80
+ } catch (error) {
81
+ console.error("Error saat menghubungi Gemini API:", error.message);
82
+ const status = error.response ? error.response.status : 500;
83
+ const data = error.response ? error.response.data : { message: "Internal Server Error" };
84
+ res.status(status).json(data);
85
+ }
86
+ });
87
+
88
+ app.listen(PORT, () => {
89
+ console.log(`Server berjalan di http://localhost:\${PORT}`);
90
+ });
91
+ EOF
92
 
93
  EXPOSE 7860
94
 
95
+ CMD ["npm", "start"]