Chuyển đến nội dung chính

Hướng dẫn API Grok Voice Think Fast 2.0: Xây dựng tác nhân thoại thời gian thực bằng Python

Tìm hiểu cách dùng Grok Voice Think Fast 2.0 để xây dựng tác nhân thoại thời gian thực xử lý hội thoại, gọi công cụ, quản lý ngắt lời, và nối lại các phiên bị ngắt kết nối.
Đã cập nhật 9 thg 8, 2026  · 15 phút đọc

Khám phá với AI

ChatGPTClaudePerplexity

Grok Voice Think Fast 2.0 của SpaceXAI là một mô hình chuyển giọng nói sang giọng nói. Bạn gửi âm thanh qua WebSocket và nó trả lại âm thanh; trong lúc đó, nó có thể suy luận và tiếp tục nói trong khi một lệnh gọi hàm mà nó đã quyết định thực hiện đang chạy. Không có bước tách riêng chuyển giọng nói thành văn bản, cũng không có bước tách riêng chuyển văn bản thành giọng nói.

SpaceXAI đã công bố Think Fast 2.0 vào ngày 29 tháng 7, 2026: âm thanh đầu tiên nhanh hơn, hành vi song công ổn định hơn (lắng nghe khi đang nói thay vì luân phiên nghiêm ngặt), và các lệnh gọi công cụ khởi chạy 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 cửa hàng trực tuyến. Người gọi có thể hỏi về đơn hàng, thay đổi chỉ dẫn giao hàng, hủy, ngắt lời tác nhân giữa câu, và nối lại cuộc trò chuyện sau khi kết nối bị rớt. Đây là con đường API, không phải Trình dựng Tác nhân Thoại không cần mã 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 muốn phiên bản ưu tiên bảng điều khiển.

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 chỉ gọi là Grok Voice. Nếu bạn vẫn nghĩ công ty là xAI, thì vẫn vậy: nó đã được sáp nhập vào SpaceX và tái thương hiệu thành SpaceXAI vào ngày 6 tháng 7, 2026. API không theo việc đổi thương hiệu, nên mọi định danh bên dưới vẫn là xai, từ biến XAI_API_KEY đến máy chủ api.x.ai.

Một ngăn xếp thoại truyền thống xích ba dịch vụ: chuyển giọng nói thành văn bản, một mô hình ngôn ngữ, rồi chuyển văn bản thành giọng nói, và mỗi bước thêm độ trễ cũng như nơi dễ mất ngữ cảnh. Think Fast 2.0 gộp thành một mô hình nhận vào âm thanh hoặc văn bản và xuất ra âm thanh hoặc văn bản trên cùng một kết nối.

Sơ đồ so sánh pipeline dạng mô-đun STT-LLM-TTS với một kết nối WebSocket Grok Voice duy nhất.

WebSocket chuyển giọng nói sang giọng nói so với kiến trúc pipeline ba dịch vụ. Ảnh: Tác giả.

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 cho biết các lệnh gọi công cụ "thường" bắt đầu thực thi trước khi tác nhân kết thúc câu đầu tiên, và từ đó có ý nghĩa thực sự.

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 tới âm thanh đầu tiên từ 1,25 giây xuống 0,70 giây. Con số của 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 một kế hoạch kiểm thử.

Bạn sẽ thấy ba chuỗi tên mô hình: grok-voice-latest, grok-voice-think-fast-2.0grok-voice-think-fast-1.0. Bí danh thì tiện khi dựng mẫu, nhưng không đủ ổn định cho việc khác.

Khi tôi thử nghiệm ngày 4 tháng 8, 2026, grok-voice-latest vẫn trỏ về grok-voice-think-fast-1.0, với ghi chú phát hành của SpaceXAI lên lịch chuyển sang Think Fast 2.0 cho ngày hôm sau. Việc chuyển này là thay đổi giá cũng như thay đổi mô hình, $0,08 mỗi phút âm thanh so với $0,05 của 1.0, nên một bí danh không ghim phiên bản sẽ đắt hơn dù mã của bạn không đổi dòng nào. 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 xử lý những gì một đường dây hỗ trợ thường gặp: tra cứu đơn hàng, tìm đơn từ email khi người gọi không có số, thay đổi chỉ dẫn giao hàng, hủy, mở hoặc kiểm tra phiếu hỗ trợ, và chuyển cuộc gọi cho người thật. Các lần ngắt lời và rớt kết nối sẽ xuất hiện dọc đường.

