openfree commited on
Commit
a03145d
·
verified ·
1 Parent(s): ea4e802

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -36
app.py CHANGED
@@ -28,7 +28,7 @@ except Exception as e:
28
  ###############################
29
  json_path = "/home/user/magic-pdf.json"
30
  if os.path.exists(json_path):
31
- # 기존에 파일이 있으면 로드
32
  with open(json_path, 'r', encoding='utf-8') as file:
33
  data = json.load(file)
34
  else:
@@ -42,17 +42,15 @@ else:
42
  }
43
  }
44
  }
45
- # 파일 생성 (필요 없으면 생략)
46
  with open(json_path, 'w', encoding='utf-8') as file:
47
  json.dump(data, file, indent=4)
48
 
49
- # 이후 device-mode나 llm-aided-config 필요한 경우 수정
50
- data['device-mode'] = "cuda" # 원하는 디바이스로 세팅
51
  if os.getenv('apikey'):
52
  data['llm-aided-config']['title_aided']['api_key'] = os.getenv('apikey')
53
  data['llm-aided-config']['title_aided']['enable'] = True
54
 
55
- # 변경사항 다시 저장
56
  with open(json_path, 'w', encoding='utf-8') as file:
57
  json.dump(data, file, indent=4)
58
 
@@ -60,14 +58,14 @@ with open(json_path, 'w', encoding='utf-8') as file:
60
  os.system('cp -r paddleocr /home/user/.paddleocr')
61
 
62
  ###############################
63
- # 라이브러리
64
  ###############################
65
  import gradio as gr
66
  from loguru import logger
67
  from gradio_pdf import PDF
68
 
69
  ###############################
70
- # magic_pdf 관련 모듈
71
  ###############################
72
  from magic_pdf.data.data_reader_writer import FileBasedDataReader
73
  from magic_pdf.libs.hash_utils import compute_sha256
@@ -174,8 +172,8 @@ def replace_image_with_base64(markdown_text, image_dir_path):
174
 
175
  def to_pdf(file_path):
176
  """
177
- 이미지(JPG/PNG 등)를 PDF로 컨버팅.
178
- TXT, CSV 파일인 경우 변환 없이 원본 경로를 그대로 반환.
179
  """
180
  ext = Path(file_path).suffix.lower()
181
  if ext in ['.txt', '.csv']:
@@ -193,8 +191,7 @@ def to_pdf(file_path):
193
 
194
  def to_markdown(file_path, end_pages, is_ocr, layout_mode, formula_enable, table_enable, language, progress=gr.Progress(track_tqdm=False)):
195
  """
196
- 업로드된 PDF/이미지 또는 TXT/CSV -> 마크다운 변환
197
- (프로그레스 바 표시용)
198
  """
199
  ext = Path(file_path).suffix.lower()
200
  if ext in ['.txt', '.csv']:
