Jay1121 commited on
Commit
9d39fc7
·
verified ·
1 Parent(s): 60717c7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -148
app.py CHANGED
@@ -25,42 +25,20 @@ print("✅ 로딩 완료!")
25
  # ------------------------------------------------------------------
26
  # 2. 시스템 프롬프트
27
  # ------------------------------------------------------------------
28
- SYSTEM_PROMPT = """너는 사용자와 반말을 쓰는 사이야.
29
  - 반말로 편하게 대화해. 존댓말 절대 쓰지 마.
30
  - PC통신 채팅방에서 대화하듯이 텍스트 위주로 툭툭 던져.
31
  - 이모지(😊) 같은 건 쓰지 말고, 옛날 텍스트 이모티콘(^^, ㅡㅡ;, ㅋㅋ)을 주로 써.
32
- - MZ말투를 유지해 주고 상대가 먼저 욕 박으면 같이 욕해.
33
  - 질문에는 솔직하게 대답하되, 너무 길지 않게 채팅하듯 끊어서 말해."""
34
 
35
  # ------------------------------------------------------------------
36
  # 3. 채팅 로직
37
  # ------------------------------------------------------------------
38
- def _normalize_history(history):
39
  """
40
- Gradio Chatbot history는 보통:
41
- - [[u, b], [u, b], ...] (list of lists)
42
- - [(u, b), (u, b), ...] (list of tuples)
43
- 인데 상황에 따라 섞여 들어오기도 해서 안전하게 표준화.
44
  """
45
- if not history:
46
- return []
47
-
48
- norm = []
49
- for h in history:
50
- if not h:
51
- continue
52
- if isinstance(h, (list, tuple)) and len(h) == 2:
53
- u, b = h[0], h[1]
54
- if u is None:
55
- continue
56
- # b가 None인 "작성중" 행은 모델 입력 히스토리에서 제외
57
- if b is None:
58
- continue
59
- norm.append((str(u), str(b)))
60
- return norm
61
-
62
-
63
- def chat_response(user_input, history_for_model):
64
  clean_input = (user_input or "").replace(" ", "")
65
 
66
  greeting_words = ["안녕", "ㅎㅇ", "하이", "반가", "접속"]
@@ -73,7 +51,7 @@ def chat_response(user_input, history_for_model):
73
  final_instruction = (
74
  f"(사용자가 밸런스 게임을 하자고 한다. 주제는 '{topic}'이다. "
75
  "아주 고르기 곤란하고 짜증나는 두 가지 선택지(A vs B)를 제시해라. "
76
- "말투는 요즘 MZ들처럼 시니컬하게 해라.) "
77
  "자, 질문해."
78
  )
79
  elif is_greeting:
@@ -82,12 +60,14 @@ def chat_response(user_input, history_for_model):
82
  final_instruction = user_input
83
 
84
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
85
- for u, b in (history_for_model or []):
86
- messages.append({"role": "user", "content": u})
87
- messages.append({"role": "assistant", "content": b})
 
 
88
  messages.append({"role": "user", "content": final_instruction})
89
 
90
- response = llm.create_chat_completion(
91
  messages=messages,
92
  max_tokens=256,
93
  stop=["<|end_of_text|>", "###", "User:"],
@@ -95,127 +75,104 @@ def chat_response(user_input, history_for_model):
95
  top_p=0.9,
96
  repeat_penalty=1.2
97
  )
98
- return response["choices"][0]["message"]["content"].strip()
99
-
100
 
101
  # ------------------------------------------------------------------
102
- # 4. CSS - 가독성 개선 & 레이아웃 수정
103
  # ------------------------------------------------------------------
