Skip to content

Ran: trợ lý hỏi đáp của tokyo.conan.school ​

Ran là ô chat nổi ở góc phải mọi trang trong khu thành viên (tokyo.conan.school). Trang này ghi lại Ran biết gì, không biết gì, và vì sao, cùng vòng máy đang mở rộng dần vùng biết đó.

Ran lấy dữ liệu từ đâu ​

Mỗi lượt hỏi, POST /api/ai/chat dựng system prompt từ hai loại nguồn. Phân biệt hai loại này là chìa khoá để đoán trước Ran trả lời được câu nào.

Loại A, đọc thẳng D1 mỗi lượt hỏi (luôn mới, không cần nạp trước):

KhốiNguồnTrả lời được câu gì
Hồ sơ người dùnglegacy_users, legacy_user_private_datanghề, ngành, công ty, dùng để lấy ví dụ đúng ngành
Lịch sử ghi danhlegacy_class_enrollments"tôi đang học lớp nào"
Danh sách khoá đang mởlegacy_courses"Conan có khoá nào"
Learner modellearner_model_aiđiểm mạnh, khoảng trống, nên đọc gì
Papers đã xuất bảnlibrary_papers"có tài liệu nào về X" (chỉ tên + tóm tắt)
Tiến độ họccourse_enrollments, course_concepts, course_concept_progress"tôi học tới đâu", "còn bao nhiêu khái niệm"
Lịch sắp tớilegacy_class_sessions"buổi tới học lúc nào"
Gói thành viên & học phímembership_plans, membership_features, legacy_users.membership_tier"học phí bao nhiêu", "gói Master có gì", "tôi đang ở gói nào"
Điểm, sticker, chứng chỉlearner_experience_totals, learner_sticker_awards, learner_certificates"tôi được bao nhiêu điểm", "tôi có huy hiệu nào"
Bài nộp đã chấmcourse_unit_task_submissions, learner_product_submissions, learner_reflections"bài của em sai chỗ nào", cả task của unit, sản phẩm, lẫn phản tư 4F

Năm khối in đậm là phần mới (01.09.2026).

Loại B, phải NẠP TRƯỚC vào Vectorize rồi mới tìm ra được. Đây là chỗ hay hỏng ngầm nhất: chỉ mục trống thì Ran vẫn trả lời trơn tru, bằng kiến thức chung của model, không phải bằng nội dung Conan School. Xem vòng nạp bên dưới.

Kết quả rà soát 01.09.2026 ​

Rà soát thực hiện bằng cách lần theo mã của chat.ts / prompts.ts / embed.ts và đối chiếu với các bảng thật trong D1, không phải bằng một phiên chat thật (phiên rà soát không có tài khoản thành viên để đăng nhập). Cột "trước" là hành vi trước thay đổi này.

Ran trả lời được ​

Câu hỏi mẫuNhờ khối nào
"Positioning là gì, khác differentiation chỗ nào?"kiến thức chung của model
"Conan đang có những khoá nào?"danh sách khoá đang mở
"Khoá nào hợp với người làm F&B như tôi?"danh sách khoá + hồ sơ người dùng
"Có tài liệu nào về pricing không?"danh mục Papers
"Tôi nên học gì tiếp?"learner model
"Giải thích lại khái niệm này bằng ví dụ ngành tôi"hồ sơ + kiến thức chung

Ran KHÔNG trả lời được (trước thay đổi này) ​

Câu hỏi mẫuVì sao hỏngĐã xử lý
"Tôi đang học tới đâu rồi?"tiến độ chưa từng được đưa vào prompt✅ khối tiến độ
"Buổi học tới của tôi là khi nào?"lịch chưa từng được đưa vào prompt✅ khối lịch
"Unit 3 của khoá X dạy gì?"nội dung unit chưa bao giờ được nạp vào Vectorize✅ vòng nạp
"Bài viết về khái niệm Claim nói gì?"course_concept_articles không nằm trong embed.ts✅ vòng nạp
"Paper X kết luận gì?"chỉ tên + tóm tắt được nạp, không có nội dung✅ vòng nạp
"Nền tảng vừa có tính năng gì mới?"changelogs/announcements không nằm trong nguồn nào✅ vòng nạp
"Học phí bao nhiêu, quyền lợi gói thành viên gồm gì?"giá và quyền lợi hard-code trong frontend, không có trong D1✅ membership_plans
"Điểm/huy hiệu của tôi hiện thế nào?"learner_experience_totals, sticker, chứng chỉ chưa nối✅ khối thành tựu
"Bài nộp của tôi được chấm ra sao?"submissions chưa nối✅ khối bài nộp đã chấm

Ba lỗi hệ thống tìm thấy ​

  1. Chỉ mục kiến thức không có ai nạp. POST /api/ai/embed là đường bấm tay duy nhất, không cron nào gọi nó. Không ai bấm thì chỉ mục đứng yên vô thời hạn, mà Ran vẫn trả lời trôi chảy. Đây đúng loại hỏng nguy hiểm nhất: hỏng mà hệ trông như đang chạy.

  2. embed.ts nạp sai thời đại. Nó nạp ebook_sections, courses, frameworks, ba nguồn của kiến trúc cũ. Toàn bộ nội dung dạy học hiện nay (course_learning_units, course_concepts, course_concept_articles, course_unit_scqa) không có mặt.

  3. Nhân vật không khớp. ✅ Đã sửa, prompts.ts nay mở đầu "Bạn là Ran". (Trước đó giao diện tokyo gọi "Ran"/"bé Ran" còn system prompt tự xưng "Conan Assistant".)

  4. Giá và quyền lợi hội viên sống trong frontend. com.conan.school/app/routes/membership.tsx giữ cả bảng quyền lợi lẫn công thức giá tăng dần theo tháng. Ran không có cách nào biết học phí; và mỗi lần đổi giá là một lượt sửa mã. Nay hai bên cùng đọc GET /api/public/membership/plans, giá được tính ở API chứ không lưu sẵn, nên trang và Ran không thể nói hai con số khác nhau.

