seawolf2357 commited on
Commit
417b22d
ยท
verified ยท
1 Parent(s): 6237077

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +224 -39
app.py CHANGED
@@ -6,6 +6,7 @@ import tempfile
6
  from collections.abc import Iterator
7
  from threading import Thread
8
 
 
9
  import cv2
10
  import gradio as gr
11
  import spaces
@@ -20,6 +21,54 @@ import pandas as pd
20
  # PDF ํ…์ŠคํŠธ ์ถ”์ถœ
21
  import PyPDF2
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  MAX_CONTENT_CHARS = 4000 # ๋„ˆ๋ฌด ํฐ ํŒŒ์ผ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์ตœ๋Œ€ ํ‘œ์‹œ 4000์ž
24
 
25
  model_id = os.getenv("MODEL_ID", "google/gemma-3-27b-it")
@@ -350,12 +399,31 @@ def process_history(history: list[dict]) -> list[dict]:
350
  # ๋ฉ”์ธ ์ถ”๋ก  ํ•จ์ˆ˜
351
  ##################################################
352
  @spaces.GPU(duration=120)
353
- def run(message: dict, history: list[dict], system_prompt: str = "", max_new_tokens: int = 512) -> Iterator[str]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  if not validate_media_constraints(message, history):
355
  yield ""
356
  return
357
 
358
  try:
 
 
 
 
 
359
  messages = []
360
  if system_prompt:
361
  messages.append({"role": "system", "content": [{"type": "text", "text": system_prompt}]})