104
  PC_COM_CSS = r"""
105
  @import url('https://cdn.jsdelivr.net/gh/neodgm/neodgm-webfont@latest/neodgm/neodgm.css');
106
 
107
  :root {
108
- --pc-bg: #000084;
109
- --pc-input-bg: #000042;
110
- --pc-text: #FFFFFF;
111
- --pc-user: #FFFF55;
112
- --pc-bot: #FFFFFF;
113
- --pc-accent: #00AAAA;
114
  --pc-grey: #AAAAAA;
115
  }
116
 
117
  body, .gradio-container {
118
- background-color: var(--pc-bg) !important;
119
  font-family: 'NeoDunggeunmo', monospace !important;
120
- color: var(--pc-text) !important;
121
  }
122
 
123
  h1 {
124
  font-family: 'NeoDunggeunmo', monospace !important;
125
- color: var(--pc-user) !important;
126
- background-color: var(--pc-bg) !important;
127
- border-bottom: 2px double var(--pc-text) !important;
 
 
128
  text-align: center;
129
- font-size: 28px !important;
130
- margin-bottom: 10px !important;
131
  }
 
132
  h1::before { content: "☎ "; }
133
  h1::after { content: " ☎"; }
134
 
135
  .gradio-container p {
136
- color: var(--pc-accent) !important;
137
- font-size: 16px !important;
138
- margin-bottom: 20px !important;
 
139
  }
140
 
141
  .chatbot {
142
- height: 65vh !important;
143
- background-color: var(--pc-input-bg) !important;
144
- border: 2px solid var(--pc-text) !important;
145
  border-radius: 0 !important;
146
- padding: 20px !important;
147
  overflow-y: scroll !important;
148
  }
149
 
150
  .message {
151
  background: transparent !important;
152
  border: none !important;
153
- padding: 5px 0 !important;
154
- font-size: 18px !important;
155
- line-height: 1.6 !important;
156
  box-shadow: none !important;
 
157
  }
158
 
159
- .message.user-row, .user {
160
- justify-content: flex-start !important;
161
- background: transparent !important;
162
- border-bottom: 1px dashed #333 !important;
163
- }
164
- .message.user-row .message, .user .message {
165
- color: var(--pc-user) !important;
166
- text-align: left !important;
167
- font-weight: bold !important;
168
- }
169
- .message.user-row .message::before, .user .message::before {
170
- content: "나 > ";
171
- color: var(--pc-grey);
172
- margin-right: 8px;
173
- }
174
 
175
- .message.bot-row, .bot {
176
- background: transparent !important;
177
- border-bottom: 1px dashed #333 !important;
178
- }
179
- .message.bot-row .message, .bot .message {
180
- color: var(--pc-bot) !important;
181
- text-align: left !important;
182
- }
183
- .message.bot-row .message::before, .bot .message::before {
184
- content: "똘배 > ";
185
- color: var(--pc-accent);
186
- margin-right: 8px;
187
- }
188
 
189
  .avatar { display: none !important; }
190
 
191
  .input-container {
 
 
192
  margin-top: 10px !important;
193
- background: transparent !important;
194
- border: none !important;
195
  gap: 10px !important;
196
  }
197
 
198
  textarea, input {
199
- background-color: var(--pc-input-bg) !important;
200
- color: var(--pc-text) !important;
201
- border: 2px solid var(--pc-grey) !important;
202
  border-radius: 0 !important;
203
  font-family: 'NeoDunggeunmo', monospace !important;
204
- font-size: 18px !important;
205
- padding: 10px !important;
 
206
  }
207
- textarea::placeholder { color: var(--pc-grey) !important; }
208
 
209
  button.primary {
210
  background: var(--pc-grey) !important;
211
  color: #000 !important;
212
- border: 2px solid var(--pc-text) !important;
213
- font-weight: bold !important;
214
  font-family: 'NeoDunggeunmo', monospace !important;
 
215
  }
216
- button.primary:hover {
217
- background: var(--pc-text) !important;
218
- }
219
 
220
  #clear-btn {
221
  background: transparent !important;
@@ -225,12 +182,8 @@ button.primary:hover {
225
  padding: 2px 10px !important;
226
  margin-top: 5px !important;
227
  width: auto !important;
228
- align-self: flex-start !important;
229
- }
230
- #clear-btn:hover {
231
- color: var(--pc-text) !important;
232
- border-color: var(--pc-text) !important;
233
  }
 
234
 
235
  .examples {
236
  margin-top: 20px !important;
@@ -246,49 +199,35 @@ button.primary:hover {
246
  }
247
  .examples button {
248
  background: transparent !important;
249
- color: var(--pc-accent) !important;
250
- border: 1px solid var(--pc-accent) !important;
251
  border-radius: 0 !important;
252
  padding: 5px 15px !important;
253
  font-size: 16px !important;
254
  font-family: 'NeoDunggeunmo', monospace !important;
255
- transition: all 0.2s;
256
- }
257
- .examples button:hover {
258
- background: var(--pc-accent) !important;
259
- color: #000 !important;
260
  }
261
 
262
  footer { display: none !important; }
263
  """
264
 
265
  # ------------------------------------------------------------------