Đây là một vài tệp nhỏ thay vì một script đơn, vì mỗi phần có nhiệm vụ khác nhau và bạn sẽ muốn kiểm thử riêng. Cấu trúc như sau:

  • config.py nạp khóa API và giữ chuỗi mô hình, tần số mẫu, và URL endpoint

  • voice_client.py bọc WebSocket, theo dõi tính phí, và cung cấp các hàm hỗ trợ gửi/nhận

  • tools.py định nghĩa các hàm đơn hàng và một kho đơn hàng trong bộ nhớ nhỏ thay cho cơ sở dữ liệu thật

  • assistant.py chứ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.py là một endpoint FastAPI nhỏ phát hành 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 sau phần kiểm thử

Lộ trình dạy chạy từ terminal. Bản demo thêm micro.

Yêu cầu tiên quyết

Bạn cần một tài khoản SpaceXAI với một khóa API, một phương thức thanh toán đã nạp tiền (không có gói miễn phí lâu dài, và tín dụng khuyến mại cho tài khoản mới sẽ không đủ), và đủ thoải mái 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ì SDK chuyên dụng, chúng ta cũng vậy. Tài liệu không nêu rõ phiên bản Python yêu cầu. Tôi 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ó sẽ nhận một token tạm thời thay vì khóa thật của bạn, nội dung này sẽ đề cập ở phần bảo mật bên dưới.

Thiết lập dự án

Mọi tệp bên dưới đều có trong repo dự án, nên bạn có thể clone thay vì chép đoạn mã:

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 duy trì kết nối thời gian thực 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ên trình duyệt. Đặt khóa vào .env:

XAI_API_KEY=xai-your-key-here

Vậy là gần như xong phần thiết lập. Phần kết nối mới là thú vị.

Hiểu API Realtime của Grok Voice

Grok Voice là tên sản phẩm. Thứ bạn thật sự viết mã để tương tác là endpoint WebSocket tại wss://api.x.ai/v1/realtime, và toàn bộ cuộc trò chuyện diễn ra như một luồng sự kiện JSON qua một socket đó.

Vòng đời sự kiện

Một kết nối theo khuôn cố định: máy chủ gửi session.created conversation.created ngay khi bạn kết nối, bạn gửi session.update để cấu hình giọng, 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 với khóa thật và thứ tự khớp tài liệu chính xác.

  • 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 cái này cho bạn

  • response.output_audio.deltaresponse.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ễ làm bạn vấp. Trang tài liệu Speech to Speech mà tôi đã liên kết phía trên có đề cập 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à cái tôi nhận được trong mọi thử nghiệm, nên hãy viết mã dựa trên 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 coi đó là lỗi.

Định dạng âm thanh và truyền tải

Codec và phương thức truyền là hai lựa chọn riêng. Codec, đặt trong audio.input.format audio.output.format, là audio/pcm (Linear16, mặc định 24000 Hz), audio/pcmu hoặc audio/pcma (G.711 ở 8 kHz, cho điện thoại), hoặc audio/opus (24 kHz). Truyền tải 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 trong input_audio_buffer.append response.output_audio.delta, dễ ghi log và gỡ lỗi

  • binary gửi byte codec thô như khung nhị phân WebSocket, bỏ qua overhead base64 với cái giá là vòng lặp nhận phải rẽ nhánh theo loại thông điệp

Bắt đầu với JSON. Mọi ví dụ trong tài liệu dùng nó, dễ kiểm tra, và overhead base64 không phải nút thắt cổ chai cho một tác nhân hỗ trợ. Chuyển sang binary nếu bạn đo được lý do.

Tương thích với OpenAI Realtime API

Bỏ qua phần này 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 theo sát OpenAI Realtime API đủ gần để đa số mã client có thể chuyển bằng cách đổi base URL và khóa, nhưng không phải thay thế hoàn hảo.

Bản ghi lời nó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 bổ sung phần mở rộng riêng: force_message cho câu thông báo bắt buộc, resumption cho nối lại, và replace để sửa cách phát âm thương hiệu trước bước 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

Đủ phần giao thức. Đây là client giao tiếp 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 hành xử:

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ú di trú của SpaceXAI khuyên đơn giản hóa các prompt viết cho những mô hình thoại thời GPT đời trước thay vì bê nguyên. Prompt của tôi yêu cầu tác nhân trả lời ngắ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 kiểm soát quyền trên thao tác ghi chính nó.

