Gõ thế nào cũng hiểu.
Prompt engineering tối ưu cho Vietnamese informal — system prompt tune sát với ngôn ngữ công nhân. Hiểu được từ lóng ("đứng máy", "làm ca", "ở KTX"), tên KCN viết tắt, và context location Bắc Ninh.
AI Service của VIVA — chat streaming OpenAI + DeepSeek, 11 function tools tra thẳng vào Laravel M2M, generative UI carousel + ứng tuyển inline, lead-capture LLM-driven, multi-turn nhớ ngữ cảnh xuyên F5. Built cho KCN Bắc Ninh · Bắc Giang.
Prompt engineering tối ưu cho Vietnamese informal — system prompt tune sát với ngôn ngữ công nhân. Hiểu được từ lóng ("đứng máy", "làm ca", "ở KTX"), tên KCN viết tắt, và context location Bắc Ninh.
AI gọi function tools đến api.xanhvina.com.vn qua M2M để lấy data trực tiếp — worker profile, jobs, lịch phỏng vấn. Jobs được scrape ngoài rồi đẩy vào Laravel, AI tự rank và explain match. Không cache stale, không hallucinate.
Lấy CV, kỹ năng, vị trí worker từ Laravel realtime.
Query live theo location/salary/skill, paginated, full filters.
So sánh 2-3 việc — lương, KTX, khoảng cách, yêu cầu, side-by-side.
NL → structured filters (industry/location/salary/benefits).
Pre-fill form, render Generative UI confirm card, worker bấm 1 nút gửi.
Handoff sang ops khi AI không đủ thông tin — lưu context đầy đủ.
LLM có thể gọi nhiều tools song song qua asyncio.gather — giảm latency 40%+ khi cần nhiều thông tin. Result compressor chỉ giữ field essential per-tool (top-10 jobs với 8 fields thay vì 50 với 30 fields) — tiết kiệm 60-70% context. Retry classifier phân loại lỗi retryable / non-retryable theo provider để tránh đốt quota vô ích.
Worker: "so sánh việc Samsung & Goertek, em muốn KTX free"
│
▼
LLM → 3 tool_calls SONG SONG:
├─ job_search(company="Samsung", benefits=["dorm"])
├─ job_search(company="Goertek", benefits=["dorm"])
└─ worker_profile(worker_id=current)
│
▼ (asyncio.gather — 1 round-trip)
Laravel /api/v1/... ← 3 calls parallel
│
▼ result_compressor: 50 fields → 8 essential
indirect_injection_guard: lọc model tokens / URL inject
▼
LLM compose so sánh:
"Samsung 11.5tr KTX free · Goertek 12tr KTX..."
│
▼
Streamed to worker via SSE ✓
Gateway dùng OpenAI gpt-4o-mini làm primary (chất lượng tiếng Việt tốt + tool calling chuẩn xác), DeepSeek deepseek-chat làm fallback giá rẻ. Provider + model có thể đổi runtime qua admin Settings UI mà không cần redeploy. Circuit breaker mở 30s khi 5xx/timeout, traffic shift tự động. Mỗi request log cost USD vào ``llm_usage_log`` — admin xem realtime trên dashboard.
Input pipeline: Unicode NFKC normalize → direct prompt-injection detector → PII masker VN-aware (CCCD 12 số, CMND 9 số, MST 10/13 số, STK ngân hàng, SĐT VN) → rate limit per-worker + per-IP. Trên đường về: indirect_injection_guard (Phase 02 B4) sanitize tool result trước khi feed lại LLM — chống prompt injection ngầm từ data ngoài.
5 cards live: JobCarouselCard swipe ngang (2-8 jobs), JobPickerCard list dọc, ApplicationFormCard ứng tuyển inline, ApplicationSuccessCard, ApplicationConfirmCard. Tool emit tool_card hoặc lead_signal SSE — frontend dispatch theo whitelist.
4 admin AI: churn risk, draft-reply HR, anomaly detection, campaign suggestions theo KCN.
profile.built · content.generated · safety.incident · match.found · churn.spike · anomaly.detected — fire-and-forget với daily idempotency keys.
Per-worker chat history với row-level security · auto-summarize mỗi 20 turns · TTL 90d worker / 365d staff / 7d guest (NEW). Guest sessions multi-turn từ 2026-04-29.
Parallel tool dispatch (asyncio.gather) + result compressor 60-70% gọn + retry classifier theo provider + indirect injection guard.
State machine 8 câu hỏi · AI trích skill từ chat · Laravel sync on complete.
Worker chat ngay không cần đăng ký · LLM tool should_capture_lead tự nhận biết khi nào hỏi SĐT (không cần regex hardcode) · auto-prefill vị trí + KCN từ context · ApplicationFormCard inline submit tạo Worker + applied_jobs[].
search/parse · feed/explain · content/summarize-job · suggestions · thinking events — gọn cho frontend SSE.
Jobs scraper EXTERNAL → Laravel /jobs/ingest → AI extract + rank · 100 jobs/day · <5% manual override.
4 luồng mới không cần rời chat: (1) bấm "Ứng tuyển" → chip "Để lại SĐT" → OTP verify là tự nộp đơn ngay kèm Slack notify HR; (2) hỏi "đơn của tôi sao rồi?" → card list 10 đơn gần nhất + status badge tiếng Việt; (3) "lưu việc Goertek" → ConfirmCard, bấm Lưu là xong; (4) "báo Samsung Bắc Ninh" → tạo Saved Search, hệ thống tự alert khi có việc mới khớp (cap 3 alert/ngày, max 5 search active). Chống spam: trần 15 đơn/ngày/worker (atomic Redis counter).
Tool mới should_capture_lead: AI đọc full ngữ cảnh hội thoại → tự quyết khi nào nên hỏi SĐT thay vì dò 12 keyword cứng. Auto-prefill vị trí + KCN từ chat → IdentifyForm không cần gõ lại.
"Goer tek 12tr Bắc Ninh" → AI normalize typo + extract {location: 'Bắc Ninh', salary_min: 12000000} trước khi tra Laravel. Loại bỏ class lỗi "AI bịa keyword" và xử lý phrasing tự nhiên VN.
Khách không đăng nhập giờ cũng nhớ ngữ cảnh xuyên các tin nhắn — RLS policy nới cho guest, conversation_id round-trip giữa client + server. Hỏi "Goertek" rồi hỏi "Bắc Ninh" — AI hiểu là Goertek tại Bắc Ninh.
Đóng tab / refresh / mở lại — đoạn hội thoại đang dở vẫn còn. Tự động cắt sau 100 lượt hoặc 24h. Reset rõ ràng qua nút "Bắt đầu chat mới".
JWT 1h hết hạn giữa cuộc chat → frontend tự re-mint trước 5 phút + retry mid-stream khi 401. User không bao giờ thấy "token expired" toast.
2-8 việc trả về dạng carousel ngang (Embla, swipe-aware, dot indicator). 1 thẻ/lượt rõ ràng hơn list dọc, có CTA "Ứng tuyển ngay" + "Xem chi tiết" nội tại.
Bấm "Ứng tuyển" trên carousel → form họ tên + SĐT + năm sinh + kinh nghiệm hiện inline. Submit tạo Worker (Laravel lookup-or-create) + ghi applied_jobs[] vào meta của conversation. Không rời khung chat.
"từ 15tr" giờ thực sự lọc theo overlap với khoảng lương — không còn match toàn bộ vì regex [0-9]. Artisan jobs:backfill-wage parse "13-18 triệu/tháng" → wage_min=13M, wage_max=18M.
Provider OpenAI + DeepSeek đọc ai.tasks.chat.max_tokens từ settings_client (Laravel admin → Redis → env). Clamp 120-4096. Marketing tune độ dài câu trả lời live, không cần redeploy.
PG default tsvector tokenize Latin, mọi query VN trả 0 lexical hit. Drop BM25 leg; pgvector cosine với 1536-dim embedding cover synonym + typo tốt cho corpus 10 bài hiện tại. Sẽ bật lại khi có pg_trgm Vietnamese index.
OpenAI gpt-4o-mini làm primary, DeepSeek deepseek-chat dự phòng. Provider/model + giá đổi runtime qua admin Settings UI, đẩy invalidate qua Redis pub/sub. Wiki RAG dùng text-embedding-3-small 1536-dim.
Semantic search pgvector 1536-dim · citation [#W{id}] · admin CRUD đầy đủ qua Laravel UI. Nhân viên content cập nhật bài → AI dùng ngay không redeploy. (Lưu ý 2026-04-29: BM25 leg bỏ tạm vì tsvector không hiểu tiếng Việt — xem changelog.)
Mọi LLM/embed/STT call ghi cost USD vào ``llm_usage_log``. Admin xem theo ngày/provider/model/worker · top-N consumers · live error feed.
profile.built, content.generated, safety.incident, match.found, churn.spike, anomaly.detected — fire-and-forget với daily idempotency keys.
Churn risk score (LLM heuristic), reply suggestions HR, anomaly detection, campaign suggestions theo KCN.
Chỉ giữ field essential per-tool (top-10 jobs với 8 fields thay vì 50 jobs với 30 fields) — context LLM gọn hơn 60-70%.
Lọc model role tokens, URL injection, các kiểu "ignore previous" tiếng Việt + Anh từ tool response trước khi feed lại LLM.
LLM có thể gọi nhiều tools cùng lúc (asyncio.gather) — giảm latency 40%+ khi cần lấy nhiều thông tin.
AI tự điền sẵn form ứng tuyển từ hồ sơ của bạn, bấm "Xác nhận & gửi" là HR nhận đơn ngay. Không cần copy-paste lại thông tin.
VIVA AI đề xuất 3 câu hỏi tiếp theo dựa trên cuộc trò chuyện, bấm là hỏi luôn — không cần nghĩ phải gõ gì.
Theo dõi đầy đủ tại GitLab commits.
Test ngay trong widget phía trên — hoặc đọc docs để biết cách nạp thêm knowledge.