266
- # 5. App 실행 (Blocks)
267
- # ✅ 핵심: api_name 붙인 단일 엔드포인트(predict)로 HF가 API 탐지함
268
- # �� gradio 4.36.1 호환: Chatbot에 type= 넣지 말기
269
  # ------------------------------------------------------------------
270
  with gr.Blocks(theme=gr.themes.Base(), css=PC_COM_CSS, title="CHOLLIAN 98") as demo:
271
- gr.Markdown("19금 채팅방")
272
  gr.Markdown(">> 01410 접속 성공... [대화실]에 입장하셨습니다.")
273
 
274
- chatbot = gr.Chatbot(
275
- label="대화내용",
276
- show_label=False,
277
- elem_classes="chatbot"
278
- )
279
 
280
  with gr.Row(elem_classes="input-container"):
281
  msg = gr.Textbox(
282
- scale=8,
283
- show_label=False,
284
- placeholder="할 말을 입력하세요...",
285
- container=False,
286
- autofocus=True
287
  )
288
- submit_btn = gr.Button(" ", scale=1, variant="primary")
289
 
290
- with gr.Row():
291
- clear = gr.Button("화면 지우기", elem_id="clear-btn")
292
 
293
  gr.Examples(
294
  examples=[
@@ -298,25 +237,27 @@ with gr.Blocks(theme=gr.themes.Base(), css=PC_COM_CSS, title="CHOLLIAN 98") as d
298
  "야 밥 뭐먹지 추천좀",
299
  ],
300
  inputs=msg,
301
- label="빠른 입력"
 
302
  )
303
 
304
- def predict(user_message, history):
305
- # history는 [[u,b],...] 형태로 들어올 확률이 큼
306
  history = history or []
307
- history_for_model = _normalize_history(history)
308
 
309
- bot_message = chat_response(user_message, history_for_model)
 
 
 
 
 
310
 
311
- # Chatbot 출력은 list of lists로 통일 (4.36.1에서 제일 안전)
312
- new_history = []
313
- for h in history:
314
- if isinstance(h, (list, tuple)) and len(h) == 2:
315
- new_history.append([h[0], h[1]])
316
- new_history.append([user_message, bot_message])
317
 
 
 
318
  return "", new_history
319
 
 
320
  msg.submit(
321
  predict,
322
  inputs=[msg, chatbot],
@@ -324,7 +265,6 @@ with gr.Blocks(theme=gr.themes.Base(), css=PC_COM_CSS, title="CHOLLIAN 98") as d
324
  queue=True,
325
  api_name="chat"
326
  )
327
-
328
  submit_btn.click(
329
  predict,
330
  inputs=[msg, chatbot],
@@ -332,14 +272,8 @@ with gr.Blocks(theme=gr.themes.Base(), css=PC_COM_CSS, title="CHOLLIAN 98") as d
332
  queue=True,
333
  api_name="chat"
334
  )
335
-
336
- clear.click(
337
- lambda: [],
338
- inputs=None,
339
- outputs=chatbot,
340
- queue=False,
341
- api_name="clear"
342
- )
343
 
344
  if __name__ == "__main__":
345
- demo.queue().launch(server_name="0.0.0.0", server_port=7860)
 
 
25
  # ------------------------------------------------------------------
26
  # 2. 시스템 프롬프트
27
  # ------------------------------------------------------------------
28
+ SYSTEM_PROMPT = """너는 사용자의 오랜 찐친 '똘배'야.
29
  - 반말로 편하게 대화해. 존댓말 절대 쓰지 마.
30
  - PC통신 채팅방에서 대화하듯이 텍스트 위주로 툭툭 던져.
31
  - 이모지(😊) 같은 건 쓰지 말고, 옛날 텍스트 이모티콘(^^, ㅡㅡ;, ㅋㅋ)을 주로 써.
32
+ - MZ세대 특유의 알빠노 감성을 유지해 주고 먼저 욕 하면 너도 욕 박아.
33
  - 질문에는 솔직하게 대답하되, 너무 길지 않게 채팅하듯 끊어서 말해."""
34
 
35
  # ------------------------------------------------------------------
36
  # 3. 채팅 로직
37
  # ------------------------------------------------------------------
