From 624f3051acef67ba5a3fbeb101b179c63aee0497 Mon Sep 17 00:00:00 2001 From: Mark Parker Date: Wed, 20 Sep 2023 14:57:56 +0200 Subject: [PATCH] add examples --- .github/workflows/release.yml | 86 +++++++++++++++++++++++++ .gitignore | 5 ++ pyproject.toml | 26 ++++++++ stark_place/commands/__init__.py | 1 + stark_place/commands/general_manager.py | 5 ++ stark_place/examples/context.py | 41 ++++++++++++ stark_place/examples/custom_run.py | 52 +++++++++++++++ stark_place/examples/hello_world.py | 24 +++++++ 8 files changed, 240 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 pyproject.toml create mode 100644 stark_place/commands/__init__.py create mode 100644 stark_place/commands/general_manager.py create mode 100644 stark_place/examples/context.py create mode 100644 stark_place/examples/custom_run.py create mode 100644 stark_place/examples/hello_world.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5d08fc1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,86 @@ +name: Publish to PyPI and Create Release + +on: + push: + branches: + - master + workflow_dispatch: + +jobs: + publish: + permissions: + id-token: write + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v2 + with: + python-version: '3.10' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install poetry + poetry install + + - name: Version bump + id: version + run: | + if [[ "v$(poetry version --short)" == "$(git describe --tags --always --abbrev=0)" ]]; then + poetry version patch + git add pyproject.toml + git config --global user.email "mark@parker-programs.com" + git config --global user.name "MarkParker5" + git commit -m "Version bump v$(poetry version --short)" + git push + echo Version bumped to $(poetry version --short) + fi + echo Using version $(poetry version --short) + echo VERSION="v$(poetry version --short)" >> $GITHUB_OUTPUT + + - name: Build distribution + id: build + run: | + poetry build + echo FILE="$(ls dist/*.whl -U | head -1)" >> $GITHUB_OUTPUT + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} + + - name: Create tag + uses: rickstaa/action-create-tag@v1 + with: + tag: ${{ steps.version.outputs.VERSION }} + + - name: Generate changelog + id: changelog + run: | + changelog=$(git log --pretty=format:"- %s" "${{ steps.version.outputs.VERSION }}..HEAD") + + - name: Create GitHub Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GIT_TOKEN }} + with: + tag_name: ${{ steps.version.outputs.VERSION }} + release_name: Release ${{ steps.version.outputs.VERSION }} + body: ${{ steps.changelog.outputs.changelog }} + draft: false + prerelease: false + + - name: Upload .whl file + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GIT_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ steps.build.outputs.FILE }} + asset_name: ${{ steps.build.outputs.FILE }} + asset_content_type: application/zip diff --git a/.gitignore b/.gitignore index 68bc17f..0d82a11 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,8 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +.DS_Store +downloads/ +site/ +build/ +test.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..2c36b25 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,26 @@ +[tool.poetry] +name = "stark-place" +version = "1.0.0" +description = "S.T.A.R.K. Platform Library And Community Extensions" +authors = ["Mark Parker "] +license = "CC BY-NC-SA 4.0" +readme = "README.md" +packages = [{include = "stark_place"}] +homepage = "https://pypi.org/project/stark-place/" +repository = "https://github.com/MarkParker5/STARK-PLACE" +documentation = "https://stark.markparker.me" +keywords = ["python", "open-source", "natural-language-processing", "framework", "cross-platform", "natural-language", "voice", "voice-commands", "python3", "voice-recognition", "speech-recognition", "speech-to-text", "community-project", "voice-assistant", "voice-interface", "NLP", "machine-learning", "AI", "text-analysis", "stark", "stark-place", "stark-engine", "mark parker"] + +[tool.poetry.dependencies] +python = "^3.10" + +[tool.poetry.group.dev.dependencies] +pytest = "^7.4.2" +mypy = "^1.5.1" +pytest-asyncio = "^0.21.1" +pytest-trio = "^0.8.0" +pytest-repeat = "^0.9.1" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/stark_place/commands/__init__.py b/stark_place/commands/__init__.py new file mode 100644 index 0000000..1df5659 --- /dev/null +++ b/stark_place/commands/__init__.py @@ -0,0 +1 @@ +from .general_manager import general_manager diff --git a/stark_place/commands/general_manager.py b/stark_place/commands/general_manager.py new file mode 100644 index 0000000..a6cdde9 --- /dev/null +++ b/stark_place/commands/general_manager.py @@ -0,0 +1,5 @@ +from stark import CommandsManager + + +general_manager = CommandsManager() +# general_manager.extend(...) diff --git a/stark_place/examples/context.py b/stark_place/examples/context.py new file mode 100644 index 0000000..f90317a --- /dev/null +++ b/stark_place/examples/context.py @@ -0,0 +1,41 @@ +import anyio +from stark import run, CommandsManager, Response +from stark.core import ResponseHandler +from stark.core.types import Word +from stark.interfaces.vosk import VoskSpeechRecognizer +from stark.interfaces.silero import SileroSpeechSynthesizer + + +VOSK_MODEL_URL = "YOUR_CHOSEN_VOSK_MODEL_URL" +SILERO_MODEL_URL = "YOUR_CHOSEN_SILERO_MODEL_URL" + +recognizer = VoskSpeechRecognizer(model_url=VOSK_MODEL_URL) +synthesizer = SileroSpeechSynthesizer(model_url=SILERO_MODEL_URL) + +manager = CommandsManager() + +@manager.new('hello', hidden=True) +def hello_context(**params): + voice = text = f'Hi, {params["name"]}!' + return Response(text=text, voice=voice) + +@manager.new('bye', hidden=True) +def bye_context(name: Word, handler: ResponseHandler): + handler.pop_context() + return Response(text=f'Bye, {name}!') + +@manager.new('hello $name:Word') +def hello(name: Word): + text = voice = f'Hello, {name}!' + return Response( + text=text, + voice=voice, + commands=[hello_context, bye_context], + parameters={'name': name} + ) + +async def main(): + await run(manager, recognizer, synthesizer) + +if __name__ == '__main__': + anyio.run(main) diff --git a/stark_place/examples/custom_run.py b/stark_place/examples/custom_run.py new file mode 100644 index 0000000..d14e197 --- /dev/null +++ b/stark_place/examples/custom_run.py @@ -0,0 +1,52 @@ +import asyncer +from stark import CommandsContext, CommandsManager, Response +from stark.interfaces.protocols import SpeechRecognizer, SpeechSynthesizer +from stark.interfaces.vosk import VoskSpeechRecognizer +from stark.interfaces.silero import SileroSpeechSynthesizer +from stark.voice_assistant import VoiceAssistant +from stark.general.blockage_detector import BlockageDetector + + +VOSK_MODEL_URL = "YOUR_CHOSEN_VOSK_MODEL_URL" +SILERO_MODEL_URL = "YOUR_CHOSEN_SILERO_MODEL_URL" + +recognizer = VoskSpeechRecognizer(model_url=VOSK_MODEL_URL) +synthesizer = SileroSpeechSynthesizer(model_url=SILERO_MODEL_URL) + +manager = CommandsManager() + +@manager.new('hello') +async def hello_command() -> Response: + text = voice = 'Hello, world!' + return Response(text=text, voice=voice) + +async def run( + manager: CommandsManager, + speech_recognizer: SpeechRecognizer, + speech_synthesizer: SpeechSynthesizer +): + async with asyncer.create_task_group() as main_task_group: + context = CommandsContext( + task_group = main_task_group, + commands_manager = manager + ) + voice_assistant = VoiceAssistant( + speech_recognizer = speech_recognizer, + speech_synthesizer = speech_synthesizer, + commands_context = context + ) + speech_recognizer.delegate = voice_assistant + context.delegate = voice_assistant + # context.fallback_command = fallback_command + + main_task_group.soonify(speech_recognizer.start_listening)() + main_task_group.soonify(context.handle_responses)() + + detector = BlockageDetector() + main_task_group.soonify(detector.monitor)() + +async def main(): + await run(manager, recognizer, synthesizer) + +if __name__ == '__main__': + asyncer.runnify(main)() # or anyio.run(main), same thing diff --git a/stark_place/examples/hello_world.py b/stark_place/examples/hello_world.py new file mode 100644 index 0000000..2de0558 --- /dev/null +++ b/stark_place/examples/hello_world.py @@ -0,0 +1,24 @@ +import anyio +from stark import run, CommandsManager, Response +from stark.interfaces.vosk import VoskSpeechRecognizer +from stark.interfaces.silero import SileroSpeechSynthesizer + + +VOSK_MODEL_URL = "YOUR_CHOSEN_VOSK_MODEL_URL" +SILERO_MODEL_URL = "YOUR_CHOSEN_SILERO_MODEL_URL" + +recognizer = VoskSpeechRecognizer(model_url=VOSK_MODEL_URL) +synthesizer = SileroSpeechSynthesizer(model_url=SILERO_MODEL_URL) + +manager = CommandsManager() + +@manager.new('hello') +async def hello_command() -> Response: + text = voice = 'Hello, world!' + return Response(text=text, voice=voice) + +async def main(): + await run(manager, recognizer, synthesizer) + +if __name__ == '__main__': + anyio.run(main)