Lý do tiếp cận AI trong lập trình Frontend
Hệ sinh thái internet hiện nay đang chứng kiến sự bùng nổ mạnh mẽ của trí tuệ nhân tạo. Đối với các kỹ sư phát triển giao diện người dùng, việc trang bị kiến thức về AI không còn là lựa chọn mà là yêu cầu tất yếu để nâng cao hiệu suất và chất lượng sản phẩm. Dưới đây là lộ trình và những kiến thức nền tảng cần thiết.
Cấu trúc ứng dụng AI điển hình
Một hệ thống ứng dụng AI thường được phân tách thành ba lớp chính:
- Giao diện tương tác (UI): Nơi người dùng nhập liệu và hiển thị kết quả từ mô hình ngôn ngữ lớn (LLM).
- Lớp dịch vụ (Service Layer): Đảm nhận việc xử lý đầu vào, tổ chức lại câu lệnh (Prompt) và quản lý các công cụ hỗ trợ.
- Hạt nhân LLM: Dịch vụ cốt lõi thực thi suy luận và tạo ra nội dung phản hồi.
Những khái niệm cơ bản về Mô hình
Mô hình ngôn ngữ lớn (LLM) đóng vai trò như bộ não, được huấn luyện trên khối lượng dữ liệu khổng lồ để thấu hiểu và tái tạo ngôn ngữ tự nhiên cũng như giải quyết các vấn đề phức tạp.
Tham số mô hình lưu trữ tri thức đã học (ví dụ: 1.5 tỷ hoặc 7 tỷ tham số). Kích thước tham số thường tỉ lệ thuận với khả năng xử lý.
Tập tin tham số chứa các trọng số và độ lệch đã được tối ưu hóa, hoạt động giống như kinh nghiệm giải quyết vấn đề để thực thi nhiệm vụ cụ thể.
Kết nối với Mô hình
Bạn có thể sử dụng các công cụ chạy cục bộ như Ollama để cài đặt và vận hành các phiên bản LLM offline thông qua lệnh ví dụ ollama run deepseek-r1:7b. Tuy nhiên, do giới hạn phần cứng cá nhân, các mô hình địa phương thường ít linh hoạt hơn so với dịch vụ đám mây chuyên nghiệp từ các nhà cung cấp lớn.
Kỹ thuật Prompt (Câu lệnh)
Prompt là cách chúng ta giao tiếp với mô hình, định hướng để nhận được câu trả lời mong muốn. Việc mô tả yêu cầu càng chi tiết thì kết quả càng chính xác, tương tự như cách một sản phẩm trưởng thành mô tả tính năng cho lập trình viên.
Triển khai cấu trúc Message
Trong quá trình lập trình, dữ liệu gửi đến LLM thường là một mảng các đối tượng tin nhắn với vai trò khác nhau:
const conversationContext = [
{ role: 'system', content: 'Bạn là trợ lý ảo hữu ích' },
{ role: 'user', content: 'Yêu cầu của người dùng' },
{ role: 'assistant', content: 'Phản hồi trước đó' },
];
- system: Thiết lập quy tắc và vai trò cố định từ phía developer.
- user: Dữ liệu đầu vào thực tế từ khách hàng.
- assistant: Lịch sử các câu trả lời của AI.
Kiểm soát Hành vi và Ngữ cảnh
Phần system prompt thường được mô hình chú trọng hơn, giúp duy trì phong cách trả lời nhất quán. Ví dụ thiết lập vai trò chuyên gia React:
const systemInstruction = `
### Vai trò
Bạn là chuyên gia tư vấn ReactJS và Ant Design.
### Yêu cầu đầu ra
1. Giải thích tư duy thiết kế trước khi đưa ra mã nguồn.
2. Từ chối các câu hỏi không liên quan đến lập trình web.`;
const chatSession = [
{ role: 'system', content: systemInstruction },
...previousMessages // Bao gồm lịch sử chat
];
Quản lý Bộ nhớ Cuộc hội thoại
Do LLM không tự ghi nhớ cuộc trò chuyện giữa các phiên, ứng dụng phải chủ động truyền tải ngữ cảnh.
Chiến lược tóm tắt: Thay vì gán hết toàn bộ lịch sử (gây tốn token), bạn có thể sử dụng LLM để tóm tắt các cuộc hội thoại cũ thành một đoạn văn ngắn gọn trước khi gửi sang phiên mới.
Giới hạn Token: Hãy lưu ý rằng mỗi lần gọi API đều có giới hạn về độ dài đầu vào và đầu ra. Nếu vượt quá ngưỡng này, hệ thống sẽ báo lỗi hoặc cắt bớt nội dung.
Tích hợp RAG (Retrieval-Augmented Generation)
RAG giúp khắc phục tình trạng thiếu thông tin nội bộ bằng cách kết hợp dữ liệu riêng với mô hình công cộng.
Quy trình xử lý dữ liệu riêng
- Tải dữ liệu: Nhập văn bản, PDF hoặc trích xuất từ web.
- Vectơ hóa: Chuyển đổi văn bản thành dạng vectơ số học để máy tính hiểu được ngữ nghĩa.
- Lưu trữ: Đưa các vectơ vào cơ sở dữ liệu chuyên biệt (Vector DB).
- Tra cứu: Khi có câu hỏi, chuyển câu hỏi thành vectơ và tìm kiếm các tài liệu tương đồng nhất để bổ sung vào Prompt.
Minh họa xử lý dữ liệu với LangChain
Sử dụng thư viện @langchain/community để xử lý việc nhúng và lưu trữ:
import { HuggingFaceTransformersEmbeddings } from "@langchain/huggingface";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
// Cấu hình mô hình nhúng
const embeddingModel = new HuggingFaceTransformersEmbeddings({
modelName: "Xenova/all-MiniLM-L6-v2",
});
// Tách văn bản thành các đoạn nhỏ hơn
const textProcessor = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 200,
});
async function buildKnowledgeBase(documents) {
const chunks = await textProcessor.splitDocuments(documents);
// Tạo và lưu trữ vectơ
const vectorStorage = await FaissStore.fromDocuments(
chunks,
embeddingModel
);
await vectorStorage.save("./db/knowledge-index");
}
Thực thi truy vấn
async function queryKnowledgeBase(userQuestion) {
// Tải lại kho dữ liệu
const storage = await FaissStore.load("./db/knowledge-index", embeddingModel);
// Tìm kiếm 2 nội dung liên quan nhất
const relevantDocs = await storage.similaritySearch(userQuestion, 2);
// Kết hợp nội dung tìm được vào prompt
const contextContent = relevantDocs.map(doc => doc.pageContent).join("\n");
return `${contextContent}\n\nCâu hỏi: ${userQuestion}`;
}
Khai thác Công cụ (Tools / Function Calling)
Để AI không chỉ chat mà còn thực thi hành động, chúng ta cần đăng ký các hàm sẵn sàng để gọi.
Cấu trúc đăng ký hàm
Thay vì dùng Map, ta có thể định nghĩa cấu hình công cụ dưới dạng đối tượng tập hợp, sau đó ánh xạ chúng khi gọi API:
const availableFunctions = {
writeFileToLocal: async (args) => {
try {
// Logic lưu file thay thế ở môi trường Node.js
await fs.promises.writeFile('output.txt', args.code);
return 'Lưu thành công';
} catch (e) {
return 'Lỗi hệ thống file';
}
},
searchApiData: async (args) => {
// Logic gọi API ngoài
return JSON.stringify({ data: 'mock_data' });
}
};
Điều phối lệnh thực thi
Khi nhận được phản hồi từ LLM nếu phát hiện yêu cầu gọi công cụ, hãy đảm bảo xử lý bất đồng bộ đúng cách:
if (response.choices[0].message.tool_calls) {
const calls = response.choices[0].message.tool_calls;
// Sử dụng vòng lặp chờ hoàn tất để tránh lỗi đồng bộ
for (const call of calls) {
const funcName = call.function.name;
const funcArgs = JSON.parse(call.function.arguments);
if (availableFunctions[funcName]) {
const result = await availableFunctions[funcName](funcArgs);
// Gửi kết quả trả về cho AI tiếp tục hội thoại
messages.push({
role: 'tool',
name: funcName,
content: result,
tool_call_id: call.id
});
}
}
}