Courses
Grok Voice Think Fast 2.0 của SpaceXAI là một mô hình chuyển giọng nói thành giọng nói. Bạn gửi âm thanh qua WebSocket và nó trả về âm thanh; trong lúc đó, nó có thể suy luận và tiếp tục nói ngay cả khi một lệnh gọi hàm mà nó đã quyết định thực hiện đang chạy. Không cần bước tách riêng chuyển giọng nói thành văn bản, cũng không cần bước chuyển văn bản thành giọng nói riêng.
SpaceXAI đã công bố Think Fast 2.0 vào ngày 29 tháng 7 năm 2026: âm thanh đầu tiên nhanh hơn, hành vi song công ổn định hơn (lắng nghe trong khi đang nói thay vì luân phiên nghiêm ngặt), và các lệnh gọi công cụ được kích hoạt sớm trong lượt. Tôi sẽ nói ngắn gọn về benchmark, vì điều quan trọng với một hướng dẫn là những gì thay đổi trong mã của bạn.
Chúng ta sẽ xây dựng một tác nhân thoại hỗ trợ khách hàng cho một cửa hàng trực tuyến. Người gọi có thể hỏi về một đơn hàng, tìm đơn theo email khi không có số, thay đổi hướng dẫn giao hàng, hủy, ngắt lời tác nhân giữa câu, và tiếp tục cuộc trò chuyện sau khi kết nối bị rớt. Đây là lộ trình API, không phải công cụ không cần mã Voice Agent Builder mà hướng dẫn Grok Voice Agent Builder của chúng tôi đã trình bày. Hãy bắt đầu từ đó nếu bạn làm bản ưu tiên console.
Grok Voice Think Fast 2.0 là gì?
Grok Voice Think Fast 2.0 là mô hình mới nhất của SpaceXAI cho Speech to Speech API, tên sản phẩm đằng sau thứ mà hầu hết mọi người gọi ngắn gọn là Grok Voice. Nếu bạn vẫn nghĩ công ty là xAI, vẫn là tổ chức đó: đã sáp nhập vào SpaceX và đổi thương hiệu thành SpaceXAI vào ngày 6 tháng 7 năm 2026. API không đổi theo thương hiệu, nên mọi định danh bên dưới vẫn là xai, từ biến XAI_API_KEY tới máy chủ api.x.ai.
Một stack thoại truyền thống xâu chuỗi ba dịch vụ: chuyển giọng nói thành văn bản, mô hình ngôn ngữ, sau đó chuyển văn bản thành giọng nói; mỗi bước làm tăng độ trễ và có thể làm mất ngữ cảnh. Think Fast 2.0 gộp lại thành một mô hình nhận đầu vào âm thanh hoặc văn bản và tạo đầu ra âm thanh hoặc văn bản trên cùng một kết nối.