@@ -238,9 +235,7 @@ def to_markdown(file_path, end_pages, is_ocr, layout_mode, formula_enable, table
238
 
239
  def to_markdown_comparison(file_a, file_b, end_pages, is_ocr, layout_mode, formula_enable, table_enable, language, progress=gr.Progress(track_tqdm=False)):
240
  """
241
- 개의 파일을 변환하여 A/B 비교용 마크다운 생성.
242
- 각 파일은 "문서 A", "문서 B" 헤더로 구분되며,
243
- 두 파일 모두 업로드된 경우 추가로 비교 분석 지시사항을 포함한다.
244
  """
245
  combined_md = ""
246
  if file_a is not None:
@@ -307,6 +302,7 @@ def format_chat_history(messages: list) -> list:
307
  """
308
  formatted_history = []
309
  for message in messages:
 
310
  if not (message.role == "assistant" and hasattr(message, "metadata")):
311
  formatted_history.append({
312
  "role": "user" if message.role == "user" else "assistant",
@@ -326,7 +322,7 @@ def convert_chat_messages_to_gradio_format(messages):
326
  gradio_chat.append((user_text or "", assistant_text or ""))
327
  user_text = msg.content
328
  assistant_text = None
329
- else:
330
  if user_text is None:
331
  user_text = ""
332
  if assistant_text is None:
@@ -337,20 +333,22 @@ def convert_chat_messages_to_gradio_format(messages):
337
  gradio_chat.append((user_text or "", assistant_text or ""))
338
  return gradio_chat
339
 
340
- def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
341
  """
342
- Gemini 응답을 스트리밍 형태로 출력 (user_message 공백 시 임시 문구 사용)
343
  """
344
- if not user_message.strip():
345
- user_message = "...(No content from user)..."
346
  try:
347
- print(f"\n=== [Gemini] New Request ===\nUser message: '{user_message}'")
348
  chat_history = format_chat_history(messages)
349
  chat = model.start_chat(history=chat_history)
350
- response = chat.send_message(user_message, stream=True)
 
351
  thought_buffer = ""
352
  response_buffer = ""
353
  thinking_complete = False
 
354
  # "Thinking" 역할 추가
355
  messages.append(
356
  ChatMessage(
@@ -360,10 +358,13 @@ def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
360
  )
361
  )
362
  yield convert_chat_messages_to_gradio_format(messages)
 
363
  for chunk in response:
364
  parts = chunk.candidates[0].content.parts
365
  current_chunk = parts[0].text
 
366
  if len(parts) == 2 and not thinking_complete:
 
367
  thought_buffer += current_chunk
368
  messages[-1] = ChatMessage(
369
  role="assistant",
@@ -371,13 +372,17 @@ def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
371
  metadata={"title": "⚙️ Thinking: *The thoughts produced by the model are experimental"}
372
  )
373
  yield convert_chat_messages_to_gradio_format(messages)
 
 
374
  response_buffer = parts[1].text
375
  messages.append(ChatMessage(role="assistant", content=response_buffer))
376
  thinking_complete = True
377
  elif thinking_complete:
 
378
  response_buffer += current_chunk
379
  messages[-1] = ChatMessage(role="assistant", content=response_buffer)
380
  else:
 
381
  thought_buffer += current_chunk
382
  messages[-1] = ChatMessage(
383
  role="assistant",
@@ -385,26 +390,42 @@ def stream_gemini_response(user_message: str, messages: list) -> Iterator[list]:
385
  metadata={"title": "⚙️ Thinking: *The thoughts produced by the model are experimental"}
386
  )
387
  yield convert_chat_messages_to_gradio_format(messages)
 
388
  print(f"\n=== [Gemini] Final Response ===\n{response_buffer}")
 
389
  except Exception as e:
390
  print(f"\n=== [Gemini] Error ===\n{str(e)}")
391
  messages.append(ChatMessage(role="assistant", content=f"오류가 발생했습니다: {str(e)}"))
392
  yield convert_chat_messages_to_gradio_format(messages)
393
 
394
- def user_message(msg: str, history: list, doc_text: str) -> tuple[str, list]:
395
  """
396
- 문서 변환 결과(문자열)와 함께 질의를 결합하여 history에 추가
 
 
 
 
 
 
 
397
  """
398
  if doc_text.strip():
399
  user_query = f"다음 문서를 참고하여 답변:\n\n{doc_text}\n\n질문: {msg}"
400
  else:
401
  user_query = msg
 
402
  history.append(ChatMessage(role="user", content=user_query))
403
- return "", history
404
 
405
  def reset_states(file_a, file_b):
406
  """
407
- 새 파일 업로드 시 chat_history, md_state, chatbot을 초기화
 
 
 
 
 
 
408
  """
409
  return [], "", ""
410
 
@@ -421,13 +442,12 @@ if __name__ == "__main__":
421
  한 파일만 업로드하면 해당 파일로 분석합니다.</p>
422
  </div>
423
  """)
424
-
425
- # 변환 결과를 보여줄 visible Markdown 컴포넌트
426
  conversion_md = gr.Markdown(label="변환 결과", visible=True)
427
- md_state = gr.State("") # 내부 상태 (문서 변환 결과 저장)
428
  chat_history = gr.State([]) # ChatMessage 리스트
 
429
 
430
- # visible Chatbot 컴포넌트
431
  chatbot = gr.Chatbot(visible=True)
432
 
433
  with gr.Row():
@@ -474,24 +494,25 @@ if __name__ == "__main__":
474
  chat_input = gr.Textbox(lines=1, placeholder="질문을 입력하세요...")
475
  clear_btn = gr.Button("대화 초기화")
476
 
 
 
 
477
  chat_input.submit(
478
  fn=user_message,
479
  inputs=[chat_input, chat_history, conversion_md],
480
- outputs=[chat_input, chat_history]
481
  ).then(
482
  fn=stream_gemini_response,
483
- inputs=[chat_input, chat_history],
484
  outputs=chatbot
485
  )
486
 
