Обработка прерываний голосовой связи в журнале чата (предварительная версия)

Замечание

Эта функция сейчас доступна в общедоступной предварительной версии. Эта предварительная версия предоставляется без соглашения об уровне обслуживания и не рекомендуется для использования в рабочей среде. Некоторые функции могут не поддерживаться или их возможности могут быть ограничены. Дополнительные сведения см. в разделе Supplemental Terms of Use for Microsoft Azure Previews.

Распространенный сценарий с голосовыми агентами заключается в том, что пользователи прерывают воспроизведение звука ответов агента. Служба Voice Live создает и возвращает звуковые ответы клиенту, но пользователи могут не слушать полные ответы— они часто прерывают работу, говорив еще раз, прежде чем ответ завершится. Это создает несоответствие между фактическим звуковым диалогом и транскрибируемыми результатами беседы, используемыми для журнала бесед.

В этом случае контекст сеанса должен быть обновлен, чтобы отразить то, что пользователь на самом деле слышал. В противном случае LLM будет предполагать, что было сказано что-то, что никогда не было доведено до пользователя.

Предпосылки

Перед началом работы выполните следующие действия:

Это важно

Автоматическое усечение требует azure-ai-voicelive >= 1.2.0b2 и версию API 2026-01-01-preview. Установите пакет SDK предварительной версии с помощью:

pip install azure-ai-voicelive --pre

Этот пакет SDK в настоящее время находится в предварительной версии. Функции и API могут изменяться до общедоступной доступности.

Это важно

Автоматическое усечение требует Azure.AI.VoiceLive >= 1.1.0-beta.1 и версию API 2026-01-01-preview. Установите пакет SDK предварительной версии с помощью:

dotnet add package Azure.AI.VoiceLive --prerelease

Этот пакет SDK в настоящее время находится в предварительной версии. Функции и API могут изменяться до общедоступной доступности.

Это важно

Автоматическое усечение требует azure-ai-voicelive >= 1.0.0-beta.3 и версию API 2026-01-01-preview. Добавьте зависимость предварительного просмотра в вашу pom.xml:

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-ai-voicelive</artifactId>
    <version>1.0.0-beta.3</version>
</dependency>

Этот пакет SDK в настоящее время находится в предварительной версии. Функции и API могут изменяться до общедоступной доступности.

Это важно

Автоматическое усечение требует @azure/ai-voicelive >= 1.0.0-beta.2 и версию API 2026-01-01-preview. Для этого пакета SDK требуется Node.js 20 или более поздней версии. Установите пакет SDK предварительной версии с помощью:

npm install @azure/ai-voicelive@1.0.0-beta.2

Этот пакет SDK в настоящее время находится в предварительной версии. Функции и API могут изменяться до общедоступной доступности.

Параметры

Следующие два параметра API голосовой трансляции обрабатывают этот сценарий:

auto_truncate

Если auto_truncate задано значение true в конфигурации VAD, служба автоматически усекает ответ последней реплики при обнаружении речи пользователя во время воспроизведения. Служба предполагает, что ответ воспроизводится в режиме реального времени.

Зависимости:

  • interrupt_response необходимо задать значение true (по умолчанию). Автоматическое усечение имеет смысл только при включении прерывания воспроизведения отклика—если ответ продолжает воспроизводиться после того, как пользователь начинает говорить, нечего усекать.

При усечении:

  1. Контекст сеанса обновляется, чтобы включить только часть ответа, воспроизводимую до того, как пользователь начал говорить.
  2. Сообщение conversation.item.truncated возвращается клиенту.

appended_text_after_truncation

Замечание

Параметр appended_text_after_truncation — это серверная функция, которую можно задать с помощью передаваемых данных JSON. Поддержка пакета SDK для этого параметра пока недоступна в текущих предварительных версиях. Используйте метод JSON-пейлоуда, показанный в разделе конфигурации примера.

Иногда разработчикам может понадобиться сообщить LLM, что пользователь прервал ответ, а не просто его тихо усечь. В этом случае appended_text_after_truncation можно задать строковое значение.

В случае усечения служба добавляет эту строку в усеченный ответ перед обновлением контекста сеанса.

Example:

  • appended_text_after_truncation: " [The user interrupted me.]"
  • Исходный ответ: "Hello, how can I help you today?"
  • Пользователь прерывает работу после: "Hello, how"
  • Окончательный сохранённый контекст: "Hello, how [The user interrupted me.]"

Это важно

При использовании этой функции обновите системный запрос, чтобы сообщить LLM об этом поведении и тщательно протестировать, чтобы избежать непредвиденных результатов.

Поддерживаемые типы VAD

Тип VAD auto_truncate appended_text_after_truncation
azure_semantic_vad
azure_semantic_vad_multilingual
server_vad
semantic_vad (OpenAI)

Пример конфигурации

from azure.ai.voicelive.models import (
    RequestSession,
    AzureSemanticVad,
)

# Configure session with auto truncation enabled
session_config = RequestSession(
    instructions="You are a helpful assistant.",
    turn_detection=AzureSemanticVad(
        interrupt_response=True,
        auto_truncate=True
    )
)

await conn.session.update(session=session_config)
using Azure.AI.VoiceLive;

// Configure session with auto truncation enabled
var sessionOptions = new VoiceLiveSessionOptions
{
    Instructions = "You are a helpful assistant.",
    TurnDetection = new AzureSemanticVadTurnDetection
    {
        InterruptResponse = true,
        AutoTruncate = true
    }
};