WebSocket chuyển giọng nói thành giọng nói so với kiến trúc pipeline ba dịch vụ. Hình do Tác giả thực hiện.
Với một tác nhân biết hành động thay vì chỉ biết nói, điều quan trọng là suy luận và giọng nói chạy song song. SpaceXAI nói rằng các lệnh gọi công cụ "thường" bắt đầu chạy trước khi tác nhân kết thúc câu đầu tiên, và chữ “thường” ở đây thực sự có ý nghĩa.
Trên các benchmark SpaceXAI trích dẫn từ Artificial Analysis, Think Fast 2.0 đạt 82,9% trên Speech to Speech Index so với 75,7% của 1.0, và giảm thời gian đến âm thanh đầu tiên từ 1,25 giây xuống 0,70 giây. Số liệu nhà cung cấp trên một benchmark tổng quát là một giả thuyết về luồng cuộc gọi của bạn, không phải kế hoạch kiểm thử.
Có ba chuỗi tên mô hình bạn sẽ thấy: grok-voice-latest, grok-voice-think-fast-2.0, và grok-voice-think-fast-1.0. Alias tiện khi dựng thử, nhưng không đủ ổn định cho các mục đích khác.
Khi tôi kiểm thử vào ngày 4 tháng 8 năm 2026, grok-voice-latest vẫn trỏ về grok-voice-think-fast-1.0, và ghi chú phát hành của SpaceXAI lên lịch chuyển sang Think Fast 2.0 vào ngày hôm sau. Chuyển đổi này là thay đổi giá cũng như thay đổi mô hình, 0,08 đô la mỗi phút âm thanh so với 0,05 đô la cho bản 1.0, nên một alias không ghim phiên bản sẽ trở nên đắt hơn dù mã của bạn không đổi. Hãy ghim chuỗi phiên bản trong mọi thứ bạn triển khai.
Chúng ta sẽ xây dựng gì
Tác nhân bao quát những gì một tổng đài hỗ trợ thường nhận: tra một đơn hàng, tìm theo email khi người gọi không có số đơn, đổi hướng dẫn giao hàng, hủy, mở hoặc kiểm tra phiếu hỗ trợ, và chuyển cuộc gọi tới người thật. Ngắt lời và rớt kết nối sẽ xuất hiện trên đường đi.
Đây là một vài tệp nhỏ chứ không phải một script, vì mỗi phần có một nhiệm vụ khác nhau và bạn sẽ muốn kiểm thử riêng rẽ. Cấu trúc như sau:
-
config.pynạp khóa API và giữ chuỗi mô hình, tần số mẫu và các URL endpoint -
voice_client.pyđóng gói WebSocket, theo dõi tính cước, và cung cấp các hàm trợ giúp gửi/nhận -
tools.pyđịnh nghĩa các hàm xử lý đơn hàng và một kho đơn hàng trong bộ nhớ nhỏ thay cho cơ sở dữ liệu thật -
assistant.pychứa prompt hệ thống, cấu hình phiên và vòng lặp sự kiện để gắn kết mọi thứ -
token_server.pylà một endpoint FastAPI nhỏ tạo token tạm thời -
app_streamlit.pyđặt cùng client sau một cuộc gọi trực tiếp trên trình duyệt, tôi sẽ quay lại phần này sau phần kiểm thử
Lộ trình giảng dạy chạy từ terminal. Bản demo thêm micro.
Điều kiện tiên quyết
Bạn cần một tài khoản SpaceXAI với khóa API, một sắp xếp thanh toán đã nạp tiền (không có tầng miễn phí vĩnh viễn, và tín dụng khuyến mại cho tài khoản mới sẽ không đủ), và đủ quen với asyncio và WebSocket để theo kịp mà không cần giải thích từng dòng về await.
Ví dụ khởi động nhanh của SpaceXAI dùng gói websockets thô thay vì một SDK chuyên dụng, và chúng ta cũng vậy. Tài liệu không nêu phiên bản Python bắt buộc. Tôi kiểm thử trên 3.11.
Giữ khóa API trên máy chủ. Nếu một ứng dụng trình duyệt hoặc di động nói chuyện trực tiếp với Voice API, nó nhận một token tạm thời thay vì khóa thật của bạn, được đề cập trong phần bảo mật bên dưới.
Thiết lập dự án
Mọi tệp dưới đây đều có trong repo dự án, nên bạn có thể clone thay vì chép từng đoạn:
git clone https://github.com/KhalidAbdelaty/grok-voice-think-fast-2.0.git
cd grok-voice-think-fast-2.0
pip install -r requirements.txt
websockets mang kết nối realtime và python-dotenv đọc khóa của bạn. Phần còn lại phục vụ endpoint token và bản demo trình duyệt. Đặt khóa của bạn trong .env:
XAI_API_KEY=xai-your-key-here
Đó là phần lớn cài đặt. Kết nối mới là phần thú vị.
Tìm hiểu Grok Voice Realtime API
Grok Voice là tên sản phẩm. Thứ bạn thực sự viết mã để tương tác là một endpoint WebSocket tại wss://api.x.ai/v1/realtime, và toàn bộ cuộc hội thoại diễn ra như một luồng sự kiện JSON qua một socket duy nhất.
Vòng đời sự kiện
Một kết nối theo một khuôn cố định: máy chủ gửi session.created và conversation.created ngay khi bạn kết nối, bạn gửi session.update để cấu hình giọng và công cụ, máy chủ xác nhận bằng session.updated, và từ đó bạn tạo các mục hội thoại và yêu cầu phản hồi. Tôi chạy thử với khóa thật và thứ tự khớp tài liệu hoàn toàn.
-
session.update(client) cấu hình giọng nói, hướng dẫn, công cụ và định dạng âm thanh -
conversation.item.create(client) thêm tin nhắn người dùng, tin nhắn trợ lý, hoặc kết quả công cụ -
response.create(client) yêu cầu mô hình nói; VAD phía máy chủ sẽ tự gửi thay bạn -
response.output_audio.deltavàresponse.output_audio_transcript.delta(server) stream câu trả lời khi nó được tạo -
response.done(server) đóng lượt
Có hai điều dễ gây nhầm. Trang tài liệu Speech to Speech mà tôi dẫn ở trên có đề cập một sự kiện conversation.item.created trong lúc nối lại phiên, nhưng tham chiếu sự kiện chính thống chỉ liệt kê conversation.item.added, và đó là thứ tôi nhận được trong mọi bài test, nên hãy code theo nó. Bạn cũng sẽ thấy một sự kiện ping không được tài liệu hóa vài giây sau khi kết nối, chỉ nhắc để bạn không đọc nhầm là lỗi.
Định dạng âm thanh và cách truyền
Codec và cách truyền là các lựa chọn riêng. Codec, đặt dưới audio.input.format và audio.output.format, là audio/pcm (Linear16, mặc định 24000 Hz), audio/pcmu hoặc audio/pcma (G.711 ở 8 kHz, cho thoại), hoặc audio/opus (24 kHz). Cách truyền là cách các byte đó đi trên dây:
-
json(mặc định) gửi âm thanh dạng văn bản base64 bên tronginput_audio_buffer.appendvàresponse.output_audio.delta, dễ ghi log và gỡ lỗi -
binarygửi byte codec thô dưới dạng frame nhị phân WebSocket, bỏ qua overhead base64 nhưng vòng lặp nhận phải rẽ nhánh theo kiểu thông điệp
Hãy bắt đầu với JSON. Mọi ví dụ trong tài liệu đều dùng nó, dễ kiểm tra, và overhead base64 không phải nút thắt cổ chai trong một tác nhân hỗ trợ. Chuyển sang nhị phân nếu bạn đo thấy có lý do.
Tương thích với OpenAI Realtime API
Bỏ qua nếu bạn chưa từng dùng OpenAI Realtime API. Với những người khác, Speech to Speech API bám khá sát OpenAI Realtime API đủ để hầu hết mã client có thể port bằng cách đổi base URL và khóa, nhưng không hoàn toàn thả-vào-là-chạy.
Bản chép lời đến dưới dạng conversation.item.input_audio_transcription.updated ở đây thay vì delta của OpenAI, một vài sự kiện OpenAI không được hỗ trợ, và SpaceXAI thêm các phần mở rộng riêng: force_message cho câu thông báo bắt buộc, resumption cho kết nối lại, và replace để sửa cách phát âm tên thương hiệu trước khi chuyển văn bản thành giọng nói.
Xây dựng tác nhân thoại thời gian thực
Bấy nhiêu về giao thức là đủ. Đây là client để nói chuyện với nó.
Kết nối và cấu hình phiên
Kết nối mở bằng bearer token và tham số truy vấn model, và thông điệp đầu tiên bạn gửi sẽ cấu hình mọi thứ về cách tác nhân hoạt động:
import asyncio
import json
import os
import websockets
MODEL = "grok-voice-think-fast-2.0" # pin the version, not grok-voice-latest
async def connect():
url = f"wss://api.x.ai/v1/realtime?model={MODEL}"
ws = await websockets.connect(
url, additional_headers={"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"}
)
await ws.send(json.dumps({
"type": "session.update",
"session": {
"voice": "eve",
"instructions": SYSTEM_PROMPT,
"turn_detection": {"type": "server_vad"},
"tools": ORDER_TOOLS,
"resumption": {"enabled": True},
}
}))
return ws
instructions là prompt hệ thống, và mô hình này muốn prompt ngắn. Ghi chú chuyển đổi của SpaceXAI khuyên đơn giản hóa các prompt viết cho các mô hình thoại thời GPT cũ thay vì bê nguyên. Prompt của tôi dặn tác nhân trả lời ngắn gọn, hỏi từng câu một, và đọc lại mọi thao tác ghi trước khi thực hiện. Xác nhận bằng lời là một điểm cộng về UX, không phải biện pháp bảo mật. Ứng dụng của bạn vẫn phải thực thi ủy quyền trên chính thao tác ghi đó.
Một điều khiến tôi bất ngờ: một chuỗi model không được nhận diện không báo lỗi tại thời điểm kết nối, mà âm thầm rơi về grok-voice-think-fast-1.0. Hạ cấp một yêu cầu trả phí chỉ vì lỗi gõ mà không nói gì là một mặc định lạ. Ghi log trường session.model của session.created một lần khi khởi động và kiểm tra xem bạn nhận đúng thứ mình yêu cầu.

Đầu ra terminal hiển thị session.created sau khi kết nối. Hình do Tác giả thực hiện.
Streaming âm thanh người dùng
Với turn_detection.type đặt là server_vad, bạn chỉ cần liên tục bổ sung âm thanh. Máy chủ quyết định khi nào người gọi ngừng nói và kích hoạt phản hồi thay bạn. Nếu đặt là null thì bạn tự chịu trách nhiệm quyết định đó, cam kết buffer một cách tường minh khi bạn cho rằng lượt đã kết thúc.
async def send_audio_chunk(ws, pcm_bytes: bytes):
await ws.send(json.dumps({
"type": "input_audio_buffer.append",
"audio": base64.b64encode(pcm_bytes).decode(),
}))
Server VAD có ba núm vặn, và chỉnh sai chúng là cách phổ biến nhất khiến một tác nhân thoại cảm giác “hỏng” dù log không báo lỗi. Mặc định không có cái nào xuất hiện trong phần echo của session.updated, nên hãy kiểm soát theo tài liệu thay vì đoán.
-
threshold(0,1 đến 0,9, mặc định 0,85), mức âm lượng để tính là giọng nói; tăng lên trong phòng ồn, giảm nếu bỏ lỡ người nói nhỏ -
silence_duration_ms, khoảng lặng của người gọi trước khi máy chủ kết thúc lượt; quá ngắn sẽ cắt ngang khi họ đang nghĩ, quá dài sẽ thấy ì ạch -
prefix_padding_ms(mặc định 333), một lát âm thanh giữ lại ngay trước khi phát hiện giọng nói, để không bị cắt mất âm tiết đầu
Hãy tinh chỉnh silence_duration_ms đầu tiên nếu người gọi liên tục bị cắt ngang khi tạm dừng để nghĩ. Đây là núm tôi chọn trước khi đụng vào hai núm còn lại.
Nhận và phát phản hồi
Âm thanh đến thành từng mẩu nhỏ dưới dạng response.output_audio.delta, và mục đích của streaming là bạn phát từng mẩu ngay khi nó đến thay vì chờ response.done.
async def play_response(ws):
async for message in ws:
event = json.loads(message)
if event["type"] == "response.output_audio.delta":
chunk = base64.b64decode(event["delta"])
speaker.write(chunk) # your playback call goes here
elif event["type"] == "response.output_audio_transcript.delta":
print(event["delta"], end="", flush=True)
Giữ lại bản chép lời ngay cả trong sản xuất. Đó là công cụ gỡ lỗi rẻ nhất cho trường hợp người gọi nói tác nhân "nói điều gì đó kỳ lạ".
Thêm công cụ vào tác nhân thoại
Một tác nhân thoại chỉ biết nói thì cũng chỉ là chatbot có micro.
Tạo các công cụ xử lý đơn hàng
Mỗi công cụ là một JSON schema cộng với một hàm Python thuần ở phía chúng ta. Mô hình không bao giờ chạm vào cơ sở dữ liệu, nó chỉ thấy những gì hàm của chúng ta trả về.
ORDER_TOOLS = [
{
"type": "function",
"name": "check_order_status",
"description": "Look up the status, ETA, and delivery instructions for an order.",
"parameters": {
"type": "object",
"properties": {
"order_number": {"type": "string", "description": "e.g. ORD-1042"},
},
"required": ["order_number"],
},
},
# find_orders, update_delivery_instructions, cancel_order,
# create_support_ticket, check_ticket_status and transfer_to_human
# all follow the same shape
]
Các thao tác đọc như check_order_status có thể an toàn để thử lại nếu hết thời gian. Các thao tác ghi thì không: thử lại update_delivery_instructions sau một lần hết thời gian mơ hồ có thể áp dụng cùng thay đổi hai lần. Một câu xác nhận trong prompt không ngăn được điều đó, nên hãy cấp khóa idempotency hoặc kiểm tra trùng lặp cho các thao tác ghi.
Hãy đặt điều kiện từ chối ngay trong hàm. cancel_order trả về lý do và phương án thay thế thay vì hủy một đơn đã gửi, vì prompt nói "không bao giờ hủy đơn đã gửi" chỉ là gợi ý, còn một hàm từ chối thì không.
Xử lý vòng lặp gọi công cụ
Bốn bước, và thứ tự quan trọng hơn bạn nghĩ. Mô hình gửi response.function_call_arguments.done, mã của bạn chạy hàm, bạn gửi kết quả lại như một mục function_call_output , và chỉ sau đó bạn mới yêu cầu mô hình tiếp tục.
async def handle_tool_call(ws, event):
args = json.loads(event["arguments"])
result = execute(event["name"], args) # never raises; errors come back as {"error": ...}
await ws.send(json.dumps({
"type": "conversation.item.create",
"item": {
"type": "function_call_output",
"call_id": event["call_id"],
"output": json.dumps(result),
},
}))
Nếu mô hình cần hơn một công cụ cho một yêu cầu, nó sẽ bắn nhiều sự kiện function_call_arguments.done trước khi bất kỳ âm thanh nào phát. Xử lý tất cả và gửi mọi kết quả trước khi gửi một response.create. Gửi quá sớm và mô hình sẽ trả lời thiếu ngữ cảnh từ các lệnh đang chạy.
Có một điểm cần chú ý mà SpaceXAI có tài liệu và tôi vẫn dính ở lần đầu: gửi response.create ngay khi kết quả công cụ của bạn được gửi có thể chồng lên câu mở đầu mà tác nhân vẫn đang phát. Có lần nó mở đầu bằng "Tôi sẽ kiểm tra trạng thái đơn ORD-1042 ngay lập tức" và gọi công cụ giữa câu, nên phản hồi ngay lúc đó sẽ đè lên chính câu mở đầu của nó.
Hãy đợi âm thanh của lượt hiện tại kết thúc, và hiển thị trạng thái "đang nghĩ" ngắn ở giữa.