487
- def clear_all():
488
- return [], "", ""
489
-
490
  clear_btn.click(
491
  fn=clear_all,
492
  inputs=[],
493
  outputs=[chat_history, md_state, chatbot]
494
  )
495
 
496
- # 로컬 서버 실행
497
- demo.launch(server_name="0.0.0.0", server_port=7860, debug=True, ssr_mode=True)
 
 
28
  ###############################
29
  json_path = "/home/user/magic-pdf.json"
30
  if os.path.exists(json_path):
31
+ # 기존 파일 로드
32
  with open(json_path, 'r', encoding='utf-8') as file:
33
  data = json.load(file)
34
  else:
 
42
  }
43
  }
44
  }
 
45
  with open(json_path, 'w', encoding='utf-8') as file:
46
  json.dump(data, file, indent=4)
47
 
48
+ # 필요 업데이트
49
+ data['device-mode'] = "cuda" # "cpu" 등으로 수정 가능
50
  if os.getenv('apikey'):
51
  data['llm-aided-config']['title_aided']['api_key'] = os.getenv('apikey')
52
  data['llm-aided-config']['title_aided']['enable'] = True
53
 
 
54
  with open(json_path, 'w', encoding='utf-8') as file:
55
  json.dump(data, file, indent=4)
56
 
 
58
  os.system('cp -r paddleocr /home/user/.paddleocr')
59
 
60
  ###############################
61
+ # 기타 라이브러리
62
  ###############################
63
  import gradio as gr
64
  from loguru import logger
65
  from gradio_pdf import PDF
66
 
67
  ###############################
68
+ # magic_pdf 관련
69
  ###############################
70
  from magic_pdf.data.data_reader_writer import FileBasedDataReader
71
  from magic_pdf.libs.hash_utils import compute_sha256
 
172
 
173
  def to_pdf(file_path):
174
  """
175
+ 이미지(JPG/PNG 등)를 PDF로 변환.
176
+ TXT, CSV 파일이면 그대로 경로 반환.
177
  """
178
  ext = Path(file_path).suffix.lower()
179
  if ext in ['.txt', '.csv']:
 
191
 
192
  def to_markdown(file_path, end_pages, is_ocr, layout_mode, formula_enable, table_enable, language, progress=gr.Progress(track_tqdm=False)):
193
  """
194
+ 업로드된 PDF/이미지/TXT/CSV -> 마크다운 변환
 
195
  """
196
  ext = Path(file_path).suffix.lower()
197
  if ext in ['.txt', '.csv']:
 
235
 
236
  def to_markdown_comparison(file_a, file_b, end_pages, is_ocr, layout_mode, formula_enable, table_enable, language, progress=gr.Progress(track_tqdm=False)):
237
  """
238
+ 두 파일을 변환 -> A/B 비교용 마크다운
 
 
239
  """
240
  combined_md = ""
241
  if file_a is not None:
 
302
  """
303
  formatted_history = []
304
  for message in messages:
305
+ # Thinking 역할(assistant+metadata)은 제외
306
  if not (message.role == "assistant" and hasattr(message, "metadata")):
307
  formatted_history.append({
308
  "role": "user" if message.role == "user" else "assistant",
 
322
  gradio_chat.append((user_text or "", assistant_text or ""))
323
  user_text = msg.content
324
  assistant_text = None
325
+ else: # assistant
326
  if user_text is None:
327
  user_text = ""
328
  if assistant_text is None:
 
333
  gradio_chat.append((user_text or "", assistant_text or ""))
334
  return gradio_chat
335
 
336
+ def stream_gemini_response(user_query: str, messages: list) -> Iterator[list]:
337
  """