Vòng nạp kiến thức ​

RanKnowledgeIndexWorkflow (src/workflows/ran-knowledge-index.ts) chạy mỗi giờ (7 * * * *), mở rộng dần vùng dữ liệu Ran với tới. Thứ tự ưu tiên khi ngân sách một lượt không đủ:

courses → course_learning_units (+SCQA) → course_concepts → course_concept_articles
        → library_papers → announcements → changelogs

Ba tính chất giữ nó không thành vòng đốt tiền:

  • Băm nội dung (ran_knowledge_sources.content_hash), mẩu không đổi thì không gọi model lại.
  • Ngân sách mỗi lượt, cron nạp tối đa 200 mẩu (60 là mặc định khi workflow chạy không tham số), phần còn lại để lượt sau.
  • Sổ, mỗi lượt một dòng ran_knowledge_runs; câu "Ran có biết chuyện này chưa" trả lời được bằng GET /api/ai/embed/status, không phải bằng cách hỏi thử Ran rồi đoán.

Workflow này không sinh nội dung, nó chỉ đọc nội dung do các engine trong course-intelligence sinh ra và nạp vào chỉ mục tìm kiếm, Ran đọc, không ghi.

Vận hành ​

ViệcCách làm
Xem kho kiến thức đang có gìGET /api/ai/embed/status (trả kèm active_index)
Nạp ngay, không đợi cronPOST /api/ai/embed/reindex {"budget":120}
Nạp lại một loại nguồnPOST /api/ai/embed/reindex {"kinds":["library_paper"],"force":true}

Migration phải áp trước khi deploy mã dùng tới nó, thứ tự này nay do CI giữ, xem Quy tắc triển khai.

Embedding đa ngữ: bước cuối, cần tài khoản Cloudflare ​

Chỉ mục conan-knowledge dùng bge-base-en-v1.5: model tiếng Anh cho kho nội dung gần như thuần tiếng Việt. Nó không làm hệ dừng, chỉ làm điểm tương đồng nhiễu, tài liệu đúng rơi ra ngoài ngưỡng, tài liệu lạc lọt vào, âm thầm.

bge-m3 đa ngữ là lời giải nhưng có 1024 chiều thay vì 768, mà số chiều gắn cứng vào Vectorize index. Mã nguồn đã sẵn sàng: src/domains/ai/retrieval.ts chọn cặp (chỉ mục, model) ở một chỗ duy nhất cho cả phía nạp lẫn phía truy vấn, nên hai bên không thể lệch nhau. Chưa gắn binding thì mọi thứ chạy nguyên như cũ.

Việc này không còn phải làm tay. CI tạo chỉ mục ở bước Ensure Vectorize indexes ngay trước bước deploy, trong cùng một job (vectorize_indexes trong deploy-api.yml), nên binding VECTORIZE_VI an toàn khi có mặt trong wrangler.toml. Thứ tự đó không đảo được: deploy với binding trỏ vào chỉ mục chưa tồn tại làm hỏng cả worker, không riêng Ran.

Nạp lại cũng tự động. Sổ ran_knowledge_sources ghi theo từng chỉ mục, nên khi chỉ mục đổi, mọi mẩu đều là "chưa nạp" và vòng nạp làm lại từ đầu. Nếu sổ không phân biệt chỉ mục, phép so băm sẽ báo "không có gì đổi" và để lại một chỉ mục rỗng, trong khi Ran vẫn trả lời trơn tru.

Vì lần nạp đầu phải làm lại vài nghìn mẩu, vòng nạp chạy mỗi giờ (7 * * * *) với ngân sách 200 mẩu, thay vì ghép vào nhịp 6 tiếng. Khi đã đuổi kịp, mỗi lượt gần như miễn phí: nội dung không đổi thì chỉ so băm, không gọi model lần nào.

Dẫn nguồn trong ô chat ​

Dưới mỗi câu trả lời, Ran hiện các chip nguồn nó đã đọc (unit, khái niệm, bài viết, Paper…), bấm được về bài gốc. Nguồn đến trong sự kiện SSE meta và được lưu vào chat_messages.metadata nên mở lại cuộc trò chuyện cũ vẫn thấy.

Đây không phải trang trí. Một câu trả lời dựa trên nội dung Conan School và một câu Ran tự suy ra trông giống hệt nhau, danh sách nguồn là cách duy nhất người học phân biệt được. Cùng một nguyên tắc với /api/ai/embed/status ở phía vận hành: đừng đánh giá bằng cảm giác về câu chữ, hãy nhìn dữ liệu.

Sửa giá và quyền lợi hội viên ​

admin.conan.school → Community → Members → Membership Plans. Sửa được tên gói, câu mô tả, công thức giá (pricing dạng JSON) và ma trận quyền lợi. Giá hiện hành được tính, không lưu sẵn, nên ô "Giá hiện hành" hiển thị đúng con số trang bán hàng đang dùng. Máy chủ từ chối lưu một công thức không cho ra được con số dùng được.

Bước tiếp theo ​

  1. Vòng nạp chưa đụng tới legacy_ebook_sections (Deep Books), hiện vẫn phải bấm tay POST /api/ai/embed cho nguồn đó.
  2. Chuyển sang chỉ mục đa ngữ: mã đã sẵn, CI đã tạo chỉ mục; chỉ còn nạp lại và so chất lượng.

Tài liệu nội bộ nền tảng Conan School.