Luồng gọi công cụ trước khi tiếp tục phản hồi. Hình do Tác giả thực hiện.
Quản lý ngắt lời và trạng thái hội thoại
Hai vấn đề riêng. Người gọi nói chồng lên tác nhân giữa phản hồi, và một WebSocket bị rớt cần nối lại.
Hỗ trợ ngắt lời tự nhiên
Với server_vad bật, barge-in là tự động phía máy chủ: ngay khi phát hiện người gọi lại nói, nó báo input_audio_buffer.speech_started và dừng sinh phản hồi cũ. Việc của bạn là nửa còn lại phía client, xóa hàng đợi âm thanh đã xếp để tác nhân im lặng thay vì hoàn tất một câu không ai muốn nghe.
if event["type"] == "input_audio_buffer.speech_started":
playback_queue.clear()
Với các phiên thủ công, không dùng VAD, response.cancel làm cùng việc theo yêu cầu. Cũng có conversation.item.truncate để cắt gọn một mục của trợ lý về phần thực tế đã phát. Tài liệu xác nhận nó tồn tại nhưng không nói thời điểm gọi trong lúc barge-in trực tiếp, nên bạn cần tự thử thời điểm.
Tôi đã kiểm thử với một thay đổi hướng dẫn giao hàng giữa phản hồi: bắt đầu yêu cầu, rồi ngắt lời bằng một phần địa chỉ khác giữa lúc tác nhân xác nhận. Điều quan trọng là tác nhân áp dụng hướng dẫn đã chỉnh thay vì lặng lẽ hoàn tất hướng dẫn cũ, không chỉ là âm thanh đã dừng. Hãy đối chiếu bản ghi đơn hàng, không phải khoảng lặng. Bản demo trình duyệt ở phần cuối cho bạn nghe thử.
Nối lại một phiên bị rớt
Nối lại phiên là tùy chọn và không phải bộ nhớ. Đặt resumption.enabled: true trong session.update, lấy ID từ sự kiện conversation.created, và nếu socket rớt, kết nối lại với ?conversation_id=<id> trong URL và bật lại tùy chọn trên kết nối mới.
async def reconnect(conversation_id):
url = f"wss://api.x.ai/v1/realtime?model={MODEL}&conversation_id={conversation_id}"
ws = await websockets.connect(url, additional_headers=auth_header)
await ws.send(json.dumps({"type": "session.update", "session": {"resumption": {"enabled": True}}}))
return ws
Các lượt đã cache, bản chép lời, lệnh gọi công cụ và kết quả công cụ sẽ phát lại trước câu hỏi tiếp theo của bạn, và bộ nhớ đệm biến mất sau 30 phút không hoạt động. Tôi đã kiểm thử bằng cách hỏi về một đơn, rớt kết nối, và nối lại để hỏi tiếp mà không lặp lại; tác nhân nêu lại ETA chính xác.
Một điểm không được tài liệu hóa: phát lại không đến tức thì, nên một câu hỏi bắn ra ngay lúc socket mở có thể vượt trước và trả về mà không nhớ lượt trước. Hãy chờ một chút trước khi đổ lỗi cho cơ chế nối lại.

