Bạn đã có 4 mảnh rời: transcribe, summarize, extract, assign. Bài này ghép chúng bằng một orchestrator — bộ điều phối chạy tuần tự, xử lý lỗi, và kích hoạt tự động khi có file họp mới.
Orchestrator là gì
Là đoạn code "nhạc trưởng": gọi từng bước đúng thứ tự, chuyển output bước này thành input bước sau, và quyết định làm gì khi một bước hỏng. Nó KHÔNG tự làm AI — nó điều phối các tool.
Kiến trúc state machine
Mỗi cuộc họp là một "job" đi qua các trạng thái:
UPLOADED → TRANSCRIBING → TRANSCRIBED → SUMMARIZING
→ SUMMARIZED → EXTRACTING → EXTRACTED → ASSIGNING
→ DONE (hoặc FAILED ở bất kỳ bước nào)
Lưu trạng thái vào database. Lợi ích: nếu bước 4 lỗi, bạn resume từ bước 4, không transcribe lại (tốn tiền, tốn thời gian).
Code orchestrator (rút gọn)
def process_meeting(job_id):
job = db.get(job_id)
try:
if job.status == "UPLOADED":
job.audio = normalize_audio(job.file)
job.status = "TRANSCRIBING"; db.save(job)
if job.status == "TRANSCRIBING":
job.transcript = transcribe(job.audio)
job.status = "TRANSCRIBED"; db.save(job)
if job.status in ("TRANSCRIBED", "SUMMARIZING"):
job.summary = summarize(job.transcript)
job.status = "SUMMARIZED"; db.save(job)
if job.status in ("SUMMARIZED", "EXTRACTING"):
job.items = extract_action_items(job.transcript, job.date)
job.status = "EXTRACTED"; db.save(job)
if job.status in ("EXTRACTED", "ASSIGNING"):
assign_tasks(job.items) # bài 5
notify_summary(job.summary) # gửi tóm tắt
job.status = "DONE"; db.save(job)
except Exception as e:
job.status = "FAILED"; job.error = str(e); db.save(job)
alert_admin(job_id, e)
Mẫu if job.status in (...) cho phép resume: gọi lại process_meeting sẽ tiếp từ chỗ dừng.
Kích hoạt tự động (trigger)
Đừng bắt người dùng bấm nút. Ba cách trigger phổ biến:
- Watch folder: có file mới trong Drive/thư mục → tạo job.
- Webhook: Zoom/Meet bắn sự kiện "recording ready" → gọi endpoint của bạn.
- Cron định kỳ: quét thư mục mỗi 5 phút (đơn giản, hợp lý cho bắt đầu).
Đồng bộ (sync) hay chạy nền (async)?
Transcribe một buổi 45 phút có thể mất vài phút. Nếu orchestrator chạy đồng bộ trong một web request, request sẽ timeout. Giải pháp: đưa job vào hàng đợi (queue) và xử lý bằng worker chạy nền. Trigger chỉ việc tạo job và trả về ngay "đã nhận, đang xử lý"; worker mới thực sự chạy pipeline. Trên hạ tầng hạn chế (như shared hosting), một cron worker quét bảng jobs đóng vai trò queue đơn giản mà hiệu quả.
Retry và giới hạn
- Retry có backoff: lỗi mạng tạm thời → thử lại 3 lần, giãn cách tăng dần.
- Timeout: transcribe lâu bất thường → cắt và báo lỗi, đừng treo mãi.
- Idempotency: một file chỉ tạo một job (dùng hash file).
Ví dụ vận hành
Trợ lý upload hop_sprint.m4a lên Drive lúc 15:00. Cron 15:05 phát hiện, tạo job. Orchestrator chạy: transcribe (2 phút) → tóm tắt → trích 4 item → tạo 3 card (1 item CHƯA_RÕ để hỏi) → gửi tóm tắt vào Telegram lúc 15:09. Nếu Trello sập lúc tạo card thứ 2, job dừng ở ASSIGNING; lần chạy sau resume, không transcribe lại.
Các bước triển khai
- Thiết kế bảng
jobsvới cột status, error, và các artifact (transcript, summary, items). - Viết từng hàm bước với input/output rõ ràng.
- Ghép trong
process_meetingtheo state machine. - Thêm try/except toàn cục → set FAILED + alert.
- Chọn 1 trigger (bắt đầu bằng cron cho đơn giản).
- Thêm retry/backoff cho các lời gọi mạng.
Checklist orchestrator
- [ ] Có lưu trạng thái để resume được không?
- [ ] Lỗi một bước có làm mất kết quả các bước trước không? (không được)
- [ ] Một file có thể tạo trùng job không? (phải chặn)
- [ ] Admin có được báo khi job FAILED không?
- [ ] Có timeout cho bước chậm không?
Sai lầm thường gặp
- Chạy tuần tự không lưu state: một lỗi ở cuối bắt transcribe lại từ đầu, đốt tiền.
- Nuốt lỗi im lặng: except rồi bỏ qua, job "biến mất" không ai biết. Luôn alert.
- Không idempotent trigger: cron quét lặp tạo nhiều job cho cùng file.
- Không có timeout: một request treo làm nghẽn cả hàng đợi.