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.
Files changed (281) hide show
  1. {marvin-2.3.2 → marvin-2.3.4}/PKG-INFO +5 -6
  2. {marvin-2.3.2 → marvin-2.3.4}/README.md +4 -4
  3. {marvin-2.3.2 → marvin-2.3.4}/cookbook/_archive/docs_writer.py +1 -1
  4. {marvin-2.3.2 → marvin-2.3.4}/cookbook/_archive/test_writing_application.py +1 -1
  5. {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/github_digest/repo_activity.py +2 -4
  6. {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/insurance_claim.py +2 -2
  7. marvin-2.3.4/cookbook/maze.py +319 -0
  8. marvin-2.3.4/docs/assets/images/docs/vision/marvin.png +0 -0
  9. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/configuration/settings.md +2 -2
  10. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/video/recording.md +1 -1
  11. marvin-2.3.4/docs/docs/vision/captioning.md +86 -0
  12. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/vision/classification.md +7 -11
  13. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/vision/extraction.md +6 -10
  14. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/vision/transformation.md +10 -15
  15. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/webcam_narration.md +1 -1
  16. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/xkcd_bird.md +2 -2
  17. {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/tailwind.css +14 -4
  18. {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/tutorial.md +7 -9
  19. {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/what_is_marvin.md +2 -2
  20. marvin-2.3.4/mkdocs.yml +201 -0
  21. {marvin-2.3.2 → marvin-2.3.4}/pyproject.toml +0 -1
  22. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/__init__.py +7 -0
  23. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_version.py +2 -2
  24. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/prompts/text_prompts.py +17 -12
  25. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/text.py +148 -25
  26. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/audio.py +0 -1
  27. marvin-2.3.4/src/marvin/beta/__init__.py +2 -0
  28. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/state.py +4 -1
  29. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/assistants.py +8 -5
  30. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/formatting.py +2 -0
  31. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/runs.py +1 -1
  32. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/client/openai.py +0 -31
  33. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/settings.py +7 -19
  34. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/types.py +20 -34
  35. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/jinja.py +75 -18
  36. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/testing.py +1 -1
  37. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/tools.py +1 -3
  38. {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/PKG-INFO +5 -6
  39. {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/SOURCES.txt +7 -10
  40. {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/requires.txt +0 -1
  41. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_classify.py +3 -1
  42. marvin-2.3.4/tests/ai/vision/test_caption.py +49 -0
  43. {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai}/vision/test_cast.py +22 -34
  44. {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai}/vision/test_classify.py +28 -44
  45. {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai}/vision/test_extract.py +49 -32
  46. {marvin-2.3.2 → marvin-2.3.4}/tests/fixtures/llms.py +1 -1
  47. {marvin-2.3.2 → marvin-2.3.4}/tests/test_settings.py +1 -1
  48. marvin-2.3.4/tests/utilities/test_jinja.py +269 -0
  49. marvin-2.3.2/cookbook/maze.py +0 -233
  50. marvin-2.3.2/docs/api_reference/beta/vision.md +0 -4
  51. marvin-2.3.2/docs/assets/images/docs/vision/marvin.webp +0 -0
  52. marvin-2.3.2/docs/docs/vision/captioning.md +0 -57
  53. marvin-2.3.2/docs/utilities (old)/chat_completion.md +0 -401
  54. marvin-2.3.2/mkdocs.yml +0 -207
  55. marvin-2.3.2/src/marvin/ai/prompts/vision_prompts.py +0 -47
  56. marvin-2.3.2/src/marvin/beta/__init__.py +0 -13
  57. marvin-2.3.2/src/marvin/beta/vision.py +0 -565
  58. marvin-2.3.2/tests/utilities/__init__.py +0 -0
  59. {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/1_general_bug_report.yaml +0 -0
  60. {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/2_feature_request.yaml +0 -0
  61. {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/3_docs_change.yaml +0 -0
  62. {marvin-2.3.2 → marvin-2.3.4}/.github/ISSUE_TEMPLATE/config.yaml +0 -0
  63. {marvin-2.3.2 → marvin-2.3.4}/.github/dependabot.yml +0 -0
  64. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/build-docs.yml +0 -0
  65. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/deploy-cloudrun-revision-community.yaml +0 -0
  66. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/deploy-cloudrun-revision-internal.yaml +0 -0
  67. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/image-build-and-push-community.yaml +0 -0
  68. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/image-build-and-push-internal.yaml +0 -0
  69. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/publish-docs.yml +0 -0
  70. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/publish-pypi.yml +0 -0
  71. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/run-tests.yml +0 -0
  72. {marvin-2.3.2 → marvin-2.3.4}/.github/workflows/static-analysis.yml +0 -0
  73. {marvin-2.3.2 → marvin-2.3.4}/.pre-commit-config.yaml +0 -0
  74. {marvin-2.3.2 → marvin-2.3.4}/LICENSE +0 -0
  75. {marvin-2.3.2 → marvin-2.3.4}/MANIFEST.in +0 -0
  76. {marvin-2.3.2 → marvin-2.3.4}/cookbook/__init__.py +0 -0
  77. {marvin-2.3.2 → marvin-2.3.4}/cookbook/azure/README.md +0 -0
  78. {marvin-2.3.2 → marvin-2.3.4}/cookbook/azure/usage.py +0 -0
  79. {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/github_digest/utils.py +0 -0
  80. {marvin-2.3.2 → marvin-2.3.4}/cookbook/flows/label_issues.py +0 -0
  81. {marvin-2.3.2 → marvin-2.3.4}/cookbook/gh_util/custom_assistant.py +0 -0
  82. {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/README.md +0 -0
  83. {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/auto_trace.py +0 -0
  84. {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/demo_app.py +0 -0
  85. {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/hello.py +0 -0
  86. {marvin-2.3.2 → marvin-2.3.4}/cookbook/logfire/send_demo_request.py +0 -0
  87. {marvin-2.3.2 → marvin-2.3.4}/cookbook/reasking.py +0 -0
  88. {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/.dockerignore +0 -0
  89. {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/Dockerfile.slackbot +0 -0
  90. {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/README.md +0 -0
  91. {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/keywords.py +0 -0
  92. {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/parent_app.py +0 -0
  93. {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/start.py +0 -0
  94. {marvin-2.3.2 → marvin-2.3.4}/cookbook/slackbot/tools.py +0 -0
  95. {marvin-2.3.2 → marvin-2.3.4}/cookbook/translate_schemas.py +0 -0
  96. {marvin-2.3.2 → marvin-2.3.4}/docs/CNAME +0 -0
  97. {marvin-2.3.2 → marvin-2.3.4}/docs/ai_style_guide.md +0 -0
  98. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/ai/audio.md +0 -0
  99. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/ai/images.md +0 -0
  100. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/ai/text.md +0 -0
  101. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/applications.md +0 -0
  102. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/assistants.md +0 -0
  103. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/formatting.md +0 -0
  104. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/index.md +0 -0
  105. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/runs.md +0 -0
  106. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants/threads.md +0 -0
  107. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/beta/assistants.md +0 -0
  108. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/marvin.md +0 -0
  109. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/settings.md +0 -0
  110. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/types.md +0 -0
  111. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/asyncio.md +0 -0
  112. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/context.md +0 -0
  113. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/images.md +0 -0
  114. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/jinja.md +0 -0
  115. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/logging.md +0 -0
  116. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/openai.md +0 -0
  117. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/pydantic.md +0 -0
  118. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/python.md +0 -0
  119. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/slack.md +0 -0
  120. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/strings.md +0 -0
  121. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/testing.md +0 -0
  122. {marvin-2.3.2 → marvin-2.3.4}/docs/api_reference/utilities/tools.md +0 -0
  123. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/ai_say.mp3 +0 -0
  124. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/dont_panic.mp3 +0 -0
  125. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/fancy_computer.mp3 +0 -0
  126. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/hello_arthur.mp3 +0 -0
  127. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/hello_marvin.mp3 +0 -0
  128. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/this_is_a_test.mp3 +0 -0
  129. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/audio/this_is_a_test_2.mp3 +0 -0
  130. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_1.png +0 -0
  131. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_2.png +0 -0
  132. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_3.png +0 -0
  133. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/applications/todo_conversation.png +0 -0
  134. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/advanced.png +0 -0
  135. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/arthur_marvin_example.png +0 -0
  136. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/code_interpreter.png +0 -0
  137. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/custom_tools.png +0 -0
  138. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/instructions.png +0 -0
  139. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/quickstart.png +0 -0
  140. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/sin_x.png +0 -0
  141. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/talking.png +0 -0
  142. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/assistants/upload_files.png +0 -0
  143. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/cli/hero.png +0 -0
  144. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/cli/tools.png +0 -0
  145. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/examples/logfire-span.jpeg +0 -0
  146. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/coffee.png +0 -0
  147. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/robot.png +0 -0
  148. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/sunset_scifi.png +0 -0
  149. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/sunset_summer.png +0 -0
  150. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/sunset_winter.png +0 -0
  151. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_0.png +0 -0
  152. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_025.png +0 -0
  153. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_075.png +0 -0
  154. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/teacup_revision_1.png +0 -0
  155. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/three_cats.png +0 -0
  156. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/two_cats_airport.png +0 -0
  157. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/docs/images/two_cats_airport_revision_0_1.png +0 -0
  158. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/ai_model.png +0 -0
  159. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/dont_panic.png +0 -0
  160. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/it_hates_me_hero.png +0 -0
  161. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/life_the_universe_and_ai.png +0 -0
  162. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/pip_install_marvin_hero.png +0 -0
  163. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/heroes/sort_of_thing_you_enjoy.png +0 -0
  164. {marvin-2.3.2 → marvin-2.3.4}/docs/assets/images/logos/askmarvin_mascot.jpeg +0 -0
  165. {marvin-2.3.2 → marvin-2.3.4}/docs/community/development_guide.md +0 -0
  166. {marvin-2.3.2 → marvin-2.3.4}/docs/community/feedback.md +0 -0
  167. {marvin-2.3.2 → marvin-2.3.4}/docs/community/index.md +0 -0
  168. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/audio/recording.md +0 -0
  169. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/audio/speech.md +0 -0
  170. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/audio/transcription.md +0 -0
  171. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/images/generation.md +0 -0
  172. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/interactive/applications.md +0 -0
  173. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/interactive/assistants.md +0 -0
  174. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/interactive/cli.md +0 -0
  175. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/classification.md +0 -0
  176. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/extraction.md +0 -0
  177. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/functions.md +0 -0
  178. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/generation.md +0 -0
  179. {marvin-2.3.2 → marvin-2.3.4}/docs/docs/text/transformation.md +0 -0
  180. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/audio_modification.md +0 -0
  181. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/being_specific_about_types.md +0 -0
  182. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/call_routing.md +0 -0
  183. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/deduplication.md +0 -0
  184. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/github_digest.md +0 -0
  185. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/hogwarts_sorting_hat/hogwarts_patch.webp +0 -0
  186. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/hogwarts_sorting_hat/hogwarts_sorting_hat.md +0 -0
  187. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/michael_scott_business/michael_scott.jpg +0 -0
  188. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/michael_scott_business/michael_scott_business.md +0 -0
  189. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/python_augmented_prompts.md +0 -0
  190. {marvin-2.3.2 → marvin-2.3.4}/docs/examples/slackbot.md +0 -0
  191. {marvin-2.3.2 → marvin-2.3.4}/docs/help/legacy_docs.md +0 -0
  192. {marvin-2.3.2 → marvin-2.3.4}/docs/hooks.py +0 -0
  193. {marvin-2.3.2 → marvin-2.3.4}/docs/index.md +0 -0
  194. {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/home.html +0 -0
  195. {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/partials/footer.html +0 -0
  196. {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/partials/grid.html +0 -0
  197. {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/partials/toc-item.html +0 -0
  198. {marvin-2.3.2 → marvin-2.3.4}/docs/overrides/tailwind.css +0 -0
  199. {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/badges.css +0 -0
  200. {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/custom.css +0 -0
  201. {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/global.css +0 -0
  202. {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/home.css +0 -0
  203. {marvin-2.3.2 → marvin-2.3.4}/docs/static/css/mkdocstrings.css +0 -0
  204. {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/installation.md +0 -0
  205. {marvin-2.3.2 → marvin-2.3.4}/docs/welcome/overview.md +0 -0
  206. {marvin-2.3.2 → marvin-2.3.4}/mkdocs.insiders.yml +0 -0
  207. {marvin-2.3.2 → marvin-2.3.4}/prefect.yaml +0 -0
  208. {marvin-2.3.2 → marvin-2.3.4}/scripts/serve_legacy_docs +0 -0
  209. {marvin-2.3.2 → marvin-2.3.4}/setup.cfg +0 -0
  210. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/__init__.py +0 -0
  211. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/base_model.py +0 -0
  212. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/chat_completion.py +0 -0
  213. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/_mappings/types.py +0 -0
  214. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/__init__.py +0 -0
  215. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/audio.py +0 -0
  216. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/images.py +0 -0
  217. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/prompts/audio_prompts.py +0 -0
  218. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/ai/prompts/image_prompts.py +0 -0
  219. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/ai_flow/__init__.py +0 -0
  220. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/ai_flow/ai_flow.py +0 -0
  221. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/ai_flow/ai_task.py +0 -0
  222. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/__init__.py +0 -0
  223. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/applications.py +0 -0
  224. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/planner.py +0 -0
  225. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/__init__.py +0 -0
  226. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/disk.py +0 -0
  227. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/applications/state/json_block.py +0 -0
  228. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/__init__.py +0 -0
  229. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/handlers.py +0 -0
  230. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/assistants/threads.py +0 -0
  231. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/beta/retries.py +0 -0
  232. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/cli/__init__.py +0 -0
  233. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/cli/assistants.py +0 -0
  234. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/cli/threads.py +0 -0
  235. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/client/__init__.py +0 -0
  236. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/__init__.py +0 -0
  237. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/assistants.py +0 -0
  238. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/chroma.py +0 -0
  239. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/code.py +0 -0
  240. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/filesystem.py +0 -0
  241. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/tools/github.py +0 -0
  242. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/__init__.py +0 -0
  243. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/asyncio.py +0 -0
  244. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/context.py +0 -0
  245. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/images.py +0 -0
  246. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/logging.py +0 -0
  247. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/mapping.py +0 -0
  248. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/openai.py +0 -0
  249. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/pydantic.py +0 -0
  250. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/python.py +0 -0
  251. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/slack.py +0 -0
  252. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/utilities/strings.py +0 -0
  253. {marvin-2.3.2 → marvin-2.3.4}/src/marvin/video.py +0 -0
  254. {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/dependency_links.txt +0 -0
  255. {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/entry_points.txt +0 -0
  256. {marvin-2.3.2 → marvin-2.3.4}/src/marvin.egg-info/top_level.txt +0 -0
  257. {marvin-2.3.2 → marvin-2.3.4}/tailwind.config.js +0 -0
  258. {marvin-2.3.2 → marvin-2.3.4}/tests/__init__.py +0 -0
  259. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/__init__.py +0 -0
  260. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_cast.py +0 -0
  261. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_classifier.py +0 -0
  262. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_extract.py +0 -0
  263. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_functions.py +0 -0
  264. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_generate.py +0 -0
  265. {marvin-2.3.2 → marvin-2.3.4}/tests/ai/test_models.py +0 -0
  266. {marvin-2.3.2/tests/ai/beta → marvin-2.3.4/tests/ai/vision}/__init__.py +0 -0
  267. {marvin-2.3.2/tests/ai/beta/vision → marvin-2.3.4/tests/beta}/__init__.py +0 -0
  268. {marvin-2.3.2/tests/beta → marvin-2.3.4/tests/beta/assistants}/__init__.py +0 -0
  269. {marvin-2.3.2 → marvin-2.3.4}/tests/beta/assistants/test_assistants.py +0 -0
  270. {marvin-2.3.2/tests/beta/assistants → marvin-2.3.4/tests/cli}/__init__.py +0 -0
  271. {marvin-2.3.2 → marvin-2.3.4}/tests/cli/test_version.py +0 -0
  272. {marvin-2.3.2/tests/cli → marvin-2.3.4/tests/client}/__init__.py +0 -0
  273. {marvin-2.3.2 → marvin-2.3.4}/tests/client/test_openai.py +0 -0
  274. {marvin-2.3.2 → marvin-2.3.4}/tests/conftest.py +0 -0
  275. {marvin-2.3.2 → marvin-2.3.4}/tests/fixtures/__init__.py +0 -0
  276. {marvin-2.3.2 → marvin-2.3.4}/tests/fixtures/assistants.py +0 -0
  277. {marvin-2.3.2 → marvin-2.3.4}/tests/package_size.sh +0 -0
  278. {marvin-2.3.2/tests/client → marvin-2.3.4/tests/utilities}/__init__.py +0 -0
  279. {marvin-2.3.2 → marvin-2.3.4}/tests/utilities/test_pydantic.py +0 -0
  280. {marvin-2.3.2 → marvin-2.3.4}/tests/utilities/test_testing_utilities.py +0 -0
  281. {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.2
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
- ## 🔍 Classify images (beta)
510
+ ## 🔍 Converting images to data
512
511
 
513
- In addition to text, Marvin has beta support for captioning, classifying, transforming, and extracting entities from images using the GPT-4 vision model:
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.beta.classify(
517
- marvin.beta.Image("docs/images/coffee.png"),
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
- ## 🔍 Classify images (beta)
239
+ ## 🔍 Converting images to data
240
240
 
241
- In addition to text, Marvin has beta support for captioning, classifying, transforming, and extracting entities from images using the GPT-4 vision model:
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.beta.classify(
245
- marvin.beta.Image("docs/images/coffee.png"),
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-4-1106-preview"
10
+ marvin.settings.openai.chat.completions.model = "gpt-4o"
11
11
 
12
12
 
13
13
  ROOT_DIR = Path(marvin.__file__).parents[2]
@@ -9,7 +9,7 @@ from marvin.beta.applications import Application
9
9
  from pydantic import BaseModel, Field
10
10
 
11
11
  marvin.settings.log_level = "DEBUG"
12
- marvin.settings.llm_model = "gpt-4"
12
+ marvin.settings.llm_model = "gpt-4o"
13
13
 
14
14
 
15
15
  class TestWriterState(BaseModel):
@@ -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.utcnow() - timedelta(days=lookback_days)
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.beta.extract(
56
- data=marvin.beta.Image.from_url(image_url),
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")
@@ -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-4
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-4'
27
+ marvin.settings.openai.chat.completions.model = 'gpt-4o'
28
28
  ```
29
29
 
30
30
  ## Settings for using Azure OpenAI models
@@ -26,7 +26,7 @@ counter = 0
26
26
  for image in recorder.stream():
27
27
  counter += 1
28
28
  # process each image
29
- marvin.beta.caption(image)
29
+ marvin.caption(image)
30
30
 
31
31
  # stop recording
32
32
  if counter == 3:
@@ -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
+ ![](/assets/images/docs/vision/marvin.png)
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.beta.Image('https://upload.wikimedia.org/wikipedia/commons/d/d5/Retriever_in_water.jpg')
35
+ img = marvin.Image('https://upload.wikimedia.org/wikipedia/commons/d/d5/Retriever_in_water.jpg')
40
36
 
41
- animal = marvin.beta.classify(
37
+ animal = marvin.classify(
42
38
  img,
43
39
  labels=['dog', 'cat', 'bird', 'fish', 'deer']
44
40
  )
45
41
 
46
- dry_or_wet = marvin.beta.classify(
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` and `vision_model_kwargs` arguments of `classify`. These parameters are passed directly to the respective APIs, so you can use any supported parameter.
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.beta.classify_async(
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.beta.classify.map(inputs, ["bug", "feature request", "inquiry"])
84
+ result = marvin.classify.map(inputs, ["bug", "feature request", "inquiry"])
89
85
  assert result == ["bug", "inquiry"]
90
86
  ```
91
87
 
92
- (`marvin.beta.classify_async.map` is also available for async environments.)
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.beta.Image(
36
+ img = marvin.Image(
41
37
  "https://images.unsplash.com/photo-1548199973-03cce0bbc87b?",
42
38
  )
43
39
 
44
- result = marvin.beta.extract(img, target=str, instructions="dog breeds")
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` and `vision_model_kwargs` arguments of `extract`. These parameters are passed directly to the respective APIs, so you can use any supported parameter.
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.beta.extract_async(
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.beta.extract.map(inputs, target=str, instructions="2-letter state codes")
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.beta.extract_async.map` is also available for async environments.)
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.