Tháng 3/2025, tôi nhận được một cuộc gọi từ anh Minh — Giám đốc nhân sự của một công ty thương mại điện tử quy mô 500 nhân viên. Vấn đề của anh rất rõ ràng: "Đội ngũ tuyển dụng của tôi mất 6 giờ mỗi ngày chỉ để sàng lọc ứng viên qua điện thoại. Tôi cần một AI có thể thay thế 80% cuộc gọi sàng lọc ban đầu." Đó là lúc tôi bắt đầu hành trình xây dựng hệ thống AI tổng đài tư vấn tuyển dụng thông minh, và bài học đầu tiên tôi rút ra là: thiết kế hội thoại quyết định 90% thành bại của dự án.

Bối Cảnh Thực Tế: Tại Sao Thiết Kế Hội Thoại Quan Trọng

Trong dự án với anh Minh, tôi đã thử nghiệm ba cách tiếp cận khác nhau. Cách tiếp cận đầu tiên — một chatbot đơn giản với if-else — thất bại hoàn toàn vì không xử lý được các câu hỏi ngoài kịch bản. Cách thứ hai — một LLM đa năng — tốn kém và thiếu cấu trúc. Cách thứ ba — thiết kế hội thoại theo state machine kết hợp RAG — đạt 94% độ chính xác trong sàng lọc và tiết kiệm 85% chi phí so với GPT-4.

Bài viết này sẽ hướng dẫn bạn xây dựng một hệ thống tương tự, sử dụng HolySheep AI làm backend với chi phí chỉ từ $0.42/MTok — rẻ hơn 85% so với các giải pháp phương Tây.

Kiến Trúc Tổng Quan: State Machine + RAG + LLM

Thiết kế hội thoại hiệu quả cho AI tổng đài đòi hỏi sự kết hợp của ba thành phần: State Machine để quản lý luồng hội thoại, RAG để truy xuất thông tin tuyển dụng, và LLM để xử lý ngôn ngữ tự nhiên. Mỗi thành phần đảm nhiệm một vai trò riêng biệt.


"""
Hệ thống AI Tổng Đài Tuyển Dụng - Kiến Trúc Core
Tác giả: HolySheep AI Technical Blog
Phiên bản: 1.0.0
"""

import json
import asyncio
from enum import Enum
from typing import Optional, Dict, List
from dataclasses import dataclass, field
from datetime import datetime

Import HolySheep SDK - Thay thế OpenAI SDK

try: from openai import AsyncOpenAI except ImportError: print("pip install openai>=1.0.0")

Cấu hình HolySheep AI - KHÔNG dùng OpenAI/Anthropic

