1. Ngữ cảnh: “chế độ giọng nói” có ý nghĩa gì đối với ChatGPT App
Trước hết cần hiểu rằng trong khuôn khổ ChatGPT Apps SDK, bạn không viết client âm thanh riêng, không điều khiển micro và không tự stream audio. Việc này do client ChatGPT (ứng dụng web hoặc di động) đảm nhiệm.
Giả định bạn đã có hiểu biết cơ bản về widget, callTool và GiftGenius từ các mô‑đun trước — ở đây chúng ta nhìn các thành phần đó dưới lăng kính chế độ giọng nói.
Từ góc nhìn của bạn với tư cách là nhà phát triển App, mọi thứ trông như sau:
- Người dùng nói vào micro. Client ChatGPT nhận dạng giọng nói và gửi văn bản cho mô hình.
- Trong luồng bạn “nhìn thấy” giống như khi người dùng gõ tin nhắn, chỉ là chúng đến nhanh hơn và mang tính hội thoại hơn.
- Mô hình trả lời bằng văn bản, và client sẽ đọc thành tiếng.
- Đồng thời mô hình có thể gọi công cụ của bạn (callTool), thay đổi displayMode của widget, cập nhật widgetState và đề xuất follow‑up — giống như ở chế độ văn bản.
Điểm khác biệt then chốt là người dùng có thể hầu như không nhìn vào màn hình, hoặc chỉ liếc điện thoại. Tức là UI của bạn không còn là kênh tương tác chính mà trở thành phần bổ sung cho giọng nói, chứ không phải ngược lại.
Từ đó kéo theo hai hệ quả:
- Mọi điều thực sự quan trọng phải được hiểu “qua tai”, thông qua lời nói của GPT.
- Widget phải “dễ liếc nhìn” theo nghĩa tốt: chỉ bằng một cái liếc nhanh đã thấy trạng thái và các lựa chọn chính, không cần đọc chữ nhỏ.
Với GiftGenius, đây là gợi ý trực tiếp: kịch bản “đang lái xe, chọn quà cho mẹ” — không còn chỉ là chat văn bản. Đó là hội thoại đa phương thức, nơi giọng nói dẫn dắt còn UI là lớp dự phòng.
2. Khác biệt giữa kịch bản voice và văn bản
Để không rơi vào bẫy “mọi thứ giống nhau, chỉ khác là người dùng nói”, hữu ích là so sánh chế độ văn bản và giọng nói theo vài trục.
| Khía cạnh | Chế độ văn bản | Chế độ giọng nói |
|---|---|---|
| Mức độ chú ý của người dùng | Nhìn màn hình, đọc, cuộn | Có thể không nhìn màn hình (hands‑free) |
| Hình thức yêu cầu | Có cấu trúc hơn, người dùng chỉnh sửa | Hội thoại, câu rời rạc, “ừ”, “làm thêm nữa” |
| Chấp nhận khoảng lặng | 1–2 giây im lặng là bình thường | Im lặng lâu gây khó chịu |
| Vai trò của UI | Kênh chính chứa chi tiết | Bổ trợ, “bảng hiển thị” với điểm tựa trực quan ngắn gọn |
| Lỗi nhập liệu | Lỗi gõ, nhưng văn bản nhìn thấy được | Giọng nói không rõ, nhiễu, “có/không giả” |
Từ đây rút ra vài kết luận quan trọng.
- Không thể trông cậy vào việc người dùng “sẽ đọc trong thẻ”. Những điều trọng yếu phải được nói rõ: bạn đã hiểu gì, định làm gì, và đã nhận được kết quả gì.
- UI phải hỗ trợ kịch bản “liếc 1 giây”. Trạng thái, tiến độ, lựa chọn chính — tất cả phải nổi bật bằng cỡ chữ lớn. Chi tiết là thứ yếu.
- Cần lấp đầy khoảng lặng. Trong khi máy chủ MCP của bạn đang xử lý yêu cầu nặng, mô hình nên nói ra điều đang diễn ra, còn widget — hiển thị tiến độ, để tránh cảm giác trợ lý bị treo.
Hãy nghĩ về chế độ giọng nói như một audiobook có minh họa: bạn có người kể chuyện bằng giọng nói (GPT) và có hình ảnh (widget). Cần đồng bộ chúng để bổ trợ cho nhau, không lặp lại và không mâu thuẫn.
3. Vai trò của widget trong chế độ giọng nói: từ “bảng điều khiển” đến “bảng hiển thị”
Trong kịch bản văn bản, widget thường là giao diện đầy đủ: form, bảng, carousel với bộ lọc, nút hành động. Ở chế độ giọng nói, vai trò này thay đổi. Khuyến nghị về giao diện đa phương thức và VUI cho thấy trong kịch bản voice, UI giống như bảng thông tin (glanceable UI): cần cho việc kiểm tra nhanh và xác nhận, chứ không phải để “làm việc bằng mắt” dày đặc.
Với GiftGenius, điều này có nghĩa như sau.
Khi người dùng đi theo trình tự bằng giọng nói, trên màn hình ở inline‑widget hoặc fullscreen ta hiển thị:
- Trạng thái lớn: “Bước 2/3: ngân sách và loại quà”.
- Ít chữ nhưng nhãn rõ: “Ngân sách tới 50 đô la”, “Ưu tiên quà kỹ thuật số”.
- Vài nút CTA lớn, nếu kịch bản voice cho phép nhấp: “Thay đổi ngân sách”, “Tiếp tục”.
- Một progress‑bar hoặc stepper đơn giản, thay vì hàng chục chỉ báo nhỏ.
Ví dụ “bảng hiển thị” đơn giản trong inline‑widget cho kịch bản voice (TypeScript + React, giản lược mạnh):
type VoiceUiMode = "default" | "voiceGlance";
interface GiftStepProps {
step: number;
totalSteps: number;
summary: string; // mô tả ngắn gọn về những gì đã thu thập
uiMode: VoiceUiMode;
}
export function GiftVoiceStep(props: GiftStepProps) {
const fontSize = props.uiMode === "voiceGlance" ? "text-lg" : "text-sm";
return (
<div className="rounded-xl border p-3 flex flex-col gap-2">
<div className={`${fontSize} font-semibold`}>
Bước {props.step} trên {props.totalSteps}
</div>
<div className={`${fontSize} text-muted-foreground`}>
{props.summary}
</div>
</div>
);
}
Ở đây không có gì “thuần giọng nói”, nhưng có ý tưởng rõ ràng: khi uiMode === "voiceGlance" chúng ta làm mọi thứ lớn và đơn giản hơn. Tín hiệu cho biết đang ở chế độ voice có thể đến từ nhiều nơi: dấu hiệu gián tiếp đến cờ rõ ràng mà mô hình đặt trong widgetState hoặc trong phản hồi từ tool.
4. Đồng bộ các phương thức: GPT nói gì và App hiển thị gì
Nguyên tắc cốt lõi của voice‑UX cho Apps là đồng bộ các phương thức: giọng nói và UI trực quan phải kể cùng một câu chuyện, nhưng ở các mức độ chi tiết khác nhau.
Lỗi thường gặp — khi nhà phát triển buộc mô hình đọc to mọi thứ hiển thị trong widget: danh sách quà dài, cấu trúc JSON với bộ lọc, v.v. Điều này trở thành cực hình. Khuyến nghị: giọng nói đưa ra tóm tắt ngắn, còn UI hiển thị chi tiết.
Ví dụ đồng bộ hợp lý cho GiftGenius.
Người dùng: “Chọn quà cho mẹ, bà ấy thích làm vườn, ngân sách tới 50 đô la”.
Mô hình (bằng giọng nói): “Tôi đã chọn được vài phương án. Phương án tốt nhất theo tôi là bộ dụng cụ làm vườn giá 45 đô la. Trên màn hình tôi hiển thị thêm hai phương án tương tự. Bạn muốn tôi nói chi tiết hay chuyển sang chọn luôn?”
Widget (inline): hiển thị ba thẻ quà với mô tả ngắn và các nút CTA “Chọn” / “Hiển thị tương tự”.
Biểu diễn dạng hội thoại‑JSON của một bước (không phải giao thức thực, chỉ minh họa cách nghĩ):
{
"user": "Hãy chọn quà cho mẹ...",
"assistant_text": "Tôi đã tìm được vài phương án...",
"widget": {
"displayMode": "inline",
"state": {
"view": "gift_list",
"items": [
{ "id": "g1", "title": "Bộ dụng cụ làm vườn", "price": 45 },
{ "id": "g2", "title": "Tạp dề làm vườn", "price": 30 },
{ "id": "g3", "title": "Bộ hạt giống hoa", "price": 20 }
]
}
}
}
Điểm quan trọng: trong system‑prompt bạn có thể ghi rõ cách mô hình nói về UI để không “đọc JSON”: “Nếu bạn hiển thị danh sách phương án trong widget, đừng đọc từng phần tử. Hãy mô tả ngắn gọn phương án tốt nhất và nói rằng các phương án còn lại có trên màn hình”.
Tương lai khi bạn làm với Realtime API và voice‑client của riêng mình, nguyên tắc vẫn vậy: UI và luồng âm thanh phải đồng thuận. Khác biệt chỉ là bạn có quyền kiểm soát trực tiếp việc streaming.
5. Realtime và độ trễ: tránh sự im lặng khó xử
Về kỹ thuật, tool_calls ở chế độ giọng nói giống chế độ văn bản: mô hình quyết định gọi công cụ, bạn trả kết quả, widget cập nhật. Nhưng trong giọng nói nảy sinh một vấn đề UX mới — độ trễ. Khi máy chủ MCP của bạn gọi API bên ngoài hoặc tính toán báo cáo nặng, người dùng nghe thấy… không gì cả. Điều này khó chịu hơn nhiều so với việc chờ văn bản trong chat.
Có hai tầng bảo vệ: giọng nói và trực quan.
- Ở tầng giọng nói, system‑prompt nên cho phép (và khuyến khích) mô hình nói “tôi đang xử lý” và đặt câu hỏi bổ sung trong khi tool vẫn đang chạy. Ví dụ: “Tôi sẽ chọn quà, mất vài giây. Trong lúc chờ, hãy cho biết còn ràng buộc nào khác không.”
- Ở tầng trực quan, widget phải hiển thị tiến độ thật rõ: loader, trạng thái “Đang tìm phương án…”, bước hiện tại. Nếu không, người dùng sẽ nghĩ app bị treo và bắt đầu nói tiếp, làm rối luồng giọng nói.
Trong thực tế, nên xử lý bằng tác vụ trì hoãn: công cụ lập tức trả về trạng thái "pending" và jobId, còn việc chọn lọc chạy nền. Widget dựa vào "pending" hiển thị tiến độ, còn giọng nói thì nói rằng “đang xử lý”.
Sơ đồ tối giản của công cụ phía server trả về “placeholder” với job‑id thay vì chặn đến khi có kết quả đầy đủ có thể như sau:
// Mã giả cho công cụ phía server của GiftGenius
export async function startGiftSearch(params: SearchParams) {
const jobId = await createBackgroundJob(params); // đưa tác vụ vào hàng đợi
return {
status: "pending",
jobId,
message: "Đã khởi động tìm quà"
};
}
Widget, khi thấy status: "pending", có thể chuyển UI sang chế độ hiển thị tiến độ:
if (toolOutput.status === "pending") {
return (
<div className="p-4 rounded-xl border flex items-center gap-3">
<Spinner />
<div className="text-base">
Đang chọn quà… Sẽ mất vài giây.
</div>
</div>
);
}
Và mô hình, theo cùng tool‑output và theo hướng dẫn, sẽ nói điều tương tự và có thể hỏi thêm. Sau đó, khi tác vụ nền hoàn tất và, giả sử, qua MCP‑notification nhận được job.completed, widget cập nhật sang danh sách quà, còn giọng nói đọc tóm tắt.
Như vậy ta đạt hành vi gần realtime nhất, dù backend không phản hồi tức thì.
6. An toàn và xác nhận trong giọng nói
Giao diện giọng nói rất “khó lường” khi đụng tới hành động quan trọng: thanh toán, xóa dữ liệu, đổi cài đặt. Nhận dạng giọng nói không hoàn hảo, người dùng nói khi đang di chuyển, và “ừ” có thể dễ thành “vâng, mua đi”. Vì vậy trong kịch bản voice, confirmation flows cực kỳ quan trọng.
Có hai mẫu cơ bản.
- Xác nhận bằng giọng nói rõ ràng (Explicit Voice Confirmation). Với hành động nguy hiểm, bạn yêu cầu một câu cụ thể. Ví dụ: “Để xác nhận mua hàng, hãy nói: “Tôi xác nhận mua hàng”” — và trong system‑prompt cấm thực hiện thanh toán nếu chỉ nghe thấy những từ mơ hồ như “ừ”, “ok”, “làm đi”.
- Chỉ xác nhận bằng giao diện trực quan (Visual Confirmation Only). Mô hình bằng giọng nói dẫn dắt người dùng tới hành động (“Tôi đã chuẩn bị đơn hàng, trên màn hình hiển thị tổng tiền và giỏ hàng”), nhưng kích hoạt thực tế là bấm nút “Thanh toán” trong widget. Điều này đặc biệt phù hợp với kịch bản thương mại, và chúng ta sẽ quay lại ở mô‑đun 14.
Với GiftGenius có thể như sau.
Mô hình: “Tôi đã chọn một bộ dụng cụ làm vườn rất phù hợp giá 45 đô la. Tôi có thể tiến hành mua qua ChatGPT. Trên màn hình đang hiển thị tổng tiền và địa chỉ giao hàng. Để xác nhận bằng giọng nói, hãy nói “Tôi xác nhận mua hàng”, hoặc bấm nút “Thanh toán” trên màn hình.”
Widget (fullscreen): hiển thị đơn hàng cuối cùng, làm đậm số tiền và địa chỉ, và hai nút rõ ràng: “Thanh toán” và “Hủy”.
Trong widget bạn có thể phản ánh trạng thái xác nhận:
type CheckoutState = "review" | "waiting_voice_confirm" | "confirmed";
if (state.phase === "waiting_voice_confirm") {
return (
<div className="space-y-3">
<h2 className="text-xl font-semibold">Gần xong</h2>
<p className="text-base">
Xác nhận mua hàng bằng giọng nói với câu
“Tôi xác nhận mua hàng” hoặc bấm nút “Thanh toán”.
</p>
<Button variant="primary">Thanh toán</Button>
<Button variant="ghost">Hủy</Button>
</div>
);
}
Như vậy, nếu mô hình vẫn diễn giải sai điều gì đó từ giọng nói, người dùng vẫn có một lớp “an toàn” trực quan.
7. Lệnh giọng nói đơn giản và thiết kế công cụ
Người dùng giọng nói sẽ không diễn đạt lệnh đúng như tên biến của công cụ bạn. Họ sẽ nói “chọn cái đầu tiên”, “hiển thị thêm rẻ hơn”, “đừng dùng đồ công nghệ”. Nhiệm vụ của bạn là thiết kế công cụ và system‑prompt để mô hình dễ dàng ánh xạ các câu như vậy sang lời gọi công cụ của bạn (callTool).
Với GiftGenius có thể dự trù các hành động như:
- Chọn một trong các phương án hiển thị theo chỉ số hoặc id.
- Chỉnh ngân sách: “rẻ hơn”, “tới 30 đô la”.
- Lọc theo loại: “chỉ quà kỹ thuật số”, “không gì cần giao bưu điện”.
Dễ thể hiện qua một công cụ với tham số enum đơn giản action và các trường bổ sung:
// Sơ đồ công cụ giả lập bằng TypeScript
type VoiceActionInput =
| { action: "select_item"; itemId: string }
| { action: "refine_budget"; maxPrice: number }
| { action: "filter_type"; type: "digital" | "physical" };
export function handleVoiceAction(input: VoiceActionInput) {
switch (input.action) {
case "select_item":
// đánh dấu quà được chọn
break;
case "refine_budget":
// tính lại danh sách theo ngân sách mới
break;
case "filter_type":
// lọc danh sách hiện có
break;
}
}
Trong system‑prompt bạn mô tả cách các hành động này tương ứng với lệnh giọng nói: “Nếu người dùng nói “chọn phương án đầu tiên”, hãy gọi công cụ gift.voiceAction với action="select_item" và id của món quà đầu tiên trên màn hình”, v.v.
Về UX, điều này giảm tải nhận thức: người dùng không cần nghĩ ra câu chữ chính xác kiểu “Hãy chỉnh bộ lọc để chỉ còn quà kỹ thuật số tới 30$”. Họ nói tự nhiên, còn mô hình chuyển nó thành cấu trúc dữ liệu.
8. Kịch bản giọng nói cho GiftGenius: ba bước
Hãy ghép tất cả lại và thiết kế một kịch bản giọng nói hoàn chỉnh cho GiftGenius, chưa đi sâu Realtime API cấp thấp.
Hình dung người dùng: họ lái xe và bật chế độ giọng nói của ChatGPT. Họ nói: “Làm ơn chọn quà cho mẹ, bà ấy thích làm vườn, ngân sách tới 50 đô la”.
Bước 1. Thu thập thông tin bằng giọng nói
Mô hình: “Tuyệt, cùng chọn quà nhé. Tôi hỏi thêm vài điều: cần quà trong vài ngày tới hay muộn hơn? Và có hạn chế gì không, ví dụ không muốn đồ nặng hay cồng kềnh?”
Widget (inline): lúc đầu chỉ là một panel nhỏ với trạng thái “Đang chọn quà cho: mẹ, làm vườn, tới 50 đô la”. Cỡ chữ lớn hơn một chút để có thể liếc và đọc ngay.
Mã trạng thái của widget có thể như sau:
interface GiftSessionState {
mode: "voice" | "text";
step: 1 | 2 | 3;
recipientSummary: string;
budget?: number;
}
const [state, setState] = useState<GiftSessionState>({
mode: "voice",
step: 1,
recipientSummary: "Mẹ, thích làm vườn"
});
Phần server sẽ cập nhật recipientSummary và budget theo câu trả lời của người dùng, và widget phản ứng theo đó.
Bước 2. Tìm kiếm và chờ đợi
Sau khi mô hình thu thập đủ thông tin, nó gọi công cụ tìm quà. Công cụ này có thể khởi chạy tác vụ nền nếu việc chọn lọc phức tạp và trả về status: "pending". Trong lúc nền chạy, mô hình nói: “Tôi sẽ tìm phương án phù hợp, mất vài giây. Trong lúc chờ, bạn cho biết cô ấy thích quà vật lý hay chấp nhận chứng chỉ kỹ thuật số?”
Widget chuyển sang chế độ giống PiP nếu người dùng chuyển sang phần khác của giao diện, hoặc vẫn inline với tiến độ: “Đang tìm quà…” kèm chỉ báo nhỏ.
Bước 3. Kết quả và lựa chọn
Khi có kết quả, mô hình: “Tôi đã tìm thấy ba phương án. Đầu tiên — bộ dụng cụ làm vườn giá 45 đô la. Thứ hai — tạp dề làm vườn giá 30 đô la. Tôi đã hiển thị chúng trên màn hình. Hãy nói “chọn cái đầu tiên” hoặc “hiển thị thêm rẻ hơn”.”
Widget hiển thị ba thẻ lớn có giá và mô tả ngắn. Mỗi thẻ có CTA “Chọn” và “Tương tự”. Ngoài ra có nút “Hiển thị thêm phương án”.
Nếu người dùng nói: “Chọn cái thứ hai”, mô hình gọi công cụ voiceAction với action="select_item" và id của món quà thứ hai. Widget đánh dấu nó là đã chọn, còn mô hình nói: “Tuyệt, đã chọn tạp dề làm vườn giá 30 đô la”.
Bước 4 (tùy chọn). Thanh toán
Nếu App tích hợp thanh toán (ở mô‑đun 14 tương lai), bắt đầu luồng checkout. Mô hình nói điều kiện và yêu cầu xác nhận bằng giọng nói hoặc nút bấm. Widget chuyển sang wizard fullscreen với các bước “Kiểm tra đơn hàng” → “Địa chỉ giao hàng” → “Xác nhận”.
Quan trọng là ở mỗi bước, mọi thông tin then chốt đều được nói ra bằng giọng nói, còn widget đóng vai trò điểm tựa trực quan, đặc biệt khi người dùng đã dừng lại và nhìn màn hình.
9. Ghi chú triển khai thực tế và giới hạn của Apps SDK
Tất cả các bước mô tả cho GiftGenius đều được triển khai trong một ChatGPT App thông thường — không cần audio‑client riêng hay WebRTC. Ở đây quan trọng là nhớ các ranh giới của stack.
Rất dễ “trôi” sang chủ đề Realtime API, WebRTC, streaming audio và tự xây một nền tảng voice trong đầu. Cho phần đó có mô‑đun 20 riêng. Trong bài này, hãy nhớ ranh giới của ChatGPT App bên trong client ChatGPT.
Trong kiến trúc hiện tại:
- Luồng audio do client ChatGPT quản lý. Bạn không gửi/nhận byte audio trong widget.
- Ở backend bạn vẫn thấy lời gọi tool và tin nhắn văn bản thông thường, nhưng mô hình có thể ở chế độ voice và câu trả lời sẽ được đọc.
- Nền tảng có thể truyền các dấu hiệu gián tiếp cho biết đang ở voice‑mode (qua user-agent hoặc các trường môi trường). Nhưng đừng phụ thuộc cứng: API có thể thay đổi, và App của bạn vẫn phải hữu ích ở chế độ thuần văn bản.
Vì vậy chiến lược tốt là: trước hết thiết kế UX hoạt động tốt cả cho văn bản lẫn giọng nói: trạng thái ngắn gọn, CTA rõ ràng, giai đoạn tiến độ dễ hiểu. Sau đó thêm vài cải tiến cho giọng nói: phông chữ lớn hơn ở chế độ "voiceGlance", tiến độ rõ ràng hơn, nhấn vào trạng thái như “Bước 2/3” và các trạng thái hiển nhiên như “Đang chờ xác nhận”.
Bổ sung trong system‑prompt, bạn mô tả hành vi giọng nói của mô hình: cách nó bình luận về trạng thái widget, các câu dùng để xác nhận, những điều cần tránh (ví dụ không đọc JSON, không đọc mọi chi tiết trong danh sách).
Nếu sau này bạn xây Custom Voice Client trên Realtime API, các quyết định UX này sẽ “chuyển” qua đó một cách nhẹ nhàng. Khác biệt chỉ là mức độ truy cập sự kiện và streaming, không phải nguyên tắc.
10. Lỗi thường gặp khi làm việc với Voice / Realtime context
Lỗi số 1: “Đọc UI thành tiếng” thay vì tóm tắt.
Đôi khi nhà phát triển viết công cụ khiến mô hình bắt đầu đọc to toàn bộ JSON phản hồi hoặc cả danh sách thẻ. Ở chế độ giọng nói, đó là “sát thủ” UX: người dùng mất phương hướng, còn bạn lãng phí token. Tốt hơn là giọng nói nêu tóm tắt ngắn và tập trung vào một‑hai phương án, phần còn lại để trên màn hình.
Lỗi số 2: Hoàn toàn thiếu phản hồi trực quan trong voice.
Có cám dỗ nghĩ: “Vì người dùng đang nói, tức là họ đang nghe, UI không cần”. Thực tế, người dùng thường liếc màn hình hoặc quay lại sau một phút. Nếu lúc đó không có trạng thái, tiến độ, hay kết quả rõ ràng, họ sẽ nghĩ App bị treo hoặc không làm gì. Hãy luôn hiển thị “Tôi đang nghĩ”, “Bước 2/3”, “Kết quả đã sẵn sàng”, v.v.
Lỗi số 3: Hành động nguy hiểm không có xác nhận mạnh.
Ở chế độ văn bản, làm nút “Thanh toán” một lần bấm đã là rủi ro; ở giọng nói còn rủi ro hơn nếu thực hiện mua chỉ vì một tiếng “ừ”. Bỏ qua confirmation flows rõ ràng (giọng nói và/hoặc trực quan) dẫn đến mua nhầm và mất niềm tin vào App. Hãy cân nhắc kỹ hành động nào cần xác nhận kép và nêu rõ trong system‑prompt và UI.
Lỗi số 4: Chỉ tối ưu cho mắt, quên cái tai.
Đôi khi App được thiết kế như thể người dùng luôn đọc chữ: câu văn phức tạp, nút quá dài, mô tả rối rắm. Ở chế độ giọng nói, mọi thứ đó còn phải được nói ra — thành “súp từ ngữ”. Hãy giữ ý chính trong các câu ngắn, đơn giản, dễ nghe hiểu.
Lỗi số 5: Nhầm lẫn giữa Apps SDK và Voice‑client riêng.
Một số học viên tìm kiếm trong Apps SDK các sự kiện micro, audio streaming, WebRTC như ở Realtime API, rồi thất vọng vì “không có”. Hãy hiểu: ChatGPT App sống trong client ChatGPT, còn giọng nói do nền tảng điều phối. Bạn làm việc với văn bản, lời gọi tool và trạng thái widget, và thiết kế UX để chế độ giọng nói “đơn giản hoạt động tốt”. Nếu cần toàn quyền kiểm soát giọng nói, đó là dự án riêng với Realtime API, phức tạp hơn.
Lỗi số 6: Thiếu chiến lược xử lý độ trễ.
Nếu không suy nghĩ trước mô hình sẽ nói gì và widget sẽ hiển thị gì trong lúc tác vụ dài, người dùng sẽ ngắt lời, hỏi thêm và phá vỡ luồng của bạn. Độ trễ trong giọng nói cảm nhận mạnh hơn văn bản. Hãy dùng trạng thái trung gian, xử lý nền và các câu giọng nói kiểu “tôi đang xử lý, trong lúc chờ hãy kể thêm…” để sự im lặng không biến thành lỗi.
GO TO FULL VERSION