양방향 API

BiDiStreamingAnalyzeContent API는 대화형 에이전트와 Agent Assist 모두에서 차세대 오디오 및 멀티모달 환경을 위한 기본 API입니다. 이 API는 오디오 데이터 스트리밍을 지원하며 스크립트 또는 상담사 제안을 반환합니다.

이전 API와 달리 간소화된 오디오 구성은 사람 간 대화를 위한 최적화된 지원과 15분의 연장된 기한 제한을 제공합니다. 실시간 번역을 제외하고 이 API는 StreamingAnalyzeContent에서 지원하는 모든 Agent Assist 기능도 지원합니다.

스트리밍 기본사항

다음 다이어그램은 스트림의 작동 방식을 보여줍니다.

서버에 오디오 구성을 전송하여 스트림을 시작합니다. 그런 다음 오디오 파일을 보내면 서버에서 스크립트 또는 상담사에게 제안을 보냅니다. 더 많은 텍스트 변환과 추천을 위해 더 많은 오디오 데이터를 전송합니다. 이 교환은 스트림을 절반 닫아 종료할 때까지 계속됩니다.

스트리밍 가이드

대화 런타임에 BiDiStreamingAnalyzeContent API를 사용하려면 다음 가이드라인을 따르세요.

  1. BiDiStreamingAnalyzeContent 메서드를 호출하고 다음 필드를 설정합니다.
    • BiDiStreamingAnalyzeContentRequest.participant
    • (선택사항) BiDiStreamingAnalyzeContentRequest.voice_session_config.input_audio_sample_rate_hertz (지정된 경우 ConversationProfile.stt_config.sample_rate_hertz의 구성을 재정의함)
    • (선택사항) BiDiStreamingAnalyzeContentRequest.voice_session_config.input_audio_encoding (지정된 경우 ConversationProfile.stt_config.audio_encoding의 구성을 재정의함)
  2. 첫 번째 BiDiStreamingAnalyzeContent 요청으로 스트림을 준비하고 오디오 구성을 설정합니다.
  3. 후속 요청에서는 BiDiStreamingAnalyzeContentRequest.audio를 통해 스트림에 오디오 바이트를 전송합니다.
  4. 오디오 페이로드가 포함된 두 번째 요청을 전송하면 스트림에서 BidiStreamingAnalyzeContentResponses가 수신됩니다.
    • 중간 및 최종 텍스트 변환 결과는 BiDiStreamingAnalyzeContentResponse.recognition_result 명령어를 사용하여 확인할 수 있습니다.
    • BiDiStreamingAnalyzeContentResponse.analyze_content_response 명령어를 사용하여 상담사 추천 및 처리된 대화 메시지에 액세스할 수 있습니다.
  5. 언제든지 스트림을 절반만 닫을 수 있습니다. 스트림을 절반 닫으면 서버는 잠재적인 Agent Assist 제안과 함께 나머지 인식 결과가 포함된 응답을 다시 전송합니다.
  6. 다음과 같은 경우 새 스트림을 시작하거나 다시 시작합니다.
    • 스트림이 끊어졌습니다. 예를 들어 스트림이 중지되지 않아야 하는데 중지되었습니다.
    • 대화가 최대 요청 시간인 15분에 가까워지고 있습니다.
  7. 최상의 품질을 위해 스트림을 시작할 때 BiDiStreamingAnalyzeContentResponse.recognition_result의 마지막 speech_end_offset 이후에 생성된 오디오 데이터를 is_final=true와 함께 BidiStreamingAnalyzeContent로 전송합니다.

Python 클라이언트 라이브러리를 통해 API 사용

클라이언트 라이브러리를 사용하면 특정 코드 언어로 Google API에 액세스할 수 있습니다. 다음과 같이 BidiStreamingAnalyzeContent와 함께 Agent Assist용 Python 클라이언트 라이브러리를 사용할 수 있습니다.

from google.cloud import dialogflow_v2beta1
from google.api_core.client_options import ClientOptions
from google.cloud import storage

import time
import google.auth
import participant_management
import conversation_management


PROJECT_ID="your-project-id"
CONVERSATION_PROFILE_ID="your-conversation-profile-id"
BUCKET_NAME="your-audio-bucket-name"

SAMPLE_RATE =48000
# Calculate the bytes with Sample_rate_hertz * bit Depth / 8 -> bytes
# 48000(sample/second) * 16(bits/sample) / 8 = 96000 byte per second,
# 96000 / 10 = 9600 we send 0.1 second to the stream API
POINT_ONE_SECOND_IN_BYTES = 9600
FOLDER_PTAH_FOR_CUSTOMER_AUDIO="your-customer-audios-files-path" 
FOLDER_PTAH_FOR_AGENT_AUDIO="your-agent-audios-file-path"
client_options = ClientOptions(api_endpoint="dialogflow.googleapis.com")
credentials, _ = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform",
                                             "https://www.googleapis.com/auth/dialogflow"])

storage_client = storage.Client(credentials = credentials, project=PROJECT_ID)

participant_client = dialogflow_v2beta1.ParticipantsClient(client_options=client_options,
                                                           credentials=credentials)

def download_blob(bucket_name, folder_path, audio_array : list):
    """Uploads a file to the bucket."""
    bucket = storage_client.bucket(bucket_name, user_project=PROJECT_ID)
    blobs = bucket.list_blobs(prefix=folder_path)
    for blob in blobs:
      if not blob.name.endswith('/'):
          audio_array.append(blob.download_as_string())

