import gradio as gr import os import sys import importlib.util from pathlib import Path import dotenv dotenv.load_dotenv() # 현재 디렉토리 설정 current_dir = Path(__file__).parent # 각 기능별 모듈 로드 함수 def load_module_from_path(module_name, file_path): """동적으로 모듈을 로드하는 함수""" try: spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module except Exception as e: print(f"모듈 로드 실패 {module_name}: {e}") return None # 각 기능별 모듈 및 함수 로드 modules = {} available_features = {} # 1. commonly-asked-question try: llm_functions_path = current_dir / "commonly-asked-question" / "llm_functions.py" if llm_functions_path.exists(): modules['commonly_asked'] = load_module_from_path("commonly_asked_llm", llm_functions_path) available_features['commonly_asked'] = modules['commonly_asked'] is not None else: available_features['commonly_asked'] = False except Exception as e: print(f"commonly-asked-question 모듈 로드 실패: {e}") available_features['commonly_asked'] = False # 2. question-recommendation try: llm_functions_path = current_dir / "question-recommendation" / "llm_functions.py" if llm_functions_path.exists(): modules['question_rec'] = load_module_from_path("question_rec_llm", llm_functions_path) available_features['question_rec'] = modules['question_rec'] is not None else: available_features['question_rec'] = False except Exception as e: print(f"question-recommendation 모듈 로드 실패: {e}") available_features['question_rec'] = False # 3. jd-recommendation try: llm_functions_path = current_dir / "jd-recommendation" / "llm_functions.py" if llm_functions_path.exists(): modules['jd_rec'] = load_module_from_path("jd_rec_llm", llm_functions_path) available_features['jd_rec'] = modules['jd_rec'] is not None else: available_features['jd_rec'] = False except Exception as e: print(f"jd-recommendation 모듈 로드 실패: {e}") available_features['jd_rec'] = False # 4. industry-classification try: llm_functions_path = current_dir / "industry-classification" / "llm_functions.py" if llm_functions_path.exists(): modules['industry'] = load_module_from_path("industry_llm", llm_functions_path) available_features['industry'] = modules['industry'] is not None else: available_features['industry'] = False except Exception as e: print(f"industry-classification 모듈 로드 실패: {e}") available_features['industry'] = False # 5. jasoseo-context-report try: llm_functions_path = current_dir / "jasoseo-context-report" / "llm_functions.py" if llm_functions_path.exists(): modules['jasoseo'] = load_module_from_path("jasoseo_llm", llm_functions_path) available_features['jasoseo'] = modules['jasoseo'] is not None else: available_features['jasoseo'] = False except Exception as e: print(f"jasoseo-context-report 모듈 로드 실패: {e}") available_features['jasoseo'] = False # 6. company-size-classification try: llm_functions_path = current_dir / "company-size-classification" / "llm_functions.py" if llm_functions_path.exists(): modules['company_size'] = load_module_from_path("company_size_llm", llm_functions_path) available_features['company_size'] = modules['company_size'] is not None else: available_features['company_size'] = False except Exception as e: print(f"company-size-classification 모듈 로드 실패: {e}") available_features['company_size'] = False # OpenAI 관련 모듈 try: from openai import OpenAI import yaml openai_available = True except ImportError: openai_available = False # OpenAI 클라이언트 초기화 client = None if openai_available and os.getenv("OPENAI_API_KEY"): client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) # 공통 CSS 스타일 common_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; } .tab-container { margin: 20px 0; height: 100%; } """ # 예제 데이터 example_companies = ["삼성전자", "토스", "카카오", "네이버", "LG전자", "현대자동차", "CJ제일제당", "하이브", "쿠팡", "배달의민족", "신한은행", "SKT", "포스코", "현대건설", "아모레퍼시픽"] example_jobs = ["백엔드 개발", "프론트엔드 개발", "데이터 사이언티스트", "마케팅", "영업", "기획", "디자인", "HR", "재무", "A&R", "경영기획", "해외영업", "온라인마케팅", "식품마케팅", "HRM(인사운영)"] experience_levels = ["신입", "경력", "인턴", "기타"] # 공통 함수들 def create_example_buttons(companies, jobs, company_input, job_input): """예제 버튼들을 생성하는 함수""" gr.Markdown("### 💡 **예제 회사**") with gr.Row(): for company in companies[:5]: btn = gr.Button(company, size="sm", variant="secondary") btn.click(fn=lambda x=company: x, outputs=company_input) with gr.Row(): for company in companies[5:10]: btn = gr.Button(company, size="sm", variant="secondary") btn.click(fn=lambda x=company: x, outputs=company_input) gr.Markdown("### 💼 **예제 직무**") with gr.Row(): for job in jobs[:5]: btn = gr.Button(job, size="sm", variant="secondary") btn.click(fn=lambda x=job: x, outputs=job_input) with gr.Row(): for job in jobs[5:10]: btn = gr.Button(job, size="sm", variant="secondary") btn.click(fn=lambda x=job: x, outputs=job_input) # 1. 일반적인 면접 질문 생성 탭 def create_commonly_asked_tab(): if not available_features.get('commonly_asked'): gr.Markdown("❌ **일반적인 면접 질문 생성 기능을 사용할 수 없습니다.** (모듈 로드 실패)") return gr.HTML("""