38
+ def chat_response(user_input, history_pairs):
39
  """
40
+ history_pairs: [(user, bot), ...] 형태로 받아서 llama_cpp messages로 변환
 
 
 
41
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  clean_input = (user_input or "").replace(" ", "")
43
 
44
  greeting_words = ["안녕", "ㅎㅇ", "하이", "반가", "접속"]
 
51
  final_instruction = (
52
  f"(사용자가 밸런스 게임을 하자고 한다. 주제는 '{topic}'이다. "
53
  "아주 고르기 곤란하고 짜증나는 두 가지 선택지(A vs B)를 제시해라. "
54
+ "말투는 어디 한 번 골라보라는 듯이 시니컬하게 해라.) "
55
  "자, 질문해."
56
  )
57
  elif is_greeting:
 
60
  final_instruction = user_input
61
 
62
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
63
+ for u, b in (history_pairs or []):
64
+ if u is None or b is None:
65
+ continue
66
+ messages.append({"role": "user", "content": str(u)})
67
+ messages.append({"role": "assistant", "content": str(b)})
68
  messages.append({"role": "user", "content": final_instruction})
69
 
70
+ r = llm.create_chat_completion(
71
  messages=messages,
72
  max_tokens=256,
73
  stop=["<|end_of_text|>", "###", "User:"],
 
75
  top_p=0.9,
76
  repeat_penalty=1.2
77
  )
78
+ return r["choices"][0]["message"]["content"].strip()
 
79
 
80
  # ------------------------------------------------------------------
81
+ # 4. CSS (네 감성 그대로)
82
  # ------------------------------------------------------------------
83
  PC_COM_CSS = r"""
84
  @import url('https://cdn.jsdelivr.net/gh/neodgm/neodgm-webfont@latest/neodgm/neodgm.css');
85
 
86
  :root {
87
+ --pc-blue: #0000AA;
88
+ --pc-white: #EFEFEF;
89
+ --pc-yellow: #FFFF55;
90
+ --pc-cyan: #00AAAA;
 
 
91
  --pc-grey: #AAAAAA;
92
  }
93
 
94
  body, .gradio-container {
95
+ background-color: var(--pc-blue) !important;
96
  font-family: 'NeoDunggeunmo', monospace !important;
97
+ color: var(--pc-white) !important;
98
  }
99
 
100
  h1 {
101
  font-family: 'NeoDunggeunmo', monospace !important;
102
+ color: var(--pc-yellow) !important;
103
+ background-color: #000084 !important;
104
+ border-bottom: 2px double var(--pc-white) !important;
105
+ padding-bottom: 10px !important;
106
+ margin-bottom: 20px !important;
107
  text-align: center;
108
+ font-size: 32px !important;
109
+ letter-spacing: 2px;
110
  }
111
+
112
  h1::before { content: "☎ "; }
113
  h1::after { content: " ☎"; }
114
 
115
  .gradio-container p {
116
+ color: var(--pc-cyan) !important;
117
+ font-size: 18px !important;
118
+ border-bottom: 1px dashed var(--pc-grey);
119
+ padding-bottom: 5px;
120
  }
121
 
122
  .chatbot {
123
+ background-color: var(--pc-blue) !important;
124
+ border: 2px solid var(--pc-white) !important;
 
125
  border-radius: 0 !important;
126
+ height: 60vh !important;
127
  overflow-y: scroll !important;
128
  }
129
 
130
  .message {
131
  background: transparent !important;
132
  border: none !important;
133
+ padding: 5px 10px !important;
134
+ font-size: 20px !important;
 
135
  box-shadow: none !important;
136
+ line-height: 1.4 !important;
137
  }
138
 
139
+ .message.user-row, .user { justify-content: flex-start !important; background: transparent !important; }
140
+ .message.user-row .message, .user .message { color: var(--pc-yellow) !important; text-align: left !important; }
141
+ .message.user-row .message::before, .user .message::before { content: "나 > "; color: var(--pc-grey); margin-right: 5px; }
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
+ .message.bot-row, .bot { background: transparent !important; }
144
+ .message.bot-row .message, .bot .message { color: var(--pc-white) !important; text-align: left !important; }
145
+ .message.bot-row .message::before, .bot .message::before { content: "똘배 > "; color: var(--pc-cyan); margin-right: 5px; }
 
 
 
 
 
 
 
 
 
 
146
 
147
  .avatar { display: none !important; }
148
 
149
  .input-container {
150
+ background-color: var(--pc-blue) !important;
151
+ border-top: 2px double var(--pc-white) !important;
152
  margin-top: 10px !important;
 
 
153
  gap: 10px !important;
154
  }
155
 