def request_iterator(participant : dialogflow_v2beta1.Participant, audios):
    """Iterate the request for bidi streaming analyze content
    """

    yield dialogflow_v2beta1.BidiStreamingAnalyzeContentRequest(
        config={
            "participant": participant.name,
            "voice_session_config": {
                "input_audio_encoding": dialogflow_v2beta1.AudioEncoding.AUDIO_ENCODING_LINEAR_16,
                "input_audio_sample_rate_hertz": SAMPLE_RATE,
            },
        }
    )
    print(f"participant {participant}")

    for i in range(0, len(audios)):
      audios_array = audio_request_iterator(audios[i])
      for chunk in audios_array:
        if not chunk:
            break
        yield dialogflow_v2beta1.BidiStreamingAnalyzeContentRequest(
        input={
            "audio":chunk
            },
        )
        time.sleep(0.1)
    yield dialogflow_v2beta1.BidiStreamingAnalyzeContentRequest(
        config={
            "participant": participant.name,
        }
    )
    time.sleep(0.1)

def participant_bidi_streaming_analyze_content(participant, audios):
    """call bidi streaming analyze content API
    """
    bidi_responses = participant_client.bidi_streaming_analyze_content(
        requests=request_iterator(participant, audios)
    )

    for response in bidi_responses:
        bidi_streaming_analyze_content_response_handler(response)

def bidi_streaming_analyze_content_response_handler(response: dialogflow_v2beta1.BidiStreamingAnalyzeContentResponse):
    """Call Bidi Streaming Analyze Content
    """
    if  response.recognition_result:
         print(f"Recognition result: { response.recognition_result.transcript}", )

def audio_request_iterator(audio):
    """Iterate the request for bidi streaming analyze content
    """
    total_audio_length = len(audio)
    print(f"total audio length {total_audio_length}")
    array = []
    for i in range(0, total_audio_length, POINT_ONE_SECOND_IN_BYTES):
        chunk = audio[i : i + POINT_ONE_SECOND_IN_BYTES]
        array.append(chunk)
        if not chunk:
            break
    return array

def python_client_handler():
    """Downloads audios from the google cloud storage bucket and stream to
    the Bidi streaming AnalyzeContent site.
    """
    print("Start streaming")
    conversation = conversation_management.create_conversation(
        project_id=PROJECT_ID, conversation_profile_id=CONVERSATION_PROFILE_ID_STAGING
    )
    conversation_id = conversation.name.split("conversations/")[1].rstrip()
    human_agent = human_agent = participant_management.create_participant(
        project_id=PROJECT_ID, conversation_id=conversation_id, role="HUMAN_AGENT"
    )

    end_user =    end_user = participant_management.create_participant(
        project_id=PROJECT_ID, conversation_id=conversation_id, role="END_USER"
    )

    end_user_requests = []
    agent_request= []
    download_blob(BUCKET_NAME, FOLDER_PTAH_FOR_CUSTOMER_AUDIO, end_user_requests)
    download_blob(BUCKET_NAME, FOLDER_PTAH_FOR_AGENT_AUDIO, agent_request)

    participant_bidi_streaming_analyze_content( human_agent, agent_request)
    participant_bidi_streaming_analyze_content( end_user, end_user_requests)

    conversation_management.complete_conversation(PROJECT_ID, conversation_id)

전화 통신 SipRec 통합 사용 설정

전화 SipRec 통합을 사용 설정하여 오디오 처리에 BidiStreamingAnalyzeContent를 사용할 수 있습니다. Agent Assist 콘솔 또는 직접 API 요청을 사용하여 오디오 처리를 구성합니다.

콘솔

다음 단계에 따라 BidiStreamingAnalyzeContent를 사용하도록 오디오 처리를 구성하세요.

  1. Agent Assist 콘솔로 이동하여 프로젝트를 선택합니다.

    Agent Assist 콘솔

  2. 대화 프로필 > 프로필 이름을 클릭합니다.

  3. 전화 통신 설정으로 이동합니다.

  4. 양방향 스트리밍 API 사용을 사용 설정하고 저장을 클릭합니다.

API

ConversationProfile.use_bidi_streaming에서 플래그를 구성하여 API를 직접 호출하여 대화 프로필을 만들거나 업데이트할 수 있습니다.

구성 예:

{
"name": "projects/PROJECT_ID/locations/global/conversationProfiles/CONVERSATION_PROFILE_ID",f
"displayName": "CONVERSATION_PROFILE_NAME",
"automatedAgentConfig": {
},
"humanAgentAssistantConfig": {
  "notificationConfig": {
    "topic": "projects/PROJECT_ID/topics/FEATURE_SUGGESTION_TOPIC_ID",
    "messageFormat": "JSON"
      },
  },
"useBidiStreaming": true,
"languageCode": "en-US"
}

할당량

동시 BidiStreamingAnalyzeContent 요청 수는 새 할당량 ConcurrentBidiStreamingSessionsPerProjectPerRegion에 의해 제한됩니다. 할당량 사용량 및 할당량 한도 상향을 요청하는 방법에 대한 자세한 내용은 Google Cloud 할당량 가이드를 참고하세요.

할당량의 경우 전역 Dialogflow 엔드포인트에 대한 BidiStreamingAnalyzeContent 요청 사용은 us-central1 리전에 있습니다.