dedlepexa commited on
Commit
5e1435a
·
verified ·
1 Parent(s): 11b54a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -29
app.py CHANGED
@@ -1,7 +1,7 @@
1
  from fastapi import FastAPI
2
  from fastapi.responses import PlainTextResponse
3
  from pydantic import BaseModel
4
- from transformers import AutoTokenizer, AutoModelForCausalLM
5
  import torch
6
  import uvicorn
7
  import threading
@@ -18,60 +18,68 @@ model.eval()
18
 
19
  # 🔹 настройки
20
  MAX_HISTORY = 40
21
- NUM_WORKERS = 3 # 🔥 ВАЖНО: количество потоков
22
 
23
- db = OrderedDict()
24
  queue = []
25
 
26
  class Message(BaseModel):
27
  message: str
28
 
29
 
30
- def generate_ai(message: str):
 
31
  prompt = f"User: {message}\nAssistant: Answer clearly and fully:\n"
32
 
33
  inputs = tokenizer(prompt, return_tensors="pt")
34
 
35
- with torch.no_grad():
36
- outputs = model.generate(
37
- **inputs,
38
- max_new_tokens=180,
39
- min_new_tokens=20,
40
- do_sample=True,
41
- temperature=0.7,
42
- top_p=0.9,
43
- eos_token_id=tokenizer.eos_token_id
44
- )
45
 
46
- input_length = inputs.input_ids.shape[1]
47
- generated_tokens = outputs[0][input_length:]
 
 
 
 
 
 
 
 
48
 
49
- reply = tokenizer.decode(generated_tokens, skip_special_tokens=True).strip()
 
50
 
51
- return reply
52
 
 
 
53
 
54
- # 🔥 Поток-воркер
 
 
 
 
 
 
 
55
  def worker():
56
  while True:
57
  if queue:
58
  message = queue.pop(0)
59
 
60
- # ⚡ если уже есть ответ — пропускаем
61
  if message in db and db[message]["status"] == "done":
62
  continue
63
 
64
- reply = generate_ai(message)
65
 
66
  if message in db:
67
  db[message]["status"] = "done"
68
  db[message]["reply"] = reply
69
-
70
  else:
71
- time.sleep(0.01) # 🔥 меньше лаг
72
 
73
 
74
- # 🔥 запускаем несколько воркеров
75
  for _ in range(NUM_WORKERS):
76
  threading.Thread(target=worker, daemon=True).start()
77
 
@@ -81,16 +89,19 @@ async def root():
81
  return PlainTextResponse("AI server работает")
82
 
83
 
84
- # 🔹 отправка запроса
85
  @app.get("/ask")
86
  async def ask(message: str):
87
 
88
- # ⚡ МГНОВЕННЫЙ КЭШ
89
  if message in db and db[message]["status"] == "done":
90
  return PlainTextResponse("cached")
91
 
92
  if message not in db:
93
- db[message] = {"status": "pending", "reply": ""}
 
 
 
94
  queue.append(message)
95
 
96
  if len(db) > MAX_HISTORY:
@@ -99,7 +110,7 @@ async def ask(message: str):
99
  return PlainTextResponse("accepted")
100
 
101
 
102
- # 🔹 получение ответа
103
  @app.get("/get")
104
  async def get(message: str):
105
 
@@ -109,7 +120,7 @@ async def get(message: str):
109
  data = db[message]
110
 
111
  if data["status"] == "pending":
112
- return PlainTextResponse("processing")
113
 
114
  return PlainTextResponse(data["reply"])
115
 
 
1
  from fastapi import FastAPI
2
  from fastapi.responses import PlainTextResponse
3
  from pydantic import BaseModel
4
+ from transformers import AutoTokenizer, AutoModelForCausalLM, TextIteratorStreamer
5
  import torch
6
  import uvicorn
7
  import threading
 
18
 
19
  # 🔹 настройки
20
  MAX_HISTORY = 40
21
+ NUM_WORKERS = 3
22
 
23
+ db = OrderedDict() # message -> {status, reply}
24
  queue = []
25
 
26
  class Message(BaseModel):
27
  message: str
28
 
29
 
30
+ # 🔥 STREAMING GENERATION
31
+ def generate_ai_stream(message: str):
32
  prompt = f"User: {message}\nAssistant: Answer clearly and fully:\n"
33
 
34
  inputs = tokenizer(prompt, return_tensors="pt")
35
 
36
+ streamer = TextIteratorStreamer(tokenizer, skip_special_tokens=True)
 
 
 
 
 
 
 
 
 
37
 
38
+ gen_kwargs = dict(
39
+ **inputs,
40
+ max_new_tokens=300,
41
+ min_new_tokens=30,
42
+ do_sample=True,
43
+ temperature=0.7,
44
+ top_p=0.9,
45
+ streamer=streamer,
46
+ eos_token_id=tokenizer.eos_token_id
47
+ )
48
 
49
+ thread = threading.Thread(target=model.generate, kwargs=gen_kwargs)
50
+ thread.start()
51
 
52
+ partial = ""
53
 
54
+ for text in streamer:
55
+ partial += text
56
 
57
+ # 🔥 обновляем ответ в реальном времени
58
+ if message in db:
59
+ db[message]["reply"] = partial
60
+
61
+ return partial.strip()
62
+
63
+
64
+ # 🔥 WORKER
65
  def worker():
66
  while True:
67
  if queue:
68
  message = queue.pop(0)
69
 
 
70
  if message in db and db[message]["status"] == "done":
71
  continue
72
 
73
+ reply = generate_ai_stream(message)
74
 
75
  if message in db:
76
  db[message]["status"] = "done"
77
  db[message]["reply"] = reply
 
78
  else:
79
+ time.sleep(0.01)
80
 
81
 
82
+ # 🔥 запускаем 3 воркера (ускорение x2-x3)
83
  for _ in range(NUM_WORKERS):
84
  threading.Thread(target=worker, daemon=True).start()
85
 
 
89
  return PlainTextResponse("AI server работает")
90
 
91
 
92
+ # 🔹 ASK
93
  @app.get("/ask")
94
  async def ask(message: str):
95
 
96
+ # кеш
97
  if message in db and db[message]["status"] == "done":
98
  return PlainTextResponse("cached")
99
 
100
  if message not in db:
101
+ db[message] = {
102
+ "status": "pending",
103
+ "reply": ""
104
+ }
105
  queue.append(message)
106
 
107
  if len(db) > MAX_HISTORY:
 
110
  return PlainTextResponse("accepted")
111
 
112
 
113
+ # 🔹 GET (визуальный стриминг)
114
  @app.get("/get")
115
  async def get(message: str):
116
 
 
120
  data = db[message]
121
 
122
  if data["status"] == "pending":
123
+ return PlainTextResponse(data["reply"] or "thinking...")
124
 
125
  return PlainTextResponse(data["reply"])
126