Một điều khiến tôi ngạc nhiên: một chuỗi tên mô hình không được nhận ra sẽ không báo lỗi khi kết nối, mà âm thầm quay về grok-voice-think-fast-1.0. Hạ cấp một yêu cầu trả phí vì lỗi gõ, mà không nói gì, là mặc định lạ. Hãy ghi log trường session.model của session.created một lần khi khởi động và kiểm tra bạn nhận đúng thứ bạn yêu cầu.

Terminal in ra sự kiện session.created sau khi mở kết nối WebSocket

Kết quả terminal hiển thị session.created sau khi kết nối. Ảnh: Tác giả.

Streaming âm thanh người dùng

Với turn_detection.type đặt là server_vad, bạn chỉ cần tiếp 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 cho bạn. Đặt là null thay vào đó và bạn tự quyết định, chốt bộ đệm 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(),
    }))

VAD phía máy chủ có ba nút chỉnh, và đặt sai là cách thường gặp nhất khiến tác nhân thoại trục trặc dù log không lỗi. Mặc định chúng không xuất hiện trong phản hồi của session.updated, nên hãy kiểm theo tài liệu chứ đừng đoán.

  • threshold (0,1 đến 0,9, mặc định 0,85), âm lượng phải lớn thế nào để tính là lời nói; tăng trong phòng ồn, giảm nếu bỏ sót người nói nhỏ

  • silence_duration_ms, khoảng im lặng của người gọi trước khi máy chủ kết thúc lượt; quá ngắn cắt ngang khi họ đang nghĩ, quá dài tạo cảm giác ì ạ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 lời nói, để không bị cụt âm tiết đầu

Tinh chỉnh silence_duration_ms trước nếu người gọi hay bị cắt khi tạm dừng suy nghĩ. Đây là tham số tôi ưu tiên trước hai cái còn lại.

Nhận và phát phản hồi

Âm thanh đến thành mảnh nhỏ dưới dạng response.output_audio.delta, và điểm của streaming là bạn phát từng mảnh ngay khi nhậ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)

Hãy giữ lại bản chép lời ngay cả trong sản xuất. Đây là công cụ gỡ lỗi rẻ nhất khi người gọi nói tác nhân "nói 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ì chỉ là chatbot có micro.

Tạo các công cụ đơ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 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 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 an toàn để thử lại nếu có timeout. Thao tác ghi thì không: thử lại update_delivery_instructions sau một timeout 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, nên hãy cho thao tác ghi một idempotency key hoặc kiểm tra trùng lặp.

Đặt cả các từ chối vào hàm. cancel_order trả về lý do và phương án thay thế thay vì hủy một đơn đã giao, vì một prompt nói "không bao giờ hủy đơn đã giao" 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 nhiều hơn một công cụ cho một yêu cầu, nó sẽ phát nhiều sự kiện function_call_arguments.done trước khi có âm thanh nào phát. Hãy xử lý tất cả và gửi mọi kết quả trước một response.create duy nhất. Gửi quá sớm và mô hình sẽ trả lời mà thiếu ngữ cảnh từ các lệnh gọi còn đang thực thi.

Có một điểm cần chú ý mà SpaceXAI có tài liệu và tôi vẫn gặp ở 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 chéo với câu mở đầu mà tác nhân vẫn đang phát. Có lần nó mở bằng "Tôi sẽ kiểm tra trạng thái đơn ORD-1042 ngay" và gọi công cụ giữa câu, nên phản hồi tức thì sẽ nói đè 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ị một trạng thái "đang xử lý" ngắn ở giữa.

Luồng từ function_call_arguments.done đến thực thi handler, gửi function_call_output, rồi response.create.

Luồng gọi công cụ trước khi tiếp tục phản hồi. Ảnh: Tác giả.

Xử 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 đè 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 được xử lý tự động phía máy chủ: ngay khi phát hiện người gọi nói lại, nó phát tín hiệu input_audio_buffer.speech_started và dừng tạo phản hồi cũ. Phần việc của bạn là nửa client của cái bắt tay đó, xóa mọi âm thanh đang chờ phát để tác nhân im lặng thay vì nói nốt câu không ai muốn nghe.

if event["type"] == "input_audio_buffer.speech_started":
    playback_queue.clear()

Với 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 ngắn mục trợ lý xuống phần đã thực sự được nghe. Tài liệu xác nhận nó tồn tại nhưng không nói khi nào nên bắn trong lúc barge-in trực tiếp, nên bạn tự thử thời điểm.

