openfree commited on
Commit
6c2404b
·
verified ·
1 Parent(s): c83bfa7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -20
app.py CHANGED
@@ -10,7 +10,6 @@ ds = load_dataset(
10
  split="train",
11
  streaming=True, # .jsonl.zst → 자동 스트리밍 해제
12
  )
13
-
14
  records = []
15
  for ex in ds:
16
  records.append(
@@ -29,10 +28,10 @@ for ex in ds:
29
  def search_svg(query: str, top_k: int):
30
  if not query.strip():
31
  return "⚠️ 검색어를 입력하세요.", None
32
-
33
  # choices: index(int) ➜ title+tags 한 줄 문자열
34
  choices = {i: f"{r['title']} {r['tags']}" for i, r in enumerate(records)}
35
-
36
  # Rapidfuzz: (choice_text, score, key) 반환
37
  matched = process.extract(
38
  query,
@@ -40,34 +39,143 @@ def search_svg(query: str, top_k: int):
40
  scorer=fuzz.WRatio,
41
  limit=int(top_k),
42
  )
43
-
44
  html_snippets = []
45
- for _choice_text, score, idx in matched: # idx 가 실제 list 인덱스
 
 
 
46
  r = records[idx]
47
  svg_html = (
48
- "<div style='border:1px solid #ddd;margin:8px;padding:8px'>"
49
- f"<strong>{r['title']}</strong> "
50
- f"(score {score})<br>"
51
- f"<em>{r['tags']}</em><br>"
52
- f"<a href='{r['url']}' target='_blank'>원본&nbsp;다운로드</a><br>"
53
- f"{r['svg']}" # 브라우저가 즉시 SVG 렌더
54
- "</div>"
 
 
55
  )
56
  html_snippets.append(svg_html)
57
-
58
- return "", "\n".join(html_snippets)
 
 
 
59
 
60
  # ──────────────────────────────────────────────────────────
61
  # 3) Gradio UI
62
  # ──────────────────────────────────────────────────────────
63
- with gr.Blocks(title="Clker SVG 검색") as demo:
64
- gr.Markdown("## 🔍 Clker.com SVG Public-Domain Clipart 검색")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  with gr.Row():
66
- query_box = gr.Textbox(label="검색어", placeholder="예: cat, tree, ...")
67
- top_slider = gr.Slider(1, 50, value=10, step=1, label="결과 개수")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  warning_md = gr.Markdown()
69
  output_html = gr.HTML()
70
-
 
 
 
 
 
 
71
  query_box.submit(
72
  fn=search_svg,
73
  inputs=[query_box, top_slider],
@@ -75,4 +183,4 @@ with gr.Blocks(title="Clker SVG 검색") as demo:
75
  )
76
 
77
  if __name__ == "__main__":
78
- demo.launch()
 
10
  split="train",
11
  streaming=True, # .jsonl.zst → 자동 스트리밍 해제
12
  )
 
13
  records = []
14
  for ex in ds:
