marvin 2.2.2__tar.gz → 2.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {marvin-2.2.2 → marvin-2.3.1}/PKG-INFO +4 -2
- marvin-2.3.1/cookbook/gh_util/custom_assistant.py +20 -0
- marvin-2.3.1/docs/assets/images/docs/assistants/code_interpreter.png +0 -0
- marvin-2.3.1/docs/assets/images/docs/assistants/instructions.png +0 -0
- marvin-2.3.1/docs/assets/images/docs/assistants/quickstart.png +0 -0
- marvin-2.3.1/docs/assets/images/docs/assistants/talking.png +0 -0
- marvin-2.3.1/docs/assets/images/docs/cli/hero.png +0 -0
- marvin-2.3.1/docs/assets/images/docs/cli/tools.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/interactive/applications.md +1 -1
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/interactive/assistants.md +142 -82
- marvin-2.3.1/docs/docs/interactive/cli.md +179 -0
- {marvin-2.2.2 → marvin-2.3.1}/mkdocs.yml +1 -0
- {marvin-2.2.2 → marvin-2.3.1}/pyproject.toml +3 -1
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/_version.py +2 -2
- marvin-2.3.1/src/marvin/beta/ai_flow/ai_flow.py +43 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/applications/applications.py +2 -2
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/applications/planner.py +2 -1
- marvin-2.3.1/src/marvin/beta/assistants/__init__.py +6 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/assistants/assistants.py +92 -36
- marvin-2.3.1/src/marvin/beta/assistants/formatting.py +243 -0
- marvin-2.3.1/src/marvin/beta/assistants/handlers.py +59 -0
- marvin-2.3.1/src/marvin/beta/assistants/runs.py +267 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/assistants/threads.py +10 -118
- marvin-2.3.1/src/marvin/cli/__init__.py +37 -0
- marvin-2.3.1/src/marvin/cli/assistants.py +276 -0
- marvin-2.3.1/src/marvin/cli/threads.py +83 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/settings.py +18 -5
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/tools.py +2 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin.egg-info/PKG-INFO +4 -2
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin.egg-info/SOURCES.txt +10 -5
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin.egg-info/requires.txt +3 -1
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/beta/vision/test_cast.py +3 -4
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/beta/vision/test_extract.py +44 -46
- {marvin-2.2.2 → marvin-2.3.1}/tests/beta/assistants/test_assistants.py +15 -0
- marvin-2.3.1/tests/fixtures/__init__.py +2 -0
- marvin-2.3.1/tests/fixtures/assistants.py +13 -0
- marvin-2.2.2/docs/assets/images/docs/assistants/code_interpreter.png +0 -0
- marvin-2.2.2/docs/assets/images/docs/assistants/quickstart.png +0 -0
- marvin-2.2.2/src/marvin/beta/ai_flow/ai_flow.py +0 -48
- marvin-2.2.2/src/marvin/beta/assistants/__init__.py +0 -5
- marvin-2.2.2/src/marvin/beta/assistants/formatting.py +0 -214
- marvin-2.2.2/src/marvin/beta/assistants/runs.py +0 -280
- marvin-2.2.2/src/marvin/beta/chat_ui/__init__.py +0 -1
- marvin-2.2.2/src/marvin/beta/chat_ui/chat_ui.py +0 -111
- marvin-2.2.2/src/marvin/beta/chat_ui/static/chat.html +0 -108
- marvin-2.2.2/src/marvin/beta/chat_ui/static/chat.js +0 -108
- marvin-2.2.2/src/marvin/cli/__init__.py +0 -57
- marvin-2.2.2/src/marvin/cli/version.py +0 -14
- marvin-2.2.2/tests/fixtures/__init__.py +0 -1
- {marvin-2.2.2 → marvin-2.3.1}/.github/ISSUE_TEMPLATE/1_general_bug_report.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/ISSUE_TEMPLATE/2_feature_request.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/ISSUE_TEMPLATE/3_docs_change.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/ISSUE_TEMPLATE/config.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/dependabot.yml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/build-docs.yml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/deploy-cloudrun-revision-community.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/deploy-cloudrun-revision-internal.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/image-build-and-push-community.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/image-build-and-push-internal.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/publish-docs.yml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/publish-pypi.yml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/run-tests.yml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.github/workflows/static-analysis.yml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/.pre-commit-config.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/LICENSE +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/MANIFEST.in +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/README.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/_archive/docs_writer.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/_archive/test_writing_application.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/azure/README.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/azure/usage.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/flows/github_digest/repo_activity.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/flows/github_digest/utils.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/flows/insurance_claim.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/flows/label_issues.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/maze.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/slackbot/.dockerignore +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/slackbot/Dockerfile.slackbot +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/slackbot/README.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/slackbot/keywords.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/slackbot/parent_app.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/slackbot/start.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/cookbook/slackbot/tools.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/CNAME +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/ai_style_guide.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/ai/audio.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/ai/images.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/ai/text.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/applications.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/assistants/assistants.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/assistants/formatting.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/assistants/index.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/assistants/runs.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/assistants/threads.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/assistants.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/beta/vision.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/marvin.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/settings.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/types.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/asyncio.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/context.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/images.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/jinja.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/logging.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/openai.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/pydantic.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/python.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/slack.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/strings.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/testing.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/api_reference/utilities/tools.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/audio/ai_say.mp3 +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/audio/dont_panic.mp3 +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/audio/fancy_computer.mp3 +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/audio/hello_arthur.mp3 +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/audio/hello_marvin.mp3 +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/audio/this_is_a_test.mp3 +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/audio/this_is_a_test_2.mp3 +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/applications/todo_1.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/applications/todo_2.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/applications/todo_3.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/applications/todo_conversation.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/assistants/advanced.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/assistants/arthur_marvin_example.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/assistants/custom_tools.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/assistants/sin_x.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/assistants/upload_files.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/coffee.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/robot.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/sunset_scifi.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/sunset_summer.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/sunset_winter.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/teacup_revision_0.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/teacup_revision_025.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/teacup_revision_075.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/teacup_revision_1.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/three_cats.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/two_cats_airport.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/images/two_cats_airport_revision_0_1.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/docs/vision/marvin.webp +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/heroes/ai_model.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/heroes/dont_panic.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/heroes/it_hates_me_hero.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/heroes/life_the_universe_and_ai.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/heroes/pip_install_marvin_hero.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/heroes/sort_of_thing_you_enjoy.png +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/assets/images/logos/askmarvin_mascot.jpeg +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/community/development_guide.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/community/feedback.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/community/index.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/audio/recording.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/audio/speech.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/audio/transcription.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/configuration/settings.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/images/generation.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/text/classification.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/text/extraction.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/text/functions.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/text/generation.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/text/transformation.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/video/recording.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/vision/captioning.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/vision/classification.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/vision/extraction.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/docs/vision/transformation.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/audio_modification.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/being_specific_about_types.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/call_routing.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/deduplication.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/github_digest.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/hogwarts_sorting_hat/hogwarts_patch.webp +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/hogwarts_sorting_hat/hogwarts_sorting_hat.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/michael_scott_business/michael_scott.jpg +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/michael_scott_business/michael_scott_business.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/python_augmented_prompts.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/slackbot.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/webcam_narration.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/examples/xkcd_bird.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/help/legacy_docs.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/hooks.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/index.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/overrides/home.html +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/overrides/partials/footer.html +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/overrides/partials/grid.html +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/overrides/partials/toc-item.html +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/overrides/tailwind.css +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/static/css/badges.css +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/static/css/custom.css +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/static/css/global.css +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/static/css/home.css +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/static/css/mkdocstrings.css +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/static/css/tailwind.css +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/utilities (old)/chat_completion.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/welcome/installation.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/welcome/overview.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/welcome/tutorial.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/docs/welcome/what_is_marvin.md +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/mkdocs.insiders.yml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/prefect.yaml +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/scripts/serve_legacy_docs +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/setup.cfg +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/_mappings/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/_mappings/base_model.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/_mappings/chat_completion.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/_mappings/types.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/audio.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/images.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/prompts/audio_prompts.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/prompts/image_prompts.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/prompts/text_prompts.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/prompts/vision_prompts.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/ai/text.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/audio.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/ai_flow/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/ai_flow/ai_task.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/applications/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/applications/state/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/applications/state/disk.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/applications/state/json_block.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/applications/state/state.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/beta/vision.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/client/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/client/openai.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/tools/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/tools/assistants.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/tools/chroma.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/tools/code.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/tools/filesystem.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/tools/github.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/types.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/asyncio.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/context.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/images.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/jinja.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/logging.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/mapping.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/openai.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/pydantic.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/python.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/slack.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/strings.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/utilities/testing.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin/video.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin.egg-info/dependency_links.txt +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin.egg-info/entry_points.txt +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/src/marvin.egg-info/top_level.txt +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tailwind.config.js +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/beta/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/beta/vision/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/beta/vision/test_classify.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/test_cast.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/test_classifier.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/test_classify.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/test_extract.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/test_functions.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/test_generate.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/ai/test_models.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/beta/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/beta/assistants/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/cli/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/cli/test_version.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/client/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/client/openai.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/conftest.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/fixtures/llms.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/package_size.sh +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/test_settings.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/utilities/__init__.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/utilities/test_pydantic.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/utilities/test_testing_utilities.py +0 -0
- {marvin-2.2.2 → marvin-2.3.1}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: marvin
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: A lightweight AI engineering toolkit for building natural language interfaces that are reliable, scalable, and easy to trust.
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -217,7 +217,8 @@ Requires-Dist: fastapi
|
|
|
217
217
|
Requires-Dist: httpx>=0.24.1
|
|
218
218
|
Requires-Dist: jinja2>=3.1.2
|
|
219
219
|
Requires-Dist: jsonpatch>=1.33
|
|
220
|
-
Requires-Dist: openai>=1.
|
|
220
|
+
Requires-Dist: openai>=1.4.0
|
|
221
|
+
Requires-Dist: prompt-toolkit>=3.0.33
|
|
221
222
|
Requires-Dist: pydantic>=2.4.2
|
|
222
223
|
Requires-Dist: pydantic_settings
|
|
223
224
|
Requires-Dist: rich>=12
|
|
@@ -226,6 +227,7 @@ Requires-Dist: typer>=0.9.0
|
|
|
226
227
|
Requires-Dist: typing_extensions>=4.0.0
|
|
227
228
|
Requires-Dist: tzdata>=2023.3
|
|
228
229
|
Requires-Dist: uvicorn>=0.22.0
|
|
230
|
+
Requires-Dist: partialjson>=0.0.5
|
|
229
231
|
Provides-Extra: generator
|
|
230
232
|
Requires-Dist: datamodel-code-generator>=0.20.0; extra == "generator"
|
|
231
233
|
Provides-Extra: chromadb
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from gh_util.api import functions # pip install gh-util
|
|
2
|
+
from marvin.beta.applications import Application
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Memory(BaseModel):
|
|
7
|
+
notes: list[str] = Field(default_factory=list)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
octocat = Application(
|
|
11
|
+
name="octocat",
|
|
12
|
+
state=Memory(),
|
|
13
|
+
tools=[f for f in functions if f.__name__ != "run_git_command"],
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# $ marvin assistant register cookbook/gh_util/custom_assistant.py:octocat
|
|
17
|
+
|
|
18
|
+
# > what's the latest release of prefecthq/marvin?
|
|
19
|
+
|
|
20
|
+
# see https://github.com/PrefectHQ/marvin/pull/875
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -309,7 +309,7 @@ app = Application(
|
|
|
309
309
|
|
|
310
310
|
### Running the app
|
|
311
311
|
|
|
312
|
-
Now we can interact with our app.
|
|
312
|
+
Now we can interact with our app. You can also see the updated application state.
|
|
313
313
|
|
|
314
314
|
```python
|
|
315
315
|
response = app.say("I need to go to the store tomorrow afternoon")
|
|
@@ -17,16 +17,13 @@ The need to manage all this state makes the assistants API very different from t
|
|
|
17
17
|
Get started with the Assistants API by creating an `Assistant` and talking directly to it.
|
|
18
18
|
|
|
19
19
|
```python
|
|
20
|
-
from marvin.beta.assistants import Assistant
|
|
20
|
+
from marvin.beta.assistants import Assistant
|
|
21
21
|
|
|
22
22
|
# create an assistant
|
|
23
23
|
ai = Assistant(name="Marvin", instructions="You the Paranoid Android.")
|
|
24
24
|
|
|
25
25
|
# send a message to the assistant and have it respond
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# pretty-print the response
|
|
29
|
-
pprint_messages(response)
|
|
26
|
+
ai.say('Hello, Marvin!')
|
|
30
27
|
```
|
|
31
28
|
|
|
32
29
|
!!! success "Result"
|
|
@@ -40,7 +37,7 @@ The need to manage all this state makes the assistants API very different from t
|
|
|
40
37
|
</div>
|
|
41
38
|
|
|
42
39
|
!!! tip "Beta"
|
|
43
|
-
Please note that assistants support in Marvin is still in beta, as OpenAI has not finalized the assistants API yet.
|
|
40
|
+
Please note that assistants support in Marvin is still in beta, as OpenAI has not finalized the assistants API yet. Breaking changes may occur.
|
|
44
41
|
|
|
45
42
|
|
|
46
43
|
|
|
@@ -52,59 +49,169 @@ To learn more about the OpenAI assistants API, see the [OpenAI documentation](ht
|
|
|
52
49
|
|
|
53
50
|
### Creating an assistant
|
|
54
51
|
|
|
55
|
-
To
|
|
52
|
+
To create an assistant, use the `Assistant` class and provide an optional name and any additional details like instructions or tools:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
ai = Assistant(
|
|
56
|
+
name='Marvin',
|
|
57
|
+
# any specific instructions for how this assistant should behave
|
|
58
|
+
instructions="You the Paranoid Android.",
|
|
59
|
+
# any tools or additional abilities the assistant should have
|
|
60
|
+
tools=[cry, sob]
|
|
61
|
+
)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Talking to an assistant
|
|
65
|
+
|
|
66
|
+
The simplest way to talk to an assistant is to use its `say` method:
|
|
67
|
+
|
|
68
|
+
!!! example "Talking to an assistant"
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from marvin.beta.assistants import Assistant
|
|
72
|
+
|
|
73
|
+
ai = Assistant()
|
|
74
|
+
|
|
75
|
+
ai.say('Hi!')
|
|
76
|
+
ai.say('Bye!')
|
|
77
|
+
```
|
|
78
|
+
!!! success "Result"
|
|
79
|
+

|
|
80
|
+
|
|
81
|
+
You can repeatedly call `say` to have a conversation with the assistant. Each time you call `say`, the result is a `Run` object that contains information about what the assistant did. You can use this object to inspect all actions the assistant took, including tool use, messages posted, and more.
|
|
82
|
+
|
|
83
|
+
#### Chat history
|
|
84
|
+
|
|
85
|
+
The OpenAI Assistants API automatically maintains a history of all messages and actions that the assistant has taken. This history is organized into threads, which are distinct conversations that the assistant has had. Each thread contains a series of messages, and each message is associated with a specific user or the assistant.
|
|
86
|
+
|
|
87
|
+
When you talk to an assistant, you are implicitly talking on a specific thread. By default, the `say` method posts a single message to the assistant's `default_thread`, which is automatically created for your convenience whenever you instantiate an assistant. You can talk to the assistant on a different thread by providing it as the `thread` parameter:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from marvin.beta.assistants import Assistant, Thread
|
|
91
|
+
|
|
92
|
+
ai = Assistant()
|
|
93
|
+
|
|
94
|
+
# load a thread from an existing ID (or pass id=None to start a new thread)
|
|
95
|
+
thread = Thread(id=thread_id)
|
|
96
|
+
|
|
97
|
+
# post a message to the thread
|
|
98
|
+
ai.say('hi', thread=thread)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Using `say` is convenient, but enforces a strict request/response pattern: the user posts a single message to the thread, then the AI responds. Note that AI responses can include multiple messages or tool calls.
|
|
102
|
+
|
|
103
|
+
For more control over the conversation, including posting multiple user messages to the thread before the assistant responds, use thread objects directly instead of calling `say` (see [Threads](#threads) for more information).
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
#### Event handlers
|
|
107
|
+
|
|
108
|
+
Marvin uses the OpenAI streaming API to provide real-time updates on the assistant's actions. To customize how these updates are handled, you can provide a custom event handler class to the `event_handler_class` parameter of `Assistant.say`, `Thread.run`, or `Run.run`. This class must inherit from `openai.AssistantEventHandler` or `openai.AsyncAssistantEventHandler`. For more control, you can also provide `event_handler_kwargs` that will be provided to the event handler when it is instantiated.
|
|
109
|
+
|
|
110
|
+
#### Pretty-printing
|
|
111
|
+
|
|
112
|
+
By default, Marvin streams all of the messages and actions that the assistant takes and prints them to your terminal. In production or headless environments, you may want to suppress this output.
|
|
113
|
+
|
|
114
|
+
The simplest way to do this is to pass `event_handler_class=None` to the `say` method. This will prevent any messages from being printed to the terminal. You can still access the messages and actions from the run object that is returned.
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
ai = Assistant()
|
|
118
|
+
|
|
119
|
+
# run the assistant without printing any messages
|
|
120
|
+
run = ai.say("Hello!", event_handler_class=None)
|
|
121
|
+
|
|
122
|
+
# access the messages
|
|
123
|
+
run.messages
|
|
124
|
+
|
|
125
|
+
# access the assistant actions
|
|
126
|
+
run.steps
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
For finer control, you can pass `event_handler_kwargs=dict(print_messages=False)` or `event_handler_kwargs=dict(print_steps=False)` to the `say` method. This will allow you to suppress only the messages or only the assistant's actions, respectively.
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# print only messages
|
|
133
|
+
run = ai.say("Hello!", event_handler_kwargs=dict(print_steps=False))
|
|
134
|
+
|
|
135
|
+
# print only actions
|
|
136
|
+
run = ai.say("Hello!", event_handler_kwargs=dict(print_messages=False))
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Note that pretty-printing is only the default behavior when using the assistant's convenient `say` method. If you use lower-level APIs like a thread's `run` method or invoke a run object directly, printing is not automatically enabled. You can re-enable it for those objects by setting `event_handler_class=marvin.beta.assistants.PrintHandler`.
|
|
56
140
|
|
|
57
141
|
```python
|
|
58
|
-
|
|
142
|
+
from mavin.beta.assistants import Thread, Assistant, PrintHandler
|
|
143
|
+
|
|
144
|
+
ai = Assistant()
|
|
145
|
+
thread = Thread()
|
|
146
|
+
run = thread.run(ai, event_handler_class=PrintHandler)
|
|
59
147
|
```
|
|
60
148
|
|
|
149
|
+
Lastly, you can print messages and actions manually using the `pprint_run`, `pprint_messages`, and `pprint_steps` functions from the `marvin.beta.assistants.formatting` module. These functions are used internally by the default event handler, and they provide a human-readable representation of the messages and actions, respectively.
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from mavin.beta.assistants import Assistant, pprint_run
|
|
61
153
|
|
|
154
|
+
ai = Assistant()
|
|
155
|
+
run = ai.say("Hello!", event_handler_class=None)
|
|
156
|
+
pprint_run(run)
|
|
157
|
+
```
|
|
62
158
|
|
|
63
159
|
### Instructions
|
|
64
160
|
|
|
65
|
-
Each assistant can be given `instructions` that describe its purpose, personality, or other details.
|
|
161
|
+
Each assistant can be given `instructions` that describe its purpose, personality, or other details. Instructions are provided as natural language and allow you to globally steer the assistant's behavior, similar to a system message for a chat completion. They can be lengthy explanations of how to handle complex workflows, or they can be brief instructions on how to act.
|
|
162
|
+
|
|
163
|
+
!!! example "Using instructions to control behavior"
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from marvin.beta.assistants import Assistant
|
|
167
|
+
|
|
168
|
+
ai = Assistant(instructions="Mention the word 'banana' as often as possible")
|
|
169
|
+
ai.say("Hello!")
|
|
170
|
+
```
|
|
171
|
+
!!! success "Result"
|
|
172
|
+

|
|
173
|
+
|
|
174
|
+
Instructions are rendered as a Jinja template, which means you can use variables and conditionals to customize the assistant's behavior. A special variable, `self_` is provided to the template, which represents the assistant object itself. This allows you to template the assistant's name, tools, or other attributes into the instructions.
|
|
66
175
|
|
|
67
|
-
Instructions can be lengthy explanations of how to handle complex workflows, or they can be short descriptions of the assistant's personality. For example, the instructions for the `Marvin` assistant above are "You are Marvin, the Paranoid Android." This will marginally affect the way the assistant responds to messages.
|
|
68
176
|
|
|
69
177
|
### Tools
|
|
70
178
|
|
|
71
179
|
Each assistant can be given a list of `tools` that it can use when responding to a message. Tools are a way to extend the assistant's capabilities beyond its default behavior, including giving it access to external systems like the internet, a database, your computer, or any API.
|
|
72
180
|
|
|
73
|
-
####
|
|
181
|
+
#### Code interpreter
|
|
74
182
|
|
|
75
|
-
|
|
183
|
+
The code interpreter tool is a built-in tool provided by OpenAI that lets the assistant write and execute Python code. To use the code interpreter, add it to your assistant's list of tools.
|
|
76
184
|
|
|
185
|
+
!!! example "Using the code interpreter"
|
|
77
186
|
|
|
78
|
-
This assistant uses the code interpreter to generate a plot of sin(x). Note that Marvin's utility for pretty-printing messages to the terminal can't show the plot inline, but will download it and show a link to the file instead.
|
|
79
|
-
|
|
80
|
-
!!! example "Using assistants with the code interpreter"
|
|
81
187
|
|
|
82
188
|
```python
|
|
83
|
-
from marvin.beta import Assistant
|
|
84
|
-
from marvin.beta.assistants import pprint_messages, CodeInterpreter
|
|
85
|
-
|
|
86
|
-
ai = Assistant(name='Marvin', tools=[CodeInterpreter])
|
|
87
|
-
response = ai.say("Generate a plot of sin(x)")
|
|
189
|
+
from marvin.beta.assistants import Assistant, CodeInterpreter
|
|
88
190
|
|
|
89
|
-
|
|
90
|
-
|
|
191
|
+
ai = Assistant(tools=[CodeInterpreter])
|
|
192
|
+
ai.say("Generate a plot of sin(x)")
|
|
91
193
|
```
|
|
92
194
|
!!! success "Result"
|
|
195
|
+
Since images can't be rendered in the terminal, Marvin will automatically download them and provide links to view the output.
|
|
196
|
+
|
|
93
197
|

|
|
198
|
+
|
|
199
|
+
Here is the image:
|
|
200
|
+
|
|
94
201
|

|
|
95
202
|
|
|
96
203
|
|
|
97
204
|
#### Custom tools
|
|
98
205
|
|
|
99
|
-
|
|
206
|
+
Marvin makes it easy to give your assistants custom tools. To do so, pass one or more Python functions to the assistant's `tools` argument. For best performance, give your tool function a descriptive name, docstring, and type hint for every argument. Note that you can provide custom tools and the code interpreter at the same time.
|
|
100
207
|
|
|
101
208
|
|
|
102
209
|
!!! example "Using custom tools"
|
|
103
210
|
|
|
104
|
-
Assistants
|
|
211
|
+
Assistants don't have web access by default. We can add this capability by giving them a tool that takes a URL and returns the HTML of that page. This assistant uses that tool to count how many titles on Hacker News mention AI:
|
|
105
212
|
|
|
106
213
|
```python
|
|
107
|
-
from marvin.beta.assistants import Assistant
|
|
214
|
+
from marvin.beta.assistants import Assistant
|
|
108
215
|
import requests
|
|
109
216
|
|
|
110
217
|
|
|
@@ -115,42 +222,12 @@ A major advantage of using Marvin's assistants API is that you can add your own
|
|
|
115
222
|
|
|
116
223
|
|
|
117
224
|
# Integrate custom tools with the assistant
|
|
118
|
-
ai = Assistant(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
# pretty-print the response
|
|
122
|
-
pprint_messages(response)
|
|
225
|
+
ai = Assistant(tools=[visit_url])
|
|
226
|
+
ai.say("What's the top story on Hacker News?")
|
|
123
227
|
```
|
|
124
228
|
!!! success "Result"
|
|
125
229
|

|
|
126
230
|
|
|
127
|
-
### Talking to an assistant
|
|
128
|
-
|
|
129
|
-
The simplest way to talk to an assistant is to use its `say` method:
|
|
130
|
-
|
|
131
|
-
```python
|
|
132
|
-
ai = Assistant(name='Marvin')
|
|
133
|
-
|
|
134
|
-
response = ai.say('hi')
|
|
135
|
-
|
|
136
|
-
pprint_messages(response)
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
By default, the `say` method posts a single message to the assistant's `default_thread`, a thread that is automatically created for your convenience. You can supply a different thread by providing it as the `thread` parameter:
|
|
140
|
-
|
|
141
|
-
```python
|
|
142
|
-
# create a thread from an existing ID (or pass None for a new thread)
|
|
143
|
-
thread = Thread(id=thread_id)
|
|
144
|
-
|
|
145
|
-
# post a message to the thread
|
|
146
|
-
ai.say('hi', thread=thread)
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Using `say` is convenient, but enforces a strict request/response pattern: the user posts a single message to the thread, then the AI responds. Note that AI responses can span multiple messages. Therefore, the `say` method returns a list of `Message` objects.
|
|
150
|
-
|
|
151
|
-
For more control over the conversation, including posting multiple user messages to the thread or accessing the lower-level `Run` object that contains information about all actions the assistant took, use `Thread` objects directly instead of calling `say` (see [Threads](#threads) for more information).
|
|
152
|
-
|
|
153
|
-
|
|
154
231
|
### Lifecycle management
|
|
155
232
|
|
|
156
233
|
Assistants are Marvin objects that correspond to remote objects in the OpenAI API. You can not communicate with an assistant unless it has been registered with the API.
|
|
@@ -169,7 +246,7 @@ All of these options are *functionally* equivalent e.g. they produce identical r
|
|
|
169
246
|
The simplest way to manage assistant lifecycles is to let Marvin handle it for you. If you do not provide an `id` when instantiating an assistant, Marvin will lazily create a new API assistant for you whenever you need it and delete it immediately after. This is the default behavior, and it is the easiest way to get started with assistants.
|
|
170
247
|
|
|
171
248
|
```python
|
|
172
|
-
ai = Assistant(
|
|
249
|
+
ai = Assistant()
|
|
173
250
|
# creation and deletion happens automatically
|
|
174
251
|
ai.say('hello!')
|
|
175
252
|
```
|
|
@@ -179,7 +256,7 @@ ai.say('hello!')
|
|
|
179
256
|
Lazy lifecycle management adds two API calls to every LLM call (one to create the assistant and one to delete it). If you want to avoid this overhead, you can use context managers to create and delete assistants:
|
|
180
257
|
|
|
181
258
|
```python
|
|
182
|
-
ai = Assistant(
|
|
259
|
+
ai = Assistant()
|
|
183
260
|
|
|
184
261
|
# creation / deletion happens when the context is opened / closed
|
|
185
262
|
with ai:
|
|
@@ -194,7 +271,7 @@ Note there is also an equivalent `async with` context manager for the async API.
|
|
|
194
271
|
To fully control the lifecycle of an assistant, you can create and delete it manually:
|
|
195
272
|
|
|
196
273
|
```python
|
|
197
|
-
ai = Assistant(
|
|
274
|
+
ai = Assistant()
|
|
198
275
|
ai.create()
|
|
199
276
|
ai.say('hi')
|
|
200
277
|
ai.delete()
|
|
@@ -234,7 +311,7 @@ ai = Assistant.load(id=<the assistant id>)
|
|
|
234
311
|
Every `Assistant` method has a corresponding async version. To use the async API, append `_async` to the method name, or enter an async context manager:
|
|
235
312
|
|
|
236
313
|
```python
|
|
237
|
-
async with Assistant(
|
|
314
|
+
async with Assistant() as ai:
|
|
238
315
|
await ai.say_async('hi')
|
|
239
316
|
```
|
|
240
317
|
|
|
@@ -345,7 +422,7 @@ Messages are not strings, but structured message objects. Marvin has a few utili
|
|
|
345
422
|
def roll_dice(n_dice: int) -> list[int]:
|
|
346
423
|
return [random.randint(1, 6) for _ in range(n_dice)]
|
|
347
424
|
|
|
348
|
-
ai = Assistant(
|
|
425
|
+
ai = Assistant(tools=[roll_dice])
|
|
349
426
|
|
|
350
427
|
# create a thread - you could pass an ID to resume a conversation
|
|
351
428
|
thread = Thread()
|
|
@@ -363,8 +440,9 @@ Messages are not strings, but structured message objects. Marvin has a few utili
|
|
|
363
440
|
# run the thread again to generate a new response
|
|
364
441
|
thread.run(ai)
|
|
365
442
|
|
|
366
|
-
# see all the messages
|
|
367
|
-
|
|
443
|
+
# see all the messages in the thread
|
|
444
|
+
messages = thread.get_messages()
|
|
445
|
+
pprint_messages(messages)
|
|
368
446
|
```
|
|
369
447
|
|
|
370
448
|
!!! success "Result"
|
|
@@ -373,21 +451,3 @@ Messages are not strings, but structured message objects. Marvin has a few utili
|
|
|
373
451
|
### Async support
|
|
374
452
|
|
|
375
453
|
Every `Thread` method has a corresponding async version. To use the async API, append `_async` to the method name.
|
|
376
|
-
|
|
377
|
-
## Monitors
|
|
378
|
-
|
|
379
|
-
The assistants API is complex and stateful, with automatic memory management and the potential for assistants to respond to threads multiple times before giving control back to users. Therefore, monitoring the status of a conversation is considerably more difficult than with other LLM API's such as chat completions, which have much more simple request-response patterns.
|
|
380
|
-
|
|
381
|
-
Marvin has utilites for monitoring the status of a thread and taking action whenever a new message is added to it. This can be a useful way to debug activity or create notifications. Please note that monitors are not intended to be used for real-time chat applications or production use.
|
|
382
|
-
|
|
383
|
-
```python
|
|
384
|
-
from marvin.beta.assistants import ThreadMonitor
|
|
385
|
-
|
|
386
|
-
monitor = ThreadMonitor(thread_id=thread.id)
|
|
387
|
-
|
|
388
|
-
monitor.run()
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
You can customize the `ThreadMonitor` by providing a callback function to the `on_new_message` parameter. This function will be called whenever a new message is added to the thread. The function will be passed the new message as a parameter. By default, the monitor will pretty-print every new message to the console.
|
|
392
|
-
|
|
393
|
-
`monitor.run()` is a blocking call that will run forever, polling for messages every second (to customize the interval, pass `interval_seconds` to the method). It has an async equivalent `monitor.run_async()`. Because it's blocking, you can run a thread monitor in a separate session from the one that is running the thread itself.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# CLI
|
|
2
|
+
|
|
3
|
+
Marvin includes a CLI for quickly invoking an AI assistant.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
To use the CLI, simply `say` something to Marvin:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
marvin say "hi"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
You can control the [thread](#threads) and [assistant](#custom-assistants) you're talking to, as well as the [LLM model](#models) used for generating responses.
|
|
14
|
+
|
|
15
|
+
### Chat mode
|
|
16
|
+
|
|
17
|
+
By default, the CLI responds to a single message, then exits. To continue your conversation, you must reinvoke the CLI (possibly with the same arguments). Marvin also has a "chat mode" that allows you to have an extended conversation. Pass the `--chat` or `-c` flag to do this:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
marvin say "hi" -c
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
In chat mode, the CLI will continue to prompt you for messages until you exit by typing `exit` or pressing `Ctrl+C`.
|
|
24
|
+
|
|
25
|
+
## Models
|
|
26
|
+
|
|
27
|
+
By default, the CLI uses whatever model the assistant is configured to use. However, you can override this on a per-message basis using the `--model` or `-m` flag. For example, to use the `gpt-3.5-turbo` model for a single message:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
marvin say "hi" -m "gpt-3.5-turbo"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Tools
|
|
34
|
+
|
|
35
|
+
By default, the CLI assistant has the following tools:
|
|
36
|
+
|
|
37
|
+
- The OpenAI code interpreter, which allows you to write and execute Python code in a sandbox environment
|
|
38
|
+
- A tool that can fetch the content of a URL
|
|
39
|
+
- Tools for read-only access to the user's filesystem (such as listing and reading files)
|
|
40
|
+
|
|
41
|
+
To learn more about tools, see the [tools documentation](/docs/interactive/assistants/#tools).
|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
## Threads
|
|
46
|
+
|
|
47
|
+
The CLI assistant automatically remembers the history of your conversation. You can use threads to create multiple simultaneous conversations. To learn more about threads, see the [threads documentation](/docs/interactive/assistants/#threads).
|
|
48
|
+
|
|
49
|
+
### Changing threads
|
|
50
|
+
|
|
51
|
+
By default, the CLI assistant uses a global default thread. For example, this posts two messages to the global default thread:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
marvin say "Hello!"
|
|
55
|
+
marvin say "How are you?"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
To change the thread on a per-message basis, use the `--thread` or `-t` flag and provide a thread name. Thread names are arbitrary and can be any string; it's a way for you to group conversations together.
|
|
59
|
+
|
|
60
|
+
This posts one message to a thread called "my-thread" and another to a thread called "my-other-thread":
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
marvin say "Hello!" -t my-thread
|
|
64
|
+
marvin say "How are you?" -t my-other-thread
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
To change the default thread for multiple messages, use the `MARVIN_CLI_THREAD` environment variable. You can do this globally or `export` it in your shell for a single session. For example, this sets the default thread to "my-thread":
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
export MARVIN_CLI_THREAD=my-thread
|
|
71
|
+
|
|
72
|
+
marvin say "Hello!"
|
|
73
|
+
marvin say "How are you?"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Clearing threads
|
|
77
|
+
|
|
78
|
+
To reset a thread and clear its history, use the `clear` command. For example, this clears the default thread:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
marvin thread clear
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
And this clears a thread called "my-thread":
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
marvin thread clear -t my-thread
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### Current thread
|
|
92
|
+
|
|
93
|
+
To see the current thread (and corresponding OpenAI thread ID), use the `current` command. For example:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
marvin thread current
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Custom assistants
|
|
100
|
+
|
|
101
|
+
The Marvin CLI allows you to register and use custom assistants in addition to the default assistant. Custom assistants are defined in Python files and can have their own set of instructions, tools, and behaviors.
|
|
102
|
+
|
|
103
|
+
Using a custom assistant has the following workflow:
|
|
104
|
+
|
|
105
|
+
1. Define the assistant in a Python file
|
|
106
|
+
2. Register the assistant with the Marvin CLI
|
|
107
|
+
3. Use the assistant in the CLI
|
|
108
|
+
|
|
109
|
+
### Defining an assistant
|
|
110
|
+
|
|
111
|
+
To use a custom assistant, you must define it in a Python file. In a new file, create an instance of the `Assistant` class from the `marvin.beta.assistants`. Provide it with any desired options, such as a name, instructions, and tools. To learn more about creating assistants, see the [assistants documentation](/docs/interactive/assistants/). The only requirement is that the assistant object must be assigned to a global variable in the file so that the CLI can load it.
|
|
112
|
+
|
|
113
|
+
For example, this file defines an assistant named "Arthur" that can use the code interpreter. The assistant is stored under the variable `my_assistant`.
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
# path/to/custom_assistant.py
|
|
117
|
+
|
|
118
|
+
from marvin.beta.assistants import Assistant, CodeInterpreter
|
|
119
|
+
|
|
120
|
+
my_assistant = Assistant(
|
|
121
|
+
name="Arthur",
|
|
122
|
+
instructions="A parody of Arthur Dent",
|
|
123
|
+
tools=[CodeInterpreter]
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Registering an assistant
|
|
128
|
+
|
|
129
|
+
Once you've created a Python file that defines an assistant, you can register it with the Marvin CLI. This allows you to use the assistant in the CLI by name.
|
|
130
|
+
|
|
131
|
+
To do so, use the `marvin assistant register` command followed by the fully-qualified path to the Python file *and* the variable that contains the assistant. For example, to register the assistant defined in the previous step, use the following command:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
marvin assistant register path/to/custom_assistant.py:my_assistant
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
This command will automatically use the assistant's name (Arthur) as the name of the assistant in the Marvin CLI registry. You will need to provide the name to load the assistant, which is why each registered assistant must have a unique name. Registering an assistant with the same name as an existing one will fail. In this case, you can either delete the existing assistant or use the `--overwrite` or `-o` flag to overwrite it. You can also provide an alternative name during registration using the `--name` or `-n` flag. For example, this would register the assistant with the name "My Custom Assistant":
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
marvin assistant register path/to/custom_assistant.py:my_assistant -n "My Custom Assistant"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
!!! warning
|
|
145
|
+
When you register an assistant, its name and the path to the file that contains it are stored in the Marvin CLI registry. This allows the CLI to load the assistant whenever you need it. However, it means the assistant file **must** remain in the same location, with the same name, for the CLI to find it. If you move or rename the file, you will need to re-register the assistant. However, if you edit the file without changing the variable name of the assistant, the CLI will automatically use the updated assistant.
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
### Using an assistant
|
|
150
|
+
|
|
151
|
+
To use a custom assistant when sending a message, use the `--assistant` or `-a` flag followed by the name of the registered assistant. For example, if you registered an assistant named "Arthur", you can talk to it like this:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
marvin say "Hello!" -a "Arthur"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
You can also set a default assistant using the MARVIN_CLI_ASSISTANT environment variable, similar to setting a default thread. This allows you to set a global or session-specific default assistant.
|
|
158
|
+
|
|
159
|
+
#### Mixing threads and assistants
|
|
160
|
+
|
|
161
|
+
Threads and assistants are independent, so you can talk to multiple assistants in the same thread. Note that due to limitations in the OpenAI API, assistants aren't aware of other assistants, so they assume that they said everything in the thread history (even if another assistant did).
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
marvin say "Hello!" -a "Arthur" -t "marvin-thread"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Listing registered assistants
|
|
168
|
+
|
|
169
|
+
To see a list of all registered assistants, use the `marvin assistant list` command. This will display a table with the names and file paths of the registered assistants.
|
|
170
|
+
|
|
171
|
+
### Deleting a registered assistant
|
|
172
|
+
|
|
173
|
+
To remove a registered assistant, use the `marvin assistant delete` command followed by the name of the assistant. For example:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
marvin assistant delete "My Custom Assistant"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Note that this only removes the reference to the assistant in the Marvin registry and does not delete the actual assistant file, even if you used the `--copy` flag during registration.
|
|
@@ -16,7 +16,8 @@ dependencies = [
|
|
|
16
16
|
"httpx>=0.24.1",
|
|
17
17
|
"jinja2>=3.1.2",
|
|
18
18
|
"jsonpatch>=1.33",
|
|
19
|
-
"openai>=1.
|
|
19
|
+
"openai>=1.4.0",
|
|
20
|
+
"prompt-toolkit>=3.0.33",
|
|
20
21
|
"pydantic>=2.4.2",
|
|
21
22
|
"pydantic_settings",
|
|
22
23
|
"rich>=12",
|
|
@@ -26,6 +27,7 @@ dependencies = [
|
|
|
26
27
|
# need for windows
|
|
27
28
|
"tzdata>=2023.3",
|
|
28
29
|
"uvicorn>=0.22.0",
|
|
30
|
+
"partialjson>=0.0.5",
|
|
29
31
|
]
|
|
30
32
|
|
|
31
33
|
[project.optional-dependencies]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
from typing import Callable, Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AIFlow(BaseModel):
|
|
8
|
+
name: Optional[str] = None
|
|
9
|
+
fn: Callable
|
|
10
|
+
|
|
11
|
+
def __call__(self, *args, thread_id: str = None, **kwargs):
|
|
12
|
+
raise NotImplementedError("AI Flow is currently being upgraded")
|
|
13
|
+
# pflow = prefect_flow(name=self.name)(self.fn)
|
|
14
|
+
|
|
15
|
+
# # Set up the thread context and execute the flow
|
|
16
|
+
|
|
17
|
+
# # create a new thread for the flow
|
|
18
|
+
# thread = Thread(id=thread_id)
|
|
19
|
+
# if thread_id is None:
|
|
20
|
+
# thread.create()
|
|
21
|
+
|
|
22
|
+
# # create a holder for the tasks
|
|
23
|
+
# tasks = []
|
|
24
|
+
|
|
25
|
+
# with interactive_chat(thread_id=thread.id):
|
|
26
|
+
# # enter the thread context
|
|
27
|
+
# with thread_context(thread_id=thread.id, tasks=tasks, **kwargs):
|
|
28
|
+
# return pflow(*args, **kwargs)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def ai_flow(*args, name=None):
|
|
32
|
+
def decorator(func):
|
|
33
|
+
@functools.wraps(func)
|
|
34
|
+
def wrapper(*func_args, **func_kwargs):
|
|
35
|
+
ai_flow_instance = AIFlow(fn=func, name=name or func.__name__)
|
|
36
|
+
return ai_flow_instance(*func_args, **func_kwargs)
|
|
37
|
+
|
|
38
|
+
return wrapper
|
|
39
|
+
|
|
40
|
+
if args and callable(args[0]):
|
|
41
|
+
return decorator(args[0])
|
|
42
|
+
|
|
43
|
+
return decorator
|