seawolf2357 commited on
Commit
00dba49
ยท
verified ยท
1 Parent(s): 1670280

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -141
app.py CHANGED
@@ -17,7 +17,10 @@ from transformers import AutoProcessor, Gemma3ForConditionalGeneration, TextIter
17
  # CSV/TXT ๋ถ„์„
18
  import pandas as pd
19
 
20
- MAX_CONTENT_CHARS = 8000 # ํŒŒ์ผ์—์„œ ์ฝ์€ ๋‚ด์šฉ์ด ๋„ˆ๋ฌด ๊ธธ ๊ฒฝ์šฐ ์ด ์ •๋„์—์„œ ์ž˜๋ผ๋ƒ„
 
 
 
21
 
22
  model_id = os.getenv("MODEL_ID", "google/gemma-3-27b-it")
23
  processor = AutoProcessor.from_pretrained(model_id, padding_side="left")
@@ -31,16 +34,18 @@ model = Gemma3ForConditionalGeneration.from_pretrained(
31
  MAX_NUM_IMAGES = int(os.getenv("MAX_NUM_IMAGES", "5"))
32
 
33
 
 
 
 
34
  def analyze_csv_file(path: str) -> str:
35
  """
36
- CSV ํŒŒ์ผ์„ ์ฝ์–ด ๋ฌธ์ž์—ดํ™”. ๋„ˆ๋ฌด ํฌ๋ฉด ์ผ๋ถ€๋งŒ ์ž˜๋ผ๋ƒ„.
37
  """
38
  try:
39
  df = pd.read_csv(path)
40
  df_str = df.to_string()
41
  if len(df_str) > MAX_CONTENT_CHARS:
42
  df_str = df_str[:MAX_CONTENT_CHARS] + "\n...(truncated)..."
43
-
44
  return f"**[CSV File: {os.path.basename(path)}]**\n\n{df_str}"
45
  except Exception as e:
46
  return f"Failed to read CSV ({os.path.basename(path)}): {str(e)}"
@@ -48,19 +53,44 @@ def analyze_csv_file(path: str) -> str:
48
 
49
  def analyze_txt_file(path: str) -> str:
50
  """
51
- TXT ํŒŒ์ผ ์ „๋ฌธ ์ฝ์–ด๋“ค์ด๋˜, ๋„ˆ๋ฌด ๊ธธ๋ฉด ์ž˜๋ผ๋ƒ„.
52
  """
53
  try:
54
  with open(path, "r", encoding="utf-8") as f:
55
  text = f.read()
56
  if len(text) > MAX_CONTENT_CHARS:
57
  text = text[:MAX_CONTENT_CHARS] + "\n...(truncated)..."
58
-
59
  return f"**[TXT File: {os.path.basename(path)}]**\n\n{text}"
60
  except Exception as e:
61
  return f"Failed to read TXT ({os.path.basename(path)}): {str(e)}"
62
 
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  def count_files_in_new_message(paths: list[str]) -> tuple[int, int]:
65
  image_count = 0
66
  video_count = 0
@@ -88,14 +118,16 @@ def count_files_in_history(history: list[dict]) -> tuple[int, int]:
88
  def validate_media_constraints(message: dict, history: list[dict]) -> bool:
89
  """
90
  - ๋น„๋””์˜ค 1๊ฐœ ์ดˆ๊ณผ ๋ถˆ๊ฐ€
91
- - ๋น„๋””์˜ค/์ด๋ฏธ์ง€ ํ˜ผํ•ฉ ๋ถˆ๊ฐ€
92
  - ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ MAX_NUM_IMAGES ์ดˆ๊ณผ ๋ถˆ๊ฐ€
93
- - <image> ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ํƒœ๊ทธ ์ˆ˜์™€ ์‹ค์ œ ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ ์ผ์น˜
94
- - CSV, TXT, PDF ๋“ฑ์€ ์—ฌ๊ธฐ์„œ ์ œํ•œํ•˜์ง€ ์•Š์Œ.
95
  """
96
  media_files = []
97
  for f in message["files"]:
98
- # ์ด๋ฏธ์ง€(์—ฌ๋Ÿฌ ํ™•์žฅ์ž)๋‚˜ mp4๋งŒ ์ฒดํฌ
 
 
99
  if re.search(r"\.(png|jpg|jpeg|gif|webp)$", f, re.IGNORECASE) or f.endswith(".mp4"):
100
  media_files.append(f)
101
 
@@ -124,6 +156,9 @@ def validate_media_constraints(message: dict, history: list[dict]) -> bool:
124
  return True
125
 
126
 
 
 
 
127
  def downsample_video(video_path: str) -> list[tuple[Image.Image, float]]:
128
  vidcap = cv2.VideoCapture(video_path)
129
  fps = vidcap.get(cv2.CAP_PROP_FPS)
@@ -158,84 +193,103 @@ def process_video(video_path: str) -> list[dict]:
158
  return content
159
 
160
 
 
 
 
161
  def process_interleaved_images(message: dict) -> list[dict]:
162
- logger.debug(f"{message['files']=}")
163
  parts = re.split(r"(<image>)", message["text"])
164
- logger.debug(f"{parts=}")
165
-
166
  content = []
167
  image_index = 0
168
  for part in parts:
169
  if part == "<image>":
170
  content.append({"type": "image", "url": message["files"][image_index]})
171
- logger.debug(f"file: {message['files'][image_index]}")
172
  image_index += 1
173
  elif part.strip():
174
  content.append({"type": "text", "text": part.strip()})
175
- elif isinstance(part, str) and part != "<image>":
176
- content.append({"type": "text", "text": part})
177
- logger.debug(f"{content=}")
 
178
  return content
179
 
180
 
 
 
 
181
  def process_new_user_message(message: dict) -> list[dict]:
182
  if not message["files"]:
183
  return [{"type": "text", "text": message["text"]}]
184
 
185
- # ํ™•์žฅ์ž๋ณ„ ๋ถ„๋ฅ˜
186
  video_files = [f for f in message["files"] if f.endswith(".mp4")]
187
  image_files = [f for f in message["files"] if re.search(r"\.(png|jpg|jpeg|gif|webp)$", f, re.IGNORECASE)]
188
  csv_files = [f for f in message["files"] if f.lower().endswith(".csv")]
189
  txt_files = [f for f in message["files"] if f.lower().endswith(".txt")]
 
190
 
191
- # ์‚ฌ์šฉ์ž ์ž…๋ ฅ ํ…์ŠคํŠธ๋ฅผ ๋จผ์ €
192
  content_list = [{"type": "text", "text": message["text"]}]
193
 
194
- # CSV ์ „๋ฌธ
195
  for csv_path in csv_files:
196
  csv_analysis = analyze_csv_file(csv_path)
197
  content_list.append({"type": "text", "text": csv_analysis})
198
 
199
- # TXT ์ „๋ฌธ
200
  for txt_path in txt_files:
201
  txt_analysis = analyze_txt_file(txt_path)
202
  content_list.append({"type": "text", "text": txt_analysis})
203
 
204
- # ๋™์˜์ƒ ์ฒ˜๋ฆฌ
 
 
 
 
 
205
  if video_files:
206
  content_list += process_video(video_files[0])
207
  return content_list
208
 
209
- # interleaved ์ด๋ฏธ์ง€
210
  if "<image>" in message["text"]:
 
211
  return process_interleaved_images(message)
212
-
213
- # ์ผ๋ฐ˜ ์ด๋ฏธ์ง€๋“ค
214
- if image_files:
215
  for img_path in image_files:
216
  content_list.append({"type": "image", "url": img_path})
217
 
218
  return content_list
219
 
220
 
 
 
 
221
  def process_history(history: list[dict]) -> list[dict]:
222
  messages = []
223
  current_user_content: list[dict] = []
224
  for item in history:
225
  if item["role"] == "assistant":
 
226
  if current_user_content:
227
  messages.append({"role": "user", "content": current_user_content})
228
  current_user_content = []
 
229
  messages.append({"role": "assistant", "content": [{"type": "text", "text": item["content"]}]})
230
  else:
 
231
  content = item["content"]
232
  if isinstance(content, str):
233
  current_user_content.append({"type": "text", "text": content})
234
  else:
 
235
  current_user_content.append({"type": "image", "url": content[0]})
236
  return messages
237
 
238
 
 
 
 
239
  @spaces.GPU(duration=120)
240
  def run(message: dict, history: list[dict], system_prompt: str = "", max_new_tokens: int = 512) -> Iterator[str]:
241
  if not validate_media_constraints(message, history):
@@ -257,140 +311,37 @@ def run(message: dict, history: list[dict], system_prompt: str = "", max_new_tok
257
  ).to(device=model.device, dtype=torch.bfloat16)
258
 
259
  streamer = TextIteratorStreamer(processor, timeout=30.0, skip_prompt=True, skip_special_tokens=True)
260
- generate_kwargs = dict(
261
  inputs,
262
  streamer=streamer,
263
  max_new_tokens=max_new_tokens,
264
  )
265
- t = Thread(target=model.generate, kwargs=generate_kwargs)
266
  t.start()
267
 
268
  output = ""
269
- for delta in streamer:
270
- output += delta
271
  yield output
272
 
273
 
 
 
 
274
  examples = [
275
  [
276
  {
277
- "text": "I need to be in Japan for 10 days, going to Tokyo, Kyoto and Osaka. Think about number of attractions in each of them and allocate number of days to each city. Make public transport recommendations.",
278
- "files": [],
279
- }
280
- ],
281
- [
282
- {
283
- "text": "Write the matplotlib code to generate the same bar chart.",
284
- "files": ["assets/additional-examples/barchart.png"],
285
- }
286
- ],
287
- [
288
- {
289
- "text": "What is odd about this video?",
290
- "files": ["assets/additional-examples/tmp.mp4"],
291
- }
292
- ],
293
- [
294
- {
295
- "text": "I already have this supplement <image> and I want to buy this one <image>. Any warnings I should know about?",
296
- "files": ["assets/additional-examples/pill1.png", "assets/additional-examples/pill2.png"],
297
- }
298
- ],
299
- [
300
- {
301
- "text": "Write a poem inspired by the visual elements of the images.",
302
- "files": ["assets/sample-images/06-1.png", "assets/sample-images/06-2.png"],
303
- }
304
- ],
305
- [
306
- {
307
- "text": "Compose a short musical piece inspired by the visual elements of the images.",
308
- "files": [
309
- "assets/sample-images/07-1.png",
310
- "assets/sample-images/07-2.png",
311
- "assets/sample-images/07-3.png",
312
- "assets/sample-images/07-4.png",
313
- ],
314
- }
315
- ],
316
- [
317
- {
318
- "text": "Write a short story about what might have happened in this house.",
319
- "files": ["assets/sample-images/08.png"],
320
- }
321
- ],
322
- [
323
- {
324
- "text": "Create a short story based on the sequence of images.",
325
- "files": [
326
- "assets/sample-images/09-1.png",
327
- "assets/sample-images/09-2.png",
328
- "assets/sample-images/09-3.png",
329
- "assets/sample-images/09-4.png",
330
- "assets/sample-images/09-5.png",
331
- ],
332
- }
333
- ],
334
- [
335
- {
336
- "text": "Describe the creatures that would live in this world.",
337
- "files": ["assets/sample-images/10.png"],
338
- }
339
- ],
340
- [
341
- {
342
- "text": "Read text in the image.",
343
- "files": ["assets/additional-examples/1.png"],
344
- }
345
- ],
346
- [
347
- {
348
- "text": "When is this ticket dated and how much did it cost?",
349
- "files": ["assets/additional-examples/2.png"],
350
- }
351
- ],
352
- [
353
- {
354
- "text": "Read the text in the image into markdown.",
355
- "files": ["assets/additional-examples/3.png"],
356
- }
357
- ],
358
- [
359
- {
360
- "text": "Evaluate this integral.",
361
- "files": ["assets/additional-examples/4.png"],
362
- }
363
- ],
364
- [
365
- {
366
- "text": "caption this image",
367
- "files": ["assets/sample-images/01.png"],
368
- }
369
- ],
370
- [
371
- {
372
- "text": "What's the sign says?",
373
- "files": ["assets/sample-images/02.png"],
374
- }
375
- ],
376
- [
377
- {
378
- "text": "Compare and contrast the two images.",
379
- "files": ["assets/sample-images/03.png"],
380
- }
381
- ],
382
- [
383
- {
384
- "text": "List all the objects in the image and their colors.",
385
- "files": ["assets/sample-images/04.png"],
386
  }
387
  ],
388
  [
389
  {
390
- "text": "Describe the atmosphere of the scene.",
391
- "files": ["assets/sample-images/05.png"],
392
  }
393
  ],
 
394
  ]
395
 
396
 
@@ -411,7 +362,10 @@ demo = gr.ChatInterface(
411
  additional_inputs=[
412
  gr.Textbox(
413
  label="System Prompt",
414
- value="You are a deeply thoughtful AI. Consider problems thoroughly and derive correct solutions through systematic reasoning. Please answer in korean."
 
 
 
415
  ),
416
  gr.Slider(label="Max New Tokens", minimum=100, maximum=8000, step=50, value=2000),
417
  ],
 
17
  # CSV/TXT ๋ถ„์„
18
  import pandas as pd
19
 
20
+ # PDF ํ…์ŠคํŠธ ์ถ”์ถœ
21
+ import PyPDF2
22
+
23
+ MAX_CONTENT_CHARS = 8000 # ๋„ˆ๋ฌด ํฐ ํŒŒ์ผ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์ตœ๋Œ€ ํ‘œ์‹œ 8000์ž
24
 
25
  model_id = os.getenv("MODEL_ID", "google/gemma-3-27b-it")
26
  processor = AutoProcessor.from_pretrained(model_id, padding_side="left")
 
34
  MAX_NUM_IMAGES = int(os.getenv("MAX_NUM_IMAGES", "5"))
35
 
36
 
37
+ ##################################################
38
+ # CSV, TXT, PDF ๋ถ„์„ ํ•จ์ˆ˜
39
+ ##################################################
40
  def analyze_csv_file(path: str) -> str:
41
  """
42
+ CSV ํŒŒ์ผ์„ ์ „์ฒด ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜. ๋„ˆ๋ฌด ๊ธธ ๊ฒฝ์šฐ ์ผ๋ถ€๋งŒ ํ‘œ์‹œ.
43
  """
44
  try:
45
  df = pd.read_csv(path)
46
  df_str = df.to_string()
47
  if len(df_str) > MAX_CONTENT_CHARS:
48
  df_str = df_str[:MAX_CONTENT_CHARS] + "\n...(truncated)..."
 
49
  return f"**[CSV File: {os.path.basename(path)}]**\n\n{df_str}"
50
  except Exception as e:
51
  return f"Failed to read CSV ({os.path.basename(path)}): {str(e)}"
 
53
 
54
  def analyze_txt_file(path: str) -> str:
55
  """
56
+ TXT ํŒŒ์ผ ์ „๋ฌธ ์ฝ๊ธฐ. ๋„ˆ๋ฌด ๊ธธ๋ฉด ์ผ๋ถ€๋งŒ ํ‘œ์‹œ.
57
  """
58
  try:
59
  with open(path, "r", encoding="utf-8") as f:
60
  text = f.read()
61
  if len(text) > MAX_CONTENT_CHARS:
62
  text = text[:MAX_CONTENT_CHARS] + "\n...(truncated)..."
 
63
  return f"**[TXT File: {os.path.basename(path)}]**\n\n{text}"
64
  except Exception as e:
65
  return f"Failed to read TXT ({os.path.basename(path)}): {str(e)}"
66
 
67
 
68
+ def pdf_to_markdown(pdf_path: str) -> str:
69
+ """
70
+ PDF โ†’ Markdown. ํŽ˜์ด์ง€๋ณ„๋กœ ๊ฐ„๋‹จํžˆ ํ…์ŠคํŠธ ์ถ”์ถœ.
71
+ """
72
+ text_chunks = []
73
+ try:
74
+ with open(pdf_path, "rb") as f:
75
+ reader = PyPDF2.PdfReader(f)
76
+ for page_num, page in enumerate(reader.pages, start=1):
77
+ page_text = page.extract_text() or ""
78
+ page_text = page_text.strip()
79
+ if page_text:
80
+ text_chunks.append(f"## Page {page_num}\n\n{page_text}\n")
81
+ except Exception as e:
82
+ return f"Failed to read PDF ({os.path.basename(pdf_path)}): {str(e)}"
83
+
84
+ full_text = "\n".join(text_chunks)
85
+ if len(full_text) > MAX_CONTENT_CHARS:
86
+ full_text = full_text[:MAX_CONTENT_CHARS] + "\n...(truncated)..."
87
+
88
+ return f"**[PDF File: {os.path.basename(pdf_path)}]**\n\n{full_text}"
89
+
90
+
91
+ ##################################################
92
+ # ์ด๋ฏธ์ง€/๋น„๋””์˜ค ์—…๋กœ๋“œ ์ œํ•œ ๊ฒ€์‚ฌ
93
+ ##################################################
94
  def count_files_in_new_message(paths: list[str]) -> tuple[int, int]:
95
  image_count = 0
96
  video_count = 0
 
118
  def validate_media_constraints(message: dict, history: list[dict]) -> bool:
119
  """
120
  - ๋น„๋””์˜ค 1๊ฐœ ์ดˆ๊ณผ ๋ถˆ๊ฐ€
121
+ - ๋น„๋””์˜ค์™€ ์ด๋ฏธ์ง€ ํ˜ผํ•ฉ ๋ถˆ๊ฐ€
122
  - ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ MAX_NUM_IMAGES ์ดˆ๊ณผ ๋ถˆ๊ฐ€
123
+ - <image> ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ํƒœ๊ทธ ์ˆ˜์™€ ์‹ค์ œ ์ด๋ฏธ์ง€ ์ˆ˜ ์ผ์น˜
124
+ - CSV, TXT, PDF ๋“ฑ์€ ์—ฌ๊ธฐ์„œ ์ œํ•œํ•˜์ง€ ์•Š์Œ
125
  """
126
  media_files = []
127
  for f in message["files"]:
128
+ # ์ด๋ฏธ์ง€: png/jpg/jpeg/gif/webp
129
+ # ๋น„๋””์˜ค: mp4
130
+ # cf) PDF, CSV, TXT ๋“ฑ์€ ์ œ์™ธ
131
  if re.search(r"\.(png|jpg|jpeg|gif|webp)$", f, re.IGNORECASE) or f.endswith(".mp4"):
132
  media_files.append(f)
133
 
 
156
  return True
157
 
158
 
159
+ ##################################################
160
+ # ๋น„๋””์˜ค ์ฒ˜๋ฆฌ
161
+ ##################################################
162
  def downsample_video(video_path: str) -> list[tuple[Image.Image, float]]:
163
  vidcap = cv2.VideoCapture(video_path)
164
  fps = vidcap.get(cv2.CAP_PROP_FPS)
 
193
  return content
194
 
195
 
196
+ ##################################################
197
+ # interleaved <image> ์ฒ˜๋ฆฌ
198
+ ##################################################
199
  def process_interleaved_images(message: dict) -> list[dict]:
 
200
  parts = re.split(r"(<image>)", message["text"])
 
 
201
  content = []
202
  image_index = 0
203
  for part in parts:
204
  if part == "<image>":
205
  content.append({"type": "image", "url": message["files"][image_index]})
 
206
  image_index += 1
207
  elif part.strip():
208
  content.append({"type": "text", "text": part.strip()})
209
+ else:
210
+ # ๊ณต๋ฐฑ์ด๊ฑฐ๋‚˜ \n ๊ฐ™์€ ๊ฒฝ์šฐ
211
+ if isinstance(part, str) and part != "<image>":
212
+ content.append({"type": "text", "text": part})
213
  return content
214
 
215
 
216
+ ##################################################
217
+ # PDF + CSV + TXT + ์ด๋ฏธ์ง€/๋น„๋””์˜ค
218
+ ##################################################
219
  def process_new_user_message(message: dict) -> list[dict]:
220
  if not message["files"]:
221
  return [{"type": "text", "text": message["text"]}]
222
 
223
+ # 1) ํŒŒ์ผ ๋ถ„๋ฅ˜
224
  video_files = [f for f in message["files"] if f.endswith(".mp4")]
225
  image_files = [f for f in message["files"] if re.search(r"\.(png|jpg|jpeg|gif|webp)$", f, re.IGNORECASE)]
226
  csv_files = [f for f in message["files"] if f.lower().endswith(".csv")]
227
  txt_files = [f for f in message["files"] if f.lower().endswith(".txt")]
228
+ pdf_files = [f for f in message["files"] if f.lower().endswith(".pdf")]
229
 
230
+ # 2) ์‚ฌ์šฉ์ž ์›๋ณธ text ์ถ”๊ฐ€
231
  content_list = [{"type": "text", "text": message["text"]}]
232
 
233
+ # 3) CSV
234
  for csv_path in csv_files:
235
  csv_analysis = analyze_csv_file(csv_path)
236
  content_list.append({"type": "text", "text": csv_analysis})
237
 
238
+ # 4) TXT
239
  for txt_path in txt_files:
240
  txt_analysis = analyze_txt_file(txt_path)
241
  content_list.append({"type": "text", "text": txt_analysis})
242
 
243
+ # 5) PDF
244
+ for pdf_path in pdf_files:
245
+ pdf_markdown = pdf_to_markdown(pdf_path)
246
+ content_list.append({"type": "text", "text": pdf_markdown})
247
+
248
+ # 6) ๋น„๋””์˜ค (ํ•œ ๊ฐœ๋งŒ ํ—ˆ์šฉ)
249
  if video_files:
250
  content_list += process_video(video_files[0])
251
  return content_list
252
 
253
+ # 7) ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ
254
  if "<image>" in message["text"]:
255
+ # interleaved
256
  return process_interleaved_images(message)
257
+ else:
258
+ # ์ผ๋ฐ˜ ์—ฌ๋Ÿฌ ์žฅ
 
259
  for img_path in image_files:
260
  content_list.append({"type": "image", "url": img_path})
261
 
262
  return content_list
263
 
264
 
265
+ ##################################################
266
+ # history -> LLM ๋ฉ”์‹œ์ง€ ๋ณ€ํ™˜
267
+ ##################################################
268
  def process_history(history: list[dict]) -> list[dict]:
269
  messages = []
270
  current_user_content: list[dict] = []
271
  for item in history:
272
  if item["role"] == "assistant":
273
+ # user_content๊ฐ€ ์Œ“์—ฌ์žˆ๋‹ค๋ฉด user ๋ฉ”์‹œ์ง€๋กœ ์ €์žฅ
274
  if current_user_content:
275
  messages.append({"role": "user", "content": current_user_content})
276
  current_user_content = []
277
+ # ๊ทธ ๋’ค item์€ assistant
278
  messages.append({"role": "assistant", "content": [{"type": "text", "text": item["content"]}]})
279
  else:
280
+ # user
281
  content = item["content"]
282
  if isinstance(content, str):
283
  current_user_content.append({"type": "text", "text": content})
284
  else:
285
+ # ์ด๋ฏธ์ง€๋‚˜ ๊ธฐํƒ€
286
  current_user_content.append({"type": "image", "url": content[0]})
287
  return messages
288
 
289
 
290
+ ##################################################
291
+ # ๋ฉ”์ธ ์ถ”๋ก  ํ•จ์ˆ˜
292
+ ##################################################
293
  @spaces.GPU(duration=120)
294
  def run(message: dict, history: list[dict], system_prompt: str = "", max_new_tokens: int = 512) -> Iterator[str]:
295
  if not validate_media_constraints(message, history):
 
311
  ).to(device=model.device, dtype=torch.bfloat16)
312
 
313
  streamer = TextIteratorStreamer(processor, timeout=30.0, skip_prompt=True, skip_special_tokens=True)
314
+ gen_kwargs = dict(
315
  inputs,
316
  streamer=streamer,
317
  max_new_tokens=max_new_tokens,
318
  )
319
+ t = Thread(target=model.generate, kwargs=gen_kwargs)
320
  t.start()
321
 
322
  output = ""
323
+ for new_text in streamer:
324
+ output += new_text
325
  yield output
326
 
327
 
328
+ ##################################################
329
+ # ์˜ˆ์‹œ๋“ค (๊ธฐ์กด)
330
+ ##################################################
331
  examples = [
332
  [
333
  {
334
+ "text": "Test with PDF",
335
+ "files": ["assets/sample.pdf"],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  }
337
  ],
338
  [
339
  {
340
+ "text": "Simple text with CSV upload.",
341
+ "files": ["assets/sample.csv"],
342
  }
343
  ],
344
+ # ...์›๋ž˜ ์˜ˆ์‹œ๋“ค ์œ ์ง€...
345
  ]
346
 
347
 
 
362
  additional_inputs=[
363
  gr.Textbox(
364
  label="System Prompt",
365
+ value=(
366
+ "You are a deeply thoughtful AI. Consider problems thoroughly and derive "
367
+ "correct solutions through systematic reasoning. Please answer in korean."
368
+ )
369
  ),
370
  gr.Slider(label="Max New Tokens", minimum=100, maximum=8000, step=50, value=2000),
371
  ],