338
+ Gemini 응답 스트리밍
339
  """
340
+ if not user_query.strip():
341
+ user_query = "...(No content from user)..."
342
  try:
343
+ print(f"\n=== [Gemini] New Request ===\nUser message: '{user_query}'")
344
  chat_history = format_chat_history(messages)
345
  chat = model.start_chat(history=chat_history)
346
+ response = chat.send_message(user_query, stream=True)
347
+
348
  thought_buffer = ""
349
  response_buffer = ""
350
  thinking_complete = False
351
+
352
  # "Thinking" 역할 추가
353
  messages.append(
354
  ChatMessage(
 
358
  )
359
  )
360
  yield convert_chat_messages_to_gradio_format(messages)
361
+
362
  for chunk in response:
363
  parts = chunk.candidates[0].content.parts
364
  current_chunk = parts[0].text
365
+
366
  if len(parts) == 2 and not thinking_complete:
367
+ # 첫 번째 파트 = 'Thinking'
368
  thought_buffer += current_chunk
369
  messages[-1] = ChatMessage(
370
  role="assistant",
 
372
  metadata={"title": "⚙️ Thinking: *The thoughts produced by the model are experimental"}
373
  )
374
  yield convert_chat_messages_to_gradio_format(messages)
375
+
376
+ # 두 번째 파트 = 최종 답변
377
  response_buffer = parts[1].text
378
  messages.append(ChatMessage(role="assistant", content=response_buffer))
379
  thinking_complete = True
380
  elif thinking_complete:
381
+ # 이미 최종 답변 들어간 상태
382
  response_buffer += current_chunk
383
  messages[-1] = ChatMessage(role="assistant", content=response_buffer)
384
  else:
385
+ # 아직 'Thinking' 중
386
  thought_buffer += current_chunk
387
  messages[-1] = ChatMessage(
388
  role="assistant",
 
390
  metadata={"title": "⚙️ Thinking: *The thoughts produced by the model are experimental"}
391
  )
392
  yield convert_chat_messages_to_gradio_format(messages)
393
+
394
  print(f"\n=== [Gemini] Final Response ===\n{response_buffer}")
395
+
396
  except Exception as e:
397
  print(f"\n=== [Gemini] Error ===\n{str(e)}")
398
  messages.append(ChatMessage(role="assistant", content=f"오류가 발생했습니다: {str(e)}"))
399
  yield convert_chat_messages_to_gradio_format(messages)
400
 
401
+ def user_message(msg: str, history: list, doc_text: str) -> tuple[str, list, str]:
402
  """
403
+ - msg: 유저가 입력창에 입력한 텍스트
404
+ - doc_text: 변환된 문서 (conversion_md)
405
+ - history: ChatMessage 리스트
406
+
407
+ return:
408
+ (1) UI 입력창을 비울 값 (""),
409
+ (2) 업데이트된 history,
410
+ (3) 실제 LLM에 전달할 user_query
411
  """
412
  if doc_text.strip():
413
  user_query = f"다음 문서를 참고하여 답변:\n\n{doc_text}\n\n질문: {msg}"
414
  else:
415
  user_query = msg
416
+
417
  history.append(ChatMessage(role="user", content=user_query))
418
+ return "", history, user_query
419
 
420
  def reset_states(file_a, file_b):
421
  """
422
+ 새 파일 업로드 시 대화초기화
423
+ """
424
+ return [], "", ""
425
+
426
+ def clear_all():
427
+ """
428
+ 대화 전체 초기화
429
  """
430
  return [], "", ""
431
 
 
442
  한 파일만 업로드하면 해당 파일로 분석합니다.</p>
443
  </div>
444
  """)
445
+
 
446
  conversion_md = gr.Markdown(label="변환 결과", visible=True)
447
+ md_state = gr.State("") # 문서 변환 결과
448
  chat_history = gr.State([]) # ChatMessage 리스트
449
+ user_query_holder = gr.State("") # (수정) user_query 임시 저장
450
 
 
451
  chatbot = gr.Chatbot(visible=True)
452
 
453
  with gr.Row():
 
494
  chat_input = gr.Textbox(lines=1, placeholder="질문을 입력하세요...")
495
  clear_btn = gr.Button("대화 초기화")
496
 
497
+ # (수정) user_message -> (chat_input, chat_history, conversion_md)
498
+ # => outputs=[chat_input, chat_history, user_query_holder]
499
+ # 이 중 user_query_holder(실제 질의)는 stream_gemini_response로 전달
500
  chat_input.submit(
501
  fn=user_message,
502
  inputs=[chat_input, chat_history, conversion_md],
503
+ outputs=[chat_input, chat_history, user_query_holder]
504
  ).then(
505
  fn=stream_gemini_response,
506
+ inputs=[user_query_holder, chat_history],
507
  outputs=chatbot
508
  )
509
 
 
 
 
510
  clear_btn.click(
511
  fn=clear_all,
512
  inputs=[],
513
  outputs=[chat_history, md_state, chatbot]
514
  )
515
 
516
+ # demo.launch(server_name="0.0.0.0", server_port=7860, debug=True, ssr_mode=True)
517
+ # 공유 링크를 원할 경우 share=True 설정
518
+ demo.launch(server_name="0.0.0.0", server_port=7860, debug=True, ssr_mode=True, share=False)