Spaces:
Sleeping
Sleeping
| import os | |
| import json | |
| import re | |
| import yaml | |
| from openai import OpenAI | |
| # OpenAI ํด๋ผ์ด์ธํธ ์ด๊ธฐํ | |
| client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
| # ํ๋กฌํํธ ํ ํ๋ฆฟ ๋ก๋ | |
| import os | |
| current_dir = os.path.dirname(os.path.abspath(__file__)) | |
| prompt_path = os.path.join(current_dir, 'prompt.yaml') | |
| with open(prompt_path, 'r', encoding='utf-8') as f: | |
| prompt_data = yaml.safe_load(f) | |
| prompt_template = prompt_data['prompt'] | |
| def parse_context_report(content): | |
| """ | |
| AI ์๋ต์์ ์ปจํ ์คํธ ๋ฆฌํฌํธ JSON์ ํ์ฑํ๋ ํจ์ | |
| """ | |
| try: | |
| print(f"ํ์ฑํ ์ปจํ ์ธ ๊ธธ์ด: {len(content)}") | |
| print(f"ํ์ฑํ ์ปจํ ์ธ ์ฒซ 200์: {repr(content[:200])}") | |
| # ํ ์คํธ ์ ์ฒ๋ฆฌ | |
| cleaned_content = content.strip() | |
| # 1. JSON ์ฝ๋ ๋ธ๋ก ์ฐพ๊ธฐ (```json ... ``` ํ์) | |
| json_patterns = [ | |
| r'```json\s*(\{.*?\})\s*```', | |
| r'```\s*(\{.*?\})\s*```', | |
| r'```json\s*(.*?)\s*```', | |
| r'```\s*(.*?)\s*```' | |
| ] | |
| for pattern in json_patterns: | |
| json_match = re.search(pattern, cleaned_content, re.DOTALL) | |
| if json_match: | |
| json_str = json_match.group(1).strip() | |
| print(f"JSON ๋ธ๋ก ๋ฐ๊ฒฌ: {repr(json_str[:100])}") | |
| # JSON ๋ฌธ์์ด ์ ๋ฆฌ | |
| json_str = re.sub(r'\n\s*', ' ', json_str) | |
| json_str = re.sub(r',\s*}', '}', json_str) | |
| json_str = re.sub(r',\s*]', ']', json_str) | |
| try: | |
| parsed_json = json.loads(json_str) | |
| if isinstance(parsed_json, dict) and 'company_profile' in parsed_json: | |
| return parsed_json | |
| except json.JSONDecodeError as e: | |
| print(f"JSON ๋ธ๋ก ํ์ฑ ์คํจ: {e}") | |
| # 2. ์ค๊ดํธ๋ก ๋๋ฌ์ธ์ธ JSON ์ฐพ๊ธฐ | |
| brace_patterns = [ | |
| r'\{.*?\}' | |
| ] | |
| for pattern in brace_patterns: | |
| brace_match = re.search(pattern, cleaned_content, re.DOTALL) | |
| if brace_match: | |
| json_str = brace_match.group(0).strip() | |
| print(f"์ค๊ดํธ ๋ธ๋ก ๋ฐ๊ฒฌ: {repr(json_str[:100])}") | |
| # JSON ๋ฌธ์์ด ์ ๋ฆฌ | |
| json_str = re.sub(r'\n\s*', ' ', json_str) | |
| json_str = re.sub(r',\s*}', '}', json_str) | |
| json_str = re.sub(r',\s*]', ']', json_str) | |
| try: | |
| parsed_json = json.loads(json_str) | |
| if isinstance(parsed_json, dict) and 'company_profile' in parsed_json: | |
| return parsed_json | |
| except json.JSONDecodeError as e: | |
| print(f"์ค๊ดํธ ๋ธ๋ก ํ์ฑ ์คํจ: {e}") | |
| # 3. ์ ์ฒด ํ ์คํธ๋ฅผ JSON์ผ๋ก ํ์ฑ ์๋ | |
| try: | |
| # ์ฝ๋ ๋ธ๋ก ๋ง์ปค ์ ๊ฑฐ | |
| if cleaned_content.startswith('```'): | |
| lines = cleaned_content.split('\n') | |
| start_idx = 1 if lines[0].startswith('```') else 0 | |
| end_idx = len(lines) | |
| for i in range(len(lines)-1, -1, -1): | |
| if lines[i].strip() == '```': | |
| end_idx = i | |
| break | |
| cleaned_content = '\n'.join(lines[start_idx:end_idx]) | |
| cleaned_content = cleaned_content.strip() | |
| parsed_json = json.loads(cleaned_content) | |
| if isinstance(parsed_json, dict) and 'company_profile' in parsed_json: | |
| return parsed_json | |
| except json.JSONDecodeError as e: | |
| print(f"์ ์ฒด JSON ํ์ฑ ์คํจ: {e}") | |
| # 4. ๊ธฐ๋ณธ ๊ตฌ์กฐ ๋ฐํ (ํ์ฑ ์คํจ ์) | |
| print("JSON ํ์ฑ ์คํจ, ๊ธฐ๋ณธ ๊ตฌ์กฐ ๋ฐํ") | |
| return { | |
| "company_profile": { | |
| "name": "ํ์ฑ ์คํจ", | |
| "vision_mission": "์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.", | |
| "core_values": ["์ ๋ณด ์์"], | |
| "talent_philosophy": "์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.", | |
| "recent_news_summary": "์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.", | |
| "main_products_services": ["์ ๋ณด ์์"] | |
| }, | |
| "position_analysis": { | |
| "role_summary": "์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.", | |
| "required_skills": { | |
| "hard": ["์ ๋ณด ์์"], | |
| "soft": ["์ ๋ณด ์์"] | |
| }, | |
| "keywords": ["์ ๋ณด ์์"] | |
| }, | |
| "industry_context": { | |
| "trends": ["์ ๋ณด ์์"], | |
| "competitors": ["์ ๋ณด ์์"] | |
| } | |
| } | |
| except Exception as e: | |
| print(f"์ปจํ ์คํธ ๋ฆฌํฌํธ ํ์ฑ ์ ์ฒด ์ค๋ฅ: {e}") | |
| print(f"ํ์ฑ ์คํจํ ์ปจํ ์ธ : {repr(content)}") | |
| return { | |
| "company_profile": { | |
| "name": "์ค๋ฅ ๋ฐ์", | |
| "vision_mission": f"ํ์ฑ ์ค๋ฅ: {str(e)}", | |
| "core_values": ["์ค๋ฅ"], | |
| "talent_philosophy": f"ํ์ฑ ์ค๋ฅ: {str(e)}", | |
| "recent_news_summary": f"ํ์ฑ ์ค๋ฅ: {str(e)}", | |
| "main_products_services": ["์ค๋ฅ"] | |
| }, | |
| "position_analysis": { | |
| "role_summary": f"ํ์ฑ ์ค๋ฅ: {str(e)}", | |
| "required_skills": { | |
| "hard": ["์ค๋ฅ"], | |
| "soft": ["์ค๋ฅ"] | |
| }, | |
| "keywords": ["์ค๋ฅ"] | |
| }, | |
| "industry_context": { | |
| "trends": ["์ค๋ฅ"], | |
| "competitors": ["์ค๋ฅ"] | |
| } | |
| } | |
| def generate_context_report(job_title, company_name, experience_level): | |
| """ | |
| OpenAI API๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ์ปจํ ์คํธ ๋ฆฌํฌํธ๋ฅผ ์์ฑํ๋ ํจ์ | |
| """ | |
| try: | |
| if not job_title or not company_name or not experience_level: | |
| return "์ง๋ฌด, ํ์ฌ๋ช , ๊ฒฝ๋ ฅ ์์ค์ ๋ชจ๋ ์ ๋ ฅํด์ฃผ์ธ์.", {} | |
| # ํ๋กฌํํธ ์์ฑ | |
| prompt = prompt_template.format( | |
| job_title=job_title, | |
| company_name=company_name, | |
| experience_level=experience_level | |
| ) | |
| # OpenAI Responses API ํธ์ถ (Web Search Preview ์ฌ์ฉ) | |
| response = client.responses.create( | |
| model="gpt-4o-mini", | |
| tools=[{ | |
| "type": "web_search_preview", | |
| "search_context_size": "high", | |
| }], | |
| input=f"๋น์ ์ ์๊ธฐ์๊ฐ์ ์์ฑ์ ์ํ ๊ธฐ์ ๋ฐ ์ง๋ฌด ๋ถ์ ์ ๋ฌธ๊ฐ์ ๋๋ค. ์น ๊ฒ์์ ํตํด ์ต์ ๊ธฐ์ ์ ๋ณด์ ์ฐ์ ๋ํฅ์ ํ์ธํ๊ณ ์ ํํ JSON ํ์์ผ๋ก ๊ตฌ์กฐํ๋ ์ ๋ณด๋ฅผ ์ ๊ณตํด์ฃผ์ธ์.\n\n{prompt}" | |
| ) | |
| content = response.output_text | |
| print(f"=== AI ์๋ต ์๋ณธ ===") | |
| print(content) | |
| print(f"=== ์ ์ฒด ์๋ต ๊ฐ์ฒด ===") | |
| print(response) | |
| # ์น ๊ฒ์ ์ฐธ๊ณ ๋งํฌ ์ถ๋ ฅ | |
| if hasattr(response, 'web_search_results') and response.web_search_results: | |
| print(f"=== ์ฐธ๊ณ ํ ์น ๊ฒ์ ๋งํฌ ===") | |
| for i, result in enumerate(response.web_search_results, 1): | |
| if hasattr(result, 'url'): | |
| print(f"{i}. {result.url}") | |
| elif hasattr(result, 'link'): | |
| print(f"{i}. {result.link}") | |
| print(f"=== AI ์๋ต ๋ ===") | |
| report_data = parse_context_report(content) | |
| if not report_data or 'company_profile' not in report_data: | |
| return "์ปจํ ์คํธ ๋ฆฌํฌํธ ์์ฑ์ ์คํจํ์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.", {} | |
| # ๊ฒฐ๊ณผ ํฌ๋งทํ | |
| result = f"""## ๐ {company_name} - {job_title} ์ปจํ ์คํธ ๋ฆฌํฌํธ | |
| ### ๐ข **๊ธฐ์ ํ๋กํ** | |
| **๐ฏ ๋น์ & ๋ฏธ์ ** | |
| {report_data['company_profile']['vision_mission']} | |
| **๐ ํต์ฌ ๊ฐ์น** | |
| """ | |
| for i, value in enumerate(report_data['company_profile']['core_values'], 1): | |
| result += f"**{i}.** {value}\n" | |
| result += f""" | |
| **๐ฅ ์ธ์ฌ์** | |
| {report_data['company_profile']['talent_philosophy']} | |
| **๐ฐ ์ต๊ทผ ๋ํฅ** | |
| {report_data['company_profile']['recent_news_summary']} | |
| **๐๏ธ ์ฃผ์ ์ ํ/์๋น์ค** | |
| """ | |
| for i, service in enumerate(report_data['company_profile']['main_products_services'], 1): | |
| result += f"**{i}.** {service}\n" | |
| result += f""" | |
| ### ๐ผ **์ง๋ฌด ๋ถ์** | |
| **๐ ์ญํ ์์ฝ** | |
| {report_data['position_analysis']['role_summary']} | |
| **๐ง ํ์ ์คํฌ** | |
| *ํ๋ ์คํฌ:* | |
| """ | |
| for skill in report_data['position_analysis']['required_skills']['hard']: | |
| result += f"โข {skill}\n" | |
| result += "\n*์ํํธ ์คํฌ:*\n" | |
| for skill in report_data['position_analysis']['required_skills']['soft']: | |
| result += f"โข {skill}\n" | |
| result += f""" | |
| **๐ท๏ธ ํต์ฌ ํค์๋** | |
| """ | |
| for keyword in report_data['position_analysis']['keywords']: | |
| result += f"`{keyword}` " | |
| result += f""" | |
| ### ๐ **์ฐ์ ๋งฅ๋ฝ** | |
| **๐ ์ฃผ์ ํธ๋ ๋** | |
| """ | |
| for i, trend in enumerate(report_data['industry_context']['trends'], 1): | |
| result += f"**{i}.** {trend}\n" | |
| result += f""" | |
| **๐ ์ฃผ์ ๊ฒฝ์์ฌ** | |
| """ | |
| for i, competitor in enumerate(report_data['industry_context']['competitors'], 1): | |
| result += f"**{i}.** {competitor}\n" | |
| result += f""" | |
| --- | |
| **๐ ์ ๋ ฅ ์ ๋ณด:** | |
| - ํ์ฌ: {company_name} | |
| - ์ง๋ฌด: {job_title} | |
| - ๊ฒฝ๋ ฅ: {experience_level} | |
| *๋ณธ ๋ฆฌํฌํธ๋ AI๊ฐ ์์ฑํ ๊ฒ์ผ๋ก, ์ค์ ์ ๋ณด์ ๋ค๋ฅผ ์ ์์ต๋๋ค. ์์์ ์์ฑ ์ ์ฐธ๊ณ ์ฉ์ผ๋ก ํ์ฉํ์ธ์.* | |
| """ | |
| return result, report_data | |
| except Exception as e: | |
| error_msg = f"""## โ ์ค๋ฅ ๋ฐ์ | |
| ์ปจํ ์คํธ ๋ฆฌํฌํธ ์์ฑ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. | |
| **์ค๋ฅ ๋ด์ฉ:** {str(e)} | |
| ๋ค์ ์๋ํด์ฃผ์ธ์. | |
| """ | |
| return error_msg, {} |