Khóa học
Chainlit là một framework Python mã nguồn mở mạnh mẽ cho phép bạn xây dựng giao diện tương tác cho các ứng dụng dùng LLM chỉ với ít mã và không cần bận tâm đến front-end.
Trong hướng dẫn này, tôi sẽ trình bày:
- Cài đặt và thiết lập Chainlit.
- Hiểu các khái niệm cốt lõi như actions, vòng đời chat và cấu hình.
- Xây dựng hai ứng dụng ví dụ:
- Một chatbot tĩnh “Surprise Me” sử dụng nút bấm
- Một bot “Surprise Me” chạy bằng Ollama
Chainlit là gì?
Chainlit giúp bạn tạo frontend cho chatbot AI, công cụ và quy trình làm việc với LLM. Nó trừu tượng hóa sự phức tạp của front-end và cho phép bạn tập trung vào logic Python, đồng thời hỗ trợ thêm nút bấm, thanh trượt, tải tệp, hoặc thậm chí kết nối công cụ bằng model context protocol (MCP).
Chainlit phù hợp để:
- Làm mẫu nhanh các ứng dụng dựa trên LLM
- Tạo công cụ nội bộ
- Xây dựng các bản demo giáo dục
- Kết nối mô hình của bạn với công cụ hoặc API bên ngoài
Các thành phần của Chainlit
Mỗi ứng dụng Chainlit được xây dựng trên một vài tính năng thiết yếu:
- Hook vòng đời chat: Cho phép bạn kiểm soát những gì xảy ra ở các giai đoạn khác nhau của cuộc trò chuyện. Ví dụ:
@cl.on_chat_startchạy khi một cuộc trò chuyện bắt đầu.@cl.on_messagechạy khi người dùng gửi tin nhắn.@cl.on_chat_endchạy khi cuộc trò chuyện kết thúc.- Hành động UI: Chainlit cho phép bạn thêm nút bấm với
cl.Actionvà xử lý bằng@cl.action_callback. Điều này rất hữu ích để xây dựng UI gọn gàng, tương tác mà không cần người dùng nhập văn bản. - Streaming tin nhắn: Với các LLM hỗ trợ streaming token, bạn có thể stream phản hồi theo thời gian thực bằng
stream=True, giúp ứng dụng sinh động và phản hồi nhanh hơn. - Cấu hình với
config.toml: Tệp này cho phép bạn bật các tính năng như lưu trữ phiên chat, tải tệp, tùy biến chủ đề và tinh chỉnh khả năng sử dụng—tất cả mà không cần sửa mã Python.
Tôi sẽ giải thích từng khái niệm với ví dụ mã thực hành để bạn thấy chính xác cách hoạt động và cách tích hợp vào ứng dụng Chainlit của mình. Hãy bắt đầu với bước đầu tiên.
Yêu cầu tiên quyết
Hãy đảm bảo bạn đã cài Python 3.8+, sau đó cài Chainlit bằng pip. Chúng ta cũng sẽ dùng Langchain cho phần demo với Ollama, nên hãy cài đặt nó. Chạy lệnh sau trong terminal:
pip install chainlit langchain langchain-community
Hiểu các kiến thức cơ bản về Chainlit qua ví dụ
Trong phần này, chúng ta sẽ đề cập đến các khối xây dựng cốt lõi của Chainlit, vốn là nền tảng của mọi dự án.
Hook vòng đời chat
Bất cứ khi nào người dùng kết nối với ứng dụng Chainlit của bạn, một phiên chat được tạo. Bạn có thể can thiệp vào các giai đoạn khác nhau của phiên đó bằng các decorator do Chainlit cung cấp, bao gồm:
Xây dựng với @cl.on_chat_start
Hook này chạy khi một phiên chat mới bắt đầu. Bạn có thể dùng để chào mừng người dùng, hiển thị thông điệp chào, hoặc khởi tạo trạng thái phiên.
import chainlit as cl
@cl.on_chat_start
def on_chat_start():
print("A new chat session has started!")

Xây dựng với @cl.on_message
Hook này chạy khi người dùng gửi tin nhắn mới. Chúng ta dùng nó để xử lý đầu vào, gọi LLM, hoặc trả về phản hồi.
import chainlit as cl
@cl.on_message
async def on_message(msg: cl.Message):
print("The user sent:", msg.content)
await cl.Message(content=f"You said: {msg.content}").send()

Xây dựng với @cl.on_stop
Hook on_stop chạy khi người dùng nhấn nút dừng (⏹) trong lúc một tác vụ đang chạy. Dùng để hủy các thao tác chạy lâu hoặc dọn dẹp các phiên bị gián đoạn.
import chainlit as cl
import asyncio
@cl.on_chat_start
async def start():
await cl.Message("Type anything and I'll pretend to work on it.").send()
@cl.on_message
async def on_message(msg: cl.Message):
await cl.Message("Working on it... you can press Stop").send()
try:
# Simulate a long task
await asyncio.sleep(10)
await cl.Message("Task complete!").send()
except asyncio.CancelledError:
print("Task was interrupted!")
# This is optional, just logs in the server
raise
@cl.on_stop
async def on_stop():
print("The user clicked Stop!")
Khi người dùng gửi tin nhắn, Chainlit mô phỏng một tác vụ với asyncio.sleep(10). Nếu người dùng nhấn nút dừng (⏹), tác vụ bị hủy và @cl.on_stop được kích hoạt để ghi nhật ký việc gián đoạn.

Xây dựng với @cl.on_chat_end
Hook này được kích hoạt khi phiên kết thúc—người dùng làm mới, đóng tab hoặc bắt đầu phiên mới. Thường dùng để ghi nhận ngắt kết nối hoặc lưu trạng thái.
import chainlit as cl
@cl.on_chat_start
async def on_chat_start():
await cl.Message("Welcome! Feel free to leave anytime").send()
@cl.on_chat_end
async def on_chat_end():
print("The user disconnected!")
Khi localhost được mở, bạn có thể tương tác với nó. Khi bạn đóng tab hoặc cửa sổ localhost, terminal sẽ hiển thị như sau:

Hành động UI (nút bấm)
Chainlit cho phép bạn thêm các nút tương tác trực tiếp vào giao diện chatbot. Mỗi nút được định nghĩa là một action và kết nối với một hàm callback Python. Bạn gửi nút kèm theo một Message bằng tham số actions:
import chainlit as cl
@cl.on_chat_start
async def start():
actions = [
cl.Action(
name="hello",
label="👋 Say Hello",
icon="smile",
payload={"value": "hi"}
)
]
await cl.Message("Click a button!", actions=actions).send()
Cách xử lý khi một nút được nhấp:
@cl.action_callback("hello")
async def on_hello(action: cl.Action):
await cl.Message("Hello there! 👋").send()
Decorator @cl.action_callback("hello") báo cho Chainlit lắng nghe các lần nhấp trên nút có tên "hello". Khi được nhấp, nó gửi một thông điệp thân thiện tới người dùng trong giao diện chat.

Mẹo: Bạn có thể tùy biến payload với bất kỳ dữ liệu nào muốn gửi về server.
Streaming tin nhắn
Chainlit hỗ trợ streaming phản hồi của LLM theo thời gian thực. Điều này có nghĩa bạn có thể gửi nội dung dần dần cho người dùng khi nó được tạo ra.
@cl.on_message
async def on_message(message: cl.Message):
await cl.Message(content="Thinking...").send()
async for chunk in llm.astream(message.content):
await cl.Message(content=chunk, author="LLM", stream=True).send()
Hãy phân tích từng phần:
- Đầu tiên, hiển thị ngay thông điệp "Thinking..." để người dùng biết ứng dụng đang xử lý.
- Sau đó, gửi tin nhắn của người dùng tới một LLM hỗ trợ streaming.
- Khi mô hình tạo đầu ra, từng phần (chunk) được stream về UI theo thời gian thực.
- Tham số
stream=Trueđảm bảo từng chunk xuất hiện dần, thay vì chờ đủ toàn bộ phản hồi.
Lưu ý: Hoạt động tốt nhất với các mô hình hỗ trợ streaming.
Cấu hình Chainlit (config.toml)
Để mở khóa các tính năng mạnh mẽ như lưu trữ phiên chat, tải tệp, chủ đề và hơn thế nữa, bạn có thể tùy biến ứng dụng Chainlit bằng tệp config.toml. Tệp này nằm ở thư mục gốc dự án (trong thư mục .chainlit) và cho phép điều chỉnh hành vi runtime mà không cần sửa mã.
Lưu trữ (Persistence)
Tham số này cho phép Chainlit lưu lịch sử chat và trạng thái phiên. Nó kích hoạt hook @cl.on_chat_resume, rất phù hợp cho ứng dụng nơi người dùng có thể ngắt kết nối và quay lại sau.
[persistence]
enabled = true
Tải tệp
Thiết lập này cho phép người dùng tải tệp trong giao diện chat. Bạn có thể giới hạn loại tệp được phép và kích thước tệp để đảm bảo an toàn và hiệu năng.
[features.spontaneous_file_upload]
enabled = true
accept = ["*/*"]
max_files = 5
max_size_mb = 500
Dưới đây là một vài kiểu tệp được Chainlit chấp nhận.
# 1. For specific file types:
# accept = ["image/jpeg", "image/png", "application/pdf"]
# 2. For all files of a certain type:
# accept = ["image/*", "audio/*", "video/*"]
# 3. For specific file extensions:
# accept = { "application/octet-stream" = [".xyz", ".pdb"] }
Điều này cho phép bạn điều chỉnh tải tệp vì mục đích an toàn, hiệu năng, hoặc các trường hợp sử dụng theo lĩnh vực.
Tùy biến UI
Tùy biến này thay đổi tên trợ lý trong tham số UI và bật Chain of Thought (CoT) trong chế độ hiển thị, hữu ích cho suy luận từng bước hoặc gỡ lỗi.
[UI]
name = "Assistant"
cot = "full"
Tinh chỉnh khả năng sử dụng
Các thiết lập này cải thiện trải nghiệm bằng cách tự động cuộn đến tin nhắn mới và cho phép chỉnh sửa tin nhắn.
[features]
user_message_autoscroll = true
edit_message = true
Các tinh chỉnh trên cho phép người dùng bật tính năng tự cuộn và chỉnh sửa tin nhắn ngay trong UI.
Dự án: Surprise Me Bot (Không dùng LLM)
Giờ khi đã biết các thành phần cơ bản của Chainlit, hãy xây dựng một ứng dụng UI đơn giản dùng nút bấm để hiển thị các fun fact định sẵn hoặc thông điệp tạo động lực cho lập trình viên.
import chainlit as cl
import random
FUN_FACTS = [
"💡 Did you know? Chainlit supports file uploads and custom themes!",
"💡 You can add buttons, sliders, and images directly in your chatbot UI!",
"💡 Chainlit supports real-time tool execution with LangChain and LLMs!",
"💡 You can customize the look of your chatbot with just a CSS file!",
"💡 Chainlit lets you connect to tools using Model Context Protocol (MCP)!"
]
SUPRISES = [
"🎉 Surprise! You're doing great!",
"🚀 Keep it up, you're making awesome progress!",
"🌟 Fun fact: Someone out there just smiled because of you. Why not make it two?",
"👏 Bravo! You just unlocked +10 imaginary developer XP!",
"💪 Remember: Even bugs fear your debugging skills!"
]
@cl.on_chat_start
async def start():
actions = [
cl.Action(
name="surprise_button",
label="🎁 Surprise Me",
icon="gift",
payload={"value": "surprise"}
),
cl.Action(
name="fact_button",
label="💡 Did You Know?",
icon="lightbulb",
payload={"value": "fact"}
)
]
await cl.Message(content="Choose an action:", actions=actions).send()
@cl.action_callback("surprise_button")
async def on_surprise(action: cl.Action):
suprise = random.choice(SUPRISES)
await cl.Message(content=suprise).send()
@cl.action_callback("fact_button")
async def on_fact(action: cl.Action):
fact = random.choice(FUN_FACTS)
await cl.Message(content=fact).send()
Đoạn mã trên định nghĩa hai danh sách: “FUN_FACTS” cho các mẹo Chainlit thú vị và “SUPRISES” cho thông điệp tạo động lực.
- Khi một phiên chat mới bắt đầu, nó hiển thị hai nút: "Surprise Me" và "Did You Know?"—bằng
cl.Action. ' - Nhấp "Surprise Me" sẽ kích hoạt @cl.action_callback("surprise_button")
, gửi một thông điệp bất ngờ ngẫu nhiên. - Nhấp "Did You Know?" sẽ kích hoạt @cl.action_callback("fact_button")`, gửi một fun fact ngẫu nhiên.
Điều này tạo ra một chatbot tương tác đơn giản dùng nút bấm, không cần LLM, rất phù hợp để học cách hoạt động của actions và callbacks trong Chainlit.
Để chạy ứng dụng này, chỉ cần chạy lệnh sau trong terminal:
chainlit run main.py
Bạn sẽ thấy các nút tương tác trong UI để bật fun fact hoặc thông điệp vui!

Dự án: Surprise Me Bot chạy bằng Ollama
Giờ hãy tự động hóa quy trình này và tạo các thông điệp bất ngờ và fun fact bằng LLM cục bộ thông qua Ollama.
import chainlit as cl
from langchain_community.llms import Ollama
import random
llm = Ollama(model="mistral", temperature=0.7) # Use any lightweight local model
# Reusable action buttons
def get_action_buttons():
return [
cl.Action(
name="surprise_button",
label="🎁 Surprise Me",
icon="gift",
payload={"value": "surprise"}
),
cl.Action(
name="fact_button",
label="💡 Did You Know?",
icon="lightbulb",
payload={"value": "fact"}
)
]
@cl.on_chat_start
async def start():
await cl.Message(content="Choose an action below to see something fun:").send()
await cl.Message(content="", actions=get_action_buttons()).send()
@cl.action_callback("surprise_button")
async def on_surprise(action: cl.Action):
prompt = "Give a short, uplifting surprise message to a developer. Make it fun."
try:
surprise = llm.invoke(prompt).strip()
except Exception:
surprise = "🎉 Surprise! You're doing great!"
await cl.Message(content=surprise).send()
await cl.Message(content="", actions=get_action_buttons()).send()
@cl.action_callback("fact_button")
async def on_fact(action: cl.Action):
prompt = "Give a fun and helpful fact about LLMs or Chainlit."
try:
fact = llm.invoke(prompt).strip()
except Exception:
fact = "💡 Did you know? You can add sliders and buttons to Chainlit with just a few lines of code!"
await cl.Message(content=fact).send()
await cl.Message(content="", actions=get_action_buttons()).send()
Ứng dụng Chainlit này tích hợp một LLM cục bộ (qua Ollama với mô hình Mistral) để tạo phản hồi động dựa trên tương tác của người dùng.
- Nó định nghĩa hai nút
cl.Action—"Surprise Me" và "Did You Know?" bằng hàmget_action_buttons()có thể tái sử dụng. - Khi khởi tạo chat (
@cl.on_chat_start) sẽ gửi một tin nhắn kèm các nút tương tác này. - Khi người dùng nhấp nút "Surprise Me", handler
@cl.action_callbackgửi prompt tới LLM yêu cầu một thông điệp ngắn, truyền cảm hứng cho lập trình viên. Phản hồi được làm sạch bằng hàm.strip()và gửi lại vào chat. - Tương tự, nhấp "Did You Know?" sẽ gọi LLM với prompt yêu cầu một fun fact hữu ích về Chainlit hoặc LLM.
- Nếu LLM gặp lỗi, sẽ trả về phản hồi tĩnh dự phòng.
- Sau mỗi tương tác, các nút được gửi lại để duy trì vòng hội thoại.
Điều này minh họa cách kết hợp UI của Chainlit với việc tạo nội dung dựa trên LLM, cung cấp nền tảng mô-đun và dễ mở rộng cho các ứng dụng chat AI cục bộ.
Chạy các lệnh sau trong terminal:
ollama run mistral
chainlit run main.py
Giờ bạn đã có một trợ lý AI cục bộ đang hoạt động, tạo thông điệp tự động.

Kết luận
Chainlit có tiềm năng mạnh mẽ cho việc làm mẫu công cụ dựa trên chat, xây dựng trợ lý và tích hợp đầu ra LLM theo thời gian thực—tất cả mà không cần động đến JavaScript. Với các trường hợp nâng cao, hãy xem Chainlit Cookbook.
Để mở rộng việc học với các công cụ AI mới, hãy xem các blog sau:
Tôi là Chuyên gia Google Developers trong lĩnh vực ML (Gen AI), Chuyên gia Kaggle 3x và Đại sứ Women Techmakers với hơn 3 năm kinh nghiệm trong ngành công nghệ. Tôi đồng sáng lập một startup công nghệ y tế vào năm 2020 và hiện đang theo học thạc sĩ khoa học máy tính tại Georgia Tech, chuyên sâu về học máy.