🎯 일반적인 면접 질문 생성

회사와 직무에 맞춤형 면접 질문을 AI가 생성해드립니다

""") with gr.Row(): with gr.Column(scale=2): gr.Markdown("### 📝 **기본 정보 입력**") company_input = gr.Textbox(label="🏢 회사명", placeholder="예: 삼성전자, 토스, 카카오 등") job_input = gr.Textbox(label="💼 직무", placeholder="예: 백엔드 개발, 마케팅, 기획 등") with gr.Row(): experience_input = gr.Dropdown(label="📊 경력 수준", choices=experience_levels, value="신입", interactive=True) num_questions_input = gr.Dropdown(label="📋 생성할 질문 수", choices=[1, 2, 3, 4, 5], value=3, interactive=True) common_questions_list = [ "자기소개를 해보세요", "지원 동기가 무엇인가요", "본인의 강점은 무엇인가요", "가장 도전적인 경험은 무엇인가요", "성공 경험을 말해주세요", "실패 경험을 말해주세요", "입사 후 포부는 무엇인가요", "성격의 장단점을 말해주세요", "존경하는 인물은 누구인가요", "마지막으로 하고 싶은 말은?" ] selected_questions = gr.CheckboxGroup(label="📝 참고할 일반 질문 (선택)", choices=common_questions_list, value=common_questions_list[:3]) generate_btn = gr.Button("🎯 면접 질문 생성", variant="primary", size="lg") with gr.Column(scale=1): create_example_buttons(example_companies, example_jobs, company_input, job_input) gr.Markdown("### 📋 **생성된 면접 질문**") result_output = gr.Markdown("위 정보를 입력하고 '면접 질문 생성' 버튼을 클릭하세요.") def process_question_generation(company, job, experience, selected, num): try: content, _ = modules['commonly_asked'].generate_interview_questions(company, job, experience, selected, num) return content except Exception as e: return f"❌ 오류가 발생했습니다: {e}" generate_btn.click( fn=process_question_generation, inputs=[company_input, job_input, experience_input, selected_questions, num_questions_input], outputs=result_output ) # 2. 면접 질문 추천 탭 def create_question_recommendation_tab(): if not available_features.get('question_rec') or not openai_available: gr.Markdown("❌ **면접 질문 추천 기능을 사용할 수 없습니다.** (모듈 로드 실패 또는 API 키 없음)") return gr.HTML("""

💡 면접 질문 추천

직무, 회사명, 경력 수준을 입력하면 AI가 맞춤형 질문을 추천합니다

""") with gr.Row(): with gr.Column(scale=2): gr.Markdown("### 📝 **정보 입력**") job_input = gr.Textbox(label="💼 직무", placeholder="예: 백엔드 개발, 마케팅, 기획 등") company_input = gr.Textbox(label="🏢 회사명", placeholder="예: 토스, 삼성전자, 네이버 등") experience_input = gr.Dropdown(label="📊 경력 수준", choices=experience_levels, value="신입") submit_btn = gr.Button("💡 면접 질문 추천받기", variant="primary", size="lg") with gr.Column(scale=1): create_example_buttons(example_companies, example_jobs, company_input, job_input) gr.Markdown("### 💬 **추천 면접 질문**") result_output = gr.Textbox(label="", placeholder="추천된 면접 질문이 여기에 표시됩니다.", lines=5, show_label=False, interactive=False) def recommend_question(job, company, experience): try: if not client: return "❌ OpenAI API 키가 설정되지 않았습니다." prompt_path = current_dir / "question-recommendation" / "prompt.yaml" with open(prompt_path, 'r', encoding='utf-8') as f: prompts = yaml.safe_load(f) result = modules['question_rec'].generate_question_recommendation(client, prompts, job, company, experience) parsed = modules['question_rec'].parse_question_recommendation(result) return parsed.get('recommended_question', "질문 생성에 실패했습니다.") except Exception as e: return f"❌ 오류가 발생했습니다: {e}" submit_btn.click(fn=recommend_question, inputs=[job_input, company_input, experience_input], outputs=result_output) # 3. 직무기술서 생성 탭 def create_jd_recommendation_tab(): if not available_features.get('jd_rec'): gr.Markdown("❌ **직무기술서 생성 기능을 사용할 수 없습니다.** (모듈 로드 실패)") return gr.HTML("""