@@ -372,7 +440,6 @@ def run(message: dict, history: list[dict], system_prompt: str = "", max_new_tok
372
  messages.append({"role": "user", "content": user_content})
373
 
374
  # ๋ชจ๋ธ ์ž…๋ ฅ ์ƒ์„ฑ ์ „ ์ตœ์ข… ํ™•์ธ
375
- # ์ด๋ฏธ์ง€๋‚˜ ๋น„๋””์˜ค๊ฐ€ ์•„๋‹Œ ํŒŒ์ผ๋“ค์€ ๋ชจ๋ธ์˜ "image" ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š๋„๋ก ํ•„ํ„ฐ๋ง
376
  for msg in messages:
377
  if msg["role"] != "user":
378
  continue
@@ -426,8 +493,6 @@ def run(message: dict, history: list[dict], system_prompt: str = "", max_new_tok
426
 
427
 
428
 
429
-
430
-
431
  ##################################################
432
  # ์˜ˆ์‹œ๋“ค (ํ•œ๊ธ€ํ™” ๋ฒ„์ „)
433
  ##################################################
@@ -536,41 +601,161 @@ examples = [
536
  ]
537
 
538
 
539
- ##################################################
540
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์„ค์ •
541
- ##################################################
542
- demo = gr.ChatInterface(
543
- fn=run,
544
- type="messages",
545
- chatbot=gr.Chatbot(type="messages", scale=1, allow_tags=["image"]),
546
- # .webp, .png, .jpg, .jpeg, .gif, .mp4, .csv, .txt, .pdf ๋ชจ๋‘ ํ—ˆ์šฉ
547
- textbox=gr.MultimodalTextbox(
548
- file_types=[
549
- ".webp", ".png", ".jpg", ".jpeg", ".gif",
550
- ".mp4", ".csv", ".txt", ".pdf"
551
- ],
552
- file_count="multiple",
553
- autofocus=True
554
- ),
555
- multimodal=True,
556
- additional_inputs=[
557
- gr.Textbox(
558
- label="System Prompt",
559
- value=(
560
- "You are a deeply thoughtful AI. Consider problems thoroughly and derive "
561
- "correct solutions through systematic reasoning. Please answer in korean."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
562
  )
563
- ),
564
- gr.Slider(label="Max New Tokens", minimum=100, maximum=8000, step=50, value=2000),
565
- ],
566
- stop_btn=False,
567
- title="Vidraft-Gemma-3-27B",
568
- examples=examples,
569
- run_examples_on_click=False,
570
- cache_examples=False,
571
- css_paths="style.css",
572
- delete_cache=(1800, 1800),
573
- )
574
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
  if __name__ == "__main__":
576
- demo.launch()
 
 
6
  from collections.abc import Iterator
7
  from threading import Thread
8
 
9
+ import requests # <-- For SERPHouse web search
10
  import cv2
11
  import gradio as gr
12
  import spaces
 
21
  # PDF ํ…์ŠคํŠธ ์ถ”์ถœ
22
  import PyPDF2
23
 
24
+ ##############################################################################
25
+ # SERPHouse API key for web search
26
+ ##############################################################################
27
+ SERPHOUSE_API_KEY = "V38CNn4HXpLtynJQyOeoUensTEYoFy8PBUxKpDqAW1pawT1vfJ2BWtPQ98h6"
28
+
29
+ ##############################################################################
30
+ # Simple function to call the SERPHouse Live endpoint
31
+ # https://api.serphouse.com/serp/live
32
+ ##############################################################################
33
+ def do_web_search(query: str) -> str:
34
+ """
35
+ Calls SERPHouse live endpoint with the given query (q).
36
+ Returns a simple text summary or error message.
37
+ """
38
+ try:
39
+ url = "https://api.serphouse.com/serp/live"
40
+ params = {
41
+ "q": query,
42
+ "domain": "google.com",
43
+ "lang": "en",
44
+ "device": "desktop",
45
+ "serp_type": "web",
46
+ "api_token": SERPHOUSE_API_KEY,
47
+ }
48
+ resp = requests.get(url, params=params, timeout=30)
49
+ resp.raise_for_status() # Raise an exception for 4xx/5xx errors
50
+ data = resp.json()
51
+
52
+ # For demonstration, let's extract top 3 organic results:
53
+ results = data.get("results", {})
54
+ organic = results.get("results", {}).get("organic", [])
55
+ if not organic:
56
+ return "No web search results found."
57
+
58
+ summary_lines = []
59
+ for item in organic[:3]:
60
+ rank = item.get("position", "-")
61
+ title = item.get("title", "No Title")
62
+ link = item.get("link", "No Link")
63
+ snippet = item.get("snippet", "(No snippet)")
64
+ summary_lines.append(f"**Rank {rank}:** [{title}]({link})\n\n> {snippet}")
65
+
66
+ return "\n\n".join(summary_lines) if summary_lines else "No web search results found."
67
+ except Exception as e:
68
+ logger.error(f"Web search failed: {e}")
69
+ return f"Web search failed: {str(e)}"
70
+
71
+
72
  MAX_CONTENT_CHARS = 4000 # ๋„ˆ๋ฌด ํฐ ํŒŒ์ผ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์ตœ๋Œ€ ํ‘œ์‹œ 4000์ž
73
 
74
  model_id = os.getenv("MODEL_ID", "google/gemma-3-27b-it")
 
399
  # ๋ฉ”์ธ ์ถ”๋ก  ํ•จ์ˆ˜
400
  ##################################################
401
  @spaces.GPU(duration=120)
402
+ def run(
403
+ message: dict,
404
+ history: list[dict],
405
+ system_prompt: str = "",
406
+ max_new_tokens: int = 512,
407
+ use_web_search: bool = False,
408
+ web_search_query: str = "",
409
+ ) -> Iterator[str]:
410
+ """
411
+ The main inference function. Now extended with optional web_search arguments:
412
+ - use_web_search: bool
413
+ - web_search_query: str
414
+ If `use_web_search` is True, calls SERPHouse for the given `web_search_query`.
415
+ """
416
+ # Validate media constraints first
417
  if not validate_media_constraints(message, history):
418
  yield ""
419
  return
420
 
421
  try:
422
+ # If user opted for "Web Search", do it here and yield a prefix message
423
+ if use_web_search and web_search_query.strip():
424
+ ws_result = do_web_search(web_search_query.strip())
425
+ yield f"**[Web Search Results for '{web_search_query.strip()}':]**\n\n{ws_result}\n\n---\n"
426
+
427
  messages = []
428
  if system_prompt:
429
  messages.append({"role": "system", "content": [{"type": "text", "text": system_prompt}]})
 
440
  messages.append({"role": "user", "content": user_content})
441
 
442
  # ๋ชจ๋ธ ์ž…๋ ฅ ์ƒ์„ฑ ์ „ ์ตœ์ข… ํ™•์ธ
 
443
  for msg in messages:
444
  if msg["role"] != "user":
445
  continue
 
493
 
494
 
495
 
 
 
496
  ##################################################
497
  # ์˜ˆ์‹œ๋“ค (ํ•œ๊ธ€ํ™” ๋ฒ„์ „)
498
  ##################################################
 
601
  ]
602
 
603
 
604
+
605
+
606
+ ##############################################################################
607
+ # Custom CSS similar to second example (colorful background, panel, etc.)
608
+ ##############################################################################
609
+ css = """
610
+ body {
611
+ background: linear-gradient(135deg, #667eea, #764ba2);
612
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
613
+ color: #333;
614
+ margin: 0;
615
+ padding: 0;
616
+ }
617
+ .gradio-container {
618
+ background: rgba(255, 255, 255, 0.95);
619
+ border-radius: 15px;
620
+ padding: 30px 40px;
621
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
622
+ margin: 40px auto;
623
+ max-width: 1200px;
624
+ }
625
+ .gradio-container h1 {
626
+ color: #333;
627
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
628
+ }
629
+ .fillable {
630
+ width: 95% !important;
631
+ max-width: unset !important;
632
+ }
633
+ #examples_container {
634
+ margin: auto;
635
+ width: 90%;
636
+ }
637
+ #examples_row {
638
+ justify-content: center;
639
+ }
640
+ .sidebar {
641
+ background: rgba(255, 255, 255, 0.98);
642
+ border-radius: 10px;
643
+ padding: 20px;
644
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
645
+ }
646
+ button, .btn {
647
+ background: linear-gradient(90deg, #ff8a00, #e52e71);
648
+ border: none;
649
+ color: #fff;
650
+ padding: 12px 24px;
651
+ text-transform: uppercase;
652
+ font-weight: bold;
653
+ letter-spacing: 1px;
654
+ border-radius: 5px;
655
+ cursor: pointer;
656
+ transition: transform 0.2s ease-in-out;
657
+ }
658
+ button:hover, .btn:hover {
659
+ transform: scale(1.05);
660
+ }
661
+ """
662
+
663
+ title_html = """
664
+ <h1 align="center" style="margin-bottom: 0.2em;"> ๐Ÿค— Vidraft-Gemma-3-27B </h1>
665
+ <p align="center" style="font-size:1.1em; color:#555;">
666
+ Multimodal Chat Interface + Optional Web Search
667
+ </p>
668
+ """
669
+
670
+ ##############################################################################
671
+ # Build a Blocks layout that includes:
672
+ # - A left sidebar with "Web Search" controls
673
+ # - The main ChatInterface in the center or right
674
+ ##############################################################################
675
+ with gr.Blocks(css=css, title="Vidraft-Gemma-3-27B") as demo:
676
+ gr.Markdown(title_html)
677
+
678
+ with gr.Row():
679
+ # Left Sidebar
680
+ with gr.Column(scale=3, variant="panel"):
681
+ gr.Markdown("### Menu / Options")
682
+ with gr.Row():
683
+ web_search_checkbox = gr.Checkbox(
684
+ label="Web Search",
685
+ value=False,
686
+ info="Check to enable a SERPHouse web search before the chat reply"
687
+ )
688
+ web_search_text = gr.Textbox(
689
+ lines=1,
690
+ label="Web Search Query",
691
+ placeholder="Enter search keywords..."
692
+ )
693
+ # No immediate function needed; the ChatInterface call will read these states
694
+
695
+ gr.Markdown("---")
696
+ gr.Markdown("#### System Prompt")
697
+ system_prompt_box = gr.Textbox(
698
+ lines=3,
699
+ value=(
700
+ "You are a deeply thoughtful AI. Consider problems thoroughly and derive "
701
+ "correct solutions through systematic reasoning. Please answer in korean."
702
+ ),
703
  )
 
 
 
 
 
 
 
 
 
 
 
704
 
705
+ max_tokens_slider = gr.Slider(
706
+ label="Max New Tokens",
707
+ minimum=100,
708
+ maximum=8000,
709
+ step=50,
710
+ value=2000,
711
+ )
712
+
713
+ gr.Markdown("<br><br>") # spacing
714
+
715
+ # Main ChatInterface to the right
716
+ with gr.Column(scale=7):
717
+ chat = gr.ChatInterface(
718
+ fn=run,
719
+ type="messages",
720
+ chatbot=gr.Chatbot(type="messages", scale=1, allow_tags=["image"]),
721
+ # .webp, .png, .jpg, .jpeg, .gif, .mp4, .csv, .txt, .pdf ๋ชจ๋‘ ํ—ˆ์šฉ
722
+ textbox=gr.MultimodalTextbox(
723
+ file_types=[
724
+ ".webp", ".png", ".jpg", ".jpeg", ".gif",
725
+ ".mp4", ".csv", ".txt", ".pdf"
726
+ ],
727
+ file_count="multiple",
728
+ autofocus=True
729
+ ),
730
+ multimodal=True,
731
+ additional_inputs=[
732
+ system_prompt_box,
733
+ max_tokens_slider,
734
+ web_search_checkbox,
735
+ web_search_text,
736
+ ],
737
+ stop_btn=False,
738
+ title="Vidraft-Gemma-3-27B",
739
+ examples=examples,
740
+ run_examples_on_click=False,
741
+ cache_examples=False,
742
+ css_paths=None, # We'll rely on the custom Blocks css
743
+ delete_cache=(1800, 1800),
744
+ )
745
+
746
+ with gr.Row(elem_id="examples_row"):
747
+ with gr.Column(scale=12, elem_id="examples_container"):
748
+ gr.Markdown("### Example Inputs (click to load)")
749
+ # We attach the same examples again at the bottom for a visual layout
750
+ # But note that ChatInterface already has these examples.
751
+ # Optionally, we could remove them here to avoid duplication:
752
+ gr.Examples(
753
+ examples=examples,
754
+ inputs=chat,
755
+ cache_examples=False
756
+ )
757
+
758
+ # Finally, launch
759
  if __name__ == "__main__":
760
+ demo.launch()
761
+