Last active
July 1, 2018 11:01
-
-
Save bkbilly/59dbc306faf2dfd87d270dfe9bce5056 to your computer and use it in GitHub Desktop.
Google Assistant text input from Terminal. e.g. python3 -m googlesamples.assistant.grpc.textinput_intext --device-id 'my-device-identifier' --device-model-id 'my-model-identifier' --intext 'broadcast dinner time'
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Copyright (C) 2017 Google Inc. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| """Sample that implements a text client for the Google Assistant Service.""" | |
| import os | |
| import logging | |
| import json | |
| import sys | |
| import click | |
| import google.auth.transport.grpc | |
| import google.auth.transport.requests | |
| import google.oauth2.credentials | |
| from google.assistant.embedded.v1alpha2 import ( | |
| embedded_assistant_pb2, | |
| embedded_assistant_pb2_grpc | |
| ) | |
| def log_assist_request_without_audio(assist_request): | |
| """Log AssistRequest fields without audio data.""" | |
| if logging.getLogger().isEnabledFor(logging.DEBUG): | |
| resp_copy = embedded_assistant_pb2.AssistRequest() | |
| resp_copy.CopyFrom(assist_request) | |
| if len(resp_copy.audio_in) > 0: | |
| size = len(resp_copy.audio_in) | |
| resp_copy.ClearField('audio_in') | |
| logging.debug('AssistRequest: audio_in (%d bytes)', | |
| size) | |
| return | |
| logging.debug('AssistRequest: %s', resp_copy) | |
| def log_assist_response_without_audio(assist_response): | |
| """Log AssistResponse fields without audio data.""" | |
| if logging.getLogger().isEnabledFor(logging.DEBUG): | |
| resp_copy = embedded_assistant_pb2.AssistResponse() | |
| resp_copy.CopyFrom(assist_response) | |
| has_audio_data = (resp_copy.HasField('audio_out') and | |
| len(resp_copy.audio_out.audio_data) > 0) | |
| if has_audio_data: | |
| size = len(resp_copy.audio_out.audio_data) | |
| resp_copy.audio_out.ClearField('audio_data') | |
| if resp_copy.audio_out.ListFields(): | |
| logging.debug('AssistResponse: %s audio_data (%d bytes)', | |
| resp_copy, | |
| size) | |
| else: | |
| logging.debug('AssistResponse: audio_data (%d bytes)', | |
| size) | |
| return | |
| logging.debug('AssistResponse: %s', resp_copy) | |
| ASSISTANT_API_ENDPOINT = 'embeddedassistant.googleapis.com' | |
| DEFAULT_GRPC_DEADLINE = 60 * 3 + 5 | |
| class SampleTextAssistant(object): | |
| """Sample Assistant that supports text based conversations. | |
| Args: | |
| language_code: language for the conversation. | |
| device_model_id: identifier of the device model. | |
| device_id: identifier of the registered device instance. | |
| channel: authorized gRPC channel for connection to the | |
| Google Assistant API. | |
| deadline_sec: gRPC deadline in seconds for Google Assistant API call. | |
| """ | |
| def __init__(self, language_code, device_model_id, device_id, | |
| channel, deadline_sec): | |
| self.language_code = language_code | |
| self.device_model_id = device_model_id | |
| self.device_id = device_id | |
| self.conversation_state = None | |
| self.assistant = embedded_assistant_pb2_grpc.EmbeddedAssistantStub( | |
| channel | |
| ) | |
| self.deadline = deadline_sec | |
| def __enter__(self): | |
| return self | |
| def __exit__(self, etype, e, traceback): | |
| if e: | |
| return False | |
| def assist(self, text_query): | |
| """Send a text request to the Assistant and playback the response. | |
| """ | |
| def iter_assist_requests(): | |
| dialog_state_in = embedded_assistant_pb2.DialogStateIn( | |
| language_code=self.language_code, | |
| conversation_state=b'' | |
| ) | |
| if self.conversation_state: | |
| dialog_state_in.conversation_state = self.conversation_state | |
| config = embedded_assistant_pb2.AssistConfig( | |
| audio_out_config=embedded_assistant_pb2.AudioOutConfig( | |
| encoding='LINEAR16', | |
| sample_rate_hertz=16000, | |
| volume_percentage=0, | |
| ), | |
| dialog_state_in=dialog_state_in, | |
| device_config=embedded_assistant_pb2.DeviceConfig( | |
| device_id=self.device_id, | |
| device_model_id=self.device_model_id, | |
| ), | |
| text_query=text_query, | |
| ) | |
| req = embedded_assistant_pb2.AssistRequest(config=config) | |
| log_assist_request_without_audio(req) | |
| yield req | |
| display_text = None | |
| for resp in self.assistant.Assist(iter_assist_requests(), | |
| self.deadline): | |
| log_assist_response_without_audio(resp) | |
| if resp.dialog_state_out.conversation_state: | |
| conversation_state = resp.dialog_state_out.conversation_state | |
| self.conversation_state = conversation_state | |
| if resp.dialog_state_out.supplemental_display_text: | |
| display_text = resp.dialog_state_out.supplemental_display_text | |
| return display_text | |
| @click.command() | |
| @click.option('--api-endpoint', default=ASSISTANT_API_ENDPOINT, | |
| metavar='<api endpoint>', show_default=True, | |
| help='Address of Google Assistant API service.') | |
| @click.option('--credentials', | |
| metavar='<credentials>', show_default=True, | |
| default=os.path.join(click.get_app_dir('google-oauthlib-tool'), | |
| 'credentials.json'), | |
| help='Path to read OAuth2 credentials.') | |
| @click.option('--device-model-id', | |
| metavar='<device model id>', | |
| default='my-model-identifier', | |
| help=(('Unique device model identifier, ' | |
| 'if not specifed, it is read from --device-config'))) | |
| @click.option('--device-id', | |
| metavar='<device id>', | |
| default='my-device-identifier', | |
| help=(('Unique registered device instance identifier, ' | |
| 'if not specified, it is read from --device-config, ' | |
| 'if no device_config found: a new device is registered ' | |
| 'using a unique id and a new device config is saved'))) | |
| @click.option('--lang', show_default=True, | |
| metavar='<language code>', | |
| default='en-US', | |
| help='Language code of the Assistant') | |
| @click.option('--verbose', '-v', is_flag=True, default=False, | |
| help='Verbose logging.') | |
| @click.option('--grpc-deadline', default=DEFAULT_GRPC_DEADLINE, | |
| metavar='<grpc deadline>', show_default=True, | |
| help='gRPC deadline in seconds') | |
| @click.option('--intext', show_default=True, | |
| metavar='<input command>', | |
| default=None, | |
| help='Input Command') | |
| def main(api_endpoint, credentials, | |
| device_model_id, device_id, lang, verbose, | |
| grpc_deadline, intext, *args, **kwargs): | |
| if not sys.stdin.isatty(): | |
| intext = sys.stdin.read() | |
| # Setup logging. | |
| logging.basicConfig(level=logging.DEBUG if verbose else logging.INFO) | |
| # Load OAuth 2.0 credentials. | |
| try: | |
| with open(credentials, 'r') as f: | |
| credentials = google.oauth2.credentials.Credentials(token=None, | |
| **json.load(f)) | |
| http_request = google.auth.transport.requests.Request() | |
| credentials.refresh(http_request) | |
| except Exception as e: | |
| logging.error('Error loading credentials: %s', e) | |
| logging.error('Run google-oauthlib-tool to initialize ' | |
| 'new OAuth 2.0 credentials.') | |
| return | |
| # Create an authorized gRPC channel. | |
| grpc_channel = google.auth.transport.grpc.secure_authorized_channel( | |
| credentials, http_request, api_endpoint) | |
| logging.info('Connecting to %s', api_endpoint) | |
| with SampleTextAssistant(lang, device_model_id, device_id, | |
| grpc_channel, grpc_deadline) as assistant: | |
| if intext is None: | |
| while True: | |
| text_query = click.prompt('') | |
| click.echo('<you> %s' % text_query) | |
| display_text = assistant.assist(text_query=text_query) | |
| click.echo('<@assistant> %s' % display_text) | |
| else: | |
| click.echo('<you> %s' % intext) | |
| display_text = assistant.assist(text_query=intext) | |
| click.echo('<@assistant> %s' % display_text) | |
| if __name__ == '__main__': | |
| main() | |
| # Test: | |
| # python3 google_assistant/textinput_intext.py -v | |
| # --device-id my-device-identifier | |
| # --device-model-id my-model-identifier | |
| # --credentials .config/google-oauthlib-tool/credentials.json | |
| # --intext 'what time is it?' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment