Bối cảnh: vì sao chuỗi phòng khám cần tự động hóa đặt lịch

Một chuỗi nha khoa hoặc phòng khám đa chi nhánh nhận yêu cầu đặt lịch từ Fanpage, Zalo OA, website và hotline, phần lớn vào buổi tối và cuối tuần, đúng lúc lễ tân đã nghỉ. Mỗi yêu cầu bị chậm phản hồi là một khách có thể chuyển sang phòng khám khác. Ngược lại, lịch được đặt vội mà không nhắc hẹn thì tỷ lệ khách không đến (no-show) cao, gây lãng phí giờ của bác sĩ.

Bài toán vì vậy gồm ba mục tiêu kỹ thuật: phản hồi tức thì 24/7 trên mọi kênh, thu thập đủ và đúng thông tin để đặt lịch hợp lệ, và ghi nhận nhất quán vào hệ thống lịch/CRM mà không trùng chỗ. Bài viết trình bày kiến trúc multi-agent mà BEEDONI thiết kế cho nhóm khách hàng y tế, nha khoa.

Vì sao chọn kiến trúc Multi-Agent

Cách tiếp cận đầu tiên của nhiều đội là viết một prompt khổng lồ chứa mọi quy tắc: tư vấn, báo giá, đặt lịch, xử lý khiếu nại. Khi prompt dài hàng nghìn token, mô hình bắt đầu “quên” quy tắc ở giữa (hiện tượng lost in the middle), chi phí và độ trễ tăng, và mỗi lần sửa một quy tắc lại có nguy cơ làm hỏng quy tắc khác.

Kiến trúc multi-agent chia nhỏ trách nhiệm theo nguyên tắc Single Responsibility. Mỗi agent có prompt ngắn, bộ công cụ riêng và bộ kiểm thử riêng:

AgentTrách nhiệmCông cụ được cấp
Triage AgentPhân loại ý định, chọn agent xử lý, phát hiện tình huống cần ngườiKhông gọi hệ thống ngoài
Consult AgentTư vấn dịch vụ, báo giá theo tài liệu (RAG)Tra cứu kho tri thức
Booking AgentThu thập thông tin, tìm và giữ khung giờ, xác nhận lịchTra lịch trống, giữ chỗ, xác nhận
Care AgentNhắc lịch, hỏi thăm sau điều trị, xử lý đổi/hủyGửi tin theo mẫu, cập nhật lịch
EscalationChuyển nhân viên kèm tóm tắt ngữ cảnhTạo yêu cầu trong hộp thư

Triage Agent và Intent Routing

Triage Agent nhận tin nhắn và trả về một đối tượng có cấu trúc (sinh bằng constrained decoding) gồm: ý định chính, ý định phụ, mức độ khẩn cấp và độ tin cậy. Tin nhắn thực tế thường chứa nhiều ý định cùng lúc, ví dụ “Bọc răng sứ giá bao nhiêu, chiều thứ Bảy có lịch không em?” vừa là hỏi giá vừa là đặt lịch. Router xử lý tuần tự: Consult Agent trả lời giá trước, sau đó chuyển giao (handoff) sang Booking Agent cùng toàn bộ ngữ cảnh.

json
{
  "primary_intent": "book_appointment",
  "secondary_intents": ["ask_price"],
  "urgency": "normal",
  "needs_human": false,
  "confidence": 0.93
}

Các từ khóa và dấu hiệu cấp cứu (đau dữ dội, sưng mặt, chảy máu không cầm) kích hoạt quy tắc cứng: AI hướng dẫn khách liên hệ hotline hoặc cơ sở y tế gần nhất và báo ngay cho nhân viên trực. Quy tắc này nằm ngoài LLM, không phụ thuộc vào việc mô hình có “hiểu” hay không.

Booking Agent: Máy trạng thái hữu hạn kết hợp Slot-Filling

Để đặt một lịch hợp lệ cần đủ các “ô” thông tin (slot): dịch vụ, chi nhánh, thời gian, họ tên, số điện thoại, và có thể là bác sĩ mong muốn. Khách hiếm khi cung cấp theo thứ tự; họ có thể nói cả ba thứ trong một câu, hoặc đổi ý giữa chừng. Nếu để LLM tự do điều khiển luồng, nó có thể quên hỏi số điện thoại hoặc xác nhận lịch trước khi kiểm tra chỗ trống.

Giải pháp là tách điều khiển luồng khỏi hiểu ngôn ngữ. Một Finite State Machine tất định quyết định bước tiếp theo; LLM chỉ làm hai việc là trích xuất slot từ câu khách nói và diễn đạt câu hỏi tiếp theo một cách tự nhiên.

text
COLLECTING ──(đủ slot bắt buộc)──▶ CHECKING_AVAILABILITY
     ▲                                   │
     │(khách đổi thông tin)              ├─(có chỗ)──▶ HOLDING ──(khách đồng ý)──▶ CONFIRMED
     └───────────────────────────────────┤                │
                                         └─(hết chỗ)──▶ OFFERING_ALTERNATIVES
                                                          │(hết hạn giữ chỗ)
                                                          ▼
                                                       RELEASED

Lợi ích của FSM là khả năng kiểm chứng: mọi đường đi đều có thể liệt kê và kiểm thử; không thể có lịch nào được xác nhận mà chưa qua bước kiểm tra chỗ trống. Đồng thời, khách vẫn trò chuyện tự nhiên vì LLM linh hoạt ở tầng ngôn ngữ.

Chuẩn hóa và xác thực slot

  • Số điện thoại: chuẩn hóa E.164, kiểm tra đầu số nhà mạng Việt Nam, đọc lại theo cụm để khách xác nhận.
  • Họ tên: khôi phục dấu tiếng Việt khi khách gõ không dấu, nhưng luôn hỏi xác nhận thay vì tự đoán.
  • Dịch vụ: ánh xạ cách gọi đời thường (“làm răng sứ”, “bọc sứ”) về mã dịch vụ trong danh mục.

Temporal Reasoning: hiểu thời gian như người Việt nói

“Chiều mai”, “sáng thứ Bảy tuần sau”, “cuối tuần này”, “tầm 5 giờ”, “sau giờ làm”: thời gian trong hội thoại hầu như không bao giờ ở dạng chuẩn. Thậm chí có những cách nói mơ hồ thực sự: “thứ Bảy tuần sau” khi hôm nay là thứ Năm có thể là hai ngày nữa hoặc chín ngày nữa tùy người.

Module suy luận thời gian chuyển biểu thức tự nhiên thành khoảng thời gian chuẩn ISO 8601, luôn tính theo múi giờ Asia/Ho_Chi_Minh (UTC+7) và mốc thời gian của chính tin nhắn, không phải thời điểm xử lý. Khi biểu thức có nhiều cách hiểu, hệ thống không đoán mà hỏi lại bằng ngày cụ thể: “Dạ anh muốn thứ Bảy ngày 7/11 đúng không ạ?”. “Tầm 5 giờ” trong ngữ cảnh phòng khám được hiểu là 17:00 nhờ ràng buộc giờ mở cửa của chi nhánh.

Giữ chỗ hai pha và tính nhất quán dữ liệu

Vào tối Chủ nhật, có thể có ba khách trên ba kênh khác nhau cùng hỏi khung 9:00 sáng thứ Hai với cùng một bác sĩ. Nếu hệ thống chỉ “kiểm tra rồi ghi”, cả ba có thể cùng thấy còn chỗ và cùng được xác nhận, một lỗi race condition điển hình.

BEEDONI áp dụng mô hình giữ chỗ hai pha, lấy cảm hứng từ Two-Phase Commit:

  1. Pha 1 (Hold): khi đưa ra đề xuất cho khách, hệ thống tạo bản ghi giữ chỗ tạm thời có thời hạn ngắn. Khung giờ đang được giữ sẽ không được đề xuất cho khách khác.
  2. Pha 2 (Confirm): khi khách đồng ý, bản ghi giữ chỗ được chuyển thành lịch hẹn chính thức trong cùng một giao dịch, kèm kiểm tra optimistic locking trên phiên bản của khung giờ.
  3. Hết hạn: nếu khách không phản hồi, một tác vụ nền giải phóng chỗ giữ và trạng thái chuyển sang RELEASED.

Khi lịch được lưu trong hệ thống bên ngoài (phần mềm quản lý phòng khám), mô hình Saga với các bước bù trừ (compensating action) đảm bảo nếu bước đồng bộ ra ngoài thất bại, lịch tạm được hủy sạch sẽ và khách nhận thông báo chính xác thay vì một xác nhận “ảo”. Mỗi lệnh gửi ra ngoài mang idempotency key để retry an toàn.

Care Agent: giảm tỷ lệ khách không đến

Đặt được lịch mới là một nửa bài toán. Care Agent gửi tin nhắc lịch theo nhịp được cấu hình (ví dụ trước một ngày và trước hai giờ), trên đúng kênh khách đã dùng, với nút xác nhận hoặc đổi lịch chỉ bằng một lần trả lời. Khi khách xin dời lịch, luồng quay lại Booking Agent với các slot đã có sẵn, khách không phải cung cấp lại thông tin.

Doanh nghiệp theo dõi các chỉ số: thời gian phản hồi đầu tiên ngoài giờ hành chính, tỷ lệ hội thoại chuyển thành lịch hẹn, tỷ lệ khách xác nhận nhắc lịch và tỷ lệ khách đến khám. Mục tiêu thiết kế của luồng nhắc lịch là nâng tỷ lệ khách đến lên mức cao, hướng tới khoảng 88%; con số thực tế phụ thuộc vào từng chuỗi và được đo trên chính dữ liệu của doanh nghiệp.

Đồng bộ Bee CRM: mỗi hội thoại là một hồ sơ khách hàng

Mọi thông tin thu thập được (dịch vụ quan tâm, lịch sử hỏi giá, lịch hẹn, kênh liên hệ) được ghi vào hồ sơ khách hàng trên Bee CRM hoặc CRM doanh nghiệp đang dùng, cùng bản tóm tắt hội thoại. Quản lý chi nhánh nhìn thấy phễu chuyển đổi theo từng kênh; đội chăm sóc biết chính xác khách nào cần gọi lại. Dữ liệu sức khỏe được phân quyền chặt chẽ và chỉ những vai trò được chỉ định mới truy cập được.

“Tự động hóa tốt không thay thế lễ tân hay bác sĩ. Nó lấy đi phần việc lặp lại lúc 11 giờ đêm, để con người tập trung vào điều chỉ con người làm được: chăm sóc bệnh nhân.”

Kết luận

Multi-agent workflow cho ngành y tế là sự kết hợp giữa sự linh hoạt của mô hình ngôn ngữ và sự chặt chẽ của kỹ thuật phần mềm truyền thống: máy trạng thái, giao dịch, khóa lạc quan và idempotency. BEEDONI đóng gói kiến trúc này thành luồng có thể cấu hình theo từng chuỗi phòng khám, nha khoa, giúp doanh nghiệp tiếp nhận và đặt lịch 24/7 trên mọi kênh mà vẫn giữ dữ liệu chính xác tuyệt đối.