Tôi kiểm thử với một thay đổi chỉ dẫn giao hàng giữa phản hồi: bắt đầu yêu cầu, ngắt lời với địa chỉ khác giữa lúc tác nhân đang xác nhận. Điều quan trọng là tác nhân áp dụng chỉ dẫn đã chỉnh sửa thay vì lặng lẽ hoàn tất chỉ dẫn cũ, không phải âm thanh có dừng hay không. Hãy kiểm tra đối chiếu hồ sơ đơn hàng, không phải sự im lặng. Bản demo trình duyệt cuối bài cho bạn nghe trường hợp này.

Nối lại một phiên bị ngắt kết nối

Nối lại phiên là lựa chọn chủ động 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 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 đã lưu, 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 kế tiếp, và bộ nhớ đệm biến mất sau 30 phút không hoạt động. Tôi đã thử bằng cách hỏi về một đơn, làm rớt kết nối, rồi nối lại để hỏi tiếp mà không lặp lại; tác nhân lấy lại ETA chính xác.

Một điểm không có trong tài liệu: phát lại không đến ngay tức thì, nên một câu hỏi bắn ra ngay khoảnh khắc socket mở có thể vượt trước và nhận về kết quả không có ký ức về lượt trước. Chờ một giây trước khi bạn đổ lỗi cho cơ chế nối lại.

Bản ghi terminal về một kết nối bị rớt, kết nối lại với conversation_id, và câu trả lời tiếp nối đúng.

Nhật ký terminal của một phiên được nối lại. Ảnh: Tác giả.

Đừ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 ngày mai, bạn bắt đầu từ con số 0 về ngữ cảnh, và đó là chủ đí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 client kết nối trực tiếp thay vì qua máy chủ của bạn, hãy phát hành 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ó chuyển token qua header sec-websocket-protocol, với tiền tố xai-client-secret..

Sơ đồ máy chủ phát hành client secret sống ngắn cho trình duyệt mở WebSocket.

Máy chủ phát token, trình duyệt tham gia cuộc gọi. Ảnh: Tác giả.

Tính phí chạy trên hai thước đo. Âm thanh, gửi hoặc nhận, tính $0,08 mỗi phút như tôi đã nói, tức $4,80 mỗi giờ, và mỗi conversation.item.create không phải âm thanh và không phải function_call_output tính phí cố định $0,004. response.create không bị tính phí. Mỗi response.done mang một đối tượng usage, trong thử nghiệm của tôi báo cáo output_audio_seconds cùng billable_audio_seconds riêng. Hãy tính từ các số đó, không phải ước lượng.

Giới hạn đã tài liệu hóa trên Speech to Speech API là 10 phiên đồng thời mỗi team và trần 120 phút mỗi phiên, đều ở us-east-1. Đừng lập kế hoạch công suất dựa trên số liệu của Voice Agent API, chúng khác nhau.

Về quyền riêng tư, hãy chính xác. FAQ bảo mật của SpaceXAI nói 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 cho huấn luyện khi chưa có phép, và các team có thể bật Zero Data Retention, dù ZDR loại bỏ lịch sử hội thoại tác nhân thoại đã lưu và vì thế không hoạt động với nối lại phiên.

Nếu bạn thông báo rằng cuộc gọi được ghi âm hoặc do AI xử lý, đó là việc của phần mở rộng force_message tôi đã liệt kê. Câu này sẽ phát đúng như viết thay vì bất kỳ diễn giả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 hay không. Hãy kiểm thử kết quả, không chỉ kết nối.

  • Một tra cứu đơ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, xác nhận phát lại 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 hồ sơ đơn hàng
  • Một từ chối, như hủy đơn đã giao, 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 vậy 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 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ố, địa chỉ

Tôi đã chạy hầu hết các trường hợp này với khóa thật khi viết bài. Các lỗi thú vị mang tính hành vi, không phải lỗi kỹ thuật: thời điểm nối lại ở trên, và một ngưỡng VAD ngoài phạm vi được chấp nhận thay vì bị từ chối, kiểu vấn đề sẽ âm thầm được phát hành nếu bạn chỉ kiểm thử đường hạnh phúc. Thêm kiểm thử đa ngôn ngữ nữa, và xem phần Câu hỏi thường gặp về một chi tiết trong cách đặt tên ngôn ngữ.

Hai trường hợp bạn không thể kiểm thử bằng cách gõ. app_streamlit.py là một trang Streamlit đưa một cuộc gọi trực tiếp vào 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 luôn mở.

streamlit run app_streamlit.py
Ngắt lời tác nhân giữa câu. Video: Tác giả.