Bản log terminal của một phiên được nối lại. Hình do Tác giả thực hiện.
Đừng dùng cái này thay cho việc lưu trạng thái đơn hàng vào cơ sở dữ liệu của bạn. Nếu bộ nhớ đệm hết hạn hoặc người gọi quay lại vào ngày mai, bạn bắt đầu từ con số không, và đó là chủ ý thiết kế.
Bảo mật và giám sát tác nhân
Không bao giờ đặt khóa API vĩnh viễn trong mã trình duyệt hoặc di động. Nếu một client kết nối trực tiếp thay vì qua máy chủ của bạn, hãy tạo một token sống ngắn:
from fastapi import FastAPI
import httpx, os
app = FastAPI()
@app.post("/session")
async def create_session():
async with httpx.AsyncClient() as client:
response = await client.post(
"https://api.x.ai/v1/realtime/client_secrets",
headers={"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"},
json={"expires_after": {"seconds": 300}},
)
return response.json() # {"value": "xai-realtime-client-secret-...", "expires_at": ...}
Trình duyệt không thể đặt header Authorization tùy chỉnh trên bắt tay WebSocket, nên nó truyền token qua header sec-websocket-protocol, với tiền tố xai-client-secret..

Máy chủ tạo token, trình duyệt tham gia cuộc gọi. Hình do Tác giả thực hiện.
Tính cước chạy theo hai thước đo. Âm thanh, gửi hoặc nhận, tính theo mức 0,08 đô la mỗi phút như đã nói, tức 4,80 đô la một giờ, và mỗi conversation.item.create không phải âm thanh và không phải function_call_output tốn cố định 0,004 đô la. response.create không bị tính phí. Mỗi response.done kèm một đối tượng usage, trong thử nghiệm của tôi báo output_audio_seconds cùng billable_audio_seconds riêng. Hãy tính cước từ đó, không phải từ ước tính.
Giới hạn được tài liệu hóa với Speech to Speech API là 10 phiên đồng thời mỗi đội và giới hạn phiên 120 phút, đều ở us-east-1. Đừng lập kế hoạch dung lượng dựa trên các con số của Voice Agent API, vốn khác nhau.
Về quyền riêng tư, hãy diễn đạt chính xác. Câu hỏi bảo mật của SpaceXAI nói rằng yêu cầu và phản hồi API được lưu giữ mã hóa 30 ngày để giám sát lạm dụng và không dùng để huấn luyện nếu không có phép, và đội có thể bật Zero Data Retention, dù ZDR làm mất lịch sử hội thoại của tác nhân thoại đã lưu và do đó không hoạt động với nối lại.
Nếu bạn cần thông báo cuộc gọi được ghi âm hoặc do AI xử lý, đó là chức năng mà phần mở rộng force_message làm. Câu được phát nguyên văn như viết thay vì bất kỳ cách diễn đạt lại nào của mô hình.
Kiểm thử tác nhân thoại
Mã trạng thái 200 trên bắt tay WebSocket không nói gì về việc tác nhân có làm đúng không. Hãy kiểm thử kết quả, không chỉ kết nối.
- Một lần tra đơn sạch, đối chiếu câu trả lời nói với bản ghi, không chỉ là có phản hồi
- Một phản hồi bị ngắt lời, xác nhận phát dừng và tác nhân xử lý yêu cầu mới
- Một cập nhật giao hàng cần xác nhận, kiểm tra với bản ghi đơn
- Một từ chối, như hủy đơn đã gửi, nơi tác nhân phải giải thích quy định thay vì xin lỗi
- Một số đơn không tồn tại, đảm bảo tác nhân nói thẳng thay vì bịa trạng thái
- Một công cụ trả về lỗi, kiểm tra tác nhân nói ra lỗi thay vì treo
- Kết nối lại và nối lại phiên, bao gồm khoảng trễ phát lại mà tôi gặp
- Âm thanh ồn, nói nhanh, và người gọi đánh vần số và địa chỉ
Tôi chạy hầu hết các bài này với khóa thật khi viết. Những lỗi thú vị mang tính hành vi, không phải lỗi hệ thống: thời điểm nối lại như trên, và một ngưỡng VAD vượt phạm vi vẫn được chấp nhận thay vì bị từ chối, kiểu vấn đề sẽ âm thầm trôi nếu bạn chỉ kiểm thử đường hạnh phúc. Thêm một bài kiểm thử đa ngôn ngữ nữa, và xem phần Câu hỏi thường gặp về một điểm đáng chú ý trong cách bạn đặt tên ngôn ngữ.
Hai bài trong số đó bạn không thể kiểm thử bằng gõ phím. app_streamlit.py là một trang Streamlit đặt một cuộc gọi trực tiếp trong trình duyệt: micro stream vào cùng WebSocket qua WebRTC, giọng của tác nhân stream ngược lại, và socket giữ mở suốt phiên.
streamlit run app_streamlit.pyNói chồng lên tác nhân và nó sẽ dừng, vì speech_started đến và trang xóa hàng đợi âm thanh. Đó là cái bắt tay từ phần ngắt lời, chạy trong thực tế.
Theo dõi bản ghi đơn hàng thay vì bản chép lời: tác nhân đọc lại một thay đổi giao hàng và nói đã thực hiện, và bản ghi hoặc đã đổi hoặc chưa. Hãy đeo tai nghe. Với loa ngoài, tác nhân sẽ tự nghe chính mình, coi đó là barge-in, và tự cắt câu, đây là dự báo về việc người gọi dùng loa ngoài sẽ làm bạn gặp gì.
Giới hạn và lưu ý triển khai Grok Voice Think Fast 2.0
Hãy tính đến những điều này: lệnh gọi công cụ thất bại giữa lượt, mô hình nói xác nhận tự tin hơn mức hành động thực sự thành công, VAD tinh chỉnh cho văn phòng yên tĩnh sẽ vỡ vụn trên đường dây điện thoại, và người gọi đổi ý giữa câu.
Với thanh toán, truy cập tài khoản, hoặc khi người gọi có vẻ bối rối hay khó chịu, hãy chuyển tới người thật. Cho mô hình một công cụ transfer_to_human cho việc đó: nếu không có, nó sẽ tự bịa một lời xin lỗi thay vì leo thang.
Một stack dạng mô-đun chuyển giọng nói thành văn bản, mô hình ngôn ngữ, chuyển văn bản thành giọng nói vẫn có chỗ đứng: kiểm soát riêng từng thành phần và có bản chép lời xác định trước khi bất kỳ suy luận nào diễn ra, đổi lại là nhiều công việc tích hợp hơn. Và nếu khối lượng của bạn không cần đối thoại trực tiếp qua lại, một chatbot văn bản hoặc job chép lời hàng loạt sẽ đơn giản và rẻ hơn một pipeline thời gian thực mà không ai đang nói chuyện cùng.
Kết luận
Trong các bài kiểm thử trong bài viết này, grok-voice-think-fast-2.0 chủ yếu làm đúng như tài liệu nói. Vòng đời sự kiện ổn, một kết nối bị rớt quay lại với các lượt trước còn nguyên, và mô hình gọi một công cụ trong khi vẫn đang nói câu mở đầu.
Ngoài việc lệch tên ở conversation.item.added, điều đáng lưu ý là phần lớn công việc còn lại nằm ở phía bạn của socket: hàng đợi phát, khi nào nên im lặng, khi nào chưa nên hỏi tiếp.
Nếu bắt đầu dự án hôm nay, mặc định của tôi sẽ là chuỗi mô hình có phiên bản thay vì alias, server_vad với silence_duration_ms được tinh chỉnh trước hai núm còn lại, truyền JSON cho đến khi có lý do đo đếm được để dùng nhị phân, resumption.enabled bật ngay trên session.update đầu tiên, và session.model được ghi log khi khởi động.
Những thói quen tôi sẽ mang vào bất kỳ tác nhân thoại nào: kiểm tra thao tác ghi với bản ghi thay vì xác nhận bằng lời nói, đặt điều kiện từ chối trong công cụ thay vì trong prompt, để phát xả hàng đợi trước response.create tiếp theo, và kiểm thử với giọng thật, tiếng ồn thật, và các công cụ hỏng theo đúng cách chúng hỏng.
Những mở rộng hiển nhiên là thoại qua điện thoại (SpaceXAI có tài liệu hỗ trợ SIP trực tiếp), một client trình duyệt dùng token tạm, một kết nối MCP vào CRM thật, và một phiên bản đa ngôn ngữ đúng nghĩa. Và nếu Voice Agent API mà tôi so sánh các giới hạn phiên kia phù hợp hơn với nhu cầu của bạn, hướng dẫn Grok Voice Agent API của chúng tôi bao quát lộ trình đó.
Tôi là một kỹ sư dữ liệu và người xây dựng cộng đồng, làm việc với pipeline dữ liệu, đám mây và công cụ AI, đồng thời viết các hướng dẫn thực hành, tác động cao cho DataCamp và các nhà phát triển mới nổi.
Câu hỏi thường gặp
Sử dụng grok-voice-latest trong sản xuất có an toàn không?
Không hẳn, như tôi đã đề cập trong phần quản lý phiên bản phía trên. Nó thay đổi theo ngày SpaceXAI chọn, không phải bạn, và kéo theo hóa đơn của bạn. Hãy ghim grok-voice-think-fast-2.0 và để alias cho các thử nghiệm cục bộ, nơi một cú chuyển bất ngờ sẽ không rơi vào cuộc gọi khách hàng trực tiếp.
Grok Voice Think Fast 2.0 có hỗ trợ ngôn ngữ khác tiếng Anh không?
Có, hơn hai mươi ngôn ngữ được tài liệu hóa với tự động nhận diện, và bạn có thể thiên lệch chép lời về một ngôn ngữ cụ thể bằng language_hint. Lưu ý tiếng Tây Ban Nha và Bồ Đào Nha cần mã vùng như es-MX hoặc pt-BR. Một es hay pt trần không được chấp nhận, và mã không nhận diện sẽ bị bỏ qua âm thầm và rơi về tự động nhận diện, nên lỗi gõ ở đây không khiến bạn tốn gì nhưng cũng không có tác dụng.
Tôi có thể đổi giọng nói không, và có bao nhiêu giọng?
eve là giọng trong tài liệu và là giọng tôi dùng, ngoài ra còn có ara, rex, sal và leo, cùng các ID giọng tùy chỉnh. GET /v1/tts/voices trả về danh sách hiện tại. Nếu nhịp nói khiến bạn khó chịu, audio.output.speed nhận 0,7 đến 1,5.
Tôi có thể làm cho tác nhân trả lời nhanh hơn không?
Hãy thử reasoning.effort, tôi đã bỏ qua trong phần hướng dẫn vì mặc định thường hợp lý. Nó mặc định là "high" và cũng nhận "none", giảm mức độ lập kế hoạch mỗi lượt. Ổn với luồng tra cứu đơn giản. Tôi sẽ không đụng vào nó với bất cứ thứ gì phải chọn giữa các công cụ.
Tôi có cần SDK chính thức của SpaceXAI để xây dựng cái này không?
Không, giống như phần điều kiện tiên quyết đã nói. Gói websockets thuần hoặc một client tương thích OpenAI trỏ vào base URL api.x.ai đều hoạt động. Một điều cần biết: xai-sdk chính thức là client gRPC riêng, không nói chuyện với WebSocket này, nên đừng tìm các phương thức realtime trên đó. Nếu muốn một điểm khởi đầu khác, xai-cookbook có mẫu cho iOS, web, WebRTC và thoại qua điện thoại.