// Update session configuration
var sessionUpdatePayload = new
{
    type = "session.update",
    session = new
    {
        instructions = sessionOptions.Instructions,
        turn_detection = new
        {
            type = "azure_semantic_vad",
            interrupt_response = true,
            auto_truncate = true
        }
    }
};
BinaryData eventData = BinaryData.FromObjectAsJson(sessionUpdatePayload);
await session.SendCommandAsync(eventData, cancellationToken).ConfigureAwait(false);
import com.azure.ai.voicelive.models.*;

// Configure session with auto truncation enabled
AzureSemanticVadTurnDetection turnDetection = new AzureSemanticVadTurnDetection()
    .setInterruptResponse(true)
    .setAutoTruncate(true);

VoiceLiveSessionOptions sessionOptions = new VoiceLiveSessionOptions()
    .setInstructions("You are a helpful assistant.")
    .setTurnDetection(turnDetection);

// Send session update
session.sendEvent(new ClientEventSessionUpdate(sessionOptions)).subscribe();
// Configure session with auto truncation enabled
await session.sendEvent({
    type: "session.update",
    session: {
        instructions: "You are a helpful assistant.",
        turn_detection: {
            type: "azure_semantic_vad",
            interrupt_response: true,
            auto_truncate: true
        }
    }
});

Эквивалентные полезные данные JSON для конфигурации сеанса:

{
  "type": "session.update",
  "session": {
    "instructions": "You are a helpful assistant.",
    "turn_detection": {
      "type": "azure_semantic_vad",
      "interrupt_response": true,
      "auto_truncate": true
    }
  }
}

Использование appended_text_after_truncation с помощью JSON

Чтобы использовать appended_text_after_truncation функцию (которая пока недоступна в типизированных классах SDK), отправьте всю конфигурацию сеанса в виде необработанного JSON. Сначала не нужно вызывать методы ПАКЕТА SDK— один необработанный JSON session.update заменяет любую предыдущую конфигурацию:

{
  "type": "session.update",
  "session": {
    "instructions": "You are a helpful assistant.",
    "turn_detection": {
      "type": "azure_semantic_vad",
      "interrupt_response": true,
      "auto_truncate": true,
      "appended_text_after_truncation": " [The user interrupted me.]"
    }
  }
}

В коде используйте необработанный подход JSON:

# Send session update with appended_text_after_truncation via raw dict
# Note: conn.send() accepts a dict - the SDK handles JSON serialization internally
session_update = {
    "type": "session.update",
    "session": {
        "instructions": "You are a helpful assistant.",
        "turn_detection": {
            "type": "azure_semantic_vad",
            "interrupt_response": True,
            "auto_truncate": True,
            "appended_text_after_truncation": " [The user interrupted me.]"
        }
    }
}
await conn.send(session_update)
// Send session update with appended_text_after_truncation via JSON
var sessionUpdatePayload = new
{
    type = "session.update",
    session = new
    {
        instructions = "You are a helpful assistant.",
        turn_detection = new
        {
            type = "azure_semantic_vad",
            interrupt_response = true,
            auto_truncate = true,
            appended_text_after_truncation = " [The user interrupted me.]"
        }
    }
};
BinaryData eventData = BinaryData.FromObjectAsJson(sessionUpdatePayload);
await session.SendCommandAsync(eventData, cancellationToken).ConfigureAwait(false);
import com.azure.core.util.BinaryData;

// Send session update with appended_text_after_truncation via raw JSON
// Note: appended_text_after_truncation is not available in typed SDK classes
String sessionUpdate = """
    {
        "type": "session.update",
        "session": {
            "instructions": "You are a helpful assistant.",
            "turn_detection": {
                "type": "azure_semantic_vad",
                "interrupt_response": true,
                "auto_truncate": true,
                "appended_text_after_truncation": " [The user interrupted me.]"
            }
        }
    }
    """;
session.send(BinaryData.fromString(sessionUpdate)).subscribe();
// Send session update with appended_text_after_truncation via JSON
await session.sendEvent({
    type: "session.update",
    session: {
        instructions: "You are a helpful assistant.",
        turn_detection: {
            type: "azure_semantic_vad",
            interrupt_response: true,
            auto_truncate: true,
            appended_text_after_truncation: " [The user interrupted me.]"
        }
    }
});

Обработка события усечения

При усечении служба отправляет событие conversation.item.truncated. Это событие можно обрабатывать в цикле событий:

async def _handle_event(self, event):
    if event.type == ServerEventType.CONVERSATION_ITEM_TRUNCATED:
        print(f"Response was truncated. Item ID: {event.item_id}")
        print(f"Truncated at index: {event.content_index}")
        # Log or handle the truncation as needed
private async Task HandleSessionUpdateAsync(SessionUpdate serverEvent, CancellationToken cancellationToken)
{
    if (serverEvent is SessionUpdateConversationItemTruncated truncatedEvent)
    {
        Console.WriteLine($"Response was truncated. Item ID: {truncatedEvent.ItemId}");
        Console.WriteLine($"Truncated at index: {truncatedEvent.ContentIndex}");
        // Log or handle the truncation as needed
    }
}
private void handleServerEvent(SessionUpdate event) {
    if (event.getType() == ServerEventType.CONVERSATION_ITEM_TRUNCATED) {
        SessionUpdateConversationItemTruncated truncatedEvent = 
            (SessionUpdateConversationItemTruncated) event;
        System.out.println("Response was truncated. Item ID: " + truncatedEvent.getItemId());
        System.out.println("Truncated at index: " + truncatedEvent.getContentIndex());
        // Log or handle the truncation as needed
    }
}
const subscription = session.subscribe({
    onConversationItemTruncated: async (event, context) => {
        console.log(`Response was truncated. Item ID: ${event.itemId}`);
        console.log(`Truncated at index: ${event.contentIndex}`);
        // Log or handle the truncation as needed
    }
});

Дальнейшие шаги