Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from llm_functions import generate_context_report | |
| # μμ λ°μ΄ν° | |
| example_companies = ["ν μ€", "μΌμ±μ μ", "CJμ μΌμ λΉ", "νμ΄λΈ", "νλ건μ€", "μ νμν", "μΉ΄μΉ΄μ€", "λ€μ΄λ²", "LGμ μ", "SKνμ΄λμ€"] | |
| example_jobs = ["λ°±μλ κ°λ°", "κ²½μκΈ°ν", "μνλ§μΌν ", "A&R", "HRM(μΈμ¬μ΄μ)", "ν΄μΈμμ ", "λ°μ΄ν° λΆμ", "μ¨λΌμΈλ§μΌν ", "κΈ°ν", "κ°λ°"] | |
| experience_levels = ["μ μ ", "κ²½λ ₯", "μΈν΄", "κΈ°ν"] | |
| def create_info_cards(report_data): | |
| """ | |
| 리ν¬νΈ λ°μ΄ν°λ₯Ό μΉ΄λ ννλ‘ νμνλ HTML μμ± | |
| """ | |
| if not report_data or 'company_profile' not in report_data: | |
| return "<div style='text-align: center; color: #6B7280; padding: 20px;'>리ν¬νΈλ₯Ό μμ±ν΄μ£ΌμΈμ</div>" | |
| # κΈ°μ νλ‘ν μΉ΄λ | |
| company_card = f""" | |
| <div style=" | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| border-radius: 15px; | |
| padding: 20px; | |
| margin: 10px 0; | |
| box-shadow: 0 4px 15px rgba(0,0,0,0.1); | |
| "> | |
| <h3 style="margin: 0 0 15px 0; font-size: 18px;">π’ κΈ°μ νλ‘ν</h3> | |
| <div style="background: rgba(255,255,255,0.1); border-radius: 10px; padding: 15px;"> | |
| <strong>π― λΉμ /λ―Έμ :</strong><br> | |
| {report_data['company_profile']['vision_mission']}<br><br> | |
| <strong>π ν΅μ¬ κ°μΉ:</strong><br> | |
| {' β’ '.join(report_data['company_profile']['core_values'])}<br><br> | |
| <strong>π₯ μΈμ¬μ:</strong><br> | |
| {report_data['company_profile']['talent_philosophy']} | |
| </div> | |
| </div> | |
| """ | |
| # μ§λ¬΄ λΆμ μΉ΄λ | |
| position_card = f""" | |
| <div style=" | |
| background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%); | |
| color: white; | |
| border-radius: 15px; | |
| padding: 20px; | |
| margin: 10px 0; | |
| box-shadow: 0 4px 15px rgba(0,0,0,0.1); | |
| "> | |
| <h3 style="margin: 0 0 15px 0; font-size: 18px;">πΌ μ§λ¬΄ λΆμ</h3> | |
| <div style="background: rgba(255,255,255,0.1); border-radius: 10px; padding: 15px;"> | |
| <strong>π μν :</strong><br> | |
| {report_data['position_analysis']['role_summary']}<br><br> | |
| <strong>π§ νλ μ€ν¬:</strong><br> | |
| {' β’ '.join(report_data['position_analysis']['required_skills']['hard'])}<br><br> | |
| <strong>π‘ μννΈ μ€ν¬:</strong><br> | |
| {' β’ '.join(report_data['position_analysis']['required_skills']['soft'])} | |
| </div> | |
| </div> | |
| """ | |
| # μ°μ λ§₯λ½ μΉ΄λ | |
| industry_card = f""" | |
| <div style=" | |
| background: linear-gradient(135deg, #fc4a1a 0%, #f7b733 100%); | |
| color: white; | |
| border-radius: 15px; | |
| padding: 20px; | |
| margin: 10px 0; | |
| box-shadow: 0 4px 15px rgba(0,0,0,0.1); | |
| "> | |
| <h3 style="margin: 0 0 15px 0; font-size: 18px;">π μ°μ λ§₯λ½</h3> | |
| <div style="background: rgba(255,255,255,0.1); border-radius: 10px; padding: 15px;"> | |
| <strong>π μ£Όμ νΈλ λ:</strong><br> | |
| {' β’ '.join(report_data['industry_context']['trends'])}<br><br> | |
| <strong>π μ£Όμ κ²½μμ¬:</strong><br> | |
| {' β’ '.join(report_data['industry_context']['competitors'])} | |
| </div> | |
| </div> | |
| """ | |
| # ν€μλ μΉ΄λ | |
| keywords_html = "" | |
| if 'keywords' in report_data['position_analysis']: | |
| keywords_html = "<div style='margin-top: 15px;'><strong>π·οΈ ν΅μ¬ ν€μλ:</strong><br>" | |
| for keyword in report_data['position_analysis']['keywords']: | |
| keywords_html += f"<span style='background: rgba(255,255,255,0.2); padding: 5px 10px; border-radius: 15px; margin: 2px; display: inline-block; font-size: 12px;'>{keyword}</span>" | |
| keywords_html += "</div>" | |
| return f""" | |
| <div style="display: flex; flex-direction: column; gap: 10px;"> | |
| {company_card} | |
| {position_card} | |
| {industry_card} | |
| <div style=" | |
| background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%); | |
| color: #333; | |
| border-radius: 15px; | |
| padding: 20px; | |
| margin: 10px 0; | |
| box-shadow: 0 4px 15px rgba(0,0,0,0.1); | |
| "> | |
| <h3 style="margin: 0 0 15px 0; font-size: 18px;">π·οΈ ν΅μ¬ ν€μλ</h3> | |
| <div style="display: flex; flex-wrap: wrap; gap: 8px;"> | |
| {''.join([f'<span style="background: #667eea; color: white; padding: 8px 15px; border-radius: 20px; font-size: 14px; font-weight: bold;">{keyword}</span>' for keyword in report_data['position_analysis']['keywords']])} | |
| </div> | |
| </div> | |
| </div> | |
| """ | |
| def process_report_generation(job_title, company_name, experience_level): | |
| """ | |
| 리ν¬νΈ μμ± κ²°κ³Όλ₯Ό μ²λ¦¬νκ³ UIμ νμν ννλ‘ λ³ννλ ν¨μ | |
| """ | |
| try: | |
| content, report_data = generate_context_report(job_title, company_name, experience_level) | |
| info_cards = create_info_cards(report_data) | |
| return content, info_cards | |
| except Exception as e: | |
| error_content = f"""## β μ€λ₯ λ°μ | |
| 컨ν μ€νΈ 리ν¬νΈ μμ± μ€ μ€λ₯κ° λ°μνμ΅λλ€. | |
| **μ€λ₯ λ΄μ©:** {str(e)} | |
| λ€μ μλν΄μ£ΌμΈμ. | |
| """ | |
| error_cards = create_info_cards({}) | |
| return error_content, error_cards | |
| def create_interface(): | |
| """ | |
| Gradio μΈν°νμ΄μ€ μμ± | |
| """ | |
| with gr.Blocks( | |
| title="π μμμ 컨ν μ€νΈ 리ν¬νΈ", | |
| 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>π μμμ 컨ν μ€νΈ 리ν¬νΈ</h1> | |
| <p>κΈ°μ κ³Ό μ§λ¬΄μ λν μ’ ν©μ μΈ λΆμμΌλ‘ μλ²½ν μκΈ°μκ°μλ₯Ό μ€λΉνμΈμ</p> | |
| </div> | |
| """) | |
| # μ€λͺ | |
| gr.Markdown(""" | |
| ### π **μ¬μ© λ°©λ²** | |
| 1. **μ§λ¬΄**: μ§μνκ³ μ νλ μ§λ¬΄λ₯Ό μ λ ₯νμΈμ | |
| 2. **νμ¬λͺ **: μ§μ νμ¬λͺ μ μ λ ₯νμΈμ | |
| 3. **κ²½λ ₯ μμ€**: μ μ /κ²½λ ₯/μΈν΄/κΈ°ν μ€ μ ννμΈμ | |
| 4. **μμ±**: '리ν¬νΈ μμ±' λ²νΌμ ν΄λ¦νμ¬ κ²°κ³Όλ₯Ό νμΈνμΈμ | |
| β¨ **νΉμ§**: κΈ°μ νλ‘ν, μ§λ¬΄ λΆμ, μ°μ λ§₯λ½μ μ’ ν©μ μΌλ‘ λΆμνμ¬ μμμ μμ±μ νμν ν΅μ¬ μ 보λ₯Ό μ 곡ν©λλ€. | |
| """) | |
| 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 | |
| ) | |
| experience_input = gr.Dropdown( | |
| label="π κ²½λ ₯ μμ€", | |
| choices=experience_levels, | |
| value="μ μ ", | |
| interactive=True | |
| ) | |
| generate_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.Markdown("### π **κ²½λ ₯ μμ€**") | |
| with gr.Row(): | |
| for level in experience_levels: | |
| level_btn = gr.Button( | |
| level, | |
| size="sm", | |
| variant="secondary", | |
| scale=1 | |
| ) | |
| level_btn.click( | |
| fn=lambda x=level: x, | |
| outputs=experience_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("### π **ν΅μ¬ μ 보**") | |
| info_cards = gr.HTML( | |
| value="<div style='text-align: center; color: #6B7280; padding: 20px;'>리ν¬νΈλ₯Ό μμ±ν΄μ£ΌμΈμ</div>", | |
| elem_classes=["info-cards"] | |
| ) | |
| # μμ± λ²νΌ ν΄λ¦ μ΄λ²€νΈ | |
| generate_btn.click( | |
| fn=process_report_generation, | |
| inputs=[job_input, company_input, experience_input], | |
| outputs=[result_output, info_cards], | |
| api_name="generate_context_report" | |
| ) | |
| # νΈν° | |
| gr.Markdown(""" | |
| --- | |
| **π 리ν¬νΈ ꡬμ±**: | |
| - **π’ κΈ°μ νλ‘ν**: λΉμ /λ―Έμ , ν΅μ¬κ°μΉ, μΈμ¬μ, μ΅κ·Όλν₯, μ£Όμμ ν/μλΉμ€ | |
| - **πΌ μ§λ¬΄ λΆμ**: μν μμ½, νμμ€ν¬(νλ/μννΈ), ν΅μ¬ν€μλ | |
| - **π μ°μ λ§₯λ½**: μ£ΌμνΈλ λ, κ²½μμ¬ μ 보 | |
| π‘ **νμ© ν**: μμ±λ ν€μλμ μ 보λ₯Ό μμμ μμ± μ μ κ·Ή νμ©νμ¬ λ§μΆ€ν μκΈ°μκ°μλ₯Ό μμ±νμΈμ. | |
| π€ **Powered by**: OpenAI GPT-4o | |
| """) | |
| 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 | |
| ) |