gaeunseo commited on
Commit
aa86eef
ยท
verified ยท
1 Parent(s): 7e7a3be

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -22
app.py CHANGED
@@ -7,41 +7,44 @@ ai_message = "Hello, how can I help you?"
7
 
8
  def stream_human_message():
9
  """
10
- Human ๋ฉ”์‹œ์ง€๋ฅผ ํ•œ ๊ธ€์ž์”ฉ ํƒ€์ดํ•‘ ํšจ๊ณผ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•ฉ๋‹ˆ๋‹ค.
11
- ๊ฐ ๋ฌธ์ž๋Š” <span> ํƒœ๊ทธ๋กœ ์ƒ์„ฑ๋˜๋ฉฐ, ํด๋ฆญ ์‹œ ํ›„์† ๋™์ž‘์€ ํŽ˜์ด์ง€ ์ƒ๋‹จ์— ๋ฏธ๋ฆฌ ๋กœ๋“œํ•œ ์Šคํฌ๋ฆฝํŠธ์—์„œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
12
  """
 
13
  html = "<div id='human_message' class='speech-bubble human'>"
14
- yield html # ์ดˆ๊ธฐ ์ปจํ…Œ์ด๋„ˆ๋งŒ ์ถœ๋ ฅ
15
  # ํ•œ ๊ธ€์ž์”ฉ ์ถ”๊ฐ€
16
  for i, ch in enumerate(human_message):
17
  html += f"<span data-index='{i}'>{ch}</span>"
18
  yield html
19
- time.sleep(0.05)
20
  html += "</div>"
21
  yield html
22
 
23
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ
24
  with gr.Blocks() as demo:
25
- # ํŽ˜์ด์ง€ ์ƒ๋‹จ์— ํ•œ ๋ฒˆ๋งŒ ๋กœ๋“œํ•  ์Šคํฌ๋ฆฝํŠธ ์ถ”๊ฐ€ (์ด๋ฒคํŠธ ์œ„์ž„ ๋ฐฉ์‹ ์‚ฌ์šฉ)
26
  gr.HTML(
27
  """
28
  <script>
29
- // ์ „์—ญ ํ”Œ๋ž˜๊ทธ: ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌํ•˜๋„๋ก
30
- window.cutDone = false;
31
- // ๋ถ€๋ชจ ์ปจํ…Œ์ด๋„ˆ์— ์ด๋ฒคํŠธ ์œ„์ž„์œผ๋กœ ํด๋ฆญ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
32
  document.addEventListener("click", function(event) {
33
- if (window.cutDone) return; // ์ด๋ฏธ ์ฒ˜๋ฆฌํ•œ ๊ฒฝ์šฐ
34
- // ํด๋ฆญํ•œ ์š”์†Œ๊ฐ€ data-index ์†์„ฑ์„ ๊ฐ€์ง„ span ์ธ์ง€ ํ™•์ธ
35
- if (event.target && event.target.matches("span[data-index]")) {
36
  var span = event.target;
37
- window.cutDone = true;
38
- // ํด๋ฆญํ•œ span ๋ฐ”๋กœ ๋’ค์— โœ‚๏ธ ์ด๋ชจํ‹ฐ์ฝ˜ ์‚ฝ์ž…
 
 
 
 
 
 
39
  var scissor = document.createElement('span');
40
  scissor.textContent = 'โœ‚๏ธ';
41
- span.parentNode.insertBefore(scissor, span.nextSibling);
42
- // ํด๋ฆญํ•œ ๋ฌธ์ž์˜ data-index ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์ดํ›„ ๋ฌธ์ž๋“ค์˜ ์ƒ‰์ƒ์„ ํšŒ์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ
 
43
  var cutIndex = parseInt(span.getAttribute('data-index'));
44
- var spans = span.parentNode.querySelectorAll('span[data-index]');
45
  spans.forEach(function(s) {
46
  var idx = parseInt(s.getAttribute('data-index'));
47
  if (idx > cutIndex) {
@@ -54,15 +57,17 @@ with gr.Blocks() as demo:
54
  """
55
  )
56
 