HOLYSHEEP_CONFIG = { "base_url": "https://api.holysheep.ai/v1", "api_key": "YOUR_HOLYSHEEP_API_KEY", # Thay bằng key của bạn "model": "deepseek-v3.2", # $0.42/MTok - tiết kiệm 85%+ "max_tokens": 2048, "temperature": 0.7 } class ConversationState(Enum): """Các trạng thái hội thoại trong quy trình tuyển dụng""" GREETING = "greeting" COLLECT_NAME = "collect_name" COLLECT_PHONE = "collect_phone" COLLECT_EMAIL = "collect_email" COLLECT_EXPERIENCE = "collect_experience" JOB_INTRO = "job_intro" SKILL_ASSESSMENT = "skill_assessment" SALARY_DISCUSSION = "salary_discussion" SCHEDULE_INTERVIEW = "schedule_interview" CLOSING = "closing" HAND_OFF = "hand_off" END = "end" @dataclass class CandidateProfile: """Hồ sơ ứng viên được thu thập trong quá trình hội thoại""" name: Optional[str] = None phone: Optional[str] = None email: Optional[str] = None years_experience: Optional[int] = None current_salary: Optional[int] = None expected_salary: Optional[int] = None skills: List[str] = field(default_factory=list) position_interest: Optional[str] = None conversation_history: List[Dict] = field(default_factory=list) created_at: datetime = field(default_factory=datetime.now) @dataclass class ConversationContext: """Ngữ cảnh hội thoại""" session_id: str state: ConversationState = ConversationState.GREETING candidate: CandidateProfile = field(default_factory=CandidateProfile) job_requirements: Dict = field(default_factory=dict) retry_count: int = 0 last_intent: Optional[str] = None entities_extracted: Dict = field(default_factory=dict) class RecruitmentConversationEngine: """ Engine xử lý hội thoại tuyển dụng Kết hợp State Machine + Intent Recognition + Entity Extraction """ def __init__(self, config: Dict): self.client = AsyncOpenAI( api_key=config["api_key"], base_url=config["base_url"] # Luôn dùng HolySheep endpoint ) self.model = config["model"] self.conversations: Dict[str, ConversationContext] = {} # Khởi tạo các intent handlers self.intent_prompts = self._build_intent_prompts() self.entity_extractors = self._build_entity_extractors() async def process_message( self, session_id: str, user_message: str, job_context: Optional[Dict] = None ) -> Dict: """Xử lý một tin nhắn từ ứng viên""" # Lấy hoặc tạo context cho session if session_id not in self.conversations: self.conversations[session_id] = ConversationContext( session_id=session_id, job_requirements=job_context or {} ) ctx = self.conversations[session_id] # Bước 1: Nhận diện ý định (Intent Recognition) intent = await self._recognize_intent(user_message, ctx) ctx.last_intent = intent # Bước 2: Trích xuất thực thể (Entity Extraction) entities = await self._extract_entities(user_message, ctx) ctx.entities_extracted.update(entities) # Bước 3: Cập nhật hồ sơ ứng viên self._update_candidate_profile(ctx, entities) # Bước 4: Xác định trạng thái tiếp theo next_state = self._determine_next_state(ctx, intent) ctx.state = next_state # Bước 5: Sinh phản hồi response = await self._generate_response(ctx, user_message) # Lưu lịch sử hội thoại ctx.candidate.conversation_history.append({ "timestamp": datetime.now().isoformat(), "user": user_message, "bot": response["message"], "state": ctx.state.value, "intent": intent }) return { "message": response["message"], "state": ctx.state.value, "candidate_summary": self._get_candidate_summary(ctx), "action_required": response.get("action"), "confidence_score": response.get("confidence", 0.9) } async def _recognize_intent( self, message: str, ctx: ConversationContext ) -> str: """Nhận diện ý định của ứng viên""" system_prompt = """Bạn là một Intent Classifier cho hệ thống tuyển dụng. Phân loại tin nhắn của ứng viên vào một trong các intent sau: INTENTS: - greet: Chào hỏi, xin chào - provide_info: Cung cấp thông tin được yêu cầu - ask_question: Hỏi về công việc, quyền lợi, quy trình - express_interest: Thể hiện quan tâm muốn ứng tuyển - express_hesitation: Do dự, cần suy nghĩ thêm - decline: Từ chối, không quan tâm - schedule_request: Yêu cầu hẹn lịch phỏng vấn - goodbye: Chào tạm biệt, kết thúc - unclear: Không rõ ý, cần làm rõ CHỈ trả về MỘT intent vào cuối dòng.""" response = await self.client.chat.completions.create( model=self.model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": message} ], max_tokens=50, temperature=0.1 ) return response.choices[0].message.content.strip().lower()

Xây Dựng Hệ Thống RAG Cho Thông Tin Tuyển Dụng

Điểm mấu chốt để AI trả lời chính xác về vị trí tuyển dụng là hệ thống RAG (Retrieval-Augmented Generation). Thay vì để LLM tự generate mọi thứ — vừa tốn chi phí vừa thiếu chính xác — chúng ta sẽ truy xuất thông tin từ tài liệu và bổ sung vào prompt.


"""
RAG System cho thông tin tuyển dụng
Tích hợp với HolySheep AI Embeddings
"""

import hashlib
from typing import List, Dict, Optional
import json

class RecruitmentRAG:
    """
    Hệ thống RAG chuyên biệt cho tuyển dụng
    - Chunking thông minh theo cấu trúc JD
    - Vector search với HolySheep Embeddings
    - Context compression để tối ưu token
    """
    
    def __init__(self, holysheep_client):
        self.client = holysheep_client
        self.document_store: Dict[str, Dict] = {}
        self.chunk_size = 512
        self.chunk_overlap = 50
        
    async def index_job_description(
        self, 
        job_data: Dict, 
        job_id: str
    ) -> Dict:
        """Đánh chỉ mục mô tả công việc"""
        
        # Tạo các chunks có cấu trúc
        chunks = self._create_structured_chunks(job_data)
        
        # Embed tất cả chunks
        embedded_chunks = []
        for i, chunk in enumerate(chunks):
            embedding = await self._get_embedding(chunk["content"])
            embedded_chunks.append({
                "chunk_id": f"{job_id}_chunk_{i}",
                "content": chunk["content"],
                "embedding": embedding,
                "metadata": chunk["metadata"],
                "chunk_index": i
            })
        
        # Lưu vào document store
        self.document_store[job_id] = {
            "job_data": job_data,
            "chunks": embedded_chunks,
            "total_chunks": len(embedded_chunks),
            "indexed_at": datetime.now().isoformat()
        }
        
        return {
            "job_id": job_id,
            "chunks_indexed": len(embedded_chunks),
            "status": "success"
        }
    
    def _create_structured_chunks(self, job_data: Dict) -> List[Dict]:
        """Tạo các chunks có cấu trúc từ JD"""
        
        chunks = []
        
        # Chunk 1: Tổng quan vị trí
        overview = f"""
        Vị trí: {job_data.get('title', 'N/A')}
        Bộ phận: {job_data.get('department', 'N/A')}
        Cấp bậc: {job_data.get('level', 'N/A')}
        Địa điểm: {job_data.get('location', 'N/A')}
        Loại công việc: {job_data.get('employment_type', 'N/A')}
        """
        chunks.append({
            "content": overview.strip(),
            "metadata": {"type": "overview", "priority": "high"}
        })
        
        # Chunk 2: Mô tả công việc
        if job_data.get("description"):
            chunks.append({
                "content": f"Mô tả công việc: {job_data['description']}",
                "metadata": {"type": "description", "priority": "high"}
            })
        
        # Chunk 3: Yêu cầu kỹ năng
        skills = job_data.get("required_skills", [])
        if skills:
            skills_text = "\n".join([f"- {s}" for s in skills])
            chunks.append({
                "content": f"Yêu cầu kỹ năng:\n{skills_text}",
                "metadata": {"type": "skills", "priority": "high"}
            })
        
        # Chunk 4: Quyền lợi
        benefits = job_data.get("benefits", [])
        if benefits:
            benefits_text = "\n".join([f"- {b}" for b in benefits])
            chunks.append({
                "content": f"Quyền lợi:\n{benefits_text}",
                "metadata": {"type": "benefits", "priority": "medium"}
            })
        
        # Chunk 5: Quy trình tuyển dụng
        process = job_data.get("hiring_process", [])
        if process:
            process_text = "\n".join([f"{i+1}. {p}" for i, p in enumerate(process)])
            chunks.append({
                "content": f"Quy trình tuyển dụng:\n{process_text}",
                "metadata": {"type": "process", "priority": "medium"}
            })
        
        return chunks
    
    async def _get_embedding(self, text: str) -> List[float]:
        """Lấy embedding từ HolySheep AI"""
        
        response = await self.client.embeddings.create(
            model="text-embedding-3-small",
            input=text
        )
        
        return response.data[0].embedding
    
    async def retrieve_relevant_context(
        self,
        query: str,
        job_id: str,
        top_k: int = 3
    ) -> Dict:
        """Truy xuất context liên quan cho câu hỏi"""
        
        if job_id not in self.document_store:
            return {"context": "", "sources": []}
        
        # Embed query
        query_embedding = await self._get_embedding(query)
        
        # Tính similarity với các chunks
        chunks = self.document_store[job_id]["chunks"]
        scored_chunks = []
        
        for chunk in chunks:
            similarity = self._cosine_similarity(
                query_embedding, 
                chunk["embedding"]
            )
            scored_chunks.append({
                "chunk": chunk,
                "score": similarity
            })
        
        # Sắp xếp và lấy top-k
        scored_chunks.sort(key=lambda x: x["score"], reverse=True)
        top_chunks = scored_chunks[:top_k]
        
        # Ghép context
        context_parts = [c["chunk"]["content"] for c in top_chunks]
        combined_context = "\n\n---\n\n".join(context_parts)
        
        return {
            "context": combined_context,
            "sources": [
                {
                    "content_preview": c["chunk"]["content"][:100] + "...",
                    "type": c["chunk"]["metadata"]["type"],
                    "score": round(c["score"], 3)
                }
                for c in top_chunks
            ]
        }
    
    def _cosine_similarity(self, a: List[float], b: List[float]) -> float:
        """Tính cosine similarity"""
        
        dot_product = sum(x * y for x, y in zip(a, b))
        norm_a = sum(x * x for x in a) ** 0.5
        norm_b = sum(y * y for y in b) ** 0.5
        
        return dot_product / (norm_a * norm_b + 1e-8)


Ví dụ sử dụng

async def main(): # Khởi tạo HolySheep client client = AsyncOpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1" ) # Tạo RAG system rag = RecruitmentRAG(client) # Đánh chỉ mục JD mẫu sample_job = { "title": "Senior Backend Engineer", "department": "Engineering", "level": "Senior (5-7 năm kinh nghiệm)", "location": "Ho Chi Minh City - Hybrid", "employment_type": "Full-time", "description": """ Chịu trách nhiệm phát triển và duy trì các dịch vụ backend cho nền tảng thương mại điện tử với 1 triệu người dùng. """, "required_skills": [ "Python/Java/Go (5+ năm)", "PostgreSQL, Redis, Kafka", "AWS/GCP, Docker, Kubernetes", "API Design, Microservices" ], "benefits": [ "Lương: $3,000 - $5,000", "Thưởng performance 2 tháng", "Bảo hiểm cao cấp", "Remote work 2 ngày/tuần" ], "hiring_process": [ "Apply online", "AI Screening Call (15 phút)", "Technical Interview (60 phút)", "Final Interview với CTO" ] } result = await rag.index_job_description(sample_job, "job_001") print(f"Đánh chỉ mục thành công: {result}") # Truy xuất context context = await rag.retrieve_relevant_context( "Mức lương và quyền lợi như thế nào?", "job_001" ) print(f"Context retrieved: {len(context['context'])} chars") if __name__ == "__main__": asyncio.run(main())

Tích Hợp Hoàn Chỉnh: AI Tổng Đài Tuyển Dụng

Giờ chúng ta kết hợp tất cả lại thành một hệ thống hoàn chỉnh. Phần quan trọng nhất là prompt engineering cho từng trạng thái hội thoại, đảm bảo AI có personality phù hợp với thương hiệu tuyển dụng.


"""
AI Tổng Đài Tuyển Dụng - Tích Hợp Hoàn Chỉnh
Tích hợp State Machine + RAG + LLM