Xây dựng công cụ phân tích CV bằng AI sử dụng GenAI

Nội dung

    Một dự án thực tiễn về Trí tuệ Nhân tạo Thế hệ mới (GenAI) giúp cải thiện CV và củng cố hồ sơ năng lực của bạn. Mộtcông cụ phản hồi CV bằng AI , xem xét CV như một nhà tuyển dụng, chỉ ra những điểm yếu và đề xuất các cải tiến.

    Xây dựng công cụ phân tích CV bằng AI sử dụng GenAI

    Xây dựng công cụ phân tích CV bằng AI sử dụng GenAI

    bạn có thểsử dụng nó cho sơ yếu lý lịch của mình,
    bạn có thểmở rộng nó,
    và bạn có thểđưa nó vào sơ yếu lý lịch của mình như một dự án GenAI.

    Đây là một cơ hội thắng lợi cực lớn dành cho bạn, miễn là bạn làm theo hướng dẫn này.

    Chúng ta sẽ cùng nhau xây dựng nó.

    Xây dựng công cụ phân tích CV bằng AI sử dụng GenAI

    Trước khi viết bất kỳ đoạn mã nào, hãy thành thật với chính mình.

    Hầu hết chúng ta đều có:

    • Đã nộp đơn xin việc vào hàng chục vị trínhưng không nhận được phản hồi nào.
    • Cập nhật sơ yếu lý lịch một cách mù quáng
    • Tôi đã sao chép các mẫu với hy vọng chúng sẽ hoạt động.

    Và sau tất cả, tôi vẫn không nhận được phản hồi thực sự nào.

    Vấn đề không phải là kỹ năng. Vấn đề làphản hồi.

    Các nhà tuyển dụng không nói cho bạn biết vấn đề là gì.
    Hệ thống ATS sẽ âm thầm từ chối bạn.

    Vì vậy, thay vì đoán mò, chúng tôi xây dựng một công cụ chobiết chính xác cần sửa chữa ở đâu.

    Khi dự án này kết thúc, chúng ta sẽ có một công cụ:

    • Chấp nhận hồ sơ xin việc dạng PDF.
    • Trích xuất nội dung
    • Sử dụng mô hình GenAI để phân tích giống như một nhà tuyển dụng.
    • Trả vềphản hồi có cấu trúc, có thể thực hiện được, chứ không phải lời khuyên chung chung.

    Đặc trưng:

    • Những điểm mạnh cần giữ lại
    • Những điểm yếu cần cải thiện
    • Các bộ phận bị thiếu
    • Sự thân thiện của ATS
    • Các bước tiếp theo cần thực hiện

    Đây không phải là một dự án ngẫu nhiên.
    Đây là mộtcông cụ đánh giá thông minh hồ sơ xin việc.

    Bước 1: Cấu trúc dự án

    Tạo một dự án Python mới (tôi đang dùng PyCharm, nhưng bất kỳ trình soạn thảo nào cũng được).

    Cấu trúc thư mục cuối cùng của chúng ta sẽ trông như thế này:

    resume_ai_analyzer/ 
    
    ├── app.py 
    ├── resume_parser.py 
    ├── feedback_engine.py 
    ├── prompts.py 
    ├── requirements.txt 
    └── .env

    Mỗi tập tin đều cómột trách nhiệm rõ ràng:

    • app.py→ Giao diện người dùng (Streamlit)
    • resume_parser.py→ Trích xuất văn bản từ bản PDF sơ yếu lý lịch
    • feedback_engine.py→ Liên hệ với LLM (Bộ phận GenAI)
    • prompts.py→ Kỹ thuật nhanh chóng
    • .env→ Khóa API (bảo mật) (Chúng tôi sẽ sử dụng khóa API miễn phí)

    Sự phân tách này rất quan trọng.

    Mở cửa sổ dòng lệnh và cài đặt các thư viện cần thiết:

    pip install streamlit pymupdf python-dotenv groq

    Bây giờ hãy thêm chúng vàorequirements.txt:

    streamlit 
    pymupdf 
    python-dotenv 
    groq

    Tại sao lại là những thư viện này?

    • Streamlit→ xây dựng giao diện người dùng nhanh chóng
    • PyMuPDF→ trích xuất văn bản từ sơ yếu lý lịch dạng PDF
    • python-dotenv→ tải các biến môi trường một cách an toàn
    • Groq→ chạy các mô hình LLaMA thông qua API

    Tạo một tệp có tên.envvà thêm nội dung sau vào đó:

    GROF_API_KEY =your_groq_api_key_here

    Bạn có thể tạo Khóa API của mình tại đây:Khóa API Groq

    Hoàn toàn miễn phí!

    Vì sao điều này lại quan trọng:

    • Không bao giờ mã hóa cứng khóa API.
    • Đảm bảo an toàn cho dự án của bạn.

    Hãy cùng định nghĩacáchtrí tuệ nhân tạo nên suy nghĩ.

    Tạo nênprompts.py:

    RESUME_FEEDBACK_PROMPT = """ 
    Bạn là một chuyên gia tuyển dụng kỹ thuật và đánh giá sơ yếu lý lịch. 
    
    Hãy phân tích sơ yếu lý lịch bên dưới và cung cấp phản hồi theo định dạng có cấu trúc sau: 
    
    1. Tóm tắt tổng quan (2-3 dòng) 
    2. Điểm mạnh 
    3. Điểm yếu 
    4. Các phần thiếu hoặc chưa được thể hiện đầy đủ 
    5. Cải thiện gạch đầu dòng (viết lại 2 gạch đầu dòng yếu) 
    6. Điểm thân thiện với hệ thống ATS (1-10) kèm lý do 
    7. Đề xuất hành động cuối cùng 
    
    Nội dung sơ yếu lý lịch: 
    ---------------- 
    {resume_text} 
    """
    

    Lý do tại sao lời nhắc này hiệu quả

    • Chúng tôichỉ định một vai trò(“chuyên viên tuyển dụng”).
    • Chúng taép buộc cấu trúc
    • Kết quả đầu ra trở nên dễ dự đoán và dễ đọc.
    • Đây là kỹ thuật xử lý sự cố nhanh chóng, chứ không chỉ đơn thuần là nhắc nhở.

    Bước 5: Trích xuất văn bản từ PDF sơ yếu lý lịch

    Xây dựng công cụ phân tích CV bằng AI sử dụng GenAI

    Bây giờ chúng ta hãy trích xuất văn bản từ bản lý lịch đã tải lên.

    Tạo nênresume_parser.py:

    import fitz   # PyMuPDF 
    
    def  extract_text_from_pdf ( uploaded_file ): 
        """ 
        Trích xuất văn bản từ sơ yếu lý lịch PDF đã tải lên. 
        """
    
         text = "" 
    
        # Mở PDF từ luồng trong bộ nhớ
         pdf_document = fitz.open ( stream 
            =uploaded_file.read(), 
            filetype= "pdf"
         ) 
    
        # Lặp qua từng trang 
        for page in pdf_document: 
            text += page.get_text() 
    
        return text.strip()

    Chuyện gì đang xảy ra ở đây vậy?

    • Streamlit tải các tệpvào bộ nhớ, chứ không phải dưới dạng đường dẫn tệp.
    • PyMuPDF đọc từng trang của tệp PDF.
    • Chúng tôi trích xuất văn bản dễ đọc (không phải hình ảnh)
    • Văn bản này trở thành dữ liệu đầu vào cho trí tuệ nhân tạo (AI).

    Đây chính là lúc GenAI phát huy tác dụng.

    Tạo nênfeedback_engine.py:

    import os 
    from dotenv import load_dotenv from groq import Groq 
    from prompts import RESUME_FEEDBACK_PROMPT # Tải các biến môi trường load_dotenv () # Khởi tạo client Groq client = Groq(api_key=os.getenv( "GROQ_API_KEY" )) def generate_feedback ( resume_text ): """     Gửi văn bản sơ yếu lý lịch đến LLaMA và trả về phản hồi có cấu trúc.     """     prompt = RESUME_FEEDBACK_PROMPT. format (         resume_text=resume_text     )     response = client.chat.completions.create(         model= "llama-3.1-8b-instant" ,         messages=[             { "role" : "system" , "content" : "Bạn là chuyên gia tuyển dụng kỹ thuật."             },             { "role" : "user" , "content" : prompt             }         ],         temperature= 0.4 ,         max_tokens= 800     ) return response.choices[ 0 ].message.content
     

    Giải thích các quyết định quan trọng

    • Nhiệt độ thấp (0,4)→ phản hồi nhất quán, giống như của nhà tuyển dụng
    • Câu hỏi được cấu trúc hợp lý→ kết quả chất lượng cao
    • Đây là cách các hệ thống GenAI thực sự được kết nối.

    Bước 7: Giao diện người dùng Streamlit (Tổng hợp tất cả các thành phần)

    Giờ đây chúng ta kết nối mọi thứ lại với nhau.

    Tạo nênapp.py:

    import streamlit as st 
    from resume_parser import extract_text_from_pdf 
    from feedback_engine import generate_feedback 
    
    # 1. Cấu hình Trang (Phải là trang đầu tiên)
     st.set_page_config( 
        page_title= "ResumeAI - Phản hồi Chuyên nghiệp" , 
        page_icon= "🚀" , 
        layout= "centered"
     ) 
    
    # 2. Cải tiến Giao diện Người dùng Hiện đại (CSS)
     st.markdown( """ 
    <style> 
        /* Nhập Phông chữ Google: Inter */ 
        @import url('//fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap'); 
    
        /* Cài đặt Toàn cầu */ 
        html, body, [class*="css"] { 
            font-family: 'Inter', sans-serif; 
        } 
    
        /* Nền Gradient Tối Hiện đại */ 
        .stApp { 
            background: radial-gradient(circle at 50% -20%, #2e1065, #0f172a 40%, #020617 100%); 
            color: #f8fafc; 
        } 
    
        /* Văn bản tiêu đề chuyển sắc */ 
        .gradient-text { 
            background: linear-gradient(90deg, #818cf8 0%, #c084fc 50%, #f472b6 100%); 
            -webkit-background-clip: text; 
            -webkit-text-fill-color: transparent; 
            font-weight: 700; 
            font-size: 3rem; 
            text-align: center; 
            letter-spacing: -1px; 
        } 
    
        /* Kiểu phụ đề */ 
        .subtitle { 
            color: #94a3b8; 
            text-align: center; 
            font-size: 1.1rem; 
            margin-bottom: 2.5rem; 
            font-weight: 300; 
        } 
    
        /* Thẻ Glassmorphism */ 
        .glass-card { 
            background: rgba(30, 41, 59, 0.4); 
            backdrop-filter: blur(12px); 
            -webkit-backdrop-filter: blur(12px); 
            border: 1px solid rgba(255, 255, 255, 0.08); 
            border-radius: 24px; 
            padding: 2.5rem; 
            box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3); 
            margin-bottom: 2rem; 
        } 
    
        /* Khu vực tải lên tập tin được định kiểu */ 
        [data-testid="stFileUploader"] section { 
            background-color: rgba(255, 255, 255, 0.03); 
            border: 1px dashed #64748b; 
            border-radius: 12px; 
            padding: 1rem; 
        } 
    
        /* Định kiểu nút hiện đại */ 
        .stButton > button { 
            background: linear-gradient(92deg, #6366f1 0%, #8b5cf6 100%); 
            màu: trắng; 
            độ đậm chữ: 600;
            border: none; 
            padding: 0.75rem 1.5rem; 
            border-radius: 12px; 
            width: 100%; 
            transition: all 0.3s ease; 
            box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3); 
            text-transform: uppercase; 
            letter-spacing: 0.5px; 
            font-size: 0.9rem; 
        } 
        .stButton > button:hover { 
            transform: translateY(-2px); 
            box-shadow: 0 8px 25px rgba(99, 102, 241, 0.5); 
        } 
    
        /* Hoạt ảnh kết quả & Khung */ 
        @keyframes fadeIn { 
            from { opacity: 0; transform: translateY(10px); } 
            to { opacity: 1; transform: translateY(0); } } 
        } 
        .feedback-container { 
            animation: fadeIn 0.8s ease-out; 
            background: rgba(15, 23, 42, 0.6); 
            border-left: 4px solid #8b5cf6; 
            padding: 2rem; 
            border-radius: 12px; 
            margin-top: 2rem; 
        } 
        .feedback-header { 
            font-size: 1.2rem; 
            font-weight: 600; 
            color: #e2e8f0; 
            margin-bottom: 1rem; 
            display: flex; 
            align-items: center; 
            gap: 0.5rem; 
        } 
    
        /* Dọn dẹp phần đệm mặc định của Streamlit */ 
        .block-container { 
            padding-top: 3rem; 
            padding-bottom: 3rem; 
        } 
    </style> 
    """ , unsafe_allow_html= True ) 
    
    # 3. Phần tiêu đề
     st.markdown( '<h1 class="gradient-text">ResumeAI</h1>' , unsafe_allow_html= True ) 
    st.markdown( 
        '<p class="subtitle">Trí tuệ sơ yếu lý lịch được hỗ trợ bởi AI. Tải lên PDF của bạn để mở khóa thông tin chi tiết từ nhà tuyển dụng chuyên nghiệp.</p>' , 
        unsafe_allow_html= True ) 
    
    # 4. Thẻ giao diện chính 
    với st.container(): 
        st.markdown( '<div class="glass-card">' , unsafe_allow_html= True ) 
    
        # Nhãn tùy chỉnh cho trình tải lên
         st.markdown( "##### 📂   Tải lên sơ yếu lý lịch" , unsafe_allow_html= True ) 
        uploaded_file = st.file_uploader( 
            "Tải lên sơ yếu lý lịch (chỉ PDF)" ,   # Nhãn được ẩn bằng CSS lý tưởng, nhưng vẫn giữ lại để dễ tiếp cận 
            type =[ "pdf" ], 
            label_visibility= "collapsed"
         ) 
    
        nếu uploaded_file:
            st.markdown("<div style='height: 15px'></div>" , unsafe_allow_html= True )   # Khoảng cách 
    
            # Nút Phân tích 
            nếu st.button( "Tạo phản hồi chuyên nghiệp" ): 
                với st.spinner( "🤖 Phân tích cú pháp, tác động và từ khóa..." ): 
                    # --- LOGIC PHẦN MỀM (Không thay đổi) ---
                     resume_text = extract_text_from_pdf(uploaded_file) 
                    feedback = generate_feedback(resume_text) 
                    # --------------------------------- 
    
                # 5. Hiển thị kết quả
                 st.markdown( """ 
                <div class="feedback-container"> 
                    <div class="feedback-header"> 
                        <span>✨ Kết quả phân tích</span> 
                    </div> 
                """ , unsafe_allow_html= True ) 
    
                # Sử dụng st.markdown cho nội dung để đảm bảo định dạng markdown (in đậm, danh sách) hiển thị chính xác
                 st.markdown(feedback) 
    
                st.markdown( "</div>" , unsafe_allow_html= True ) 
    
        st.markdown( '</div>' , unsafe_allow_html= True )   # Kết thúc glass-card 
    
    # Chân trang
     st.markdown( """ 
    <div style="text-align: center; color: #475569; margin-top: 2rem; font-size: 0.8rem;"> 
        BÍ MẬT • CÔNG CỤ PHÂN TÍCH SƠ YẾU LÝ LỊCH AI 
    </div> 
    """ , unsafe_allow_html= True )

    Hiểu về giao diện người dùng (mà không bị lạc lối trong CSS)

    Đoạn mã giao diện người dùng ở trên có vẻ dài, nhưng ý tưởng đằng sau nó thực ra rất đơn giản.
    Thay vì giải thích từng quy tắc CSS, chúng ta hãy chia nhỏ nó thànhnhững phần quan trọng.

    A) Cấu hình trang và định danh ứng dụng

    Ở phần đầu, chúng ta thiết lập cấu hình trang:

    • Tên và biểu tượng ứng dụng.
    • Bố cục căn giữa.

    Điều này đảm bảo ứng dụng mang lại cảm giác như mộtsản phẩm hoàn chỉnh, chứ không phải chỉ là một bản demo nhanh.

    B) Chủ đề tối tùy chỉnh và kiểu dáng trực quan

    Thay vì sử dụng giao diện mặc định của Streamlit, chúng tôi chènCSS tùy chỉnhđể đạt được:

    • Nền chuyển màu tối (không phải màu đen nhàm chán).
    • Kiểu chữ hiện đại sử dụng Google Fonts.
    • Các tấm thiệp theo phong cách Glassmorphism.

    Giao diện người dùng tốt rất quan trọng nếu bạn muốn trình bày dự án cho nhà tuyển dụng hoặc người dùng.

    C) Quy trình người dùng đơn giản (Tải lên → Phân tích → Kết quả)

    Giao diện người dùng tuân theo một luồng thiết kế rất có chủ đích:

    1. Tải lên sơ yếu lý lịch (PDF).
    2. Nhấp chuột vào một nút hành động rõ ràng.
    3. Xem kết quả được trình bày dưới dạng hoạt ảnh và có cấu trúc.

    Không có sự nhầm lẫn hay các bước không cần thiết.
    Điều này giúp tập trung vàonhững gì người dùng thực sự muốn.

    D) Trình bày phản hồi (Dễ đọc > Đẹp mắt)

    Kết quả được hiển thị bên trong một vùng chứa chuyên dụng với:

    • Hiệu ứng hoạt hình tinh tế.
    • Xóa tiêu đề.
    • Định dạng Markdown.

    Điều này giúp cho các phản hồi dài do AI tạo ra trở nên dễ đọc hơn.

    Hãy nhớ:UX không phải để phô trương mà là để giảm thiểu khó khăn.

    Tóm tắt quy trình

    1. Tải lên sơ yếu lý lịch.
    2. Trích xuất văn bản.
    3. Gửi đến LLaMA.
    4. Hiển thị phản hồi có cấu trúc.

    Vậy thôi.

    Từ thiết bị đầu cuối:

    streamlit run app.py

    Tải lên sơ yếu lý lịch của bạn ở định dạng PDF và xem kết quả.

    Bằng cách xây dựng điều này:

    • Bạn tự cải thiệnsơ yếu lý lịch của mình.
    • Bạn sẽ học vềthiết kế hệ thống GenAI.
    • Bạn sẽ có mộtdự án thực tếđể đưa vào hồ sơ năng lực của mình.
    • Bạn có thể mở rộng phần này tùy ý.

    Đây chính xác là loại dự án giúp ích cho người dùng, giúp phát triển sự nghiệp của bạn và dạy cho bạn những kỹ năng thực tế.

    Nguồn: //medium.com/activated-thinker/build-an-ai-resume-analyzer-using-genai-f075c6fd73f6

    Để lại một bình luận

    Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

    Chat with us
    Hello! How can I help you today?