57
- # CSS ์Šคํƒ€์ผ ์ ์šฉ (๋งํ’์„  ๋ชจ์–‘ ๋ฐ ๋ฐฐ์น˜)
58
  gr.HTML(
59
  """
60
  <style>
 
61
  .chat-container {
62
  display: flex;
63
  flex-direction: column;
64
  gap: 10px;
65
  }
 
66
  .speech-bubble {
67
  position: relative;
68
  padding: 10px 15px;
@@ -72,6 +77,7 @@ with gr.Blocks() as demo:
72
  font-size: 16px;
73
  line-height: 1.4;
74
  }
 
75
  .human {
76
  background: #d0f0d0;
77
  align-self: flex-end;
@@ -86,6 +92,7 @@ with gr.Blocks() as demo:
86
  border-style: solid;
87
  border-color: transparent transparent transparent #d0f0d0;
88
  }
 
89
  .ai {
90
  background: #e0e0e0;
91
  align-self: flex-start;
@@ -98,7 +105,7 @@ with gr.Blocks() as demo:
98
  top: 10px;
99
  border-width: 10px 10px 10px 0;
100
  border-style: solid;
101
- border-color: transparent #e0e0e0 transparent transparent;
102
  }
103
  </style>
104
  """
@@ -106,12 +113,12 @@ with gr.Blocks() as demo:
106
 
107
  gr.Markdown("## Chat Interface")
108
  with gr.Column(elem_classes="chat-container"):
109
- # ์œ„์ชฝ์— Human ๋ฉ”์‹œ์ง€ (์ŠคํŠธ๋ฆฌ๋ฐ ์—…๋ฐ์ดํŠธ)
110
  human_bubble = gr.HTML("")
111
- # ์•„๋ž˜์ชฝ์— AI ๋ฉ”์‹œ์ง€ (๊ณ ์ •)
112
  ai_bubble = gr.HTML(f"<div id='ai_message' class='speech-bubble ai'>{ai_message}</div>")
113
 
114
- # ํƒ€์ดํ•‘ ํšจ๊ณผ๋ฅผ ์‹œ์ž‘ํ•  ๋ฒ„ํŠผ
115
  start_button = gr.Button("Start Typing")
116
  start_button.click(fn=stream_human_message, outputs=human_bubble)
117
 
 
7
 
8
  def stream_human_message():
9
  """
10
+ Human ๋ฉ”์‹œ์ง€๋ฅผ ํ•œ ๊ธ€์ž์”ฉ ํƒ€์ดํ•‘ํ•˜๋Š” ํšจ๊ณผ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•ฉ๋‹ˆ๋‹ค.
11
+ ๊ฐ ๊ธ€์ž๋Š” <span> ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ง€๋ฉฐ, Start Typing ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋˜์–ด ๊ธฐ์กด์˜ โœ‚๏ธ ์œ„์น˜ ๋ฐ ํšŒ์ƒ‰ ์ฒ˜๋ฆฌ ๋“ฑ์ด ๋ฆฌ์…‹๋ฉ๋‹ˆ๋‹ค.
12
  """
13
+ # ์ดˆ๊ธฐ ๋งํ’์„  ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ
14
  html = "<div id='human_message' class='speech-bubble human'>"
15
+ yield html # ์ดˆ๊ธฐ ์ปจํ…Œ์ด๋„ˆ ์ถœ๋ ฅ
16
  # ํ•œ ๊ธ€์ž์”ฉ ์ถ”๊ฐ€
17
  for i, ch in enumerate(human_message):
18
  html += f"<span data-index='{i}'>{ch}</span>"
19
  yield html
20
+ time.sleep(0.05) # ํƒ€์ดํ•‘ ํšจ๊ณผ ๋”œ๋ ˆ์ด
21
  html += "</div>"
22
  yield html
23
 
 
24
  with gr.Blocks() as demo:
25
+ # ํŽ˜์ด์ง€ ์ƒ๋‹จ์— ๋‹จ ํ•œ ๋ฒˆ ๋กœ๋“œ๋  ์Šคํฌ๋ฆฝํŠธ: ์ด๋ฒคํŠธ ์œ„์ž„ ๋ฐฉ์‹์œผ๋กœ ํด๋ฆญ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
26
  gr.HTML(
27
  """
28
  <script>
29
+ // ๋ฌธ์„œ ์ „์ฒด์—์„œ ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ, human ๋งํ’์„  ๋‚ด์˜ span ์š”์†Œ์— ๋Œ€ํ•ด ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
 
 
30
  document.addEventListener("click", function(event) {
31
+ // human ๋งํ’์„  ๋‚ด๋ถ€์˜ data-index ์†์„ฑ์„ ๊ฐ€์ง„ span์ด ํด๋ฆญ๋œ ๊ฒฝ์šฐ์—๋งŒ ์ฒ˜๋ฆฌ
32
+ if (event.target && event.target.matches("div.speech-bubble.human span[data-index]")) {
 
33
  var span = event.target;
34
+ var container = span.parentNode;
35
+ // ๊ธฐ์กด์— ์‚ฝ์ž…๋œ ๋ชจ๋“  scissor ์š”์†Œ ์ œ๊ฑฐ
36
+ var oldScissors = container.querySelectorAll("span.scissor");
37
+ oldScissors.forEach(function(s) { s.remove(); });
38
+ // ๋ชจ๋“  span์˜ ํšŒ์ƒ‰ ์Šคํƒ€์ผ ์ œ๊ฑฐ
39
+ var spans = container.querySelectorAll("span[data-index]");
40
+ spans.forEach(function(s) { s.style.color = ''; });
41
+ // ํด๋ฆญํ•œ span ๋’ค์— โœ‚๏ธ ์•„์ด์ฝ˜์„ ์‚ฝ์ž… (ํด๋ž˜์Šค "scissor" ์ถ”๊ฐ€)
42
  var scissor = document.createElement('span');
43
  scissor.textContent = 'โœ‚๏ธ';
44
+ scissor.classList.add('scissor');
45
+ container.insertBefore(scissor, span.nextSibling);
46
+ // ํด๋ฆญํ•œ ๋ฌธ์ž ์ดํ›„์˜ ๋ชจ๋“  span์— ๋Œ€ํ•ด ํ…์ŠคํŠธ ์ƒ‰์ƒ์„ ํšŒ์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝ
47
  var cutIndex = parseInt(span.getAttribute('data-index'));
 
48
  spans.forEach(function(s) {
49
  var idx = parseInt(s.getAttribute('data-index'));
50
  if (idx > cutIndex) {
 
57
  """
58
  )
59
 
60
+ # CSS ์Šคํƒ€์ผ: ๋งํ’์„  ๋ชจ์–‘ ๋ฐ ๋ฐฐ์น˜ ์„ค์ •
61
  gr.HTML(
62
  """
63
  <style>
64
+ /* ์ „์ฒด ์ฑ„ํŒ… ์˜์—ญ: ์„ธ๋กœ ๋ฐฐ์น˜ */
65
  .chat-container {
66
  display: flex;
67
  flex-direction: column;
68
  gap: 10px;
69
  }
70
+ /* ๊ณตํ†ต ๋งํ’์„  ์Šคํƒ€์ผ */
71
  .speech-bubble {
72
  position: relative;
73
  padding: 10px 15px;
 
77
  font-size: 16px;
78
  line-height: 1.4;
79
  }
80
+ /* Human ๋งํ’์„ : ์˜ค๋ฅธ์ชฝ ์ •๋ ฌ, ์ดˆ๋ก์ƒ‰ ๋ฐฐ๊ฒฝ ๋ฐ ์˜ค๋ฅธ์ชฝ ๊ผฌ๋ฆฌ */
81
  .human {
82
  background: #d0f0d0;
83
  align-self: flex-end;
 
92
  border-style: solid;
93
  border-color: transparent transparent transparent #d0f0d0;
94
  }
95
+ /* AI ๋งํ’์„ : ์™ผ์ชฝ ์ •๋ ฌ, ํšŒ์ƒ‰ ๋ฐฐ๊ฒฝ ๋ฐ ์™ผ์ชฝ ๊ผฌ๋ฆฌ */
96
  .ai {
97
  background: #e0e0e0;
98
  align-self: flex-start;
 
105
  top: 10px;
106
  border-width: 10px 10px 10px 0;
107
  border-style: solid;
108
+ border-color: transparent #e0f0e0 transparent transparent;
109
  }
110
  </style>
111
  """
 
113
 
114
  gr.Markdown("## Chat Interface")
115
  with gr.Column(elem_classes="chat-container"):
116
+ # ์œ„์ชฝ: Human ๋งํ’์„  (์ŠคํŠธ๋ฆฌ๋ฐ ์—…๋ฐ์ดํŠธ๋จ)
117
  human_bubble = gr.HTML("")
118
+ # ์•„๋ž˜์ชฝ: AI ๋งํ’์„  (๊ณ ์ • ๋ฉ”์‹œ์ง€)
119
  ai_bubble = gr.HTML(f"<div id='ai_message' class='speech-bubble ai'>{ai_message}</div>")
120
 
121
+ # ํƒ€์ดํ•‘ ์‹œ์ž‘ ๋ฒ„ํŠผ: ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ stream_human_message๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ์ƒˆ HTML์„ ์ƒ์„ฑ (์ฆ‰, โœ‚๏ธ ์œ„์น˜๊ฐ€ ๋ฆฌ์…‹๋จ)
122
  start_button = gr.Button("Start Typing")
123
  start_button.click(fn=stream_human_message, outputs=human_bubble)
124