156
  textarea, input {
157
+ background-color: var(--pc-blue) !important;
158
+ color: var(--pc-white) !important;
159
+ border: 1px solid var(--pc-grey) !important;
160
  border-radius: 0 !important;
161
  font-family: 'NeoDunggeunmo', monospace !important;
162
+ font-size: 20px !important;
163
+ outline: none !important;
164
+ box-shadow: none !important;
165
  }
 
166
 
167
  button.primary {
168
  background: var(--pc-grey) !important;
169
  color: #000 !important;
170
+ border: 1px solid var(--pc-white) !important;
171
+ border-radius: 0 !important;
172
  font-family: 'NeoDunggeunmo', monospace !important;
173
+ box-shadow: 2px 2px 0px #000 !important;
174
  }
175
+ button.primary:hover { background: var(--pc-white) !important; }
 
 
176
 
177
  #clear-btn {
178
  background: transparent !important;
 
182
  padding: 2px 10px !important;
183
  margin-top: 5px !important;
184
  width: auto !important;
 
 
 
 
 
185
  }
186
+ #clear-btn:hover { color: var(--pc-white) !important; border-color: var(--pc-white) !important; }
187
 
188
  .examples {
189
  margin-top: 20px !important;
 
199
  }
200
  .examples button {
201
  background: transparent !important;
202
+ color: var(--pc-cyan) !important;
203
+ border: 1px solid var(--pc-cyan) !important;
204
  border-radius: 0 !important;
205
  padding: 5px 15px !important;
206
  font-size: 16px !important;
207
  font-family: 'NeoDunggeunmo', monospace !important;
 
 
 
 
 
208
  }
209
 
210
  footer { display: none !important; }
211
  """
212
 
213
  # ------------------------------------------------------------------
214
+ # 5. App (가로 배치 + API 엔드포인트 생성)
 
 
215
  # ------------------------------------------------------------------
216
  with gr.Blocks(theme=gr.themes.Base(), css=PC_COM_CSS, title="CHOLLIAN 98") as demo:
217
+ gr.Markdown("# ≪ 십 리 안 ≫")
218
  gr.Markdown(">> 01410 접속 성공... [대화실]에 입장하셨습니다.")
219
 
220
+ # Chatbot은 4.36.1에서 list-of-lists 포맷이 제일 안전
221
+ chatbot = gr.Chatbot(show_label=False, elem_classes="chatbot")
 
 
 
222
 
223
  with gr.Row(elem_classes="input-container"):
224
  msg = gr.Textbox(
225
+ scale=8, show_label=False, container=False,
226
+ placeholder="명령어를 입력하세요..."
 
 
 
227
  )
228
+ submit_btn = gr.Button("[ 전송 ]", scale=1, variant="primary")
229
 
230
+ clear = gr.Button("[ 화면 지우기 ]", elem_id="clear-btn")
 
231
 
232
  gr.Examples(
233
  examples=[
 
237
  "야 밥 뭐먹지 추천좀",
238
  ],
239
  inputs=msg,
240
+ label="빠른 입력",
241
+ cache_examples=False
242
  )
243
 
244
+ def predict(user_input, history):
 
245
  history = history or []
 
246
 
247
+ # 모델로 넘길 히스토리: [(u,b), ...]
248
+ hist_pairs = []
249
+ for u, b in history:
250
+ if u is None or b is None:
251
+ continue
252
+ hist_pairs.append((u, b))
253
 
254
+ bot_out = chat_response(user_input, hist_pairs)
 
 
 
 
 
255
 
256
+ # Gradio Chatbot 출력: [[u,b], ...]
257
+ new_history = [list(x) for x in history] + [[user_input, bot_out]]
258
  return "", new_history
259
 
260
+ # ✅ 이 api_name 때문에 API 문서에 엔드포인트가 생김 -> "No API found" 사라짐
261
  msg.submit(
262
  predict,
263
  inputs=[msg, chatbot],
 
265
  queue=True,
266
  api_name="chat"
267
  )
 
268
  submit_btn.click(
269
  predict,
270
  inputs=[msg, chatbot],
 
272
  queue=True,
273
  api_name="chat"
274
  )
275
+ clear.click(lambda: [], None, chatbot, queue=False, api_name="clear")
 
 
 
 
 
 
 
276
 
277
  if __name__ == "__main__":
278
+ # Spaces면 보통 포트 지정 안 하는 게 안전함 (지정해도 되는데, 이게 덜 말썽남)
279
+ demo.queue().launch(server_name="0.0.0.0")