From 838c9111ce18737d4e22767be1e03b165dbffab5 Mon Sep 17 00:00:00 2001 From: Soheila Zangeneh <49654056+soheilazangeneh@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:12:41 -0500 Subject: [PATCH] chore(dialogflow-cx): migrate code from googleapis/python-dialogflow-cx (#9077) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs(samples): add initial sample codes (#13) Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [x] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/python-dialogflow-cx/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [x] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes #12 🦕 * fix: corrects the repo/homepage link (#15) * fix: corrects the repo/homepage link * chore: adds newline to end of file * chore(deps): update dependency google-cloud-dialogflow-cx to v0.1.1 (#16) * chore(deps): update dependency google-cloud-dialogflow-cx to v0.2.0 (#26) * Sample code update for regionalization (#29) * Modify sample code to support regional endpoints * format codes Co-authored-by: Yuexin Wu * chore(deps): update dependency google-cloud-dialogflow-cx to v0.4.0 (#49) * chore(deps): update dependency google-cloud-dialogflow-cx to v0.4.1 (#79) * chore(deps): update dependency pytest to v6.2.4 (#82) * chore(deps): update dependency google-cloud-dialogflow-cx to v0.5.0 (#97) * chore(deps): update dependency google-cloud-dialogflow-cx to v0.6.0 (#101) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-dialogflow-cx](https://togithub.com/googleapis/python-dialogflow-cx) | `==0.5.0` -> `==0.6.0` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.6.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.6.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.6.0/compatibility-slim/0.5.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.6.0/confidence-slim/0.5.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-dialogflow-cx ### [`v0.6.0`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​060-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev050v060-2021-06-07) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v0.5.0...v0.6.0) ##### Features - support sentiment analysis in bot testing ([#​98](https://www.github.com/googleapis/python-dialogflow-cx/issues/98)) ([db258bc](https://www.github.com/googleapis/python-dialogflow-cx/commit/db258bcc9971542e347b50f396bd51ec88520fde))
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-dialogflow-cx). * chore(deps): update dependency google-cloud-dialogflow-cx to v0.7.1 (#109) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-dialogflow-cx](https://togithub.com/googleapis/python-dialogflow-cx) | `==0.6.0` -> `==0.7.1` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.7.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.7.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.7.1/compatibility-slim/0.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.7.1/confidence-slim/0.6.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-dialogflow-cx ### [`v0.7.1`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​071-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev070v071-2021-06-16) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v0.7.0...v0.7.1) ### [`v0.7.0`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​070-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev060v070-2021-06-16) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v0.6.0...v0.7.0) ##### Features - **v3beta1:** Support partial response feature ([5e21ed4](https://www.github.com/googleapis/python-dialogflow-cx/commit/5e21ed454ad6a5d687e634ad4e697f1921104c47)) - **v3beta1:** support sentiment analysis in bot testing ([#​100](https://www.github.com/googleapis/python-dialogflow-cx/issues/100)) ([f24f302](https://www.github.com/googleapis/python-dialogflow-cx/commit/f24f3028fa83da14614d1340e5bce7719be287b6)) ##### Bug Fixes - exclude docs and tests from package ([#​104](https://www.github.com/googleapis/python-dialogflow-cx/issues/104)) ([2ddb70b](https://www.github.com/googleapis/python-dialogflow-cx/commit/2ddb70b5825ad0d59165d7dfbfe36677d586cccf)) - **v3beta1:** Set agent default language code as required ([#​103](https://www.github.com/googleapis/python-dialogflow-cx/issues/103)) ([5e21ed4](https://www.github.com/googleapis/python-dialogflow-cx/commit/5e21ed454ad6a5d687e634ad4e697f1921104c47)) ##### Documentation - **v3beta1:** Update docs of Agents, Fulfillments, SecuritySettings and Sessions ([5e21ed4](https://www.github.com/googleapis/python-dialogflow-cx/commit/5e21ed454ad6a5d687e634ad4e697f1921104c47))
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-dialogflow-cx). * chore(deps): update dependency google-cloud-dialogflow-cx to v0.8.0 (#121) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-dialogflow-cx](https://togithub.com/googleapis/python-dialogflow-cx) | `==0.7.1` -> `==0.8.0` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.8.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.8.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.8.0/compatibility-slim/0.7.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/0.8.0/confidence-slim/0.7.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-dialogflow-cx ### [`v0.8.0`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​080-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev071v080-2021-06-30) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v0.7.1...v0.8.0) ##### Features - add always_use_jwt_access ([3550fa7](https://www.github.com/googleapis/python-dialogflow-cx/commit/3550fa7fa5863a313bd9288a1f515557f8f9fdea)) - add return_partial response to Fulfillment ([3550fa7](https://www.github.com/googleapis/python-dialogflow-cx/commit/3550fa7fa5863a313bd9288a1f515557f8f9fdea)) - mark agent.default_language_code as required ([3550fa7](https://www.github.com/googleapis/python-dialogflow-cx/commit/3550fa7fa5863a313bd9288a1f515557f8f9fdea)) ##### Bug Fixes - disable always_use_jwt_access ([#​119](https://www.github.com/googleapis/python-dialogflow-cx/issues/119)) ([3550fa7](https://www.github.com/googleapis/python-dialogflow-cx/commit/3550fa7fa5863a313bd9288a1f515557f8f9fdea)) ##### Documentation - add notes to train agent before sending queries ([3550fa7](https://www.github.com/googleapis/python-dialogflow-cx/commit/3550fa7fa5863a313bd9288a1f515557f8f9fdea)) - added notes to train agent before sending queries ([#​111](https://www.github.com/googleapis/python-dialogflow-cx/issues/111)) ([8a53800](https://www.github.com/googleapis/python-dialogflow-cx/commit/8a5380055dfa7d58f83be5ce0da310318b54fc51)) - omit mention of Python 2.7 in 'CONTRIBUTING.rst' ([#​1127](https://www.github.com/googleapis/python-dialogflow-cx/issues/1127)) ([#​110](https://www.github.com/googleapis/python-dialogflow-cx/issues/110)) ([40974f5](https://www.github.com/googleapis/python-dialogflow-cx/commit/40974f56c27833ab23575426f75d0868e1a10d94)), closes [#​1126](https://www.github.com/googleapis/python-dialogflow-cx/issues/1126) ##### [0.7.1](https://www.github.com/googleapis/python-dialogflow-cx/compare/v0.7.0...v0.7.1) (2021-06-16) ##### Bug Fixes - **deps:** add packaging requirement ([#​105](https://www.github.com/googleapis/python-dialogflow-cx/issues/105)) ([5d47692](https://www.github.com/googleapis/python-dialogflow-cx/commit/5d476920c8c6825050a828896231542f6bfde2e2))
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-dialogflow-cx). * chore(deps): update dependency google-cloud-dialogflow-cx to v1 (#123) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-dialogflow-cx](https://togithub.com/googleapis/python-dialogflow-cx) | `==0.8.0` -> `==1.0.0` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.0.0/compatibility-slim/0.8.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.0.0/confidence-slim/0.8.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-dialogflow-cx ### [`v1.0.0`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​100-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev080v100-2021-06-30) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v0.8.0...v1.0.0) ##### Features - bump release level to production/stable ([#​88](https://www.github.com/googleapis/python-dialogflow-cx/issues/88)) ([47739f9](https://www.github.com/googleapis/python-dialogflow-cx/commit/47739f927032ca8701297260f0374f11b2c756b9))
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-dialogflow-cx). * chore(deps): update dependency google-cloud-dialogflow-cx to v1.1.0 (#132) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.1.1 (#136) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-dialogflow-cx](https://togithub.com/googleapis/python-dialogflow-cx) | `==1.1.0` -> `==1.1.1` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.1.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.1.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.1.1/compatibility-slim/1.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.1.1/confidence-slim/1.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-dialogflow-cx ### [`v1.1.1`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​111-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev110v111-2021-07-24) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v1.1.0...v1.1.1)
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-dialogflow-cx). * docs(samples): add agent creation code snippet (#146) * add agent creation code snippet * update test * Updated test * moved delete agent * lint fix * lint fix * Fixed Copyright * chore(deps): update dependency google-cloud-dialogflow-cx to v1.2.0 (#140) * docs(samples): add update intent sample (#142) * add update intent sample * fixed lint * added agent creation * fixed lint * added randomized agent name * Failing test fix * Fixed failing test * Change intent request * removed self from test * lint fix * Update samples/snippets/update_intent_test.py Co-authored-by: Leah E. Cole <6719667+leahecole@users.noreply.github.com> Co-authored-by: Leah E. Cole <6719667+leahecole@users.noreply.github.com> * chore: generate python samples templates in owlbot.py (#149) Generate python samples templates in owlbot.py * docs(samples): add region tags (#150) * docs(samples): add region tags (#151) Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/python-dialogflow-cx/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 * chore(deps): update dependency google-cloud-dialogflow-cx to v1.3.0 (#160) * chore(deps): update dependency pytest to v6.2.5 (#158) Co-authored-by: Anthonios Partheniou * chore(deps): update dependency google-cloud-dialogflow-cx to v1.3.1 (#163) * docs(samples): added page management samples (#152) * docs(samples): added page management samples * fixed failing test * Remvoe await * added await * added pytest async * Lint fix * Lint and test case fix * removed pytest.async * test fix * update tests * fix uuid * added asyncio * added loop * removed async * test fix * changed pytest scope to session * changes fixture scope * test change * test fix * changed response type * fixed list page test * lint fix * failing test fix * revised code per comments * converted object to string Co-authored-by: Anthonios Partheniou * chore: blacken samples noxfile template (#170) * docs(samples): added filter sample (#171) * docs(samples): added filter sample * lint fix * removed pytest variables * update test id * Update samples/snippets/list_testcase_results_test.py Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> * Revised Code * fixed failing test * lint fix * lint fix * lint fix * Update samples/snippets/list_testcase_results.py Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> * chore(deps): update dependency google-cloud-dialogflow-cx to v1.3.2 (#175) * chore: fail samples nox session if python version is missing (#180) * chore(python): Add kokoro configs for python 3.10 samples testing (#188) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.4.0 (#185) Co-authored-by: Anthonios Partheniou * chore(deps): update dependency google-cloud-dialogflow-cx to v1.5.0 (#190) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-dialogflow-cx](https://togithub.com/googleapis/python-dialogflow-cx) | `==1.4.0` -> `==1.5.0` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.5.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.5.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.5.0/compatibility-slim/1.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.5.0/confidence-slim/1.4.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-dialogflow-cx ### [`v1.5.0`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​150-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev140v150-2021-10-11) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v1.4.0...v1.5.0) ##### Features - add context manager support in client ([#​187](https://www.togithub.com/googleapis/python-dialogflow-cx/issues/187)) ([70d4776](https://www.github.com/googleapis/python-dialogflow-cx/commit/70d4776d80f1f60b3f45e08e8dc64a47e2fae3e6))
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-dialogflow-cx). * docs(samples): add voice selection (#184) * docs(samples): add voice selection * lint fix * Update samples/snippets/detect_intent_stream.py Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> * Update samples/snippets/detect_intent_stream.py Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> * docs(samples): added webhook sample (#169) * docs(samples): added webhook sample * fixed webhoot test * failling test fix * used json * added flask to requirment.txt * Changed request handling * update test * fixed failing test * convert response to string * lint * made test clearer * Added Flask and changed get_json * Removed flask import * added request * Changed code * changed test * changed test * changed test * Changed test * test fix * test fix * lint fix * Revised Code * Lint fix * fixed requirments.txt * Revised Code * lint fix * lint fix * lint fix * revised code * lint fix * docs(samples): adds list training phrases sample (#196) * chore(deps): update dependency flask to v2.0.2 (#194) Co-authored-by: Anthonios Partheniou * docs(samples): added comment to webhook sample (#211) * docs(samples): added comment to webhook sample * Update samples/snippets/webhook.py Co-authored-by: Leah E. Cole <6719667+leahecole@users.noreply.github.com> * comments fix Co-authored-by: Leah E. Cole <6719667+leahecole@users.noreply.github.com> * chore(deps): update dependency google-cloud-dialogflow-cx to v1.6.0 (#205) Co-authored-by: Anthonios Partheniou * chore(deps): update dependency google-cloud-dialogflow-cx to v1.7.0 (#213) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-dialogflow-cx](https://togithub.com/googleapis/python-dialogflow-cx) | `==1.6.0` -> `==1.7.0` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.7.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.7.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.7.0/compatibility-slim/1.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-dialogflow-cx/1.7.0/confidence-slim/1.6.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-dialogflow-cx ### [`v1.7.0`](https://togithub.com/googleapis/python-dialogflow-cx/blob/master/CHANGELOG.md#​170-httpswwwgithubcomgoogleapispython-dialogflow-cxcomparev160v170-2021-11-12) [Compare Source](https://togithub.com/googleapis/python-dialogflow-cx/compare/v1.6.0...v1.7.0) ##### Features - allow setting custom CA for generic webhooks ([#​207](https://www.togithub.com/googleapis/python-dialogflow-cx/issues/207)) ([441d66b](https://www.github.com/googleapis/python-dialogflow-cx/commit/441d66b3864c34cf37570b6c58ccf097eb20e919)) ##### Documentation - **samples:** added comment to webhook sample ([#​211](https://www.togithub.com/googleapis/python-dialogflow-cx/issues/211)) ([4d36e31](https://www.github.com/googleapis/python-dialogflow-cx/commit/4d36e31f20e38755dd5d4a7a92bb8c48722cb11e))
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-dialogflow-cx). * docs(samples): Added LRO code snippet (#220) * docs(samples): Added LRO code snippet * lint fix * converted export_agent response to string in test * Update samples/snippets/long_running_operation.py Co-authored-by: Dan Lee <71398022+dandhlee@users.noreply.github.com> * changed name of function Co-authored-by: Dan Lee <71398022+dandhlee@users.noreply.github.com> * chore(samples): Add check for tests in directory (#227) Source-Link: https://github.com/googleapis/synthtool/commit/52aef91f8d25223d9dbdb4aebd94ba8eea2101f3 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:36a95b8f494e4674dc9eee9af98961293b51b86b3649942aac800ae6c1f796d4 Co-authored-by: Owl Bot * chore(python): Noxfile recognizes that tests can live in a folder (#234) Source-Link: https://github.com/googleapis/synthtool/commit/4760d8dce1351d93658cb11d02a1b7ceb23ae5d7 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:f0e4b51deef56bed74d3e2359c583fc104a8d6367da3984fc5c66938db738828 Co-authored-by: Owl Bot * chore(deps): update dependency google-cloud-dialogflow-cx to v1.8.0 (#233) Co-authored-by: Anthonios Partheniou * chore(deps): update dependency pytest to v7 (#246) * chore: use gapic-generator-python 0.63.1 (#245) - [x] Regenerate this pull request now. docs: add autogenerated code snippets PiperOrigin-RevId: 426256923 Source-Link: https://github.com/googleapis/googleapis/commit/9ebabfa115341b8016b6ed64b22c04260360a8ff Source-Link: https://github.com/googleapis/googleapis-gen/commit/a88175263e60a1d45d3a447848652b0f670b2cb8 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYTg4MTc1MjYzZTYwYTFkNDVkM2E0NDc4NDg2NTJiMGY2NzBiMmNiOCJ9 Fixes #229 * chore(deps): update all dependencies (#251) * chore(deps): update all dependencies (#256) * chore(deps): update all dependencies * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot * chore: Adding support for pytest-xdist and pytest-parallel (#264) Source-Link: https://github.com/googleapis/synthtool/commit/82f5cb283efffe96e1b6cd634738e0e7de2cd90a Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:5d8da01438ece4021d135433f2cf3227aa39ef0eaccc941d62aa35e6902832ae Co-authored-by: Owl Bot * chore(deps): update dependency google-cloud-dialogflow-cx to v1.9.1 (#267) * chore(deps): update all dependencies (#271) * chore(deps): update dependency pytest to v7.1.1 (#272) Co-authored-by: Anthonios Partheniou * chore(python): use black==22.3.0 (#282) Source-Link: https://github.com/googleapis/synthtool/commit/6fab84af09f2cf89a031fd8671d1def6b2931b11 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:7cffbc10910c3ab1b852c05114a08d374c195a81cdec1d4a67a1d129331d0bfe * chore(deps): update dependency flask to v2.1.0 (#280) Co-authored-by: Anthonios Partheniou * chore(deps): update dependency flask to v2.1.1 (#284) Co-authored-by: Anthonios Partheniou * chore(python): add nox session to sort python imports (#295) Source-Link: https://github.com/googleapis/synthtool/commit/1b71c10e20de7ed3f97f692f99a0e3399b67049f Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:00c9d764fd1cd56265f12a5ef4b99a0c9e87cf261018099141e2ca5158890416 Co-authored-by: Owl Bot * chore(deps): update dependency pytest to v7.1.2 (#299) * chore(deps): update dependency flask to v2.1.2 (#301) * docs(samples): Adds snippet for validating a form parameter. (#302) * docs(samples): Configure session parameters snippet (#303) * chore: update copyright year * chore: Cleans up stray # in docstring. * docs(samples): Adds snippet for configuring new session parameters. * Update module docstring for the validate form parameter snippet. * docs(samples): Configure session parameters trigger transition (#304) * chore: Typo fixes * docs(samples): Adds snippet for configuring new session parameters trigger transition. * docs(samples): Adds snippet for configuring optional or required form parameters (#305) * docs(samples): Adds snippet for configuring a webhook to enable an agent response. (#306) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.11.0 (#308) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.12.0 (#315) * chore: Update dialogflow_cx_webhook snippet to match NodeJS (#409) * chore: Update dialogflow_cx_webhook snippet to match NodeJS * Updates noxfile to skip deps install, if empty; otherwise an exception occurs * chore: Dialogflow cx v3 webhook validate form parameter (#410) * chore: update region tag for webhook validate form parameter snippet * update snippet and test for consistency with NodeJS implementation * linting * chore: update dialogflow_cx_v3_webhook_configure_session_parameters snippet (#411) * chore: Remove refactored webhook snippets (#412) * docs: add streaming detect intent with partial response sample (#414) * docs: add streaming detect intent with partial response sample * linting * docs: add detect intent with sentiment analysis snippet (#416) * docs: add detect intent with intent input snippet (#417) WIP * docs: add detect intent with text-to-speech synthesized output snippet (#419) chore: Update test-samples-impl.sh python3.6 --> python3.9 (#418) Source-Link: https://github.com/googleapis/synthtool/commit/1f071109dfe8c05f93879cc7123abd9b61f340e6 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:a5d81b61dfd1a432d3c03f51a25d2e71b37be24da509966d50724aea7c57c5c2 Co-authored-by: Owl Bot Co-authored-by: nicain fix test * docs: Dialogflow cx v3 detect intent event input snippet (#421) * docs: add detect event with event input snippet * Update detect_intent_event_test.py * fix: Update detect_intent_synthesize_tts_response.py (#423) * fix: Update detect_intent_synthesize_tts_response.py * Update detect_intent_synthesize_tts_response.py * docs: Add dialogflow cx detect intent with disabled webhook snippet (#422) * docs: Add dialogflow cx detect intent with disabled webhook snippet * Update detect_intent_disabled_webhook_test.py * chore(python): drop python 3.6 (#420) Source-Link: https://github.com/googleapis/synthtool/commit/4f89b13af10d086458f9b379e56a614f9d6dab7b Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:e7bb19d47c13839fe8c147e50e02e8b6cf5da8edd1af8b82208cd6f66cc2829c Co-authored-by: Owl Bot Co-authored-by: nicain * docs: Update region_tag: dialogflow_detect_intent_text --> dialogflow_cx_detect_intent_text (#424) * chore(deps): update all dependencies (#429) * chore(deps): update all dependencies * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * revert Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou * chore(deps): update all dependencies (#430) * chore(deps): update all dependencies * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * revert Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou * chore(deps): update all dependencies (#431) * chore(deps): update all dependencies * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * revert Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou * chore(deps): update all dependencies (#432) * chore(deps): update all dependencies * revert * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Anthonios Partheniou Co-authored-by: Owl Bot * chore(deps): update dependency google-cloud-dialogflow-cx to v1.13.1 (#438) * docs(samples): Add prebuilt telecom agent webhook code in python (#434) * feat: add prebuilt telecom webhook python sample code and test * feat:add test * fix:lint errors * fix:add new line at the end of file * fix: add more comprehensive tests * fix: pylint * feat:change helper function and address comments * fix: pylint Co-authored-by: nicain Co-authored-by: Anthonios Partheniou * chore(deps): update dependency pytest to v7.1.3 (#450) * chore: detect samples tests in nested directories (#456) Source-Link: https://github.com/googleapis/synthtool/commit/50db768f450a50d7c1fd62513c113c9bb96fd434 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:e09366bdf0fd9c8976592988390b24d53583dd9f002d476934da43725adbb978 Co-authored-by: Owl Bot * feat: Adding snippet to extract SessionInfo (#457) This snippet provides an example of how to extract SessionInfo from WebhookRequests. Co-authored-by: Anthonios Partheniou * chore(deps): update dependency google-cloud-dialogflow-cx to v1.13.4 (#464) * chore(deps): update dependency pytest to v7.2.0 (#467) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.13.5 (#468) * chore(python): drop flake8-import-order in samples noxfile (#473) Source-Link: https://github.com/googleapis/synthtool/commit/6ed3a831cb9ff69ef8a504c353e098ec0192ad93 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:3abfa0f1886adaf0b83f07cb117b24a639ea1cb9cffe56d43280b977033563eb Co-authored-by: Owl Bot * fix(deps): Require google-api-core >=1.34.0, >=2.11.0 (#469) * chore: update to gapic-generator-python 1.5.0 feat: add support for `google.cloud..__version__` PiperOrigin-RevId: 484665853 Source-Link: https://github.com/googleapis/googleapis/commit/8eb249a19db926c2fbc4ecf1dc09c0e521a88b22 Source-Link: https://github.com/googleapis/googleapis-gen/commit/c8aa327b5f478865fc3fd91e3c2768e54e26ad44 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYzhhYTMyN2I1ZjQ3ODg2NWZjM2ZkOTFlM2MyNzY4ZTU0ZTI2YWQ0NCJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * docs: Clarify interactive logging TTL behavior PiperOrigin-RevId: 485069403 Source-Link: https://github.com/googleapis/googleapis/commit/63cd62a6f31bcdbb178908c691dcc38da33221c6 Source-Link: https://github.com/googleapis/googleapis-gen/commit/d4f928e8aa29d03051428f8661827a534de6e1f6 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZDRmOTI4ZThhYTI5ZDAzMDUxNDI4Zjg2NjE4MjdhNTM0ZGU2ZTFmNiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * update version in gapic_version.py * add .release-please-manifest.json with correct version * set manifest to true in .github/release-please.yml * add release-please-config.json * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * feat: new APIs added to reflect updates to the filestore service - Add ENTERPRISE Tier - Add snapshot APIs: RevertInstance, ListSnapshots, CreateSnapshot, DeleteSnapshot, UpdateSnapshot - Add multi-share APIs: ListShares, GetShare, CreateShare, DeleteShare, UpdateShare - Add ConnectMode to NetworkConfig (for Private Service Access support) - New status codes (SUSPENDED/SUSPENDING, REVERTING/RESUMING) - Add SuspensionReason (for KMS related suspension) - Add new fields to Instance information: max_capacity_gb, capacity_step_size_gb, max_share_count, capacity_gb, multi_share_enabled PiperOrigin-RevId: 487492758 Source-Link: https://github.com/googleapis/googleapis/commit/5be5981f50322cf0c7388595e0f31ac5d0693469 Source-Link: https://github.com/googleapis/googleapis-gen/commit/ab0e217f560cc2c1afc11441c2eab6b6950efd2b Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYWIwZTIxN2Y1NjBjYzJjMWFmYzExNDQxYzJlYWI2YjY5NTBlZmQyYiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * update path to snippet metadata json * feat: Add files field to finding's list of attributes PiperOrigin-RevId: 488290111 Source-Link: https://github.com/googleapis/googleapis/commit/7349e1cd02f5b40058f457387f604357dc871a57 Source-Link: https://github.com/googleapis/googleapis-gen/commit/721049d512deebaa96d438aa23e970299d97712b Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNzIxMDQ5ZDUxMmRlZWJhYTk2ZDQzOGFhMjNlOTcwMjk5ZDk3NzEyYiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * docs: Clarified Agent Assist max retention is 30 days PiperOrigin-RevId: 489241089 Source-Link: https://github.com/googleapis/googleapis/commit/e7950299cb44b7e532ef8e311a143c0f22e82c2f Source-Link: https://github.com/googleapis/googleapis-gen/commit/4380bee60092cd1aaf2be81b6c08bb76f8c12a66 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNDM4MGJlZTYwMDkyY2QxYWFmMmJlODFiNmMwOGJiNzZmOGMxMmE2NiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * docs: Clarified Agent Assist max retention is 30 days PiperOrigin-RevId: 489494670 Source-Link: https://github.com/googleapis/googleapis/commit/e35c0d3893f60dfabadd2759d8100c0c81a7cf97 Source-Link: https://github.com/googleapis/googleapis-gen/commit/4c3848551a76fdf190533292127211a4ad8fee8b Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNGMzODQ4NTUxYTc2ZmRmMTkwNTMzMjkyMTI3MjExYTRhZDhmZWU4YiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * chore: use templated setup.py and owlbot.py * chore(python): fix warehouse-package-name for dialogflow/cx v3 and v3beta1 PiperOrigin-RevId: 492185983 Source-Link: https://github.com/googleapis/googleapis/commit/ac614c70cdf2e0bfed71b046ebbc31a5490cbd04 Source-Link: https://github.com/googleapis/googleapis-gen/commit/ce0d078339e501a500a28fdc4836a8dcccbb7e3b Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiY2UwZDA3ODMzOWU1MDFhNTAwYTI4ZmRjNDgzNmE4ZGNjY2JiN2UzYiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix(deps): Require google-api-core >=1.34.0, >=2.11.0 fix: Drop usage of pkg_resources fix: Fix timeout default values docs(samples): Snippetgen should call await on the operation coroutine before calling result PiperOrigin-RevId: 493260409 Source-Link: https://github.com/googleapis/googleapis/commit/fea43879f83a8d0dacc9353b3f75f8f46d37162f Source-Link: https://github.com/googleapis/googleapis-gen/commit/387b7344c7529ee44be84e613b19a820508c612b Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMzg3YjczNDRjNzUyOWVlNDRiZTg0ZTYxM2IxOWE4MjA1MDhjNjEyYiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add gapic_version.py Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou * chore(deps): update dependency google-cloud-dialogflow-cx to v1.14.0 (#476) * docs(samples): Update previous month logic to avoid zero-index bug in webhook_prebuilt_telecom sample (#479) * fix: Update previous month logic to avoid zer-index bug * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot * chore(python): add support for python 3.11 (#477) Source-Link: https://github.com/googleapis/synthtool/commit/7197a001ffb6d8ce7b0b9b11c280f0c536c1033a Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:c43f1d918bcf817d337aa29ff833439494a158a0831508fda4ec75dc4c0d0320 Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou * chore(deps): update dependency google-cloud-dialogflow-cx to v1.14.1 (#481) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.15.0 (#484) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.16.0 (#487) * chore(deps): update dependency pytest to v7.2.1 (#490) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.17.0 (#491) * chore(deps): update dependency google-cloud-dialogflow-cx to v1.17.1 (#494) Co-authored-by: Anthonios Partheniou * chore(deps): update dependency google-cloud-dialogflow-cx to v1.18.0 (#499) * Rename folder * Update CODEOWNERS * Update headers * remove dialogflow/noxfile.py * Update .github/CODEOWNERS --------- Co-authored-by: wuyuexin Co-authored-by: Dan O'Meara Co-authored-by: WhiteSource Renovate Co-authored-by: WhiteSource Renovate Co-authored-by: Yuexin Wu Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com> Co-authored-by: Leah E. Cole <6719667+leahecole@users.noreply.github.com> Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Co-authored-by: Anthonios Partheniou Co-authored-by: gcf-owl-bot[bot] <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Co-authored-by: Franklin Nunez <69214580+b-loved-dreamer@users.noreply.github.com> Co-authored-by: Dan Lee <71398022+dandhlee@users.noreply.github.com> Co-authored-by: Owl Bot Co-authored-by: nicain Co-authored-by: Yvonne Li Co-authored-by: hjosiah <104866418+hjosiah@users.noreply.github.com> Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com> --- .github/CODEOWNERS | 3 +- dialogflow-cx/README.rst | 221 +++++++++++++ dialogflow-cx/README.rst.in | 25 ++ dialogflow-cx/create_agent.py | 40 +++ dialogflow-cx/create_agent_test.py | 42 +++ dialogflow-cx/detect_intent_audio.py | 116 +++++++ dialogflow-cx/detect_intent_audio_test.py | 49 +++ .../detect_intent_disabled_webhook.py | 94 ++++++ .../detect_intent_disabled_webhook_test.py | 43 +++ dialogflow-cx/detect_intent_event.py | 90 +++++ dialogflow-cx/detect_intent_event_test.py | 49 +++ dialogflow-cx/detect_intent_stream.py | 157 +++++++++ dialogflow-cx/detect_intent_stream_test.py | 51 +++ .../detect_intent_synthesize_tts_response.py | 104 ++++++ ...ect_intent_synthesize_tts_response_test.py | 42 +++ dialogflow-cx/detect_intent_texts.py | 110 ++++++ dialogflow-cx/detect_intent_texts_test.py | 47 +++ .../detect_intent_with_intent_input.py | 94 ++++++ .../detect_intent_with_intent_input_test.py | 39 +++ .../detect_intent_with_sentiment_analysis.py | 89 +++++ ...ect_intent_with_sentiment_analysis_test.py | 43 +++ dialogflow-cx/list_testcase_results.py | 35 ++ dialogflow-cx/list_testcase_results_test.py | 30 ++ dialogflow-cx/list_training_phrases.py | 41 +++ dialogflow-cx/list_training_phrases_test.py | 34 ++ dialogflow-cx/long_running_operation.py | 43 +++ dialogflow-cx/long_running_operation_test.py | 67 ++++ dialogflow-cx/noxfile_config.py | 40 +++ dialogflow-cx/page_management.py | 80 +++++ dialogflow-cx/page_management_test.py | 115 +++++++ dialogflow-cx/requirements-test.txt | 1 + dialogflow-cx/requirements.txt | 3 + dialogflow-cx/resources/hello.wav | Bin 0 -> 29564 bytes ...treaming_detect_intent_partial_response.py | 126 +++++++ ...ing_detect_intent_partial_response_test.py | 50 +++ dialogflow-cx/update_intent.py | 34 ++ dialogflow-cx/update_intent_test.py | 83 +++++ dialogflow-cx/webhook.py | 43 +++ .../webhook_configure_session_parameters.py | 39 +++ ...bhook_configure_session_parameters_test.py | 36 ++ dialogflow-cx/webhook_log_session_info.py | 46 +++ .../webhook_log_session_info_test.py | 65 ++++ dialogflow-cx/webhook_prebuilt_telecom.py | 300 +++++++++++++++++ .../webhook_prebuilt_telecom_test.py | 312 ++++++++++++++++++ dialogflow-cx/webhook_test.py | 35 ++ .../webhook_validate_form_parameter.py | 46 +++ .../webhook_validate_form_parameter_test.py | 36 ++ 47 files changed, 3287 insertions(+), 1 deletion(-) create mode 100644 dialogflow-cx/README.rst create mode 100644 dialogflow-cx/README.rst.in create mode 100644 dialogflow-cx/create_agent.py create mode 100644 dialogflow-cx/create_agent_test.py create mode 100644 dialogflow-cx/detect_intent_audio.py create mode 100644 dialogflow-cx/detect_intent_audio_test.py create mode 100644 dialogflow-cx/detect_intent_disabled_webhook.py create mode 100644 dialogflow-cx/detect_intent_disabled_webhook_test.py create mode 100644 dialogflow-cx/detect_intent_event.py create mode 100644 dialogflow-cx/detect_intent_event_test.py create mode 100644 dialogflow-cx/detect_intent_stream.py create mode 100644 dialogflow-cx/detect_intent_stream_test.py create mode 100644 dialogflow-cx/detect_intent_synthesize_tts_response.py create mode 100644 dialogflow-cx/detect_intent_synthesize_tts_response_test.py create mode 100644 dialogflow-cx/detect_intent_texts.py create mode 100644 dialogflow-cx/detect_intent_texts_test.py create mode 100644 dialogflow-cx/detect_intent_with_intent_input.py create mode 100644 dialogflow-cx/detect_intent_with_intent_input_test.py create mode 100644 dialogflow-cx/detect_intent_with_sentiment_analysis.py create mode 100644 dialogflow-cx/detect_intent_with_sentiment_analysis_test.py create mode 100644 dialogflow-cx/list_testcase_results.py create mode 100644 dialogflow-cx/list_testcase_results_test.py create mode 100644 dialogflow-cx/list_training_phrases.py create mode 100644 dialogflow-cx/list_training_phrases_test.py create mode 100644 dialogflow-cx/long_running_operation.py create mode 100644 dialogflow-cx/long_running_operation_test.py create mode 100644 dialogflow-cx/noxfile_config.py create mode 100644 dialogflow-cx/page_management.py create mode 100644 dialogflow-cx/page_management_test.py create mode 100644 dialogflow-cx/requirements-test.txt create mode 100644 dialogflow-cx/requirements.txt create mode 100644 dialogflow-cx/resources/hello.wav create mode 100644 dialogflow-cx/streaming_detect_intent_partial_response.py create mode 100644 dialogflow-cx/streaming_detect_intent_partial_response_test.py create mode 100644 dialogflow-cx/update_intent.py create mode 100644 dialogflow-cx/update_intent_test.py create mode 100644 dialogflow-cx/webhook.py create mode 100644 dialogflow-cx/webhook_configure_session_parameters.py create mode 100644 dialogflow-cx/webhook_configure_session_parameters_test.py create mode 100644 dialogflow-cx/webhook_log_session_info.py create mode 100644 dialogflow-cx/webhook_log_session_info_test.py create mode 100644 dialogflow-cx/webhook_prebuilt_telecom.py create mode 100644 dialogflow-cx/webhook_prebuilt_telecom_test.py create mode 100644 dialogflow-cx/webhook_test.py create mode 100644 dialogflow-cx/webhook_validate_form_parameter.py create mode 100644 dialogflow-cx/webhook_validate_form_parameter_test.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1680fc1c38ea..00abede8b1db 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -44,10 +44,11 @@ /dataproc/**/* @GoogleCloudPlatform/python-samples-reviewers /datastore/**/* @GoogleCloudPlatform/cloud-native-db-dpes @GoogleCloudPlatform/python-samples-reviewers /dialogflow/**/* @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/python-samples-reviewers +/dialogflow-cx/**/* @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/python-samples-reviewers /dns/**/* @GoogleCloudPlatform/python-samples-reviewers /documentai/**/* @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/python-samples-reviewers /endpoints/**/* @GoogleCloudPlatform/python-samples-reviewers -/enterpriseknowledgegraph/**/* @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/python-samples-reviewers +/enterpriseknowledgegraph/**/* @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/python-samples-reviewers /eventarc/**/* @GoogleCloudPlatform/aap-dpes @GoogleCloudPlatform/python-samples-reviewers /error_reporting/**/* @GoogleCloudPlatform/python-samples-reviewers /firestore/**/* @GoogleCloudPlatform/cloud-native-db-dpes @GoogleCloudPlatform/python-samples-reviewers diff --git a/dialogflow-cx/README.rst b/dialogflow-cx/README.rst new file mode 100644 index 000000000000..7c403a4d7121 --- /dev/null +++ b/dialogflow-cx/README.rst @@ -0,0 +1,221 @@ + +.. This file is automatically generated. Do not edit this file directly. + +Dialogflow CX API Python Samples +=============================================================================== + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=/README.rst + + +This directory contains samples for Dialogflow CX API. The `Dialogflow CX API`_ enables you to create conversational experiences across devices and platforms. + + + + +.. _Dialogflow CX API: https://cloud.google.com/dialogflow/cx/docs/ + + +Setup +------------------------------------------------------------------------------- + + + +Authentication +++++++++++++++ + +This sample requires you to have authentication setup. Refer to the +`Authentication Getting Started Guide`_ for instructions on setting up +credentials for applications. + +.. _Authentication Getting Started Guide: + https://cloud.google.com/docs/authentication/getting-started + + + + +Install Dependencies +++++++++++++++++++++ + +#. Clone python-docs-samples and change directory to the sample directory you want to use. + + .. code-block:: bash + + $ git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git + +#. Install `pip`_ and `virtualenv`_ if you do not already have them. You may want to refer to the `Python Development Environment Setup Guide`_ for Google Cloud Platform for instructions. + + .. _Python Development Environment Setup Guide: + https://cloud.google.com/python/setup + +#. Create a virtualenv. Samples are compatible with Python 3.6+. + + .. code-block:: bash + + $ virtualenv env + $ source env/bin/activate + +#. Install the dependencies needed to run the samples. + + .. code-block:: bash + + $ pip install -r requirements.txt + +.. _pip: https://pip.pypa.io/ +.. _virtualenv: https://virtualenv.pypa.io/ + + + + + + +Samples +------------------------------------------------------------------------------- + + +Detect Intent Text ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=/detect_intent_texts.py,/README.rst + + + + +To run this sample: + +.. code-block:: bash + + $ python detect_intent_texts.py + + + usage: detect_intent_texts.py [-h] --agent AGENT [--session-id SESSION_ID] + [--language-code LANGUAGE_CODE] + texts [texts ...] + + DialogFlow API Detect Intent Python sample with text inputs. + + Examples: + python detect_intent_texts.py -h + python detect_intent_texts.py --agent AGENT --session-id SESSION_ID "hello" "book a meeting room" "Mountain View" + python detect_intent_texts.py --agent AGENT --session-id SESSION_ID "tomorrow" "10 AM" "2 hours" "10 people" "A" "yes" + + positional arguments: + texts Text inputs. + + optional arguments: + -h, --help show this help message and exit + --agent AGENT Agent resource name. Required. + --session-id SESSION_ID + Identifier of the DetectIntent session. Defaults to a + random UUID. + --language-code LANGUAGE_CODE + Language code of the query. Defaults to "en-US". + + + + + +Detect Intent Audio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=/detect_intent_audio.py,/README.rst + + + + +To run this sample: + +.. code-block:: bash + + $ python detect_intent_audio.py + + + usage: detect_intent_audio.py [-h] --agent AGENT [--session-id SESSION_ID] + [--language-code LANGUAGE_CODE] + --audio-file-path AUDIO_FILE_PATH + + DialogFlow API Detect Intent Python sample with audio file. + + Examples: + python detect_intent_audio.py -h + python detect_intent_audio.py --agent AGENT --session-id SESSION_ID --audio-file-path resources/hello.wav + + optional arguments: + -h, --help show this help message and exit + --agent AGENT Agent resource name. Required. + --session-id SESSION_ID + Identifier of the DetectIntent session. Defaults to a + random UUID. + --language-code LANGUAGE_CODE + Language code of the query. Defaults to "en-US". + --audio-file-path AUDIO_FILE_PATH + Path to the audio file. + + + + + +Detect Intent Stream ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=/detect_intent_stream.py,/README.rst + + + + +To run this sample: + +.. code-block:: bash + + $ python detect_intent_stream.py + + + usage: detect_intent_stream.py [-h] --agent AGENT [--session-id SESSION_ID] + [--language-code LANGUAGE_CODE] + --audio-file-path AUDIO_FILE_PATH + + DialogFlow API Detect Intent Python sample with audio files processed as an audio stream. + + Examples: + python detect_intent_stream.py -h + python detect_intent_stream.py --agent AGENT --session-id SESSION_ID --audio-file-path resources/hello.wav + + optional arguments: + -h, --help show this help message and exit + --agent AGENT Agent resource name. Required. + --session-id SESSION_ID + Identifier of the DetectIntent session. Defaults to a + random UUID. + --language-code LANGUAGE_CODE + Language code of the query. Defaults to "en-US". + --audio-file-path AUDIO_FILE_PATH + Path to the audio file. + + + + + + + + + +The client library +------------------------------------------------------------------------------- + +This sample uses the `Google Cloud Client Library for Python`_. +You can read the documentation for more details on API usage and use GitHub +to `browse the source`_ and `report issues`_. + +.. _Google Cloud Client Library for Python: + https://googlecloudplatform.github.io/google-cloud-python/ +.. _browse the source: + https://github.com/GoogleCloudPlatform/google-cloud-python +.. _report issues: + https://github.com/GoogleCloudPlatform/google-cloud-python/issues + + + +.. _Google Cloud SDK: https://cloud.google.com/sdk/ diff --git a/dialogflow-cx/README.rst.in b/dialogflow-cx/README.rst.in new file mode 100644 index 000000000000..043c9b772158 --- /dev/null +++ b/dialogflow-cx/README.rst.in @@ -0,0 +1,25 @@ +# This file is used to generate README.rst + +product: + name: Dialogflow CX API + short_name: Dialogflow CX API + url: https://cloud.google.com/dialogflow/cx/docs/ + description: > + The `Dialogflow CX API`_ enables you to create conversational experiences across devices and platforms. + +setup: +- auth +- install_deps + +samples: +- name: Detect Intent Text + file: detect_intent_texts.py + show_help: True +- name: Detect Intent Audio + file: detect_intent_audio.py + show_help: True +- name: Detect Intent Stream + file: detect_intent_stream.py + show_help: True + +cloud_client_library: true diff --git a/dialogflow-cx/create_agent.py b/dialogflow-cx/create_agent.py new file mode 100644 index 000000000000..541571b88784 --- /dev/null +++ b/dialogflow-cx/create_agent.py @@ -0,0 +1,40 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + + +"""DialogFlow API Create Agent Sample""" + +## [START dialogflow_cx_create_agent_sample] +from google.cloud.dialogflowcx_v3.services.agents.client import AgentsClient +from google.cloud.dialogflowcx_v3.types.agent import Agent + + +def create_agent(project_id, display_name): + + parent = "projects/" + project_id + "/locations/global" + + agents_client = AgentsClient() + + agent = Agent( + display_name=display_name, + default_language_code="en", + time_zone="America/Los_Angeles", + ) + + response = agents_client.create_agent(request={"agent": agent, "parent": parent}) + + return response + + +## [END dialogflow_cx_create_agent_sample] diff --git a/dialogflow-cx/create_agent_test.py b/dialogflow-cx/create_agent_test.py new file mode 100644 index 000000000000..dbb60b094e74 --- /dev/null +++ b/dialogflow-cx/create_agent_test.py @@ -0,0 +1,42 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Test for create_agent""" + +import os +import uuid + +from google.cloud.dialogflowcx_v3.services.agents.client import AgentsClient +from google.cloud.dialogflowcx_v3.types.agent import DeleteAgentRequest + +import pytest + +from create_agent import create_agent + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +pytest.AGENT_PATH = "" + + +def delete_agent(name): + agents_client = AgentsClient() + request = DeleteAgentRequest(name=name) + agents_client.delete_agent(request=request) + + +def test_create_agent(): + agentName = f"fake_agent_{uuid.uuid4()}" + response = create_agent(PROJECT_ID, agentName) + delete_agent(response.name) + + assert response.display_name == agentName diff --git a/dialogflow-cx/detect_intent_audio.py b/dialogflow-cx/detect_intent_audio.py new file mode 100644 index 000000000000..7ff892aa08ce --- /dev/null +++ b/dialogflow-cx/detect_intent_audio.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""DialogFlow API Detect Intent Python sample with audio file. + +Examples: + python detect_intent_audio.py -h + python detect_intent_audio.py --agent AGENT \ + --session-id SESSION_ID --audio-file-path resources/hello.wav +""" + +import argparse +import uuid + +from google.cloud.dialogflowcx_v3.services.agents import AgentsClient +from google.cloud.dialogflowcx_v3.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3.types import audio_config +from google.cloud.dialogflowcx_v3.types import session + + +# [START dialogflow_detect_intent_audio] +def run_sample(): + # TODO(developer): Replace these values when running the function + project_id = "YOUR-PROJECT-ID" + # For more information about regionalization see https://cloud.google.com/dialogflow/cx/docs/how/region + location_id = "YOUR-LOCATION-ID" + # For more info on agents see https://cloud.google.com/dialogflow/cx/docs/concept/agent + agent_id = "YOUR-AGENT-ID" + agent = f"projects/{project_id}/locations/{location_id}/agents/{agent_id}" + # For more information on sessions see https://cloud.google.com/dialogflow/cx/docs/concept/session + session_id = str(uuid.uuid4()) + audio_file_path = "YOUR-AUDIO-FILE-PATH" + # For more supported languages see https://cloud.google.com/dialogflow/es/docs/reference/language + language_code = "en-us" + + detect_intent_audio(agent, session_id, audio_file_path, language_code) + + +def detect_intent_audio(agent, session_id, audio_file_path, language_code): + """Returns the result of detect intent with an audio file as input. + + Using the same `session_id` between requests allows continuation + of the conversation.""" + session_path = f"{agent}/sessions/{session_id}" + print(f"Session path: {session_path}\n") + client_options = None + agent_components = AgentsClient.parse_agent_path(agent) + location_id = agent_components["location"] + if location_id != "global": + api_endpoint = f"{location_id}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + + input_audio_config = audio_config.InputAudioConfig( + audio_encoding=audio_config.AudioEncoding.AUDIO_ENCODING_LINEAR_16, + sample_rate_hertz=24000, + ) + + with open(audio_file_path, "rb") as audio_file: + input_audio = audio_file.read() + + audio_input = session.AudioInput(config=input_audio_config, audio=input_audio) + query_input = session.QueryInput(audio=audio_input, language_code=language_code) + request = session.DetectIntentRequest(session=session_path, query_input=query_input) + response = session_client.detect_intent(request=request) + + print("=" * 20) + print(f"Query text: {response.query_result.transcript}") + response_messages = [ + " ".join(msg.text.text) for msg in response.query_result.response_messages + ] + print(f"Response text: {' '.join(response_messages)}\n") + + +# [END dialogflow_detect_intent_audio] + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "--agent", help="Agent resource name. Required.", required=True + ) + parser.add_argument( + "--session-id", + help="Identifier of the DetectIntent session. " "Defaults to a random UUID.", + default=str(uuid.uuid4()), + ) + parser.add_argument( + "--language-code", + help='Language code of the query. Defaults to "en-US".', + default="en-US", + ) + parser.add_argument( + "--audio-file-path", help="Path to the audio file.", required=True + ) + + args = parser.parse_args() + + detect_intent_audio( + args.agent, args.session_id, args.audio_file_path, args.language_code + ) diff --git a/dialogflow-cx/detect_intent_audio_test.py b/dialogflow-cx/detect_intent_audio_test.py new file mode 100644 index 000000000000..e5dd3ab00795 --- /dev/null +++ b/dialogflow-cx/detect_intent_audio_test.py @@ -0,0 +1,49 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_texts.""" + +from __future__ import absolute_import + +import os +import uuid + + +from detect_intent_audio import detect_intent_audio + +DIRNAME = os.path.realpath(os.path.dirname(__file__)) +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") +AGENT_ID_US_CENTRAL1 = os.getenv("AGENT_ID_US_CENTRAL1") +AGENT = f"projects/{PROJECT_ID}/locations/global/agents/{AGENT_ID}" +AGENT_US_CENTRAL1 = ( + f"projects/{PROJECT_ID}/locations/us-central1/agents/{AGENT_ID_US_CENTRAL1}" +) +SESSION_ID = uuid.uuid4() +AUDIO_PATH = os.getenv("AUDIO_PATH") +AUDIO = f"{DIRNAME}/{AUDIO_PATH}" + + +def test_detect_intent_texts(capsys): + detect_intent_audio(AGENT, SESSION_ID, AUDIO, "en-US") + out, _ = capsys.readouterr() + + assert "Response text: Hi! I'm the virtual flights agent." in out + + +def test_detect_intent_texts_regional(capsys): + detect_intent_audio(AGENT_US_CENTRAL1, SESSION_ID, AUDIO, "en-US") + out, _ = capsys.readouterr() + + assert "Response text: Hi! I'm the virtual flights agent." in out diff --git a/dialogflow-cx/detect_intent_disabled_webhook.py b/dialogflow-cx/detect_intent_disabled_webhook.py new file mode 100644 index 000000000000..e5965859bcce --- /dev/null +++ b/dialogflow-cx/detect_intent_disabled_webhook.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""DialogFlow Detect Intent Python sample, with a disabled webhook.""" + + +# [START dialogflow_cx_detect_intent_with_disabled_webhook] +import uuid + +from google.cloud.dialogflowcx_v3.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3.types import session + + +def run_sample(): + # TODO(developer): Update these values when running the function + project_id = "YOUR-PROJECT-ID" + location = "YOUR-LOCATION-ID" + agent_id = "YOUR-AGENT-ID" + text = "Perfect!" + language_code = "en-us" + + detect_intent_disabled_webhook( + project_id, + location, + agent_id, + text, + language_code, + ) + + +def detect_intent_disabled_webhook( + project_id, + location, + agent_id, + text, + language_code, +): + """Returns the result of detect intent with sentiment analysis""" + + client_options = None + if location != "global": + api_endpoint = f"{location}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + session_id = str(uuid.uuid4()) + session_path = session_client.session_path( + project=project_id, + location=location, + agent=agent_id, + session=session_id, + ) + + # Prepare request + text_input = session.TextInput(text=text) + query_input = session.QueryInput(text=text_input, language_code=language_code) + query_params = session.QueryParameters( + disable_webhook=True, + ) + request = session.DetectIntentRequest( + session=session_path, + query_input=query_input, + query_params=query_params, + ) + + response = session_client.detect_intent(request=request) + print(f"Detect Intent Request: {request.query_params.disable_webhook}") + response_text = [] + for message in response.query_result.response_messages: + if message.text: + curr_response_text = message.text.text + print(f"Agent Response: {curr_response_text}") + response_text.append(curr_response_text) + return response_text + + +# [END dialogflow_cx_detect_intent_with_disabled_webhook] + + +if __name__ == "__main__": + run_sample() diff --git a/dialogflow-cx/detect_intent_disabled_webhook_test.py b/dialogflow-cx/detect_intent_disabled_webhook_test.py new file mode 100644 index 000000000000..64422d3b5c99 --- /dev/null +++ b/dialogflow-cx/detect_intent_disabled_webhook_test.py @@ -0,0 +1,43 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_with_sentiment_analysis.py""" + +from __future__ import absolute_import + +import os + +from detect_intent_disabled_webhook import detect_intent_disabled_webhook + + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") + + +def test_detect_intent_positive(): + response_text_list = detect_intent_disabled_webhook( + PROJECT_ID, + "global", + AGENT_ID, + "Perfect!", + "en-us", + ) + for response_text in response_text_list: + assert response_text[0] in [ + "You are welcome!", + "It's my pleasure.", + "Anytime.", + "Of course.", + "It's my pleasure to serve you.", + ] diff --git a/dialogflow-cx/detect_intent_event.py b/dialogflow-cx/detect_intent_event.py new file mode 100644 index 000000000000..2cd4790b23a0 --- /dev/null +++ b/dialogflow-cx/detect_intent_event.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""DialogFlow Detects intent using EventInput.""" + + +# [START dialogflow_cx_v3_detect_intent_event_input_async] +import uuid + +from google.cloud.dialogflowcx_v3.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3.types import session + + +def run_sample(): + # TODO(developer): Update these values when running the function + # project_id = "YOUR-PROJECT-ID" + # location = "YOUR-LOCATION-ID" + # agent_id = "YOUR-AGENT-ID" + # event = "YOUR-EVENT" + # language_code = "YOUR-LANGUAGE-CODE" + + project_id = "dialogflow-cx-demo-1-348717" + location = "global" + agent_id = "8caa6b47-5dd7-4380-b86e-ea4301d565b0" + event = "sys.no-match-default" + language_code = "en-us" + + detect_intent_with_event_input( + project_id, + location, + agent_id, + event, + language_code, + ) + + +def detect_intent_with_event_input( + project_id, + location, + agent_id, + event, + language_code, +): + """Detects intent using EventInput""" + client_options = None + if location != "global": + api_endpoint = f"{location}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + session_id = str(uuid.uuid4()) + session_path = session_client.session_path( + project=project_id, + location=location, + agent=agent_id, + session=session_id, + ) + + # Construct detect intent request: + event = session.EventInput(event=event) + query_input = session.QueryInput(event=event, language_code=language_code) + request = session.DetectIntentRequest( + session=session_path, + query_input=query_input, + ) + + response = session_client.detect_intent(request=request) + response_text = response.query_result.response_messages[0].text.text[0] + print(f"Response: {response_text}") + return response_text + + +# [END dialogflow_cx_v3_detect_intent_event_input_async] + + +if __name__ == "__main__": + run_sample() diff --git a/dialogflow-cx/detect_intent_event_test.py b/dialogflow-cx/detect_intent_event_test.py new file mode 100644 index 000000000000..dfbca5e0ff36 --- /dev/null +++ b/dialogflow-cx/detect_intent_event_test.py @@ -0,0 +1,49 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_with_sentiment_analysis.py""" + +from __future__ import absolute_import + +import os + +from detect_intent_event import detect_intent_with_event_input + + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") + + +def test_detect_intent_positive(): + response_text = detect_intent_with_event_input( + PROJECT_ID, + "global", + AGENT_ID, + "sys.no-match-default", + "en-us", + ) + assert response_text in [ + "Can you say that again?", + "I didn't get that. Can you repeat?", + "I didn't get that. Can you say it again?", + "I missed that, say that again?", + "I missed what you said. What was that?", + "One more time?", + "Say that one more time?", + "Sorry, can you say that again?", + "Sorry, could you say that again?", + "Sorry, I didn't get that. Can you rephrase?", + "Sorry, what was that?", + "What was that?", + ] diff --git a/dialogflow-cx/detect_intent_stream.py b/dialogflow-cx/detect_intent_stream.py new file mode 100644 index 000000000000..244fecaf03b8 --- /dev/null +++ b/dialogflow-cx/detect_intent_stream.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""DialogFlow API Detect Intent Python sample with audio files processed as an audio stream. + +Examples: + python detect_intent_stream.py -h + python detect_intent_stream.py --agent AGENT \ + --session-id SESSION_ID --audio-file-path resources/hello.wav +""" + +import argparse +import uuid + +from google.cloud.dialogflowcx_v3beta1.services.agents import AgentsClient +from google.cloud.dialogflowcx_v3beta1.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3beta1.types import audio_config +from google.cloud.dialogflowcx_v3beta1.types import session + + +# [START dialogflow_detect_intent_stream] +def run_sample(): + # TODO(developer): Replace these values when running the function + project_id = "YOUR-PROJECT-ID" + # For more information about regionalization see https://cloud.google.com/dialogflow/cx/docs/how/region + location_id = "YOUR-LOCATION-ID" + # For more info on agents see https://cloud.google.com/dialogflow/cx/docs/concept/agent + agent_id = "YOUR-AGENT-ID" + agent = f"projects/{project_id}/locations/{location_id}/agents/{agent_id}" + # For more information on sessions see https://cloud.google.com/dialogflow/cx/docs/concept/session + session_id = uuid.uuid4() + audio_file_path = "YOUR-AUDIO-FILE-PATH" + # For more supported languages see https://cloud.google.com/dialogflow/es/docs/reference/language + language_code = "en-us" + + detect_intent_stream(agent, session_id, audio_file_path, language_code) + + +def detect_intent_stream(agent, session_id, audio_file_path, language_code): + """Returns the result of detect intent with streaming audio as input. + + Using the same `session_id` between requests allows continuation + of the conversation.""" + session_path = f"{agent}/sessions/{session_id}" + print(f"Session path: {session_path}\n") + client_options = None + agent_components = AgentsClient.parse_agent_path(agent) + location_id = agent_components["location"] + if location_id != "global": + api_endpoint = f"{location_id}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + + input_audio_config = audio_config.InputAudioConfig( + audio_encoding=audio_config.AudioEncoding.AUDIO_ENCODING_LINEAR_16, + sample_rate_hertz=24000, + ) + + def request_generator(): + audio_input = session.AudioInput(config=input_audio_config) + query_input = session.QueryInput(audio=audio_input, language_code=language_code) + voice_selection = audio_config.VoiceSelectionParams() + synthesize_speech_config = audio_config.SynthesizeSpeechConfig() + output_audio_config = audio_config.OutputAudioConfig() + + # Sets the voice name and gender + voice_selection.name = "en-GB-Standard-A" + voice_selection.ssml_gender = ( + audio_config.SsmlVoiceGender.SSML_VOICE_GENDER_FEMALE + ) + + synthesize_speech_config.voice = voice_selection + + # Sets the audio encoding + output_audio_config.audio_encoding = ( + audio_config.OutputAudioEncoding.OUTPUT_AUDIO_ENCODING_UNSPECIFIED + ) + output_audio_config.synthesize_speech_config = synthesize_speech_config + + # The first request contains the configuration. + yield session.StreamingDetectIntentRequest( + session=session_path, + query_input=query_input, + output_audio_config=output_audio_config, + ) + + # Here we are reading small chunks of audio data from a local + # audio file. In practice these chunks should come from + # an audio input device. + with open(audio_file_path, "rb") as audio_file: + while True: + chunk = audio_file.read(4096) + if not chunk: + break + # The later requests contains audio data. + audio_input = session.AudioInput(audio=chunk) + query_input = session.QueryInput(audio=audio_input) + yield session.StreamingDetectIntentRequest(query_input=query_input) + + responses = session_client.streaming_detect_intent(requests=request_generator()) + + print("=" * 20) + for response in responses: + print(f'Intermediate transcript: "{response.recognition_result.transcript}".') + + # Note: The result from the last response is the final transcript along + # with the detected content. + response = response.detect_intent_response + print(f"Query text: {response.query_result.transcript}") + response_messages = [ + " ".join(msg.text.text) for msg in response.query_result.response_messages + ] + print(f"Response text: {' '.join(response_messages)}\n") + + +# [END dialogflow_detect_intent_stream] + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "--agent", help="Agent resource name. Required.", required=True + ) + parser.add_argument( + "--session-id", + help="Identifier of the DetectIntent session. " "Defaults to a random UUID.", + default=str(uuid.uuid4()), + ) + parser.add_argument( + "--language-code", + help='Language code of the query. Defaults to "en-US".', + default="en-US", + ) + parser.add_argument( + "--audio-file-path", help="Path to the audio file.", required=True + ) + + args = parser.parse_args() + + detect_intent_stream( + args.agent, args.session_id, args.audio_file_path, args.language_code + ) diff --git a/dialogflow-cx/detect_intent_stream_test.py b/dialogflow-cx/detect_intent_stream_test.py new file mode 100644 index 000000000000..4fd19ebe61c8 --- /dev/null +++ b/dialogflow-cx/detect_intent_stream_test.py @@ -0,0 +1,51 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_texts.""" + +from __future__ import absolute_import + +import os +import uuid + + +from detect_intent_stream import detect_intent_stream + +DIRNAME = os.path.realpath(os.path.dirname(__file__)) +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") +AGENT_ID_US_CENTRAL1 = os.getenv("AGENT_ID_US_CENTRAL1") +AGENT = f"projects/{PROJECT_ID}/locations/global/agents/{AGENT_ID}" +AGENT_US_CENTRAL1 = ( + f"projects/{PROJECT_ID}/locations/us-central1/agents/{AGENT_ID_US_CENTRAL1}" +) +SESSION_ID = uuid.uuid4() +AUDIO_PATH = os.getenv("AUDIO_PATH") +AUDIO = f"{DIRNAME}/{AUDIO_PATH}" + + +def test_detect_intent_texts(capsys): + detect_intent_stream(AGENT, SESSION_ID, AUDIO, "en-US") + out, _ = capsys.readouterr() + + assert "Intermediate transcript:" in out + assert "Response text: Hi! I'm the virtual flights agent." in out + + +def test_detect_intent_texts_regional(capsys): + detect_intent_stream(AGENT_US_CENTRAL1, SESSION_ID, AUDIO, "en-US") + out, _ = capsys.readouterr() + + assert "Intermediate transcript:" in out + assert "Response text: Hi! I'm the virtual flights agent." in out diff --git a/dialogflow-cx/detect_intent_synthesize_tts_response.py b/dialogflow-cx/detect_intent_synthesize_tts_response.py new file mode 100644 index 000000000000..96e8fbecbeaf --- /dev/null +++ b/dialogflow-cx/detect_intent_synthesize_tts_response.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +# Detects intent and returns a synthesized Text-to-Speech (TTS) response + +# [START dialogflow_cx_v3_detect_intent_synthesize_tts_response_async] +import uuid + +from google.cloud.dialogflowcx_v3.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3.types import audio_config +from google.cloud.dialogflowcx_v3.types import session + + +def run_sample(): + # TODO(developer): Update these values when running the function + project_id = "YOUR-PROJECT-ID" + location = "YOUR-LOCATION-ID" + agent_id = "YOUR-AGENT-ID" + text = "YOUR-TEXT" + audio_encoding = "YOUR-AUDIO-ENCODING" + language_code = "YOUR-LANGUAGE-CODE" + output_file = "YOUR-OUTPUT-FILE" + + detect_intent_synthesize_tts_response( + project_id, + location, + agent_id, + text, + audio_encoding, + language_code, + output_file, + ) + + +def detect_intent_synthesize_tts_response( + project_id, + location, + agent_id, + text, + audio_encoding, + language_code, + output_file, +): + """Returns the result of detect intent with synthesized response.""" + client_options = None + if location != "global": + api_endpoint = f"{location}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + session_id = str(uuid.uuid4()) + + # Constructs the audio query request + session_path = session_client.session_path( + project=project_id, + location=location, + agent=agent_id, + session=session_id, + ) + text_input = session.TextInput(text=text) + query_input = session.QueryInput(text=text_input, language_code=language_code) + synthesize_speech_config = audio_config.SynthesizeSpeechConfig( + speaking_rate=1.25, + pitch=10.0, + ) + output_audio_config = audio_config.OutputAudioConfig( + synthesize_speech_config=synthesize_speech_config, + audio_encoding=audio_config.OutputAudioEncoding[audio_encoding], + ) + request = session.DetectIntentRequest( + session=session_path, + query_input=query_input, + output_audio_config=output_audio_config, + ) + + response = session_client.detect_intent(request=request) + print( + "Speaking Rate: " + f"{response.output_audio_config.synthesize_speech_config.speaking_rate}" + ) + print("Pitch: " f"{response.output_audio_config.synthesize_speech_config.pitch}") + with open(output_file, "wb") as fout: + fout.write(response.output_audio) + print(f"Audio content written to file: {output_file}") + + +# [END dialogflow_cx_v3_detect_intent_synthesize_tts_response_async] + + +if __name__ == "__main__": + run_sample() diff --git a/dialogflow-cx/detect_intent_synthesize_tts_response_test.py b/dialogflow-cx/detect_intent_synthesize_tts_response_test.py new file mode 100644 index 000000000000..3c64f9874b0c --- /dev/null +++ b/dialogflow-cx/detect_intent_synthesize_tts_response_test.py @@ -0,0 +1,42 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_with_sentiment_analysis.py""" + +from __future__ import absolute_import + +import os + +from detect_intent_synthesize_tts_response import detect_intent_synthesize_tts_response + + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") + + +def test_detect_intent_positive(capsys, tmp_path_factory): + + output_file = tmp_path_factory.mktemp("data") / "tmp.wav" + + detect_intent_synthesize_tts_response( + PROJECT_ID, + "global", + AGENT_ID, + "Perfect!", + "OUTPUT_AUDIO_ENCODING_LINEAR_16", + "en-us", + output_file, + ) + out, _ = capsys.readouterr() + assert f"Audio content written to file: {output_file}" in out diff --git a/dialogflow-cx/detect_intent_texts.py b/dialogflow-cx/detect_intent_texts.py new file mode 100644 index 000000000000..9eb77afb94a5 --- /dev/null +++ b/dialogflow-cx/detect_intent_texts.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""DialogFlow API Detect Intent Python sample with text inputs. + +Examples: + python detect_intent_texts.py -h + python detect_intent_texts.py --agent AGENT \ + --session-id SESSION_ID \ + "hello" "book a meeting room" "Mountain View" + python detect_intent_texts.py --agent AGENT \ + --session-id SESSION_ID \ + "tomorrow" "10 AM" "2 hours" "10 people" "A" "yes" +""" + +import argparse +import uuid + +from google.cloud.dialogflowcx_v3beta1.services.agents import AgentsClient +from google.cloud.dialogflowcx_v3beta1.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3beta1.types import session + + +# [START dialogflow_cx_detect_intent_text] +def run_sample(): + # TODO(developer): Replace these values when running the function + project_id = "YOUR-PROJECT-ID" + # For more information about regionalization see https://cloud.google.com/dialogflow/cx/docs/how/region + location_id = "YOUR-LOCATION-ID" + # For more info on agents see https://cloud.google.com/dialogflow/cx/docs/concept/agent + agent_id = "YOUR-AGENT-ID" + agent = f"projects/{project_id}/locations/{location_id}/agents/{agent_id}" + # For more information on sessions see https://cloud.google.com/dialogflow/cx/docs/concept/session + session_id = uuid.uuid4() + texts = ["Hello"] + # For more supported languages see https://cloud.google.com/dialogflow/es/docs/reference/language + language_code = "en-us" + + detect_intent_texts(agent, session_id, texts, language_code) + + +def detect_intent_texts(agent, session_id, texts, language_code): + """Returns the result of detect intent with texts as inputs. + + Using the same `session_id` between requests allows continuation + of the conversation.""" + session_path = f"{agent}/sessions/{session_id}" + print(f"Session path: {session_path}\n") + client_options = None + agent_components = AgentsClient.parse_agent_path(agent) + location_id = agent_components["location"] + if location_id != "global": + api_endpoint = f"{location_id}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + + for text in texts: + text_input = session.TextInput(text=text) + query_input = session.QueryInput(text=text_input, language_code=language_code) + request = session.DetectIntentRequest( + session=session_path, query_input=query_input + ) + response = session_client.detect_intent(request=request) + + print("=" * 20) + print(f"Query text: {response.query_result.text}") + response_messages = [ + " ".join(msg.text.text) for msg in response.query_result.response_messages + ] + print(f"Response text: {' '.join(response_messages)}\n") + + +# [END dialogflow_cx_detect_intent_text] + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "--agent", help="Agent resource name. Required.", required=True + ) + parser.add_argument( + "--session-id", + help="Identifier of the DetectIntent session. " "Defaults to a random UUID.", + default=str(uuid.uuid4()), + ) + parser.add_argument( + "--language-code", + help='Language code of the query. Defaults to "en-US".', + default="en-US", + ) + parser.add_argument("texts", nargs="+", type=str, help="Text inputs.") + + args = parser.parse_args() + + detect_intent_texts(args.agent, args.session_id, args.texts, args.language_code) diff --git a/dialogflow-cx/detect_intent_texts_test.py b/dialogflow-cx/detect_intent_texts_test.py new file mode 100644 index 000000000000..7000520134c8 --- /dev/null +++ b/dialogflow-cx/detect_intent_texts_test.py @@ -0,0 +1,47 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_texts.""" + +from __future__ import absolute_import + +import os +import uuid + + +from detect_intent_texts import detect_intent_texts + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") +AGENT = f"projects/{PROJECT_ID}/locations/global/agents/{AGENT_ID}" +SESSION_ID = uuid.uuid4() +TEXTS = ["hello", "book a flight"] +AGENT_ID_US_CENTRAL1 = os.getenv("AGENT_ID_US_CENTRAL1") +AGENT_US_CENTRAL1 = ( + f"projects/{PROJECT_ID}/locations/us-central1/agents/{AGENT_ID_US_CENTRAL1}" +) + + +def test_detect_intent_texts(capsys): + detect_intent_texts(AGENT, SESSION_ID, TEXTS, "en-US") + out, _ = capsys.readouterr() + + assert "Response text: I can help you find a ticket" in out + + +def test_detect_intent_texts_regional(capsys): + detect_intent_texts(AGENT_US_CENTRAL1, SESSION_ID, TEXTS, "en-US") + out, _ = capsys.readouterr() + + assert "Response text: I can help you find a ticket" in out diff --git a/dialogflow-cx/detect_intent_with_intent_input.py b/dialogflow-cx/detect_intent_with_intent_input.py new file mode 100644 index 000000000000..9a1e77c27486 --- /dev/null +++ b/dialogflow-cx/detect_intent_with_intent_input.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""DialogFlow Detect Intent Python sample with specified intent.""" + + +# [START dialogflow_cx_v3_detect_intent_with_intent_input_async] +import uuid + +from google.cloud.dialogflowcx_v3.services.intents import IntentsClient +from google.cloud.dialogflowcx_v3.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3.types import session + + +def run_sample(): + # TODO(developer): Update these values when running the function + project_id = "YOUR-PROJECT-ID" + location = "YOUR-LOCATION-ID" + agent_id = "YOUR-AGENT-ID" + intent_id = "YOUR-INTENT-ID" + language_code = "en-us" + + detect_intent_with_intent_input( + project_id, + location, + agent_id, + intent_id, + language_code, + ) + + +def detect_intent_with_intent_input( + project_id, + location, + agent_id, + intent_id, + language_code, +): + """Returns the result of detect intent with sentiment analysis""" + client_options = None + if location != "global": + api_endpoint = f"{location}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + session_id = str(uuid.uuid4()) + intents_client = IntentsClient() + + session_path = session_client.session_path( + project=project_id, + location=location, + agent=agent_id, + session=session_id, + ) + intent_path = intents_client.intent_path( + project=project_id, + location=location, + agent=agent_id, + intent=intent_id, + ) + + intent = session.IntentInput(intent=intent_path) + query_input = session.QueryInput(intent=intent, language_code=language_code) + request = session.DetectIntentRequest( + session=session_path, + query_input=query_input, + ) + + response = session_client.detect_intent(request=request) + response_text = [] + for response_message in response.query_result.response_messages: + response_text.append(response_message.text.text) + print(response_message.text.text) + return response_text + + +# [END dialogflow_cx_v3_detect_intent_with_intent_input_async] + + +if __name__ == "__main__": + run_sample() diff --git a/dialogflow-cx/detect_intent_with_intent_input_test.py b/dialogflow-cx/detect_intent_with_intent_input_test.py new file mode 100644 index 000000000000..28899d482ce6 --- /dev/null +++ b/dialogflow-cx/detect_intent_with_intent_input_test.py @@ -0,0 +1,39 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_with_sentiment_analysis.py""" + +from __future__ import absolute_import + +import os + +from detect_intent_with_intent_input import detect_intent_with_intent_input + + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") +INTENT_ID = os.getenv("INTENT_ID") + + +def test_detect_intent_with_intent_input(): + response_text = detect_intent_with_intent_input( + PROJECT_ID, + "global", + AGENT_ID, + INTENT_ID, + "en-us", + ) + assert len(response_text) == 2 + assert response_text[0] == ["Let's find a one-way ticket for you. "] + assert response_text[1] == ["Which city are you leaving from?"] diff --git a/dialogflow-cx/detect_intent_with_sentiment_analysis.py b/dialogflow-cx/detect_intent_with_sentiment_analysis.py new file mode 100644 index 000000000000..57009e5fe9ad --- /dev/null +++ b/dialogflow-cx/detect_intent_with_sentiment_analysis.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""DialogFlow Detect Intent Python sample, text input and sentiment analysis.""" + + +# [START dialogflow_cx_v3_detect_intent_sentiment_analysis_async] +import uuid + +from google.cloud.dialogflowcx_v3beta1.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3beta1.types import session + + +def run_sample(): + # TODO(developer): Update these values when running the function + project_id = "YOUR-PROJECT-ID" + location = "YOUR-LOCATION-ID" + agent_id = "YOUR-AGENT-ID" + text = "Perfect!" + language_code = "en-us" + + detect_intent_with_sentiment_analysis( + project_id, + location, + agent_id, + text, + language_code, + ) + + +def detect_intent_with_sentiment_analysis( + project_id, + location, + agent_id, + text, + language_code, +): + """Returns the result of detect intent with sentiment analysis""" + + client_options = None + if location != "global": + api_endpoint = f"{location}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + session_id = str(uuid.uuid4()) + + session_path = session_client.session_path( + project=project_id, + location=location, + agent=agent_id, + session=session_id, + ) + + text_input = session.TextInput(text=text) + query_input = session.QueryInput(text=text_input, language_code=language_code) + query_params = session.QueryParameters( + analyze_query_text_sentiment=True, + ) + request = session.DetectIntentRequest( + session=session_path, + query_input=query_input, + query_params=query_params, + ) + + response = session_client.detect_intent(request=request) + score = response.query_result.sentiment_analysis_result.score + print("Sentiment Score: {score}") + return score + + +# [END dialogflow_cx_v3_detect_intent_sentiment_analysis_async] + + +if __name__ == "__main__": + run_sample() diff --git a/dialogflow-cx/detect_intent_with_sentiment_analysis_test.py b/dialogflow-cx/detect_intent_with_sentiment_analysis_test.py new file mode 100644 index 000000000000..640d15816830 --- /dev/null +++ b/dialogflow-cx/detect_intent_with_sentiment_analysis_test.py @@ -0,0 +1,43 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_with_sentiment_analysis.py""" + +from __future__ import absolute_import + +import os + +import pytest + +from detect_intent_with_sentiment_analysis import detect_intent_with_sentiment_analysis + + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") + + +@pytest.mark.parametrize( + "text, expected_score_min, expected_score_max", + (["Perfect", 0.5, 1], ["I am not happy", -1, -0.5]), +) +def test_detect_intent_positive(text, expected_score_min, expected_score_max): + + score = detect_intent_with_sentiment_analysis( + PROJECT_ID, + "global", + AGENT_ID, + text, + "en-us", + ) + assert expected_score_min < score < expected_score_max diff --git a/dialogflow-cx/list_testcase_results.py b/dialogflow-cx/list_testcase_results.py new file mode 100644 index 000000000000..8723f2db2857 --- /dev/null +++ b/dialogflow-cx/list_testcase_results.py @@ -0,0 +1,35 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +# [START dialogflow_list_test_case_results_sample] + +from google.cloud.dialogflowcx_v3.services.test_cases.client import TestCasesClient +from google.cloud.dialogflowcx_v3.types.test_case import ListTestCaseResultsRequest + + +def list_test_case(project_id, agent_id, test_id, location): + + req = ListTestCaseResultsRequest() + req.parent = f"projects/{project_id}/locations/{location}/agents/{agent_id}/testCases/{test_id}" + req.filter = "environment=draft" + client = TestCasesClient( + client_options={"api_endpoint": f"{location}-dialogflow.googleapis.com"} + ) + # Makes a call to list all test case results that match filter + result = client.list_test_case_results(request=req) + print(result) + return result + + +# [END dialogflow_list_test_case_results_sample] diff --git a/dialogflow-cx/list_testcase_results_test.py b/dialogflow-cx/list_testcase_results_test.py new file mode 100644 index 000000000000..35f1ac636afd --- /dev/null +++ b/dialogflow-cx/list_testcase_results_test.py @@ -0,0 +1,30 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + + +import google.auth + +from list_testcase_results import list_test_case + +LOCATION = "global" + +_, PROJECT_ID = google.auth.default() +AGENT_ID = "143dee60-56fe-4191-a8d8-095f569f6cd8" +TEST_ID = "3c48d39e-71c0-4cb0-b974-3d5c596d347e" + + +def test_list_testcase_results(): + result = list_test_case(PROJECT_ID, AGENT_ID, TEST_ID, LOCATION) + + assert "Hello! How can I help you?" in str(result) diff --git a/dialogflow-cx/list_training_phrases.py b/dialogflow-cx/list_training_phrases.py new file mode 100644 index 000000000000..6fcfc1ee038b --- /dev/null +++ b/dialogflow-cx/list_training_phrases.py @@ -0,0 +1,41 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +# [START dialogflow_list_training_phrases] + + +def list_training_phrases(project_id, agent_id, intent_id, location): + """Returns all training phrases for a specified intent.""" + + from google.cloud import dialogflowcx + + # Create the intents client + intent_client = dialogflowcx.IntentsClient() + + # Specify working intent + intent_name = intent_client.intent_path(project_id, location, agent_id, intent_id) + + # Compose the get-intent request + get_intent_request = dialogflowcx.GetIntentRequest(name=intent_name) + + intent = intent_client.get_intent(get_intent_request) + + # Iterate through the training phrases. + for phrase in intent.training_phrases: + print(phrase) + + return intent.training_phrases + + +# [END dialogflow_list_training_phrases] diff --git a/dialogflow-cx/list_training_phrases_test.py b/dialogflow-cx/list_training_phrases_test.py new file mode 100644 index 000000000000..8527d436f2cc --- /dev/null +++ b/dialogflow-cx/list_training_phrases_test.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +import os + +import google.auth + +import list_training_phrases + + +_, PROJECT_ID = google.auth.default() +INTENT_ID = os.getenv("INTENT_ID") +LOCATION = "global" +AGENT_ID = os.getenv("AGENT_ID") + + +def test_list_training_phrases(capsys): + training_phrases = list_training_phrases.list_training_phrases( + PROJECT_ID, AGENT_ID, INTENT_ID, LOCATION + ) + assert len(training_phrases) >= 15 # Number of training phrases at this point. diff --git a/dialogflow-cx/long_running_operation.py b/dialogflow-cx/long_running_operation.py new file mode 100644 index 000000000000..c1efa5e59086 --- /dev/null +++ b/dialogflow-cx/long_running_operation.py @@ -0,0 +1,43 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + + +""" DialogFlow CX long running operation code snippet """ + +## [START dialogflow_cx_long_running_snippet] +from google.cloud.dialogflowcx_v3.services.agents.client import AgentsClient +from google.cloud.dialogflowcx_v3.types.agent import ExportAgentRequest + + +def export_long_running_agent(project_id, agent_id, location): + + api_endpoint = f"{location}-dialogflow.googleapis.com:443" + client_options = {"api_endpoint": api_endpoint} + + agents_client = AgentsClient(client_options=client_options) + + export_request = ExportAgentRequest() + + export_request.name = ( + f"projects/{project_id}/locations/{location}/agents/{agent_id}" + ) + + # export_agent returns a long running operation + operation = agents_client.export_agent(request=export_request) + + # Returns the result of the operation when the operation is done + return operation.result() + + +## [END dialogflow_cx_long_running_snippet] diff --git a/dialogflow-cx/long_running_operation_test.py b/dialogflow-cx/long_running_operation_test.py new file mode 100644 index 000000000000..287ccaeb1cc5 --- /dev/null +++ b/dialogflow-cx/long_running_operation_test.py @@ -0,0 +1,67 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +import os +import uuid + +from google.cloud.dialogflowcx_v3.services.agents.client import AgentsClient +from google.cloud.dialogflowcx_v3.types.agent import Agent, DeleteAgentRequest + +import pytest + +from long_running_operation import export_long_running_agent + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +pytest.AGENT_ID = None +pytest.PARENT = None + + +def create_agent(project_id, display_name): + parent = "projects/" + project_id + "/locations/global" + + agents_client = AgentsClient() + + agent = Agent( + display_name=display_name, + default_language_code="en", + time_zone="America/Los_Angeles", + ) + + response = agents_client.create_agent(request={"agent": agent, "parent": parent}) + + return response + + +def delete_agent(name): + agents_client = AgentsClient() + agent = DeleteAgentRequest(name=name) + agents_client.delete_agent(request=agent) + + +@pytest.fixture(scope="function", autouse=True) +def setup_teardown(): + agentName = "temp_agent_" + str(uuid.uuid4()) + pytest.PARENT = create_agent(PROJECT_ID, agentName).name + pytest.AGENT_ID = pytest.PARENT.split("/")[5] + print("Created Agent in setUp") + + yield + + delete_agent(pytest.PARENT) + + +def test_export_agent(): + actualResponse = export_long_running_agent(PROJECT_ID, pytest.AGENT_ID, "global") + + assert pytest.AGENT_ID in str(actualResponse) diff --git a/dialogflow-cx/noxfile_config.py b/dialogflow-cx/noxfile_config.py new file mode 100644 index 000000000000..6a9082c602ef --- /dev/null +++ b/dialogflow-cx/noxfile_config.py @@ -0,0 +1,40 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +# Default TEST_CONFIG_OVERRIDE for python repos. + +# You can copy this file into your directory, then it will be inported from +# the noxfile.py. + +# The source of truth: +# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/noxfile_config.py + +TEST_CONFIG_OVERRIDE = { + # You can opt out from the test for specific Python versions. + "ignored_versions": ["2.7"], + # An envvar key for determining the project id to use. Change it + # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a + # build specific Cloud project. You can also use your own string + # to use your own Cloud project. + # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + # A dictionary you want to inject into your test. Don't put any + # secrets here. These values will override predefined values. + "envs": { + "AGENT_ID": "53516802-3e2a-4016-80b6-a3df0d240240", + "AGENT_ID_US_CENTRAL1": "edf8372c-c66a-4984-83ba-b85885e95e2a", + "AUDIO_PATH": "resources/hello.wav", + "INTENT_ID": "164428bd-647a-4e30-ab0f-cc7f3e3b76f9", + }, +} diff --git a/dialogflow-cx/page_management.py b/dialogflow-cx/page_management.py new file mode 100644 index 000000000000..4478502ea305 --- /dev/null +++ b/dialogflow-cx/page_management.py @@ -0,0 +1,80 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +from google.cloud.dialogflowcx_v3 import PagesAsyncClient +from google.cloud.dialogflowcx_v3.types.page import ( + CreatePageRequest, + DeletePageRequest, + ListPagesRequest, + Page, +) + + +# [START dialogflow_cx_create_page] +async def create_page(project_id, agent_id, flow_id, location, displayName): + pages_client = PagesAsyncClient() + + page = Page() + page.display_name = displayName + + request = CreatePageRequest() + request.parent = ( + "projects/" + + project_id + + "/locations/" + + location + + "/agents/" + + agent_id + + "/flows/" + + flow_id + ) + request.page = page + + response = await pages_client.create_page(request=request) + return response + + +# [END dialogflow_cx_create_page] + + +# [START dialogflow_cx_list_page] +async def list_page(project_id, agent_id, flow_id, location): + pages_client = PagesAsyncClient() + + request = ListPagesRequest() + request.parent = ( + f"projects/{project_id}/locations/{location}/agents/{agent_id}/flows/{flow_id}" + ) + + request.language_code = "en" + + response = await pages_client.list_pages(request=request) + return response + + +# [END dialogflow_cx_list_page] + + +# [START dialogflow_cx_delete_page] +async def delete_page(project_id, agent_id, flow_id, page_id, location): + pages_client = PagesAsyncClient() + + request = DeletePageRequest() + request.name = f"projects/{project_id}/locations/{location}/agents/{agent_id}/flows/{flow_id}/pages/{page_id}" + + response = await pages_client.delete_page(request=request) + return response + + +# [END dialogflow_cx_delete_page] diff --git a/dialogflow-cx/page_management_test.py b/dialogflow-cx/page_management_test.py new file mode 100644 index 000000000000..ba9137342008 --- /dev/null +++ b/dialogflow-cx/page_management_test.py @@ -0,0 +1,115 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +import asyncio +from copy import Error +import os +import uuid + +from google.cloud.dialogflowcx_v3.services.agents.client import AgentsClient +from google.cloud.dialogflowcx_v3.types.agent import Agent, DeleteAgentRequest + +import pytest + +from page_management import create_page, delete_page, list_page + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +pytest.AGENT_ID = None +pytest.PARENT = None +pytest.CREATED_PAGE = None +pytest.PAGE_ID = None + + +def delete_agent(name): + agents_client = AgentsClient() + agent = DeleteAgentRequest(name=name) + agents_client.delete_agent(request=agent) + + +@pytest.fixture +def loop(): + loop = asyncio.new_event_loop() + yield loop + loop.close() + + +@pytest.fixture(scope="module", autouse=True) +def setup_teardown(): + loop = asyncio.new_event_loop() + agentName = "temp_agent_" + str(uuid.uuid4()) + + parent = "projects/" + PROJECT_ID + "/locations/global" + + agents_client = AgentsClient() + + agent = Agent( + display_name=agentName, + default_language_code="en", + time_zone="America/Los_Angeles", + ) + + response = agents_client.create_agent(request={"agent": agent, "parent": parent}) + pytest.PARENT = response.name + + pytest.AGENT_ID = pytest.PARENT.split("/")[5] + print("Created Agent in setUp") + + yield + + delete_agent(pytest.PARENT) + loop.close() + + +def test_create_page(loop: asyncio.AbstractEventLoop): + pytest.CREATED_PAGE = f"fake_page_{uuid.uuid4()}" + actualResponse = loop.run_until_complete( + create_page( + PROJECT_ID, + pytest.AGENT_ID, + "00000000-0000-0000-0000-000000000000", + "global", + pytest.CREATED_PAGE, + ) + ) + + pytest.PAGE_ID = actualResponse.name.split("/")[9] + assert actualResponse.display_name == pytest.CREATED_PAGE + + +def test_list_page(loop: asyncio.AbstractEventLoop): + actualResponse = loop.run_until_complete( + list_page( + PROJECT_ID, + pytest.AGENT_ID, + "00000000-0000-0000-0000-000000000000", + "global", + ) + ) + + assert pytest.PAGE_ID in str(actualResponse) + + +def test_delete_page(loop: asyncio.AbstractEventLoop): + try: + loop.run_until_complete( + delete_page( + PROJECT_ID, + pytest.AGENT_ID, + "00000000-0000-0000-0000-000000000000", + pytest.PAGE_ID, + "global", + ) + ) + except Error: + pytest.fail("Unexpected MyError ..") diff --git a/dialogflow-cx/requirements-test.txt b/dialogflow-cx/requirements-test.txt new file mode 100644 index 000000000000..805eb2a9f845 --- /dev/null +++ b/dialogflow-cx/requirements-test.txt @@ -0,0 +1 @@ +pytest==7.2.1 diff --git a/dialogflow-cx/requirements.txt b/dialogflow-cx/requirements.txt new file mode 100644 index 000000000000..7a2cd9f3d4ae --- /dev/null +++ b/dialogflow-cx/requirements.txt @@ -0,0 +1,3 @@ +google-cloud-dialogflow-cx==1.18.0 +Flask==2.2.2 +python-dateutil==2.8.2 diff --git a/dialogflow-cx/resources/hello.wav b/dialogflow-cx/resources/hello.wav new file mode 100644 index 0000000000000000000000000000000000000000..0aadf16c7116b218b7fcb6828286846661dcc301 GIT binary patch literal 29564 zcmcG$1$5j`?fW@ct)nDB&|nHeU`%*>gvli0CirgpoT)h%^PwdG{z z%=_NAZ}$};lqEz|2q9M=GV->uvYc` zM|!J%SJ7F8zlxKp8U8cBf45h`Rzd$7|M#z7-&OopeX4N%%~ut!zyI)`|Gnk^JnO&H`~L^ae>Km)WB;!p z|KGI#-=F`NSO0gZ{qM^1zYF)jo3|>C{OjjmvHl%r{%QT^>OYQykokH1BfEdDe!*2i z{KpahIR^Y|-@i)iKjZopo&IBM)pb>LWc`fgf5(oh796$xL-XHPzxe(|_1{sqih}>x z|L@oTa9KrP750CZPZgHGDf`8970f@!ul`>URaj^wm#WX-*#6eX-<(v*wW{~mr|POI zTU9|-jSc+l-3)-L^de8_yf~acqqJu>9Fz8G` zKN`PCNopY3c^L1=*#VPhc(5fCG)?9c?Q2(Jq|(fBI3Uz}CZCq@Sj zC^Vx1ni17i*`EypXvSal1Q(6>p)mo(jR>gFApr_Bh6j{r792tP5Jeos2ls#Cu_8<+ z#Dfl2pesGPa-kU|ARHuu1Q3CEq7iq#pFDXHJx*8-3lJO*qCgr5Lm1284>Z;Tc?cE& z+fOX^pE!aMOdP_K2$Ikd0fK-AQQ}1qS?~)q{*;^@jn73CkccW7k_I2mXM+wTV*!Gf z0V~XhIcPqBD5?W$gJckoFv$@8ZbY*Q)g!@Z4mHx58CD{>l*1C34L_qkK1c!GKzmRF zNx+2W_znwEKlM{GJS6p0kdAOk5XB|17-4cC9st4|ivD~^0|3!n56uVRd-xc>gQciN zgL+dyHS{e-hX~2ui+H&QPov`*nqL5Fg05gB7z?_9NFX&hkE2l2UVDLh~u)K zb5g2$HXf8%L7$`$q@&QiP>97=-Xt!WZx(;$4L-p&VW5U?l393>qW3oPwJW?Rppw zI)RP|cK~U(0C5_F% zcmUD=0=_}`!az?j3(QC7Xr%K{B*}&dCk6_UEbqe%#8no24zHtYJq$)Vs)MwoM_Qnu z1~dTOk>0AKQB_{UMKoW7^I>;50X~E=U>H~crXx%6pm|QfN62pKBAK^BklFAlg1n0G z79r1wL7XRprl3COF26zgqLkq)!laY*@ApSZbnfC*O(a{*` zJPX;-4`lC22ty($h3jEQ*aj{{boT(;!7eZl3_$ZnB73dUuLDUw57|i>RG`tFkZ&!5 zZDD`73wh!oMC~*LUB$g0S!Eq0=L96F4@kB~q$MA+pK&l9;lB^#Krf`R#>lpKNFLSE z$m8HN*n{NQ2xCd^7d*Mr@y;)!z*a_C6dBVXwF3!F#TPr|-%I{XuHHxiBc6I=y{5QXiKFT8+bU(4?tmfRcR1V~%okykWE6mI}8zRKeH4yJM@D5Bs z`q+kAp2Oe3e()UJ0XvYNJ%wA~TzCXpkW3lG?P6FTX=uSuPrL_T!|LE7kYUrY)mSZT zIXDW7nb*u5I1KoJ20H*UU=vu%WHHr{9BfGLO_A27Avyn!Y|)N<%7--H9(mw9WCdc- z26=Qfuo#WF!Tex$!2_Tv))jLio<_pj@F21Y8_;66kWJQw8EBqr$OmVDVi1oBvERWf z*bVv_8PWp<6OkV@LbLS-!$A{}36~(N-hiUPG++k`tQfUzgk9hqcnnGLI@0zxWKp#d zf7!@4z9No?AJk7%qxJH$f1l!DQGgB>!@_ z6K2!*Fi3#a|Obz0()T{_=xGotYDI0BQO;+W23Qf z@Py$q{h2z*{;nc>K8hj}3)x`?sD{#4JI&mZAvv30X=i91cIh#h?&mfqkGp%6GHCJ>-i5&=1**pW&g=xkyGIk%!+w z*=YjE0}y4G6UaMvLN4<5JILcULL@6D1jWY2Na{kAk<@DHw;Y&Gw&G(e1mAvK`m^{q%uQbCb*Ba!E56) zuJ^DWqQHiL36Ax=0P#O1-#8HW)33k&p|gV39A80n2k&q_zhgZZ?lxF z`dCx=kv>fCVV=OM$a@}1VGzpIyFnV#Qah9bKOx^ZgCctfn2X}C6UjOmlFUw66KVS~ zwgbblDc~{66E{$eQ4EhlDcr%VWFip%2S7_~E!G)}z$#Fry@#^V2b3?xs76=|X~u>M zx79ERd_}s}G3h8;8sQ!ggMGzT;REq~$lJZh2KFCRZ#Pi}+yZaICur6_$PTAtXR-F!C#3%=urZT{3S<*K7Ty63v5m;mcB7bB z3)_po#W!GV@POIP+=DbYiVegXg7?gO`WAhUsRy{&J+K5$V`?*7nNoNkbKo6WH}OW; zd^nG}#spv}7KEw5EJjFg2qe&#m>J*zwjOy)48}t~c@9hk+mY?PV-_(*j2fh48ctsZ2tZN^>ZiqQD~5vKf>jX|_T6us+I*CsE!tgRaXym37Uht zFrGO|=hDrg6Wqe8<0fnm=!SCf8kF-#VY{(ttQ^I=uF%S)Gu3E5-JJeNAA#SnS*)k5 zulO*mF|^QyG);%WQjm{D;5+d**g0?p?qp(+m(@hRiK80*JBrO0k>_q^thAaL0L#D| zyp*+tRUMxTrZM~Jx6D!C$Lio3>?6~f{z^}Smr+!03|KG~W$f|bEcO)Nho1xGOc&-P zL%<%`RO}?OxFlvFJ(}r+v^N`B_CTatGaL#oppn7g5sK(4lm*>z2&x(bfe z5g3EK_XRc*dxGqJ26zLWpy=5HMfpGJLv$H!WpGe}s=O`8U!J2(@D)`RQRqG*0u;lU z$h+ggLME72``?nUsYA4z$wFDSbATWzawgT%zm1Lr$#@|?oHdqplAX$KhL4Bgfu(+5 zpdXwLc3?6#&TYuyu=n7*kpN>Bqv~f4_=ar<9GC&R=w98UGP7L8`<0VwBRz|$&SUgz+6TT4&WxhVXl(NL~CNLZ)9K*;IkTF*O+ku z6*ZPr`L_oe1Rl{nnC0|f`cvREd5h>u=sY!uT;F~FQaTUJ!4jCdfp~uwnNQ06vOo|# zfstS-v)kW<97MHX{O}rH!al~S$?3~E&Lw$ugcF4y1S+14E8?Z{{}TDd>%?mXV(v*e z+P^2Tnu)`9vud$cfV1E-YcaQtpsplB?Bu6&C*uXoB$Vw)xEo4Xkkl7hL^8=SX@40Zn8GrH`^cWna5%WjG@_R>DX=3xf}bhgA~lHL^Y>zD z0W6?pg!n-2SmAZyML{`l9Lvf?`7^z2&k*-!_iN8_-(qTuKhFQbhkF@fFLA~7cfn3T(-tfM57dVdFLM*2&&#bQ;MQ)jQjnC=z5lh^ITr5`$&o^>8Ji=SauT$>(kE~ZJB|GTe}gw>KjVzx{ov>DoAIadvIKvKvSsI0@v7#E zJb8gatiBsmJ+wyX1Vnuadsd*2e z@xz7Rginz5-4}ZJD>&g8JMh>$!ZX25x&_|$)X>1Pz+vjJ_o928tC{Pud$9L5rJ)-z zhw0bUE8?_spLK&N$%I)HHk*CC6S$IG$u72Qmi>TryZN~JPwO{ligzoe3cT=psi~yG z-y9C%X37?7JB7>$dmX+bvSthweKKNw=<3k$u;{4JL_?A-p`PcY+`5TjMy_dWK ziccSg29V2~_wV)cJw=|O)L!N=ig8W-cikhblZ2E25&#=xUU-RgfcvvRfiSA?!tequ!h7%2EtUD zRigHI9okRz@SpWh@YnFMh&vv;_lW-p(-w{i)F88nDc+O*M4Zi?#O=yjLwED;b2hTK zv==+7dA@r|uf(&}@!cF(Syo9|`v|^8zw*t!JRq=k$BJkQ)QX=y8Fk z)L?3{AKksO$8m44DKI49@NM;8B4or%Ph+AjkxMYdabmvbru~~?U1_zVuSE}Z!!2Fh zc_=z|V&?l(hy%{MuGZe|0W~X&e^)j)WJ=8YL^8Q`k|e%)WQXwVP)~ThghT1KYg9{K z99&MzD_iHB`LZ{IlfA4sx+2qB&ohSX2raBntUlm;U`t>CwolwBC?i}DxhQm!daE>5 zu#H_0<1?GdX>Pf*o>S#L<(DuTdNF=IT9i+1YezMek%5l;4)SFB%XEhdRwzT%{#kqlBhezq|{;|G^goscRV~D}TWslJjV)mB*UJ#O-ndd0ETRGEF z-*?RaTOgC1;~D3w=2_^Mvf2vHC`z?A!>`7jO;ROB#K|K+1cd~NL!U(tPTSU?ePecw zTOmCINo9+_fBk&@bN)9vXKSIg;FM4(t`4qPfLycn|sNk_UYl@!7G{+(#EwIP*uB+yzAg zD!)3m`ep=@0&~5LeUi1nt|mKhzREua)sAYApi60Ay?%{%sYMCA$&rXo3b za#X{FJ1LpzmDR7N79?znt{YZAbX3&tq&4Z2Q$L4Dp}6egr{`}bzU}+@eD;9iZk2Pb z3Xh+xM~8zZ%pvlMw;?@;J73)|@^D;5?A8ct&{1g_--g?mhg5HGAEf{FR2;pUPV;Z~ zJ@jbYTRbv~0&4zQQ9IEiUJ)w;JfsIvJ$-F`eW~Yxv4I2RI?quX-!P~oKJP`&_WU$m zwB@^d4fz+T@Om8_>jz7$=OD0%CTWg^wTj6~C_7|TO!t)UwSKF` zOB^JB=lN79|Mu=n!MBX;(A+ioj^e4Np-#Q`LZE=k@^$l?$UbnqXo7ZN#EU2_a&72b zjZDcFFW{BpXP6~abzckLLaGa@dB4$9NxLW0b-{hy7s33-cJto|UkHl1S6GL^1^O>a z@B8BI?0e-qN^T}c5s8k^mA;~nKSpME{n5FotNxVrlly`9F0smOa-MU=c?o!4@LjPb z>`m;Ll#&_~>IiEMPtAzuM3slE4$F&tm$0*1W_)iA7Rc9q%Hl~L!*m`wPCUoxsP z#s0;cPj?5`0wvyH&wZ+dvqC|IUX8Rzb_pLJ#K`Z7hVfRj#{;K-udjfdN`J=s)&#pR~FtZ}7wTCJ98@rlOBhG9=aO_7qsqbXD3 z2dh>DYFAv$5oXr=7M3~m`^O&}iWXHYx7>2B^ZiZ2(qFhmus$mx|e``e1_=DAZ#gq1feL!4fB zJ9jI`1zUgDE4qQ8KzT!3GiaK2llGNHuWBa$C~hWr$KHX>2k$U1YZ`kUnCTb$7Wi8D z@1m@Gh5Lxl<~QWD#bmI6?m?qyM?LVh^_qza_j?D&BCD8JcrUwi*39og1q*c%7Q)$x znC*G#bUQnGBI#bd&$4^kr4jD$8=08OY|VRCsC1x zvm;>v`9>ckVr!ixw3i7jm9BjlYA|&X*F2QA zKhYn3F#JiVH@s2Q$`}})sK{V?n0FV~&&$oZ`D15pM8TF)mcF*xZ$0lE>8@}>huC2t z(DM+%2E}_-O-*mLPW6YvE>lUGiI$=}E*HBKyC2ud+sa?T{fuX#XAqU(0Y06rKY|ZTRZF6ni>}l@V{)4PYVN+>s>3!L9*&JDK**wWK@o3QyQ72KU z2uLcaU&iqaFho~AGMOwV&t6PQIG!`^UMlKZN-&`D9VVlooyB|T0#o3bN$VEmGp(#V?O z=FmnV>A|a2GRazOho`+|vSExqtm0O=ylkdUU72KjZql0^md;kC&2D{Z*AZTN3wx|! zxJWIHmp7Hi$d5>E(!R1=vJtY5(q=NQe3N{Z?1wl-xSjWqQ^?wk+yPiLpg z*4XMZUo<-PophmPhf8`FzbZUXIH8bTJiGLbu7~NcT}VVye+GIo3-A}*BFPZ-+RztK zH)42+?UK%=>`7UbJSYBC3@@rvxFfWBNM!H=l>||}*VE6k+OSk#r{YPuwrsl2r7tuL zHT_}w(~@u5Z(VF{Z$C)%p#NmW@<$2BNj}TM<-_IuWXbZi^7HaFa)Ye5!mdbEj+6J4 zW{c(t#v_|P!kUHInO*)2?_~E_$8&2tbFA^UeyQ$z>9yj+MHz*lFsWcg0a19Mw7dSh zshOiYag=&VUj^l?D}r9~Pufvo@ll)OW+axTh^o=aGm^R`w2C_zH6-jq$eQ30LDf|+ zgblGY-$my#%U%PgqM-a*d2d}vg|cF9WnCj~?qce15}BXcUbscnC&q$b%nqiu&8kKgic9AwuU8ZDY>m~Dq!+11n zHpma?eS^Gz3Qr(7AtCjV+^ zWGVRuQELUISsB_kVqxUg=%+D)xF4~@qZdTRMlfODLN^6nS5H@@N&SMltWf%bSMGW5 zEV3CbV@!`t+fC`_1*UnX4AUv|EK7-XgX5sPJ-I9}8R+rx+| z`v$F1_fSOtq&k*<=uP%iI4K)#nQwY$I%JAA4>yfBJuzJ{Pq%!sj&m$_tI6g81=x=_ z=U(C;5)GE5%W~xV6?IjcRQJ?L8d43^x0P??^Q6y3_xOKthT=M=lHzzTxwhGtTc#No z>E*iY(pSZGi{cAo3;Ptt6;&%{O7hF2DwE9LY{0$Rw=VDj++&~R(~_1-owj4>>F~U$ zn=zKSxcG|LKun*Qp;40}_k>D==V>phfTEMIKj#~K5LiI2bIVW_HpQ~uyu~yT-FF`` zEj7P1=bCF;!yOade(w{C!{lP0IEDPBqJ0vZ%&Qoz>aJd)?xxwO*`Zmf2FTvtNNu8B z{5*C!XipC#S9u0HwpikgTK$&t+>*^jYYH0YPt6nLjn1o{&o4Yte6Fml;*HT@z2fTU z!|4gwagI!wCmpDQL07}3M6Qde8Mis1G+|W2s`x2!-q_>Orz5(ACIx+0FHi)DuXE>M zJLzkb!_(Wj#OxaOlOU(r;?68GoNVJ`r80&9Fr+}rIp&0&THx)r6OVs>G4{-E4T zKX|!{yt?`C3Y5jZvOo2UOrf?=*D~LC`ab@FD-cD>S7;`NL`4K5^)YqgXC>T9_!2LQ zKN0shws|x!@=nOapa&|KY^vx2#}4)egk*?EWP{# zZ8L4MHd;fd8Y;_WDUzFlN!-8i-{4?>TklO5W4mPTX$Y!VQ1)BN$s%vTqkLZe#Qg3B z8HF{9SC?+q#TvR;uGqi2^}bxX8@`Hb5`;?`#bm8I)E+h?@?cbX%-PrjvF&3_QQ46{ zA`XYCf@PYgiZ`+?;wQY<_#-AZu!C$yWH>L`@7SibKG?EROw-H$*5Gf0rDQZBZOkmMJYtm8wixT{&FdOj<5#E~vrnjekMwp?kf#E}s3V zd6(g2g{5pPqFPfJR?t0vNPfS9vcjvyKT0p@A`NvcU+fp%WxkE{T6{lugYca+TvZUH z4(l30MmCBeVsqovah8}fF-b9+Xm9wykSy(F^;U&XoX$&Pk#HV;k`xi&oYx)u?IUat zEQw~HSz=jj&9~;+lAM>^5+AxJriX(P)-vusK}XS_k~y*v#TjL?>VfLIYKH2RGF355 z#*%1+NxZA9+F*WQxi80Uv+uXaj4vzxDr-|xuc&ju$GoGtTXJD;Xnv0ZNztPcfzDrf z(Y(^W+r68t%OtZ(xlKhoWqZ^QgHML>B6~%5iEET_BjJ4f`?zIsvbbt7qR1VgZG&5B z4=CfM%lRzM3+xy(l!_yExr!b4?DcGoElzVY%V*0JYbUG3Uc+f}Kk_D1Npv>IWYy-) z6BtB?P`=4m99M2tMXH;sFRR`udn&fb+Dlx5GVXYm1Ox@1d#}2p>{;echON2|rDa8+ za8&-*+?qeS{-~EbAy1#*y|8gfX*tK>G>@}qy6vQgdCxNQIO1`NtD454mErZG;$w5- zS|+|t$Vk{1pBTR;u6fMs$cV80!NW8WN=gj)$5^R=4A^~BJae2E?VW9BEzQi!O-oGW zrs`&`<%Ct^xbB)l3?lObDPRFh&oT4Qh{j8&$hRnRP&`?sd7=qL_YFMNeZ?)=YH82ZoT0Yr_ zd1g=xVH$fZf2~-jP-s_%CPXZWni4CFADozzP?2yczFGX%xCSwIBE^XE!J1H|4^e&; zQO*P?-y+Xi=WF{6TfSwk`M&9)sfKx#d5WdT+RTyd+Jx2^J_baf3F|uN6u-Ubi=;wE z%6lr0sP?EG>h9`6syWIuMJrhsv4#JU^B$iKH~V{em%19+`Ian0kBa(bOmXX?*9G13 z>*s0n-sjaScvd*9*j$=kQOo$vveq%wbB8oA{a90YW?^&LcU59=tuS!}J1QckSKO+& zqSzKO+L(jUJ)-)B*9jh=J*3*8cr8xi^+b1lmuWd#H4C5>oUeAJeX~Vxu4Z9d>)5*3 z{I+J!SMFrr0je=w53FXr;w}+v6?K>Nmbv8nm1@-r)$ghJeEW|>CaD|l{L|HxfY39+Z*=EM(-UmVMg9TGDj+8Tj}9@q9(Z&wVF*m#5SweWLb z8TrAp&(X!c#rDEl-_q9fyXk=Wi)DgUYI|jmac6p8Qf+A^ILjK$OA+=LQ<4aITVERgYIZR$>#Ff72Y!{JNj&FO8n{sWx}dBd2EB2 zj?poZ?Lrf^T~yQMy(MFKnV5*d{XFuHTW{ZBJ#6`E>2BU?lo~6HH_V$Y-K{%qkDM)u zJhYBh7aCD@QYMgy`BEs0Q+`!RG}AN}HD5JtHM7*Cl)dHKB+G>fyt%A5ko2ecnz`rL z^H4q2rlNV-g5th~&-3Tz-OTNu%gXDNA6?j^_)Mus_sH92~b;RN*am<_8#_ii?Vy?>?};e?it&(%Grn`~@Ad`O zEtY4Ny5<>1k0H}|9NBn+b(Zb2vo(=Ht_~za13s0@2-M<8X^{L6r9xdpvssg&si!@q zxvf5++%ES?7~vw`E0zef53KNwaUZhtEDsFJE4r5*E8bXGnZF=!O>VnfVP3!dF9jcq zrk18vD2#V4I~@l-XQ|Dw4AroW#X}Va&5w}X;f0YiW4^^TNnj=Pi?0)Bj%CNXqi%=y z3E88qqh2bXFT%L3v6YB&5Am0Cux+umpQV#|m{DnXXn1a{FwrKVWiq;tze8*x+Xha< zr>sl7qr%nVVrfIgH&uU4mZr1zhIUBMC9P1iT)9EsTsls)hc}vKg!9qr{dxBkyU|P- z>=jg5Y)P}C-wG!dnDZax&nT!})U{++S#m|BA;Pl2amaI*Tu6uGW!%xCHnO$K_Szbu zk0Z85U5FkLb2WAos!(1;?}+RYF+Tip$U_ZVd00AH{E#2cYQcLd3jaf(hFA$r;{C2DibNF@7x31{Qm#J!1m z7Ck(wLwHEYKFtj!NB%{0kJ}YH8PJl8JUtxqEh~*}4BaYC6>D_c%I)RR71t}8=$lry zH-5CR9b9*kcQAFE8H>N-jOIs+q|!u1e^t6>jW!UpCL}bpZs??tH^H}pYHQ0>ofJjV zCE^=`+T0=d4Q9IE=9Ri#w)y5ahOYXv<+c)Y5x;0tVMw94;8Om?g6N`&B@N4->WIq8 zmSE>^#69u=-5rnR?Gt^GhAJyH2STq$YGNM7dg9I}Tu-zoRK&fEX&4>n*ZRTOC7+B-qI;OimgkdGk?Le>Tc2Ypiip$w8gk~9*f^FOisU_$0N z74MC64Y7IAz1+u&CgpESiV-L43!4;nE1>d^6*Mf`S+b`rw4%LXk7X!Y6>30H^cH*y z@3SaUHcT0+y&IYn**eA?tB8M=@GLQqV2b+`lZH519Bv8juE|y0m2D7hLY$QPlYQ;o z=WNx@-3<TwZLG}+2MZYF55OZ8NZEQ0zMChmK z4x>8fSW#)=_QJ7+TMJ&H6@c3%&&rqT`x{?ddOKy_Nq!IW2fmb>Dw-#ot!fjb3{yu< zid`E&CBd9fknlZWar}bV-qFg)G2ydA#%h-;Ur9d;pL5!P!BiQ_Go{uYCaqzD{%wW4 z;;_zG9;@4=J6y3z-^I|;+}~Esb(+{mHDUh3>ae$S-}0x5=16WxAEPR*SlL;Pw(Dk= zGo|UJBT6Dm29}V@j?}ct_Gt(NHrX^tY&txF-qilBlGN zWJhvHA}?-x6d7R%8xe9@-Cog9+C$WayOw!DRN8k~!i>H3Bg^8;^2!n`M(UIG%`0CR zuA61nUiLGN{hmvdo2ku;;9TK15*&zxSiG+LkncPx#3-&wK zDAs;F1PcNKVJox)`7vAzE@NwP4SI&AV6DV^V#{GPy^(6@8$^`3U%3W4F?)(-rJ+GZ zhq9Z+or^q$?jmk!_40Z84#suXAZL5?s4J8kY9~35{n37x8RyR#&)0I^o zFwe5DcZZOxA%}Ndd|LKV9<8jU&em+w&d|(M?^O*@c11Z;BCO6E&pHl0)C%u956iRK zWALOAWu6o0DwJ62rO7LSFYpo`;1u(dL?6Y~B+bPGga>$g&{}0fv|F(UQxJGbeIO1x zODq!&^K`zFhUo65Q=y^gcxmm5?#4mZ+Kz6nA@1*-Bo=_ zWi!(>o6SMH=M!E0JXQ^{Ts=2f5jHOjgwGC*3)!f>q{&f_R!I~`#4QE6Yz}tJ-^nxG zmTo#`kQmwK=GM>lcFyXqa92IoL-!=_68{)Do3)jPi{HuCD1%gK$_KLH;$nU#XCb=* zdjWd~D*~HBKlP1qU9&*_p|as6kBUE*%q>gOJB@_3t3&Q!+1uGZ*v2|a+`*&?&gEZM zs6t;xPmF(+n4GAOpC3Crs$b;j2xsKzs5#M0WUugdAzW3a@K1W1ZBSWCo-(&pZm)vJ zMT1I%%d6=eXw_)MkzXlUXN-QT^zYFY*t8@pmV53X{K>&MyiA4 z0U?_s1D&bCt{J9dy2!Hcx;eb3|d9ioN!2~L>cv3QxhvvQZR zp}Yj~_l}LD7g{efE|`k;__bx)Q{mn}T&?Y=%@-=0R=m*7)bBH%wu)Upyl<&8YM-x_ z`?9mdx!&EKSmwJypX1(D%m~9{^f3)%pG3U~j|o|(;cA8l502;;^)2Rlv@7~j#8ypb zei{*N;1;IjdUH1APA<$U?WgZwnQpjRiJAQ7!S;nNrS}nimh-18LR3$3RPs#RT@cC^F$c*P#2KQG_o6SCoKIb%nvkcwA3SZ{=bdBiBFi;X zbxVe0qHhmf1Xf~=uyxD>YQCqBv%meFeY)#+Vi)}z@2c`%7&{t|$_T@Q)tXnTBy|(* zq_El12jea#Hb|_V&@Zx$(gu22ghk7~U(Q;aEiPDAe674x-`U_X4Kn>{-DW$7?oR3k z82qaETk!svSxL&o_c8s$bXr`sO14X~U33fWLZY}|@g!y`<#)HXebF-|w&KTS`;05? zeTa+H8~P0V3*Ki2F*P6?YsG5DiRY_CC#3D<71DH3V{UzHe4xKC!QIAL-|2Ck@GK+x zdGC97`m(%2Lg8}TIgahlSkE#aL6_p0yxD@ITszK#Py7vhp{`u(X{3ue4$QX$a0GMZ z8&wA7HCec%rIeD-R^JZ_3hxtbO1xLio8BeuZDM3tOMbcMW%;uFS$RhaAC~OV-LL3p za2gU!rN%vm5vHD|akeIIn*M_qtd5B29eXCWQ)F652jvG@nYf3fv81^)OKOtdlXMk4 zWKHrvbuBXqb%Ek1#n*K0&1YP1eT)3N>2=ID<}TeSAP+Ef6U@gR&W{sk%DO7ID;LW? z3r}zi!0+!$EO%VB_ObT0B{bj| zD0;(v$)tPl*(=TKOg#)X;{@9$-zSzr_NOLN>rq8Y>kA8brNY{Z#vv`@{z`6}KB{_` zbU{j=7+NtLPBNzE-T784Q<2xNG|m9b=dJzC22)F8uxW=S;8^Dy1H1BP$qm6fBX`Hx zqY}dos5ePh3BT|g@gMQ^!Yq+N{HL%try8@6cxh{4^jB=twa||Wj%oDN=OuoB#?qefJ+DMmgSFM_AG<<87htb^$FrThvL~ zQB3mVxFlySufEu+92nX){?D`dIx}$!olkEVb`N(#_Wvh7%tGRmLBJh#0vk+^^hWd}pd-?@!#O53!zd9lq8+MNxZ100!ZgkeSP_O6QM#nO+tx!iEs%e`7B)}SF5LmevYToK%F!7 zy4N0=s8rtx%&X{_vo!Nv7L(JvFsC%n;INwT;JBPl_B-+!xoeD=PtHNLmabCxbMyti&~ zopzmchr0WCUb}0$)}rVA5m+1Ps?h$?FJg_6w?nq5#*63iy0Wg~J@97uV0;Ds8_JQl zS#w}CneV(~*>1wkWwy`mbc)4H1q6Dx;}3Y8-r{dSY0-Yl0nAsdl*8~Bi&DgS!ioH8 zoNc%P_M{t9L%ke?ow}(4N_`4)X z8Y;~bR~PN)MdK;{WiG4Psn5~9tjw^DC*|y(!nu-Nl5LU;l5)v=$!Wq!fpDi6;BBiol%8Im} zh=jomrA;d%pAxJ@crR@WO-pKG{-uc5pn)BrW&9@ z53r9JK@|~{yUcTiEM(;DGyLx2#VGdO7c+tLB5h8RpH1;)T4)&>4>@p{=?Sr;i!6pz;NPD8JMhAEED_8=R%iu@*cj z&omCU0~hY8M;!C;y_p0gy7^8Arn75Ee+wBJwI}vPh~m?)kt z=^#!LoM$fuqv*Gknsj-$dMmvOUu|z4&mHFg`v>dqR+;s!wS(h;E5RE(bGh<8~KT!AlLiWd96r3 zz1;(ygms*GzHy<+V-0g3^_BWh2UY}L(-f>=djuV1EJc4srlgy2BiDp>cV8wF?b8hu zdLp~dtRh-q*`h`AmGaq=aIsXxmb8`qA-}9T8!|TL_hdo!g*8}d^<&c%!hlq-&#`~& zkkv4EYH_Q|@%Dw}0k{P8W!h1Fyh8|~FV?RIhXmP*Ey44``C(~6aY|e?jNP5->lgZW z&~xw>Tp&mgzU13k>C7hY5l182UTd(UiTjSPFdzW6aW8rsQNo1yclxZT&N|{d85oSc z%KDE$0E#2WG`i#GrGX4h=Tc$?EgnU`4n_WJG$-#O|L zwUm5}c7m^j>D)2m{mK{WeX8A(X1od@2-Ni1oIR}djX@@%J>Peb)mXG!)>LK^w&0}V z6M=#KLSod8k2#SXNV8OLU*k))7BMGf!GVa%g}KeX+p?P$l~s(e
00p9oSeNHc0 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 literal 0 HcmV?d00001 diff --git a/dialogflow-cx/streaming_detect_intent_partial_response.py b/dialogflow-cx/streaming_detect_intent_partial_response.py new file mode 100644 index 000000000000..1042b14cdc5f --- /dev/null +++ b/dialogflow-cx/streaming_detect_intent_partial_response.py @@ -0,0 +1,126 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + + +# [START dialogflow_cx_streaming_detect_intent_enable_partial_response] +import uuid + +from google.cloud.dialogflowcx_v3.services.sessions import SessionsClient +from google.cloud.dialogflowcx_v3.types import audio_config +from google.cloud.dialogflowcx_v3.types import InputAudioConfig +from google.cloud.dialogflowcx_v3.types import session + + +def run_sample(): + """ + TODO(developer): Modify these variables before running the sample. + """ + project_id = "YOUR-PROJECT-ID" + location = "YOUR-LOCATION-ID" + agent_id = "YOUR-AGENT-ID" + audio_file_name = "YOUR-AUDIO-FILE-PATH" + encoding = "AUDIO_ENCODING_LINEAR_16" + sample_rate_hertz = 16000 + language_code = "en" + + streaming_detect_intent_partial_response( + project_id, + location, + agent_id, + audio_file_name, + encoding, + sample_rate_hertz, + language_code, + ) + + +def streaming_detect_intent_partial_response( + project_id, + location, + agent_id, + audio_file_name, + encoding, + sample_rate_hertz, + language_code, +): + + client_options = None + if location != "global": + api_endpoint = f"{location}-dialogflow.googleapis.com:443" + print(f"API Endpoint: {api_endpoint}\n") + client_options = {"api_endpoint": api_endpoint} + session_client = SessionsClient(client_options=client_options) + session_id = str(uuid.uuid4()) + + session_path = session_client.session_path( + project=project_id, + location=location, + agent=agent_id, + session=session_id, + ) + + def request_generator(): + audio_encoding = audio_config.AudioEncoding[encoding] + config = InputAudioConfig( + audio_encoding=audio_encoding, + sample_rate_hertz=sample_rate_hertz, + single_utterance=True, + ) + audio_input = session.AudioInput(config=config) + query_input = session.QueryInput(audio=audio_input, language_code=language_code) + yield session.StreamingDetectIntentRequest( + session=session_path, + query_input=query_input, + enable_partial_response=True, + ) + # Here we are reading small chunks of audio data from a local + # audio file. In practice these chunks should come from + # an audio input device. + with open(audio_file_name, "rb") as audio_file: + while True: + chunk = audio_file.read(4096) + if not chunk: + break + # The later requests contains audio data. + audio_input = session.AudioInput(audio=chunk, config=config) + query_input = session.QueryInput( + audio=audio_input, language_code=language_code + ) + yield session.StreamingDetectIntentRequest( + session=session_path, + query_input=query_input, + enable_partial_response=True, + ) + + responses = session_client.streaming_detect_intent(requests=request_generator()) + + print("=" * 20) + for response in responses: + print(f'Intermediate transcript: "{response.recognition_result.transcript}".') + + # Note: The result from the last response is the final transcript along + # with the detected content. + response = response.detect_intent_response + print(f"Query text: {response.query_result.transcript}") + response_messages = [ + " ".join(msg.text.text) for msg in response.query_result.response_messages + ] + print(f"Response text: {' '.join(response_messages)}\n") + + +# [END dialogflow_cx_streaming_detect_intent_enable_partial_response] + + +if __name__ == "__main__": + run_sample() diff --git a/dialogflow-cx/streaming_detect_intent_partial_response_test.py b/dialogflow-cx/streaming_detect_intent_partial_response_test.py new file mode 100644 index 000000000000..e67061991efd --- /dev/null +++ b/dialogflow-cx/streaming_detect_intent_partial_response_test.py @@ -0,0 +1,50 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Tests for detect_intent_texts.""" + +from __future__ import absolute_import + +import os + +from streaming_detect_intent_partial_response import ( + streaming_detect_intent_partial_response, +) + + +DIRNAME = os.path.realpath(os.path.dirname(__file__)) +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +AGENT_ID = os.getenv("AGENT_ID") +AUDIO_PATH = os.getenv("AUDIO_PATH") +AUDIO = f"{DIRNAME}/{AUDIO_PATH}" + + +def test_streaming_detect_intent_partial_response(capsys): + + encoding = "AUDIO_ENCODING_LINEAR_16" + sample_rate_hertz = 24000 + + streaming_detect_intent_partial_response( + PROJECT_ID, + "global", + AGENT_ID, + AUDIO, + encoding, + sample_rate_hertz, + "en-US", + ) + out, _ = capsys.readouterr() + + assert "Intermediate transcript:" in out + assert "Response text: Hi! I'm the virtual flights agent." in out diff --git a/dialogflow-cx/update_intent.py b/dialogflow-cx/update_intent.py new file mode 100644 index 000000000000..ccbf7ee408ae --- /dev/null +++ b/dialogflow-cx/update_intent.py @@ -0,0 +1,34 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +# [START dialogflow_cx_update_intent] +from google.cloud.dialogflowcx_v3.services.intents import IntentsClient +from google.protobuf import field_mask_pb2 + + +def update_intent(project_id, agent_id, intent_id, location, displayName): + + intents_client = IntentsClient() + + intent_name = intents_client.intent_path(project_id, location, agent_id, intent_id) + + intent = intents_client.get_intent(request={"name": intent_name}) + + intent.display_name = displayName + update_mask = field_mask_pb2.FieldMask(paths=["display_name"]) + response = intents_client.update_intent(intent=intent, update_mask=update_mask) + return response + + +# [END dialogflow_cx_update_intent] diff --git a/dialogflow-cx/update_intent_test.py b/dialogflow-cx/update_intent_test.py new file mode 100644 index 000000000000..e3870af36573 --- /dev/null +++ b/dialogflow-cx/update_intent_test.py @@ -0,0 +1,83 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +import os +import uuid + +from google.cloud.dialogflowcx_v3.services.agents.client import AgentsClient +from google.cloud.dialogflowcx_v3.services.intents.client import IntentsClient +from google.cloud.dialogflowcx_v3.types.agent import Agent, DeleteAgentRequest +from google.cloud.dialogflowcx_v3.types.intent import CreateIntentRequest, Intent + +import pytest + +from update_intent import update_intent + +PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT") +pytest.INTENT_ID = None +pytest.AGENT_ID = None +pytest.PARENT = None + + +def create_agent(project_id, display_name): + parent = "projects/" + project_id + "/locations/global" + + agents_client = AgentsClient() + + agent = Agent( + display_name=display_name, + default_language_code="en", + time_zone="America/Los_Angeles", + ) + + response = agents_client.create_agent(request={"agent": agent, "parent": parent}) + + return response + + +def delete_agent(name): + agents_client = AgentsClient() + agent = DeleteAgentRequest(name=name) + agents_client.delete_agent(request=agent) + + +@pytest.fixture(scope="function", autouse=True) +def setup_teardown(): + agentName = "temp_agent_" + str(uuid.uuid4()) + pytest.PARENT = create_agent(PROJECT_ID, agentName).name + pytest.AGENT_ID = pytest.PARENT.split("/")[5] + print("Created Agent in setUp") + intentClient = IntentsClient() + intent = Intent() + + intent.display_name = "fake_intent" + + req = CreateIntentRequest() + req.parent = pytest.PARENT + req.intent = intent + + pytest.INTENT_ID = intentClient.create_intent(request=req).name.split("/")[7] + + yield + + delete_agent(pytest.PARENT) + + +def test_fieldmaskTest(): + fake_intent = f"fake_intent_{uuid.uuid4()}" + actualResponse = update_intent( + PROJECT_ID, pytest.AGENT_ID, pytest.INTENT_ID, "global", fake_intent + ) + + assert actualResponse.display_name == fake_intent diff --git a/dialogflow-cx/webhook.py b/dialogflow-cx/webhook.py new file mode 100644 index 000000000000..bf3e8627cf5c --- /dev/null +++ b/dialogflow-cx/webhook.py @@ -0,0 +1,43 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +""" handle_webhook will return the correct fullfilment response dependong the tag that is sent in the request""" + +# [START dialogflow_cx_webhook] + +# TODO(developer): change entry point to handle_webhook in cloud function + + +def handle_webhook(request): + + req = request.get_json() + + tag = req["fulfillmentInfo"]["tag"] + + if tag == "Default Welcome Intent": + text = "Hello from a GCF Webhook" + elif tag == "get-name": + text = "My name is Flowhook" + else: + text = f"There are no fulfillment responses defined for {tag} tag" + + # You can also use the google.cloud.dialogflowcx_v3.types.WebhookRequest protos instead of manually writing the json object + # Please see https://googleapis.dev/python/dialogflow/latest/dialogflow_v2/types.html?highlight=webhookresponse#google.cloud.dialogflow_v2.types.WebhookResponse for an overview + res = {"fulfillment_response": {"messages": [{"text": {"text": [text]}}]}} + + # Returns json + return res + + +# [END dialogflow_cx_webhook] diff --git a/dialogflow-cx/webhook_configure_session_parameters.py b/dialogflow-cx/webhook_configure_session_parameters.py new file mode 100644 index 000000000000..e29bda3703c5 --- /dev/null +++ b/dialogflow-cx/webhook_configure_session_parameters.py @@ -0,0 +1,39 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + + +""" DialogFlow CX: webhook to configure new session parameters.""" + +# [START dialogflow_cx_v3_webhook_configure_session_parameters] + +# TODO (developer): change entry point to configure_session_params in Cloud Function + + +def configure_session_params(request): + """Webhook to validate or configure new session parameters.""" + + order_number = 123 + + json_response = { + "sessionInfo": { + "parameters": { + "orderNumber": order_number, + }, + }, + } + + return json_response + + +# [END dialogflow_cx_v3_webhook_configure_session_parameters] diff --git a/dialogflow-cx/webhook_configure_session_parameters_test.py b/dialogflow-cx/webhook_configure_session_parameters_test.py new file mode 100644 index 000000000000..2a30ada0f823 --- /dev/null +++ b/dialogflow-cx/webhook_configure_session_parameters_test.py @@ -0,0 +1,36 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Test configure new session parameters""" + +import flask +import pytest + +from webhook_configure_session_parameters import configure_session_params + + +@pytest.fixture(name="app", scope="module") +def fixture_app(): + """Flask fixture to pass a flask.Request to the test function.""" + return flask.Flask(__name__) + + +def test_validate_parameter(app): + """Test for configure new session parameters.""" + + request = {"fulfillmentInfo": {"tag": "configure-session-parameter"}} + + with app.test_request_context(json=request): + res = configure_session_params(flask.request) + assert "orderNumber" in res["sessionInfo"]["parameters"] diff --git a/dialogflow-cx/webhook_log_session_info.py b/dialogflow-cx/webhook_log_session_info.py new file mode 100644 index 000000000000..c6bec04687c4 --- /dev/null +++ b/dialogflow-cx/webhook_log_session_info.py @@ -0,0 +1,46 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. +""" DialogFlow CX: webhook to log session ID for each request.""" + +# [START dialogflow_cx_v3_webhook_log_session_id] + +import re + + +def log_session_id_for_troubleshooting(request): + """Webhook will log session id corresponding to request.""" + + req = request.get_json() + # You can read more about SessionInfo at https://cloud.google.com/dialogflow/cx/docs/reference/rest/v3/SessionInfo + # Use a regex pattern to get the session ID + session_id_regex = r".+\/sessions\/(.+)" + session = req["sessionInfo"]["session"] + regex_match = re.search(session_id_regex, session) + session_id = regex_match.group(1) + + # Instead of printing, use the logging tools available to you + print(f"Debug Node: session ID = {session_id}") + + # Return a generic response + res = { + "fulfillment_response": { + "messages": [{"text": {"text": [f"Request Session ID: {session_id}"]}}] + } + } + + # Returns json + return res + + +# [END dialogflow_cx_v3_webhook_log_session_id] diff --git a/dialogflow-cx/webhook_log_session_info_test.py b/dialogflow-cx/webhook_log_session_info_test.py new file mode 100644 index 000000000000..0d3633126db2 --- /dev/null +++ b/dialogflow-cx/webhook_log_session_info_test.py @@ -0,0 +1,65 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. +"""Test validate form webhook request session ID snippet.""" + +import flask +import pytest + +from webhook_log_session_info import log_session_id_for_troubleshooting + + +@pytest.fixture(name="app", scope="module") +def fixture_app(): + """Flask fixture to pass a flask.Request to the test function""" + return flask.Flask(__name__) + + +@pytest.fixture +def session_id(): + return "d0bdaa0c-0d00-0000-b0eb-b00b0db000b0" + + +@pytest.fixture +def session_prefix(): + agent_id = "000000f0-f000-00b0-0000-af00d0e00000" + return f"projects/test_project/locations/us-central1/agents/{agent_id}" + + +@pytest.fixture +def session(session_prefix, session_id): + """Session string without environment path""" + return f"{session_prefix}/sessions/{session_id}" + + +@pytest.fixture +def env_session(session_prefix, session_id): + """Session string with environment path""" + environment = "0d0000f0-0aac-0d0c-0a00-b00b0000a000" + return f"{session_prefix}/environments/{environment}/sessions/{session_id}" + + +def test_logging_session_id(app, session, session_id): + """Parameterized test for regular session string.""" + request = {"sessionInfo": {"session": session}} + with app.test_request_context(json=request): + res = log_session_id_for_troubleshooting(flask.request) + assert session_id in str(res) + + +def test_logging_session_id_with_env_path(app, env_session, session_id): + """Parameterized test for session string with environment path.""" + request = {"sessionInfo": {"session": env_session}} + with app.test_request_context(json=request): + res = log_session_id_for_troubleshooting(flask.request) + assert session_id in str(res) diff --git a/dialogflow-cx/webhook_prebuilt_telecom.py b/dialogflow-cx/webhook_prebuilt_telecom.py new file mode 100644 index 000000000000..01c9c118e467 --- /dev/null +++ b/dialogflow-cx/webhook_prebuilt_telecom.py @@ -0,0 +1,300 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +""" handle_webhook will return the correct fullfilment response depending on the tag that is sent in the request""" +# [START dialogflow_cx_v3_webhook_prebuilt_telecom] +import copy +import logging + + +def cxPrebuiltAgentsTelecom(request): + logging.info("Cloud Function:" + "Invoked cloud function from Dialogflow") + request_dict = request.get_json() + + # Get the parameters in current page + parameter_info_list = request_dict["pageInfo"]["formInfo"]["parameterInfo"] + parameter_dict = {} + for parameter_info in parameter_info_list: + key = parameter_info["displayName"] + parameter_dict[key] = parameter_info["value"] + + # Get the tag + tag = request_dict["fulfillmentInfo"]["tag"] + + # BEGIN detectCustomerAnomaly + if tag == "detectCustomerAnomaly": + logging.info(tag + " was triggered.") + phone_number = parameter_dict["phone_number"] + bill_state = parameter_dict["bill_state"] + parameters = copy.deepcopy(parameter_dict) + bill_amount = None + product_line = None + anomaly_detect = "false" + purchase = "The Godfather" + purchase_amount = 9.99 + total_bill_amount = 64.33 + bill_without_purchase = 54.34 + updated_parameters = {} + + month_name, first_of_month, last_month_name = get_date_details(bill_state) + logging.info(month_name, first_of_month, last_month_name) + + # Getting the month name based on the bill state - current or previous + # For example, if the current month is December, we get the values as + # December, December 1st, November + + # Only 999999 will have anomaly detection + if str(phone_number) == "999999": + anomaly_detect = "true" + product_line = "phone" + purchase = "device protection" + updated_parameters["product_line"] = product_line + updated_parameters["bill_month"] = month_name + updated_parameters["last_month"] = last_month_name + + # If bill hike amount is given - we just add it to the total bill + if "bill_amount" in parameters: + bill_amount = parameters["bill_amount"] + purchase_amount = bill_amount["amount"] + total_bill_amount = 54.34 + purchase_amount + + # Adding the updated session parameters to the new parameters json + updated_parameters["anomaly_detect"] = anomaly_detect + updated_parameters["purchase"] = purchase + updated_parameters["purchase_amount"] = purchase_amount + updated_parameters["bill_without_purchase"] = bill_without_purchase + updated_parameters["total_bill"] = total_bill_amount + updated_parameters["first_month"] = first_of_month + + res = {"sessionInfo": {"parameters": updated_parameters}} + + # BEGIN validatePhoneLine + elif tag == "validatePhoneLine": + logging.info(tag + " was triggered.") + phone = parameter_dict["phone_number"] + phone_line_verified = "false" + line_index = None + domestic_coverage = "false" + covered_lines = ["5555555555", "5105105100", "1231231234", "9999999999"] + + # Loop over the covered lines array + for index, line in enumerate(covered_lines): + # For each phone line in the array, check if the last 4 digits are + # included in the string. when true, update the line_index variable + if phone == line: + line_index = index + logging.info("This is the index " + str(line_index)) + + # Only 9999999999 will fail + if line_index == 3: + phone_line_verified = "false" + else: + phone_line_verified = "true" + + # Only 1231231234 will have domestic coverage + if line_index == 2: + domestic_coverage = "true" + else: + domestic_coverage = "false" + + res = { + "sessionInfo": { + "parameters": { + "phone_line_verified": phone_line_verified, + "domestic_coverage": domestic_coverage, + } + } + } + + # BEGIN cruisePlanCoverage + elif tag == "cruisePlanCoverage": + logging.info(tag + " was triggered.") + port = parameter_dict["destination"] + port_is_covered = None + # Sample list of covered cruise ports. + covered_ports = [ + "mexico", + "canada", + "anguilla", + ] + + if port.lower() in covered_ports: + port_is_covered = "true" + else: + port_is_covered = "false" + + res = { + "sessionInfo": { + "parameters": { + "port_is_covered": port_is_covered, + } + } + } + + # BEGIN internationalCoverage + elif tag == "internationalCoverage": + logging.info(tag + " was triggered.") + destination = parameter_dict["destination"] + coverage = None + # Sample list of covered international monthly destinations. + covered_by_monthly = [ + "anguilla", + "australia", + "brazil", + "canada", + "chile", + "england", + "france", + "india", + "japan", + "mexico", + "russia", + "singapore", + ] + # Sample list of covered international daily destinations. + covered_by_daily = [ + "anguilla", + "australia", + "brazil", + "canada", + "chile", + "england", + "france", + "india", + "japan", + "mexico", + "singapore", + ] + if ( + destination.lower() in covered_by_monthly + and destination.lower() in covered_by_daily + ): + coverage = "both" + elif ( + destination.lower() in covered_by_monthly + and destination.lower() not in covered_by_daily + ): + coverage = "monthly_only" + elif ( + destination.lower() not in covered_by_monthly + and destination.lower() not in covered_by_daily + ): + coverage = "neither" + else: + # This should never happen, because covered_by_daily is a subset of + # covered_by_monthly + coverage = "daily_only" + + res = { + "sessionInfo": { + "parameters": { + "coverage": coverage, + } + } + } + + # BEGIN cheapestPlan + elif tag == "cheapestPlan": + logging.info(tag + " was triggered.") + trip_duration = parameter_dict["trip_duration"] + monthly_cost = None + daily_cost = None + suggested_plan = None + + # Can only suggest cheapest if both are valid for location. + + # When trip is longer than 30 days, calculate per-month cost (example $ + # amounts). Suggest monthly plan. + if trip_duration > 30: + monthly_cost = (int(trip_duration / 30)) * 70 + daily_cost = trip_duration * 10 + suggested_plan = "monthly" + + # When trip is <= 30 days, but greater than 6 days, calculate monthly + # plan cost and daily plan cost. Suggest monthly b/c it is the cheaper + # one. + elif trip_duration <= 30 and trip_duration > 6: + monthly_cost = 70 + daily_cost = trip_duration * 10 + suggested_plan = "monthly" + + # When trip is <= 6 days, calculate daily plan cost. Suggest daily + # plan. + elif trip_duration <= 6 and trip_duration > 0: + monthly_cost = 70 + daily_cost = trip_duration * 10 + suggested_plan = "daily" + + else: + # This should never happen b/c trip_duration would have to be + # negative + suggested_plan = "null" + + res = { + "sessionInfo": { + "parameters": { + "monthly_cost": monthly_cost, + "daily_cost": daily_cost, + "suggested_plan": suggested_plan, + } + } + } + + # Default Case + else: + res = None + logging.info(f'{"default case called"}') + + # Returns json + return res + + +# Get the current month, first day of current month and last month values +# based on today's date +def get_date_details(bill_state): + from datetime import date + from dateutil.relativedelta import relativedelta + + monthNames = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ] + today = date.today() + # index starts with 0 + first_month_name = monthNames[(today.month - 1)] + firstDay = today.replace(day=1) + first_day_str = str(firstDay) + + last_month_name = monthNames[(today.month - 1) - 1] + last_month_first_day_str = str( + today.replace(day=1, month=(today - relativedelta(months=1)).month) + ) + second_last_month_name = monthNames[(today.month - 1) - 2] + if bill_state == "current": + return [first_month_name, first_day_str, last_month_name] + else: + return [last_month_name, last_month_first_day_str, second_last_month_name] + + +# [END dialogflow_cx_v3_webhook_prebuilt_telecom] diff --git a/dialogflow-cx/webhook_prebuilt_telecom_test.py b/dialogflow-cx/webhook_prebuilt_telecom_test.py new file mode 100644 index 000000000000..a1a655ff9e5f --- /dev/null +++ b/dialogflow-cx/webhook_prebuilt_telecom_test.py @@ -0,0 +1,312 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Test validate form parameter webhook snippet.""" + +import flask +import pytest + +from webhook_prebuilt_telecom import cxPrebuiltAgentsTelecom + + +@pytest.fixture(name="app", scope="module") +def fixture_app(): + """Flask fixture to pass a flask.Request to the test function""" + return flask.Flask(__name__) + + +def test_detect_customeranomaly_current(app): + """Parameterized test for detecting customer anomaly webhook snippet.""" + + from datetime import date + + request = { + "fulfillmentInfo": {"tag": "detectCustomerAnomaly"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [ + {"displayName": "phone_number", "value": 999999}, + {"displayName": "bill_state", "value": "current"}, + {"displayName": "bill_amount", "value": {"amount": 1000}}, + ] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["anomaly_detect"] == "true" + assert res["sessionInfo"]["parameters"]["total_bill"] == 1054.34 + assert res["sessionInfo"]["parameters"]["first_month"] == str( + date.today().replace(day=1) + ) + + +def test_detect_customeranomaly_other(app): + """Parameterized test for detecting customer anomaly webhook snippet.""" + + from datetime import date + + request = { + "fulfillmentInfo": {"tag": "detectCustomerAnomaly"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [ + {"displayName": "phone_number", "value": 8231234789}, + {"displayName": "bill_state", "value": "other situation"}, + {"displayName": "bill_amount", "value": {"amount": 1000}}, + ] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + today = date.today() + assert res["sessionInfo"]["parameters"]["anomaly_detect"] == "false" + assert res["sessionInfo"]["parameters"]["total_bill"] == 1054.34 + assert res["sessionInfo"]["parameters"]["first_month"] == str( + today.replace(day=1, month=1 + ((today.month - 2) % 12)) + ) + + +def test_validate_phoneline(app): + """Parameterized test for validate form parameter webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "validatePhoneLine"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [ + {"displayName": "phone_number", "value": "5105105100"} + ] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["phone_line_verified"] == "true" + + +def test_invalid_phoneline(app): + """Parameterized test for validate form parameter webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "validatePhoneLine"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [ + {"displayName": "phone_number", "value": "9999999999"} + ] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["phone_line_verified"] == "false" + + +def test_invalid_phoneline2(app): + """Parameterized test for validate form parameter webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "validatePhoneLine"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [ + {"displayName": "phone_number", "value": "1231231234"} + ] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["domestic_coverage"] == "true" + + +def test_cruiseplan_coverage(app): + """Parameterized test for cruise plan coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "cruisePlanCoverage"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "destination", "value": "mexico"}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["port_is_covered"] == "true" + + +def test_cruiseplan_notcovered(app): + """Parameterized test for cruise plan coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "cruisePlanCoverage"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "destination", "value": "china"}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["port_is_covered"] == "false" + + +def test_international_coverage1(app): + """Parameterized test for international coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "internationalCoverage"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "destination", "value": "singapore"}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["coverage"] == "both" + + +def test_international_coverage2(app): + """Parameterized test for international coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "internationalCoverage"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "destination", "value": "russia"}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["coverage"] == "monthly_only" + + +def test_international_coverage3(app): + """Parameterized test for international coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "internationalCoverage"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "destination", "value": "china"}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["coverage"] == "neither" + + +def test_cheapest_plan1(app): + """Parameterized test for international coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "cheapestPlan"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "trip_duration", "value": 40}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["monthly_cost"] == 70 + assert res["sessionInfo"]["parameters"]["daily_cost"] == 400 + assert res["sessionInfo"]["parameters"]["suggested_plan"] == "monthly" + + +def test_cheapest_plan2(app): + """Parameterized test for international coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "cheapestPlan"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "trip_duration", "value": 20}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["monthly_cost"] == 70 + assert res["sessionInfo"]["parameters"]["daily_cost"] == 200 + assert res["sessionInfo"]["parameters"]["suggested_plan"] == "monthly" + + +def test_cheapest_plan3(app): + """Parameterized test for international coverage webhook snippet.""" + + request = { + "fulfillmentInfo": {"tag": "cheapestPlan"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "trip_duration", "value": 5}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["monthly_cost"] == 70 + assert res["sessionInfo"]["parameters"]["daily_cost"] == 50 + assert res["sessionInfo"]["parameters"]["suggested_plan"] == "daily" + + +def test_cheapest_plan4(app): + """Invalid Case: This happens only when customer enters a negative number""" + + request = { + "fulfillmentInfo": {"tag": "cheapestPlan"}, + "pageInfo": { + "formInfo": { + "parameterInfo": [{"displayName": "trip_duration", "value": -1}] + } + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res["sessionInfo"]["parameters"]["suggested_plan"] == "null" + + +def test_default_tag(app): + """Default Case.""" + + request = { + "fulfillmentInfo": {"tag": None}, + "pageInfo": { + "formInfo": {"parameterInfo": [{"displayName": None, "value": None}]} + }, + } + + with app.test_request_context(json=request): + res = cxPrebuiltAgentsTelecom(flask.request) + assert res is None diff --git a/dialogflow-cx/webhook_test.py b/dialogflow-cx/webhook_test.py new file mode 100644 index 000000000000..b7948a26fbdd --- /dev/null +++ b/dialogflow-cx/webhook_test.py @@ -0,0 +1,35 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Test webhook""" + +import flask +import pytest + +from webhook import handle_webhook + +# Create a fake 'app' for generating test request contexts. + +request = {"fulfillmentInfo": {"tag": "Default Welcome Intent"}} + + +@pytest.fixture(scope="module") +def app(): + return flask.Flask(__name__) + + +def test_handle_webhook(app): + with app.test_request_context(json=request): + res = handle_webhook(flask.request) + assert "Hello from a GCF Webhook" in str(res) diff --git a/dialogflow-cx/webhook_validate_form_parameter.py b/dialogflow-cx/webhook_validate_form_parameter.py new file mode 100644 index 000000000000..4c073a6347a6 --- /dev/null +++ b/dialogflow-cx/webhook_validate_form_parameter.py @@ -0,0 +1,46 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + + +""" DialogFlow CX: webhook to validate or invalidate form parameters snippet.""" + + +# [START dialogflow_cx_v3_webhook_validate_form_parameter] + + +def validate_parameter(request): + """Webhook will validate or invalidate parameter based on logic configured by the user.""" + return { + "page_info": { + "form_info": { + "parameter_info": [ + { + "displayName": "orderNumber", + "required": True, + "state": "INVALID", + "value": 123, + }, + ], + }, + }, + "sessionInfo": { + "parameters": { + # Set session parameter to None if the form parameter is 'INVALID' and your agent needs to reprompt the user + "orderNumber": None, + }, + }, + } + + +# [END dialogflow_cx_v3_webhook_validate_form_parameter] diff --git a/dialogflow-cx/webhook_validate_form_parameter_test.py b/dialogflow-cx/webhook_validate_form_parameter_test.py new file mode 100644 index 000000000000..0a0b650621f5 --- /dev/null +++ b/dialogflow-cx/webhook_validate_form_parameter_test.py @@ -0,0 +1,36 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +"""Test validate form parameter webhook snippet.""" + +import flask +import pytest + +from webhook_validate_form_parameter import validate_parameter + + +@pytest.fixture(name="app", scope="module") +def fixture_app(): + """Flask fixture to pass a flask.Request to the test function""" + return flask.Flask(__name__) + + +def test_validate_parameter(app): + """Parameterized test for validate form parameter webhook snippet.""" + + request = {"pageInfo": {"formInfo": {"parameterInfo": [{"value": 123}]}}} + + with app.test_request_context(json=request): + res = validate_parameter(flask.request) + assert res["page_info"]["form_info"]["parameter_info"][0]["state"] == "INVALID"