kyle8581's picture
.
594e237
import gradio as gr
from llm_functions import classify_industry
# ์˜ˆ์ œ ๋ฐ์ดํ„ฐ
example_companies = ["์‚ผ์„ฑ์ „์ž", "์‹ ํ•œ์€ํ–‰", "์ฟ ํŒก", "์•„๋ชจ๋ ˆํผ์‹œํ”ฝ", "ํ˜„๋Œ€๊ฑด์„ค", "ํ•˜์ด๋ธŒ", "ํ† ์Šค", "๋„ฅ์Šจ", "์‚ผ์„ฑ๋ฐ”์ด์˜ค๋กœ์ง์Šค", "HMM"]
example_jobs = ["๊ฒฝ์˜๊ธฐํš", "์˜จ๋ผ์ธ๋งˆ์ผ€ํŒ…", "HRM(์ธ์‚ฌ์šด์˜)", "๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ", "ํ•ด์™ธ์˜์—…", "๋ฐ์ดํ„ฐ ๋ถ„์„", "์˜์—…", "๋งˆ์ผ€ํŒ…", "๊ธฐํš", "๊ฐœ๋ฐœ"]
def create_tag_cards(tags):
"""
๋ถ„๋ฅ˜๋œ ํƒœ๊ทธ๋“ค์„ ์นด๋“œ ํ˜•ํƒœ๋กœ ํ‘œ์‹œํ•˜๋Š” HTML ์ƒ์„ฑ
"""
if not tags:
return "<div style='text-align: center; color: #6B7280; padding: 20px;'>๋ถ„๋ฅ˜๋ฅผ ์‹คํ–‰ํ•ด์ฃผ์„ธ์š”</div>"
# ํƒœ๊ทธ๋ช… ๋งคํ•‘
tag_mapping = {
"platform-portal": "ํ”Œ๋žซํผ/ํฌํ„ธ",
"e-commerce": "์ด์ปค๋จธ์Šค",
"game": "๊ฒŒ์ž„",
"it-solution-si": "IT์†”๋ฃจ์…˜/SI",
"o2o-vertical": "O2O/๋ฒ„ํ‹ฐ์ปฌ",
"ai-data": "AI/๋ฐ์ดํ„ฐ",
"cloud-saas": "ํด๋ผ์šฐ๋“œ/SaaS",
"fintech": "ํ•€ํ…Œํฌ",
"semiconductor": "๋ฐ˜๋„์ฒด",
"electronics-home": "๊ฐ€์ „/์ „์ž์ œํ’ˆ",
"automotive-mobility": "์ž๋™์ฐจ/๋ชจ๋นŒ๋ฆฌํ‹ฐ",
"battery": "2์ฐจ์ „์ง€",
"display": "๋””์Šคํ”Œ๋ ˆ์ด",
"heavy-industry-shipbuilding": "์ค‘๊ณต์—…/์กฐ์„ ",
"steel-metal": "์ฒ ๊ฐ•/๊ธˆ์†",
"bank": "์€ํ–‰",
"securities": "์ฆ๊ถŒ",
"insurance": "๋ณดํ—˜",
"card": "์นด๋“œ",
"asset-management": "์ž์‚ฐ์šด์šฉ",
"dept-store-mart": "๋ฐฑํ™”์ /๋งˆํŠธ",
"convenience-store": "ํŽธ์˜์ ",
"fmcg-beverage": "FMCG/์‹์Œ๋ฃŒ",
"fashion-beauty": "ํŒจ์…˜/๋ทฐํ‹ฐ",
"duty-free": "๋ฉด์„ธ์ ",
"pharma-new-drug": "์ œ์•ฝ/์‹ ์•ฝ๊ฐœ๋ฐœ",
"bio-cmo": "๋ฐ”์ด์˜ค/CMO",
"medical-device": "์˜๋ฃŒ๊ธฐ๊ธฐ",
"digital-healthcare": "๋””์ง€ํ„ธํ—ฌ์Šค์ผ€์–ด",
"entertainment": "์—”ํ„ฐํ…Œ์ธ๋จผํŠธ",
"contents-video": "์ฝ˜ํ…์ธ /์˜์ƒ์ œ์ž‘",
"ad-agency": "๊ด‘๊ณ ๋Œ€ํ–‰์‚ฌ",
"webtoon-webnovel": "์›นํˆฐ/์›น์†Œ์„ค",
"broadcasting-press": "๋ฐฉ์†ก/์–ธ๋ก ",
"construction-engineering": "๊ฑด์„ค/์—”์ง€๋‹ˆ์–ด๋ง",
"realestate-development": "๋ถ€๋™์‚ฐ๊ฐœ๋ฐœ",
"plant": "ํ”Œ๋žœํŠธ",
"interior": "์ธํ…Œ๋ฆฌ์–ด",
"public-soc": "SOC (๊ณตํ•ญ,๋„๋กœ,์ฒ ๋„)",
"public-energy": "์—๋„ˆ์ง€ ๊ณต๊ธฐ์—…",
"public-finance": "๊ธˆ์œต ๊ณต๊ธฐ์—…",
"public-admin": "์ผ๋ฐ˜ํ–‰์ •",
"mpe-semiconductor": "๋ฐ˜๋„์ฒด ์†Œ๋ถ€์žฅ",
"mpe-display": "๋””์Šคํ”Œ๋ ˆ์ด ์†Œ๋ถ€์žฅ",
"mpe-battery": "2์ฐจ์ „์ง€ ์†Œ๋ถ€์žฅ",
"auto-parts": "์ž๋™์ฐจ ๋ถ€ํ’ˆ",
"chemical-materials": "ํ™”ํ•™/์†Œ์žฌ",
"hotel": "ํ˜ธํ…”",
"travel-agency": "์—ฌํ–‰์‚ฌ",
"airline": "ํ•ญ๊ณต์‚ฌ",
"leisure-resort": "๋ ˆ์ €/๋ฆฌ์กฐํŠธ",
"consulting": "์ปจ์„คํŒ…",
"accounting-tax": "ํšŒ๊ณ„/์„ธ๋ฌด",
"law-firm": "๋ฒ•๋ฅ  (๋กœํŽŒ)",
"market-research": "๋ฆฌ์„œ์น˜",
"logistics-delivery": "๋ฌผ๋ฅ˜/ํƒ๋ฐฐ",
"shipping": "ํ•ด์šด",
"forwarding": "ํฌ์›Œ๋”ฉ",
"land-transport": "์œก์ƒ์šด์†ก",
"edutech": "์—๋“€ํ…Œํฌ",
"private-academy": "์ž…์‹œ/๋ณด์Šตํ•™์›",
"edu-publishing": "๊ต์œก์ถœํŒ",
"language-edu": "์™ธ๊ตญ์–ด๊ต์œก",
"ngo-npo": "NGO/NPO",
"social-enterprise": "์‚ฌํšŒ์ ๊ธฐ์—…",
"foundation": "์žฌ๋‹จ"
}
cards_html = "<div style='display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;'>"
colors = ["#EBF8FF", "#ECFDF5", "#FEF2F2", "#F5F3FF", "#FFF7ED", "#F0FDFA", "#FDF2F8"]
border_colors = ["#1E40AF", "#059669", "#DC2626", "#7C3AED", "#EA580C", "#0F766E", "#BE185D"]
for i, tag in enumerate(tags):
color = colors[i % len(colors)]
border_color = border_colors[i % len(border_colors)]
tag_name = tag_mapping.get(tag, tag)
cards_html += f"""
<div style="
background-color: {color};
border: 2px solid {border_color};
border-radius: 12px;
padding: 15px;
margin: 5px;
min-width: 150px;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
">
<div style="
font-weight: bold;
color: {border_color};
font-size: 14px;
margin-bottom: 5px;
">#{tag_name}</div>
<div style="
color: #6B7280;
font-size: 12px;
font-family: monospace;
">{tag}</div>
</div>
"""
cards_html += "</div>"
return cards_html
def process_classification(job_title, company_name):
"""
๋ถ„๋ฅ˜ ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  UI์— ํ‘œ์‹œํ•  ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
"""
try:
content, tags = classify_industry(job_title, company_name)
tag_cards = create_tag_cards(tags)
return content, tag_cards
except Exception as e:
error_content = f"""## โŒ ์˜ค๋ฅ˜ ๋ฐœ์ƒ
์‚ฐ์—… ๋ถ„๋ฅ˜ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
**์˜ค๋ฅ˜ ๋‚ด์šฉ:** {str(e)}
๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.
"""
error_cards = create_tag_cards([])
return error_content, error_cards
def create_interface():
"""
Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ
"""
with gr.Blocks(
title="๐Ÿท๏ธ AI ์‚ฐ์—… ๋ถ„๋ฅ˜๊ธฐ",
theme=gr.themes.Soft(),
css="""
.main-header {
text-align: center;
padding: 20px;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
margin-bottom: 20px;
}
.input-section {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin: 10px 0;
}
.example-section {
background-color: #f0f9ff;
padding: 15px;
border-radius: 8px;
margin: 10px 0;
}
"""
) as demo:
# ํ—ค๋”
gr.HTML("""
<div class="main-header">
<h1>๐Ÿท๏ธ AI ์‚ฐ์—… ๋ถ„๋ฅ˜๊ธฐ</h1>
<p>์ง๋ฌด์™€ ํšŒ์‚ฌ๋ช…์„ ๋ฐ”ํƒ•์œผ๋กœ ์ •ํ™•ํ•œ ์‚ฐ์—… ๋ถ„์•ผ๋ฅผ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค</p>
</div>
""")
# ์„ค๋ช…
gr.Markdown("""
### ๐Ÿš€ **์‚ฌ์šฉ ๋ฐฉ๋ฒ•**
1. **์ง๋ฌด**: ๋ถ„๋ฅ˜ํ•˜๊ณ  ์‹ถ์€ ์ง๋ฌด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”
2. **ํšŒ์‚ฌ๋ช…**: ํ•ด๋‹น ํšŒ์‚ฌ๋ช…์„ ์ž…๋ ฅํ•˜์„ธ์š”
3. **๋ถ„๋ฅ˜**: '์‚ฐ์—… ๋ถ„๋ฅ˜' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜์„ธ์š”
โœจ **ํŠน์ง•**: ํšŒ์‚ฌ์˜ ์‚ฌ์—… ์˜์—ญ๊ณผ ์ง๋ฌด ํŠน์„ฑ์„ ์ข…ํ•ฉ์ ์œผ๋กœ ๊ณ ๋ คํ•˜์—ฌ ์ •ํ™•ํ•œ ์‚ฐ์—… ํƒœ๊ทธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
""")
with gr.Row():
with gr.Column(scale=2):
# ์ž…๋ ฅ ์„น์…˜
gr.HTML('<div class="input-section">')
gr.Markdown("### ๐Ÿ“ **๊ธฐ๋ณธ ์ •๋ณด ์ž…๋ ฅ**")
with gr.Row():
job_input = gr.Textbox(
label="๐Ÿ’ผ ์ง๋ฌด",
placeholder="์˜ˆ: ๊ฒฝ์˜๊ธฐํš, ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ, ์˜จ๋ผ์ธ๋งˆ์ผ€ํŒ… ๋“ฑ",
value="",
scale=1
)
company_input = gr.Textbox(
label="๐Ÿข ํšŒ์‚ฌ๋ช…",
placeholder="์˜ˆ: ์‚ผ์„ฑ์ „์ž, ํ† ์Šค, ์นด์นด์˜ค ๋“ฑ",
value="",
scale=1
)
classify_btn = gr.Button(
"๐Ÿท๏ธ ์‚ฐ์—… ๋ถ„๋ฅ˜",
variant="primary",
size="lg"
)
gr.HTML('</div>')
with gr.Column(scale=1):
# ์˜ˆ์ œ ๋ฐ ๊ฐ€์ด๋“œ
gr.HTML('<div class="example-section">')
gr.Markdown("### ๐Ÿ’ก **์˜ˆ์ œ ํšŒ์‚ฌ**")
company_rows = [example_companies[i:i+2] for i in range(0, len(example_companies), 2)]
for row in company_rows:
with gr.Row():
for company in row:
example_btn = gr.Button(
company,
size="sm",
variant="secondary",
scale=1
)
example_btn.click(
fn=lambda x=company: x,
outputs=company_input
)
gr.Markdown("### ๐Ÿ’ผ **์˜ˆ์ œ ์ง๋ฌด**")
job_rows = [example_jobs[i:i+2] for i in range(0, len(example_jobs), 2)]
for row in job_rows:
with gr.Row():
for job in row:
job_btn = gr.Button(
job,
size="sm",
variant="secondary",
scale=1
)
job_btn.click(
fn=lambda x=job: x,
outputs=job_input
)
gr.HTML('</div>')
# ๊ฒฐ๊ณผ ์ถœ๋ ฅ ์„น์…˜
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("### ๐Ÿ“‹ **๋ถ„๋ฅ˜ ๊ฒฐ๊ณผ**")
result_output = gr.Markdown(
value="์ง๋ฌด์™€ ํšŒ์‚ฌ๋ช…์„ ์ž…๋ ฅํ•˜๊ณ  '์‚ฐ์—… ๋ถ„๋ฅ˜' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”.",
elem_classes=["result-output"]
)
with gr.Column(scale=1):
gr.Markdown("### ๐Ÿท๏ธ **์‚ฐ์—… ํƒœ๊ทธ**")
tag_cards = gr.HTML(
value="<div style='text-align: center; color: #6B7280; padding: 20px;'>๋ถ„๋ฅ˜๋ฅผ ์‹คํ–‰ํ•ด์ฃผ์„ธ์š”</div>",
elem_classes=["tag-cards"]
)
# ๋ถ„๋ฅ˜ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
classify_btn.click(
fn=process_classification,
inputs=[job_input, company_input],
outputs=[result_output, tag_cards],
api_name="classify_industry"
)
# ํ‘ธํ„ฐ
gr.Markdown("""
---
**๐Ÿ’ก ๋ถ„๋ฅ˜ ๊ธฐ์ค€**:
- **ITยทํ”Œ๋žซํผยท๊ฒŒ์ž„**: ํ”Œ๋žซํผ, ์ด์ปค๋จธ์Šค, ๊ฒŒ์ž„, IT์†”๋ฃจ์…˜, ํ•€ํ…Œํฌ ๋“ฑ
- **์ œ์กฐยทํ•˜๋“œ์›จ์–ด**: ๋ฐ˜๋„์ฒด, ๊ฐ€์ „, ์ž๋™์ฐจ, 2์ฐจ์ „์ง€, ๋””์Šคํ”Œ๋ ˆ์ด ๋“ฑ
- **๊ธˆ์œต**: ์€ํ–‰, ์ฆ๊ถŒ, ๋ณดํ—˜, ์นด๋“œ, ์ž์‚ฐ์šด์šฉ ๋“ฑ
- **์œ ํ†ตยท์†Œ๋น„์žฌ**: ๋ฐฑํ™”์ , ํŽธ์˜์ , FMCG, ํŒจ์…˜๋ทฐํ‹ฐ ๋“ฑ
- **๊ธฐํƒ€**: ๋ฐ”์ด์˜ค์ œ์•ฝ, ๋ฏธ๋””์–ด์ฝ˜ํ…์ธ , ๊ฑด์„ค๋ถ€๋™์‚ฐ, ๊ณต๊ธฐ์—… ๋“ฑ
๐Ÿค– **Powered by**: OpenAI GPT-4o-mini with Web Search
""")
return demo
if __name__ == "__main__":
# Gradio ์•ฑ ์‹คํ–‰
demo = create_interface()
demo.launch(
server_name="0.0.0.0",
# server_port=7862,
share=True,
show_error=True
)