kyle8581's picture
.
2b267d0
import os
import random
import datetime
import json
import multiprocessing
import sys
from tqdm import tqdm
# μƒμœ„ λ””λ ‰ν† λ¦¬μ˜ utils.pyλ₯Ό importν•˜κΈ° μœ„ν•΄ 경둜 μΆ”κ°€
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from utils import track_api_cost
from llm_functions import generate_guide
# ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ ν™˜κ²½ λ³€μˆ˜ λ‘œλ“œ (ν•„μš”μ‹œ)
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
# 예제 데이터
example_companies = ["μ‚Όμ„±μ „μž", "카카였", "넀이버", "쿠팑", "ν† μŠ€", "ν˜„λŒ€μžλ™μ°¨", "CJμ œμΌμ œλ‹Ή", "ν•˜μ΄λΈŒ"]
example_jobs_jds = {
"λ°±μ—”λ“œ 개발자": "Spring Boot, JPA, MySQL κ²½ν—˜μž. MSA ν™˜κ²½ κ²½ν—˜ μš°λŒ€. ν΄λΌμš°λ“œ(AWS) ν™˜κ²½ 배포 및 운영 κ²½ν—˜μž.",
"ν”„λ‘ νŠΈμ—”λ“œ 개발자": "React, TypeScript, Redux μ‚¬μš©. λ°˜μ‘ν˜• μ›Ή 개발 κ²½ν—˜ ν•„μˆ˜. UI/UX에 λŒ€ν•œ 이해도가 높은 λΆ„.",
"데이터 뢄석가": "SQL, Python(Pandas, Scikit-learn) ν™œμš© λŠ₯λ ₯. 톡계적 지식과 데이터 μ‹œκ°ν™”(Tableau λ“±) λŠ₯λ ₯.",
"ν”„λ‘œλ•νŠΈ λ§€λ‹ˆμ €(PM)": "IT ν”„λ‘œλ•νŠΈ 기획 및 관리 κ²½ν—˜. μ‚¬μš©μž μŠ€ν† λ¦¬ μž‘μ„±, 백둜그 관리. 데이터 기반 μ˜μ‚¬κ²°μ • λŠ₯λ ₯.",
"λ§ˆμΌ€ν„°": "λ””μ§€ν„Έ λ§ˆμΌ€νŒ…(SA, DA, SEO) κ²½ν—˜. μ½˜ν…μΈ  기획 및 μ œμž‘, μ„±κ³Ό 뢄석. SNS 채널 운영 κ²½ν—˜."
}
example_questions = {
"지원동기": "{company_name}에 μ§€μ›ν•œ 동기에 λŒ€ν•΄ κΈ°μˆ ν•΄μ£Όμ‹­μ‹œμ˜€.",
"μ„±μž₯κ³Όμ •": "본인의 μ„±μž₯과정을 κ°„λž΅νžˆ κΈ°μˆ ν•˜λ˜ ν˜„μž¬μ˜ μžμ‹ μ—κ²Œ κ°€μž₯ 큰 영ν–₯을 끼친 사건, 인물 등을 ν¬ν•¨ν•˜μ—¬ κΈ°μˆ ν•΄μ£Όμ‹­μ‹œμ˜€.",
"μ§λ¬΄μ—­λŸ‰": "{job_title} 직무 μˆ˜ν–‰μ— ν•„μš”ν•œ μ—­λŸ‰μ€ 무엇이라고 μƒκ°ν•˜λ©°, 이λ₯Ό κ°–μΆ”κΈ° μœ„ν•΄ μ–΄λ–€ λ…Έλ ₯을 ν•΄μ™”λŠ”μ§€ κΈ°μˆ ν•΄μ£Όμ‹­μ‹œμ˜€.",
"μž…μ‚¬ν›„ν¬λΆ€": "μž…μ‚¬ ν›„ 10λ…„ λ™μ•ˆμ˜ νšŒμ‚¬μƒν™œ μ‹œλ‚˜λ¦¬μ˜€μ™€ 그것을 μΆ”κ΅¬ν•˜λŠ” 이유λ₯Ό κΈ°μˆ ν•΄μ£Όμ‹­μ‹œμ˜€."
}
experience_levels = ["μ‹ μž…", "κ²½λ ₯", "인턴"]
NUM_TESTS = 100
NUM_PROCESSES = 10
MODEL_NAME = "gpt-4o-mini"
def run_test(test_input_with_id):
"""κ°œλ³„ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό μ‹€ν–‰ν•˜λŠ” μ›Œμ»€ ν•¨μˆ˜"""
test_id, test_input = test_input_with_id
total_cost = 0
error_message = ""
status = "βœ… Success"
try:
parsed_guide, response = generate_guide(**test_input)
if response and hasattr(response, 'usage'):
total_cost = track_api_cost(response, MODEL_NAME, None)
if "error" in parsed_guide or not parsed_guide:
status = "❌ Failure"
error_message = str(parsed_guide.get("error", "Unknown failure"))
return {
"id": test_id,
"input": test_input,
"parsed_result": parsed_guide,
"error": error_message,
"cost": total_cost,
"status": status,
}
except Exception as e:
return {
"id": test_id,
"input": test_input,
"parsed_result": {},
"error": f"Exception: {str(e)}",
"cost": total_cost,
"status": "❌ Error"
}
def main():
"""ν…ŒμŠ€νŠΈλ₯Ό μ€€λΉ„, μ‹€ν–‰ν•˜κ³  λ³΄κ³ μ„œλ₯Ό μƒμ„±ν•˜λŠ” 메인 ν•¨μˆ˜"""
print(f"총 {NUM_TESTS}개의 ν…ŒμŠ€νŠΈλ₯Ό {NUM_PROCESSES}개 ν”„λ‘œμ„ΈμŠ€λ‘œ 병렬 μ‹€ν–‰ν•©λ‹ˆλ‹€...")
test_inputs = []
for i in range(NUM_TESTS):
company = random.choice(example_companies)
job_title, jd = random.choice(list(example_jobs_jds.items()))
question_type, question_template = random.choice(list(example_questions.items()))
question = question_template.format(company_name=company, job_title=job_title)
experience = random.choice(experience_levels)
test_input = {
"company_name": company,
"jd": jd,
"question": question,
"experience_level": experience
}
test_inputs.append((i + 1, test_input))
results = []
with multiprocessing.Pool(processes=NUM_PROCESSES) as pool:
with tqdm(total=NUM_TESTS, desc="κ°€μ΄λ“œ 생성 ν…ŒμŠ€νŠΈ") as pbar:
for result in pool.imap_unordered(run_test, test_inputs):
results.append(result)
pbar.update()
results.sort(key=lambda x: x['id'])
print("λͺ¨λ“  ν…ŒμŠ€νŠΈκ°€ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
now = datetime.datetime.now()
report_filename = f"guide_generation_report_{now.strftime('%Y%m%d_%H%M%S')}.html"
failure_count = sum(1 for r in results if "Success" not in r["status"])
total_cost = sum(r['cost'] for r in results)
failure_rate = (failure_count / NUM_TESTS) * 100 if NUM_TESTS > 0 else 0
html_template = """
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><title>κ°€μ΄λ“œ 생성 ν…ŒμŠ€νŠΈ λ³΄κ³ μ„œ</title>
<style>body{{font-family:sans-serif;margin:20px;}} h1,h2{{text-align:center;}} .summary{{border:1px solid #ddd;padding:20px;margin-bottom:20px;}} table{{width:100%;border-collapse:collapse;}} th,td{{border:1px solid #ddd;padding:8px;text-align:left;vertical-align:top;}} th{{background-color:#f2f2f2;}} .status-success{{color:green;font-weight:bold;}} .status-failure{{color:red;font-weight:bold;}} pre{{white-space:pre-wrap;word-wrap:break-word;background-color:#f9f9f9;padding:10px;border:1px solid #ddd;}} .container{{max-width:1400px;margin:auto;}}</style>
</head><body><div class="container"><h1>κ°€μ΄λ“œ 생성 ν…ŒμŠ€νŠΈ λ³΄κ³ μ„œ</h1><div class="summary"><h2>μš”μ•½</h2><p><strong>ν…ŒμŠ€νŠΈ μ‹œκ°„:</strong> {now}</p><p><strong>총 ν…ŒμŠ€νŠΈ 수:</strong> {total_tests}</p><p><strong>성곡:</strong> {success_count}</p><p><strong>μ‹€νŒ¨/μ—λŸ¬:</strong> {failure_count}</p><p><strong>μ‹€νŒ¨μœ¨:</strong> <span class="{status_class}">{failure_rate:.2f}%</span></p><p><strong>총 μ˜ˆμƒ λΉ„μš©:</strong> ${total_cost:.6f}</p></div>
<h2>상세 κ²°κ³Ό</h2><table><thead><tr><th>ID</th><th>μž…λ ₯ (Input)</th><th>νŒŒμ‹± κ²°κ³Ό (Parsed)</th><th>μ—λŸ¬</th><th>λΉ„μš©</th><th>μƒνƒœ</th></tr></thead><tbody>{table_rows}</tbody></table></div></body></html>
"""
table_rows_html = ""
for res in results:
status_class = "status-success" if "Success" in res["status"] else "status-failure"
table_rows_html += f"""
<tr>
<td>{res['id']}</td>
<td><pre>{json.dumps(res['input'], indent=2, ensure_ascii=False)}</pre></td>
<td><pre>{json.dumps(res['parsed_result'], indent=2, ensure_ascii=False)}</pre></td>
<td><pre>{res['error']}</pre></td>
<td>${res['cost']:.6f}</td>
<td class="{status_class}">{res['status']}</td>
</tr>
"""
final_html = html_template.format(
now=now.strftime('%Y-%m-%d %H:%M:%S'),
total_tests=NUM_TESTS,
success_count=NUM_TESTS - failure_count,
failure_count=failure_count,
status_class="status-success" if failure_rate < 10 else "status-failure",
failure_rate=failure_rate,
total_cost=total_cost,
table_rows=table_rows_html
)
with open(report_filename, "w", encoding="utf-8") as f:
f.write(final_html)
print(f"'{report_filename}' 파일둜 λ³΄κ³ μ„œκ°€ μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
print(f"총 μ˜ˆμƒ λΉ„μš©: ${total_cost:.6f}")
if __name__ == "__main__":
main()