15
  records.append(
 
28
  def search_svg(query: str, top_k: int):
29
  if not query.strip():
30
  return "⚠️ 검색어를 입력하세요.", None
31
+
32
  # choices: index(int) ➜ title+tags 한 줄 문자열
33
  choices = {i: f"{r['title']} {r['tags']}" for i, r in enumerate(records)}
34
+
35
  # Rapidfuzz: (choice_text, score, key) 반환
36
  matched = process.extract(
37
  query,
 
39
  scorer=fuzz.WRatio,
40
  limit=int(top_k),
41
  )
42
+
43
  html_snippets = []
44
+ html_start = '<div class="gallery-grid">'
45
+ html_end = '</div>'
46
+
47
+ for _, score, idx in matched: # idx 가 실제 list 인덱스
48
  r = records[idx]
49
  svg_html = (
50
+ '<div class="gallery-item">'
51
+ f'<div class="svg-container">{r["svg"]}</div>'
52
+ f'<div class="item-details">'
53
+ f'<h3>{r["title"]}</h3>'
54
+ f'<div class="score">매칭 점수: {score}</div>'
55
+ f'<div class="tags">{r["tags"]}</div>'
56
+ f'<a href="{r["url"]}" target="_blank" class="download-link">원본 다운로드</a>'
57
+ f'</div>'
58
+ '</div>'
59
  )
60
  html_snippets.append(svg_html)
61
+
62
+ if not html_snippets:
63
+ return "검색 결과가 없습니다.", None
64
+
65
+ return "", html_start + ''.join(html_snippets) + html_end
66
 
67
  # ──────────────────────────────────────────────────────────
68
  # 3) Gradio UI
69
  # ──────────────────────────────────────────────────────────
70
+ TITLE = "🔍 Clker SVG"
71
+ DESCRIPTION = """
72
+ 이 애플리케이션은 "nyuuzyou/clker-svg" 데이터셋을 사용하여 퍼블릭 도메인 SVG 클립아트를 빠르게 검색할 수 있습니다.
73
+ 퍼지 매칭을 통해 제목과 태그에서 유사한 항목을 찾아 시각적 갤러리로 표시합니다.
74
+ """
75
+ DISCORD_BADGE = """<p style="text-align:center; margin-top: -10px;"><a href="https://discord.gg/openfreeai" target="_blank"> <img src="https://img.shields.io/static/v1?label=Discord&message=Openfree%20AI&color=%230000ff&labelColor=%23800080&logo=discord&logoColor=white&style=for-the-badge" alt="badge"></a></p>"""
76
+
77
+ CSS = """
78
+ .gallery-grid {
79
+ display: grid;
80
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
81
+ gap: 20px;
82
+ margin-top: 20px;
83
+ }
84
+ .gallery-item {
85
+ border: 1px solid #ddd;
86
+ border-radius: 8px;
87
+ overflow: hidden;
88
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
89
+ transition: transform 0.3s;
90
+ background: white;
91
+ }
92
+ .gallery-item:hover {
93
+ transform: translateY(-5px);
94
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
95
+ }
96
+ .svg-container {
97
+ height: 180px;
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: center;
101
+ padding: 10px;
102
+ background: #f9f9f9;
103
+ }
104
+ .svg-container svg {
105
+ max-width: 100%;
106
+ max-height: 160px;
107
+ }
108
+ .item-details {
109
+ padding: 15px;
110
+ }
111
+ .item-details h3 {
112
+ margin: 0 0 10px 0;
113
+ font-size: 16px;
114
+ color: #333;
115
+ white-space: nowrap;
116
+ overflow: hidden;
117
+ text-overflow: ellipsis;
118
+ }
119
+ .score {
120
+ font-size: 14px;
121
+ color: #666;
122
+ margin-bottom: 5px;
123
+ }
124
+ .tags {
125
+ font-size: 12px;
126
+ color: #888;
127
+ margin-bottom: 10px;
128
+ white-space: nowrap;
129
+ overflow: hidden;
130
+ text-overflow: ellipsis;
131
+ }
132
+ .download-link {
133
+ display: inline-block;
134
+ padding: 5px 10px;
135
+ background: #4a90e2;
136
+ color: white;
137
+ text-decoration: none;
138
+ border-radius: 4px;
139
+ font-size: 12px;
140
+ }
141
+ .download-link:hover {
142
+ background: #3a7bc8;
143
+ }
144
+ """
145
+
146
+ with gr.Blocks(title=TITLE, css=CSS) as demo:
147
+ gr.Markdown(f"# {TITLE}")
148
+ gr.Markdown(DESCRIPTION)
149
+ gr.HTML(DISCORD_BADGE)
150
+
151
  with gr.Row():
152
+ with gr.Column(scale=4):
153
+ query_box = gr.Textbox(
154
+ label="검색어",
155
+ placeholder="예: cat, tree, house, computer, flower...",
156
+ show_label=True
157
+ )
158
+ with gr.Column(scale=1):
159
+ top_slider = gr.Slider(
160
+ minimum=1,
161
+ maximum=50,
162
+ value=12,
163
+ step=3,
164
+ label="결과 개수"
165
+ )
166
+
167
+ with gr.Row():
168
+ search_button = gr.Button("검색", variant="primary")
169
+
170
  warning_md = gr.Markdown()
171
  output_html = gr.HTML()
172
+
173
+ search_button.click(
174
+ fn=search_svg,
175
+ inputs=[query_box, top_slider],
176
+ outputs=[warning_md, output_html],
177
+ )
178
+
179
  query_box.submit(
180
  fn=search_svg,
181
  inputs=[query_box, top_slider],
 
183
  )
184
 
185
  if __name__ == "__main__":
186
+ demo.launch()