Nói đè lên tác nhân và nó sẽ dừng, vì speech_started đến và trang xả hàng đợi âm thanh. Đây là cái bắt tay trong phần ngắt lời, chạy thật.

Hãy quan sát hồ sơ đơn hàng thay vì bản chép lời: tác nhân đọc lại thay đổi giao hàng và nói đã xong, và hồ sơ hoặc đã đổi hoặc chưa. Hãy đeo tai nghe. Khi mở loa ngoài, tác nhân tự nghe chính mình, coi đó là barge-in, và tự cắt ngang câu của nó, đây là bản xem trước việc người gọi dùng loa ngoài sẽ gây ra.

Hạn chế của Grok Voice Think Fast 2.0 và cân nhắc triển khai

Hãy lên kế hoạch cho 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 câu 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 nhưng đổ vỡ 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 người gọi có vẻ bối rối hay khó chịu, hãy chuyển cho người thật. Hãy cho mô hình một công cụ transfer_to_human cho việc đó: nếu không, nó sẽ ngẫu hứng xin lỗi thay vì leo thang.

Một ngăn xếp 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ỗ: 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 suy luận, với cái giá là nhiều công việc tích hợp hơn. Và nếu khối lượng công việc của bạn không cần đối đáp trực tiếp, một chatbot văn bản hoặc job chép lời theo lô 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.

Kết luận

Qua các bài kiểm thử trong bài viết này, grok-voice-think-fast-2.0 phần lớn 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 được nối lại với các lượt trước còn nguyên, và mô hình gọi công cụ trong khi vẫn đang nói câu mở đầu.

Ngoài sự 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 socket của bạn: hàng đợi phát lại, khi nào nên im lặng, khi nào chưa nên hỏi câu tiếp theo.

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ì bí danh, server_vad với silence_duration_ms được tinh chỉnh trước hai nút còn lại, truyền JSON cho tới khi có lý do đo đếm được để dùng binary, resumption.enabled trong session.update đầu tiên, và session.model được ghi log khi khởi động.

Những thói quen tôi sẽ áp dụng cho mọi tác nhân thoại: kiểm tra thao tác ghi với bản ghi thay vì nghe câu xác nhận, đặt các từ chối trong công cụ thay vì trong prompt, để phát lại xong trước response.create kế tiếp, và kiểm thử với giọng thật, tiếng ồn thật, và công cụ hỏng theo cách chúng thực sự hỏng.

Những phần mở rộng hiển nhiên là tổng đài (SpaceXAI tài liệu hóa hỗ trợ SIP trực tiếp), một client trình duyệt dùng token tạm thời, một kết nối MCP tới một CRM thực, 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 giới hạn phiên ở trên gần với nhu cầu của bạn hơn, hướng dẫn Grok Voice Agent API của chúng tôi trình bày con đường đó.


Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

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

grok-voice-latest có an toàn để dùng trong sản xuất không?

Không hẳn, như tôi đã đề cập trong phần quản lý phiên bản ở trên. Nó thay đổi vào ngày SpaceXAI chọn, không phải bạn, và hóa đơn của bạn sẽ đi theo. Hãy ghim grok-voice-think-fast-2.0 và để bí danh cho 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 đang trực tiếp.

Grok Voice Think Fast 2.0 có hỗ trợ ngôn ngữ khác ngoài 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 phần 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. Dùng es hoặc 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à quay về tự động nhận diện, nên một lỗi gõ ở đây không làm hỏng nhưng cũng không có tác dụng.

Tôi có thể đổi giọng nói, và có bao nhiêu giọng?

eve là giọng trong tài liệu và tôi đã dùng, cùng với ara, rex, sal, và leo cũng có, cộng thêm ID giọng tùy chỉnh. GET /v1/tts/voices trả về danh sách hiện có. Nếu nhịp nói khiến bạn khó chịu, audio.output.speed nhận giá trị 0,7 đến 1,5.

Tôi có thể làm 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 là đúng. 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 với bất kỳ 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 cái này không?

Không, giống như phần yêu cầu tiên quyết đã nói. Gói websockets thuần hoặc một client tương thích OpenAI trỏ tới 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 điểm bắt đầu khác với của tôi, xai-cookbook có mẫu cho iOS, web, WebRTC, và tổng đài.

Chủ đề
Trí tuệ Nhân tạo

Học cùng DataCamp

Courses

Hiểu về Trí tuệ Nhân tạo

2 giờ
421.9K
Tìm hiểu các khái niệm cơ bản về Trí tuệ Nhân tạo như học máy, học sâu, NLP, AI tạo sinh và hơn thế nữa.
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow