AI Hunter
Member
Anh em nhìn lại source code của mình xem. Có phải file
Đó là kiến trúc Monolith (Nguyên khối). Và nó là cơn ác mộng khi bảo trì.
Hôm nay, chúng ta sẽ chuyển sang kiến trúc Client-Server.
Tại sao lại là FastAPI?
Đơn giản vì nó... nhanh (như tên gọi), hỗ trợ Async (bất đồng bộ) cực tốt cho AI, và tự động sinh document API (Swagger UI) siêu xịn.
Cài đặt:
Tạo một file mới tên là
Mở terminal và chạy:
Truy cập http://localhost:8000/docs. Bạn sẽ thấy giao diện Swagger UI hiện ra. Hãy thử test gửi tin nhắn ngay trên web, nếu thấy JSON trả về là Backend đã ngon!
Bây giờ quay lại file
Ở ví dụ trên, chúng ta dùng Request/Response thông thường (đợi AI nghĩ xong mới trả về hết). Để làm hiệu ứng chữ chạy (Streaming) qua API, bạn cần dùng
(Phần này khá dài và phức tạp, tôi sẽ dành riêng một bài Advanced Tutorial nếu anh em có nhu cầu).
Chúc mừng! Bạn vừa thăng cấp từ "Coder dạo" thành "Software Architect".
Hệ thống Jarvis của bạn giờ đây đã sẵn sàng để vươn ra biển lớn.
app.py của Chainlit đang phình to ra cả trăm dòng code không? Nào là logic RAG, nào là Memory, nào là Search, nào là xử lý UI...Đó là kiến trúc Monolith (Nguyên khối). Và nó là cơn ác mộng khi bảo trì.
Hôm nay, chúng ta sẽ chuyển sang kiến trúc Client-Server.
- Server (Backend): Chạy bằng FastAPI. Chịu trách nhiệm suy nghĩ, xử lý dữ liệu, kết nối Database. (Chỉ trả về JSON).
- Client (Frontend): Chạy bằng Chainlit. Chỉ chịu trách nhiệm hiển thị và gửi yêu cầu về Server.
1. Vũ khí: FastAPI
Tại sao lại là FastAPI?
Đơn giản vì nó... nhanh (như tên gọi), hỗ trợ Async (bất đồng bộ) cực tốt cho AI, và tự động sinh document API (Swagger UI) siêu xịn.
Cài đặt:
Mã:
pip install fastapi uvicorn pydantic requests
2. Bước 1: Xây dựng Backend (Server)
Tạo một file mới tên là
server.py. Đây sẽ là "bộ não" độc lập của Jarvis.
Python:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from openai import OpenAI
# Import các module cũ của bạn (RAG, Search, Memory...) vào đây
# from my_agent_logic import get_answer
app = FastAPI(title="Jarvis Brain API")
client = OpenAI(api_key="sk-proj-xxxx")
# 1. Định nghĩa cấu trúc dữ liệu đầu vào (Request Model)
class ChatRequest(BaseModel):
user_id: str
message: str
enable_search: bool = False
# 2. Định nghĩa cấu trúc dữ liệu đầu ra (Response Model)
class ChatResponse(BaseModel):
answer: str
thought_process: str = None # Để hiển thị Chain of Thought
# 3. Tạo Endpoint xử lý Chat
@app.post("/chat", response_model=ChatResponse)
async def chat_endpoint(req: ChatRequest):
print(f"📩 Nhận tin nhắn từ {req.user_id}: {req.message}")
try:
# --- LOGIC AI NẰM Ở ĐÂY ---
# (Thay vì viết trực tiếp, bạn nên gọi hàm từ các module khác)
# Giả lập logic xử lý
system_prompt = "Bạn là Jarvis."
if req.enable_search:
system_prompt += " Hãy dùng Search Tool nếu cần."
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": req.message}
]
)
answer_text = response.choices[0].message.content
return ChatResponse(
answer=answer_text,
thought_process="Đã check Memory -> Đã check Search -> Tổng hợp."
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# 4. Endpoint kiểm tra sức khỏe hệ thống
@app.get("/health")
def health_check():
return {"status": "Jarvis is alive and kicking! 🚀"}
# Chạy server: uvicorn server:app --reload
Mở terminal và chạy:
Mã:
uvicorn server:app --reload
Truy cập http://localhost:8000/docs. Bạn sẽ thấy giao diện Swagger UI hiện ra. Hãy thử test gửi tin nhắn ngay trên web, nếu thấy JSON trả về là Backend đã ngon!
3. Bước 2: Cập nhật Frontend (Client)
Bây giờ quay lại file
app.py (Chainlit). Chúng ta sẽ xóa sạch logic AI đi, chỉ giữ lại code gọi API.
Python:
import chainlit as cl
import requests
API_URL = "[URL]http://localhost:8000/chat[/URL]"
@cl.on_chat_start
async def start():
await cl.Message(content="Jarvis API Client Connected! 🔗").send()
@cl.on_message
async def main(message: cl.Message):
# Chuẩn bị dữ liệu gửi đi
payload = {
"user_id": "user_demo", # Sau này có thể lấy từ session
"message": message.content,
"enable_search": True
}
# Hiển thị trạng thái đang suy nghĩ
msg = cl.Message(content="")
await msg.send()
# Gọi sang FastAPI (Server)
# Lưu ý: Ở môi trường Production nên dùng aiohttp để gọi bất đồng bộ
try:
response = requests.post(API_URL, json=payload)
if response.status_code == 200:
data = response.json()
# Hiển thị suy nghĩ (nếu có)
if data.get("thought_process"):
async with cl.Step(name="Thinking Process") as step:
step.output = data["thought_process"]
# Hiển thị câu trả lời cuối cùng
msg.content = data["answer"]
await msg.update()
else:
msg.content = f"Lỗi Server: {response.text}"
await msg.update()
except Exception as e:
msg.content = f"Không kết nối được tới não bộ Jarvis: {str(e)}"
await msg.update()
4. Tại sao làm thế này lại "Xịn"?
- Độc lập tác chiến: Team AI cứ việc tối ưu model, sửa logic Search ở file
server.py. Team Frontend cứ việc sửa màu sắc, thêm nút bấm ởapp.py. Hai bên không dẫm chân lên nhau. - Mở rộng vô biên: Bạn có thể bật 10 cái Server FastAPI chạy song song để phục vụ 1000 user (Load Balancing), trong khi vẫn chỉ dùng 1 giao diện Chainlit.
- Đa nền tảng: Giờ bạn muốn viết App Android? Chỉ việc gọi vào
http://localhost:8000/chat. Xong phim!
5. Nâng cao: Streaming Response
Ở ví dụ trên, chúng ta dùng Request/Response thông thường (đợi AI nghĩ xong mới trả về hết). Để làm hiệu ứng chữ chạy (Streaming) qua API, bạn cần dùng
StreamingResponse của FastAPI và xử lý stream ở phía Client.(Phần này khá dài và phức tạp, tôi sẽ dành riêng một bài Advanced Tutorial nếu anh em có nhu cầu).
Tổng kết
Chúc mừng! Bạn vừa thăng cấp từ "Coder dạo" thành "Software Architect".
Hệ thống Jarvis của bạn giờ đây đã sẵn sàng để vươn ra biển lớn.
Bài viết liên quan