Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from llm_functions import generate_interview_questions | |
| # LLM ๊ด๋ จ ํจ์๋ค์ llm_functions.py๋ก ์ด๋๋จ | |
| # ์์ ๋ฐ์ดํฐ | |
| example_companies = ["์ผ์ฑ์ ์", "ํ ์ค", "์นด์นด์ค", "๋ค์ด๋ฒ", "LG์ ์", "ํ๋์๋์ฐจ", "CJ์ ์ผ์ ๋น", "ํ์ด๋ธ", "์ฟ ํก", "๋ฐฐ๋ฌ์๋ฏผ์กฑ"] | |
| example_jobs = ["๋ฐฑ์๋ ๊ฐ๋ฐ", "ํ๋ก ํธ์๋ ๊ฐ๋ฐ", "๋ฐ์ดํฐ ์ฌ์ด์ธํฐ์คํธ", "๋ง์ผํ ", "์์ ", "๊ธฐํ", "๋์์ธ", "HR", "์ฌ๋ฌด", "A&R"] | |
| experience_levels = ["์ ์ ", "๊ฒฝ๋ ฅ", "์ธํด", "๊ธฐํ"] | |
| common_questions_list = [ | |
| "์๊ธฐ์๊ฐ๋ฅผ ํด๋ณด์ธ์", | |
| "์ง์ ๋๊ธฐ๊ฐ ๋ฌด์์ธ๊ฐ์", | |
| "๋ณธ์ธ์ ๊ฐ์ ์ ๋ฌด์์ธ๊ฐ์", | |
| "๊ฐ์ฅ ๋์ ์ ์ธ ๊ฒฝํ์ ๋ฌด์์ธ๊ฐ์", | |
| "์ฑ๊ณต ๊ฒฝํ์ ๋งํด์ฃผ์ธ์", | |
| "์คํจ ๊ฒฝํ์ ๋งํด์ฃผ์ธ์", | |
| "์ ์ฌ ํ ํฌ๋ถ๋ ๋ฌด์์ธ๊ฐ์", | |
| "์ฑ๊ฒฉ์ ์ฅ๋จ์ ์ ๋งํด์ฃผ์ธ์", | |
| "์กด๊ฒฝํ๋ ์ธ๋ฌผ์ ๋๊ตฌ์ธ๊ฐ์", | |
| "๋ง์ง๋ง์ผ๋ก ํ๊ณ ์ถ์ ๋ง์?" | |
| ] | |
| # generate_interview_questions ํจ์๋ llm_functions.py๋ก ์ด๋๋จ | |
| def create_question_cards(questions): | |
| """ | |
| ์์ฑ๋ ์ง๋ฌธ๋ค์ ์นด๋ ํํ๋ก ํ์ํ๋ HTML ์์ฑ | |
| """ | |
| if not questions: | |
| return "<div style='text-align: center; color: #6B7280; padding: 20px;'>์ง๋ฌธ์ ์์ฑํด์ฃผ์ธ์</div>" | |
| cards_html = "<div style='display: flex; flex-direction: column; gap: 15px;'>" | |
| colors = ["#EBF8FF", "#ECFDF5", "#FEF2F2", "#F5F3FF", "#FFF7ED"] | |
| border_colors = ["#1E40AF", "#059669", "#DC2626", "#7C3AED", "#EA580C"] | |
| for i, question in enumerate(questions): | |
| color = colors[i % len(colors)] | |
| border_color = border_colors[i % len(border_colors)] | |
| cards_html += f""" | |
| <div style=" | |
| background-color: {color}; | |
| border: 2px solid {border_color}; | |
| border-radius: 12px; | |
| padding: 20px; | |
| box-shadow: 0 2px 8px rgba(0,0,0,0.1); | |
| "> | |
| <div style=" | |
| font-weight: bold; | |
| color: {border_color}; | |
| font-size: 16px; | |
| margin-bottom: 10px; | |
| ">์ง๋ฌธ {i+1}</div> | |
| <div style=" | |
| color: #374151; | |
| font-size: 15px; | |
| line-height: 1.5; | |
| ">{question}</div> | |
| </div> | |
| """ | |
| cards_html += "</div>" | |
| return cards_html | |
| def process_question_generation(company_name, job_title, experience_level, selected_questions, num_questions): | |
| """ | |
| ์ง๋ฌธ ์์ฑ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๊ณ UI์ ํ์ํ ํํ๋ก ๋ณํํ๋ ํจ์ | |
| """ | |
| try: | |
| content, questions = generate_interview_questions(company_name, job_title, experience_level, selected_questions, num_questions) | |
| question_cards = create_question_cards(questions) | |
| return content, question_cards | |
| except Exception as e: | |
| error_content = f"""## โ ์ค๋ฅ ๋ฐ์ | |
| ์ง๋ฌธ ์์ฑ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. | |
| **์ค๋ฅ ๋ด์ฉ:** {str(e)} | |
| ๋ค์ ์๋ํด์ฃผ์ธ์. | |
| """ | |
| error_cards = create_question_cards([]) | |
| return error_content, error_cards | |
| # ์ ์ญ ์ํ ๊ด๋ฆฌ | |
| class AppState: | |
| def __init__(self): | |
| self.companies = ["ํ ์ค", "๋ค์ด๋ฒ", "์นด์นด์ค", "์ผ์ฑ์ ์", "LG์ ์", "ํ๋์๋์ฐจ", "SKํ์ด๋์ค", "CJ์ ์ผ์ ๋น", "ํ์ด๋ธ", "ํ๋๊ฑด์ค"] | |
| self.jobs = ["๋ฐฑ์๋ ๊ฐ๋ฐ์", "ํ๋ก ํธ์๋ ๊ฐ๋ฐ์", "๋ฐ์ดํฐ ์ฌ์ด์ธํฐ์คํธ", "๋ง์ผํ ", "์์ ", "๊ธฐํ", "๋์์ด๋", "A&R", "ํด์ธ์์ ", "์ฌ์ ๊ธฐํ"] | |
| self.questions = common_questions_list.copy() | |
| app_state = AppState() | |
| # ๋ ์ด์ ์ฌ์ฉํ์ง ์๋ ํจ์๋ค ์ ๊ฑฐ๋จ | |
| def add_company(new_company): | |
| """์ ํ์ฌ ์ถ๊ฐ""" | |
| if new_company and new_company.strip() and new_company.strip() not in app_state.companies: | |
| app_state.companies.append(new_company.strip()) | |
| return gr.Dropdown.update(choices=app_state.companies), "" | |
| return gr.Dropdown.update(), "" | |
| def add_job(new_job): | |
| """์ ์ง๋ฌด ์ถ๊ฐ""" | |
| if new_job and new_job.strip() and new_job.strip() not in app_state.jobs: | |
| app_state.jobs.append(new_job.strip()) | |
| return gr.Dropdown.update(choices=app_state.jobs), "" | |
| return gr.Dropdown.update(), "" | |
| def add_question(new_question): | |
| """์ ์ผ๋ฐ ์ง๋ฌธ ์ถ๊ฐ""" | |
| if new_question and new_question.strip() and new_question.strip() not in app_state.questions: | |
| app_state.questions.append(new_question.strip()) | |
| return gr.CheckboxGroup.update(choices=app_state.questions), "" | |
| 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>ํ์ฌ์ ์ง๋ฌด์ ๋ง์ถคํ ๋ฉด์ ์ง๋ฌธ์ AI๊ฐ ์์ฑํด๋๋ฆฝ๋๋ค</p> | |
| </div> | |
| """) | |
| # ์ค๋ช | |
| gr.Markdown(""" | |
| ### ๐ **์ฌ์ฉ ๋ฐฉ๋ฒ** | |
| 1. **ํ์ฌ๋ช **: ์ง์ํ๊ณ ์ ํ๋ ํ์ฌ๋ฅผ ์ ๋ ฅํ์ธ์ | |
| 2. **์ง๋ฌด**: ์ง์ ์ง๋ฌด๋ฅผ ์ ๋ ฅํ์ธ์ | |
| 3. **๊ฒฝ๋ ฅ ์์ค**: ๋ณธ์ธ์ ๊ฒฝ๋ ฅ ์์ค์ ์ ํํ์ธ์ | |
| 4. **์ผ๋ฐ ์ง๋ฌธ**: ์ฐธ๊ณ ํ ์ผ๋ฐ์ ์ธ ๋ฉด์ ์ง๋ฌธ๋ค์ ์ ํํ์ธ์ | |
| 5. **์์ฑ**: '์ง๋ฌธ ์์ฑ' ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ง์ถคํ ์ง๋ฌธ์ ๋ฐ์๋ณด์ธ์ | |
| โจ **ํน์ง**: ํ์ฌ์ ํน์ฑ, ์ง๋ฌด ์๊ตฌ์ฌํญ, ๊ฒฝ๋ ฅ ์์ค์ ๋ชจ๋ ๊ณ ๋ คํ ๊ตฌ์ฒด์ ์ด๊ณ ํ์ค์ ์ธ ์ง๋ฌธ์ ์์ฑํฉ๋๋ค. | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| # ์ ๋ ฅ ์น์ | |
| gr.HTML('<div class="input-section">') | |
| gr.Markdown("### ๐ **๊ธฐ๋ณธ ์ ๋ณด ์ ๋ ฅ**") | |
| with gr.Row(): | |
| company_input = gr.Textbox( | |
| label="๐ข ํ์ฌ๋ช ", | |
| placeholder="์: ์ผ์ฑ์ ์, ํ ์ค, ์นด์นด์ค ๋ฑ", | |
| value="", | |
| scale=2, | |
| elem_id="company_input" | |
| ) | |
| job_input = gr.Textbox( | |
| label="๐ผ ์ง๋ฌด", | |
| placeholder="์: ๋ฐฑ์๋ ๊ฐ๋ฐ, ๋ง์ผํ , ๊ธฐํ ๋ฑ", | |
| value="", | |
| scale=2, | |
| elem_id="job_input" | |
| ) | |
| with gr.Row(): | |
| experience_input = gr.Dropdown( | |
| label="๐ ๊ฒฝ๋ ฅ ์์ค", | |
| choices=experience_levels, | |
| value="์ ์ ", | |
| interactive=True, | |
| scale=2 | |
| ) | |
| num_questions_input = gr.Dropdown( | |
| label="๐ข ์ง๋ฌธ ๊ฐ์", | |
| choices=[1, 2, 3, 4, 5], | |
| value=3, | |
| interactive=True, | |
| scale=1 | |
| ) | |
| common_questions_input = gr.CheckboxGroup( | |
| label="๐ ์ฐธ๊ณ ํ ์ผ๋ฐ ๋ฉด์ ์ง๋ฌธ (3-5๊ฐ ์ ํ ๊ถ์ฅ)", | |
| choices=common_questions_list, | |
| value=common_questions_list[:4], | |
| 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("### ๐ข **ํ์ฌ ๊ด๋ฆฌ**") | |
| with gr.Row(): | |
| new_company_input = gr.Textbox( | |
| label="์ ํ์ฌ ์ถ๊ฐ", | |
| placeholder="ํ์ฌ๋ช ์ ๋ ฅ", | |
| scale=2 | |
| ) | |
| add_company_btn = gr.Button("์ถ๊ฐ", size="sm", scale=1) | |
| # ์์ ํ์ฌ ๋๋กญ๋ค์ด | |
| company_dropdown = gr.Dropdown( | |
| label="์์ ํ์ฌ ์ ํ", | |
| choices=app_state.companies, | |
| value=None, | |
| interactive=True | |
| ) | |
| # ์ฌ์ฉ์ ์ ์ ์ง๋ฌด ์ถ๊ฐ | |
| gr.Markdown("### ๐ผ **์ง๋ฌด ๊ด๋ฆฌ**") | |
| with gr.Row(): | |
| new_job_input = gr.Textbox( | |
| label="์ ์ง๋ฌด ์ถ๊ฐ", | |
| placeholder="์ง๋ฌด๋ช ์ ๋ ฅ", | |
| scale=2 | |
| ) | |
| add_job_btn = gr.Button("์ถ๊ฐ", size="sm", scale=1) | |
| # ์์ ์ง๋ฌด ๋๋กญ๋ค์ด | |
| job_dropdown = gr.Dropdown( | |
| label="์์ ์ง๋ฌด ์ ํ", | |
| choices=app_state.jobs, | |
| value=None, | |
| interactive=True | |
| ) | |
| # ์ฌ์ฉ์ ์ ์ ์ผ๋ฐ ์ง๋ฌธ ์ถ๊ฐ | |
| gr.Markdown("### ๐ **์ผ๋ฐ ์ง๋ฌธ ๊ด๋ฆฌ**") | |
| with gr.Row(): | |
| new_question_input = gr.Textbox( | |
| label="์ ์ผ๋ฐ ์ง๋ฌธ ์ถ๊ฐ", | |
| placeholder="์ง๋ฌธ ๋ด์ฉ ์ ๋ ฅ", | |
| scale=2 | |
| ) | |
| add_question_btn = gr.Button("์ถ๊ฐ", size="sm", scale=1) | |
| 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("### ๐ฏ **์ง๋ฌธ ์นด๋**") | |
| question_cards = gr.HTML( | |
| value="<div style='text-align: center; color: #6B7280; padding: 20px;'>์ง๋ฌธ์ ์์ฑํด์ฃผ์ธ์</div>", | |
| elem_classes=["question-cards"] | |
| ) | |
| # ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐ๊ฒฐ | |
| add_company_btn.click( | |
| fn=add_company, | |
| inputs=[new_company_input], | |
| outputs=[company_dropdown, new_company_input] | |
| ) | |
| add_job_btn.click( | |
| fn=add_job, | |
| inputs=[new_job_input], | |
| outputs=[job_dropdown, new_job_input] | |
| ) | |
| add_question_btn.click( | |
| fn=add_question, | |
| inputs=[new_question_input], | |
| outputs=[common_questions_input, new_question_input] | |
| ) | |
| # ๋๋กญ๋ค์ด ์ ํ ์ ์ ๋ ฅ ํ๋์ ์๋ ์ ๋ ฅ | |
| company_dropdown.change( | |
| fn=lambda x: x if x else "", | |
| inputs=[company_dropdown], | |
| outputs=[company_input] | |
| ) | |
| job_dropdown.change( | |
| fn=lambda x: x if x else "", | |
| inputs=[job_dropdown], | |
| outputs=[job_input] | |
| ) | |
| # ์์ฑ ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ | |
| generate_btn.click( | |
| fn=process_question_generation, | |
| inputs=[company_input, job_input, experience_input, common_questions_input, num_questions_input], | |
| outputs=[result_output, question_cards], | |
| api_name="generate_questions" | |
| ) | |
| # ํธํฐ | |
| gr.Markdown(""" | |
| --- | |
| **๐ก ์์ฑ๋ ์ง๋ฌธ ํ์ฉ ํ**: | |
| - ๊ฐ ์ง๋ฌธ์ ๋ํด STAR(Situation, Task, Action, Result) ๊ธฐ๋ฒ์ผ๋ก ๋ต๋ณ์ ์ค๋นํด๋ณด์ธ์ | |
| - ํ์ฌ์ ์ง๋ฌด์ ๋ํ ์ฌ์ ์กฐ์ฌ๋ฅผ ๋ฐํ์ผ๋ก ๊ตฌ์ฒด์ ์ธ ์ฌ๋ก๋ฅผ ์ค๋นํ์ธ์ | |
| - ์์ฑ๋ ์ง๋ฌธ์ ๋ฐํ์ผ๋ก ์ถ๊ฐ ์ง๋ฌธ๋ค๋ ์์ํด๋ณด์ธ์ | |
| ๐ค **Powered by**: OpenAI GPT-4o with Web Search | |
| """) | |
| return demo | |
| if __name__ == "__main__": | |
| # Gradio ์ฑ ์คํ | |
| demo = create_interface() | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| # server_port=7864, | |
| share=True, | |
| show_error=True | |
| ) | |