kyle8581's picture
.
2b267d0
from openai import OpenAI
from dotenv import load_dotenv
import yaml
import os
import json
import re
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# load prompt
try:
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 file:
prompt = yaml.safe_load(file)["prompt"]
except Exception as e:
print(f"Warning: prompt.yaml λ‘œλ“œ μ‹€νŒ¨. κΈ°λ³Έ ν”„λ‘¬ν”„νŠΈλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. 였λ₯˜: {e}")
prompt = "Question: {question}\nJD: {jd}\nCompany: {company_name}\nExperience: {experience_level}\nGenerate a guide based on this information in markdown table format."
def parse_json_from_response(text: str) -> dict | None:
"""
Markdown μ½”λ“œ 블둝 μ•ˆμ— 포함될 수 μžˆλŠ” JSON λ¬Έμžμ—΄μ„ μΆ”μΆœν•˜κ³  νŒŒμ‹±ν•©λ‹ˆλ‹€.
Deprecated: 이 ν•¨μˆ˜λŠ” JSON νŒŒμ‹±μš©μ΄λ―€λ‘œ guide generationμ—μ„œλŠ” 더 이상 μ‚¬μš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
Args:
text (str): LLM이 λ°˜ν™˜ν•œ 전체 ν…μŠ€νŠΈ 응닡.
Returns:
dict | None: νŒŒμ‹±λœ λ”•μ…”λ„ˆλ¦¬ 객체, λ˜λŠ” μ‹€νŒ¨ μ‹œ None.
"""
if not text:
return None
# ```json ... ``` λ˜λŠ” ``` ... ``` ν˜•μ‹μ˜ μ½”λ“œ λΈ”λ‘μ—μ„œ JSON μΆ”μΆœ
match = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", text)
if match:
json_str = match.group(1)
else:
# μ½”λ“œ 블둝이 μ—†λ‹€λ©΄, 전체 ν…μŠ€νŠΈλ₯Ό JSON으둜 κ°€μ •
json_str = text
try:
return json.loads(json_str)
except json.JSONDecodeError:
# 전체 νŒŒμ‹±μ΄ μ‹€νŒ¨ν•˜λ©΄, 첫 '{'와 λ§ˆμ§€λ§‰ '}'λ₯Ό κΈ°μ€€μœΌλ‘œ λ‹€μ‹œ μ‹œλ„
start_index = json_str.find('{')
end_index = json_str.rfind('}')
if start_index != -1 and end_index != -1 and start_index < end_index:
potential_json = json_str[start_index:end_index+1]
try:
return json.loads(potential_json)
except json.JSONDecodeError:
pass # μ΄λ§ˆμ €λ„ μ‹€νŒ¨ν•˜λ©΄ κ·Έλƒ₯ None λ°˜ν™˜
return None
def parse_markdown_table_from_response(text: str) -> str:
"""
LLM μ‘λ‹΅μ—μ„œ λ§ˆν¬λ‹€μš΄ ν…Œμ΄λΈ”μ„ μΆ”μΆœν•˜μ—¬ λ°˜ν™˜ν•©λ‹ˆλ‹€.
Args:
text (str): LLM이 λ°˜ν™˜ν•œ 전체 ν…μŠ€νŠΈ 응닡.
Returns:
str: μΆ”μΆœλœ λ§ˆν¬λ‹€μš΄ ν…Œμ΄λΈ” λ¬Έμžμ—΄, μ‹€νŒ¨ μ‹œ 전체 ν…μŠ€νŠΈ λ°˜ν™˜
"""
if not text:
return ""
# λ§ˆν¬λ‹€μš΄ μ½”λ“œ λΈ”λ‘μ—μ„œ ν…Œμ΄λΈ” μΆ”μΆœ μ‹œλ„
markdown_match = re.search(r"```(?:markdown)?\s*([\s\S]*?)\s*```", text)
if markdown_match:
return markdown_match.group(1).strip()
# ν…Œμ΄λΈ” νŒ¨ν„΄ 직접 μ°ΎκΈ° (| ... | ... | ν˜•νƒœ)
lines = text.split('\n')
table_lines = []
in_table = False
for line in lines:
line = line.strip()
if '|' in line and ('단계' in line or '---' in line or 'β‘ ' in line):
in_table = True
table_lines.append(line)
elif in_table and '|' in line:
table_lines.append(line)
elif in_table and not line:
# 빈 쀄이면 ν…Œμ΄λΈ” 끝
break
if table_lines:
return '\n'.join(table_lines)
# ν…Œμ΄λΈ”μ„ μ°Ύμ§€ λͺ»ν–ˆμœΌλ©΄ 전체 ν…μŠ€νŠΈ λ°˜ν™˜
return text.strip()
def generate_guide(question, jd, company_name, experience_level):
"""
μžκΈ°μ†Œκ°œμ„œ λ¬Έν•­ κ°€μ΄λ“œλ₯Ό μƒμ„±ν•˜κ³ , λ§ˆν¬λ‹€μš΄ ν…Œμ΄λΈ”κ³Ό 전체 응닡 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜
"""
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt.format(question=question, jd=jd, company_name=company_name, experience_level=experience_level)}],
# response_format을 μ œκ±°ν•˜μ—¬ 일반 ν…μŠ€νŠΈ 응닡을 λ°›μŒ
)
# λ§ˆν¬λ‹€μš΄ ν…Œμ΄λΈ” νŒŒμ‹±
guide_content = parse_markdown_table_from_response(response.choices[0].message.content)
# ν˜Έν™˜μ„±μ„ μœ„ν•΄ λ”•μ…”λ„ˆλ¦¬ ν˜•νƒœλ‘œ λ°˜ν™˜
guide_dict = {"guide": guide_content}
return guide_dict, response
except Exception as e:
print(f"κ°€μ΄λ“œ 생성 λ˜λŠ” νŒŒμ‹± 쀑 였λ₯˜ λ°œμƒ: {e}")
return {"error": f"Failed to generate or parse guide: {str(e)}", "guide": ""}, None
if __name__ == "__main__":
example_input = {
"question": "μ‚Όμ„±μ „μžλ₯Ό μ§€μ›ν•œ μ΄μœ μ™€ μž…μ‚¬ ν›„ 이루고 싢은 κΏˆμ„ κΈ°μˆ ν•˜μ‹œμ˜€.",
"jd": "μ‚Όμ„±μ „μžλŠ” 세계적인 기술 κΈ°μ—…μœΌλ‘œ, λ‹€μ–‘ν•œ λΆ„μ•Όμ—μ„œ 선도적인 κΈ°μˆ μ„ κ°œλ°œν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν”„λ‘ νŠΈμ—”λ“œ 개발자둜 μž…μ‚¬ν•˜λ©΄ λ‹€μ–‘ν•œ ν”„λ‘œμ νŠΈμ— μ°Έμ—¬ν•˜λ©°, μ΅œμ‹  κΈ°μˆ μ„ μ μš©ν•˜μ—¬ μ‚¬μš©μž κ²½ν—˜μ„ κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.",
"company_name": "μ‚Όμ„±μ „μž",
"experience_level": "μ‹ μž…"
}
guide_dict, _ = generate_guide(**example_input)
print("Guide content:")
print(guide_dict.get("guide", "No guide generated"))