Если у вас имеется собственный контактный центр, задача найти упоминание чего-либо конкретного в большом количестве аудиофрагментов возникает регулярно. Недавно нам удовлетворили заявку на доступ к prewiev режиму сервиса Яндекса Speech Sense и я решил попробовать одну из таких задач решить при помощи этого сервиса.
Все трудности, тонкие моменты и полный путь от начала настройки и до победы описаны в этой статье.
В принципе в документации описан функционал, который мало отличается от других систем речевой аналитики, и это только на первый взгляд. Сюрпризом стало полное отсутствие собственных средств загрузки аудиофрагментов в систему. Всю загрузку необходимо реализовать самостоятельно. В документации описан только один способ, при помощи bash и Python под unix. Поэтому в этой статье я еще и опишу как такие инструкции адаптировать под Windows и PowerShell.
Сама инструкция довольно короткая https://yandex.cloud/ru/docs/speechsense/operations/data/upload-data я рассчитывал справиться за пару часов, это мне не удалось. Так что Ваша выгода от прочтения статьи может составлять 2-3 рабочих дня. Или больше.
Начинайте настройку окружения, перед тем как клонируете репозиторий https://github.com/yandex-cloud/cloudapi вот с этой инструкции:
https://packaging.python.org/en/latest/tutorials/installing-packages/ до пункта "Creating Virtual Environments". Проверьте версию Питона, чтобы была выше 3.6
py --version
и наличие pip
py -m pip --version
Если pip не настроен, по ссылке указано что делать. Потом запустите обновление pip и прочего
py -m pip install --upgrade pip setuptools wheel
Это сбережет Вам как минимум нервы, а может быть и время.
Если все прошло хорошо, пакет grpcio-tools под Windows необходимо установить не так, как указано в документации Яндекс
pip install grpcio-tools
а вот так:
py -m pip install "grpcio-tools"
Следующим шагом инструкцию
python3 -m grpc_tools.protoc -I . \
--python_out=./upload_data/ \
--grpc_python_out=./upload_data/ \
yandex/cloud/speechsense/v1/*
Для PowerShell нужно поменять на
py -m grpc_tools.protoc --proto_path=с:\project\speech_sense\
--python_out=с:\project\speech_sense\upload_data\
--grpc_python_out=с:\project\speech_sense\upload_data\
с:\project\speech_sense\yandex\cloud\speechsense\v1\*
Это если с:\project\speech_sense\ путь куда вы клонировали репозиторий Яндекса. И да, эта команда совершенно точно не будет работать с первого раза.
Чтобы всё сработало Вам нужно папку third_party\googleapis\ скопировать в корневую папку проекта (с:\project\speech_sense), иначе получаете ошибку
"google/api/annotations.proto: File not found.
yandex/cloud/speechsense/v1/talk_service.proto:9:1: Import "google/api/annotations.proto" was not found or had errors."
Всё верно, вы правильно подумали. В репозитории Яндекса сloudapi папка google изначально расположена так, чтобы инструкции из документации Яндекса гарантированно не работали. О необходимости такой манипуляции вы больше нигде не прочитаете.
С созданием файла upload_grpc.py нет никаких проблем, а вот затем идёт пункт инструкции "Задайте API-ключ сервисного аккаунта:" и никак не помечено, что это уже не в скрипт пайтона надо прописывать, а это опять команда bash. Для windows используется не export а
set API_KEY=<API-ключ_сервисного_аккаунта>
(https://stackoverflow.com/questions/59087882/how-do-i-set-an-api-key-in-windows-terminal) Как потом это решение заставить это работать непонятно, но я забегаю вперёд.
И вот наконец, закончив настройку и запустив
py upload_grpc.py --audio-path с:\project\speech_sense\upload_data\wave\123.wav
--connection-id ID
--key ${API_KEY}
получите ошибку ModuleNotFoundError: No module named 'google.api'
Кажется, что не хватает уже известной папки google теперь в upload_data. Но даже когда её поместить в upload_data, скрипт опять выпадает с ошибкой ImportError: cannot import name 'annotations_pb2' from 'google.api' (unknown location)
Проблема в 15-й строке talk_service_pb2.py
from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2
Но в google\api\ есть только annotations.proto
Проблема решается вот так
py -m pip install -U googleapis-common-protos==1.5.10
Получаете новую ошибку
TypeError: Descriptors cannot be created directly.
If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
If you cannot immediately regenerate your protos, some other possible workarounds are:
Downgrade the protobuf package to 3.20.x or lower.
Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).
Которую в свою очередь решает команда
py -m pip install -U protobuf==3.20.0
Получаете следующую ошибкуModuleNotFoundError: No module named 'yandex.cloud.speechsense.v1.analysis'.
Что то пошло совершенно не так. И чтобы понять, что пошло не так необходимо вернуться к grpcio-tools.
Там в последнем параметре указано с:\project\speech_sense\yandex\cloud\speechsense\v1\*
и в результате папка analysis
не собралась. Я решил эту проблему собрав папку analysis дополнительно
py -m grpc_tools.protoc --proto_path=с:\project\speech_sense\
--python_out=с:\project\speech_sense\upload_data\analysis\
--grpc_python_out=с:\project\speech_sense\upload_data\analysis\
с:\project\speech_sense\yandex\cloud\speechsense\v1\analysis\*
и скопировав в с:\project\speech_sense\upload_data\yandex\cloud\speechsense\v1\
папку из upload_data\analysis\yandex\cloud\speechsense\v1\
вручную.
Далее получаем ошибку usage: upload_grpc.py [-h] --key KEY --connection-id CONNECTION_ID --audio-path AUDIO_PATH [--meta-path META_PATH]
о которой я уже упоминал ранее. Попытка использовать API_KEY установленный через SET вот так
upload_grpc.py: error: argument --key: expected one argument
py upload_grpc.py --audio-path с:\project\speech_sense\upload_data\wave\123.wav
--connection-id ID
--key %API_KEY%
Выдаёт ошибку grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.UNAUTHENTICATED
details = "UNAUTHENTICATED: Unknown api key '%API****KEY% (0291C3E7)'"
Решения я не нашел и просто прописал ключ в командной строке не через переменную, а напрямую.
Далее получаем ошибку grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
оказывается надо не id проекта копировать, а id подключения.
status = StatusCode.INVALID_ARGUMENT
details = "Connection in active state was not found: ID"
debug_error_string = "UNKNOWN:Error received from peer ipv4:51.250.48.112:443 {created_time:"2024-06-21T13:50:40.1128112+00:00", grpc_status:3, grpc_message:"Connection in active state was not found: ID"}"
Указав корректный ID от подключения, получаем ошибку grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
выглядит так как будто сервисный аккаунт не имеет права добавлять разговоры, хотя инструкция
status = StatusCode.PERMISSION_DENIED
details = "User is not permitted to add talk in space SPACEID"
debug_error_string = "UNKNOWN:Error received from peer ipv4:51.250.48.112:443 {created_time:"2024-06-21T14:01:07.0448397+00:00", grpc_status:7, grpc_message:"User is not permitted to add talk in space SPACEID"}"
Добавьте сервисный аккаунт в пространство с ролью Data editor. Это позволит сервисному аккаунту загружать данные в созданное подключение.
кажется давно и успешно мной выполнена.
Оказалось, что на роли сервисного аккаунта, которые установили при его создании сервис SpeechSense не обращает никакого внимания. При добавлении в пространство сервисный аккаунт становится "Аудитором", даже если у него роль speechsense.data.editor прописана в ролях при создании. Необходимо поменять роль именно в меню участников пространства.
На этом всё заработало и upload_grpc.py успешно загрузил файл в аудиоканал, все осталные пункты документации пока работают как по написанному и можно приступать к аналитике. Надо сказать, что преобразование STT для этого аудиофрагмента прошло довольно качественно и некорректно распознанных слов не было вообще.
Надеюсь, что моя статья поможет читателям избежать моих трудностей при старте в данном сервисе.