📋 AI 직무기술서 생성기

맞춤형 직무기술서로 완벽한 자기소개서를 준비하세요

""") with gr.Row(): with gr.Column(scale=2): gr.Markdown("### 📝 **기본 정보 입력**") job_input = gr.Textbox(label="💼 직무", placeholder="예: 경영기획, 백엔드 개발, 온라인마케팅 등") company_input = gr.Textbox(label="🏢 회사명", placeholder="예: 삼성전자, 토스, 카카오 등") experience_input = gr.Dropdown(label="📈 경력 수준", choices=experience_levels, value="신입", interactive=True) generate_btn = gr.Button("📋 직무기술서 생성", variant="primary", size="lg") with gr.Column(scale=1): create_example_buttons(example_companies, example_jobs, company_input, job_input) gr.Markdown("### 📜 **생성된 직무기술서**") result_output = gr.Markdown("위 정보를 입력하고 '직무기술서 생성' 버튼을 클릭하세요.") def process_jd_generation(job, company, experience): try: content, _ = modules['jd_rec'].generate_jd_recommendation(job, company, experience) return content except Exception as e: return f"❌ 오류가 발생했습니다: {e}" generate_btn.click(fn=process_jd_generation, inputs=[job_input, company_input, experience_input], outputs=result_output) # 4. 산업 분류 탭 def create_industry_classification_tab(): if not available_features.get('industry'): gr.Markdown("❌ **산업 분류 기능을 사용할 수 없습니다.** (모듈 로드 실패)") return gr.HTML("""

🏷️ AI 산업 분류기

직무와 회사명을 바탕으로 정확한 산업 분야를 분류합니다

""") with gr.Row(): with gr.Column(scale=2): gr.Markdown("### 📝 **기본 정보 입력**") job_input = gr.Textbox(label="💼 직무", placeholder="예: 경영기획, 백엔드 개발, 온라인마케팅 등") company_input = gr.Textbox(label="🏢 회사명", placeholder="예: 삼성전자, 토스, 카카오 등") classify_btn = gr.Button("🏷️ 산업 분류", variant="primary", size="lg") with gr.Column(scale=1): create_example_buttons(example_companies, example_jobs, company_input, job_input) gr.Markdown("### 📑 **분류 결과**") result_output = gr.Markdown("위 정보를 입력하고 '산업 분류' 버튼을 클릭하세요.") def process_classification(job, company): try: content, _ = modules['industry'].classify_industry(job, company) return content except Exception as e: return f"❌ 오류가 발생했습니다: {e}" classify_btn.click(fn=process_classification, inputs=[job_input, company_input], outputs=result_output) # 5. 자소서 컨텍스트 리포트 탭 def create_jasoseo_context_tab(): if not available_features.get('jasoseo'): gr.Markdown("❌ **자소서 컨텍스트 리포트 기능을 사용할 수 없습니다.** (모듈 로드 실패)") return gr.HTML("""

📊 자소서 컨텍스트 리포트

기업과 직무에 대한 종합적인 분석으로 완벽한 자기소개서를 준비하세요

""") with gr.Row(): with gr.Column(scale=2): gr.Markdown("### 📝 **기본 정보 입력**") job_input = gr.Textbox(label="💼 직무", placeholder="예: 백엔드 개발, 경영기획, 마케팅 등") company_input = gr.Textbox(label="🏢 회사명", placeholder="예: 토스, 삼성전자, 카카오 등") experience_input = gr.Dropdown(label="📈 경력 수준", choices=experience_levels, value="신입", interactive=True) generate_btn = gr.Button("📊 리포트 생성", variant="primary", size="lg") with gr.Column(scale=1): create_example_buttons(example_companies, example_jobs, company_input, job_input) gr.Markdown("### 📈 **컨텍스트 리포트**") result_output = gr.Markdown("위 정보를 입력하고 '리포트 생성' 버튼을 클릭하세요.") def process_report_generation(job, company, experience): try: content, _ = modules['jasoseo'].generate_context_report(job, company, experience) return content except Exception as e: return f"❌ 오류가 발생했습니다: {e}" generate_btn.click(fn=process_report_generation, inputs=[job_input, company_input, experience_input], outputs=result_output) # 6. 기업 규모 분류 탭 def create_company_size_tab(): if not available_features.get('company_size'): gr.Markdown("❌ **기업 규모 분류 기능을 사용할 수 없습니다.** (모듈 로드 실패)") return gr.HTML("""

🏢 AI 기업 규모 예측기

실시간 웹 정보를 활용한 기업 정보 분석

""") with gr.Row(): with gr.Column(scale=2): gr.Markdown("### 📝 **기업 정보 입력**") company_input = gr.Textbox(label="🏢 기업명 입력", placeholder="분석하고 싶은 기업명을 입력하세요 (예: 삼성전자, 카카오 등)") analyze_btn = gr.Button("🔍 기업 규모 분석", variant="primary", size="lg") with gr.Column(scale=1): gr.Markdown(""" ### ℹ️ **분류 기준** - **대기업**: 매출 1조원 이상 - **중견기업**: 매출 1000억-1조원 - **중소기업**: 매출 1000억원 미만 - **스타트업**: 설립 10년 이내 - **외국계기업**: 해외 본사 - **공공기관/공기업**: 정부 출자/출연 """) gr.Markdown("### 💼 **예제 기업 선택** (클릭하면 자동 입력됩니다)") example_company_names = ["삼성전자", "현대자동차", "SK하이닉스", "포스코홀딩스", "토스", "카카오", "네이버", "쿠팡", "배달의민족", "당근마켓"] with gr.Row(): for company in example_company_names[:5]: btn = gr.Button(company, size="sm", variant="secondary") btn.click(fn=lambda x=company: x, outputs=company_input) with gr.Row(): for company in example_company_names[5:]: btn = gr.Button(company, size="sm", variant="secondary") btn.click(fn=lambda x=company: x, outputs=company_input) gr.Markdown("### 📊 **분석 결과**") result_output = gr.Markdown("기업명을 입력하고 '기업 규모 분석' 버튼을 클릭하세요.") def process_analysis_result(company): try: content, _ = modules['company_size'].analyze_company_size(company) return content except Exception as e: return f"❌ 오류가 발생했습니다: {e}" analyze_btn.click(fn=process_analysis_result, inputs=[company_input], outputs=result_output) # 메인 애플리케이션 생성 def create_main_app(): with gr.Blocks( title="🚀 JasoSeo Agent - 취업 지원 AI 도구", theme=gr.themes.Soft(primary_hue="purple", secondary_hue="pink", neutral_hue="gray"), css=common_css ) as app: gr.HTML("""

🚀 JasoSeo Agent

AI 기반 취업 지원 통합 플랫폼

""") status_items = [name for name, ok in available_features.items() if ok] status_text = f"✅ 사용 가능한 기능 ({len(status_items)}/{len(available_features)}): {', '.join(status_items)}" if status_items else "❌ 사용 가능한 기능이 없습니다." gr.Markdown(f"**{status_text}**") with gr.Tabs(elem_classes="tab-container"): with gr.Tab("🎯 면접 질문 생성", elem_id="commonly-asked-tab"): create_commonly_asked_tab() with gr.Tab("💡 질문 추천", elem_id="question-recommendation-tab"): create_question_recommendation_tab() with gr.Tab("📋 직무기술서", elem_id="jd-recommendation-tab"): create_jd_recommendation_tab() with gr.Tab("🏷️ 산업 분류", elem_id="industry-classification-tab"): create_industry_classification_tab() with gr.Tab("📊 컨텍스트 리포트", elem_id="jasoseo-context-tab"): create_jasoseo_context_tab() with gr.Tab("🏢 기업 규모", elem_id="company-size-tab"): create_company_size_tab() return app if __name__ == "__main__": if not os.getenv("OPENAI_API_KEY"): print("⚠️ OPENAI_API_KEY 환경 변수가 설정되지 않았습니다. 일부 기능이 제한될 수 있습니다.") print("\n📊 모듈 로드 상태:") for feature, available in available_features.items(): print(f" {'✅' if available else '❌'} {feature}") print("\n🚀 JasoSeo Agent 시작 중...") app = create_main_app() app.launch(share=True, show_error=True, debug=True)