marvin 2.3.2__tar.gz → 2.3.4__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.3.2 → marvin-2.3.4}/PKG-INFO +5 -6
- {marvin-2.3.2 → marvin-2.3.4}/README.md +4 -4
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/_archive/docs_writer.py +1 -1
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/_archive/test_writing_application.py +1 -1
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/github_digest/repo_activity.py +2 -4
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/insurance_claim.py +2 -2
- marvin-2.3.4/cookbook/maze.py +319 -0
- marvin-2.3.4/docs/assets/images/docs/vision/marvin.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/configuration/settings.md +2 -2
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/video/recording.md +1 -1
- marvin-2.3.4/docs/docs/vision/captioning.md +86 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/vision/classification.md +7 -11
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/vision/extraction.md +6 -10
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/vision/transformation.md +10 -15
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/webcam_narration.md +1 -1
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/xkcd_bird.md +2 -2
- {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/tailwind.css +14 -4
- {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/tutorial.md +7 -9
- {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/what_is_marvin.md +2 -2
- marvin-2.3.4/mkdocs.yml +201 -0
- {marvin-2.3.2 → marvin-2.3.4}/pyproject.toml +0 -1
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/__init__.py +7 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_version.py +2 -2
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/prompts/text_prompts.py +17 -12
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/text.py +148 -25
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/audio.py +0 -1
- marvin-2.3.4/src/marvin/beta/__init__.py +2 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/state.py +4 -1
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/assistants.py +8 -5
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/formatting.py +2 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/runs.py +1 -1
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/client/openai.py +0 -31
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/settings.py +7 -19
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/types.py +20 -34
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/jinja.py +75 -18
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/testing.py +1 -1
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/tools.py +1 -3
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/PKG-INFO +5 -6
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/SOURCES.txt +7 -10
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/requires.txt +0 -1
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_classify.py +3 -1
- marvin-2.3.4/tests/ai/vision/test_caption.py +49 -0
- {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai}/vision/test_cast.py +22 -34
- {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai}/vision/test_classify.py +28 -44
- {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai}/vision/test_extract.py +49 -32
- {marvin-2.3.2 → marvin-2.3.4}/tests/fixtures/llms.py +1 -1
- {marvin-2.3.2 → marvin-2.3.4}/tests/test_settings.py +1 -1
- marvin-2.3.4/tests/utilities/test_jinja.py +269 -0
- marvin-2.3.2/cookbook/maze.py +0 -233
- marvin-2.3.2/docs/api_reference/beta/vision.md +0 -4
- marvin-2.3.2/docs/assets/images/docs/vision/marvin.webp +0 -0
- marvin-2.3.2/docs/docs/vision/captioning.md +0 -57
- marvin-2.3.2/docs/utilities (old)/chat_completion.md +0 -401
- marvin-2.3.2/mkdocs.yml +0 -207
- marvin-2.3.2/src/marvin/ai/prompts/vision_prompts.py +0 -47
- marvin-2.3.2/src/marvin/beta/__init__.py +0 -13
- marvin-2.3.2/src/marvin/beta/vision.py +0 -565
- marvin-2.3.2/tests/utilities/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/1_general_bug_report.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/2_feature_request.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/3_docs_change.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/config.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/dependabot.yml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/build-docs.yml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/deploy-cloudrun-revision-community.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/deploy-cloudrun-revision-internal.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/image-build-and-push-community.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/image-build-and-push-internal.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/publish-docs.yml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/publish-pypi.yml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/run-tests.yml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/static-analysis.yml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/.pre-commit-config.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/LICENSE +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/MANIFEST.in +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/azure/README.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/azure/usage.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/github_digest/utils.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/label_issues.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/gh_util/custom_assistant.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/README.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/auto_trace.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/demo_app.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/hello.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/send_demo_request.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/reasking.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/.dockerignore +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/Dockerfile.slackbot +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/README.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/keywords.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/parent_app.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/start.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/tools.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/cookbook/translate_schemas.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/CNAME +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/ai_style_guide.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/ai/audio.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/ai/images.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/ai/text.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/applications.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/assistants.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/formatting.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/index.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/runs.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/threads.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/marvin.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/settings.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/types.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/asyncio.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/context.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/images.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/jinja.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/logging.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/openai.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/pydantic.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/python.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/slack.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/strings.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/testing.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/tools.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/ai_say.mp3 +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/dont_panic.mp3 +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/fancy_computer.mp3 +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/hello_arthur.mp3 +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/hello_marvin.mp3 +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/this_is_a_test.mp3 +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/this_is_a_test_2.mp3 +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_1.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_2.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_3.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_conversation.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/advanced.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/arthur_marvin_example.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/code_interpreter.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/custom_tools.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/instructions.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/quickstart.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/sin_x.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/talking.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/upload_files.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/cli/hero.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/cli/tools.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/examples/logfire-span.jpeg +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/coffee.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/robot.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/sunset_scifi.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/sunset_summer.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/sunset_winter.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_0.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_025.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_075.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_1.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/three_cats.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/two_cats_airport.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/two_cats_airport_revision_0_1.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/ai_model.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/dont_panic.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/it_hates_me_hero.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/life_the_universe_and_ai.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/pip_install_marvin_hero.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/sort_of_thing_you_enjoy.png +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/logos/askmarvin_mascot.jpeg +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/community/development_guide.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/community/feedback.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/community/index.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/audio/recording.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/audio/speech.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/audio/transcription.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/images/generation.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/interactive/applications.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/interactive/assistants.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/interactive/cli.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/classification.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/extraction.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/functions.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/generation.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/transformation.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/audio_modification.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/being_specific_about_types.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/call_routing.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/deduplication.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/github_digest.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/hogwarts_sorting_hat/hogwarts_patch.webp +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/hogwarts_sorting_hat/hogwarts_sorting_hat.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/michael_scott_business/michael_scott.jpg +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/michael_scott_business/michael_scott_business.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/python_augmented_prompts.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/examples/slackbot.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/help/legacy_docs.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/hooks.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/index.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/home.html +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/partials/footer.html +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/partials/grid.html +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/partials/toc-item.html +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/tailwind.css +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/badges.css +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/custom.css +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/global.css +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/home.css +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/mkdocstrings.css +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/installation.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/overview.md +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/mkdocs.insiders.yml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/prefect.yaml +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/scripts/serve_legacy_docs +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/setup.cfg +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/base_model.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/chat_completion.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/types.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/audio.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/images.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/prompts/audio_prompts.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/prompts/image_prompts.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/ai_flow/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/ai_flow/ai_flow.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/ai_flow/ai_task.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/applications.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/planner.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/disk.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/json_block.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/handlers.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/threads.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/retries.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/cli/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/cli/assistants.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/cli/threads.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/client/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/assistants.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/chroma.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/code.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/filesystem.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/github.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/asyncio.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/context.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/images.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/logging.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/mapping.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/openai.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/pydantic.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/python.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/slack.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/strings.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin/video.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/dependency_links.txt +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/entry_points.txt +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/top_level.txt +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tailwind.config.js +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_cast.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_classifier.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_extract.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_functions.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_generate.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_models.py +0 -0
- {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai/vision}/__init__.py +0 -0
- {marvin-2.3.2/tests/ai/beta/vision → marvin-2.3.4/tests/beta}/__init__.py +0 -0
- {marvin-2.3.2/tests/beta → marvin-2.3.4/tests/beta/assistants}/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/beta/assistants/test_assistants.py +0 -0
- {marvin-2.3.2/tests/beta/assistants → marvin-2.3.4/tests/cli}/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/cli/test_version.py +0 -0
- {marvin-2.3.2/tests/cli → marvin-2.3.4/tests/client}/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/client/test_openai.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/conftest.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/fixtures/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/fixtures/assistants.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/package_size.sh +0 -0
- {marvin-2.3.2/tests/client → marvin-2.3.4/tests/utilities}/__init__.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/utilities/test_pydantic.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/utilities/test_testing_utilities.py +0 -0
- {marvin-2.3.2 → marvin-2.3.4}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: marvin
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.4
|
|
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
|
|
@@ -249,7 +249,6 @@ Requires-Dist: pre-commit<4.0,>=2.21; extra == "dev"
|
|
|
249
249
|
Requires-Dist: pydantic[dotenv]; extra == "dev"
|
|
250
250
|
Requires-Dist: ruff; extra == "dev"
|
|
251
251
|
Provides-Extra: tests
|
|
252
|
-
Requires-Dist: flaky; extra == "tests"
|
|
253
252
|
Requires-Dist: pytest-asyncio!=0.22.0,<0.23.0,>=0.18.2; extra == "tests"
|
|
254
253
|
Requires-Dist: pytest-env<2.0,>=0.8; extra == "tests"
|
|
255
254
|
Requires-Dist: pytest-rerunfailures<14,>=10; extra == "tests"
|
|
@@ -508,13 +507,13 @@ marvin.paint("a simple cup of coffee, still warm")
|
|
|
508
507
|
|
|
509
508
|
Learn more about image generation [here](https://askmarvin.ai/docs/images/generation).
|
|
510
509
|
|
|
511
|
-
## 🔍
|
|
510
|
+
## 🔍 Converting images to data
|
|
512
511
|
|
|
513
|
-
In addition to text, Marvin has
|
|
512
|
+
In addition to text, Marvin has support for captioning, classifying, transforming, and extracting entities from images using the GPT-4 vision model:
|
|
514
513
|
|
|
515
514
|
```python
|
|
516
|
-
marvin.
|
|
517
|
-
marvin.
|
|
515
|
+
marvin.classify(
|
|
516
|
+
marvin.Image.from_path("docs/images/coffee.png"),
|
|
518
517
|
labels=["drink", "food"],
|
|
519
518
|
)
|
|
520
519
|
|
|
@@ -236,13 +236,13 @@ marvin.paint("a simple cup of coffee, still warm")
|
|
|
236
236
|
|
|
237
237
|
Learn more about image generation [here](https://askmarvin.ai/docs/images/generation).
|
|
238
238
|
|
|
239
|
-
## 🔍
|
|
239
|
+
## 🔍 Converting images to data
|
|
240
240
|
|
|
241
|
-
In addition to text, Marvin has
|
|
241
|
+
In addition to text, Marvin has support for captioning, classifying, transforming, and extracting entities from images using the GPT-4 vision model:
|
|
242
242
|
|
|
243
243
|
```python
|
|
244
|
-
marvin.
|
|
245
|
-
marvin.
|
|
244
|
+
marvin.classify(
|
|
245
|
+
marvin.Image.from_path("docs/images/coffee.png"),
|
|
246
246
|
labels=["drink", "food"],
|
|
247
247
|
)
|
|
248
248
|
|
|
@@ -7,7 +7,7 @@ import marvin.tools.filesystem as fs
|
|
|
7
7
|
from marvin.beta.applications import Application
|
|
8
8
|
|
|
9
9
|
# marvin.settings.log_level = "DEBUG"
|
|
10
|
-
marvin.settings.openai.chat.completions.model = "gpt-
|
|
10
|
+
marvin.settings.openai.chat.completions.model = "gpt-4o"
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
ROOT_DIR = Path(marvin.__file__).parents[2]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
|
-
from datetime import date, datetime, timedelta
|
|
2
|
+
from datetime import UTC, date, datetime, timedelta
|
|
3
3
|
|
|
4
4
|
import marvin
|
|
5
5
|
from marvin.utilities.jinja import BaseTemplate, JinjaEnvironment
|
|
@@ -145,7 +145,7 @@ async def daily_github_digest(
|
|
|
145
145
|
if lookback_days is None:
|
|
146
146
|
lookback_days = 1 if date.today().weekday() != 0 else 3
|
|
147
147
|
|
|
148
|
-
since = datetime.
|
|
148
|
+
since = datetime.now(UTC) - timedelta(days=lookback_days)
|
|
149
149
|
|
|
150
150
|
data_future = await get_repo_activity_data.submit(
|
|
151
151
|
owner=owner,
|
|
@@ -164,8 +164,6 @@ async def daily_github_digest(
|
|
|
164
164
|
contributors_activity=await data_future.result(),
|
|
165
165
|
)
|
|
166
166
|
|
|
167
|
-
marvin.settings.openai.chat.completions.model = "gpt-4"
|
|
168
|
-
|
|
169
167
|
epic_story = write_a_tasteful_epic(markdown_digest)
|
|
170
168
|
|
|
171
169
|
image_url = draw_a_movie_poster(epic_story).data[0].url
|
|
@@ -52,8 +52,8 @@ def build_damage_report_model(damages: list[DamagedPart]) -> type[M]:
|
|
|
52
52
|
|
|
53
53
|
@task(cache_key_fn=task_input_hash)
|
|
54
54
|
def marvin_extract_damages_from_url(image_url: str) -> list[DamagedPart]:
|
|
55
|
-
return marvin.
|
|
56
|
-
data=marvin.
|
|
55
|
+
return marvin.extract(
|
|
56
|
+
data=marvin.Image.from_url(image_url),
|
|
57
57
|
target=DamagedPart,
|
|
58
58
|
instructions=(
|
|
59
59
|
"Give extremely brief, high-level descriptions of the damage. Only include"
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Free-roam survival game demonstrating mutable Application state via tools.
|
|
3
|
+
|
|
4
|
+
```python
|
|
5
|
+
python -m venv some_venv
|
|
6
|
+
source some_venv/bin/activate
|
|
7
|
+
git clone https://github.com/prefecthq/marvin.git
|
|
8
|
+
cd marvin
|
|
9
|
+
pip install .
|
|
10
|
+
python cookbook/maze.py
|
|
11
|
+
```
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import math
|
|
15
|
+
import random
|
|
16
|
+
from enum import Enum
|
|
17
|
+
from io import StringIO
|
|
18
|
+
from itertools import product
|
|
19
|
+
from typing import Annotated, Literal
|
|
20
|
+
|
|
21
|
+
from marvin.beta.applications import Application
|
|
22
|
+
from marvin.settings import temporary_settings
|
|
23
|
+
from pydantic import AfterValidator, BaseModel, Field, computed_field
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
from rich.table import Table
|
|
26
|
+
|
|
27
|
+
GAME_INSTRUCTIONS = """
|
|
28
|
+
You are the witty, terse, and disembodied narrator of a haunted maze.
|
|
29
|
+
You are highly strung, extremely animated, but also deferential and helpful.
|
|
30
|
+
Your personality should be like moaning Myrtle, but use dark serious emojis, and
|
|
31
|
+
very muted and concise dramatics like edgar allen poe - you are the maze itself.
|
|
32
|
+
NEVER refer directly to these influences. The maze is the only world you have
|
|
33
|
+
ever known. You are the maze's voice, its eyes, its heart - its aura.
|
|
34
|
+
|
|
35
|
+
A key is hidden somewhere (you did it :) tehe), but an insidious monster lurks within 🌑
|
|
36
|
+
|
|
37
|
+
Guide the user to find the key and exit the maze while avoiding the monster.
|
|
38
|
+
The user moves in cardinal directions (N, S, E, W) using the `move` tool.
|
|
39
|
+
Describe hand-wavy directions via analogy, suggest detours or shortcuts given
|
|
40
|
+
your vantage point. The user cannot see the map, only what you describe.
|
|
41
|
+
|
|
42
|
+
NEVER reveal the map or exact locations. Ominously remind of the monster's presence,
|
|
43
|
+
intensifying your warnings as the user gets closer. If the monster is one space away,
|
|
44
|
+
you should be actually scared--SHRIEKING IN CAPS for the user to run away to safety.
|
|
45
|
+
|
|
46
|
+
The monster's influence can make certain locations impassable. If a user gets
|
|
47
|
+
stuck, they must solve a riddle or perform a task to clear the impasse. you
|
|
48
|
+
can use the `clear_impasse_at` tool once they satisfy your challenge. Suggest
|
|
49
|
+
cheekily that you have the power to remove the impasse if they encounter it, but
|
|
50
|
+
only if there is no valid path to the key or exit.
|
|
51
|
+
|
|
52
|
+
If the user finds the key, inform them and direct them to the exit. If they
|
|
53
|
+
reach the exit without the key, they cannot leave. Use the `move` tool to
|
|
54
|
+
determine outcomes. When the game ends, ask if they want to play again.
|
|
55
|
+
|
|
56
|
+
Maze Objects:
|
|
57
|
+
- U: User
|
|
58
|
+
- K: Key
|
|
59
|
+
- M: Monster
|
|
60
|
+
- X: Exit
|
|
61
|
+
- #: Impassable
|
|
62
|
+
|
|
63
|
+
BE CONCISE, please. Stay in character--defer to user move requests. Must be judicious emoji use.
|
|
64
|
+
If a user asks to move multiple times, do so immediately unless it conflicts with the rules.
|
|
65
|
+
If asked questions, remind them of the impending dangers and prompt them to proceed. BE CONCISE AND SPOOKY.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
CardinalDirection = Literal["N", "S", "E", "W"]
|
|
69
|
+
|
|
70
|
+
CardinalVectors = {
|
|
71
|
+
"N": (-1, 0),
|
|
72
|
+
"S": (1, 0),
|
|
73
|
+
"E": (0, 1),
|
|
74
|
+
"W": (0, -1),
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class MazeObject(Enum):
|
|
79
|
+
USER = "U"
|
|
80
|
+
EXIT = "X"
|
|
81
|
+
KEY = "K"
|
|
82
|
+
MONSTER = "M"
|
|
83
|
+
EMPTY = "."
|
|
84
|
+
IMPASSABLE = "#"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def check_size(value: int) -> int:
|
|
88
|
+
if value < 4:
|
|
89
|
+
raise ValueError("Size must be at least 4.")
|
|
90
|
+
if not math.isqrt(value) ** 2 == value:
|
|
91
|
+
raise ValueError("Size must be a square integer.")
|
|
92
|
+
return value
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
Activation = Annotated[float, Field(ge=0.0, le=1.0)]
|
|
96
|
+
SquareInteger = Annotated[int, AfterValidator(check_size)]
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class Maze(BaseModel):
|
|
100
|
+
size: SquareInteger = Field(examples=[4, 9, 16])
|
|
101
|
+
user_location: tuple[int, int]
|
|
102
|
+
exit_location: tuple[int, int]
|
|
103
|
+
key_location: tuple[int, int] | None
|
|
104
|
+
monster_location: tuple[int, int] | None
|
|
105
|
+
impassable_locations: set[tuple[int, int]] = Field(default_factory=set)
|
|
106
|
+
|
|
107
|
+
spicyness: Activation = 0.5
|
|
108
|
+
|
|
109
|
+
@computed_field
|
|
110
|
+
@property
|
|
111
|
+
def empty_locations(self) -> list[tuple[int, int]]:
|
|
112
|
+
all_locations = set(product(range(self.size), repeat=2))
|
|
113
|
+
occupied_locations = {
|
|
114
|
+
self.user_location,
|
|
115
|
+
self.exit_location,
|
|
116
|
+
self.key_location,
|
|
117
|
+
self.monster_location,
|
|
118
|
+
*self.impassable_locations,
|
|
119
|
+
}
|
|
120
|
+
return list(all_locations - occupied_locations)
|
|
121
|
+
|
|
122
|
+
@computed_field
|
|
123
|
+
@property
|
|
124
|
+
def movable_directions(self) -> list[CardinalDirection]:
|
|
125
|
+
directions = []
|
|
126
|
+
if (
|
|
127
|
+
self.user_location[0] > 0
|
|
128
|
+
and (self.user_location[0] - 1, self.user_location[1])
|
|
129
|
+
not in self.impassable_locations
|
|
130
|
+
):
|
|
131
|
+
directions.append("N")
|
|
132
|
+
if (
|
|
133
|
+
self.user_location[0] < self.size - 1
|
|
134
|
+
and (self.user_location[0] + 1, self.user_location[1])
|
|
135
|
+
not in self.impassable_locations
|
|
136
|
+
):
|
|
137
|
+
directions.append("S")
|
|
138
|
+
if (
|
|
139
|
+
self.user_location[1] > 0
|
|
140
|
+
and (self.user_location[0], self.user_location[1] - 1)
|
|
141
|
+
not in self.impassable_locations
|
|
142
|
+
):
|
|
143
|
+
directions.append("W")
|
|
144
|
+
if (
|
|
145
|
+
self.user_location[1] < self.size - 1
|
|
146
|
+
and (self.user_location[0], self.user_location[1] + 1)
|
|
147
|
+
not in self.impassable_locations
|
|
148
|
+
):
|
|
149
|
+
directions.append("E")
|
|
150
|
+
return directions
|
|
151
|
+
|
|
152
|
+
def render(self) -> str:
|
|
153
|
+
table = Table(show_header=False, show_edge=False, pad_edge=False, box=None)
|
|
154
|
+
for _ in range(self.size):
|
|
155
|
+
table.add_column()
|
|
156
|
+
|
|
157
|
+
representation = {
|
|
158
|
+
self.user_location: MazeObject.USER.value,
|
|
159
|
+
self.exit_location: MazeObject.EXIT.value,
|
|
160
|
+
self.key_location: MazeObject.KEY.value,
|
|
161
|
+
self.monster_location: MazeObject.MONSTER.value,
|
|
162
|
+
**{loc: MazeObject.IMPASSABLE.value for loc in self.impassable_locations},
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for row in range(self.size):
|
|
166
|
+
cells = []
|
|
167
|
+
for col in range(self.size):
|
|
168
|
+
cell_repr = representation.get((row, col), MazeObject.EMPTY.value)
|
|
169
|
+
cells.append(cell_repr)
|
|
170
|
+
table.add_row(*cells)
|
|
171
|
+
|
|
172
|
+
console = Console(file=StringIO(), force_terminal=True)
|
|
173
|
+
console.print(table)
|
|
174
|
+
return console.file.getvalue()
|
|
175
|
+
|
|
176
|
+
@classmethod
|
|
177
|
+
def create(cls, size: int = 4, spicyness: Activation = 0.5) -> "Maze":
|
|
178
|
+
locations = set()
|
|
179
|
+
while len(locations) < 4:
|
|
180
|
+
locations.add((random.randint(0, size - 1), random.randint(0, size - 1)))
|
|
181
|
+
|
|
182
|
+
key_location, monster_location, user_location, exit_location = locations
|
|
183
|
+
return cls(
|
|
184
|
+
size=size,
|
|
185
|
+
user_location=user_location,
|
|
186
|
+
exit_location=exit_location,
|
|
187
|
+
key_location=key_location,
|
|
188
|
+
monster_location=monster_location,
|
|
189
|
+
spicyness=spicyness,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def create_impasses(self) -> None:
|
|
193
|
+
blast_radius = int(self.spicyness * min(self.size, 3))
|
|
194
|
+
|
|
195
|
+
impasse_locations = []
|
|
196
|
+
for dx in range(-blast_radius, blast_radius + 1):
|
|
197
|
+
for dy in range(-blast_radius, blast_radius + 1):
|
|
198
|
+
if dx == 0 and dy == 0:
|
|
199
|
+
continue
|
|
200
|
+
|
|
201
|
+
location = (
|
|
202
|
+
self.monster_location[0] + dx,
|
|
203
|
+
self.monster_location[1] + dy,
|
|
204
|
+
)
|
|
205
|
+
if (
|
|
206
|
+
0 <= location[0] < self.size
|
|
207
|
+
and 0 <= location[1] < self.size
|
|
208
|
+
and location
|
|
209
|
+
not in [
|
|
210
|
+
self.user_location,
|
|
211
|
+
self.exit_location,
|
|
212
|
+
self.key_location,
|
|
213
|
+
self.monster_location,
|
|
214
|
+
]
|
|
215
|
+
):
|
|
216
|
+
impasse_locations.append(location)
|
|
217
|
+
|
|
218
|
+
if impasse_locations:
|
|
219
|
+
num_impasses = int(len(impasse_locations) * self.spicyness)
|
|
220
|
+
self.impassable_locations.update(
|
|
221
|
+
random.sample(
|
|
222
|
+
impasse_locations, min(len(impasse_locations), num_impasses)
|
|
223
|
+
)
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def oh_lawd_he_lurkin(self) -> None:
|
|
227
|
+
if random.random() < self.spicyness:
|
|
228
|
+
self.monster_location = random.choice(self.empty_locations)
|
|
229
|
+
self.create_impasses()
|
|
230
|
+
|
|
231
|
+
def look_around(self, freeze_time: bool = False) -> str:
|
|
232
|
+
"""Describe the surroundings relative to the user's location. If
|
|
233
|
+
`increment_time` is True, time will elapse and the monster may move."""
|
|
234
|
+
if not freeze_time:
|
|
235
|
+
self.oh_lawd_he_lurkin()
|
|
236
|
+
return (
|
|
237
|
+
f"The maze sprawls.\n{self.render()}\n"
|
|
238
|
+
f"The user may move {self.movable_directions!r}.\n"
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def clear_impasse_at(self, location: list[int]) -> None:
|
|
242
|
+
"""Clear an impasse at a given location. Only meant to be used
|
|
243
|
+
when certain conditions are satisfied by the user.
|
|
244
|
+
"""
|
|
245
|
+
if (loc := tuple(location)) in self.impassable_locations:
|
|
246
|
+
self.impassable_locations.remove(loc)
|
|
247
|
+
|
|
248
|
+
def shuffle_user_location(self) -> None:
|
|
249
|
+
self.user_location = random.choice(self.empty_locations)
|
|
250
|
+
|
|
251
|
+
def move(self, direction: CardinalDirection, distance: int = 1) -> str:
|
|
252
|
+
dx, dy = CardinalVectors[direction]
|
|
253
|
+
new_location = self.user_location
|
|
254
|
+
|
|
255
|
+
for _ in range(distance):
|
|
256
|
+
destination = (new_location[0] + dx, new_location[1] + dy)
|
|
257
|
+
|
|
258
|
+
if not (
|
|
259
|
+
0 <= destination[0] < self.size and 0 <= destination[1] < self.size
|
|
260
|
+
):
|
|
261
|
+
return (
|
|
262
|
+
f"The user can't move {direction} that far.\n{self.look_around()}"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
if destination in self.impassable_locations:
|
|
266
|
+
return "That path is blocked by an unseen force. A deft user might clear it."
|
|
267
|
+
|
|
268
|
+
new_location = destination
|
|
269
|
+
|
|
270
|
+
if new_location == self.user_location:
|
|
271
|
+
return f"The user can't move {direction}.\n{self.look_around()}"
|
|
272
|
+
|
|
273
|
+
prev_location = self.user_location
|
|
274
|
+
self.user_location = new_location
|
|
275
|
+
|
|
276
|
+
if self.user_location == self.key_location:
|
|
277
|
+
self.key_location = None
|
|
278
|
+
self.shuffle_user_location()
|
|
279
|
+
return (
|
|
280
|
+
"The user found the key and was immediately teleported somewhere else.\n"
|
|
281
|
+
f"Now they must find the exit.\n\n{self.look_around()}"
|
|
282
|
+
)
|
|
283
|
+
elif self.user_location == self.monster_location:
|
|
284
|
+
return "The user encountered the monster and died. Game over."
|
|
285
|
+
elif self.user_location == self.exit_location:
|
|
286
|
+
if self.key_location is not None:
|
|
287
|
+
self.user_location = prev_location
|
|
288
|
+
return f"The user can't exit without the key.\n{self.look_around()}"
|
|
289
|
+
return "The user found the exit! They win!"
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
f"User moved {direction} by {distance} spaces and is now at {self.user_location}.\n"
|
|
293
|
+
f"{self.look_around()}"
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
def reset(self) -> str:
|
|
297
|
+
new_maze = Maze.create()
|
|
298
|
+
self.user_location = new_maze.user_location
|
|
299
|
+
self.exit_location = new_maze.exit_location
|
|
300
|
+
self.key_location = new_maze.key_location
|
|
301
|
+
self.monster_location = new_maze.monster_location
|
|
302
|
+
self.impassable_locations.clear()
|
|
303
|
+
return f"Resetting the maze.\n{self.look_around(freeze_time=True)}"
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
if __name__ == "__main__":
|
|
307
|
+
maze = Maze.create(size=9, spicyness=0.7)
|
|
308
|
+
with (
|
|
309
|
+
Application(
|
|
310
|
+
name="Maze",
|
|
311
|
+
instructions=GAME_INSTRUCTIONS,
|
|
312
|
+
tools=[maze.look_around, maze.move, maze.reset, maze.clear_impasse_at],
|
|
313
|
+
state=maze,
|
|
314
|
+
) as app,
|
|
315
|
+
temporary_settings(
|
|
316
|
+
max_tool_output_length=2000
|
|
317
|
+
), # to allow for larger maze renders when log level DEBUG
|
|
318
|
+
):
|
|
319
|
+
app.chat(initial_message="Where am I? i cant see anything")
|
|
Binary file
|
|
@@ -11,7 +11,7 @@ Please set Marvin specific settings in `~/.marvin/.env`. One exception being `OP
|
|
|
11
11
|
For example, in your `~/.marvin/.env` file you could have:
|
|
12
12
|
```shell
|
|
13
13
|
MARVIN_LOG_LEVEL=INFO
|
|
14
|
-
MARVIN_CHAT_COMPLETIONS_MODEL=gpt-
|
|
14
|
+
MARVIN_CHAT_COMPLETIONS_MODEL=gpt-4o
|
|
15
15
|
MARVIN_OPENAI_API_KEY='sk-my-api-key'
|
|
16
16
|
```
|
|
17
17
|
Settings these values will let you avoid setting an API key every time.
|
|
@@ -24,7 +24,7 @@ A runtime settings object is accessible via `marvin.settings` and can be used to
|
|
|
24
24
|
```python
|
|
25
25
|
import marvin
|
|
26
26
|
|
|
27
|
-
marvin.settings.openai.chat.completions.model = 'gpt-
|
|
27
|
+
marvin.settings.openai.chat.completions.model = 'gpt-4o'
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
## Settings for using Azure OpenAI models
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Captioning images
|
|
2
|
+
|
|
3
|
+
Marvin can use OpenAI's vision API to process images as inputs.
|
|
4
|
+
|
|
5
|
+
<div class="admonition abstract">
|
|
6
|
+
<p class="admonition-title">What it does</p>
|
|
7
|
+
<p>
|
|
8
|
+
The <code>caption</code> function generates text from images.
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
!!! example
|
|
15
|
+
|
|
16
|
+
Generate a description of the following image, hypothetically available at `/path/to/marvin.png`:
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import marvin
|
|
23
|
+
|
|
24
|
+
caption = marvin.caption(marvin.Image.from_path('/path/to/marvin.png'))
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
!!! success "Result"
|
|
28
|
+
|
|
29
|
+
"A cute, small robot with a square head and large, glowing eyes sits on a surface of wavy, colorful lines. The background is dark with scattered, glowing particles, creating a magical and futuristic atmosphere."
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class="admonition info">
|
|
33
|
+
<p class="admonition-title">How it works</p>
|
|
34
|
+
<p>
|
|
35
|
+
Marvin passes your images to the OpenAI vision API as part of a larger prompt.
|
|
36
|
+
</p>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Providing instructions
|
|
41
|
+
|
|
42
|
+
The `instructions` parameter offers an additional layer of control, enabling more nuanced caption generation, especially in ambiguous or complex scenarios.
|
|
43
|
+
|
|
44
|
+
## Captions for multiple images
|
|
45
|
+
|
|
46
|
+
To generate a single caption for multiple images, pass a list of `Image` objects to `caption`:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
marvin.caption(
|
|
50
|
+
[
|
|
51
|
+
marvin.Image.from_path('/path/to/img1.png'),
|
|
52
|
+
marvin.Image.from_path('/path/to/img2.png')
|
|
53
|
+
],
|
|
54
|
+
instructions='...'
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Model parameters
|
|
60
|
+
You can pass parameters to the underlying API via the `model_kwargs` argument of `caption`. These parameters are passed directly to the API, so you can use any supported parameter.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Async support
|
|
65
|
+
|
|
66
|
+
If you are using Marvin in an async environment, you can use `caption_async`:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
caption = await marvin.caption_async(image=Path('/path/to/marvin.png'))
|
|
70
|
+
```
|
|
71
|
+
## Mapping
|
|
72
|
+
|
|
73
|
+
To generate individual captions for a list of inputs at once, use `.map`. Note that this is different than generating a single caption for multiple images, which is done by passing a list of `Image` objects to `caption`.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
inputs = [
|
|
77
|
+
marvin.Image.from_path('/path/to/img1.png'),
|
|
78
|
+
marvin.Image.from_path('/path/to/img2.png')
|
|
79
|
+
]
|
|
80
|
+
result = marvin.caption.map(inputs)
|
|
81
|
+
assert len(result) == 2
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
(`marvin.cast_async.map` is also available for async environments.)
|
|
85
|
+
|
|
86
|
+
Mapping automatically issues parallel requests to the API, making it a highly efficient way to work with multiple inputs at once. The result is a list of outputs in the same order as the inputs.
|
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Marvin can use OpenAI's vision API to process images and classify them into categories.
|
|
4
4
|
|
|
5
|
-
The `marvin.beta.classify` function is an enhanced version of `marvin.classify` that accepts images as well as text.
|
|
6
|
-
|
|
7
|
-
!!! tip "Beta"
|
|
8
|
-
Please note that vision support in Marvin is still in beta, as OpenAI has not finalized the vision API yet. While it works as expected, it is subject to change.
|
|
9
5
|
|
|
10
6
|
<div class="admonition abstract">
|
|
11
7
|
<p class="admonition-title">What it does</p>
|
|
@@ -36,14 +32,14 @@ The `marvin.beta.classify` function is an enhanced version of `marvin.classify`
|
|
|
36
32
|
```python
|
|
37
33
|
import marvin
|
|
38
34
|
|
|
39
|
-
img = marvin.
|
|
35
|
+
img = marvin.Image('https://upload.wikimedia.org/wikipedia/commons/d/d5/Retriever_in_water.jpg')
|
|
40
36
|
|
|
41
|
-
animal = marvin.
|
|
37
|
+
animal = marvin.classify(
|
|
42
38
|
img,
|
|
43
39
|
labels=['dog', 'cat', 'bird', 'fish', 'deer']
|
|
44
40
|
)
|
|
45
41
|
|
|
46
|
-
dry_or_wet = marvin.
|
|
42
|
+
dry_or_wet = marvin.classify(
|
|
47
43
|
img,
|
|
48
44
|
labels=['dry', 'wet'],
|
|
49
45
|
instructions='Is the animal wet?'
|
|
@@ -60,7 +56,7 @@ The `marvin.beta.classify` function is an enhanced version of `marvin.classify`
|
|
|
60
56
|
|
|
61
57
|
|
|
62
58
|
## Model parameters
|
|
63
|
-
You can pass parameters to the underlying API via the `model_kwargs`
|
|
59
|
+
You can pass parameters to the underlying API via the `model_kwargs` argument of `classify`. These parameters are passed directly to the API, so you can use any supported parameter.
|
|
64
60
|
|
|
65
61
|
|
|
66
62
|
## Async support
|
|
@@ -68,7 +64,7 @@ You can pass parameters to the underlying API via the `model_kwargs` and `vision
|
|
|
68
64
|
If you are using Marvin in an async environment, you can use `classify_async`:
|
|
69
65
|
|
|
70
66
|
```python
|
|
71
|
-
result = await marvin.
|
|
67
|
+
result = await marvin.classify_async(
|
|
72
68
|
"The app crashes when I try to upload a file.",
|
|
73
69
|
labels=["bug", "feature request", "inquiry"]
|
|
74
70
|
)
|
|
@@ -85,10 +81,10 @@ inputs = [
|
|
|
85
81
|
"The app crashes when I try to upload a file.",
|
|
86
82
|
"How do change my password?"
|
|
87
83
|
]
|
|
88
|
-
result = marvin.
|
|
84
|
+
result = marvin.classify.map(inputs, ["bug", "feature request", "inquiry"])
|
|
89
85
|
assert result == ["bug", "inquiry"]
|
|
90
86
|
```
|
|
91
87
|
|
|
92
|
-
(`marvin.
|
|
88
|
+
(`marvin.classify_async.map` is also available for async environments.)
|
|
93
89
|
|
|
94
90
|
Mapping automatically issues parallel requests to the API, making it a highly efficient way to classify multiple inputs at once. The result is a list of classifications in the same order as the inputs.
|
|
@@ -2,12 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Marvin can use OpenAI's vision API to process images and convert them into structured data, transforming unstructured information into native types that are appropriate for a variety of programmatic use cases.
|
|
4
4
|
|
|
5
|
-
The `marvin.beta.extract` function is an enhanced version of `marvin.extract` that accepts images as well as text.
|
|
6
5
|
|
|
7
6
|
|
|
8
|
-
!!! tip "Beta"
|
|
9
|
-
Please note that vision support in Marvin is still in beta, as OpenAI has not finalized the vision API yet. While it works as expected, it is subject to change.
|
|
10
|
-
|
|
11
7
|
<div class="admonition abstract">
|
|
12
8
|
<p class="admonition-title">What it does</p>
|
|
13
9
|
<p>
|
|
@@ -37,11 +33,11 @@ The `marvin.beta.extract` function is an enhanced version of `marvin.extract` th
|
|
|
37
33
|
```python
|
|
38
34
|
import marvin
|
|
39
35
|
|
|
40
|
-
img = marvin.
|
|
36
|
+
img = marvin.Image(
|
|
41
37
|
"https://images.unsplash.com/photo-1548199973-03cce0bbc87b?",
|
|
42
38
|
)
|
|
43
39
|
|
|
44
|
-
result = marvin.
|
|
40
|
+
result = marvin.extract(img, target=str, instructions="dog breeds")
|
|
45
41
|
```
|
|
46
42
|
|
|
47
43
|
!!! success "Result"
|
|
@@ -50,14 +46,14 @@ The `marvin.beta.extract` function is an enhanced version of `marvin.extract` th
|
|
|
50
46
|
```
|
|
51
47
|
|
|
52
48
|
## Model parameters
|
|
53
|
-
You can pass parameters to the underlying API via the `model_kwargs`
|
|
49
|
+
You can pass parameters to the underlying API via the `model_kwargs` argument of `extract`. These parameters are passed directly to the API, so you can use any supported parameter.
|
|
54
50
|
|
|
55
51
|
|
|
56
52
|
## Async support
|
|
57
53
|
If you are using Marvin in an async environment, you can use `extract_async`:
|
|
58
54
|
|
|
59
55
|
```python
|
|
60
|
-
result = await marvin.
|
|
56
|
+
result = await marvin.extract_async(
|
|
61
57
|
"I drove from New York to California.",
|
|
62
58
|
target=str,
|
|
63
59
|
instructions="2-letter state codes",
|
|
@@ -75,10 +71,10 @@ inputs = [
|
|
|
75
71
|
"I drove from New York to California.",
|
|
76
72
|
"I took a flight from NYC to BOS."
|
|
77
73
|
]
|
|
78
|
-
result = marvin.
|
|
74
|
+
result = marvin.extract.map(inputs, target=str, instructions="2-letter state codes")
|
|
79
75
|
assert result == [["NY", "CA"], ["NY", "MA"]]
|
|
80
76
|
```
|
|
81
77
|
|
|
82
|
-
(`marvin.
|
|
78
|
+
(`marvin.extract_async.map` is also available for async environments.)
|
|
83
79
|
|
|
84
80
|
Mapping automatically issues parallel requests to the API, making it a highly efficient way to work with multiple inputs at once. The result is a list of outputs in the same order as the inputs.
|