Update main.py
Browse files
main.py
CHANGED
|
@@ -4,7 +4,8 @@ import httpx
|
|
| 4 |
import time
|
| 5 |
import base64
|
| 6 |
import urllib.parse
|
| 7 |
-
import os
|
|
|
|
| 8 |
from pydantic import BaseModel, Field
|
| 9 |
from typing import List, Optional, Union, Literal
|
| 10 |
|
|
@@ -18,7 +19,7 @@ class OpenAIImageRequest(BaseModel):
|
|
| 18 |
user: Optional[str] = None
|
| 19 |
|
| 20 |
# Pollinations specific parameters
|
| 21 |
-
seed_value: Optional[int] = Field(default=None, alias="seed", description="Seed
|
| 22 |
model: Optional[str] = Field(default=None, description="Model to use for Pollinations.")
|
| 23 |
enhance: Optional[bool] = Field(default=True, description="Enhance parameter for Pollinations.")
|
| 24 |
nologo: Optional[bool] = Field(default=True, description="NoLogo parameter for Pollinations.")
|
|
@@ -41,8 +42,8 @@ class OpenAIImageResponse(BaseModel):
|
|
| 41 |
# --- FastAPI Application ---
|
| 42 |
app = fastapi.FastAPI(
|
| 43 |
title="OpenAI-compatible Image Generation API for Pollinations",
|
| 44 |
-
description="This API wraps the image.pollinations.ai service to provide an OpenAI-like interface.",
|
| 45 |
-
version="1.
|
| 46 |
)
|
| 47 |
|
| 48 |
# --- Helper Functions ---
|
|
@@ -77,6 +78,7 @@ async def create_image_generation(request: OpenAIImageRequest):
|
|
| 77 |
"""
|
| 78 |
Mimics the OpenAI image generation endpoint.
|
| 79 |
Receives a prompt and other parameters, then calls the Pollinations API.
|
|
|
|
| 80 |
"""
|
| 81 |
pollinations_base_url = "https://image.pollinations.ai/prompt/"
|
| 82 |
results_data: List[Union[ImageURL, ImageB64]] = []
|
|
@@ -88,6 +90,24 @@ async def create_image_generation(request: OpenAIImageRequest):
|
|
| 88 |
detail="Invalid 'size' format. Expected 'widthxheight', e.g., '1024x1024'."
|
| 89 |
)
|
| 90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
async with httpx.AsyncClient() as client:
|
| 92 |
for _ in range(request.n):
|
| 93 |
encoded_prompt = urllib.parse.quote(request.prompt)
|
|
@@ -98,8 +118,12 @@ async def create_image_generation(request: OpenAIImageRequest):
|
|
| 98 |
query_params["width"] = width
|
| 99 |
if height:
|
| 100 |
query_params["height"] = height
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
if request.model:
|
| 104 |
query_params["model"] = request.model
|
| 105 |
if request.enhance is not None:
|
|
@@ -138,11 +162,8 @@ async def create_image_generation(request: OpenAIImageRequest):
|
|
| 138 |
|
| 139 |
# --- Main guard for running with Uvicorn ---
|
| 140 |
if __name__ == "__main__":
|
| 141 |
-
|
| 142 |
-
# Khi chạy trong Docker trên Hugging Face, CMD trong Dockerfile sẽ được sử dụng.
|
| 143 |
-
port_to_use = 7860 # Mặc định cho HF Spaces và yêu cầu của bạn
|
| 144 |
try:
|
| 145 |
-
# Hugging Face Spaces có thể đặt biến môi trường PORT
|
| 146 |
port_from_env = os.environ.get("PORT")
|
| 147 |
if port_from_env:
|
| 148 |
port_to_use = int(port_from_env)
|
|
@@ -152,5 +173,4 @@ if __name__ == "__main__":
|
|
| 152 |
print(f"Error reading PORT environment variable: {e}. Using default port {port_to_use}.")
|
| 153 |
|
| 154 |
print(f"Starting Uvicorn server on host 0.0.0.0, port {port_to_use}")
|
| 155 |
-
# reload=True hữu ích cho phát triển cục bộ, Docker CMD sẽ không dùng reload.
|
| 156 |
uvicorn.run("main:app", host="0.0.0.0", port=port_to_use, reload=True)
|
|
|
|
| 4 |
import time
|
| 5 |
import base64
|
| 6 |
import urllib.parse
|
| 7 |
+
import os
|
| 8 |
+
import math # Thêm import math
|
| 9 |
from pydantic import BaseModel, Field
|
| 10 |
from typing import List, Optional, Union, Literal
|
| 11 |
|
|
|
|
| 19 |
user: Optional[str] = None
|
| 20 |
|
| 21 |
# Pollinations specific parameters
|
| 22 |
+
seed_value: Optional[int] = Field(default=None, alias="seed", description="Seed provided by the user. Will be transformed before use.")
|
| 23 |
model: Optional[str] = Field(default=None, description="Model to use for Pollinations.")
|
| 24 |
enhance: Optional[bool] = Field(default=True, description="Enhance parameter for Pollinations.")
|
| 25 |
nologo: Optional[bool] = Field(default=True, description="NoLogo parameter for Pollinations.")
|
|
|
|
| 42 |
# --- FastAPI Application ---
|
| 43 |
app = fastapi.FastAPI(
|
| 44 |
title="OpenAI-compatible Image Generation API for Pollinations",
|
| 45 |
+
description="This API wraps the image.pollinations.ai service to provide an OpenAI-like interface with custom seed transformation.",
|
| 46 |
+
version="1.1.0" # Updated version
|
| 47 |
)
|
| 48 |
|
| 49 |
# --- Helper Functions ---
|
|
|
|
| 78 |
"""
|
| 79 |
Mimics the OpenAI image generation endpoint.
|
| 80 |
Receives a prompt and other parameters, then calls the Pollinations API.
|
| 81 |
+
If a seed is provided by the user, it's transformed before being sent.
|
| 82 |
"""
|
| 83 |
pollinations_base_url = "https://image.pollinations.ai/prompt/"
|
| 84 |
results_data: List[Union[ImageURL, ImageB64]] = []
|
|
|
|
| 90 |
detail="Invalid 'size' format. Expected 'widthxheight', e.g., '1024x1024'."
|
| 91 |
)
|
| 92 |
|
| 93 |
+
# --- Seed Transformation Logic ---
|
| 94 |
+
final_seed_to_use = None
|
| 95 |
+
if request.seed_value is not None:
|
| 96 |
+
user_provided_seed = float(request.seed_value)
|
| 97 |
+
current_timestamp_int = int(time.time()) # Thời gian hiện tại (giây)
|
| 98 |
+
sqrt2_times_pi = math.sqrt(2) * math.pi # √2 × π
|
| 99 |
+
|
| 100 |
+
intermediate_sum = user_provided_seed + float(current_timestamp_int) + sqrt2_times_pi
|
| 101 |
+
final_seed_to_use = math.floor(intermediate_sum) % 10 # Lấy số nguyên hàng đơn vị (0-9)
|
| 102 |
+
|
| 103 |
+
# Ghi log để debug (bạn có thể xóa hoặc giữ lại)
|
| 104 |
+
print(f"User provided seed: {request.seed_value}")
|
| 105 |
+
print(f"Current timestamp (int): {current_timestamp_int}")
|
| 106 |
+
print(f"Calculated constant (sqrt(2)*pi): {sqrt2_times_pi}")
|
| 107 |
+
print(f"Intermediate sum for seed: {intermediate_sum}")
|
| 108 |
+
print(f"Transformed seed for Pollinations: {final_seed_to_use}")
|
| 109 |
+
# --- End Seed Transformation Logic ---
|
| 110 |
+
|
| 111 |
async with httpx.AsyncClient() as client:
|
| 112 |
for _ in range(request.n):
|
| 113 |
encoded_prompt = urllib.parse.quote(request.prompt)
|
|
|
|
| 118 |
query_params["width"] = width
|
| 119 |
if height:
|
| 120 |
query_params["height"] = height
|
| 121 |
+
|
| 122 |
+
if final_seed_to_use is not None: # Sử dụng seed đã biến đổi nếu có
|
| 123 |
+
query_params["seed"] = final_seed_to_use
|
| 124 |
+
# Nếu người dùng không cung cấp seed_value, final_seed_to_use sẽ là None
|
| 125 |
+
# và không có tham số 'seed' nào được gửi, để Pollinations tự xử lý.
|
| 126 |
+
|
| 127 |
if request.model:
|
| 128 |
query_params["model"] = request.model
|
| 129 |
if request.enhance is not None:
|
|
|
|
| 162 |
|
| 163 |
# --- Main guard for running with Uvicorn ---
|
| 164 |
if __name__ == "__main__":
|
| 165 |
+
port_to_use = 7860
|
|
|
|
|
|
|
| 166 |
try:
|
|
|
|
| 167 |
port_from_env = os.environ.get("PORT")
|
| 168 |
if port_from_env:
|
| 169 |
port_to_use = int(port_from_env)
|
|
|
|
| 173 |
print(f"Error reading PORT environment variable: {e}. Using default port {port_to_use}.")
|
| 174 |
|
| 175 |
print(f"Starting Uvicorn server on host 0.0.0.0, port {port_to_use}")
|
|
|
|
| 176 |
uvicorn.run("main:app", host="0.0.0.0", port=port_to_use, reload=True)
|