File size: 4,014 Bytes
4c3c323
 
 
 
 
6e596d5
 
4c3c323
 
6e596d5
4c3c323
 
 
 
 
 
6e596d5
4c3c323
 
6e596d5
4c3c323
6e596d5
 
 
 
4c3c323
6e596d5
4c3c323
6e596d5
4c3c323
 
 
 
6e596d5
 
4c3c323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e596d5
4c3c323
 
6e596d5
4c3c323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e596d5
4c3c323
 
6e596d5
4c3c323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import gradio as gr
import fitz  # PyMuPDF
import openai
import re
import os

# ✅ 使用 Hugging Face Secrets 管理 API 金鑰
openai.api_key = os.environ.get("OPENAI_API_KEY")

# --- 清理文字 ---
def clean_text(text):
    text = re.sub(r'^\s*\d+\s*$', '', text, flags=re.MULTILINE)
    text = re.sub(r'\n\s*\n+', '\n\n', text)
    text = re.sub(r'[ \t]+', ' ', text)
    return text.strip()

# --- 改進版:區塊式擷取 PDF 文字 + 座標排序 ---
def extract_text_from_pdf(file):
    doc = fitz.open(file.name)
    text_blocks = []
    for page in doc:
        blocks = page.get_text("blocks")  # 回傳每段區塊含座標
        blocks = sorted(blocks, key=lambda b: (b[1], b[0]))  # 先依 y,再依 x 排序
        for b in blocks:
            text_blocks.append(b[4])
    doc.close()
    return clean_text("\n".join(text_blocks))

# --- GPT 履歷分析(STAR 法則)---
def analyze_resume(resume_text):
    prompt = f"""
你是一位專業的履歷健檢與職涯輔導顧問,請協助我以下幾件事:

注意:這份履歷是由 PDF 擷取而來,可能因版面問題導致部分文字順序略有錯亂。請你盡量根據語意邏輯判斷內容。

1. 根據下方履歷內容,幫我整理出:
   - 學歷背景
   - 技能與工具
   - 工作經歷與專案經歷

2. 對於每一段經歷,請用 STAR 法則整理:
   - S(情境)
   - T(任務)
   - A(行動)
   - R(成果)

3. 指出這份履歷的優勢,以及可以優化的建議

4. 推薦幾個可能適合的職缺方向(例如:前端工程師、資料分析師、產品實習生等)

這是履歷內容:
------------------------
{resume_text}
------------------------

請以條列式輸出,分段清楚。
"""
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "你是一位履歷健檢顧問"},
            {"role": "user", "content": prompt}
        ],
        temperature=0.7,
        max_tokens=1500
    )
    content = response['choices'][0]['message']['content']
    return content.replace("**", "").replace("* ", "• ").replace("*", "").strip()

# --- GPT 自傳撰寫 ---
def generate_autobiography(resume_text):
    prompt = f"""
這是從 PDF 擷取的履歷文字,順序可能略有錯亂。請盡量根據語意整理,幫我撰寫一段約 300 字的個人自傳。口吻自然、自信,強調個人特質、學習歷程與職涯目標,可作為履歷中的「自我介紹」使用:

履歷內容:
------------------------
{resume_text}
------------------------
"""
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "你是一位履歷與自傳輔導顧問"},
            {"role": "user", "content": prompt}
        ],
        temperature=0.7,
        max_tokens=800
    )
    return response['choices'][0]['message']['content'].strip()

# --- Gradio UI ---
with gr.Blocks(title="求職小幫手 AI") as demo:
    gr.Markdown("## 🧑‍💼 求職小幫手 AI\n上傳履歷 PDF,我們幫你分析亮點並撰寫個人自傳!")

    with gr.Row():
        pdf_input = gr.File(label="📄 上傳履歷 PDF", file_types=[".pdf"])
        extract_btn = gr.Button("⬇️ 擷取與清理內容")

    resume_textbox = gr.Textbox(label="📄 擷取後的履歷純文字", lines=20, interactive=False)

    with gr.Row():
        analyze_btn = gr.Button("🧠 分析履歷(STAR 法則)")
        bio_btn = gr.Button("📝 撰寫個人自傳")

    analysis_output = gr.Textbox(label="✨ GPT 履歷分析結果", lines=25)
    bio_output = gr.Textbox(label="✍️ GPT 產生的個人自傳", lines=15)

    extract_btn.click(fn=extract_text_from_pdf, inputs=pdf_input, outputs=resume_textbox)
    analyze_btn.click(fn=analyze_resume, inputs=resume_textbox, outputs=analysis_output)
    bio_btn.click(fn=generate_autobiography, inputs=resume_textbox, outputs=bio_output)

demo.launch()