File size: 4,644 Bytes
3ad07ca
7ad98df
d21beae
8999c6c
0ac520f
 
 
7ad98df
2cb1925
ebe9410
db89028
ebe9410
676575d
 
 
ef0fa30
 
676575d
2cb1925
676575d
d21beae
f35ca0a
7ad98df
8999c6c
d21beae
 
f35ca0a
12da3bd
ef0fa30
 
d21beae
3ad07ca
676575d
 
 
7ad98df
 
676575d
 
 
2cb1925
 
34ead6e
7ad98df
514acf7
f74d7d9
2cb1925
f74d7d9
 
 
 
 
 
 
405b43a
 
f74d7d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf36740
 
f05ef3e
f74d7d9
 
 
 
 
676575d
 
 
 
514acf7
7ad98df
ef0fa30
 
2cb1925
676575d
2cb1925
676575d
 
2cb1925
 
 
 
676575d
2cb1925
676575d
 
2cb1925
676575d
7ad98df
 
676575d
 
2cb1925
 
7ad98df
b89abb6
7ad98df
 
514acf7
f74d7d9
 
 
676575d
 
ef0fa30
 
676575d
5e1435a
7ad98df
 
7bf31c9
 
7ad98df
8999c6c
7bf31c9
676575d
 
7ad98df
5e1435a
ebaea68
676575d
 
 
0ac520f
 
 
676575d
0ac520f
9b5d185
 
 
676575d
9b5d185
d21beae
0ac520f
 
ef0fa30
0ac520f
 
676575d
 
 
 
34224fe
 
2cb1925
676575d
 
 
 
 
 
 
 
34224fe
676575d
 
34224fe
676575d
 
 
 
 
34224fe
0ac520f
d21beae
676575d
34224fe
0ac520f
050542e
34224fe
0ac520f
34224fe
 
0ac520f
 
 
 
 
 
 
 
 
676575d
 
81b2953
0ac520f
81b2953
94b62b7
7ad98df
 
f74d7d9
676575d
 
 
7ad98df
 
 
676575d
 
 
94b62b7
d21beae
94b62b7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
from fastapi import FastAPI
from fastapi.responses import PlainTextResponse, FileResponse
from diffusers import StableDiffusionPipeline
import torch
import threading
import time
from collections import OrderedDict
import os
from PIL import Image  # 🔥 ДОБАВЛЕНО

app = FastAPI()

# =========================
# ⚡ CPU OPTIMIZATION
# =========================
torch.set_num_threads(2)

# =========================
# 🔥 MODEL
# =========================
model_name = "Lykon/dreamshaper-7"

pipe = StableDiffusionPipeline.from_pretrained(
    model_name,
    torch_dtype=torch.float32,
    safety_checker=None
)

pipe = pipe.to("cpu")

pipe.enable_attention_slicing()

# =========================
# 📦 STORAGE
# =========================
db = OrderedDict()
queue = []
progress_db = {}

MAX_HISTORY = 40
NUM_WORKERS = 1

IMG_DIR = "image"
os.makedirs(IMG_DIR, exist_ok=True)

# =========================
# ✂️ 12 SPLIT FUNCTION (NEW)
# =========================
def split_image_into_12(img_path: str):

    img = Image.open(img_path)

    w, h = img.size

    cols = 4
    rows = 3

    tile_w = w // cols
    tile_h = h // rows

    base = img_path.replace(".png", "")

    index = 1

    for r in range(rows):
        for c in range(cols):

            left = c * tile_w
            top = r * tile_h
            right = left + tile_w
            bottom = top + tile_h

            crop = img.crop((left, top, right, bottom))

            # 🔥 ПРОСТОЙ ПОРЯДОК 1 → 12
            out_path = f"{base}_{index}.png"

            crop.save(out_path)

            index += 1


# =========================
# 🚀 GENERATION ENGINE
# =========================
def generate_ai_stream(message: str, mode="fast"):

    try:
        start = time.time()

        # ⚡ режимы
        if mode == "fast":
            steps = 2
            cfg = 1.5
        else:
            steps = 6
            cfg = 3.0

        progress_db[message] = 0

        # 🔥 fake-progress
        for i in range(steps):
            progress_db[message] = int((i / steps) * 100)
            time.sleep(0.12)

        image = pipe(
            message,
            num_inference_steps=steps,
            guidance_scale=cfg,
            height=256,
            width=256
        ).images[0]

        filename = f"{IMG_DIR}/img_{int(time.time()*1000)}.png"
        image.save(filename)

        # 🔥 NEW: split into 12 parts
        split_image_into_12(filename)

        progress_db[message] = 100

        duration = round(time.time() - start, 2)

        result = f"{filename} | {mode} | {duration}s"

    except Exception as e:
        result = f"error: {str(e)}"

    if message in db:
        db[message]["reply"] = result
        db[message]["status"] = "done"

    progress_db.pop(message, None)

    return result


# =========================
# 🔄 WORKER
# =========================
def worker():
    while True:
        if queue:
            message, mode = queue.pop(0)

            if message in db and db[message]["status"] == "done":
                continue

            generate_ai_stream(message, mode)
        else:
            time.sleep(0.03)


threading.Thread(target=worker, daemon=True).start()


# =========================
# 🌐 API
# =========================

@app.get("/")
async def root():
    return PlainTextResponse("⚡ CPU LCM Image Generator Running")


@app.get("/fast")
async def fast(message: str):

    if message not in db:
        db[message] = {"status": "pending", "reply": ""}
        queue.append((message, "fast"))

        if len(db) > MAX_HISTORY:
            db.popitem(last=False)

    return PlainTextResponse("accepted")


@app.get("/quality")
async def quality(message: str):

    if message not in db:
        db[message] = {"status": "pending", "reply": ""}
        queue.append((message, "quality"))

        if len(db) > MAX_HISTORY:
            db.popitem(last=False)

    return PlainTextResponse("accepted")


@app.get("/get")
async def get(message: str):

    if message not in db:
        return PlainTextResponse("not found")

    data = db[message]

    if data["status"] == "pending":
        progress = progress_db.get(message, 0)
        return PlainTextResponse(f"generating... {progress}%")

    return PlainTextResponse(data["reply"])


@app.get("/image")
async def get_image(path: str):

    if not os.path.exists(path):
        return PlainTextResponse("file not found")

    return FileResponse(path)


# =========================
# 🚀 RUN
# =========================
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=7860)