CHUỖI THỰC HÀNH: CHATBOT AI HỎI ĐÁP ĐẤT ĐAI — PHP 8.x + MySQL 9.x Lưu ý trách nhiệm: chatbot chỉ tổng hợp thông tin tham khảo từ nguồn do quản trị viên phê duyệt. Không dùng để kết luận quyền sử dụng đất, tranh chấp, quy hoạch hoặc nghĩa vụ tài chính cụ thể. Không nhập CCCD, số sổ, ảnh giấy tờ, địa chỉ/tọa độ chính xác hay dữ liệu cá nhân vào chat. # 10/10 — Chạy thử, triển khai và vận hành có trách nhiệm Bạn đã có một website hoàn chỉnh theo cấu trúc ở bài 01–09. Phần khó nhất sau khi chạy được không phải “đổi model”, mà là giữ kho tri thức đúng, bí mật không lộ và biết khi nào chatbot phải từ chối. Dưới đây là quy trình kết thúc để đưa vào vận hành an toàn. ## 1. Chạy local theo thứ tự ```bash # 1) tạo schema (chỉ lần đầu) mysql -u land_chat -p land_ai_chatbot < database/schema.sql # 2) kiểm tra kết nối và fake mode php cli/check.php # 3) import tài liệu minh họa, sau đó tự duyệt nguồn thật trước khi publish php cli/import_knowledge.php cli/knowledge.sample.json # 4) chạy server học local php -S localhost:8080 -t public ``` Mở `http://localhost:8080/healthz`, rồi `http://localhost:8080/`. Khi vẫn `AI_FAKE_MODE=true`, bạn có thể kiểm thử database, CSRF, rate limit và UI mà không cần API key. Chỉ đổi sang AI thật sau khi tất cả test an toàn đạt. ## 2. Bật AI thật — chỉ trên máy chủ, bằng khóa của chính bạn Trong `.env` của máy chủ (không phải `.env.example`, không commit): ```dotenv AI_FAKE_MODE=false AI_BASE_URL=https://TEN-MIEN-API-CUA-NHA-CUNG-CAP/v1 AI_MODEL=TEN_MODEL_CUA_BAN # Thay dòng dưới bằng khóa thật của BẠN ngay trên máy chủ. # Không gửi khóa qua forum, chat, email công khai, Git hoặc JavaScript. AI_API_KEY=YOUR_AI_API_KEY_HERE ``` Sau khi thay nhãn mẫu bằng khóa thật tại server, bảo đảm quyền đọc `.env` chỉ dành cho user chạy PHP/web server. Đừng in `.env` khi debug. Nếu nghi ngờ khóa đã từng xuất hiện ở commit, log hoặc ảnh chụp, **thu hồi/rotate khóa ngay**, xóa khỏi nơi lộ và kiểm tra lịch sử sử dụng tại nhà cung cấp; đừng chỉ đổi chữ trong source code. ## 3. Ví dụ cấu hình web server Apache (đổi đường dẫn thực tế, bật HTTPS ở virtual host production): ```apache <VirtualHost *:80> ServerName chatbot.example.vn DocumentRoot /var/www/land-ai-chatbot/public <Directory /var/www/land-ai-chatbot/public> AllowOverride None Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/land-chatbot-error.log </VirtualHost> ``` Nginx + PHP-FPM (mẫu rút gọn): ```nginx server { listen 80; server_name chatbot.example.vn; root /var/www/land-ai-chatbot/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } location ~ /\. { deny all; } } ``` Production cần HTTPS trước khi bật HSTS. Không dùng PHP built-in server cho internet. ## 4. Checklist nghiệm thu trước go-live - [ ] DocumentRoot là `public/`; truy cập `/../.env`, `/database/schema.sql`, `/app/Database.php` đều không tải được. - [ ] `.env` có trong `.gitignore`; không có khóa thật trong Git, database, JS, HTML, log hay forum. - [ ] `APP_DEBUG=false`, HTTPS hoạt động và security headers xuất hiện. - [ ] Câu hỏi không có nguồn đã duyệt bị từ chối an toàn, không có câu trả lời đoán mò. - [ ] Mỗi câu trả lời có nguồn thì giao diện hiển thị URL/tên nguồn và ngày kiểm tra. - [ ] Gửi chuỗi CCCD/số sổ mẫu bị cảnh báo và không được lưu vào `chat_messages`. - [ ] Gửi quá nhanh nhận 429; lỗi AI/DB không trả stack trace, DSN hay secret. - [ ] Người phụ trách đã kiểm tra câu trả lời mẫu với tình huống địa phương thực tế và quy định nội bộ. ## 5. Vận hành kho tri thức Mỗi tài liệu nên có chủ sở hữu và lịch rà soát. Quy trình tối thiểu: nhập `draft` → đối chiếu URL/bản gốc/ngày hiệu lực/phạm vi địa phương → người có trách nhiệm duyệt → `published` → rà soát định kỳ → `archived` khi thay thế/hết hiệu lực. Nếu không chắc văn bản còn hiệu lực, đừng publish. SQL hỗ trợ rà soát nguồn quá cũ (ví dụ trên 180 ngày): ```sql SELECT id, title, source_url, source_checked_at FROM knowledge_documents WHERE status = 'published' AND source_checked_at < CURRENT_DATE - INTERVAL 180 DAY ORDER BY source_checked_at ASC; ``` Audit gần đây: ```sql SELECT event_type, request_id, session_id, created_at FROM audit_events ORDER BY id DESC LIMIT 100; ``` Không đưa toàn bộ `chat_messages` vào công cụ phân tích bên thứ ba. Đặt chính sách xóa/ẩn lịch sử theo mục đích và quy định của tổ chức, rồi kiểm thử backup/restore được mã hóa và phân quyền. ## 6. Các cải tiến sau bản đầu tiên - Dùng migration versioned thay vì sửa trực tiếp `schema.sql` trên production. - Tách rate limit sang Redis khi có nhiều web server. - Thêm trang quản trị duyệt nguồn và kiểm soát quyền truy cập; không cho AI tự publish tài liệu. - Viết test tự động cho XSS, CSRF, prompt-injection, PII, không có nguồn, rate limit và lỗi timeout. - Theo dõi chi phí/timeout của AI bằng số liệu đã giảm thiểu dữ liệu, không log prompt hoặc Authorization header đầy đủ. Như vậy bạn có một chatbot có thể triển khai được, nhưng vẫn biết dừng đúng chỗ: nó hỗ trợ tìm hiểu từ nguồn được duyệt, không thay thế quy trình pháp lý hay quyết định của con người.